@tilua/parser 1.0.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/README.md +702 -0
- package/dist/index.cjs +10324 -0
- package/dist/index.d.cts +1675 -0
- package/dist/index.d.ts +1675 -0
- package/dist/index.js +10221 -0
- package/package.json +43 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1675 @@
|
|
|
1
|
+
interface BaseToken {
|
|
2
|
+
line: {
|
|
3
|
+
start: number;
|
|
4
|
+
end: number;
|
|
5
|
+
};
|
|
6
|
+
column: {
|
|
7
|
+
start: number;
|
|
8
|
+
end: number;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
declare const Keywords: readonly ["and", "break", "do", "else", "elseif", "end", "false", "for", "function", "if", "in", "nil", "not", "or", "repeat", "return", "then", "true", "until", "while", "continue", "const", "let", "import", "export", "from", "as"];
|
|
12
|
+
interface KeywordToken extends BaseToken {
|
|
13
|
+
type: "Keyword";
|
|
14
|
+
value: typeof Keywords[number];
|
|
15
|
+
}
|
|
16
|
+
interface IdentifierToken extends BaseToken {
|
|
17
|
+
type: "Identifier";
|
|
18
|
+
value: string;
|
|
19
|
+
}
|
|
20
|
+
type LiteralToken = (BaseToken & {
|
|
21
|
+
type: "Literal";
|
|
22
|
+
kind: "number";
|
|
23
|
+
value: number;
|
|
24
|
+
raw: string;
|
|
25
|
+
}) | (BaseToken & {
|
|
26
|
+
type: "Literal";
|
|
27
|
+
kind: "string";
|
|
28
|
+
value: string;
|
|
29
|
+
raw: string;
|
|
30
|
+
}) | (BaseToken & {
|
|
31
|
+
type: "Literal";
|
|
32
|
+
kind: "nil";
|
|
33
|
+
value: null;
|
|
34
|
+
}) | (BaseToken & {
|
|
35
|
+
type: "Literal";
|
|
36
|
+
kind: "boolean";
|
|
37
|
+
value: boolean;
|
|
38
|
+
});
|
|
39
|
+
declare const Operators: readonly ["+=", "-=", "*=", "/=", "//=", "%=", "^=", "..=", "==", "~=", "<=", ">=", "//", "..", "...", "+", "-", "*", "/", "%", "^", "#", "<", ">", "="];
|
|
40
|
+
interface OperatorToken extends BaseToken {
|
|
41
|
+
type: "Operator";
|
|
42
|
+
value: typeof Operators[number];
|
|
43
|
+
}
|
|
44
|
+
declare const Punctuators: readonly ["::", "(", ")", "{", "}", "[", "]", ";", ":", ",", ".", "?", "=>", "->", "&", "|", "@"];
|
|
45
|
+
interface PunctuatorToken extends BaseToken {
|
|
46
|
+
type: "Punctuator";
|
|
47
|
+
value: typeof Punctuators[number];
|
|
48
|
+
}
|
|
49
|
+
interface InterpolatedStringPart_String {
|
|
50
|
+
kind: "string";
|
|
51
|
+
value: string;
|
|
52
|
+
raw: string;
|
|
53
|
+
}
|
|
54
|
+
interface InterpolatedStringPart_Expression {
|
|
55
|
+
kind: "expression";
|
|
56
|
+
raw: string;
|
|
57
|
+
/** Where `raw` starts in the file, so what is parsed from it can be
|
|
58
|
+
* placed there rather than at the top of an imaginary one. */
|
|
59
|
+
line: number;
|
|
60
|
+
column: number;
|
|
61
|
+
}
|
|
62
|
+
interface InterpolatedStringToken extends BaseToken {
|
|
63
|
+
type: "InterpolatedString";
|
|
64
|
+
parts: (InterpolatedStringPart_String | InterpolatedStringPart_Expression)[];
|
|
65
|
+
}
|
|
66
|
+
interface EOFToken extends BaseToken {
|
|
67
|
+
type: "EOF";
|
|
68
|
+
}
|
|
69
|
+
type Token = KeywordToken | LiteralToken | OperatorToken | PunctuatorToken | IdentifierToken | InterpolatedStringToken | EOFToken;
|
|
70
|
+
declare class LexError extends Error {
|
|
71
|
+
line: number;
|
|
72
|
+
column: number;
|
|
73
|
+
constructor(message: string, line: number, column: number);
|
|
74
|
+
}
|
|
75
|
+
/** A `--` comment: its text after the dashes (a long comment's content), and
|
|
76
|
+
* where it starts and ends. */
|
|
77
|
+
interface SourceComment {
|
|
78
|
+
text: string;
|
|
79
|
+
line: number;
|
|
80
|
+
column: number;
|
|
81
|
+
endLine: number;
|
|
82
|
+
}
|
|
83
|
+
interface TokenizeOptions {
|
|
84
|
+
/** When given, a malformed token is recorded here instead of thrown, and
|
|
85
|
+
* lexing goes on: an unclosed string or comment ends at the end of its
|
|
86
|
+
* line (a long bracket at the end of the source), and a character that
|
|
87
|
+
* starts no token is skipped. An editor mid-keystroke still gets every
|
|
88
|
+
* other token. */
|
|
89
|
+
errors?: LexError[];
|
|
90
|
+
/** When given, every comment is collected here, in order. */
|
|
91
|
+
comments?: SourceComment[];
|
|
92
|
+
}
|
|
93
|
+
declare function tokenize(source: string, options?: TokenizeOptions): Token[];
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Comments that switch checking off, as TypeScript's `// @ts-...` comments do:
|
|
97
|
+
*
|
|
98
|
+
* --@tilua-nocheck no scope or type errors anywhere in this file
|
|
99
|
+
* --@tilua-ignore none on the next line of code
|
|
100
|
+
* --@tilua-expect-error none on the next line of code, and an error if
|
|
101
|
+
* that line has none to suppress
|
|
102
|
+
*
|
|
103
|
+
* A space after `--` is fine, and so is text after the directive (a reason).
|
|
104
|
+
* `nocheck` counts only in the comments before the first line of code, as in
|
|
105
|
+
* TypeScript. Syntax errors are never suppressed: code that does not parse
|
|
106
|
+
* cannot be compiled either way.
|
|
107
|
+
*/
|
|
108
|
+
type DirectiveKind = "nocheck" | "ignore" | "expect-error";
|
|
109
|
+
interface Directive {
|
|
110
|
+
kind: DirectiveKind;
|
|
111
|
+
/** Where the comment starts. */
|
|
112
|
+
line: number;
|
|
113
|
+
column: number;
|
|
114
|
+
/** `ignore` / `expect-error`: the line whose diagnostics it covers — the
|
|
115
|
+
* next line with code on it. */
|
|
116
|
+
target?: number;
|
|
117
|
+
}
|
|
118
|
+
interface Directives {
|
|
119
|
+
/** The file has `--@tilua-nocheck` before its first line of code. */
|
|
120
|
+
nocheck: boolean;
|
|
121
|
+
/** Every directive, in order — a `nocheck` after the code starts included,
|
|
122
|
+
* so a tool can point out that it does nothing. */
|
|
123
|
+
all: Directive[];
|
|
124
|
+
}
|
|
125
|
+
/** The directives in `comments`, placed against `tokens` (both from one
|
|
126
|
+
* `tokenize` of the file). */
|
|
127
|
+
declare function readDirectives(comments: readonly SourceComment[], tokens: readonly Token[]): Directives;
|
|
128
|
+
/** The directives of `source`, for a caller that parsed it some other way. */
|
|
129
|
+
declare function directivesOf(source: string): Directives;
|
|
130
|
+
interface DirectiveOutcome<T> {
|
|
131
|
+
/** The diagnostics no directive suppresses. */
|
|
132
|
+
kept: T[];
|
|
133
|
+
/** `--@tilua-expect-error` comments with nothing to suppress. Each is an
|
|
134
|
+
* error to report: "Unused '@tilua-expect-error' directive". */
|
|
135
|
+
unusedExpectErrors: Directive[];
|
|
136
|
+
}
|
|
137
|
+
/** Filter scope and type diagnostics — never syntax errors — through the
|
|
138
|
+
* file's directives. `lineOf` gives the line a diagnostic starts on. */
|
|
139
|
+
declare function applyDirectives<T>(directives: Directives, diagnostics: readonly T[], lineOf: (diagnostic: T) => number): DirectiveOutcome<T>;
|
|
140
|
+
declare const UNUSED_EXPECT_ERROR = "Unused '@tilua-expect-error' directive";
|
|
141
|
+
|
|
142
|
+
interface BaseNode {
|
|
143
|
+
line: {
|
|
144
|
+
start: number;
|
|
145
|
+
end: number;
|
|
146
|
+
};
|
|
147
|
+
column: {
|
|
148
|
+
start: number;
|
|
149
|
+
end: number;
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
interface Program extends BaseNode {
|
|
153
|
+
type: "Program";
|
|
154
|
+
body: Block;
|
|
155
|
+
}
|
|
156
|
+
interface Block extends BaseNode {
|
|
157
|
+
type: "Block";
|
|
158
|
+
statements: Statement[];
|
|
159
|
+
}
|
|
160
|
+
interface ImportSpecifier extends BaseNode {
|
|
161
|
+
type: "ImportSpecifier";
|
|
162
|
+
/** the exported name in the source module */
|
|
163
|
+
imported: Identifier;
|
|
164
|
+
/** the local binding name — same as `imported` unless renamed with `as` */
|
|
165
|
+
local: Identifier;
|
|
166
|
+
}
|
|
167
|
+
interface ImportStatement extends BaseNode {
|
|
168
|
+
type: "ImportStatement";
|
|
169
|
+
/** `import Default from '...'` */
|
|
170
|
+
defaultImport?: Identifier;
|
|
171
|
+
/** `import * as Module from '...'` — the module's exports as one value. */
|
|
172
|
+
namespaceImport?: Identifier;
|
|
173
|
+
/** `import type { A } from '...'`: every name it brings in is a type and
|
|
174
|
+
* may only be used as one — never as a value. It exists for the type
|
|
175
|
+
* checker alone, and leaves nothing in compiled code. */
|
|
176
|
+
isTypeOnly?: boolean;
|
|
177
|
+
/** `import { a, b as c } from '...'` */
|
|
178
|
+
specifiers: ImportSpecifier[];
|
|
179
|
+
source: StringLiteral;
|
|
180
|
+
}
|
|
181
|
+
/** `export const x = 1`, `export let y = 2`, `export function f() end` */
|
|
182
|
+
interface ExportStatement extends BaseNode {
|
|
183
|
+
type: "ExportStatement";
|
|
184
|
+
declaration: VariableDeclaration | FunctionDeclaration | ClassDeclaration;
|
|
185
|
+
}
|
|
186
|
+
/** `export default <expr>` — mirrors JS default export / dynamic import()'s
|
|
187
|
+
* `{ default: ... }` shape. Distinct from ExportStatement because the
|
|
188
|
+
* right-hand side is any expression, not necessarily a declaration. */
|
|
189
|
+
interface ExportDefaultStatement extends BaseNode {
|
|
190
|
+
type: "ExportDefaultStatement";
|
|
191
|
+
/** `export default class Name ... end` keeps its name: it declares the
|
|
192
|
+
* class here as well as exporting it, the way TypeScript's does. */
|
|
193
|
+
declaration: Expression | ClassDeclaration;
|
|
194
|
+
}
|
|
195
|
+
interface ExportSpecifier extends BaseNode {
|
|
196
|
+
type: "ExportSpecifier";
|
|
197
|
+
/** The name in this module — or, with `from`, in the other module. */
|
|
198
|
+
local: Identifier;
|
|
199
|
+
/** The name it is exported as — same as `local` unless renamed with `as`. */
|
|
200
|
+
exported: Identifier;
|
|
201
|
+
}
|
|
202
|
+
/** `export { a, b as c }` exports names declared elsewhere in the module;
|
|
203
|
+
* `export { a, b as c } from "./x"` re-exports another module's names. */
|
|
204
|
+
interface ExportNamedStatement extends BaseNode {
|
|
205
|
+
type: "ExportNamedStatement";
|
|
206
|
+
specifiers: ExportSpecifier[];
|
|
207
|
+
source?: StringLiteral;
|
|
208
|
+
}
|
|
209
|
+
/** `export * from "./x"` — every named export of another module (not its
|
|
210
|
+
* default), except names this module exports itself. */
|
|
211
|
+
interface ExportAllStatement extends BaseNode {
|
|
212
|
+
type: "ExportAllStatement";
|
|
213
|
+
source: StringLiteral;
|
|
214
|
+
}
|
|
215
|
+
type Statement = VariableDeclaration | FunctionDeclaration | FunctionDeclarationStatement | ClassDeclaration | AssignmentStatement | CompoundAssignmentStatement | CallStatement | ExpressionStatement | DoStatement | WhileStatement | RepeatStatement | IfStatement | NumericForStatement | GenericForStatement | ReturnStatement | BreakStatement | ContinueStatement | TypeAliasStatement | ExportTypeAliasStatement | ImportStatement | ExportStatement | ExportDefaultStatement | ExportNamedStatement | ExportAllStatement | DeclareStatement | DeclareClassStatement | ErrorStatement;
|
|
216
|
+
/** `declare game: DataModel` / `declare function require(m: string): unknown`
|
|
217
|
+
* — an ambient value/function declaration for a definitions file (`.d.tilua`).
|
|
218
|
+
* Contributes a global type; emits no runtime code. */
|
|
219
|
+
interface DeclareStatement extends BaseNode {
|
|
220
|
+
type: "DeclareStatement";
|
|
221
|
+
name: string;
|
|
222
|
+
/** The name as a node, so tools can point at it — `name` has no span. */
|
|
223
|
+
id: Identifier;
|
|
224
|
+
/** the declared value's type (function form is lowered to a FunctionTypeNode) */
|
|
225
|
+
valueType: TypeNode;
|
|
226
|
+
}
|
|
227
|
+
/** `declare class Part extends BasePart { Shape: EnumItem }` — a *nominal*
|
|
228
|
+
* type for a definitions file, the way Roblox's own classes are: a `Part` is
|
|
229
|
+
* an `Instance` because it extends one, not because it has the same members,
|
|
230
|
+
* and no table literal is ever a `Part`. The body lists the members the class
|
|
231
|
+
* adds; it inherits the rest. Declares a type only, no value. */
|
|
232
|
+
interface DeclareClassStatement extends BaseNode {
|
|
233
|
+
type: "DeclareClassStatement";
|
|
234
|
+
name: Identifier;
|
|
235
|
+
/** `extends Base` — another class. */
|
|
236
|
+
superclass?: TypeReference;
|
|
237
|
+
body: TableTypeNode;
|
|
238
|
+
}
|
|
239
|
+
/** A statement position that could not be parsed. Only produced when parsing
|
|
240
|
+
* in recovery mode (`parseWithRecovery`); its span covers the skipped tokens
|
|
241
|
+
* so tools can still map a cursor there. */
|
|
242
|
+
interface ErrorStatement extends BaseNode {
|
|
243
|
+
type: "ErrorStatement";
|
|
244
|
+
}
|
|
245
|
+
/** `const x = 1` / `let x, y = a, b` — the only variable-binding form in tilua
|
|
246
|
+
* (Luau's `local` is gone). `const` bindings are immutable and infer literal
|
|
247
|
+
* types (`const n = 1` → `1`); `let` bindings are mutable and widen. */
|
|
248
|
+
interface VariableDeclaration extends BaseNode {
|
|
249
|
+
type: "VariableDeclaration";
|
|
250
|
+
kind: "const" | "let";
|
|
251
|
+
names: BindingTarget[];
|
|
252
|
+
init: Expression[];
|
|
253
|
+
}
|
|
254
|
+
type BindingTarget = IdentifierPattern | ObjectPattern | ArrayPattern;
|
|
255
|
+
interface IdentifierPattern extends BaseNode {
|
|
256
|
+
type: "IdentifierPattern";
|
|
257
|
+
name: string;
|
|
258
|
+
/** only meaningful at the top level of a binding (`local x: T`, `{a}: T`) */
|
|
259
|
+
typeAnnotation?: TypeNode;
|
|
260
|
+
/** `local x <const>` attribute list */
|
|
261
|
+
attributes?: string[];
|
|
262
|
+
}
|
|
263
|
+
interface ObjectPattern extends BaseNode {
|
|
264
|
+
type: "ObjectPattern";
|
|
265
|
+
properties: ObjectPatternProperty[];
|
|
266
|
+
/** `...rest` — collects the remaining own keys into a new object */
|
|
267
|
+
rest?: BindingTarget;
|
|
268
|
+
typeAnnotation?: TypeNode;
|
|
269
|
+
}
|
|
270
|
+
interface ObjectPatternProperty extends BaseNode {
|
|
271
|
+
type: "ObjectPatternProperty";
|
|
272
|
+
/** identifier/string key, or any expression when `computed` */
|
|
273
|
+
key: Identifier | StringLiteral | Expression;
|
|
274
|
+
computed: boolean;
|
|
275
|
+
/** binding target; for shorthand this is an IdentifierPattern named after `key` */
|
|
276
|
+
value: BindingTarget;
|
|
277
|
+
/** `{ a = 1 }` / `{ a: b = 1 }` default */
|
|
278
|
+
default?: Expression;
|
|
279
|
+
shorthand: boolean;
|
|
280
|
+
}
|
|
281
|
+
interface ArrayPattern extends BaseNode {
|
|
282
|
+
type: "ArrayPattern";
|
|
283
|
+
/** `null` entries are elision holes (`[, a]`) */
|
|
284
|
+
elements: (ArrayPatternElement | null)[];
|
|
285
|
+
/** `...rest` — collects the remaining elements into a new array */
|
|
286
|
+
rest?: BindingTarget;
|
|
287
|
+
typeAnnotation?: TypeNode;
|
|
288
|
+
}
|
|
289
|
+
interface ArrayPatternElement extends BaseNode {
|
|
290
|
+
type: "ArrayPatternElement";
|
|
291
|
+
value: BindingTarget;
|
|
292
|
+
default?: Expression;
|
|
293
|
+
}
|
|
294
|
+
/** `function f() ... end` — declares `f` in the enclosing scope, visible to
|
|
295
|
+
* its own body (so it can recurse). Like TypeScript's function declaration,
|
|
296
|
+
* the name cannot be reassigned. `function a.b() end` and `function T:m() end`
|
|
297
|
+
* assign to a member instead: see `FunctionDeclarationStatement`. */
|
|
298
|
+
interface FunctionDeclaration extends BaseNode {
|
|
299
|
+
type: "FunctionDeclaration";
|
|
300
|
+
/** The name on the line the body is written on, when the declaration is
|
|
301
|
+
* an overload set — `name` is the first signature's. */
|
|
302
|
+
implementationName?: Identifier;
|
|
303
|
+
name: Identifier;
|
|
304
|
+
func: FunctionBody;
|
|
305
|
+
attributes?: string[];
|
|
306
|
+
/** TS-style overload signatures preceding the implementation (`func`). */
|
|
307
|
+
signatures?: FunctionSignature[];
|
|
308
|
+
}
|
|
309
|
+
/** `function a.b() end` / `function T:m() end` — defines a member. */
|
|
310
|
+
interface FunctionDeclarationStatement extends BaseNode {
|
|
311
|
+
type: "FunctionDeclarationStatement";
|
|
312
|
+
target: FunctionName;
|
|
313
|
+
isMethod: boolean;
|
|
314
|
+
func: FunctionBody;
|
|
315
|
+
attributes?: string[];
|
|
316
|
+
/** TS-style overload signatures preceding the implementation (`func`). */
|
|
317
|
+
signatures?: FunctionSignature[];
|
|
318
|
+
}
|
|
319
|
+
/** A bodyless function declaration — an overload signature. tilua uses the
|
|
320
|
+
* exact TS shape: one or more `function f(...): T` lines with no `end`,
|
|
321
|
+
* followed by the implementation `function f(...) ... end`. */
|
|
322
|
+
interface FunctionSignature extends BaseNode {
|
|
323
|
+
type: "FunctionSignature";
|
|
324
|
+
/** The name this signature was written with — one line of an overload
|
|
325
|
+
* set, each of which a tool can point at on its own. */
|
|
326
|
+
name?: Identifier;
|
|
327
|
+
generics: GenericTypeParameter[];
|
|
328
|
+
params: FunctionParameter[];
|
|
329
|
+
hasVarargs: boolean;
|
|
330
|
+
varargTypeAnnotation?: TypeNode;
|
|
331
|
+
returnType?: TypeNode;
|
|
332
|
+
/** `: v is T` / `: asserts v` instead of a plain return type. */
|
|
333
|
+
predicate?: TypePredicateNode;
|
|
334
|
+
}
|
|
335
|
+
interface FunctionName extends BaseNode {
|
|
336
|
+
type: "FunctionName";
|
|
337
|
+
base: Identifier;
|
|
338
|
+
path: Identifier[];
|
|
339
|
+
method?: Identifier;
|
|
340
|
+
}
|
|
341
|
+
/** `class Name extends Base ... end` — tilua's one runtime class form.
|
|
342
|
+
*
|
|
343
|
+
* It is sugar, and the shape it stands for is the ordinary Lua one: the
|
|
344
|
+
* class is a single table holding the methods and the statics, and an
|
|
345
|
+
* instance is a table whose metatable points at it. An instance therefore
|
|
346
|
+
* references *the class*, not a copy and not a prototype chain of its own —
|
|
347
|
+
* one class, one place its behaviour lives.
|
|
348
|
+
*
|
|
349
|
+
* The declaration contributes both a type (the instance type, nominal, as
|
|
350
|
+
* `declare class` does) and a value (the class table, with `new` and the
|
|
351
|
+
* statics on it). */
|
|
352
|
+
interface ClassDeclaration extends BaseNode {
|
|
353
|
+
type: "ClassDeclaration";
|
|
354
|
+
name: Identifier;
|
|
355
|
+
/** `class Box<T>` — the instance type is then generic, and `Box<number>`
|
|
356
|
+
* instantiates it. */
|
|
357
|
+
typeParams: GenericTypeParameter[];
|
|
358
|
+
/** `extends Base` / `extends Box<number>` — another class declared in
|
|
359
|
+
* this file or imported, with its own arguments filled in. */
|
|
360
|
+
superclass?: Identifier;
|
|
361
|
+
/** The arguments `extends Box<number>` was written with. */
|
|
362
|
+
superArguments?: TypeNode[];
|
|
363
|
+
members: ClassMember[];
|
|
364
|
+
}
|
|
365
|
+
/** `class ... end` written where a value goes: `const Counter = class ... end`,
|
|
366
|
+
* `export default class ... end`. The name is optional and, when written, is
|
|
367
|
+
* visible only inside the class — as in JavaScript. An expression has no name
|
|
368
|
+
* to instantiate, so it takes no type parameters. */
|
|
369
|
+
interface ClassExpression extends BaseNode {
|
|
370
|
+
type: "ClassExpression";
|
|
371
|
+
name?: Identifier;
|
|
372
|
+
superclass?: Identifier;
|
|
373
|
+
superArguments?: TypeNode[];
|
|
374
|
+
members: ClassMember[];
|
|
375
|
+
}
|
|
376
|
+
type ClassMember = ClassField | ClassMethod | ClassAccessor | ClassConstructor;
|
|
377
|
+
/** The two ways a class is written. Everything after parsing treats them
|
|
378
|
+
* alike: only the name and the type parameters differ. */
|
|
379
|
+
type ClassLike = ClassDeclaration | ClassExpression;
|
|
380
|
+
/** `x: number` / `x = 1` / `static count = 0`. An instance field is assigned
|
|
381
|
+
* when the instance is built, before the constructor body runs; a `static`
|
|
382
|
+
* one is assigned on the class table, once. */
|
|
383
|
+
interface ClassField extends BaseNode {
|
|
384
|
+
type: "ClassField";
|
|
385
|
+
name: Identifier;
|
|
386
|
+
isStatic: boolean;
|
|
387
|
+
typeAnnotation?: TypeNode;
|
|
388
|
+
init?: Expression;
|
|
389
|
+
}
|
|
390
|
+
/** `function name(...) ... end` inside a class body — `this` is bound in it.
|
|
391
|
+
* A `static` one is a plain function on the class table, with no `this`. */
|
|
392
|
+
interface ClassMethod extends BaseNode {
|
|
393
|
+
type: "ClassMethod";
|
|
394
|
+
name: Identifier;
|
|
395
|
+
isStatic: boolean;
|
|
396
|
+
func: FunctionBody;
|
|
397
|
+
/** TS-style overload signatures preceding the implementation. */
|
|
398
|
+
signatures?: FunctionSignature[];
|
|
399
|
+
}
|
|
400
|
+
/** `get name(): T ... end` / `set name(v: T) ... end` — read and written as a
|
|
401
|
+
* property, run as a function. */
|
|
402
|
+
interface ClassAccessor extends BaseNode {
|
|
403
|
+
type: "ClassAccessor";
|
|
404
|
+
kind: "get" | "set";
|
|
405
|
+
name: Identifier;
|
|
406
|
+
isStatic: boolean;
|
|
407
|
+
func: FunctionBody;
|
|
408
|
+
}
|
|
409
|
+
/** `constructor(...) ... end` — runs on a fresh instance. A class that
|
|
410
|
+
* extends another must call `super(...)` before touching `this`. */
|
|
411
|
+
interface ClassConstructor extends BaseNode {
|
|
412
|
+
type: "ClassConstructor";
|
|
413
|
+
func: FunctionBody;
|
|
414
|
+
}
|
|
415
|
+
/** `new Name(args)` — builds an instance. Lowers to the class's own
|
|
416
|
+
* `Name.new(args)`, which is also callable by hand. */
|
|
417
|
+
interface NewExpression extends BaseNode {
|
|
418
|
+
type: "NewExpression";
|
|
419
|
+
callee: Expression;
|
|
420
|
+
arguments: Expression[];
|
|
421
|
+
typeArguments?: (TypeNode | TypePackNode)[];
|
|
422
|
+
}
|
|
423
|
+
/** `super` — only inside a class that extends another: `super(...)` in the
|
|
424
|
+
* constructor runs the base's on this instance, and `super.method(...)` in a
|
|
425
|
+
* method calls the base's version of it. */
|
|
426
|
+
interface SuperExpression extends BaseNode {
|
|
427
|
+
type: "SuperExpression";
|
|
428
|
+
}
|
|
429
|
+
interface AssignmentStatement extends BaseNode {
|
|
430
|
+
type: "AssignmentStatement";
|
|
431
|
+
targets: (Expression | ObjectPattern | ArrayPattern)[];
|
|
432
|
+
values: Expression[];
|
|
433
|
+
}
|
|
434
|
+
interface CompoundAssignmentStatement extends BaseNode {
|
|
435
|
+
type: "CompoundAssignmentStatement";
|
|
436
|
+
operator: "+=" | "-=" | "*=" | "/=" | "//=" | "%=" | "^=" | "..=";
|
|
437
|
+
target: Expression;
|
|
438
|
+
value: Expression;
|
|
439
|
+
}
|
|
440
|
+
interface CallStatement extends BaseNode {
|
|
441
|
+
type: "CallStatement";
|
|
442
|
+
expression: CallExpression | MethodCallExpression | NewExpression;
|
|
443
|
+
}
|
|
444
|
+
/** An expression written as a statement, where Lua would want a call or an
|
|
445
|
+
* assignment: `value` on a line of its own.
|
|
446
|
+
*
|
|
447
|
+
* It does nothing, and the compiler drops it. It is here because writing a
|
|
448
|
+
* name and asking the editor about it — hover, completion — is how code gets
|
|
449
|
+
* written, and making that a syntax error means the file stops being
|
|
450
|
+
* analysable exactly when the help is wanted. A call is a `CallStatement`
|
|
451
|
+
* still; this is every other shape. */
|
|
452
|
+
interface ExpressionStatement extends BaseNode {
|
|
453
|
+
type: "ExpressionStatement";
|
|
454
|
+
expression: Expression;
|
|
455
|
+
}
|
|
456
|
+
interface DoStatement extends BaseNode {
|
|
457
|
+
type: "DoStatement";
|
|
458
|
+
body: Block;
|
|
459
|
+
}
|
|
460
|
+
interface WhileStatement extends BaseNode {
|
|
461
|
+
type: "WhileStatement";
|
|
462
|
+
condition: Expression;
|
|
463
|
+
body: Block;
|
|
464
|
+
}
|
|
465
|
+
interface RepeatStatement extends BaseNode {
|
|
466
|
+
type: "RepeatStatement";
|
|
467
|
+
body: Block;
|
|
468
|
+
condition: Expression;
|
|
469
|
+
}
|
|
470
|
+
interface IfClause extends BaseNode {
|
|
471
|
+
type: "IfClause";
|
|
472
|
+
condition: Expression;
|
|
473
|
+
body: Block;
|
|
474
|
+
}
|
|
475
|
+
interface IfStatement extends BaseNode {
|
|
476
|
+
type: "IfStatement";
|
|
477
|
+
clauses: IfClause[];
|
|
478
|
+
alternate?: Block;
|
|
479
|
+
}
|
|
480
|
+
interface NumericForStatement extends BaseNode {
|
|
481
|
+
type: "NumericForStatement";
|
|
482
|
+
variable: TypedIdentifier;
|
|
483
|
+
start: Expression;
|
|
484
|
+
end: Expression;
|
|
485
|
+
step?: Expression;
|
|
486
|
+
body: Block;
|
|
487
|
+
}
|
|
488
|
+
interface GenericForStatement extends BaseNode {
|
|
489
|
+
type: "GenericForStatement";
|
|
490
|
+
variables: BindingTarget[];
|
|
491
|
+
iterators: Expression[];
|
|
492
|
+
body: Block;
|
|
493
|
+
}
|
|
494
|
+
interface ReturnStatement extends BaseNode {
|
|
495
|
+
type: "ReturnStatement";
|
|
496
|
+
arguments: Expression[];
|
|
497
|
+
}
|
|
498
|
+
interface BreakStatement extends BaseNode {
|
|
499
|
+
type: "BreakStatement";
|
|
500
|
+
}
|
|
501
|
+
interface ContinueStatement extends BaseNode {
|
|
502
|
+
type: "ContinueStatement";
|
|
503
|
+
}
|
|
504
|
+
interface TypeAliasStatement extends BaseNode {
|
|
505
|
+
type: "TypeAliasStatement";
|
|
506
|
+
name: Identifier;
|
|
507
|
+
generics: GenericTypeParameter[];
|
|
508
|
+
definition: TypeNode;
|
|
509
|
+
}
|
|
510
|
+
interface ExportTypeAliasStatement extends BaseNode {
|
|
511
|
+
type: "ExportTypeAliasStatement";
|
|
512
|
+
alias: TypeAliasStatement;
|
|
513
|
+
}
|
|
514
|
+
interface GenericTypeParameter extends BaseNode {
|
|
515
|
+
type: "GenericTypeParameter";
|
|
516
|
+
name: string;
|
|
517
|
+
/** The name as a node. Absent on parameters the analyzer synthesizes. */
|
|
518
|
+
id?: Identifier;
|
|
519
|
+
isPack?: boolean;
|
|
520
|
+
/** `<const T>` — infer the argument at its narrowest instead of widening
|
|
521
|
+
* it: literals stay literal and array literals become tuples. */
|
|
522
|
+
isConst?: boolean;
|
|
523
|
+
/** `<T extends C>` upper bound (TS style). */
|
|
524
|
+
constraint?: TypeNode;
|
|
525
|
+
default?: TypeNode | TypePackNode;
|
|
526
|
+
}
|
|
527
|
+
type Expression = Identifier | NilLiteral | BooleanLiteral | NumberLiteral | StringLiteral | InterpolatedStringExpression | VarargExpression | FunctionExpression | TableExpression | ArrayExpression | BinaryExpression | UnaryExpression | MemberExpression | IndexExpression | CallExpression | MethodCallExpression | NewExpression | SuperExpression | ClassExpression | SpreadElement | ParenthesizedExpression | TypeAssertionExpression | SatisfiesExpression | AsConstExpression | IfElseExpression | ErrorExpression;
|
|
528
|
+
/** An expression that could not be parsed. Only produced in recovery mode
|
|
529
|
+
* (`parseWithRecovery`), where a broken initializer, condition, field value or
|
|
530
|
+
* argument keeps its place in the tree; its span covers the skipped tokens
|
|
531
|
+
* (and is empty when nothing was written). Its type is `any`. */
|
|
532
|
+
interface ErrorExpression extends BaseNode {
|
|
533
|
+
type: "ErrorExpression";
|
|
534
|
+
}
|
|
535
|
+
interface Identifier extends BaseNode {
|
|
536
|
+
type: "Identifier";
|
|
537
|
+
name: string;
|
|
538
|
+
}
|
|
539
|
+
interface TypedIdentifier extends BaseNode {
|
|
540
|
+
type: "TypedIdentifier";
|
|
541
|
+
name: string;
|
|
542
|
+
typeAnnotation?: TypeNode;
|
|
543
|
+
attributes?: string[];
|
|
544
|
+
}
|
|
545
|
+
interface NilLiteral extends BaseNode {
|
|
546
|
+
type: "NilLiteral";
|
|
547
|
+
}
|
|
548
|
+
interface BooleanLiteral extends BaseNode {
|
|
549
|
+
type: "BooleanLiteral";
|
|
550
|
+
value: boolean;
|
|
551
|
+
}
|
|
552
|
+
interface NumberLiteral extends BaseNode {
|
|
553
|
+
type: "NumberLiteral";
|
|
554
|
+
value: number;
|
|
555
|
+
raw: string;
|
|
556
|
+
}
|
|
557
|
+
interface StringLiteral extends BaseNode {
|
|
558
|
+
type: "StringLiteral";
|
|
559
|
+
value: string;
|
|
560
|
+
raw: string;
|
|
561
|
+
}
|
|
562
|
+
type InterpolatedStringPart = {
|
|
563
|
+
kind: "string";
|
|
564
|
+
value: string;
|
|
565
|
+
raw: string;
|
|
566
|
+
} | {
|
|
567
|
+
kind: "expression";
|
|
568
|
+
expression: Expression;
|
|
569
|
+
};
|
|
570
|
+
interface InterpolatedStringExpression extends BaseNode {
|
|
571
|
+
type: "InterpolatedStringExpression";
|
|
572
|
+
parts: InterpolatedStringPart[];
|
|
573
|
+
}
|
|
574
|
+
interface VarargExpression extends BaseNode {
|
|
575
|
+
type: "VarargExpression";
|
|
576
|
+
}
|
|
577
|
+
interface FunctionParameter extends BaseNode {
|
|
578
|
+
type: "FunctionParameter";
|
|
579
|
+
/** `...rest: T[]` — every argument from this position on, as an array,
|
|
580
|
+
* the way JavaScript's rest parameter collects them. It is always last,
|
|
581
|
+
* and the function is a vararg function: `...` still means Lua's pack
|
|
582
|
+
* (`const a, b = ...`), and this is the array of it. */
|
|
583
|
+
rest?: boolean;
|
|
584
|
+
/** `name?: T` — the argument may be omitted, and its type admits `nil`. */
|
|
585
|
+
optional?: boolean;
|
|
586
|
+
/** the parameter name, or `""` when `pattern` is set */
|
|
587
|
+
name: string;
|
|
588
|
+
/** JS-style destructured parameter (`function f({a}, [b]) end`) */
|
|
589
|
+
pattern?: ObjectPattern | ArrayPattern;
|
|
590
|
+
typeAnnotation?: TypeNode;
|
|
591
|
+
/** default value (`function f(a = 1) end`) */
|
|
592
|
+
default?: Expression;
|
|
593
|
+
}
|
|
594
|
+
interface FunctionBody extends BaseNode {
|
|
595
|
+
type: "FunctionBody";
|
|
596
|
+
generics: GenericTypeParameter[];
|
|
597
|
+
params: FunctionParameter[];
|
|
598
|
+
hasVarargs: boolean;
|
|
599
|
+
varargTypeAnnotation?: TypeNode;
|
|
600
|
+
returnType?: TypeNode;
|
|
601
|
+
/** `: v is T` / `: asserts v` instead of a plain return type. */
|
|
602
|
+
predicate?: TypePredicateNode;
|
|
603
|
+
/** Declared as `function T:m(...)`, so `params[0]` is the injected `self`. */
|
|
604
|
+
isMethod?: boolean;
|
|
605
|
+
body: Block;
|
|
606
|
+
}
|
|
607
|
+
interface FunctionExpression extends BaseNode {
|
|
608
|
+
type: "FunctionExpression";
|
|
609
|
+
func: FunctionBody;
|
|
610
|
+
}
|
|
611
|
+
type TableField =
|
|
612
|
+
/** `a: v` or `"a": v` — JS colon syntax (NOT Luau `a = v`). */
|
|
613
|
+
{
|
|
614
|
+
type: "TableFieldNamed";
|
|
615
|
+
key: Identifier | StringLiteral;
|
|
616
|
+
value: Expression;
|
|
617
|
+
}
|
|
618
|
+
/** `[expr]: v` — computed key. */
|
|
619
|
+
| {
|
|
620
|
+
type: "TableFieldComputed";
|
|
621
|
+
key: Expression;
|
|
622
|
+
value: Expression;
|
|
623
|
+
}
|
|
624
|
+
/** `{ a }` shorthand — sugar for `{ a: a }`. */
|
|
625
|
+
| {
|
|
626
|
+
type: "TableFieldShorthand";
|
|
627
|
+
name: Identifier;
|
|
628
|
+
}
|
|
629
|
+
/** `{ ...expr }` — JS object spread. */
|
|
630
|
+
| {
|
|
631
|
+
type: "TableFieldSpread";
|
|
632
|
+
argument: Expression;
|
|
633
|
+
};
|
|
634
|
+
/** `{ a: 1, [k]: v }` — object literal (Luau `{}` narrowed to objects only). */
|
|
635
|
+
interface TableExpression extends BaseNode {
|
|
636
|
+
type: "TableExpression";
|
|
637
|
+
fields: TableField[];
|
|
638
|
+
}
|
|
639
|
+
/** `[1, 2, ...rest]` — array literal. Lowers to a Luau `{1, 2}` sequence table. */
|
|
640
|
+
interface ArrayExpression extends BaseNode {
|
|
641
|
+
type: "ArrayExpression";
|
|
642
|
+
elements: (Expression | SpreadElement)[];
|
|
643
|
+
}
|
|
644
|
+
/** `...expr` — the values of an array, one after another, where a list of
|
|
645
|
+
* values is written: inside an array literal (`[...xs, 1]`) and in a call's
|
|
646
|
+
* arguments (`f(a, ...rest)`). It is not a value of its own, and the parser
|
|
647
|
+
* only produces one in those two places.
|
|
648
|
+
*
|
|
649
|
+
* Lua spreads with `table.unpack`, which only yields every value when it is
|
|
650
|
+
* written last; anywhere else the compiler builds the whole list first. Bare
|
|
651
|
+
* `...` is unaffected — that is the vararg pack, and `f(...)` passes it on
|
|
652
|
+
* as it always did. */
|
|
653
|
+
interface SpreadElement extends BaseNode {
|
|
654
|
+
type: "SpreadElement";
|
|
655
|
+
argument: Expression;
|
|
656
|
+
}
|
|
657
|
+
declare const BinaryOperators: readonly ["+", "-", "*", "/", "//", "%", "^", "..", "==", "~=", "<", ">", "<=", ">=", "and", "or"];
|
|
658
|
+
interface BinaryExpression extends BaseNode {
|
|
659
|
+
type: "BinaryExpression";
|
|
660
|
+
operator: typeof BinaryOperators[number];
|
|
661
|
+
left: Expression;
|
|
662
|
+
right: Expression;
|
|
663
|
+
}
|
|
664
|
+
declare const UnaryOperators: readonly ["-", "not", "#"];
|
|
665
|
+
interface UnaryExpression extends BaseNode {
|
|
666
|
+
type: "UnaryExpression";
|
|
667
|
+
operator: typeof UnaryOperators[number];
|
|
668
|
+
argument: Expression;
|
|
669
|
+
}
|
|
670
|
+
interface MemberExpression extends BaseNode {
|
|
671
|
+
type: "MemberExpression";
|
|
672
|
+
object: Expression;
|
|
673
|
+
property: Identifier;
|
|
674
|
+
/** `object?.property` — when `object` is nil, the whole chain this link
|
|
675
|
+
* belongs to is nil and nothing after it is evaluated. */
|
|
676
|
+
optional?: boolean;
|
|
677
|
+
}
|
|
678
|
+
interface IndexExpression extends BaseNode {
|
|
679
|
+
type: "IndexExpression";
|
|
680
|
+
object: Expression;
|
|
681
|
+
index: Expression;
|
|
682
|
+
}
|
|
683
|
+
interface CallExpression extends BaseNode {
|
|
684
|
+
type: "CallExpression";
|
|
685
|
+
callee: Expression;
|
|
686
|
+
arguments: Expression[];
|
|
687
|
+
/** `f<T>(x)` — type arguments written out rather than inferred. */
|
|
688
|
+
typeArguments?: (TypeNode | TypePackNode)[];
|
|
689
|
+
/** `f?.(...)` — see `MemberExpression.optional`. The call does not happen,
|
|
690
|
+
* and the arguments are not evaluated, when `callee` is nil. */
|
|
691
|
+
optional?: boolean;
|
|
692
|
+
/** The `(` opened on a line after the callee ended:
|
|
693
|
+
*
|
|
694
|
+
* const value = map[key]
|
|
695
|
+
* ("text"):upper()
|
|
696
|
+
*
|
|
697
|
+
* is one statement — a call of `map[key]` — because a line break does
|
|
698
|
+
* not end a statement, in Lua or in JavaScript. Flagged here so the
|
|
699
|
+
* analyzer can say so; Lua 5.1 calls it "ambiguous syntax". */
|
|
700
|
+
argumentsOnNewLine?: boolean;
|
|
701
|
+
}
|
|
702
|
+
interface MethodCallExpression extends BaseNode {
|
|
703
|
+
type: "MethodCallExpression";
|
|
704
|
+
object: Expression;
|
|
705
|
+
method: Identifier;
|
|
706
|
+
arguments: Expression[];
|
|
707
|
+
/** `obj:m<T>(x)` — see `CallExpression.typeArguments`. */
|
|
708
|
+
typeArguments?: (TypeNode | TypePackNode)[];
|
|
709
|
+
/** `object?:method(...)` — see `MemberExpression.optional`. The
|
|
710
|
+
* arguments are not evaluated when `object` is nil. */
|
|
711
|
+
optional?: boolean;
|
|
712
|
+
}
|
|
713
|
+
interface ParenthesizedExpression extends BaseNode {
|
|
714
|
+
type: "ParenthesizedExpression";
|
|
715
|
+
expression: Expression;
|
|
716
|
+
}
|
|
717
|
+
/** `expr satisfies T` — checks that `expr` is assignable to `T` without
|
|
718
|
+
* changing its inferred type, so a literal keeps its narrow type while still
|
|
719
|
+
* being validated against a wider contract. Unlike `as`, it never widens or
|
|
720
|
+
* reinterprets. */
|
|
721
|
+
interface SatisfiesExpression extends BaseNode {
|
|
722
|
+
type: "SatisfiesExpression";
|
|
723
|
+
expression: Expression;
|
|
724
|
+
typeAnnotation: TypeNode;
|
|
725
|
+
}
|
|
726
|
+
interface TypeAssertionExpression extends BaseNode {
|
|
727
|
+
type: "TypeAssertionExpression";
|
|
728
|
+
expression: Expression;
|
|
729
|
+
typeAnnotation: TypeNode;
|
|
730
|
+
}
|
|
731
|
+
/** `expr as const` — freezes the expression's inferred type to its narrowest
|
|
732
|
+
* (literal) form, the way TypeScript's `as const` does. Kept as a distinct
|
|
733
|
+
* node from TypeAssertionExpression because there's no TypeNode on the
|
|
734
|
+
* right-hand side: the type checker computes the literal type itself. */
|
|
735
|
+
interface AsConstExpression extends BaseNode {
|
|
736
|
+
type: "AsConstExpression";
|
|
737
|
+
expression: Expression;
|
|
738
|
+
}
|
|
739
|
+
interface IfElseExpression extends BaseNode {
|
|
740
|
+
type: "IfElseExpression";
|
|
741
|
+
clauses: {
|
|
742
|
+
condition: Expression;
|
|
743
|
+
body: Expression;
|
|
744
|
+
}[];
|
|
745
|
+
alternate: Expression;
|
|
746
|
+
}
|
|
747
|
+
type TypeNode = TypeReference | TypeLiteralString | TypeLiteralBoolean | TypeLiteralNumber | TableTypeNode | ArrayTypeNode | TupleTypeNode | FunctionTypeNode | UnionTypeNode | IntersectionTypeNode | ParenthesizedTypeNode | TypeofTypeNode | VariadicTypeNode | TypePackNode | KeyofTypeNode | IndexedAccessTypeNode | ConditionalTypeNode | InferTypeNode | MappedTypeNode | TemplateLiteralTypeNode | DifferenceTypeNode;
|
|
748
|
+
/** `A - B` — every value of `A` that is not a `B`. Binds tighter than `|`
|
|
749
|
+
* and looser than `&`, so `A | B - C` is `A | (B - C)`.
|
|
750
|
+
*
|
|
751
|
+
* Mostly it simplifies away (a union drops members; `string - "a"` is just
|
|
752
|
+
* `string`), but over an opaque type it is retained — which is what lets the
|
|
753
|
+
* `else` of `if a == 1` on an `unknown` say `unknown - 1` instead of
|
|
754
|
+
* forgetting the test. `Exclude<T, U>` is defined as `T - U`. */
|
|
755
|
+
interface DifferenceTypeNode extends BaseNode {
|
|
756
|
+
type: "DifferenceTypeNode";
|
|
757
|
+
base: TypeNode;
|
|
758
|
+
excluded: TypeNode;
|
|
759
|
+
}
|
|
760
|
+
/** A template literal type: `` `on${string}` ``, `` `get${K}` ``.
|
|
761
|
+
* `quasis` are the literal chunks and `types` the interpolated types;
|
|
762
|
+
* `quasis.length === types.length + 1`, exactly as in an ECMAScript template.
|
|
763
|
+
* When every interpolation is a union of string literals the type reduces to
|
|
764
|
+
* the union of all concatenations; otherwise it stays a pattern that literal
|
|
765
|
+
* strings are matched against. */
|
|
766
|
+
interface TemplateLiteralTypeNode extends BaseNode {
|
|
767
|
+
type: "TemplateLiteralTypeNode";
|
|
768
|
+
quasis: string[];
|
|
769
|
+
types: TypeNode[];
|
|
770
|
+
}
|
|
771
|
+
/** `keyof T` — the union of `T`'s property names as string-literal types,
|
|
772
|
+
* plus its indexer key type when it has one. */
|
|
773
|
+
interface KeyofTypeNode extends BaseNode {
|
|
774
|
+
type: "KeyofTypeNode";
|
|
775
|
+
target: TypeNode;
|
|
776
|
+
}
|
|
777
|
+
/** `T[K]` — indexed access. Distinguished from the `T[]` array suffix by
|
|
778
|
+
* whether the brackets are empty. */
|
|
779
|
+
interface IndexedAccessTypeNode extends BaseNode {
|
|
780
|
+
type: "IndexedAccessTypeNode";
|
|
781
|
+
objectType: TypeNode;
|
|
782
|
+
indexType: TypeNode;
|
|
783
|
+
}
|
|
784
|
+
/** `C extends E ? A : B`. Distributes over a naked type parameter, as in
|
|
785
|
+
* TypeScript, which is what makes `Exclude<T, U>` filter a union. */
|
|
786
|
+
interface ConditionalTypeNode extends BaseNode {
|
|
787
|
+
type: "ConditionalTypeNode";
|
|
788
|
+
checkType: TypeNode;
|
|
789
|
+
extendsType: TypeNode;
|
|
790
|
+
trueType: TypeNode;
|
|
791
|
+
falseType: TypeNode;
|
|
792
|
+
}
|
|
793
|
+
/** `infer U`, only meaningful inside a conditional's `extends` clause: it
|
|
794
|
+
* binds `U` to whatever matched at that position. */
|
|
795
|
+
interface InferTypeNode extends BaseNode {
|
|
796
|
+
type: "InferTypeNode";
|
|
797
|
+
name: string;
|
|
798
|
+
/** The bound name as a node. */
|
|
799
|
+
id?: Identifier;
|
|
800
|
+
}
|
|
801
|
+
/** `{ [K in C]: V }` — a mapped type. `optional` / `readonly` carry the
|
|
802
|
+
* modifier as written: `true` adds it (`?`), `false` removes it (`-?`),
|
|
803
|
+
* `undefined` leaves the source property's modifier alone. */
|
|
804
|
+
interface MappedTypeNode extends BaseNode {
|
|
805
|
+
type: "MappedTypeNode";
|
|
806
|
+
/** The name bound to each key in turn (`K`). */
|
|
807
|
+
parameter: string;
|
|
808
|
+
/** `parameter` as a node. */
|
|
809
|
+
parameterId?: Identifier;
|
|
810
|
+
/** The union of keys to map over (`C`). */
|
|
811
|
+
constraint: TypeNode;
|
|
812
|
+
/** `[K in C as R]` — remaps each key through `R`. */
|
|
813
|
+
nameType?: TypeNode;
|
|
814
|
+
/** The property type, which may mention `parameter`. */
|
|
815
|
+
template: TypeNode;
|
|
816
|
+
optional?: boolean;
|
|
817
|
+
readonly?: boolean;
|
|
818
|
+
}
|
|
819
|
+
/** The return position of a TypeScript-style type guard:
|
|
820
|
+
* `function isStr(v: unknown): v is string`, `function check(v): asserts v`,
|
|
821
|
+
* or `function assertStr(v): asserts v is string`.
|
|
822
|
+
*
|
|
823
|
+
* Deliberately *not* a member of `TypeNode` — it may only appear as a
|
|
824
|
+
* function's return annotation, and keeping it out of the union means every
|
|
825
|
+
* existing `TypeNode` consumer stays exhaustive without change. A function
|
|
826
|
+
* carrying one returns `boolean` (`is`) or nothing (`asserts`). */
|
|
827
|
+
interface TypePredicateNode extends BaseNode {
|
|
828
|
+
type: "TypePredicateNode";
|
|
829
|
+
/** Name of the parameter this guard talks about. */
|
|
830
|
+
parameterName: string;
|
|
831
|
+
/** `asserts x` — narrows the rest of the enclosing block, not a branch. */
|
|
832
|
+
asserts: boolean;
|
|
833
|
+
/** Absent for a bare `asserts x` (a truthiness assertion). */
|
|
834
|
+
typeAnnotation?: TypeNode;
|
|
835
|
+
}
|
|
836
|
+
interface TypePackNode extends BaseNode {
|
|
837
|
+
type: "TypePackNode";
|
|
838
|
+
types: TypeNode[];
|
|
839
|
+
hasVarargs: boolean;
|
|
840
|
+
varargType?: TypeNode;
|
|
841
|
+
}
|
|
842
|
+
interface TypeReference extends BaseNode {
|
|
843
|
+
type: "TypeReference";
|
|
844
|
+
base: string;
|
|
845
|
+
namespace?: string;
|
|
846
|
+
typeArguments: (TypeNode | TypePackNode)[];
|
|
847
|
+
}
|
|
848
|
+
interface TypeLiteralString extends BaseNode {
|
|
849
|
+
type: "TypeLiteralString";
|
|
850
|
+
value: string;
|
|
851
|
+
}
|
|
852
|
+
interface TypeLiteralBoolean extends BaseNode {
|
|
853
|
+
type: "TypeLiteralBoolean";
|
|
854
|
+
value: boolean;
|
|
855
|
+
}
|
|
856
|
+
/** `1`, `3.5` — a single-valued number type. The checker already produces
|
|
857
|
+
* these when narrowing (`if n == 1`), so they have to be writable too. */
|
|
858
|
+
interface TypeLiteralNumber extends BaseNode {
|
|
859
|
+
type: "TypeLiteralNumber";
|
|
860
|
+
value: number;
|
|
861
|
+
}
|
|
862
|
+
type TableTypeProperty = ({
|
|
863
|
+
type: "TableTypeIndexer";
|
|
864
|
+
keyType: TypeNode;
|
|
865
|
+
valueType: TypeNode;
|
|
866
|
+
} & BaseNode)
|
|
867
|
+
/** `name: T` (required) or `name?: T` (optional — TS style, the property
|
|
868
|
+
* may be absent). `optional` reflects the `?` after the name only;
|
|
869
|
+
* `name: T | nil` is a required property whose value may be nil. */
|
|
870
|
+
| ({
|
|
871
|
+
type: "TableTypeProperty";
|
|
872
|
+
name: string;
|
|
873
|
+
key: Identifier;
|
|
874
|
+
valueType: TypeNode;
|
|
875
|
+
optional: boolean;
|
|
876
|
+
readonly?: boolean;
|
|
877
|
+
} & BaseNode);
|
|
878
|
+
interface TableTypeNode extends BaseNode {
|
|
879
|
+
type: "TableTypeNode";
|
|
880
|
+
properties: TableTypeProperty[];
|
|
881
|
+
}
|
|
882
|
+
/** `T[]` — array type. Replaces Luau's `{T}` array-table notation. */
|
|
883
|
+
interface ArrayTypeNode extends BaseNode {
|
|
884
|
+
type: "ArrayTypeNode";
|
|
885
|
+
element: TypeNode;
|
|
886
|
+
}
|
|
887
|
+
/** `[number, string]` — fixed-length tuple type. */
|
|
888
|
+
interface TupleTypeNode extends BaseNode {
|
|
889
|
+
type: "TupleTypeNode";
|
|
890
|
+
elements: TypeNode[];
|
|
891
|
+
}
|
|
892
|
+
interface FunctionTypeParameter extends BaseNode {
|
|
893
|
+
type: "FunctionTypeParameter";
|
|
894
|
+
/** `(...rest: T[]) -> R` — see `FunctionParameter.rest`. */
|
|
895
|
+
rest?: boolean;
|
|
896
|
+
/** `name?: T` — the argument may be omitted, and its type admits `nil`. */
|
|
897
|
+
optional?: boolean;
|
|
898
|
+
name?: string;
|
|
899
|
+
/** The name as a node (absent for an unnamed parameter). */
|
|
900
|
+
id?: Identifier;
|
|
901
|
+
typeAnnotation: TypeNode;
|
|
902
|
+
}
|
|
903
|
+
interface FunctionTypeNode extends BaseNode {
|
|
904
|
+
type: "FunctionTypeNode";
|
|
905
|
+
generics: GenericTypeParameter[];
|
|
906
|
+
params: FunctionTypeParameter[];
|
|
907
|
+
hasVarargs: boolean;
|
|
908
|
+
varargType?: TypeNode;
|
|
909
|
+
returnType: TypeNode;
|
|
910
|
+
/** `(v: unknown) -> v is string` — a guard written as a function *type*. */
|
|
911
|
+
predicate?: TypePredicateNode;
|
|
912
|
+
}
|
|
913
|
+
interface UnionTypeNode extends BaseNode {
|
|
914
|
+
type: "UnionTypeNode";
|
|
915
|
+
types: TypeNode[];
|
|
916
|
+
}
|
|
917
|
+
interface IntersectionTypeNode extends BaseNode {
|
|
918
|
+
type: "IntersectionTypeNode";
|
|
919
|
+
types: TypeNode[];
|
|
920
|
+
}
|
|
921
|
+
interface ParenthesizedTypeNode extends BaseNode {
|
|
922
|
+
type: "ParenthesizedTypeNode";
|
|
923
|
+
typeAnnotation: TypeNode;
|
|
924
|
+
}
|
|
925
|
+
/** `typeof x` / `typeof x.y` (TypeScript's type query) or `typeof(expr)`
|
|
926
|
+
* (Luau's spelling): the type of a value. */
|
|
927
|
+
interface TypeofTypeNode extends BaseNode {
|
|
928
|
+
type: "TypeofTypeNode";
|
|
929
|
+
expression: Expression;
|
|
930
|
+
}
|
|
931
|
+
interface VariadicTypeNode extends BaseNode {
|
|
932
|
+
type: "VariadicTypeNode";
|
|
933
|
+
typeAnnotation: TypeNode;
|
|
934
|
+
}
|
|
935
|
+
type Node = Program | Block | Statement | Expression | TypeNode | FunctionBody | FunctionParameter | FunctionName | IfClause | TypedIdentifier | GenericTypeParameter | FunctionSignature | TypePredicateNode | TableField | SpreadElement | FunctionTypeParameter | TableTypeProperty | BindingTarget | ObjectPatternProperty | ArrayPatternElement;
|
|
936
|
+
|
|
937
|
+
declare class ParseError extends Error {
|
|
938
|
+
line: number;
|
|
939
|
+
column: number;
|
|
940
|
+
constructor(message: string, line: number, column: number);
|
|
941
|
+
}
|
|
942
|
+
interface ParserOptions {
|
|
943
|
+
/** When true, `parseProgram` records syntax errors in `.errors` and
|
|
944
|
+
* synchronizes to the next statement boundary instead of throwing on the
|
|
945
|
+
* first one. The returned AST has an `ErrorStatement` wherever a statement
|
|
946
|
+
* could not be parsed. */
|
|
947
|
+
recover?: boolean;
|
|
948
|
+
/** Recovery only: read where a block ends from indentation when an `end`
|
|
949
|
+
* is missing — a line indented no deeper than the line that opened the
|
|
950
|
+
* block is past it. Valid code never needs this; `parseWithRecovery`
|
|
951
|
+
* reparses with it when the first pass found an `end` missing. */
|
|
952
|
+
indentation?: boolean;
|
|
953
|
+
}
|
|
954
|
+
declare function parse(source: string): Program;
|
|
955
|
+
declare function parseTokens(tokens: Token[]): Program;
|
|
956
|
+
/** `inClass` carries the enclosing class in. A template's `${...}` is parsed
|
|
957
|
+
* on its own, so without it a `super` written inside one in a class method
|
|
958
|
+
* would read as an ordinary name. */
|
|
959
|
+
declare function parseExpressionFromSource(raw: string, inClass?: boolean): Expression;
|
|
960
|
+
interface RecoverResult {
|
|
961
|
+
program: Program;
|
|
962
|
+
errors: ParseError[];
|
|
963
|
+
/** The file's `--@tilua-...` comments; see `applyDirectives`. */
|
|
964
|
+
directives: Directives;
|
|
965
|
+
}
|
|
966
|
+
/**
|
|
967
|
+
* Like `parse`, but never throws on a syntax error: it records every error and
|
|
968
|
+
* returns a best-effort AST. A broken expression becomes an `ErrorExpression`,
|
|
969
|
+
* a broken field or argument is skipped to the next `,`, a missing `)`, `}`,
|
|
970
|
+
* `then`, `do` or `end` is recorded and read past, and only what none of those
|
|
971
|
+
* cover becomes an `ErrorStatement`. A malformed token (an unclosed string) is
|
|
972
|
+
* an error too, and the rest of the file still lexes.
|
|
973
|
+
*
|
|
974
|
+
* This is the entry point a language server should use for open documents.
|
|
975
|
+
*/
|
|
976
|
+
declare function parseWithRecovery(source: string): RecoverResult;
|
|
977
|
+
|
|
978
|
+
type BindingId = number;
|
|
979
|
+
type BindingKind = "local" | "param" | "self" | "for-numeric" | "for-generic" | "global";
|
|
980
|
+
/** A node that can serve as a binding's "declared here" site. */
|
|
981
|
+
type DeclarationNode = Identifier | TypedIdentifier | FunctionParameter | IdentifierPattern;
|
|
982
|
+
interface Binding {
|
|
983
|
+
readonly id: BindingId;
|
|
984
|
+
/** Name at the point this binding was created. Rename passes update
|
|
985
|
+
* this and every node in `references` (+ `declarationNode`) together —
|
|
986
|
+
* this field is just what analysis saw, not a source of truth after a
|
|
987
|
+
* rename pass has run. */
|
|
988
|
+
name: string;
|
|
989
|
+
readonly kind: BindingKind;
|
|
990
|
+
/** Absent for a `global` binding that was never assigned to in this
|
|
991
|
+
* file (e.g. only ever read, or a pre-registered builtin). */
|
|
992
|
+
declarationNode?: DeclarationNode;
|
|
993
|
+
/** Every Identifier *usage* resolved to this binding (does not include
|
|
994
|
+
* `declarationNode` itself). */
|
|
995
|
+
readonly references: Identifier[];
|
|
996
|
+
/** True for globals pre-registered via `analyzeScopes`'s
|
|
997
|
+
* `builtinGlobals` option (e.g. `game`, `script`, `print`). Such
|
|
998
|
+
* bindings are never given a `declarationNode` from assignment
|
|
999
|
+
* inference, since they're not really "defined" in this file. */
|
|
1000
|
+
isBuiltin?: boolean;
|
|
1001
|
+
/** True for a binding that cannot be reassigned: a `const`, an import, or
|
|
1002
|
+
* a function declaration. */
|
|
1003
|
+
isConst?: boolean;
|
|
1004
|
+
/** Set when the binding comes from something other than `const` / `let`,
|
|
1005
|
+
* which is also what an error about reassigning it names. */
|
|
1006
|
+
declaredBy?: "import" | "namespace" | "function" | "type" | "class";
|
|
1007
|
+
}
|
|
1008
|
+
interface ScopeDiagnostic {
|
|
1009
|
+
/** the offending node (redeclaration site, or assignment target) */
|
|
1010
|
+
node: {
|
|
1011
|
+
line: {
|
|
1012
|
+
start: number;
|
|
1013
|
+
end: number;
|
|
1014
|
+
};
|
|
1015
|
+
column: {
|
|
1016
|
+
start: number;
|
|
1017
|
+
end: number;
|
|
1018
|
+
};
|
|
1019
|
+
};
|
|
1020
|
+
message: string;
|
|
1021
|
+
kind: "redeclare" | "const-assign" | "type-only" | "undeclared" | "use-before-define";
|
|
1022
|
+
}
|
|
1023
|
+
interface ScopeAnalysis {
|
|
1024
|
+
/** Every Identifier that appears in a variable *usage* position (i.e.
|
|
1025
|
+
* every node also reachable through some `Binding.references`, plus
|
|
1026
|
+
* `FunctionDeclarationStatement.target.base`), mapped to its binding.
|
|
1027
|
+
* Property names, method names, table field names, and type-position
|
|
1028
|
+
* identifiers are never entered here — they aren't variable refs. */
|
|
1029
|
+
readonly bindingOf: Map<Identifier | IdentifierPattern, BindingId>;
|
|
1030
|
+
readonly bindings: Map<BindingId, Binding>;
|
|
1031
|
+
/** Redeclaration-in-same-scope and assignment-to-const errors. */
|
|
1032
|
+
readonly diagnostics: ScopeDiagnostic[];
|
|
1033
|
+
/** Convenience: every global binding's id, keyed by name. Global
|
|
1034
|
+
* bindings have no lexical scope, so this is the closest thing to
|
|
1035
|
+
* "the" scope for them — and later a multi-file language server can
|
|
1036
|
+
* swap this map out for a project-wide registry without changing
|
|
1037
|
+
* anything else about this shape. */
|
|
1038
|
+
readonly globalsByName: Map<string, BindingId>;
|
|
1039
|
+
}
|
|
1040
|
+
interface AnalyzeScopesOptions {
|
|
1041
|
+
/** Names to pre-register as global bindings with `isBuiltin: true`
|
|
1042
|
+
* before the walk starts (e.g. Roblox/Luau standard globals:
|
|
1043
|
+
* `game`, `script`, `workspace`, `print`, `pairs`, ...). Referencing
|
|
1044
|
+
* one of these does not count as "defining" it, so `declarationNode`
|
|
1045
|
+
* is left unset even though the binding exists up front. */
|
|
1046
|
+
builtinGlobals?: readonly string[];
|
|
1047
|
+
/** Report each read of a name nothing declares — not a local, not one of
|
|
1048
|
+
* `builtinGlobals`, not `declare`d in the file, never assigned as a
|
|
1049
|
+
* global: "Cannot find name 'x'", as TypeScript says. Only meaningful
|
|
1050
|
+
* when `builtinGlobals` lists everything the file's type libraries
|
|
1051
|
+
* declare, so it is off unless asked for. */
|
|
1052
|
+
reportUndeclared?: boolean;
|
|
1053
|
+
}
|
|
1054
|
+
declare function getBinding(analysis: ScopeAnalysis, id: Identifier | IdentifierPattern): Binding | undefined;
|
|
1055
|
+
declare function isGlobal(binding: Binding): boolean;
|
|
1056
|
+
/** True if a global binding was never assigned to anywhere in this file
|
|
1057
|
+
* (and isn't a pre-registered builtin) — i.e. it's read-only and
|
|
1058
|
+
* undeclared, which is almost always a typo rather than an intentional
|
|
1059
|
+
* implicit global. Handy for a "possibly undefined global" diagnostic. */
|
|
1060
|
+
declare function isUnassignedGlobal(binding: Binding): boolean;
|
|
1061
|
+
declare function analyzeScopes(program: Program, options?: AnalyzeScopesOptions): ScopeAnalysis;
|
|
1062
|
+
|
|
1063
|
+
type Type = AnyType | UnknownType | NeverType | PrimitiveType | LiteralType | ArrayType | TupleType | ObjectType | FunctionType | UnionType | IntersectionType | TypeParamType | GenericRefType | KeyofType | IndexedAccessType | ConditionalType | InferType | MappedType | TemplateLiteralType | DifferenceType;
|
|
1064
|
+
/** `any` — opts out of checking. Assignable to and from everything. */
|
|
1065
|
+
interface AnyType {
|
|
1066
|
+
kind: "any";
|
|
1067
|
+
alias?: string;
|
|
1068
|
+
}
|
|
1069
|
+
/** `unknown` — top type. Everything is assignable to it; it is assignable to nothing but itself. */
|
|
1070
|
+
interface UnknownType {
|
|
1071
|
+
kind: "unknown";
|
|
1072
|
+
alias?: string;
|
|
1073
|
+
/** The `unknown` a program wrote, as opposed to the one the analyzer falls
|
|
1074
|
+
* back to when it cannot work a type out. Only a written one makes reading
|
|
1075
|
+
* a member of it an error — the fallback means "not known here", and
|
|
1076
|
+
* reporting that would be noise. */
|
|
1077
|
+
declared?: boolean;
|
|
1078
|
+
}
|
|
1079
|
+
/** `never` — bottom type. Assignable to everything; nothing (but never) is assignable to it. */
|
|
1080
|
+
interface NeverType {
|
|
1081
|
+
kind: "never";
|
|
1082
|
+
alias?: string;
|
|
1083
|
+
}
|
|
1084
|
+
type PrimitiveName = "nil" | "boolean" | "number" | "string" | "thread" | "buffer";
|
|
1085
|
+
interface PrimitiveType {
|
|
1086
|
+
kind: "primitive";
|
|
1087
|
+
name: PrimitiveName;
|
|
1088
|
+
alias?: string;
|
|
1089
|
+
}
|
|
1090
|
+
/** `"foo"`, `42`, `true` — a single-valued type. `base` is the primitive it widens to. */
|
|
1091
|
+
interface LiteralType {
|
|
1092
|
+
kind: "literal";
|
|
1093
|
+
base: "boolean" | "number" | "string";
|
|
1094
|
+
value: string | number | boolean;
|
|
1095
|
+
alias?: string;
|
|
1096
|
+
}
|
|
1097
|
+
/** `T[]` */
|
|
1098
|
+
interface ArrayType {
|
|
1099
|
+
kind: "array";
|
|
1100
|
+
element: Type;
|
|
1101
|
+
alias?: string;
|
|
1102
|
+
}
|
|
1103
|
+
/** `[A, B, C]` — fixed length.
|
|
1104
|
+
*
|
|
1105
|
+
* `isPack` marks the other thing this shape is used for: a *type pack*, the
|
|
1106
|
+
* several values a Lua function returns (`(number, string)`). The two are
|
|
1107
|
+
* structurally identical but behave differently in an expression list — a
|
|
1108
|
+
* pack spreads across several names, a tuple is one value — so they have to
|
|
1109
|
+
* be told apart. */
|
|
1110
|
+
interface TupleType {
|
|
1111
|
+
kind: "tuple";
|
|
1112
|
+
elements: Type[];
|
|
1113
|
+
isPack?: boolean;
|
|
1114
|
+
alias?: string;
|
|
1115
|
+
}
|
|
1116
|
+
interface ObjectProperty {
|
|
1117
|
+
type: Type;
|
|
1118
|
+
optional: boolean;
|
|
1119
|
+
readonly?: boolean;
|
|
1120
|
+
}
|
|
1121
|
+
interface ObjectType {
|
|
1122
|
+
kind: "object";
|
|
1123
|
+
properties: Map<string, ObjectProperty>;
|
|
1124
|
+
/** `{ [K]: V }` catch-all, if present. */
|
|
1125
|
+
indexer?: {
|
|
1126
|
+
key: Type;
|
|
1127
|
+
value: Type;
|
|
1128
|
+
};
|
|
1129
|
+
/** `object` was produced by `as const` — literal members are kept narrow
|
|
1130
|
+
* and every property is `readonly`. */
|
|
1131
|
+
frozen?: boolean;
|
|
1132
|
+
/** The alias this object was resolved from — display only, ignored by
|
|
1133
|
+
* `isAssignable` (the type is structural). Dropped on `widen`/`substitute`. */
|
|
1134
|
+
name?: string;
|
|
1135
|
+
/** Set on a `declare class` — the type is then *nominal*. See `ClassInfo`. */
|
|
1136
|
+
class?: ClassInfo;
|
|
1137
|
+
}
|
|
1138
|
+
/** What makes an object a class instance. `properties` then holds every
|
|
1139
|
+
* member, inherited ones included. Only the class itself and the classes
|
|
1140
|
+
* extending it are assignable to it — no table literal, no structurally
|
|
1141
|
+
* identical class. Going the other way, a class satisfies a shape naming
|
|
1142
|
+
* members it has (`{ Name: string }`) but is not a table: never a
|
|
1143
|
+
* `{ [K]: V }` or `{}`, which is what keeps `typeof(part)` from matching the
|
|
1144
|
+
* `{ [unknown]: unknown }` overload. */
|
|
1145
|
+
interface ClassInfo {
|
|
1146
|
+
name: string;
|
|
1147
|
+
/** The class it directly extends, if any. */
|
|
1148
|
+
superclass?: string;
|
|
1149
|
+
/** The class itself, then each class it extends, nearest first. */
|
|
1150
|
+
ancestors: readonly string[];
|
|
1151
|
+
/** For a generic class, the arguments each level of the chain was made
|
|
1152
|
+
* with, by class name — its own and every class it extends. `Box<number>`
|
|
1153
|
+
* holds `{ Box: [number] }`, and a `class Ints extends Box<number>` holds
|
|
1154
|
+
* the same entry under `Box`, which is what tells it apart from a
|
|
1155
|
+
* `Box<string>`. A class with no type parameters anywhere carries
|
|
1156
|
+
* nothing, and costs nothing. */
|
|
1157
|
+
typeArguments?: ReadonlyMap<string, readonly Type[]>;
|
|
1158
|
+
}
|
|
1159
|
+
declare function isClassType(t: Type): t is ObjectType & {
|
|
1160
|
+
class: ClassInfo;
|
|
1161
|
+
};
|
|
1162
|
+
interface FunctionParam {
|
|
1163
|
+
name?: string;
|
|
1164
|
+
type: Type;
|
|
1165
|
+
optional?: boolean;
|
|
1166
|
+
}
|
|
1167
|
+
/** A TS-style type guard: `function f(v: unknown): v is string` narrows `v` at
|
|
1168
|
+
* every call site used as a condition. `asserts` variants narrow the *rest of
|
|
1169
|
+
* the enclosing block* instead of a branch (`assert(x)`), and a missing `type`
|
|
1170
|
+
* means a bare truthiness assertion (`asserts v`). */
|
|
1171
|
+
interface TypePredicate {
|
|
1172
|
+
/** Index into `params` of the parameter this guard talks about. */
|
|
1173
|
+
param: number;
|
|
1174
|
+
/** The type the parameter is narrowed to; absent = narrow to truthy. */
|
|
1175
|
+
type?: Type;
|
|
1176
|
+
asserts: boolean;
|
|
1177
|
+
}
|
|
1178
|
+
interface FunctionType {
|
|
1179
|
+
kind: "function";
|
|
1180
|
+
params: FunctionParam[];
|
|
1181
|
+
varargs?: Type;
|
|
1182
|
+
/** A tuple when the function returns multiple values. */
|
|
1183
|
+
returns: Type;
|
|
1184
|
+
/** Names of the function's own generic parameters (`function f<T>(...)`).
|
|
1185
|
+
* `params` / `returns` may contain `typeParam` nodes for these. */
|
|
1186
|
+
typeParams?: string[];
|
|
1187
|
+
/** `<T = Instance>` — what a call uses for a parameter it is not given and
|
|
1188
|
+
* cannot infer. */
|
|
1189
|
+
typeParamDefaults?: Record<string, Type>;
|
|
1190
|
+
/** Set when the function was declared with an `x is T` / `asserts x` return. */
|
|
1191
|
+
predicate?: TypePredicate;
|
|
1192
|
+
alias?: string;
|
|
1193
|
+
}
|
|
1194
|
+
/** A bound generic parameter (`T` inside `function f<T>(...)` or
|
|
1195
|
+
* `type Box<T> = ...`). Resolved away by `substitute` at instantiation.
|
|
1196
|
+
* `constraint` is the `<T extends C>` upper bound, used for member access on a
|
|
1197
|
+
* bare `T` and as the fallback when `T` can't be inferred. */
|
|
1198
|
+
interface TypeParamType {
|
|
1199
|
+
kind: "typeParam";
|
|
1200
|
+
name: string;
|
|
1201
|
+
constraint?: Type;
|
|
1202
|
+
/** Declared `<const T>`: the call site infers the argument at its
|
|
1203
|
+
* narrowest rather than widening it. */
|
|
1204
|
+
isConst?: boolean;
|
|
1205
|
+
}
|
|
1206
|
+
declare function typeParam(name: string, constraint?: Type, isConst?: boolean): TypeParamType;
|
|
1207
|
+
interface UnionType {
|
|
1208
|
+
kind: "union";
|
|
1209
|
+
types: Type[];
|
|
1210
|
+
alias?: string;
|
|
1211
|
+
}
|
|
1212
|
+
interface IntersectionType {
|
|
1213
|
+
kind: "intersection";
|
|
1214
|
+
types: Type[];
|
|
1215
|
+
/** The alias this was resolved from — display only, exactly like
|
|
1216
|
+
* `ObjectType.name`. A class hierarchy written as `type Part = BasePart &
|
|
1217
|
+
* { ... }` is unreadable without it. */
|
|
1218
|
+
name?: string;
|
|
1219
|
+
}
|
|
1220
|
+
/** An unresolved reference: an in-scope generic parameter, or a named type
|
|
1221
|
+
* that couldn't be resolved to an alias in this pass. */
|
|
1222
|
+
interface GenericRefType {
|
|
1223
|
+
kind: "genericRef";
|
|
1224
|
+
name: string;
|
|
1225
|
+
typeArguments: Type[];
|
|
1226
|
+
}
|
|
1227
|
+
/** `keyof T`. */
|
|
1228
|
+
interface KeyofType {
|
|
1229
|
+
kind: "keyof";
|
|
1230
|
+
target: Type;
|
|
1231
|
+
}
|
|
1232
|
+
/** `T[K]`. */
|
|
1233
|
+
interface IndexedAccessType {
|
|
1234
|
+
kind: "indexedAccess";
|
|
1235
|
+
objectType: Type;
|
|
1236
|
+
indexType: Type;
|
|
1237
|
+
}
|
|
1238
|
+
/** `C extends E ? A : B`. */
|
|
1239
|
+
interface ConditionalType {
|
|
1240
|
+
kind: "conditional";
|
|
1241
|
+
checkType: Type;
|
|
1242
|
+
extendsType: Type;
|
|
1243
|
+
trueType: Type;
|
|
1244
|
+
falseType: Type;
|
|
1245
|
+
/** Names bound by `infer` inside `extendsType`. */
|
|
1246
|
+
inferVars: string[];
|
|
1247
|
+
/** Set when `checkType` is a *naked* type parameter, to that parameter's
|
|
1248
|
+
* name. Such a conditional distributes over a union, and inside each
|
|
1249
|
+
* branch the parameter denotes the single member being tested — the
|
|
1250
|
+
* property `Exclude<T, U>` relies on. */
|
|
1251
|
+
distributeParam?: string;
|
|
1252
|
+
}
|
|
1253
|
+
/** `infer U`, valid only inside a conditional's `extends` clause. */
|
|
1254
|
+
interface InferType {
|
|
1255
|
+
kind: "infer";
|
|
1256
|
+
name: string;
|
|
1257
|
+
}
|
|
1258
|
+
/** `A - B` — every value of `A` that is not a `B`.
|
|
1259
|
+
*
|
|
1260
|
+
* Only kept when `A` is *opaque*: `unknown`, or a type parameter or nominal
|
|
1261
|
+
* reference not yet resolved. For a union the subtraction is performed by
|
|
1262
|
+
* dropping members, and for a concrete type such as `string` it is discarded
|
|
1263
|
+
* (`string - "a"` supports exactly the same operations as `string`, and
|
|
1264
|
+
* TypeScript likewise does not track it). For `unknown`, though, the
|
|
1265
|
+
* subtraction is the *only* thing known about the value, so throwing it away
|
|
1266
|
+
* loses the whole result of the test:
|
|
1267
|
+
*
|
|
1268
|
+
* let a: unknown
|
|
1269
|
+
* if a == 1 then -- a: 1
|
|
1270
|
+
* else -- a: unknown - 1
|
|
1271
|
+
* end
|
|
1272
|
+
*/
|
|
1273
|
+
interface DifferenceType {
|
|
1274
|
+
kind: "difference";
|
|
1275
|
+
base: Type;
|
|
1276
|
+
excluded: Type;
|
|
1277
|
+
}
|
|
1278
|
+
/** `` `on${string}` `` — literal chunks interleaved with interpolated types
|
|
1279
|
+
* (`quasis.length === types.length + 1`). Reduced to a union of string
|
|
1280
|
+
* literals when every interpolation is one; otherwise it stays a *pattern*
|
|
1281
|
+
* and `isAssignable` matches literal strings against it. */
|
|
1282
|
+
interface TemplateLiteralType {
|
|
1283
|
+
kind: "templateLiteral";
|
|
1284
|
+
quasis: string[];
|
|
1285
|
+
types: Type[];
|
|
1286
|
+
alias?: string;
|
|
1287
|
+
}
|
|
1288
|
+
/** The alias `type` is printed as instead of its structure, if it has one. */
|
|
1289
|
+
declare function aliasNameOf(type: Type): string | undefined;
|
|
1290
|
+
/** The same type, printed as what it is made of. */
|
|
1291
|
+
declare function withoutAliasName(type: Type): Type;
|
|
1292
|
+
/** `type` remembered as the alias it was written as. A type that already
|
|
1293
|
+
* carries one keeps it: the name nearest what the reader wrote wins. */
|
|
1294
|
+
declare function withAliasName(type: Type, alias: string): Type;
|
|
1295
|
+
/** `{ [K in C]: V }`. `optional` / `readonly`: `true` adds the modifier,
|
|
1296
|
+
* `false` strips it, `undefined` inherits it from the source property. */
|
|
1297
|
+
interface MappedType {
|
|
1298
|
+
kind: "mapped";
|
|
1299
|
+
parameter: string;
|
|
1300
|
+
constraint: Type;
|
|
1301
|
+
nameType?: Type;
|
|
1302
|
+
template: Type;
|
|
1303
|
+
optional?: boolean;
|
|
1304
|
+
readonly?: boolean;
|
|
1305
|
+
/** The `T` of `[K in keyof T]`, kept so a homomorphic mapped type can carry
|
|
1306
|
+
* each source property's own `?` / `readonly` across. */
|
|
1307
|
+
source?: Type;
|
|
1308
|
+
}
|
|
1309
|
+
declare const anyType: AnyType;
|
|
1310
|
+
declare const unknownType: UnknownType;
|
|
1311
|
+
declare const declaredUnknownType: UnknownType;
|
|
1312
|
+
declare const neverType: NeverType;
|
|
1313
|
+
declare const nilType: PrimitiveType;
|
|
1314
|
+
declare const booleanType: PrimitiveType;
|
|
1315
|
+
declare const numberType: PrimitiveType;
|
|
1316
|
+
declare const stringType: PrimitiveType;
|
|
1317
|
+
declare const threadType: PrimitiveType;
|
|
1318
|
+
declare const bufferType: PrimitiveType;
|
|
1319
|
+
declare function primitive(name: PrimitiveName): PrimitiveType;
|
|
1320
|
+
declare function literal(value: string | number | boolean): LiteralType;
|
|
1321
|
+
declare function arrayOf(element: Type): ArrayType;
|
|
1322
|
+
declare function tuple(elements: Type[], isPack?: boolean): TupleType;
|
|
1323
|
+
declare function objectType(entries: Iterable<[string, ObjectProperty]>, indexer?: ObjectType["indexer"], frozen?: boolean): ObjectType;
|
|
1324
|
+
declare function fn(params: FunctionParam[], returns: Type, varargs?: Type, typeParams?: string[], predicate?: TypePredicate): FunctionType;
|
|
1325
|
+
declare function substitute(t: Type, subst: Map<string, Type>): Type;
|
|
1326
|
+
declare function unify(param: Type, arg: Type, vars: Set<string>, out: Map<string, Type>): void;
|
|
1327
|
+
declare function union(types: Type[]): Type;
|
|
1328
|
+
declare function intersection(types: Type[]): Type;
|
|
1329
|
+
/** `base - excluded`, simplified as far as the base allows. */
|
|
1330
|
+
declare function difference(base: Type, excluded: Type): Type;
|
|
1331
|
+
/** `T | nil` — the type of an optional property or parameter. */
|
|
1332
|
+
declare function optional(t: Type): Type;
|
|
1333
|
+
/** Widens literal types to their primitive base (the default for a plain
|
|
1334
|
+
* `local x = "foo"` binding, unless `as const` says otherwise). Recurses
|
|
1335
|
+
* into arrays/tuples/objects/unions. */
|
|
1336
|
+
declare function widen(t: Type): Type;
|
|
1337
|
+
declare function setAliasExpander(fn: ((t: GenericRefType) => Type) | undefined): void;
|
|
1338
|
+
declare function setDeferredBound(fn: ((t: Type) => Type | undefined) | undefined): void;
|
|
1339
|
+
declare function isAssignable(rawA: Type, rawB: Type): boolean;
|
|
1340
|
+
declare function equalTypes(a: Type, b: Type): boolean;
|
|
1341
|
+
/** Keep the parts of `t` compatible with `filter` — TypeScript's
|
|
1342
|
+
* `getNarrowedType`. Per union member: a member already assignable to the
|
|
1343
|
+
* filter survives as-is; a member the filter is assignable to is *replaced*
|
|
1344
|
+
* by the filter (so `string` narrowed by `"a"` becomes `"a"`, not `string`);
|
|
1345
|
+
* anything else is dropped. `any` / `unknown` narrow straight to the filter. */
|
|
1346
|
+
declare function narrowTo(t: Type, filter: Type): Type;
|
|
1347
|
+
/** Remove the parts of `t` assignable to `exclude` (the `else` branch).
|
|
1348
|
+
* `boolean` minus a `true`/`false` literal leaves the other literal — the
|
|
1349
|
+
* only primitive here with a finite, enumerable domain. */
|
|
1350
|
+
declare function narrowExclude(t: Type, exclude: Type): Type;
|
|
1351
|
+
/** `nil | false` — every falsy value in Luau. Built literally rather than via
|
|
1352
|
+
* `union()`, which would format its members for deduping and so touch caches
|
|
1353
|
+
* declared further down this module. */
|
|
1354
|
+
declare const falsyType: Type;
|
|
1355
|
+
/** Can a value of this type ever be truthy? */
|
|
1356
|
+
declare function isPossiblyTruthy(t: Type): boolean;
|
|
1357
|
+
/** Can a value of this type ever be falsy? */
|
|
1358
|
+
declare function isPossiblyFalsy(t: Type): boolean;
|
|
1359
|
+
/** Keep only what can be truthy — drops `nil` and the `false` literal, and
|
|
1360
|
+
* narrows a bare `boolean` to `true`. */
|
|
1361
|
+
declare function narrowTruthy(t: Type): Type;
|
|
1362
|
+
/** Keep only what can be falsy — `nil` and `false`. */
|
|
1363
|
+
declare function narrowFalsy(t: Type): Type;
|
|
1364
|
+
declare function containsTypeParam(t: Type, seen?: Set<Type>, bound?: Set<string>): boolean;
|
|
1365
|
+
/** Structurally match `arg` against `pattern`, binding every `infer` name it
|
|
1366
|
+
* contains into `out`. This is what turns `T extends (...unknown) -> infer R`
|
|
1367
|
+
* into `R = <the return type>`. Returns false when the shapes cannot match at
|
|
1368
|
+
* all; a `true` result still needs the usual assignability check. */
|
|
1369
|
+
declare function matchInfer(arg: Type, pattern: Type, out: Map<string, Type>): boolean;
|
|
1370
|
+
/** Does a concrete string match a template literal *pattern*? Each
|
|
1371
|
+
* interpolation is matched against the widest thing it could stand for:
|
|
1372
|
+
* `string` swallows any run, `number` a numeric run, and a literal union only
|
|
1373
|
+
* its own members. Anchored at both ends, like TypeScript. */
|
|
1374
|
+
declare function templateMatches(value: string, pattern: TemplateLiteralType): boolean;
|
|
1375
|
+
/** Do these two types share any value? The compatibility test behind
|
|
1376
|
+
* discriminant filtering and `narrowTo`. */
|
|
1377
|
+
declare function overlaps(a: Type, b: Type): boolean;
|
|
1378
|
+
declare function formatType(t: Type): string;
|
|
1379
|
+
|
|
1380
|
+
interface TypeDiagnostic {
|
|
1381
|
+
/** Usually an expression or statement; a type where the type is wrong
|
|
1382
|
+
* (`declare class A extends NotAClass`), or a block where nothing in it
|
|
1383
|
+
* is to blame (a function that never returns). Only its span is read. */
|
|
1384
|
+
node: Expression | Statement | TypeNode | Block | ClassMember;
|
|
1385
|
+
message: string;
|
|
1386
|
+
}
|
|
1387
|
+
interface TypeAnalysis {
|
|
1388
|
+
/** Inferred type of every expression node. */
|
|
1389
|
+
readonly typeOf: Map<Expression, Type>;
|
|
1390
|
+
/** Declared (or first-inferred) type of every value binding. */
|
|
1391
|
+
readonly bindingType: Map<BindingId, Type>;
|
|
1392
|
+
/** Type of a specific variable *reference*, after flow narrowing at that
|
|
1393
|
+
* point. For an un-narrowed reference this equals `bindingType`. */
|
|
1394
|
+
readonly narrowedTypeOf: Map<Identifier, Type>;
|
|
1395
|
+
/** What every type annotation node resolves to — `number`, `Shape`,
|
|
1396
|
+
* `typeof x`, a property's type inside `{ ... }`. Inside a generic alias or
|
|
1397
|
+
* function its parameters stay unresolved (`T`). */
|
|
1398
|
+
readonly typeOfTypeNode: Map<TypeNode | TypePackNode, Type>;
|
|
1399
|
+
/** What each call argument is expected to be: the parameter it lands on,
|
|
1400
|
+
* with the signature's type parameters replaced by their constraints — a
|
|
1401
|
+
* union when an overload set disagrees. Recorded even for a call that does
|
|
1402
|
+
* not type-check, since that is exactly when an editor wants to offer the
|
|
1403
|
+
* values that would. */
|
|
1404
|
+
readonly expectedTypeOf: Map<Expression, Type>;
|
|
1405
|
+
/** Top-level type aliases, resolved — and the type names this module
|
|
1406
|
+
* imports, so tooling treats both alike. */
|
|
1407
|
+
readonly aliases: Map<string, Type>;
|
|
1408
|
+
readonly diagnostics: TypeDiagnostic[];
|
|
1409
|
+
}
|
|
1410
|
+
/** A type a module exports: the resolved type, plus the parameter names of a
|
|
1411
|
+
* generic alias so an importer can instantiate it (`Box<number>`). */
|
|
1412
|
+
interface ExportedType {
|
|
1413
|
+
readonly type: Type;
|
|
1414
|
+
readonly params: readonly string[];
|
|
1415
|
+
}
|
|
1416
|
+
/** What a module makes available to `import`. See `moduleExports`. */
|
|
1417
|
+
interface ModuleExports {
|
|
1418
|
+
/** `export const` / `export let` / `export function` names. */
|
|
1419
|
+
readonly values: ReadonlyMap<string, Type>;
|
|
1420
|
+
/** `export type` names. */
|
|
1421
|
+
readonly types: ReadonlyMap<string, ExportedType>;
|
|
1422
|
+
/** `export default <expr>`. */
|
|
1423
|
+
readonly default?: Type;
|
|
1424
|
+
/** The module is still being analyzed further up an import cycle. Its
|
|
1425
|
+
* names read as `any`, and nothing about them is reported. */
|
|
1426
|
+
readonly partial?: boolean;
|
|
1427
|
+
}
|
|
1428
|
+
interface AnalyzeTypesOptions {
|
|
1429
|
+
/** Types for pre-registered globals (`analyzeScopes`'s `builtinGlobals`).
|
|
1430
|
+
* Anything not listed is treated as `any`. Overrides `libs`. */
|
|
1431
|
+
globalTypes?: Record<string, Type>;
|
|
1432
|
+
/** Extra named types available to annotations (e.g. Roblox classes). */
|
|
1433
|
+
libTypes?: Record<string, Type>;
|
|
1434
|
+
/** Parsed definitions files (`.d.tilua`): their `type` aliases become
|
|
1435
|
+
* available to annotations and their `declare` statements seed global
|
|
1436
|
+
* types. A project lists them under `types` in `tilua.config.json`; see
|
|
1437
|
+
* `resolveTypeLibraries`. */
|
|
1438
|
+
libs?: readonly Program[];
|
|
1439
|
+
/** Resolve an `import`'s module path to what that module exports. Called
|
|
1440
|
+
* once per distinct path. Return `undefined` when there is no such module:
|
|
1441
|
+
* the import is reported and its names are `any`. Without this option
|
|
1442
|
+
* every import is `any` — a single file cannot know better. */
|
|
1443
|
+
resolveModule?: (specifier: string) => ModuleExports | undefined;
|
|
1444
|
+
/** Emit assignability diagnostics (default: true). */
|
|
1445
|
+
diagnostics?: boolean;
|
|
1446
|
+
/** Report each type name nothing declares: "Cannot find name 'Nope'".
|
|
1447
|
+
* Only meaningful when `libs` holds everything the file can name, so it
|
|
1448
|
+
* is off unless asked for — exactly like `analyzeScopes`'s
|
|
1449
|
+
* `reportUndeclared`. */
|
|
1450
|
+
reportUnknownTypes?: boolean;
|
|
1451
|
+
}
|
|
1452
|
+
declare function analyzeTypes(program: Program, scopes: ScopeAnalysis, options?: AnalyzeTypesOptions): TypeAnalysis;
|
|
1453
|
+
/** The exports of an analyzed module, in the shape another module's
|
|
1454
|
+
* `resolveModule` returns. */
|
|
1455
|
+
declare function moduleExports(program: Program, scopes: ScopeAnalysis, types: TypeAnalysis,
|
|
1456
|
+
/** For `export ... from`: the same resolver the module was analyzed with. */
|
|
1457
|
+
resolveModule?: (specifier: string) => ModuleExports | undefined): ModuleExports;
|
|
1458
|
+
|
|
1459
|
+
/**
|
|
1460
|
+
* The types that belong to the language itself, available in every file with
|
|
1461
|
+
* or without a type library — as TypeScript's `Partial` and `ReturnType` are.
|
|
1462
|
+
*
|
|
1463
|
+
* They are written in tilua on top of `keyof`, `T[K]`, conditional types with
|
|
1464
|
+
* `infer`, mapped types and set difference; the analyzer knows none of these
|
|
1465
|
+
* names. A type library or the file itself may declare one of them again, and
|
|
1466
|
+
* that declaration wins.
|
|
1467
|
+
*
|
|
1468
|
+
* What a runtime provides — `print`, `string`, `game` — is not here: that is a
|
|
1469
|
+
* type library's job (`@tilua-types/lua`, `@tilua-types/roblox`).
|
|
1470
|
+
*
|
|
1471
|
+
* The methods an array and a string answer to — `names:filter(f)`,
|
|
1472
|
+
* `text:trim()` — are a library's too. `propertyType` reads them from types
|
|
1473
|
+
* named `ArrayMethods<T>` and `StringMethods`, whichever library declares
|
|
1474
|
+
* those; the library also says which of them the compiler must emit code for
|
|
1475
|
+
* (`tilua.methods` in its package.json). Nothing about `filter` is written
|
|
1476
|
+
* into the analyzer.
|
|
1477
|
+
*/
|
|
1478
|
+
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 (...unknown) => infer R ? R : never\ntype Parameters<T> = T extends (...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";
|
|
1479
|
+
|
|
1480
|
+
interface ProjectHost {
|
|
1481
|
+
/** A file's text, or `undefined` when there is no such file. */
|
|
1482
|
+
readFile(path: string): string | undefined;
|
|
1483
|
+
}
|
|
1484
|
+
declare const nodeHost: ProjectHost;
|
|
1485
|
+
|
|
1486
|
+
declare const CONFIG_FILE_NAMES: readonly ["tilua.config.json", "tilua.config.jsonc"];
|
|
1487
|
+
interface TiluaConfig {
|
|
1488
|
+
/** Absolute path of the config file. */
|
|
1489
|
+
readonly path: string;
|
|
1490
|
+
/** The folder it sits in. Relative paths in it resolve from here. */
|
|
1491
|
+
readonly directory: string;
|
|
1492
|
+
/** The config file's text, for locating problems in it. */
|
|
1493
|
+
readonly source: string;
|
|
1494
|
+
/** Type libraries to load, in order: `"lua"`, `"@tilua-types/roblox"`, `"./types"`. */
|
|
1495
|
+
readonly types: readonly string[];
|
|
1496
|
+
/** Import path aliases, as in tsconfig: `{ "@shared/*": ["src/shared/*"] }`. */
|
|
1497
|
+
readonly paths: Readonly<Record<string, readonly string[]>>;
|
|
1498
|
+
/** Where `paths` targets resolve from, absolute. The config's folder unless set. */
|
|
1499
|
+
readonly baseUrl: string;
|
|
1500
|
+
/** Absolute path of a Rojo sourcemap, or `null` for none. */
|
|
1501
|
+
readonly sourceMap: string | null;
|
|
1502
|
+
/** Which Lua the compiler must emit for. `"luau"` (the default) keeps
|
|
1503
|
+
* Luau's own syntax; `"lua51"` also lowers what stock Lua 5.1 has no
|
|
1504
|
+
* syntax for. The parser does not care — it is the compiler's to act on,
|
|
1505
|
+
* and lives here because it belongs to the project. */
|
|
1506
|
+
readonly target: BuildTarget;
|
|
1507
|
+
}
|
|
1508
|
+
/** `"luau"` is Roblox's Lua. `"lua51"` is stock Lua 5.1. */
|
|
1509
|
+
type BuildTarget = "luau" | "lua51";
|
|
1510
|
+
interface ConfigProblem {
|
|
1511
|
+
/** The file the problem is about: a config file, or a sourcemap it names. */
|
|
1512
|
+
readonly file: string;
|
|
1513
|
+
readonly message: string;
|
|
1514
|
+
/** 1-based position in `file`, when the problem has one. */
|
|
1515
|
+
readonly line?: number;
|
|
1516
|
+
readonly column?: number;
|
|
1517
|
+
}
|
|
1518
|
+
interface ConfigLookup {
|
|
1519
|
+
/** The config that applies, if one was found and could be read. */
|
|
1520
|
+
readonly config?: TiluaConfig;
|
|
1521
|
+
readonly problems: readonly ConfigProblem[];
|
|
1522
|
+
/** Every config path looked at on the way up, found or not — what a cache
|
|
1523
|
+
* must watch, so that creating or deleting a config is noticed. */
|
|
1524
|
+
readonly searched: readonly string[];
|
|
1525
|
+
}
|
|
1526
|
+
/** The config that applies to `file`: the nearest one in its folder or above. */
|
|
1527
|
+
declare function findConfig(file: string, host?: ProjectHost): ConfigLookup;
|
|
1528
|
+
/** Read and check one config file. Problems do not stop the rest of it from
|
|
1529
|
+
* applying: an unknown option is reported and the known ones still work. */
|
|
1530
|
+
declare function loadConfig(path: string, host?: ProjectHost): {
|
|
1531
|
+
config?: TiluaConfig;
|
|
1532
|
+
problems: ConfigProblem[];
|
|
1533
|
+
};
|
|
1534
|
+
/** Blank out `//` and `/* *\/` comments and trailing commas, keeping every
|
|
1535
|
+
* other character where it was — so a JSON error's position still points
|
|
1536
|
+
* into the original text. */
|
|
1537
|
+
declare function stripJsonComments(text: string): string;
|
|
1538
|
+
|
|
1539
|
+
interface TypeLibraries {
|
|
1540
|
+
/** Definitions files, dependencies before what depends on them. */
|
|
1541
|
+
readonly files: readonly string[];
|
|
1542
|
+
/** Lowering modules the libraries ship, in the same order. */
|
|
1543
|
+
readonly lowerings: readonly LoweringModule[];
|
|
1544
|
+
readonly problems: readonly ConfigProblem[];
|
|
1545
|
+
}
|
|
1546
|
+
/** A library's own lowering: JavaScript the compiler loads and asks what a
|
|
1547
|
+
* call written against this library's types should become.
|
|
1548
|
+
*
|
|
1549
|
+
* The library declares the *types* in its definitions file; this is the other
|
|
1550
|
+
* half. `names:filter(f)` is a call to a function only because `@tilua-types/lua`
|
|
1551
|
+
* says so and ships the Luau behind it — the compiler knows how to ask, and
|
|
1552
|
+
* nothing about `filter`.
|
|
1553
|
+
*
|
|
1554
|
+
* `tilua.lowering` in the package.json names the module; what it must export
|
|
1555
|
+
* is the compiler's business (see @tilua/compiler's `LoweringPlugin`). */
|
|
1556
|
+
interface LoweringModule {
|
|
1557
|
+
/** The JavaScript module to load. */
|
|
1558
|
+
readonly file: string;
|
|
1559
|
+
/** The package it came from, for reporting. */
|
|
1560
|
+
readonly from: string;
|
|
1561
|
+
}
|
|
1562
|
+
declare function resolveTypeLibraries(config: TiluaConfig, host?: ProjectHost): TypeLibraries;
|
|
1563
|
+
|
|
1564
|
+
/**
|
|
1565
|
+
* The contract between a type library and the compiler.
|
|
1566
|
+
*
|
|
1567
|
+
* A library's definitions file says what a value *is*; when what it gives is
|
|
1568
|
+
* not something the value already answers to, the library must also say how
|
|
1569
|
+
* it runs. `names:filter(f)` is a call to a function because `@tilua-types/lua`
|
|
1570
|
+
* declares the method and ships the Luau behind it — the compiler lowers the
|
|
1571
|
+
* language (`import`, `export`, `?.`, `a ? b : c`, destructuring, spreads)
|
|
1572
|
+
* and asks a library about everything else.
|
|
1573
|
+
*
|
|
1574
|
+
* These types are declarations only: nothing here runs, and the parser never
|
|
1575
|
+
* loads a lowering module. They live here so a library can be checked against
|
|
1576
|
+
* the same contract the compiler implements, without depending on the
|
|
1577
|
+
* compiler — in TypeScript, or by JSDoc in the JavaScript it ships:
|
|
1578
|
+
*
|
|
1579
|
+
* // lowering.mjs, in a type library
|
|
1580
|
+
* // @ts-check
|
|
1581
|
+
* /** @type {import("@tilua/parser").LoweringPlugin} *\/
|
|
1582
|
+
* const plugin = {
|
|
1583
|
+
* runtime: { array: "local __NAME__ = {}\n..." },
|
|
1584
|
+
* methodCall({ method, receiver, use }) {
|
|
1585
|
+
* if (receiver?.kind === "array" && method === "filter") {
|
|
1586
|
+
* return { callee: `${use("array")}.filter` }
|
|
1587
|
+
* }
|
|
1588
|
+
* return undefined
|
|
1589
|
+
* },
|
|
1590
|
+
* }
|
|
1591
|
+
* export default plugin
|
|
1592
|
+
*/
|
|
1593
|
+
|
|
1594
|
+
interface LoweringPlugin {
|
|
1595
|
+
/** Luau the plugin needs in the output, by a key it chooses. Each is a
|
|
1596
|
+
* file's worth of source with `__NAME__` standing for the local the
|
|
1597
|
+
* compiler gives it, and each is emitted once, at the top of the output,
|
|
1598
|
+
* only if `use` asked for it:
|
|
1599
|
+
*
|
|
1600
|
+
* local __NAME__ = {}
|
|
1601
|
+
* function __NAME__.filter(t, test) ... end
|
|
1602
|
+
*/
|
|
1603
|
+
readonly runtime?: Readonly<Record<string, string>>;
|
|
1604
|
+
/** What `receiver:method(...)` becomes. `undefined` leaves a plain Luau
|
|
1605
|
+
* method call, which is what a value that answers to the method itself
|
|
1606
|
+
* wants — `text:upper()` reaches Lua's own. */
|
|
1607
|
+
methodCall?(call: MethodCall): MethodLowering | undefined;
|
|
1608
|
+
}
|
|
1609
|
+
interface MethodCall {
|
|
1610
|
+
/** The name written after `:`. */
|
|
1611
|
+
readonly method: string;
|
|
1612
|
+
/** The receiver's type, as the analyzer worked it out. `undefined` when
|
|
1613
|
+
* nothing typed it, where a plugin should decline rather than guess. */
|
|
1614
|
+
readonly receiver: Type | undefined;
|
|
1615
|
+
/** How many arguments were written. */
|
|
1616
|
+
readonly argumentCount: number;
|
|
1617
|
+
/** The local name the output gives one of `runtime`'s entries, emitting
|
|
1618
|
+
* it if this is the first call that needed it. */
|
|
1619
|
+
use(runtime: string): string;
|
|
1620
|
+
}
|
|
1621
|
+
interface MethodLowering {
|
|
1622
|
+
/** What to call instead: a name, or a `table.member` path — usually built
|
|
1623
|
+
* from `use(...)`. */
|
|
1624
|
+
readonly callee: string;
|
|
1625
|
+
/** Pass the receiver as the first argument. Default: yes. */
|
|
1626
|
+
readonly passReceiver?: boolean;
|
|
1627
|
+
}
|
|
1628
|
+
|
|
1629
|
+
/** Every file `specifier` could mean from `fromFile`, in the order they are
|
|
1630
|
+
* tried. A resolver that caches should watch all of them: creating an earlier
|
|
1631
|
+
* candidate changes what the import means. */
|
|
1632
|
+
declare function moduleCandidates(fromFile: string, specifier: string, config?: TiluaConfig): string[];
|
|
1633
|
+
/** The file `specifier` names from `fromFile`, if it exists. */
|
|
1634
|
+
declare function resolveModulePath(fromFile: string, specifier: string, config?: TiluaConfig, host?: ProjectHost): string | undefined;
|
|
1635
|
+
|
|
1636
|
+
interface SourceMapNode {
|
|
1637
|
+
name: string;
|
|
1638
|
+
className: string;
|
|
1639
|
+
filePaths?: string[];
|
|
1640
|
+
children?: SourceMapNode[];
|
|
1641
|
+
}
|
|
1642
|
+
interface SourceMapOptions {
|
|
1643
|
+
/** The type names the loaded libraries define. An instance of a class not
|
|
1644
|
+
* among them is typed as `Instance`. */
|
|
1645
|
+
readonly classes: ReadonlySet<string>;
|
|
1646
|
+
/** A class's own member names. A child whose name a member already takes
|
|
1647
|
+
* is left out — Roblox resolves the member first. Defaults to the members
|
|
1648
|
+
* every instance has. */
|
|
1649
|
+
readonly membersOf?: (className: string) => ReadonlySet<string>;
|
|
1650
|
+
}
|
|
1651
|
+
interface SourceMapTypes {
|
|
1652
|
+
/** The tree's classes, and `game` / `workspace` for a place. */
|
|
1653
|
+
readonly program: Program;
|
|
1654
|
+
/** `declare script: ...` for a file the tree maps, or `undefined`. */
|
|
1655
|
+
scriptFor(file: string): Program | undefined;
|
|
1656
|
+
}
|
|
1657
|
+
declare function sourceMapTypes(text: string, path: string, options: SourceMapOptions): {
|
|
1658
|
+
types?: SourceMapTypes;
|
|
1659
|
+
problem?: string;
|
|
1660
|
+
};
|
|
1661
|
+
|
|
1662
|
+
declare const tilua: {
|
|
1663
|
+
readonly tokenize: typeof tokenize;
|
|
1664
|
+
readonly parseTokens: typeof parseTokens;
|
|
1665
|
+
readonly parse: typeof parse;
|
|
1666
|
+
readonly parseExpressionFromSource: typeof parseExpressionFromSource;
|
|
1667
|
+
readonly parseWithRecovery: typeof parseWithRecovery;
|
|
1668
|
+
readonly analyzeScopes: typeof analyzeScopes;
|
|
1669
|
+
readonly getBinding: typeof getBinding;
|
|
1670
|
+
readonly isGlobal: typeof isGlobal;
|
|
1671
|
+
readonly isUnassignedGlobal: typeof isUnassignedGlobal;
|
|
1672
|
+
readonly analyzeTypes: typeof analyzeTypes;
|
|
1673
|
+
};
|
|
1674
|
+
|
|
1675
|
+
export { type AnalyzeTypesOptions, type AnyType, 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 CallStatement, 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 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 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, 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 NewExpression, 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 TypePackNode, type TypeParamType, type TypePredicate, type TypePredicateNode, type TypeReference, type TypedIdentifier, type TypeofTypeNode, UNUSED_EXPECT_ERROR, type UnaryExpression, UnaryOperators, type UnionType, type UnionTypeNode, type UnknownType, type VarargExpression, type VariableDeclaration, type VariadicTypeNode, 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, typeParam, unify, union, unknownType, widen, withAliasName, withoutAliasName };
|