@tilua/parser 3.0.1 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -24,6 +24,7 @@ __export(index_exports, {
24
24
  CONFIG_FILE_NAMES: () => CONFIG_FILE_NAMES,
25
25
  Keywords: () => Keywords,
26
26
  LANGUAGE_GLOBALS: () => LANGUAGE_GLOBALS,
27
+ LUAU_KEYWORDS: () => LUAU_KEYWORDS,
27
28
  LexError: () => LexError,
28
29
  Operators: () => Operators,
29
30
  PRELUDE_SOURCE: () => PRELUDE_SOURCE,
@@ -45,20 +46,27 @@ __export(index_exports, {
45
46
  difference: () => difference,
46
47
  directivesOf: () => directivesOf,
47
48
  equalTypes: () => equalTypes,
49
+ escapeLuauString: () => escapeLuauString,
48
50
  falsyType: () => falsyType,
49
51
  findConfig: () => findConfig,
50
52
  fn: () => fn,
51
53
  formatType: () => formatType,
52
54
  getBinding: () => getBinding,
55
+ hasMembers: () => hasMembers,
53
56
  intersection: () => intersection,
54
57
  isAssignable: () => isAssignable,
55
58
  isClassType: () => isClassType,
59
+ isFunctionType: () => isFunctionType,
56
60
  isGlobal: () => isGlobal,
61
+ isIdentifier: () => isIdentifier,
62
+ isInstanceOf: () => isInstanceOf,
63
+ isLuauName: () => isLuauName,
57
64
  isPossiblyFalsy: () => isPossiblyFalsy,
58
65
  isPossiblyTruthy: () => isPossiblyTruthy,
59
66
  isUnassignedGlobal: () => isUnassignedGlobal,
60
67
  literal: () => literal,
61
68
  loadConfig: () => loadConfig,
69
+ luauString: () => luauString,
62
70
  matchInfer: () => matchInfer,
63
71
  moduleCandidates: () => moduleCandidates,
64
72
  moduleExports: () => moduleExports,
@@ -81,6 +89,7 @@ __export(index_exports, {
81
89
  readDirectives: () => readDirectives,
82
90
  resolveModulePath: () => resolveModulePath,
83
91
  resolveTypeLibraries: () => resolveTypeLibraries,
92
+ returnsTuple: () => returnsTuple,
84
93
  setAliasExpander: () => setAliasExpander,
85
94
  setDeferredBound: () => setDeferredBound,
86
95
  sourceMapTypes: () => sourceMapTypes,
@@ -99,7 +108,8 @@ __export(index_exports, {
99
108
  unknownType: () => unknownType,
100
109
  widen: () => widen,
101
110
  withAliasName: () => withAliasName,
102
- withoutAliasName: () => withoutAliasName
111
+ withoutAliasName: () => withoutAliasName,
112
+ withoutNil: () => withoutNil2
103
113
  });
104
114
  module.exports = __toCommonJS(index_exports);
105
115
 
@@ -708,7 +718,7 @@ function bindThis(func, at) {
708
718
  func.isMethod = true;
709
719
  }
710
720
  function bindThisParam(params, at) {
711
- params.unshift({ type: "FunctionParameter", name: "this", ...spanFrom(at, at) });
721
+ params.unshift({ type: "FunctionParameter", name: "this", implicit: true, ...spanFrom(at, at) });
712
722
  }
713
723
  var ParseError = class extends Error {
714
724
  constructor(message, line, column) {
@@ -1765,7 +1775,7 @@ var Parser = class {
1765
1775
  };
1766
1776
  }
1767
1777
  if (isMethod) {
1768
- func.params.unshift({ type: "FunctionParameter", name: "self", ...spanFrom(target, target) });
1778
+ func.params.unshift({ type: "FunctionParameter", name: "self", implicit: true, ...spanFrom(target, target) });
1769
1779
  func.isMethod = true;
1770
1780
  }
1771
1781
  return {
@@ -1959,47 +1969,7 @@ var Parser = class {
1959
1969
  const isStatic = modifiers.has("static");
1960
1970
  if (this.checkKeyword("function")) {
1961
1971
  this.advance();
1962
- const memberName = this.parseIdentifier();
1963
- if (modifiers.has("abstract")) {
1964
- const head = this.parseFunctionHead();
1965
- const func = {
1966
- type: "FunctionBody",
1967
- generics: head.generics,
1968
- params: head.params,
1969
- hasVarargs: head.hasVarargs,
1970
- returnType: head.returnType,
1971
- predicate: head.predicate,
1972
- body: { type: "Block", statements: [], ...spanFrom(head.start, this.previous()) },
1973
- ...spanFrom(head.start, this.previous())
1974
- };
1975
- if (!isStatic) bindThis(func, start);
1976
- if (!head.returnType) this.problem("An abstract method has no body to infer from: write its return type");
1977
- if (this.checkPunctuator("{")) this.problem("An abstract method has no body");
1978
- return { type: "ClassMethod", name: memberName, isStatic, func, isAbstract: true, ...spanFrom(start, this.previous()) };
1979
- }
1980
- const signatures = [];
1981
- let written = memberName;
1982
- while (true) {
1983
- const head = this.parseFunctionHead();
1984
- if (this.isClassOverloadContinuation(memberName.name, isStatic)) {
1985
- if (!isStatic) bindThisParam(head.params, start);
1986
- signatures.push({ ...this.headToSignature(head), name: written });
1987
- if (isStatic) this.advance();
1988
- this.expectKeyword("function");
1989
- written = this.parseIdentifier();
1990
- continue;
1991
- }
1992
- const func = this.headToBody(head, start);
1993
- if (!isStatic) bindThis(func, start);
1994
- return {
1995
- type: "ClassMethod",
1996
- name: memberName,
1997
- isStatic,
1998
- func,
1999
- signatures: signatures.length ? signatures : void 0,
2000
- ...spanFrom(start, this.previous())
2001
- };
2002
- }
1972
+ return this.parseClassMethod(start, modifiers);
2003
1973
  }
2004
1974
  if (!isStatic && this.checkIdentifierValue("constructor") && this.punctuatorAt(1, "(")) {
2005
1975
  this.advance();
@@ -2009,6 +1979,9 @@ var Parser = class {
2009
1979
  bindThis(func, start);
2010
1980
  return { type: "ClassConstructor", func, ...spanFrom(start, this.previous()) };
2011
1981
  }
1982
+ if (this.startsMethodShorthand(0)) {
1983
+ return this.parseClassMethod(start, modifiers);
1984
+ }
2012
1985
  if ((this.checkIdentifierValue("get") || this.checkIdentifierValue("set")) && this.peek(1).type === "Identifier" && this.punctuatorAt(2, "(")) {
2013
1986
  const kind = this.advance().value;
2014
1987
  const memberName = this.parseIdentifier();
@@ -2038,25 +2011,90 @@ var Parser = class {
2038
2011
  return { type: "ClassField", name: memberName, isStatic, typeAnnotation, init, ...spanFrom(start, this.previous()) };
2039
2012
  }
2040
2013
  if (this.recover) {
2041
- this.softError("Expected a class member: a field, 'function', 'constructor', 'get' or 'set'");
2014
+ this.softError("Expected a class member: a field, a method, 'constructor', 'get' or 'set'");
2042
2015
  this.advance();
2043
2016
  return void 0;
2044
2017
  }
2045
- this.error("Expected a class member: a field, 'function', 'constructor', 'get' or 'set'");
2018
+ this.error("Expected a class member: a field, a method, 'constructor', 'get' or 'set'");
2019
+ }
2020
+ /** A name at `offset` opening a method without `function`: `name(` or
2021
+ * `name<T>(`. A field's name is followed by `:` or `=` instead. */
2022
+ startsMethodShorthand(offset) {
2023
+ if (this.peek(offset).type !== "Identifier") return false;
2024
+ const next = this.peek(offset + 1);
2025
+ return (next.type === "Punctuator" || next.type === "Operator") && (next.value === "(" || next.value === "<");
2026
+ }
2027
+ /** A method, from its name on: `function` (if written) and the modifiers
2028
+ * are behind. */
2029
+ parseClassMethod(start, modifiers) {
2030
+ const isStatic = modifiers.has("static");
2031
+ const memberName = this.parseIdentifier();
2032
+ if (modifiers.has("abstract")) {
2033
+ const head = this.parseFunctionHead();
2034
+ const func = {
2035
+ type: "FunctionBody",
2036
+ generics: head.generics,
2037
+ params: head.params,
2038
+ hasVarargs: head.hasVarargs,
2039
+ returnType: head.returnType,
2040
+ predicate: head.predicate,
2041
+ body: { type: "Block", statements: [], ...spanFrom(head.start, this.previous()) },
2042
+ ...spanFrom(head.start, this.previous())
2043
+ };
2044
+ if (!isStatic) bindThis(func, start);
2045
+ if (!head.returnType) this.problem("An abstract method has no body to infer from: write its return type");
2046
+ if (this.checkPunctuator("{")) this.problem("An abstract method has no body");
2047
+ return { type: "ClassMethod", name: memberName, isStatic, func, isAbstract: true, ...spanFrom(start, this.previous()) };
2048
+ }
2049
+ const signatures = [];
2050
+ let written = memberName;
2051
+ while (true) {
2052
+ const head = this.parseFunctionHead();
2053
+ const skip = this.classOverloadContinuation(memberName.name, isStatic);
2054
+ if (skip !== void 0) {
2055
+ if (!isStatic) bindThisParam(head.params, start);
2056
+ signatures.push({ ...this.headToSignature(head), name: written });
2057
+ for (let i = 0; i < skip; i++) this.advance();
2058
+ written = this.parseIdentifier();
2059
+ continue;
2060
+ }
2061
+ const func = this.headToBody(head, start);
2062
+ if (!isStatic) bindThis(func, start);
2063
+ return {
2064
+ type: "ClassMethod",
2065
+ name: memberName,
2066
+ isStatic,
2067
+ func,
2068
+ signatures: signatures.length ? signatures : void 0,
2069
+ ...spanFrom(start, this.previous())
2070
+ };
2071
+ }
2046
2072
  }
2047
- /** Give a class method its `this`: a real first parameter, the way
2048
- * `function T:m()` gets a real `self`. Every later pass — scopes, types,
2049
- * arity, lowering — then sees an ordinary parameter and needs to know
2050
- * nothing about classes. */
2051
2073
  /** After a bodyless head inside a class body, does another declaration of
2052
- * the same member follow? Then the head was an overload signature. */
2053
- isClassOverloadContinuation(name, isStatic) {
2054
- const offset = isStatic ? 1 : 0;
2055
- if (isStatic && !this.checkIdentifierValue("static")) return false;
2074
+ * the same member follow? Then the head was an overload signature, and
2075
+ * this is how many tokens stand before the next one's name: a `;` that
2076
+ * ends the head, as TypeScript writes it, the modifiers, and `function`
2077
+ * when it is written. `undefined` when no overload follows. Each head may
2078
+ * be written either way, with `function` or without. */
2079
+ classOverloadContinuation(name, isStatic) {
2080
+ let offset = 0;
2081
+ if (this.punctuatorAt(0, ";")) offset++;
2082
+ let sawStatic = false;
2083
+ while (true) {
2084
+ const t = this.peek(offset);
2085
+ const word = t.type === "Identifier" ? t.value : void 0;
2086
+ if (word === void 0 || !CLASS_MODIFIERS.has(word) || this.startsMethodShorthand(offset)) break;
2087
+ if (word === "static") sawStatic = true;
2088
+ offset++;
2089
+ }
2090
+ if (sawStatic !== isStatic) return void 0;
2056
2091
  const keyword = this.peek(offset);
2057
- if (!(keyword.type === "Keyword" && keyword.value === "function")) return false;
2058
- const named = this.peek(offset + 1);
2059
- return named.type === "Identifier" && named.value === name;
2092
+ const hasKeyword = keyword.type === "Keyword" && keyword.value === "function";
2093
+ if (hasKeyword) offset++;
2094
+ const named = this.peek(offset);
2095
+ if (!(named.type === "Identifier" && named.value === name)) return void 0;
2096
+ if (!hasKeyword && !this.startsMethodShorthand(offset)) return void 0;
2097
+ return offset;
2060
2098
  }
2061
2099
  operatorAt(ahead, value) {
2062
2100
  const token = this.peek(ahead);
@@ -4676,11 +4714,34 @@ declare metatable<T> T[]: {
4676
4714
  -- \`nil\` when it is missing; an indexer's keys follow the named ones. A
4677
4715
  -- member of the table's own with one of these names is what a call reaches,
4678
4716
  -- and a class instance, which has a metatable of its own, has none of them.
4717
+ --
4718
+ -- The rest are JavaScript's \`Object\` functions, written as methods of the
4719
+ -- table they take first:
4720
+ --
4721
+ -- point:hasOwn("x") -- Object.hasOwn(point, "x")
4722
+ -- point:assign({ z: 3 }) -- Object.assign(point, { z: 3 })
4723
+ -- point:freeze() -- Object.freeze(point)
4724
+ --
4725
+ -- \`hasOwn\` asks the table itself, not what its metatable's \`__index\`
4726
+ -- lends it. \`assign\` copies each source's members onto the table, later ones
4727
+ -- over earlier ones, skipping a \`nil\` source, and answers the table. \`freeze\`
4728
+ -- is Luau's \`table.freeze\`; under Lua 5.1, which cannot freeze a table, the
4729
+ -- table is answered as it is and \`isFrozen\` is false.
4679
4730
  declare metatable<T extends {}> T: {
4680
4731
  __index: {
4681
4732
  keys: (self: T) => ObjectKeys<T>,
4682
4733
  values: (self: T) => ObjectValues<T>,
4683
4734
  entries: (self: T) => ObjectEntries<T>,
4735
+
4736
+ hasOwn: (self: T, key: unknown) => boolean,
4737
+ hasOwnProperty: (self: T, key: unknown) => boolean,
4738
+ assign: (<U>(self: T, source: U) => T & U)
4739
+ & (<U, V>(self: T, a: U, b: V) => T & U & V)
4740
+ & (<U, V, W>(self: T, a: U, b: V, c: W) => T & U & V & W)
4741
+ -- Generic like the rest: a plain signature would be tried first.
4742
+ & (<S extends {}>(self: T, ...sources: S[]) => T),
4743
+ freeze: (self: T) => Readonly<T>,
4744
+ isFrozen: (self: T) => boolean,
4684
4745
  },
4685
4746
  }
4686
4747
  `;
@@ -11866,7 +11927,53 @@ function aliasTargets(config, specifier) {
11866
11927
 
11867
11928
  // src/project/sourcemap.ts
11868
11929
  var import_node_path4 = require("path");
11930
+
11931
+ // src/luau.ts
11932
+ var LUAU_KEYWORDS = /* @__PURE__ */ new Set([
11933
+ "and",
11934
+ "break",
11935
+ "do",
11936
+ "else",
11937
+ "elseif",
11938
+ "end",
11939
+ "false",
11940
+ "for",
11941
+ "function",
11942
+ "if",
11943
+ "in",
11944
+ "local",
11945
+ "nil",
11946
+ "not",
11947
+ "or",
11948
+ "repeat",
11949
+ "return",
11950
+ "then",
11951
+ "true",
11952
+ "until",
11953
+ "while"
11954
+ ]);
11869
11955
  var IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
11956
+ function isIdentifier(name) {
11957
+ return IDENTIFIER.test(name);
11958
+ }
11959
+ function isLuauName(name) {
11960
+ return IDENTIFIER.test(name) && !LUAU_KEYWORDS.has(name);
11961
+ }
11962
+ var NAMED_ESCAPES = {
11963
+ "\\": "\\\\",
11964
+ '"': '\\"',
11965
+ "\n": "\\n",
11966
+ "\r": "\\r",
11967
+ " ": "\\t"
11968
+ };
11969
+ function escapeLuauString(text) {
11970
+ return text.replace(/[\\"\x00-\x1f\x7f]/g, (c) => NAMED_ESCAPES[c] ?? `\\${c.charCodeAt(0).toString().padStart(3, "0")}`);
11971
+ }
11972
+ function luauString(text) {
11973
+ return `"${escapeLuauString(text)}"`;
11974
+ }
11975
+
11976
+ // src/project/sourcemap.ts
11870
11977
  var INSTANCE_MEMBERS = /* @__PURE__ */ new Set(["Name", "ClassName", "Parent", "Archivable"]);
11871
11978
  var SCRIPT_EXTENSIONS = /* @__PURE__ */ new Set([".tilua", ".luau", ".lua"]);
11872
11979
  function sourceMapTypes(text, path, options) {
@@ -11893,7 +12000,7 @@ function sourceMapTypes(text, path, options) {
11893
12000
  const alias = aliasFor(segments);
11894
12001
  aliasOfNode.set(node, alias);
11895
12002
  for (const filePath of node.filePaths ?? []) aliasOfFile.set(fileKey((0, import_node_path4.resolve)(directory, filePath)), alias);
11896
- const className = IDENTIFIER.test(node.className) && options.classes.has(node.className) ? node.className : "Instance";
12003
+ const className = isIdentifier(node.className) && options.classes.has(node.className) ? node.className : "Instance";
11897
12004
  const taken = options.membersOf?.(className) ?? INSTANCE_MEMBERS;
11898
12005
  const members = [];
11899
12006
  if (parent) members.push(`Parent: ${parent}`);
@@ -11902,7 +12009,7 @@ function sourceMapTypes(text, path, options) {
11902
12009
  if (!isNode(child)) continue;
11903
12010
  const childAlias = visit(child, [...segments, child.name], alias);
11904
12011
  const service = child.name === child.className && options.classes.has(child.className);
11905
- if (!IDENTIFIER.test(child.name) || taken.has(child.name) && !service || named.has(child.name)) continue;
12012
+ if (!isIdentifier(child.name) || taken.has(child.name) && !service || named.has(child.name)) continue;
11906
12013
  named.add(child.name);
11907
12014
  members.push(`${child.name}: ${childAlias}`);
11908
12015
  }
@@ -11944,6 +12051,34 @@ function fileKey(path) {
11944
12051
  return process.platform === "win32" ? normalized.toLowerCase() : normalized;
11945
12052
  }
11946
12053
 
12054
+ // src/loweringHelpers.ts
12055
+ function withoutNil2(type) {
12056
+ if (!type) return [];
12057
+ const members = type.kind === "union" ? type.types : [type];
12058
+ return members.filter((m) => !(m.kind === "primitive" && m.name === "nil"));
12059
+ }
12060
+ function isFunctionType(type) {
12061
+ const members = withoutNil2(type);
12062
+ return members.length > 0 && members.every((m) => m.kind === "function" || m.kind === "intersection" && m.types.every(isFunctionType));
12063
+ }
12064
+ function everyObject(type, test) {
12065
+ const members = withoutNil2(type);
12066
+ return members.length > 0 && members.every((m) => m.kind === "object" && test(m));
12067
+ }
12068
+ function isInstanceOf(type, className) {
12069
+ return everyObject(type, (m) => m.class !== void 0 && m.class.ancestors.includes(className));
12070
+ }
12071
+ function hasMembers(type, names) {
12072
+ return everyObject(type, (m) => names.every((name) => m.properties.has(name)));
12073
+ }
12074
+ function returnsTuple(receiver, method) {
12075
+ return everyObject(receiver, (m) => {
12076
+ const found = m.properties.get(method)?.type;
12077
+ const signatures = !found ? [] : found.kind === "intersection" ? found.types : [found];
12078
+ return signatures.length > 0 && signatures.every((f) => f.kind === "function" && f.returns.kind === "tuple");
12079
+ });
12080
+ }
12081
+
11947
12082
  // src/index.ts
11948
12083
  var tilua = {
11949
12084
  tokenize,
@@ -11964,6 +12099,7 @@ var index_default = tilua;
11964
12099
  CONFIG_FILE_NAMES,
11965
12100
  Keywords,
11966
12101
  LANGUAGE_GLOBALS,
12102
+ LUAU_KEYWORDS,
11967
12103
  LexError,
11968
12104
  Operators,
11969
12105
  PRELUDE_SOURCE,
@@ -11984,20 +12120,27 @@ var index_default = tilua;
11984
12120
  difference,
11985
12121
  directivesOf,
11986
12122
  equalTypes,
12123
+ escapeLuauString,
11987
12124
  falsyType,
11988
12125
  findConfig,
11989
12126
  fn,
11990
12127
  formatType,
11991
12128
  getBinding,
12129
+ hasMembers,
11992
12130
  intersection,
11993
12131
  isAssignable,
11994
12132
  isClassType,
12133
+ isFunctionType,
11995
12134
  isGlobal,
12135
+ isIdentifier,
12136
+ isInstanceOf,
12137
+ isLuauName,
11996
12138
  isPossiblyFalsy,
11997
12139
  isPossiblyTruthy,
11998
12140
  isUnassignedGlobal,
11999
12141
  literal,
12000
12142
  loadConfig,
12143
+ luauString,
12001
12144
  matchInfer,
12002
12145
  moduleCandidates,
12003
12146
  moduleExports,
@@ -12020,6 +12163,7 @@ var index_default = tilua;
12020
12163
  readDirectives,
12021
12164
  resolveModulePath,
12022
12165
  resolveTypeLibraries,
12166
+ returnsTuple,
12023
12167
  setAliasExpander,
12024
12168
  setDeferredBound,
12025
12169
  sourceMapTypes,
@@ -12038,5 +12182,6 @@ var index_default = tilua;
12038
12182
  unknownType,
12039
12183
  widen,
12040
12184
  withAliasName,
12041
- withoutAliasName
12185
+ withoutAliasName,
12186
+ withoutNil
12042
12187
  });
package/dist/index.d.cts CHANGED
@@ -639,6 +639,12 @@ interface FunctionParameter extends BaseNode {
639
639
  typeAnnotation?: TypeNode;
640
640
  /** default value (`function f(a = 1) end`) */
641
641
  default?: Expression;
642
+ /** Not written in the source: the `this` a class method is given, or the
643
+ * `self` of `function T:m()`. It carries the span of what implies it
644
+ * (the method, the `T:m`) so a diagnostic has somewhere to point, but no
645
+ * text there is its name — an editor colours, hovers and renames none
646
+ * of it. */
647
+ implicit?: boolean;
642
648
  }
643
649
  interface FunctionBody extends BaseNode {
644
650
  type: "FunctionBody";
@@ -1601,7 +1607,7 @@ resolveModule?: (specifier: string) => ModuleExports | undefined): ModuleExports
1601
1607
  * `ObjectValues<T>` and `ObjectEntries<T>`, an object's members as tuples in
1602
1608
  * the order they were written.
1603
1609
  */
1604
- declare const PRELUDE_SOURCE = "\n-- In Luau only `nil` and `false` are falsy: `0` and `\"\"` are truthy.\n-- These are what truthiness narrowing computes, made available to write down.\ntype Falsy = nil | false\ntype Truthy<T> = T - Falsy\n\n-- `-` is set difference. Over a union it drops members; over a concrete type\n-- it simplifies away; over an opaque type (`unknown`, an unresolved parameter)\n-- it is kept, so `Exclude<unknown, 1>` stays `unknown - 1`.\ntype Exclude<T, U> = T - U\ntype Extract<T, U> = T extends U ? T : never\ntype NonNullable<T> = T - nil\n\ntype ReturnType<T> = T extends (...args: unknown[]) => infer R ? R : never\ntype Parameters<T> = T extends (...args: infer P) => unknown ? P : never\n\ntype Partial<T> = { [K in keyof T]?: T[K] }\ntype Required<T> = { [K in keyof T]-?: T[K] }\ntype Readonly<T> = { readonly [K in keyof T]: T[K] }\ntype Mutable<T> = { -readonly [K in keyof T]: T[K] }\n\ntype Pick<T, K> = { [P in K]: T[P] }\ntype Omit<T, K> = Pick<T, Exclude<keyof T, K>>\ntype Record<K, V> = { [P in K]: V }\n\n-- ============================================================\n-- The metatables of the language's own values\n-- ============================================================\n\n-- A string's methods. The first group is Lua's string library, which a\n-- string really answers to; where Lua answers several values, tilua answers\n-- one, as the global functions do (`find` is an array, `gsub` the new\n-- string). The second group is written the way JavaScript writes it.\n--\n-- Positions are Lua's: `sub` and `slice` count from 1, and `indexOf` is\n-- `nil` when the text is not there.\ndeclare metatable string: {\n __index: {\n upper: (self: string) => string,\n lower: (self: string) => string,\n len: (self: string) => number,\n sub: (self: string, i: number, j?: number) => string,\n rep: (self: string, n: number, separator?: string) => string,\n reverse: (self: string) => string,\n format: (self: string, ...args: unknown[]) => string,\n byte: ((self: string, i?: number) => number) & ((self: string, i: number, j: number) => number[]),\n find: (self: string, pattern: string, init?: number, plain?: boolean) => [number, number, ...string[]] | nil,\n match: (self: string, pattern: string, init?: number) => [...string[]] | nil,\n gmatch: (self: string, pattern: string) => () => [string, ...string[]] | nil,\n gsub: (self: string, pattern: string, replacement: unknown, n?: number) => string,\n\n trim: (self: string) => string,\n trimStart: (self: string) => string,\n trimEnd: (self: string) => string,\n startsWith: (self: string, text: string) => boolean,\n endsWith: (self: string, text: string) => boolean,\n includes: (self: string, text: string) => boolean,\n indexOf: (self: string, text: string, start?: number) => number | nil,\n slice: (self: string, start?: number, stop?: number) => string,\n replace: (self: string, text: string, replacement: string) => string,\n replaceAll: (self: string, text: string, replacement: string) => string,\n padStart: (self: string, length: number, padding?: string) => string,\n padEnd: (self: string, length: number, padding?: string) => string,\n },\n}\n\n-- An array's methods. Lua gives an array no metatable: the compiler lowers\n-- each call to a plain function, so they work on any array, one a Lua\n-- library made included.\n--\n-- Indices are Lua's: the first element is 1, and `indexOf` / `findIndex`\n-- answer `nil` rather than JavaScript's -1. `sort` takes Lua's comparator\n-- (true when `a` comes first). `push`, `pop`, `shift`, `unshift`,\n-- `sort` and `reverse` change the array; everything else returns a new one.\n-- A `filter` whose test is a guard \u2014 `v is S`, or `v => v ~= nil` \u2014\n-- answers an array of what it let through.\ndeclare metatable<T> T[]: {\n __index: {\n find: (self: T[], test: (value: T, index: number) => boolean) => T | nil,\n findIndex: (self: T[], test: (value: T, index: number) => boolean) => number | nil,\n filter: (<S extends T>(self: T[], test: (value: T, index: number) => value is S) => S[])\n & ((self: T[], test: (value: T, index: number) => boolean) => T[]),\n map: <U>(self: T[], transform: (value: T, index: number) => U) => U[],\n forEach: (self: T[], visit: (value: T, index: number) => nil) => nil,\n some: (self: T[], test: (value: T, index: number) => boolean) => boolean,\n every: (self: T[], test: (value: T, index: number) => boolean) => boolean,\n reduce: <U>(self: T[], step: (total: U, value: T, index: number) => U, initial: U) => U,\n includes: (self: T[], value: T) => boolean,\n indexOf: (self: T[], value: T, start?: number) => number | nil,\n join: (self: T[], separator?: string) => string,\n concat: (self: T[], ...others: T[][]) => T[],\n slice: (self: T[], start?: number, stop?: number) => T[],\n flat: (self: T[]) => T[],\n reverse: (self: T[]) => T[],\n sort: (self: T[], compare?: (a: T, b: T) => boolean) => T[],\n push: (self: T[], ...args: T[]) => number,\n pop: (self: T[]) => T | nil,\n shift: (self: T[]) => T | nil,\n unshift: (self: T[], ...args: T[]) => number,\n },\n}\n\n-- A table's methods. Unlike JavaScript's `Object.keys`, they answer a\n-- tuple, in the order the table's type wrote its members:\n--\n-- const point = { x: 1, y: \"up\" }\n-- point:keys() -- [\"x\", \"y\"]\n-- point:values() -- [number, string]\n-- point:entries() -- [[\"x\", number], [\"y\", string]]\n--\n-- A Lua table has no order of its own, so the compiler hands its runtime the\n-- keys as the type lists them. An optional member keeps its place, holding\n-- `nil` when it is missing; an indexer's keys follow the named ones. A\n-- member of the table's own with one of these names is what a call reaches,\n-- and a class instance, which has a metatable of its own, has none of them.\ndeclare metatable<T extends {}> T: {\n __index: {\n keys: (self: T) => ObjectKeys<T>,\n values: (self: T) => ObjectValues<T>,\n entries: (self: T) => ObjectEntries<T>,\n },\n}\n";
1610
+ declare const PRELUDE_SOURCE = "\n-- In Luau only `nil` and `false` are falsy: `0` and `\"\"` are truthy.\n-- These are what truthiness narrowing computes, made available to write down.\ntype Falsy = nil | false\ntype Truthy<T> = T - Falsy\n\n-- `-` is set difference. Over a union it drops members; over a concrete type\n-- it simplifies away; over an opaque type (`unknown`, an unresolved parameter)\n-- it is kept, so `Exclude<unknown, 1>` stays `unknown - 1`.\ntype Exclude<T, U> = T - U\ntype Extract<T, U> = T extends U ? T : never\ntype NonNullable<T> = T - nil\n\ntype ReturnType<T> = T extends (...args: unknown[]) => infer R ? R : never\ntype Parameters<T> = T extends (...args: infer P) => unknown ? P : never\n\ntype Partial<T> = { [K in keyof T]?: T[K] }\ntype Required<T> = { [K in keyof T]-?: T[K] }\ntype Readonly<T> = { readonly [K in keyof T]: T[K] }\ntype Mutable<T> = { -readonly [K in keyof T]: T[K] }\n\ntype Pick<T, K> = { [P in K]: T[P] }\ntype Omit<T, K> = Pick<T, Exclude<keyof T, K>>\ntype Record<K, V> = { [P in K]: V }\n\n-- ============================================================\n-- The metatables of the language's own values\n-- ============================================================\n\n-- A string's methods. The first group is Lua's string library, which a\n-- string really answers to; where Lua answers several values, tilua answers\n-- one, as the global functions do (`find` is an array, `gsub` the new\n-- string). The second group is written the way JavaScript writes it.\n--\n-- Positions are Lua's: `sub` and `slice` count from 1, and `indexOf` is\n-- `nil` when the text is not there.\ndeclare metatable string: {\n __index: {\n upper: (self: string) => string,\n lower: (self: string) => string,\n len: (self: string) => number,\n sub: (self: string, i: number, j?: number) => string,\n rep: (self: string, n: number, separator?: string) => string,\n reverse: (self: string) => string,\n format: (self: string, ...args: unknown[]) => string,\n byte: ((self: string, i?: number) => number) & ((self: string, i: number, j: number) => number[]),\n find: (self: string, pattern: string, init?: number, plain?: boolean) => [number, number, ...string[]] | nil,\n match: (self: string, pattern: string, init?: number) => [...string[]] | nil,\n gmatch: (self: string, pattern: string) => () => [string, ...string[]] | nil,\n gsub: (self: string, pattern: string, replacement: unknown, n?: number) => string,\n\n trim: (self: string) => string,\n trimStart: (self: string) => string,\n trimEnd: (self: string) => string,\n startsWith: (self: string, text: string) => boolean,\n endsWith: (self: string, text: string) => boolean,\n includes: (self: string, text: string) => boolean,\n indexOf: (self: string, text: string, start?: number) => number | nil,\n slice: (self: string, start?: number, stop?: number) => string,\n replace: (self: string, text: string, replacement: string) => string,\n replaceAll: (self: string, text: string, replacement: string) => string,\n padStart: (self: string, length: number, padding?: string) => string,\n padEnd: (self: string, length: number, padding?: string) => string,\n },\n}\n\n-- An array's methods. Lua gives an array no metatable: the compiler lowers\n-- each call to a plain function, so they work on any array, one a Lua\n-- library made included.\n--\n-- Indices are Lua's: the first element is 1, and `indexOf` / `findIndex`\n-- answer `nil` rather than JavaScript's -1. `sort` takes Lua's comparator\n-- (true when `a` comes first). `push`, `pop`, `shift`, `unshift`,\n-- `sort` and `reverse` change the array; everything else returns a new one.\n-- A `filter` whose test is a guard \u2014 `v is S`, or `v => v ~= nil` \u2014\n-- answers an array of what it let through.\ndeclare metatable<T> T[]: {\n __index: {\n find: (self: T[], test: (value: T, index: number) => boolean) => T | nil,\n findIndex: (self: T[], test: (value: T, index: number) => boolean) => number | nil,\n filter: (<S extends T>(self: T[], test: (value: T, index: number) => value is S) => S[])\n & ((self: T[], test: (value: T, index: number) => boolean) => T[]),\n map: <U>(self: T[], transform: (value: T, index: number) => U) => U[],\n forEach: (self: T[], visit: (value: T, index: number) => nil) => nil,\n some: (self: T[], test: (value: T, index: number) => boolean) => boolean,\n every: (self: T[], test: (value: T, index: number) => boolean) => boolean,\n reduce: <U>(self: T[], step: (total: U, value: T, index: number) => U, initial: U) => U,\n includes: (self: T[], value: T) => boolean,\n indexOf: (self: T[], value: T, start?: number) => number | nil,\n join: (self: T[], separator?: string) => string,\n concat: (self: T[], ...others: T[][]) => T[],\n slice: (self: T[], start?: number, stop?: number) => T[],\n flat: (self: T[]) => T[],\n reverse: (self: T[]) => T[],\n sort: (self: T[], compare?: (a: T, b: T) => boolean) => T[],\n push: (self: T[], ...args: T[]) => number,\n pop: (self: T[]) => T | nil,\n shift: (self: T[]) => T | nil,\n unshift: (self: T[], ...args: T[]) => number,\n },\n}\n\n-- A table's methods. Unlike JavaScript's `Object.keys`, they answer a\n-- tuple, in the order the table's type wrote its members:\n--\n-- const point = { x: 1, y: \"up\" }\n-- point:keys() -- [\"x\", \"y\"]\n-- point:values() -- [number, string]\n-- point:entries() -- [[\"x\", number], [\"y\", string]]\n--\n-- A Lua table has no order of its own, so the compiler hands its runtime the\n-- keys as the type lists them. An optional member keeps its place, holding\n-- `nil` when it is missing; an indexer's keys follow the named ones. A\n-- member of the table's own with one of these names is what a call reaches,\n-- and a class instance, which has a metatable of its own, has none of them.\n--\n-- The rest are JavaScript's `Object` functions, written as methods of the\n-- table they take first:\n--\n-- point:hasOwn(\"x\") -- Object.hasOwn(point, \"x\")\n-- point:assign({ z: 3 }) -- Object.assign(point, { z: 3 })\n-- point:freeze() -- Object.freeze(point)\n--\n-- `hasOwn` asks the table itself, not what its metatable's `__index`\n-- lends it. `assign` copies each source's members onto the table, later ones\n-- over earlier ones, skipping a `nil` source, and answers the table. `freeze`\n-- is Luau's `table.freeze`; under Lua 5.1, which cannot freeze a table, the\n-- table is answered as it is and `isFrozen` is false.\ndeclare metatable<T extends {}> T: {\n __index: {\n keys: (self: T) => ObjectKeys<T>,\n values: (self: T) => ObjectValues<T>,\n entries: (self: T) => ObjectEntries<T>,\n\n hasOwn: (self: T, key: unknown) => boolean,\n hasOwnProperty: (self: T, key: unknown) => boolean,\n assign: (<U>(self: T, source: U) => T & U)\n & (<U, V>(self: T, a: U, b: V) => T & U & V)\n & (<U, V, W>(self: T, a: U, b: V, c: W) => T & U & V & W)\n -- Generic like the rest: a plain signature would be tried first.\n & (<S extends {}>(self: T, ...sources: S[]) => T),\n freeze: (self: T) => Readonly<T>,\n isFrozen: (self: T) => boolean,\n },\n}\n";
1605
1611
 
1606
1612
  interface ProjectHost {
1607
1613
  /** A file's text, or `undefined` when there is no such file. */
@@ -1722,6 +1728,10 @@ declare function resolveTypeLibraries(config: TiluaConfig, host?: ProjectHost):
1722
1728
  * },
1723
1729
  * }
1724
1730
  * export default plugin
1731
+ *
1732
+ * What a plugin runs to decide and to write — `luauString`, `isInstanceOf`,
1733
+ * `returnsTuple`, ... — is exported beside this contract (see `luau.ts` and
1734
+ * `loweringHelpers.ts`), so no plugin keeps a copy.
1725
1735
  */
1726
1736
 
1727
1737
  interface LoweringPlugin {
@@ -1865,6 +1875,66 @@ declare function sourceMapTypes(text: string, path: string, options: SourceMapOp
1865
1875
  problem?: string;
1866
1876
  };
1867
1877
 
1878
+ /**
1879
+ * Writing Luau source as text: what a name may be and how a string is quoted.
1880
+ *
1881
+ * The compiler emits Luau, a lowering plugin hands back Luau expressions, and
1882
+ * a server filling placeholders into a bundle writes Luau strings. Each needs
1883
+ * the same few rules, and they live here so none of them keeps its own copy.
1884
+ * Nothing here parses or runs Luau.
1885
+ */
1886
+ /** Luau's reserved words. tilua reserves most of them too — `local` is the
1887
+ * exception, so a tilua name can still be one of these. */
1888
+ declare const LUAU_KEYWORDS: ReadonlySet<string>;
1889
+ /** Is `name` shaped like a name — a letter or `_`, then letters, digits and
1890
+ * `_`? tilua's and Luau's names are both this shape; whether it is also a
1891
+ * keyword is another question (`isLuauName`). */
1892
+ declare function isIdentifier(name: string): boolean;
1893
+ /** Can `name` be written bare in Luau — as a variable, `t.name` or `{ name = v }`? */
1894
+ declare function isLuauName(name: string): boolean;
1895
+ /** `text` as the inside of a double-quoted Luau string, without the quotes:
1896
+ * for splicing into a `"..."` that is already written.
1897
+ *
1898
+ * Every control character is escaped, as `\n` where Luau has a name for it and
1899
+ * as three decimal digits otherwise — always three, so a digit that follows
1900
+ * (`"\1" .. "2"`) is never read as part of the escape. Not `JSON.stringify`:
1901
+ * its `\u0001` is not a Luau escape. Anything else, `é` or `한` included, is
1902
+ * written as it is; Luau source is UTF-8. */
1903
+ declare function escapeLuauString(text: string): string;
1904
+ /** `text` as a double-quoted Luau string literal: `"a\nb"`. */
1905
+ declare function luauString(text: string): string;
1906
+
1907
+ /**
1908
+ * Questions a lowering plugin asks of a type, answered once here.
1909
+ *
1910
+ * A plugin decides how to lower a call from the receiver's or an argument's
1911
+ * type (see `LoweringPlugin`). The same few questions come up in every one —
1912
+ * is it a function, is it an instance of this class, what does this method
1913
+ * return — and a plugin imports these rather than walking the type model
1914
+ * itself:
1915
+ *
1916
+ * import { isInstanceOf } from "@tilua/parser"
1917
+ *
1918
+ * Each looks through a union with `nil` (`Part | nil`): whether the value may
1919
+ * be missing is a check the analyzer asked for elsewhere, not a reason to
1920
+ * lower differently.
1921
+ */
1922
+
1923
+ /** The members of `type` that are not `nil`: `[A, B]` for `A | B | nil`,
1924
+ * `[T]` for any other `T`, and `[]` for `undefined` or `nil` alone. */
1925
+ declare function withoutNil(type: Type | undefined): Type[];
1926
+ /** A function, or an overloaded one (an intersection of functions). */
1927
+ declare function isFunctionType(type: Type | undefined): boolean;
1928
+ /** An instance of `className` or of a class extending it: a `Part` is an
1929
+ * instance of `BasePart` and of `Instance`. */
1930
+ declare function isInstanceOf(type: Type | undefined, className: string): boolean;
1931
+ /** Has every one of `names` as a member — a structural check, for a type
1932
+ * known by its shape rather than its class. */
1933
+ declare function hasMembers(type: Type | undefined, names: readonly string[]): boolean;
1934
+ /** Does every signature of `receiver`'s `method` return a tuple — several
1935
+ * values, as tilua has them in one array? False when the method is missing. */
1936
+ declare function returnsTuple(receiver: Type | undefined, method: string): boolean;
1937
+
1868
1938
  declare const tilua: {
1869
1939
  readonly tokenize: typeof tokenize;
1870
1940
  readonly parseTokens: typeof parseTokens;
@@ -1878,4 +1948,4 @@ declare const tilua: {
1878
1948
  readonly analyzeTypes: typeof analyzeTypes;
1879
1949
  };
1880
1950
 
1881
- export { type AnalyzeTypesOptions, type AnyType, type ArgumentInfo, type ArrayExpression, type ArrayPattern, type ArrayPatternElement, type ArrayType, type ArrayTypeNode, type AsConstExpression, type AssignmentStatement, type BaseNode, type BaseToken, type BinaryExpression, BinaryOperators, type Binding, type BindingId, type BindingKind, type BindingTarget, type Block, type BooleanLiteral, type BreakStatement, type BuildTarget, CONFIG_FILE_NAMES, type CallExpression, type CallLowering, type CallSite, type CallStatement, type ClassAccessibility, type ClassAccessor, type ClassConstructor, type ClassDeclaration, type ClassExpression, type ClassField, type ClassInfo, type ClassLike, type ClassMember, type ClassMethod, type CompoundAssignmentStatement, type ConditionalType, type ConditionalTypeNode, type ConfigLookup, type ConfigProblem, type ContinueStatement, type DeclareClassStatement, type DeclareMetatableStatement, type DeclareStatement, type DifferenceType, type DifferenceTypeNode, type Directive, type DirectiveKind, type DirectiveOutcome, type Directives, type DoStatement, type EOFToken, type ErrorExpression, type ErrorStatement, type ExportAllStatement, type ExportDefaultStatement, type ExportNamedStatement, type ExportSpecifier, type ExportStatement, type ExportTypeAliasStatement, type ExportedType, type Expression, type ExpressionStatement, type FunctionBody, type FunctionDeclaration, type FunctionDeclarationStatement, type FunctionExpression, type FunctionName, type FunctionParam, type FunctionParameter, type FunctionSignature, type FunctionType, type FunctionTypeNode, type FunctionTypeParameter, type GenericForStatement, type GenericRefType, type GenericTypeParameter, type GlobalCall, type GlobalValue, type Identifier, type IdentifierPattern, type IdentifierToken, type IfClause, type IfElseExpression, type IfStatement, type ImportSpecifier, type ImportStatement, type IndexExpression, type IndexedAccessType, type IndexedAccessTypeNode, type InferType, type InferTypeNode, type InterpolatedStringExpression, type InterpolatedStringPart, type InterpolatedStringPart_Expression, type InterpolatedStringPart_String, type InterpolatedStringToken, type IntersectionType, type IntersectionTypeNode, type KeyofType, type KeyofTypeNode, type KeywordToken, Keywords, LANGUAGE_GLOBALS, LexError, type LiteralToken, type LiteralType, type LoweringModule, type LoweringPlugin, type MappedType, type MappedTypeNode, type MemberExpression, type MethodCall, type MethodCallExpression, type MethodLowering, type ModuleExports, type NeverType, type NilLiteral, type Node, type NumberLiteral, type NumericForStatement, type ObjectPattern, type ObjectPatternProperty, type ObjectProperty, type ObjectType, type OperatorToken, Operators, PRELUDE_SOURCE, type ParenthesizedExpression, type ParenthesizedTypeNode, ParseError, type ParserOptions, type PrimitiveName, type PrimitiveType, type Program, type ProjectHost, type PunctuatorToken, Punctuators, type RecoverResult, type RepeatStatement, type ReturnStatement, type SatisfiesExpression, type ScopeAnalysis, type ScopeDiagnostic, type SourceComment, type SourceMapNode, type SourceMapOptions, type SourceMapTypes, type SpreadElement, type Statement, type StringLiteral, type SuperExpression, type TableExpression, type TableField, type TableTypeNode, type TableTypeProperty, type TemplateLiteralType, type TemplateLiteralTypeNode, type TiluaConfig, type Token, type TokenizeOptions, type TupleType, type TupleTypeNode, type Type, type TypeAliasStatement, type TypeAnalysis, type TypeAssertionExpression, type TypeDiagnostic, type TypeLibraries, type TypeLiteralBoolean, type TypeLiteralNumber, type TypeLiteralString, type TypeNode, type TypeOrigin, type TypeParamType, type TypePredicate, type TypePredicateNode, type TypeReference, type TypedIdentifier, type TypeofTypeNode, UNUSED_EXPECT_ERROR, type UnaryExpression, UnaryOperators, type Unification, type UnionType, type UnionTypeNode, type UnknownType, type VariableDeclaration, type WhileStatement, aliasNameOf, analyzeScopes, analyzeTypes, anyType, applyDirectives, arrayOf, booleanType, bufferType, containsTypeParam, declaredUnknownType, tilua as default, difference, directivesOf, equalTypes, falsyType, findConfig, fn, formatType, getBinding, intersection, isAssignable, isClassType, isGlobal, isPossiblyFalsy, isPossiblyTruthy, isUnassignedGlobal, literal, loadConfig, matchInfer, moduleCandidates, moduleExports, narrowExclude, narrowFalsy, narrowTo, narrowTruthy, neverType, nilType, nodeHost, numberType, objectType, optional, overlaps, parse, parseExpressionFromSource, parseTokens, parseWithRecovery, primitive, readDirectives, resolveModulePath, resolveTypeLibraries, setAliasExpander, setDeferredBound, sourceMapTypes, stringType, stripJsonComments, substitute, templateMatches, threadType, tilua, tokenize, tuple, tupleMembers, typeParam, unify, union, unknownType, widen, withAliasName, withoutAliasName };
1951
+ export { type AnalyzeTypesOptions, type AnyType, type ArgumentInfo, type ArrayExpression, type ArrayPattern, type ArrayPatternElement, type ArrayType, type ArrayTypeNode, type AsConstExpression, type AssignmentStatement, type BaseNode, type BaseToken, type BinaryExpression, BinaryOperators, type Binding, type BindingId, type BindingKind, type BindingTarget, type Block, type BooleanLiteral, type BreakStatement, type BuildTarget, CONFIG_FILE_NAMES, type CallExpression, type CallLowering, type CallSite, type CallStatement, type ClassAccessibility, type ClassAccessor, type ClassConstructor, type ClassDeclaration, type ClassExpression, type ClassField, type ClassInfo, type ClassLike, type ClassMember, type ClassMethod, type CompoundAssignmentStatement, type ConditionalType, type ConditionalTypeNode, type ConfigLookup, type ConfigProblem, type ContinueStatement, type DeclareClassStatement, type DeclareMetatableStatement, type DeclareStatement, type DifferenceType, type DifferenceTypeNode, type Directive, type DirectiveKind, type DirectiveOutcome, type Directives, type DoStatement, type EOFToken, type ErrorExpression, type ErrorStatement, type ExportAllStatement, type ExportDefaultStatement, type ExportNamedStatement, type ExportSpecifier, type ExportStatement, type ExportTypeAliasStatement, type ExportedType, type Expression, type ExpressionStatement, type FunctionBody, type FunctionDeclaration, type FunctionDeclarationStatement, type FunctionExpression, type FunctionName, type FunctionParam, type FunctionParameter, type FunctionSignature, type FunctionType, type FunctionTypeNode, type FunctionTypeParameter, type GenericForStatement, type GenericRefType, type GenericTypeParameter, type GlobalCall, type GlobalValue, type Identifier, type IdentifierPattern, type IdentifierToken, type IfClause, type IfElseExpression, type IfStatement, type ImportSpecifier, type ImportStatement, type IndexExpression, type IndexedAccessType, type IndexedAccessTypeNode, type InferType, type InferTypeNode, type InterpolatedStringExpression, type InterpolatedStringPart, type InterpolatedStringPart_Expression, type InterpolatedStringPart_String, type InterpolatedStringToken, type IntersectionType, type IntersectionTypeNode, type KeyofType, type KeyofTypeNode, type KeywordToken, Keywords, LANGUAGE_GLOBALS, LUAU_KEYWORDS, LexError, type LiteralToken, type LiteralType, type LoweringModule, type LoweringPlugin, type MappedType, type MappedTypeNode, type MemberExpression, type MethodCall, type MethodCallExpression, type MethodLowering, type ModuleExports, type NeverType, type NilLiteral, type Node, type NumberLiteral, type NumericForStatement, type ObjectPattern, type ObjectPatternProperty, type ObjectProperty, type ObjectType, type OperatorToken, Operators, PRELUDE_SOURCE, type ParenthesizedExpression, type ParenthesizedTypeNode, ParseError, type ParserOptions, type PrimitiveName, type PrimitiveType, type Program, type ProjectHost, type PunctuatorToken, Punctuators, type RecoverResult, type RepeatStatement, type ReturnStatement, type SatisfiesExpression, type ScopeAnalysis, type ScopeDiagnostic, type SourceComment, type SourceMapNode, type SourceMapOptions, type SourceMapTypes, type SpreadElement, type Statement, type StringLiteral, type SuperExpression, type TableExpression, type TableField, type TableTypeNode, type TableTypeProperty, type TemplateLiteralType, type TemplateLiteralTypeNode, type TiluaConfig, type Token, type TokenizeOptions, type TupleType, type TupleTypeNode, type Type, type TypeAliasStatement, type TypeAnalysis, type TypeAssertionExpression, type TypeDiagnostic, type TypeLibraries, type TypeLiteralBoolean, type TypeLiteralNumber, type TypeLiteralString, type TypeNode, type TypeOrigin, type TypeParamType, type TypePredicate, type TypePredicateNode, type TypeReference, type TypedIdentifier, type TypeofTypeNode, UNUSED_EXPECT_ERROR, type UnaryExpression, UnaryOperators, type Unification, type UnionType, type UnionTypeNode, type UnknownType, type VariableDeclaration, type WhileStatement, aliasNameOf, analyzeScopes, analyzeTypes, anyType, applyDirectives, arrayOf, booleanType, bufferType, containsTypeParam, declaredUnknownType, tilua as default, difference, directivesOf, equalTypes, escapeLuauString, falsyType, findConfig, fn, formatType, getBinding, hasMembers, intersection, isAssignable, isClassType, isFunctionType, isGlobal, isIdentifier, isInstanceOf, isLuauName, isPossiblyFalsy, isPossiblyTruthy, isUnassignedGlobal, literal, loadConfig, luauString, matchInfer, moduleCandidates, moduleExports, narrowExclude, narrowFalsy, narrowTo, narrowTruthy, neverType, nilType, nodeHost, numberType, objectType, optional, overlaps, parse, parseExpressionFromSource, parseTokens, parseWithRecovery, primitive, readDirectives, resolveModulePath, resolveTypeLibraries, returnsTuple, setAliasExpander, setDeferredBound, sourceMapTypes, stringType, stripJsonComments, substitute, templateMatches, threadType, tilua, tokenize, tuple, tupleMembers, typeParam, unify, union, unknownType, widen, withAliasName, withoutAliasName, withoutNil };
package/dist/index.d.ts CHANGED
@@ -639,6 +639,12 @@ interface FunctionParameter extends BaseNode {
639
639
  typeAnnotation?: TypeNode;
640
640
  /** default value (`function f(a = 1) end`) */
641
641
  default?: Expression;
642
+ /** Not written in the source: the `this` a class method is given, or the
643
+ * `self` of `function T:m()`. It carries the span of what implies it
644
+ * (the method, the `T:m`) so a diagnostic has somewhere to point, but no
645
+ * text there is its name — an editor colours, hovers and renames none
646
+ * of it. */
647
+ implicit?: boolean;
642
648
  }
643
649
  interface FunctionBody extends BaseNode {
644
650
  type: "FunctionBody";
@@ -1601,7 +1607,7 @@ resolveModule?: (specifier: string) => ModuleExports | undefined): ModuleExports
1601
1607
  * `ObjectValues<T>` and `ObjectEntries<T>`, an object's members as tuples in
1602
1608
  * the order they were written.
1603
1609
  */
1604
- declare const PRELUDE_SOURCE = "\n-- In Luau only `nil` and `false` are falsy: `0` and `\"\"` are truthy.\n-- These are what truthiness narrowing computes, made available to write down.\ntype Falsy = nil | false\ntype Truthy<T> = T - Falsy\n\n-- `-` is set difference. Over a union it drops members; over a concrete type\n-- it simplifies away; over an opaque type (`unknown`, an unresolved parameter)\n-- it is kept, so `Exclude<unknown, 1>` stays `unknown - 1`.\ntype Exclude<T, U> = T - U\ntype Extract<T, U> = T extends U ? T : never\ntype NonNullable<T> = T - nil\n\ntype ReturnType<T> = T extends (...args: unknown[]) => infer R ? R : never\ntype Parameters<T> = T extends (...args: infer P) => unknown ? P : never\n\ntype Partial<T> = { [K in keyof T]?: T[K] }\ntype Required<T> = { [K in keyof T]-?: T[K] }\ntype Readonly<T> = { readonly [K in keyof T]: T[K] }\ntype Mutable<T> = { -readonly [K in keyof T]: T[K] }\n\ntype Pick<T, K> = { [P in K]: T[P] }\ntype Omit<T, K> = Pick<T, Exclude<keyof T, K>>\ntype Record<K, V> = { [P in K]: V }\n\n-- ============================================================\n-- The metatables of the language's own values\n-- ============================================================\n\n-- A string's methods. The first group is Lua's string library, which a\n-- string really answers to; where Lua answers several values, tilua answers\n-- one, as the global functions do (`find` is an array, `gsub` the new\n-- string). The second group is written the way JavaScript writes it.\n--\n-- Positions are Lua's: `sub` and `slice` count from 1, and `indexOf` is\n-- `nil` when the text is not there.\ndeclare metatable string: {\n __index: {\n upper: (self: string) => string,\n lower: (self: string) => string,\n len: (self: string) => number,\n sub: (self: string, i: number, j?: number) => string,\n rep: (self: string, n: number, separator?: string) => string,\n reverse: (self: string) => string,\n format: (self: string, ...args: unknown[]) => string,\n byte: ((self: string, i?: number) => number) & ((self: string, i: number, j: number) => number[]),\n find: (self: string, pattern: string, init?: number, plain?: boolean) => [number, number, ...string[]] | nil,\n match: (self: string, pattern: string, init?: number) => [...string[]] | nil,\n gmatch: (self: string, pattern: string) => () => [string, ...string[]] | nil,\n gsub: (self: string, pattern: string, replacement: unknown, n?: number) => string,\n\n trim: (self: string) => string,\n trimStart: (self: string) => string,\n trimEnd: (self: string) => string,\n startsWith: (self: string, text: string) => boolean,\n endsWith: (self: string, text: string) => boolean,\n includes: (self: string, text: string) => boolean,\n indexOf: (self: string, text: string, start?: number) => number | nil,\n slice: (self: string, start?: number, stop?: number) => string,\n replace: (self: string, text: string, replacement: string) => string,\n replaceAll: (self: string, text: string, replacement: string) => string,\n padStart: (self: string, length: number, padding?: string) => string,\n padEnd: (self: string, length: number, padding?: string) => string,\n },\n}\n\n-- An array's methods. Lua gives an array no metatable: the compiler lowers\n-- each call to a plain function, so they work on any array, one a Lua\n-- library made included.\n--\n-- Indices are Lua's: the first element is 1, and `indexOf` / `findIndex`\n-- answer `nil` rather than JavaScript's -1. `sort` takes Lua's comparator\n-- (true when `a` comes first). `push`, `pop`, `shift`, `unshift`,\n-- `sort` and `reverse` change the array; everything else returns a new one.\n-- A `filter` whose test is a guard \u2014 `v is S`, or `v => v ~= nil` \u2014\n-- answers an array of what it let through.\ndeclare metatable<T> T[]: {\n __index: {\n find: (self: T[], test: (value: T, index: number) => boolean) => T | nil,\n findIndex: (self: T[], test: (value: T, index: number) => boolean) => number | nil,\n filter: (<S extends T>(self: T[], test: (value: T, index: number) => value is S) => S[])\n & ((self: T[], test: (value: T, index: number) => boolean) => T[]),\n map: <U>(self: T[], transform: (value: T, index: number) => U) => U[],\n forEach: (self: T[], visit: (value: T, index: number) => nil) => nil,\n some: (self: T[], test: (value: T, index: number) => boolean) => boolean,\n every: (self: T[], test: (value: T, index: number) => boolean) => boolean,\n reduce: <U>(self: T[], step: (total: U, value: T, index: number) => U, initial: U) => U,\n includes: (self: T[], value: T) => boolean,\n indexOf: (self: T[], value: T, start?: number) => number | nil,\n join: (self: T[], separator?: string) => string,\n concat: (self: T[], ...others: T[][]) => T[],\n slice: (self: T[], start?: number, stop?: number) => T[],\n flat: (self: T[]) => T[],\n reverse: (self: T[]) => T[],\n sort: (self: T[], compare?: (a: T, b: T) => boolean) => T[],\n push: (self: T[], ...args: T[]) => number,\n pop: (self: T[]) => T | nil,\n shift: (self: T[]) => T | nil,\n unshift: (self: T[], ...args: T[]) => number,\n },\n}\n\n-- A table's methods. Unlike JavaScript's `Object.keys`, they answer a\n-- tuple, in the order the table's type wrote its members:\n--\n-- const point = { x: 1, y: \"up\" }\n-- point:keys() -- [\"x\", \"y\"]\n-- point:values() -- [number, string]\n-- point:entries() -- [[\"x\", number], [\"y\", string]]\n--\n-- A Lua table has no order of its own, so the compiler hands its runtime the\n-- keys as the type lists them. An optional member keeps its place, holding\n-- `nil` when it is missing; an indexer's keys follow the named ones. A\n-- member of the table's own with one of these names is what a call reaches,\n-- and a class instance, which has a metatable of its own, has none of them.\ndeclare metatable<T extends {}> T: {\n __index: {\n keys: (self: T) => ObjectKeys<T>,\n values: (self: T) => ObjectValues<T>,\n entries: (self: T) => ObjectEntries<T>,\n },\n}\n";
1610
+ declare const PRELUDE_SOURCE = "\n-- In Luau only `nil` and `false` are falsy: `0` and `\"\"` are truthy.\n-- These are what truthiness narrowing computes, made available to write down.\ntype Falsy = nil | false\ntype Truthy<T> = T - Falsy\n\n-- `-` is set difference. Over a union it drops members; over a concrete type\n-- it simplifies away; over an opaque type (`unknown`, an unresolved parameter)\n-- it is kept, so `Exclude<unknown, 1>` stays `unknown - 1`.\ntype Exclude<T, U> = T - U\ntype Extract<T, U> = T extends U ? T : never\ntype NonNullable<T> = T - nil\n\ntype ReturnType<T> = T extends (...args: unknown[]) => infer R ? R : never\ntype Parameters<T> = T extends (...args: infer P) => unknown ? P : never\n\ntype Partial<T> = { [K in keyof T]?: T[K] }\ntype Required<T> = { [K in keyof T]-?: T[K] }\ntype Readonly<T> = { readonly [K in keyof T]: T[K] }\ntype Mutable<T> = { -readonly [K in keyof T]: T[K] }\n\ntype Pick<T, K> = { [P in K]: T[P] }\ntype Omit<T, K> = Pick<T, Exclude<keyof T, K>>\ntype Record<K, V> = { [P in K]: V }\n\n-- ============================================================\n-- The metatables of the language's own values\n-- ============================================================\n\n-- A string's methods. The first group is Lua's string library, which a\n-- string really answers to; where Lua answers several values, tilua answers\n-- one, as the global functions do (`find` is an array, `gsub` the new\n-- string). The second group is written the way JavaScript writes it.\n--\n-- Positions are Lua's: `sub` and `slice` count from 1, and `indexOf` is\n-- `nil` when the text is not there.\ndeclare metatable string: {\n __index: {\n upper: (self: string) => string,\n lower: (self: string) => string,\n len: (self: string) => number,\n sub: (self: string, i: number, j?: number) => string,\n rep: (self: string, n: number, separator?: string) => string,\n reverse: (self: string) => string,\n format: (self: string, ...args: unknown[]) => string,\n byte: ((self: string, i?: number) => number) & ((self: string, i: number, j: number) => number[]),\n find: (self: string, pattern: string, init?: number, plain?: boolean) => [number, number, ...string[]] | nil,\n match: (self: string, pattern: string, init?: number) => [...string[]] | nil,\n gmatch: (self: string, pattern: string) => () => [string, ...string[]] | nil,\n gsub: (self: string, pattern: string, replacement: unknown, n?: number) => string,\n\n trim: (self: string) => string,\n trimStart: (self: string) => string,\n trimEnd: (self: string) => string,\n startsWith: (self: string, text: string) => boolean,\n endsWith: (self: string, text: string) => boolean,\n includes: (self: string, text: string) => boolean,\n indexOf: (self: string, text: string, start?: number) => number | nil,\n slice: (self: string, start?: number, stop?: number) => string,\n replace: (self: string, text: string, replacement: string) => string,\n replaceAll: (self: string, text: string, replacement: string) => string,\n padStart: (self: string, length: number, padding?: string) => string,\n padEnd: (self: string, length: number, padding?: string) => string,\n },\n}\n\n-- An array's methods. Lua gives an array no metatable: the compiler lowers\n-- each call to a plain function, so they work on any array, one a Lua\n-- library made included.\n--\n-- Indices are Lua's: the first element is 1, and `indexOf` / `findIndex`\n-- answer `nil` rather than JavaScript's -1. `sort` takes Lua's comparator\n-- (true when `a` comes first). `push`, `pop`, `shift`, `unshift`,\n-- `sort` and `reverse` change the array; everything else returns a new one.\n-- A `filter` whose test is a guard \u2014 `v is S`, or `v => v ~= nil` \u2014\n-- answers an array of what it let through.\ndeclare metatable<T> T[]: {\n __index: {\n find: (self: T[], test: (value: T, index: number) => boolean) => T | nil,\n findIndex: (self: T[], test: (value: T, index: number) => boolean) => number | nil,\n filter: (<S extends T>(self: T[], test: (value: T, index: number) => value is S) => S[])\n & ((self: T[], test: (value: T, index: number) => boolean) => T[]),\n map: <U>(self: T[], transform: (value: T, index: number) => U) => U[],\n forEach: (self: T[], visit: (value: T, index: number) => nil) => nil,\n some: (self: T[], test: (value: T, index: number) => boolean) => boolean,\n every: (self: T[], test: (value: T, index: number) => boolean) => boolean,\n reduce: <U>(self: T[], step: (total: U, value: T, index: number) => U, initial: U) => U,\n includes: (self: T[], value: T) => boolean,\n indexOf: (self: T[], value: T, start?: number) => number | nil,\n join: (self: T[], separator?: string) => string,\n concat: (self: T[], ...others: T[][]) => T[],\n slice: (self: T[], start?: number, stop?: number) => T[],\n flat: (self: T[]) => T[],\n reverse: (self: T[]) => T[],\n sort: (self: T[], compare?: (a: T, b: T) => boolean) => T[],\n push: (self: T[], ...args: T[]) => number,\n pop: (self: T[]) => T | nil,\n shift: (self: T[]) => T | nil,\n unshift: (self: T[], ...args: T[]) => number,\n },\n}\n\n-- A table's methods. Unlike JavaScript's `Object.keys`, they answer a\n-- tuple, in the order the table's type wrote its members:\n--\n-- const point = { x: 1, y: \"up\" }\n-- point:keys() -- [\"x\", \"y\"]\n-- point:values() -- [number, string]\n-- point:entries() -- [[\"x\", number], [\"y\", string]]\n--\n-- A Lua table has no order of its own, so the compiler hands its runtime the\n-- keys as the type lists them. An optional member keeps its place, holding\n-- `nil` when it is missing; an indexer's keys follow the named ones. A\n-- member of the table's own with one of these names is what a call reaches,\n-- and a class instance, which has a metatable of its own, has none of them.\n--\n-- The rest are JavaScript's `Object` functions, written as methods of the\n-- table they take first:\n--\n-- point:hasOwn(\"x\") -- Object.hasOwn(point, \"x\")\n-- point:assign({ z: 3 }) -- Object.assign(point, { z: 3 })\n-- point:freeze() -- Object.freeze(point)\n--\n-- `hasOwn` asks the table itself, not what its metatable's `__index`\n-- lends it. `assign` copies each source's members onto the table, later ones\n-- over earlier ones, skipping a `nil` source, and answers the table. `freeze`\n-- is Luau's `table.freeze`; under Lua 5.1, which cannot freeze a table, the\n-- table is answered as it is and `isFrozen` is false.\ndeclare metatable<T extends {}> T: {\n __index: {\n keys: (self: T) => ObjectKeys<T>,\n values: (self: T) => ObjectValues<T>,\n entries: (self: T) => ObjectEntries<T>,\n\n hasOwn: (self: T, key: unknown) => boolean,\n hasOwnProperty: (self: T, key: unknown) => boolean,\n assign: (<U>(self: T, source: U) => T & U)\n & (<U, V>(self: T, a: U, b: V) => T & U & V)\n & (<U, V, W>(self: T, a: U, b: V, c: W) => T & U & V & W)\n -- Generic like the rest: a plain signature would be tried first.\n & (<S extends {}>(self: T, ...sources: S[]) => T),\n freeze: (self: T) => Readonly<T>,\n isFrozen: (self: T) => boolean,\n },\n}\n";
1605
1611
 
1606
1612
  interface ProjectHost {
1607
1613
  /** A file's text, or `undefined` when there is no such file. */
@@ -1722,6 +1728,10 @@ declare function resolveTypeLibraries(config: TiluaConfig, host?: ProjectHost):
1722
1728
  * },
1723
1729
  * }
1724
1730
  * export default plugin
1731
+ *
1732
+ * What a plugin runs to decide and to write — `luauString`, `isInstanceOf`,
1733
+ * `returnsTuple`, ... — is exported beside this contract (see `luau.ts` and
1734
+ * `loweringHelpers.ts`), so no plugin keeps a copy.
1725
1735
  */
1726
1736
 
1727
1737
  interface LoweringPlugin {
@@ -1865,6 +1875,66 @@ declare function sourceMapTypes(text: string, path: string, options: SourceMapOp
1865
1875
  problem?: string;
1866
1876
  };
1867
1877
 
1878
+ /**
1879
+ * Writing Luau source as text: what a name may be and how a string is quoted.
1880
+ *
1881
+ * The compiler emits Luau, a lowering plugin hands back Luau expressions, and
1882
+ * a server filling placeholders into a bundle writes Luau strings. Each needs
1883
+ * the same few rules, and they live here so none of them keeps its own copy.
1884
+ * Nothing here parses or runs Luau.
1885
+ */
1886
+ /** Luau's reserved words. tilua reserves most of them too — `local` is the
1887
+ * exception, so a tilua name can still be one of these. */
1888
+ declare const LUAU_KEYWORDS: ReadonlySet<string>;
1889
+ /** Is `name` shaped like a name — a letter or `_`, then letters, digits and
1890
+ * `_`? tilua's and Luau's names are both this shape; whether it is also a
1891
+ * keyword is another question (`isLuauName`). */
1892
+ declare function isIdentifier(name: string): boolean;
1893
+ /** Can `name` be written bare in Luau — as a variable, `t.name` or `{ name = v }`? */
1894
+ declare function isLuauName(name: string): boolean;
1895
+ /** `text` as the inside of a double-quoted Luau string, without the quotes:
1896
+ * for splicing into a `"..."` that is already written.
1897
+ *
1898
+ * Every control character is escaped, as `\n` where Luau has a name for it and
1899
+ * as three decimal digits otherwise — always three, so a digit that follows
1900
+ * (`"\1" .. "2"`) is never read as part of the escape. Not `JSON.stringify`:
1901
+ * its `\u0001` is not a Luau escape. Anything else, `é` or `한` included, is
1902
+ * written as it is; Luau source is UTF-8. */
1903
+ declare function escapeLuauString(text: string): string;
1904
+ /** `text` as a double-quoted Luau string literal: `"a\nb"`. */
1905
+ declare function luauString(text: string): string;
1906
+
1907
+ /**
1908
+ * Questions a lowering plugin asks of a type, answered once here.
1909
+ *
1910
+ * A plugin decides how to lower a call from the receiver's or an argument's
1911
+ * type (see `LoweringPlugin`). The same few questions come up in every one —
1912
+ * is it a function, is it an instance of this class, what does this method
1913
+ * return — and a plugin imports these rather than walking the type model
1914
+ * itself:
1915
+ *
1916
+ * import { isInstanceOf } from "@tilua/parser"
1917
+ *
1918
+ * Each looks through a union with `nil` (`Part | nil`): whether the value may
1919
+ * be missing is a check the analyzer asked for elsewhere, not a reason to
1920
+ * lower differently.
1921
+ */
1922
+
1923
+ /** The members of `type` that are not `nil`: `[A, B]` for `A | B | nil`,
1924
+ * `[T]` for any other `T`, and `[]` for `undefined` or `nil` alone. */
1925
+ declare function withoutNil(type: Type | undefined): Type[];
1926
+ /** A function, or an overloaded one (an intersection of functions). */
1927
+ declare function isFunctionType(type: Type | undefined): boolean;
1928
+ /** An instance of `className` or of a class extending it: a `Part` is an
1929
+ * instance of `BasePart` and of `Instance`. */
1930
+ declare function isInstanceOf(type: Type | undefined, className: string): boolean;
1931
+ /** Has every one of `names` as a member — a structural check, for a type
1932
+ * known by its shape rather than its class. */
1933
+ declare function hasMembers(type: Type | undefined, names: readonly string[]): boolean;
1934
+ /** Does every signature of `receiver`'s `method` return a tuple — several
1935
+ * values, as tilua has them in one array? False when the method is missing. */
1936
+ declare function returnsTuple(receiver: Type | undefined, method: string): boolean;
1937
+
1868
1938
  declare const tilua: {
1869
1939
  readonly tokenize: typeof tokenize;
1870
1940
  readonly parseTokens: typeof parseTokens;
@@ -1878,4 +1948,4 @@ declare const tilua: {
1878
1948
  readonly analyzeTypes: typeof analyzeTypes;
1879
1949
  };
1880
1950
 
1881
- export { type AnalyzeTypesOptions, type AnyType, type ArgumentInfo, type ArrayExpression, type ArrayPattern, type ArrayPatternElement, type ArrayType, type ArrayTypeNode, type AsConstExpression, type AssignmentStatement, type BaseNode, type BaseToken, type BinaryExpression, BinaryOperators, type Binding, type BindingId, type BindingKind, type BindingTarget, type Block, type BooleanLiteral, type BreakStatement, type BuildTarget, CONFIG_FILE_NAMES, type CallExpression, type CallLowering, type CallSite, type CallStatement, type ClassAccessibility, type ClassAccessor, type ClassConstructor, type ClassDeclaration, type ClassExpression, type ClassField, type ClassInfo, type ClassLike, type ClassMember, type ClassMethod, type CompoundAssignmentStatement, type ConditionalType, type ConditionalTypeNode, type ConfigLookup, type ConfigProblem, type ContinueStatement, type DeclareClassStatement, type DeclareMetatableStatement, type DeclareStatement, type DifferenceType, type DifferenceTypeNode, type Directive, type DirectiveKind, type DirectiveOutcome, type Directives, type DoStatement, type EOFToken, type ErrorExpression, type ErrorStatement, type ExportAllStatement, type ExportDefaultStatement, type ExportNamedStatement, type ExportSpecifier, type ExportStatement, type ExportTypeAliasStatement, type ExportedType, type Expression, type ExpressionStatement, type FunctionBody, type FunctionDeclaration, type FunctionDeclarationStatement, type FunctionExpression, type FunctionName, type FunctionParam, type FunctionParameter, type FunctionSignature, type FunctionType, type FunctionTypeNode, type FunctionTypeParameter, type GenericForStatement, type GenericRefType, type GenericTypeParameter, type GlobalCall, type GlobalValue, type Identifier, type IdentifierPattern, type IdentifierToken, type IfClause, type IfElseExpression, type IfStatement, type ImportSpecifier, type ImportStatement, type IndexExpression, type IndexedAccessType, type IndexedAccessTypeNode, type InferType, type InferTypeNode, type InterpolatedStringExpression, type InterpolatedStringPart, type InterpolatedStringPart_Expression, type InterpolatedStringPart_String, type InterpolatedStringToken, type IntersectionType, type IntersectionTypeNode, type KeyofType, type KeyofTypeNode, type KeywordToken, Keywords, LANGUAGE_GLOBALS, LexError, type LiteralToken, type LiteralType, type LoweringModule, type LoweringPlugin, type MappedType, type MappedTypeNode, type MemberExpression, type MethodCall, type MethodCallExpression, type MethodLowering, type ModuleExports, type NeverType, type NilLiteral, type Node, type NumberLiteral, type NumericForStatement, type ObjectPattern, type ObjectPatternProperty, type ObjectProperty, type ObjectType, type OperatorToken, Operators, PRELUDE_SOURCE, type ParenthesizedExpression, type ParenthesizedTypeNode, ParseError, type ParserOptions, type PrimitiveName, type PrimitiveType, type Program, type ProjectHost, type PunctuatorToken, Punctuators, type RecoverResult, type RepeatStatement, type ReturnStatement, type SatisfiesExpression, type ScopeAnalysis, type ScopeDiagnostic, type SourceComment, type SourceMapNode, type SourceMapOptions, type SourceMapTypes, type SpreadElement, type Statement, type StringLiteral, type SuperExpression, type TableExpression, type TableField, type TableTypeNode, type TableTypeProperty, type TemplateLiteralType, type TemplateLiteralTypeNode, type TiluaConfig, type Token, type TokenizeOptions, type TupleType, type TupleTypeNode, type Type, type TypeAliasStatement, type TypeAnalysis, type TypeAssertionExpression, type TypeDiagnostic, type TypeLibraries, type TypeLiteralBoolean, type TypeLiteralNumber, type TypeLiteralString, type TypeNode, type TypeOrigin, type TypeParamType, type TypePredicate, type TypePredicateNode, type TypeReference, type TypedIdentifier, type TypeofTypeNode, UNUSED_EXPECT_ERROR, type UnaryExpression, UnaryOperators, type Unification, type UnionType, type UnionTypeNode, type UnknownType, type VariableDeclaration, type WhileStatement, aliasNameOf, analyzeScopes, analyzeTypes, anyType, applyDirectives, arrayOf, booleanType, bufferType, containsTypeParam, declaredUnknownType, tilua as default, difference, directivesOf, equalTypes, falsyType, findConfig, fn, formatType, getBinding, intersection, isAssignable, isClassType, isGlobal, isPossiblyFalsy, isPossiblyTruthy, isUnassignedGlobal, literal, loadConfig, matchInfer, moduleCandidates, moduleExports, narrowExclude, narrowFalsy, narrowTo, narrowTruthy, neverType, nilType, nodeHost, numberType, objectType, optional, overlaps, parse, parseExpressionFromSource, parseTokens, parseWithRecovery, primitive, readDirectives, resolveModulePath, resolveTypeLibraries, setAliasExpander, setDeferredBound, sourceMapTypes, stringType, stripJsonComments, substitute, templateMatches, threadType, tilua, tokenize, tuple, tupleMembers, typeParam, unify, union, unknownType, widen, withAliasName, withoutAliasName };
1951
+ export { type AnalyzeTypesOptions, type AnyType, type ArgumentInfo, type ArrayExpression, type ArrayPattern, type ArrayPatternElement, type ArrayType, type ArrayTypeNode, type AsConstExpression, type AssignmentStatement, type BaseNode, type BaseToken, type BinaryExpression, BinaryOperators, type Binding, type BindingId, type BindingKind, type BindingTarget, type Block, type BooleanLiteral, type BreakStatement, type BuildTarget, CONFIG_FILE_NAMES, type CallExpression, type CallLowering, type CallSite, type CallStatement, type ClassAccessibility, type ClassAccessor, type ClassConstructor, type ClassDeclaration, type ClassExpression, type ClassField, type ClassInfo, type ClassLike, type ClassMember, type ClassMethod, type CompoundAssignmentStatement, type ConditionalType, type ConditionalTypeNode, type ConfigLookup, type ConfigProblem, type ContinueStatement, type DeclareClassStatement, type DeclareMetatableStatement, type DeclareStatement, type DifferenceType, type DifferenceTypeNode, type Directive, type DirectiveKind, type DirectiveOutcome, type Directives, type DoStatement, type EOFToken, type ErrorExpression, type ErrorStatement, type ExportAllStatement, type ExportDefaultStatement, type ExportNamedStatement, type ExportSpecifier, type ExportStatement, type ExportTypeAliasStatement, type ExportedType, type Expression, type ExpressionStatement, type FunctionBody, type FunctionDeclaration, type FunctionDeclarationStatement, type FunctionExpression, type FunctionName, type FunctionParam, type FunctionParameter, type FunctionSignature, type FunctionType, type FunctionTypeNode, type FunctionTypeParameter, type GenericForStatement, type GenericRefType, type GenericTypeParameter, type GlobalCall, type GlobalValue, type Identifier, type IdentifierPattern, type IdentifierToken, type IfClause, type IfElseExpression, type IfStatement, type ImportSpecifier, type ImportStatement, type IndexExpression, type IndexedAccessType, type IndexedAccessTypeNode, type InferType, type InferTypeNode, type InterpolatedStringExpression, type InterpolatedStringPart, type InterpolatedStringPart_Expression, type InterpolatedStringPart_String, type InterpolatedStringToken, type IntersectionType, type IntersectionTypeNode, type KeyofType, type KeyofTypeNode, type KeywordToken, Keywords, LANGUAGE_GLOBALS, LUAU_KEYWORDS, LexError, type LiteralToken, type LiteralType, type LoweringModule, type LoweringPlugin, type MappedType, type MappedTypeNode, type MemberExpression, type MethodCall, type MethodCallExpression, type MethodLowering, type ModuleExports, type NeverType, type NilLiteral, type Node, type NumberLiteral, type NumericForStatement, type ObjectPattern, type ObjectPatternProperty, type ObjectProperty, type ObjectType, type OperatorToken, Operators, PRELUDE_SOURCE, type ParenthesizedExpression, type ParenthesizedTypeNode, ParseError, type ParserOptions, type PrimitiveName, type PrimitiveType, type Program, type ProjectHost, type PunctuatorToken, Punctuators, type RecoverResult, type RepeatStatement, type ReturnStatement, type SatisfiesExpression, type ScopeAnalysis, type ScopeDiagnostic, type SourceComment, type SourceMapNode, type SourceMapOptions, type SourceMapTypes, type SpreadElement, type Statement, type StringLiteral, type SuperExpression, type TableExpression, type TableField, type TableTypeNode, type TableTypeProperty, type TemplateLiteralType, type TemplateLiteralTypeNode, type TiluaConfig, type Token, type TokenizeOptions, type TupleType, type TupleTypeNode, type Type, type TypeAliasStatement, type TypeAnalysis, type TypeAssertionExpression, type TypeDiagnostic, type TypeLibraries, type TypeLiteralBoolean, type TypeLiteralNumber, type TypeLiteralString, type TypeNode, type TypeOrigin, type TypeParamType, type TypePredicate, type TypePredicateNode, type TypeReference, type TypedIdentifier, type TypeofTypeNode, UNUSED_EXPECT_ERROR, type UnaryExpression, UnaryOperators, type Unification, type UnionType, type UnionTypeNode, type UnknownType, type VariableDeclaration, type WhileStatement, aliasNameOf, analyzeScopes, analyzeTypes, anyType, applyDirectives, arrayOf, booleanType, bufferType, containsTypeParam, declaredUnknownType, tilua as default, difference, directivesOf, equalTypes, escapeLuauString, falsyType, findConfig, fn, formatType, getBinding, hasMembers, intersection, isAssignable, isClassType, isFunctionType, isGlobal, isIdentifier, isInstanceOf, isLuauName, isPossiblyFalsy, isPossiblyTruthy, isUnassignedGlobal, literal, loadConfig, luauString, matchInfer, moduleCandidates, moduleExports, narrowExclude, narrowFalsy, narrowTo, narrowTruthy, neverType, nilType, nodeHost, numberType, objectType, optional, overlaps, parse, parseExpressionFromSource, parseTokens, parseWithRecovery, primitive, readDirectives, resolveModulePath, resolveTypeLibraries, returnsTuple, setAliasExpander, setDeferredBound, sourceMapTypes, stringType, stripJsonComments, substitute, templateMatches, threadType, tilua, tokenize, tuple, tupleMembers, typeParam, unify, union, unknownType, widen, withAliasName, withoutAliasName, withoutNil };
package/dist/index.js CHANGED
@@ -603,7 +603,7 @@ function bindThis(func, at) {
603
603
  func.isMethod = true;
604
604
  }
605
605
  function bindThisParam(params, at) {
606
- params.unshift({ type: "FunctionParameter", name: "this", ...spanFrom(at, at) });
606
+ params.unshift({ type: "FunctionParameter", name: "this", implicit: true, ...spanFrom(at, at) });
607
607
  }
608
608
  var ParseError = class extends Error {
609
609
  constructor(message, line, column) {
@@ -1660,7 +1660,7 @@ var Parser = class {
1660
1660
  };
1661
1661
  }
1662
1662
  if (isMethod) {
1663
- func.params.unshift({ type: "FunctionParameter", name: "self", ...spanFrom(target, target) });
1663
+ func.params.unshift({ type: "FunctionParameter", name: "self", implicit: true, ...spanFrom(target, target) });
1664
1664
  func.isMethod = true;
1665
1665
  }
1666
1666
  return {
@@ -1854,47 +1854,7 @@ var Parser = class {
1854
1854
  const isStatic = modifiers.has("static");
1855
1855
  if (this.checkKeyword("function")) {
1856
1856
  this.advance();
1857
- const memberName = this.parseIdentifier();
1858
- if (modifiers.has("abstract")) {
1859
- const head = this.parseFunctionHead();
1860
- const func = {
1861
- type: "FunctionBody",
1862
- generics: head.generics,
1863
- params: head.params,
1864
- hasVarargs: head.hasVarargs,
1865
- returnType: head.returnType,
1866
- predicate: head.predicate,
1867
- body: { type: "Block", statements: [], ...spanFrom(head.start, this.previous()) },
1868
- ...spanFrom(head.start, this.previous())
1869
- };
1870
- if (!isStatic) bindThis(func, start);
1871
- if (!head.returnType) this.problem("An abstract method has no body to infer from: write its return type");
1872
- if (this.checkPunctuator("{")) this.problem("An abstract method has no body");
1873
- return { type: "ClassMethod", name: memberName, isStatic, func, isAbstract: true, ...spanFrom(start, this.previous()) };
1874
- }
1875
- const signatures = [];
1876
- let written = memberName;
1877
- while (true) {
1878
- const head = this.parseFunctionHead();
1879
- if (this.isClassOverloadContinuation(memberName.name, isStatic)) {
1880
- if (!isStatic) bindThisParam(head.params, start);
1881
- signatures.push({ ...this.headToSignature(head), name: written });
1882
- if (isStatic) this.advance();
1883
- this.expectKeyword("function");
1884
- written = this.parseIdentifier();
1885
- continue;
1886
- }
1887
- const func = this.headToBody(head, start);
1888
- if (!isStatic) bindThis(func, start);
1889
- return {
1890
- type: "ClassMethod",
1891
- name: memberName,
1892
- isStatic,
1893
- func,
1894
- signatures: signatures.length ? signatures : void 0,
1895
- ...spanFrom(start, this.previous())
1896
- };
1897
- }
1857
+ return this.parseClassMethod(start, modifiers);
1898
1858
  }
1899
1859
  if (!isStatic && this.checkIdentifierValue("constructor") && this.punctuatorAt(1, "(")) {
1900
1860
  this.advance();
@@ -1904,6 +1864,9 @@ var Parser = class {
1904
1864
  bindThis(func, start);
1905
1865
  return { type: "ClassConstructor", func, ...spanFrom(start, this.previous()) };
1906
1866
  }
1867
+ if (this.startsMethodShorthand(0)) {
1868
+ return this.parseClassMethod(start, modifiers);
1869
+ }
1907
1870
  if ((this.checkIdentifierValue("get") || this.checkIdentifierValue("set")) && this.peek(1).type === "Identifier" && this.punctuatorAt(2, "(")) {
1908
1871
  const kind = this.advance().value;
1909
1872
  const memberName = this.parseIdentifier();
@@ -1933,25 +1896,90 @@ var Parser = class {
1933
1896
  return { type: "ClassField", name: memberName, isStatic, typeAnnotation, init, ...spanFrom(start, this.previous()) };
1934
1897
  }
1935
1898
  if (this.recover) {
1936
- this.softError("Expected a class member: a field, 'function', 'constructor', 'get' or 'set'");
1899
+ this.softError("Expected a class member: a field, a method, 'constructor', 'get' or 'set'");
1937
1900
  this.advance();
1938
1901
  return void 0;
1939
1902
  }
1940
- this.error("Expected a class member: a field, 'function', 'constructor', 'get' or 'set'");
1903
+ this.error("Expected a class member: a field, a method, 'constructor', 'get' or 'set'");
1904
+ }
1905
+ /** A name at `offset` opening a method without `function`: `name(` or
1906
+ * `name<T>(`. A field's name is followed by `:` or `=` instead. */
1907
+ startsMethodShorthand(offset) {
1908
+ if (this.peek(offset).type !== "Identifier") return false;
1909
+ const next = this.peek(offset + 1);
1910
+ return (next.type === "Punctuator" || next.type === "Operator") && (next.value === "(" || next.value === "<");
1911
+ }
1912
+ /** A method, from its name on: `function` (if written) and the modifiers
1913
+ * are behind. */
1914
+ parseClassMethod(start, modifiers) {
1915
+ const isStatic = modifiers.has("static");
1916
+ const memberName = this.parseIdentifier();
1917
+ if (modifiers.has("abstract")) {
1918
+ const head = this.parseFunctionHead();
1919
+ const func = {
1920
+ type: "FunctionBody",
1921
+ generics: head.generics,
1922
+ params: head.params,
1923
+ hasVarargs: head.hasVarargs,
1924
+ returnType: head.returnType,
1925
+ predicate: head.predicate,
1926
+ body: { type: "Block", statements: [], ...spanFrom(head.start, this.previous()) },
1927
+ ...spanFrom(head.start, this.previous())
1928
+ };
1929
+ if (!isStatic) bindThis(func, start);
1930
+ if (!head.returnType) this.problem("An abstract method has no body to infer from: write its return type");
1931
+ if (this.checkPunctuator("{")) this.problem("An abstract method has no body");
1932
+ return { type: "ClassMethod", name: memberName, isStatic, func, isAbstract: true, ...spanFrom(start, this.previous()) };
1933
+ }
1934
+ const signatures = [];
1935
+ let written = memberName;
1936
+ while (true) {
1937
+ const head = this.parseFunctionHead();
1938
+ const skip = this.classOverloadContinuation(memberName.name, isStatic);
1939
+ if (skip !== void 0) {
1940
+ if (!isStatic) bindThisParam(head.params, start);
1941
+ signatures.push({ ...this.headToSignature(head), name: written });
1942
+ for (let i = 0; i < skip; i++) this.advance();
1943
+ written = this.parseIdentifier();
1944
+ continue;
1945
+ }
1946
+ const func = this.headToBody(head, start);
1947
+ if (!isStatic) bindThis(func, start);
1948
+ return {
1949
+ type: "ClassMethod",
1950
+ name: memberName,
1951
+ isStatic,
1952
+ func,
1953
+ signatures: signatures.length ? signatures : void 0,
1954
+ ...spanFrom(start, this.previous())
1955
+ };
1956
+ }
1941
1957
  }
1942
- /** Give a class method its `this`: a real first parameter, the way
1943
- * `function T:m()` gets a real `self`. Every later pass — scopes, types,
1944
- * arity, lowering — then sees an ordinary parameter and needs to know
1945
- * nothing about classes. */
1946
1958
  /** After a bodyless head inside a class body, does another declaration of
1947
- * the same member follow? Then the head was an overload signature. */
1948
- isClassOverloadContinuation(name, isStatic) {
1949
- const offset = isStatic ? 1 : 0;
1950
- if (isStatic && !this.checkIdentifierValue("static")) return false;
1959
+ * the same member follow? Then the head was an overload signature, and
1960
+ * this is how many tokens stand before the next one's name: a `;` that
1961
+ * ends the head, as TypeScript writes it, the modifiers, and `function`
1962
+ * when it is written. `undefined` when no overload follows. Each head may
1963
+ * be written either way, with `function` or without. */
1964
+ classOverloadContinuation(name, isStatic) {
1965
+ let offset = 0;
1966
+ if (this.punctuatorAt(0, ";")) offset++;
1967
+ let sawStatic = false;
1968
+ while (true) {
1969
+ const t = this.peek(offset);
1970
+ const word = t.type === "Identifier" ? t.value : void 0;
1971
+ if (word === void 0 || !CLASS_MODIFIERS.has(word) || this.startsMethodShorthand(offset)) break;
1972
+ if (word === "static") sawStatic = true;
1973
+ offset++;
1974
+ }
1975
+ if (sawStatic !== isStatic) return void 0;
1951
1976
  const keyword = this.peek(offset);
1952
- if (!(keyword.type === "Keyword" && keyword.value === "function")) return false;
1953
- const named = this.peek(offset + 1);
1954
- return named.type === "Identifier" && named.value === name;
1977
+ const hasKeyword = keyword.type === "Keyword" && keyword.value === "function";
1978
+ if (hasKeyword) offset++;
1979
+ const named = this.peek(offset);
1980
+ if (!(named.type === "Identifier" && named.value === name)) return void 0;
1981
+ if (!hasKeyword && !this.startsMethodShorthand(offset)) return void 0;
1982
+ return offset;
1955
1983
  }
1956
1984
  operatorAt(ahead, value) {
1957
1985
  const token = this.peek(ahead);
@@ -4571,11 +4599,34 @@ declare metatable<T> T[]: {
4571
4599
  -- \`nil\` when it is missing; an indexer's keys follow the named ones. A
4572
4600
  -- member of the table's own with one of these names is what a call reaches,
4573
4601
  -- and a class instance, which has a metatable of its own, has none of them.
4602
+ --
4603
+ -- The rest are JavaScript's \`Object\` functions, written as methods of the
4604
+ -- table they take first:
4605
+ --
4606
+ -- point:hasOwn("x") -- Object.hasOwn(point, "x")
4607
+ -- point:assign({ z: 3 }) -- Object.assign(point, { z: 3 })
4608
+ -- point:freeze() -- Object.freeze(point)
4609
+ --
4610
+ -- \`hasOwn\` asks the table itself, not what its metatable's \`__index\`
4611
+ -- lends it. \`assign\` copies each source's members onto the table, later ones
4612
+ -- over earlier ones, skipping a \`nil\` source, and answers the table. \`freeze\`
4613
+ -- is Luau's \`table.freeze\`; under Lua 5.1, which cannot freeze a table, the
4614
+ -- table is answered as it is and \`isFrozen\` is false.
4574
4615
  declare metatable<T extends {}> T: {
4575
4616
  __index: {
4576
4617
  keys: (self: T) => ObjectKeys<T>,
4577
4618
  values: (self: T) => ObjectValues<T>,
4578
4619
  entries: (self: T) => ObjectEntries<T>,
4620
+
4621
+ hasOwn: (self: T, key: unknown) => boolean,
4622
+ hasOwnProperty: (self: T, key: unknown) => boolean,
4623
+ assign: (<U>(self: T, source: U) => T & U)
4624
+ & (<U, V>(self: T, a: U, b: V) => T & U & V)
4625
+ & (<U, V, W>(self: T, a: U, b: V, c: W) => T & U & V & W)
4626
+ -- Generic like the rest: a plain signature would be tried first.
4627
+ & (<S extends {}>(self: T, ...sources: S[]) => T),
4628
+ freeze: (self: T) => Readonly<T>,
4629
+ isFrozen: (self: T) => boolean,
4579
4630
  },
4580
4631
  }
4581
4632
  `;
@@ -11761,7 +11812,53 @@ function aliasTargets(config, specifier) {
11761
11812
 
11762
11813
  // src/project/sourcemap.ts
11763
11814
  import { dirname as dirname4, extname, resolve as resolve4 } from "path";
11815
+
11816
+ // src/luau.ts
11817
+ var LUAU_KEYWORDS = /* @__PURE__ */ new Set([
11818
+ "and",
11819
+ "break",
11820
+ "do",
11821
+ "else",
11822
+ "elseif",
11823
+ "end",
11824
+ "false",
11825
+ "for",
11826
+ "function",
11827
+ "if",
11828
+ "in",
11829
+ "local",
11830
+ "nil",
11831
+ "not",
11832
+ "or",
11833
+ "repeat",
11834
+ "return",
11835
+ "then",
11836
+ "true",
11837
+ "until",
11838
+ "while"
11839
+ ]);
11764
11840
  var IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
11841
+ function isIdentifier(name) {
11842
+ return IDENTIFIER.test(name);
11843
+ }
11844
+ function isLuauName(name) {
11845
+ return IDENTIFIER.test(name) && !LUAU_KEYWORDS.has(name);
11846
+ }
11847
+ var NAMED_ESCAPES = {
11848
+ "\\": "\\\\",
11849
+ '"': '\\"',
11850
+ "\n": "\\n",
11851
+ "\r": "\\r",
11852
+ " ": "\\t"
11853
+ };
11854
+ function escapeLuauString(text) {
11855
+ return text.replace(/[\\"\x00-\x1f\x7f]/g, (c) => NAMED_ESCAPES[c] ?? `\\${c.charCodeAt(0).toString().padStart(3, "0")}`);
11856
+ }
11857
+ function luauString(text) {
11858
+ return `"${escapeLuauString(text)}"`;
11859
+ }
11860
+
11861
+ // src/project/sourcemap.ts
11765
11862
  var INSTANCE_MEMBERS = /* @__PURE__ */ new Set(["Name", "ClassName", "Parent", "Archivable"]);
11766
11863
  var SCRIPT_EXTENSIONS = /* @__PURE__ */ new Set([".tilua", ".luau", ".lua"]);
11767
11864
  function sourceMapTypes(text, path, options) {
@@ -11788,7 +11885,7 @@ function sourceMapTypes(text, path, options) {
11788
11885
  const alias = aliasFor(segments);
11789
11886
  aliasOfNode.set(node, alias);
11790
11887
  for (const filePath of node.filePaths ?? []) aliasOfFile.set(fileKey(resolve4(directory, filePath)), alias);
11791
- const className = IDENTIFIER.test(node.className) && options.classes.has(node.className) ? node.className : "Instance";
11888
+ const className = isIdentifier(node.className) && options.classes.has(node.className) ? node.className : "Instance";
11792
11889
  const taken = options.membersOf?.(className) ?? INSTANCE_MEMBERS;
11793
11890
  const members = [];
11794
11891
  if (parent) members.push(`Parent: ${parent}`);
@@ -11797,7 +11894,7 @@ function sourceMapTypes(text, path, options) {
11797
11894
  if (!isNode(child)) continue;
11798
11895
  const childAlias = visit(child, [...segments, child.name], alias);
11799
11896
  const service = child.name === child.className && options.classes.has(child.className);
11800
- if (!IDENTIFIER.test(child.name) || taken.has(child.name) && !service || named.has(child.name)) continue;
11897
+ if (!isIdentifier(child.name) || taken.has(child.name) && !service || named.has(child.name)) continue;
11801
11898
  named.add(child.name);
11802
11899
  members.push(`${child.name}: ${childAlias}`);
11803
11900
  }
@@ -11839,6 +11936,34 @@ function fileKey(path) {
11839
11936
  return process.platform === "win32" ? normalized.toLowerCase() : normalized;
11840
11937
  }
11841
11938
 
11939
+ // src/loweringHelpers.ts
11940
+ function withoutNil2(type) {
11941
+ if (!type) return [];
11942
+ const members = type.kind === "union" ? type.types : [type];
11943
+ return members.filter((m) => !(m.kind === "primitive" && m.name === "nil"));
11944
+ }
11945
+ function isFunctionType(type) {
11946
+ const members = withoutNil2(type);
11947
+ return members.length > 0 && members.every((m) => m.kind === "function" || m.kind === "intersection" && m.types.every(isFunctionType));
11948
+ }
11949
+ function everyObject(type, test) {
11950
+ const members = withoutNil2(type);
11951
+ return members.length > 0 && members.every((m) => m.kind === "object" && test(m));
11952
+ }
11953
+ function isInstanceOf(type, className) {
11954
+ return everyObject(type, (m) => m.class !== void 0 && m.class.ancestors.includes(className));
11955
+ }
11956
+ function hasMembers(type, names) {
11957
+ return everyObject(type, (m) => names.every((name) => m.properties.has(name)));
11958
+ }
11959
+ function returnsTuple(receiver, method) {
11960
+ return everyObject(receiver, (m) => {
11961
+ const found = m.properties.get(method)?.type;
11962
+ const signatures = !found ? [] : found.kind === "intersection" ? found.types : [found];
11963
+ return signatures.length > 0 && signatures.every((f) => f.kind === "function" && f.returns.kind === "tuple");
11964
+ });
11965
+ }
11966
+
11842
11967
  // src/index.ts
11843
11968
  var tilua = {
11844
11969
  tokenize,
@@ -11858,6 +11983,7 @@ export {
11858
11983
  CONFIG_FILE_NAMES,
11859
11984
  Keywords,
11860
11985
  LANGUAGE_GLOBALS,
11986
+ LUAU_KEYWORDS,
11861
11987
  LexError,
11862
11988
  Operators,
11863
11989
  PRELUDE_SOURCE,
@@ -11879,20 +12005,27 @@ export {
11879
12005
  difference,
11880
12006
  directivesOf,
11881
12007
  equalTypes,
12008
+ escapeLuauString,
11882
12009
  falsyType,
11883
12010
  findConfig,
11884
12011
  fn,
11885
12012
  formatType,
11886
12013
  getBinding,
12014
+ hasMembers,
11887
12015
  intersection,
11888
12016
  isAssignable,
11889
12017
  isClassType,
12018
+ isFunctionType,
11890
12019
  isGlobal,
12020
+ isIdentifier,
12021
+ isInstanceOf,
12022
+ isLuauName,
11891
12023
  isPossiblyFalsy,
11892
12024
  isPossiblyTruthy,
11893
12025
  isUnassignedGlobal,
11894
12026
  literal,
11895
12027
  loadConfig,
12028
+ luauString,
11896
12029
  matchInfer,
11897
12030
  moduleCandidates,
11898
12031
  moduleExports,
@@ -11915,6 +12048,7 @@ export {
11915
12048
  readDirectives,
11916
12049
  resolveModulePath,
11917
12050
  resolveTypeLibraries,
12051
+ returnsTuple,
11918
12052
  setAliasExpander,
11919
12053
  setDeferredBound,
11920
12054
  sourceMapTypes,
@@ -11933,5 +12067,6 @@ export {
11933
12067
  unknownType,
11934
12068
  widen,
11935
12069
  withAliasName,
11936
- withoutAliasName
12070
+ withoutAliasName,
12071
+ withoutNil2 as withoutNil
11937
12072
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tilua/parser",
3
- "version": "3.0.1",
3
+ "version": "3.1.0",
4
4
  "description": "tilua parser for roblox",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",