luaut-language-server 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,16 +1,7 @@
1
1
  import { Connection } from 'vscode-languageserver/node';
2
- import { Program, ParseError, ScopeAnalysis, TypeAnalysis, Binding, ObjectProperty, Type, FunctionType } from 'luaut-parser';
2
+ import { Program, ParseError, ScopeAnalysis, TypeAnalysis, ModuleExports, Binding, ObjectProperty, Type, FunctionType } from 'luaut-parser';
3
3
  import { TextDocument } from 'vscode-languageserver-textdocument';
4
- import { Diagnostic, Position, Hover, Location, DocumentHighlight, Range, WorkspaceEdit, CompletionItem, SignatureHelp, DocumentSymbol } from 'vscode-languageserver';
5
-
6
- /**
7
- * Analysis cache.
8
- *
9
- * The three parser passes are cheap (single-digit milliseconds for a normal
10
- * file) but not free, and every LSP request wants the same result for the same
11
- * document version — so each document is analyzed once per version and the
12
- * result is reused by hover, definition, completion and the rest.
13
- */
4
+ import { Position, Range, CompletionItem, Location, Diagnostic, Hover, DocumentHighlight, WorkspaceEdit, SignatureHelp, DocumentSymbol, SemanticTokens, SemanticTokensLegend } from 'vscode-languageserver';
14
5
 
15
6
  interface Analysis {
16
7
  readonly uri: string;
@@ -20,23 +11,56 @@ interface Analysis {
20
11
  readonly parseErrors: readonly ParseError[];
21
12
  readonly scopes: ScopeAnalysis;
22
13
  readonly types: TypeAnalysis;
14
+ /** Every file this analysis read for an import, with the text it read —
15
+ * or `undefined` for a file it looked for and did not find. How a cached
16
+ * result tells that an import changed, appeared or vanished under it. */
17
+ readonly dependencies: ReadonlyMap<string, string | undefined>;
23
18
  }
24
19
  interface AnalyzerOptions {
25
20
  /** Definitions to analyze against. Defaults to core Luau + Roblox. */
26
21
  libs?: readonly Program[];
22
+ /** The open document for a file path, if there is one. */
23
+ openDocument?: (path: string) => TextDocument | undefined;
27
24
  }
25
+ /** A file URI's path, or `undefined` for anything that is not a file. */
26
+ declare function pathOfUri(uri: string): string | undefined;
27
+ declare function uriOfPath(path: string): string;
28
+ /** Paths compare case-insensitively on Windows, where editors and the file
29
+ * system disagree about drive-letter case. */
30
+ declare function samePath(a: string, b: string): boolean;
28
31
  declare class Analyzer {
29
32
  private readonly libs;
30
33
  private readonly builtinGlobals;
34
+ private readonly openDocument?;
31
35
  private readonly cache;
36
+ /** Imported modules, by path key. */
37
+ private readonly modules;
32
38
  constructor(options?: AnalyzerOptions);
33
- /** Analyze `document`, reusing the previous result if its version is
34
- * unchanged. */
39
+ /** Analyze `document`, reusing the previous result while neither it nor
40
+ * anything it imports has changed. */
35
41
  get(document: TextDocument): Analysis;
36
42
  /** Analyze source text that is not a tracked document — used by
37
43
  * completion, which analyzes a speculatively edited copy of the file. */
38
44
  analyze(uri: string, version: number, source: string): Analysis;
39
45
  forget(uri: string): void;
46
+ /** The file an import in `fromUri` names. Relative paths only (`./x`,
47
+ * `../x`); the extension may be left off, and a folder means its
48
+ * `index.luaut`. */
49
+ resolveModulePath(fromUri: string, specifier: string): string | undefined;
50
+ /** Every file an import could mean, in the order they are tried. */
51
+ private moduleCandidates;
52
+ /** What the module at `path` exports, analyzing it if need be. */
53
+ exportsAt(path: string): ModuleExports | undefined;
54
+ /** The analysis of the module at `path`, analyzing it if need be. */
55
+ moduleAt(path: string): Analysis | undefined;
56
+ private sourceOf;
57
+ /** `importing` holds every module on the current import chain, so an
58
+ * import back into one of them is recognized as a cycle. */
59
+ private analyzeModule;
60
+ private exportsOf;
61
+ /** Does every module `analysis` imported — and everything those import —
62
+ * still have the text it was analyzed against? */
63
+ private isFresh;
40
64
  }
41
65
 
42
66
  /**
@@ -56,11 +80,88 @@ declare function createServer(connection: Connection, options?: ServerOptions):
56
80
  /** Run the server over stdio — the transport editors launch it with. */
57
81
  declare function startServer(options?: ServerOptions): void;
58
82
 
83
+ /**
84
+ * Position mapping and AST lookup.
85
+ *
86
+ * luaut spans are 1-based with an exclusive end column; LSP positions are
87
+ * 0-based. Every conversion between the two lives here so the features never
88
+ * do the arithmetic themselves.
89
+ */
90
+
91
+ /** The shape every luaut AST node shares. */
92
+ interface Spanned {
93
+ type?: string;
94
+ line: {
95
+ start: number;
96
+ end: number;
97
+ };
98
+ column: {
99
+ start: number;
100
+ end: number;
101
+ };
102
+ }
103
+ declare function toRange(node: Spanned): Range;
104
+ /** A one-character range, for a diagnostic on a node with a collapsed span. */
105
+ declare function toPosition(line: number, column: number): Position;
106
+ /** Is `pos` inside `node`'s span? The end is exclusive, except that `inclusive`
107
+ * admits a cursor sitting immediately after the node — which is where it is
108
+ * while you are still typing the identifier under it. */
109
+ declare function containsPosition(node: Spanned, pos: Position, inclusive?: boolean): boolean;
110
+ /** Every child node of `node`, in source order-ish (declaration order of the
111
+ * fields). Generic on purpose: it walks the object graph rather than knowing
112
+ * the node types, so a new node kind in the parser needs no change here.
113
+ *
114
+ * Some nodes carry no span — the field wrappers of object literals
115
+ * (`TableFieldNamed`) and type literals (`TableTypeProperty`). They are
116
+ * walked *through*: their own children are returned in their place. Skipping
117
+ * them would hide everything inside, which is how hovering an object key used
118
+ * to land on the whole object. */
119
+ declare function children(node: Spanned): Spanned[];
120
+ /** The chain of nodes containing `pos`, outermost first — the last entry is
121
+ * the innermost node at the cursor and the ones before it are its ancestors.
122
+ *
123
+ * It descends through every child rather than only children that contain
124
+ * `pos`, because a parent's span does not always cover its child's: a
125
+ * binding's span is the name alone, while its type annotation sits after it.
126
+ * So an ancestor in this path is a real ancestor, but not necessarily one
127
+ * whose own span contains the cursor. */
128
+ declare function pathAt(root: Spanned, pos: Position, inclusive?: boolean): Spanned[];
129
+ /** The innermost node containing `pos`. */
130
+ declare function nodeAt(root: Spanned, pos: Position, inclusive?: boolean): Spanned | undefined;
131
+ /** The innermost node of one of `types` containing `pos`. */
132
+ declare function enclosing<T extends Spanned>(root: Spanned, pos: Position, types: readonly string[], inclusive?: boolean): T | undefined;
133
+ /** Walk every node under `root`, depth first. */
134
+ declare function walk(root: Spanned, visit: (node: Spanned, parent?: Spanned) => void, parent?: Spanned): void;
135
+
136
+ /** Completion inside an `import` or `export ... from`, or `undefined` when the
137
+ * cursor is not in one. */
138
+ declare function importCompletion(analyzer: Analyzer, document: TextDocument, position: Position): CompletionItem[] | undefined;
139
+ /** Go-to-definition inside a statement that names another module: the module
140
+ * string opens the module, a name jumps to where it is really declared —
141
+ * through any `export { } from` and `export *` in between. `undefined` when
142
+ * the cursor is not in such a statement, so the caller can fall back to
143
+ * ordinary definition. */
144
+ declare function importDefinition(analyzer: Analyzer, analysis: Analysis, position: Position): Location | null | undefined;
145
+ interface Declaration {
146
+ uri: string;
147
+ node: Spanned;
148
+ }
149
+ /** Where the export `name` (`"default"` for the default) of `module` is
150
+ * declared — following re-exports into the module that declares it. */
151
+ declare function exportDeclaration(analyzer: Analyzer, module: Analysis, name: string, seen?: Set<string>): Declaration | undefined;
152
+
59
153
  /** Syntax errors, scope errors and type errors, as one list. */
60
154
 
61
155
  declare function diagnostics(analysis: Analysis): Diagnostic[];
62
156
 
63
- /** Hover: the type of the thing under the cursor, as luaut would write it. */
157
+ /**
158
+ * Hover: what the thing under the cursor is, as luaut would write it.
159
+ *
160
+ * Every answer comes from the parser's own tables — binding types, the type of
161
+ * each expression, the resolved type of each type annotation — and every name
162
+ * has a node of its own to point at. Nothing is recovered from the source
163
+ * text.
164
+ */
64
165
 
65
166
  declare function hover(analysis: Analysis, position: Position): Hover | null;
66
167
 
@@ -70,7 +171,8 @@ declare function hover(analysis: Analysis, position: Position): Hover | null;
70
171
  * appear?") asked with different answers.
71
172
  */
72
173
 
73
- /** The binding referred to at `position`, if the cursor is on a variable. */
174
+ /** The binding referred to at `position`, if the cursor is on a variable
175
+ * a use of it or its declaration. */
74
176
  declare function bindingAt(analysis: Analysis, position: Position): Binding | undefined;
75
177
  declare function definition(analysis: Analysis, position: Position): Location | null;
76
178
  declare function references(analysis: Analysis, position: Position, includeDeclaration: boolean): Location[];
@@ -110,6 +212,24 @@ declare function signatureHelp(analyzer: Analyzer, document: TextDocument, posit
110
212
 
111
213
  declare function documentSymbols(analysis: Analysis): DocumentSymbol[];
112
214
 
215
+ /**
216
+ * Semantic highlighting, from the parser rather than from patterns.
217
+ *
218
+ * A TextMate grammar only sees characters, and in luaut a word's role depends
219
+ * on where it stands: `extends` is a keyword inside a type and a plain name
220
+ * elsewhere, `type Foo = ...` declares an alias while `type(x)` calls a
221
+ * builtin, and `typeof x` in a type is a query while `typeof(v)` in code is a
222
+ * call. Guessing that with regexes is how `extends (` came out coloured as a
223
+ * function call. Here every token is classified from the same lexer and AST
224
+ * the analyzer uses, so the colours cannot disagree with what the file means.
225
+ *
226
+ * The grammar still colours what is unambiguous — comments, strings, numbers,
227
+ * reserved words — so the file looks right before the server answers.
228
+ */
229
+
230
+ declare const semanticTokensLegend: SemanticTokensLegend;
231
+ declare function semanticTokens(analysis: Analysis): SemanticTokens;
232
+
113
233
  /** What members a type has — shared by completion and signature help. */
114
234
 
115
235
  interface Member {
@@ -133,51 +253,4 @@ declare function signatureLabel(signature: FunctionType): {
133
253
  parameters: string[];
134
254
  };
135
255
 
136
- /**
137
- * Position mapping and AST lookup.
138
- *
139
- * luaut spans are 1-based with an exclusive end column; LSP positions are
140
- * 0-based. Every conversion between the two lives here so the features never
141
- * do the arithmetic themselves.
142
- */
143
-
144
- /** The shape every luaut AST node shares. */
145
- interface Spanned {
146
- type?: string;
147
- line: {
148
- start: number;
149
- end: number;
150
- };
151
- column: {
152
- start: number;
153
- end: number;
154
- };
155
- }
156
- declare function toRange(node: Spanned): Range;
157
- /** A one-character range, for a diagnostic on a node with a collapsed span. */
158
- declare function toPosition(line: number, column: number): Position;
159
- /** Is `pos` inside `node`'s span? The end is exclusive, except that `inclusive`
160
- * admits a cursor sitting immediately after the node — which is where it is
161
- * while you are still typing the identifier under it. */
162
- declare function containsPosition(node: Spanned, pos: Position, inclusive?: boolean): boolean;
163
- /** Every child node of `node`, in source order-ish (declaration order of the
164
- * fields). Generic on purpose: it walks the object graph rather than knowing
165
- * the node types, so a new node kind in the parser needs no change here. */
166
- declare function children(node: Spanned): Spanned[];
167
- /** The chain of nodes containing `pos`, outermost first — the last entry is
168
- * the innermost node at the cursor and the ones before it are its ancestors.
169
- *
170
- * It descends through every child rather than only children that contain
171
- * `pos`, because a parent's span does not always cover its child's: a
172
- * binding's span is the name alone, while its type annotation sits after it.
173
- * So an ancestor in this path is a real ancestor, but not necessarily one
174
- * whose own span contains the cursor. */
175
- declare function pathAt(root: Spanned, pos: Position, inclusive?: boolean): Spanned[];
176
- /** The innermost node containing `pos`. */
177
- declare function nodeAt(root: Spanned, pos: Position, inclusive?: boolean): Spanned | undefined;
178
- /** The innermost node of one of `types` containing `pos`. */
179
- declare function enclosing<T extends Spanned>(root: Spanned, pos: Position, types: readonly string[], inclusive?: boolean): T | undefined;
180
- /** Walk every node under `root`, depth first. */
181
- declare function walk(root: Spanned, visit: (node: Spanned, parent?: Spanned) => void, parent?: Spanned): void;
182
-
183
- export { type Analysis, Analyzer, type AnalyzerOptions, type Member, type ServerOptions, type Spanned, bindingAt, children, completion, containsPosition, createServer, definition, diagnostics, documentSymbols, enclosing, highlights, hover, membersOf, nodeAt, pathAt, prepareRename, references, rename, signatureHelp, signatureLabel, signaturesOf, startServer, toPosition, toRange, walk };
256
+ export { type Analysis, Analyzer, type AnalyzerOptions, type Member, type ServerOptions, type Spanned, bindingAt, children, completion, containsPosition, createServer, definition, diagnostics, documentSymbols, enclosing, exportDeclaration, highlights, hover, importCompletion, importDefinition, membersOf, nodeAt, pathAt, pathOfUri, prepareRename, references, rename, samePath, semanticTokens, semanticTokensLegend, signatureHelp, signatureLabel, signaturesOf, startServer, toPosition, toRange, uriOfPath, walk };
package/dist/index.d.ts CHANGED
@@ -1,16 +1,7 @@
1
1
  import { Connection } from 'vscode-languageserver/node';
2
- import { Program, ParseError, ScopeAnalysis, TypeAnalysis, Binding, ObjectProperty, Type, FunctionType } from 'luaut-parser';
2
+ import { Program, ParseError, ScopeAnalysis, TypeAnalysis, ModuleExports, Binding, ObjectProperty, Type, FunctionType } from 'luaut-parser';
3
3
  import { TextDocument } from 'vscode-languageserver-textdocument';
4
- import { Diagnostic, Position, Hover, Location, DocumentHighlight, Range, WorkspaceEdit, CompletionItem, SignatureHelp, DocumentSymbol } from 'vscode-languageserver';
5
-
6
- /**
7
- * Analysis cache.
8
- *
9
- * The three parser passes are cheap (single-digit milliseconds for a normal
10
- * file) but not free, and every LSP request wants the same result for the same
11
- * document version — so each document is analyzed once per version and the
12
- * result is reused by hover, definition, completion and the rest.
13
- */
4
+ import { Position, Range, CompletionItem, Location, Diagnostic, Hover, DocumentHighlight, WorkspaceEdit, SignatureHelp, DocumentSymbol, SemanticTokens, SemanticTokensLegend } from 'vscode-languageserver';
14
5
 
15
6
  interface Analysis {
16
7
  readonly uri: string;
@@ -20,23 +11,56 @@ interface Analysis {
20
11
  readonly parseErrors: readonly ParseError[];
21
12
  readonly scopes: ScopeAnalysis;
22
13
  readonly types: TypeAnalysis;
14
+ /** Every file this analysis read for an import, with the text it read —
15
+ * or `undefined` for a file it looked for and did not find. How a cached
16
+ * result tells that an import changed, appeared or vanished under it. */
17
+ readonly dependencies: ReadonlyMap<string, string | undefined>;
23
18
  }
24
19
  interface AnalyzerOptions {
25
20
  /** Definitions to analyze against. Defaults to core Luau + Roblox. */
26
21
  libs?: readonly Program[];
22
+ /** The open document for a file path, if there is one. */
23
+ openDocument?: (path: string) => TextDocument | undefined;
27
24
  }
25
+ /** A file URI's path, or `undefined` for anything that is not a file. */
26
+ declare function pathOfUri(uri: string): string | undefined;
27
+ declare function uriOfPath(path: string): string;
28
+ /** Paths compare case-insensitively on Windows, where editors and the file
29
+ * system disagree about drive-letter case. */
30
+ declare function samePath(a: string, b: string): boolean;
28
31
  declare class Analyzer {
29
32
  private readonly libs;
30
33
  private readonly builtinGlobals;
34
+ private readonly openDocument?;
31
35
  private readonly cache;
36
+ /** Imported modules, by path key. */
37
+ private readonly modules;
32
38
  constructor(options?: AnalyzerOptions);
33
- /** Analyze `document`, reusing the previous result if its version is
34
- * unchanged. */
39
+ /** Analyze `document`, reusing the previous result while neither it nor
40
+ * anything it imports has changed. */
35
41
  get(document: TextDocument): Analysis;
36
42
  /** Analyze source text that is not a tracked document — used by
37
43
  * completion, which analyzes a speculatively edited copy of the file. */
38
44
  analyze(uri: string, version: number, source: string): Analysis;
39
45
  forget(uri: string): void;
46
+ /** The file an import in `fromUri` names. Relative paths only (`./x`,
47
+ * `../x`); the extension may be left off, and a folder means its
48
+ * `index.luaut`. */
49
+ resolveModulePath(fromUri: string, specifier: string): string | undefined;
50
+ /** Every file an import could mean, in the order they are tried. */
51
+ private moduleCandidates;
52
+ /** What the module at `path` exports, analyzing it if need be. */
53
+ exportsAt(path: string): ModuleExports | undefined;
54
+ /** The analysis of the module at `path`, analyzing it if need be. */
55
+ moduleAt(path: string): Analysis | undefined;
56
+ private sourceOf;
57
+ /** `importing` holds every module on the current import chain, so an
58
+ * import back into one of them is recognized as a cycle. */
59
+ private analyzeModule;
60
+ private exportsOf;
61
+ /** Does every module `analysis` imported — and everything those import —
62
+ * still have the text it was analyzed against? */
63
+ private isFresh;
40
64
  }
41
65
 
42
66
  /**
@@ -56,11 +80,88 @@ declare function createServer(connection: Connection, options?: ServerOptions):
56
80
  /** Run the server over stdio — the transport editors launch it with. */
57
81
  declare function startServer(options?: ServerOptions): void;
58
82
 
83
+ /**
84
+ * Position mapping and AST lookup.
85
+ *
86
+ * luaut spans are 1-based with an exclusive end column; LSP positions are
87
+ * 0-based. Every conversion between the two lives here so the features never
88
+ * do the arithmetic themselves.
89
+ */
90
+
91
+ /** The shape every luaut AST node shares. */
92
+ interface Spanned {
93
+ type?: string;
94
+ line: {
95
+ start: number;
96
+ end: number;
97
+ };
98
+ column: {
99
+ start: number;
100
+ end: number;
101
+ };
102
+ }
103
+ declare function toRange(node: Spanned): Range;
104
+ /** A one-character range, for a diagnostic on a node with a collapsed span. */
105
+ declare function toPosition(line: number, column: number): Position;
106
+ /** Is `pos` inside `node`'s span? The end is exclusive, except that `inclusive`
107
+ * admits a cursor sitting immediately after the node — which is where it is
108
+ * while you are still typing the identifier under it. */
109
+ declare function containsPosition(node: Spanned, pos: Position, inclusive?: boolean): boolean;
110
+ /** Every child node of `node`, in source order-ish (declaration order of the
111
+ * fields). Generic on purpose: it walks the object graph rather than knowing
112
+ * the node types, so a new node kind in the parser needs no change here.
113
+ *
114
+ * Some nodes carry no span — the field wrappers of object literals
115
+ * (`TableFieldNamed`) and type literals (`TableTypeProperty`). They are
116
+ * walked *through*: their own children are returned in their place. Skipping
117
+ * them would hide everything inside, which is how hovering an object key used
118
+ * to land on the whole object. */
119
+ declare function children(node: Spanned): Spanned[];
120
+ /** The chain of nodes containing `pos`, outermost first — the last entry is
121
+ * the innermost node at the cursor and the ones before it are its ancestors.
122
+ *
123
+ * It descends through every child rather than only children that contain
124
+ * `pos`, because a parent's span does not always cover its child's: a
125
+ * binding's span is the name alone, while its type annotation sits after it.
126
+ * So an ancestor in this path is a real ancestor, but not necessarily one
127
+ * whose own span contains the cursor. */
128
+ declare function pathAt(root: Spanned, pos: Position, inclusive?: boolean): Spanned[];
129
+ /** The innermost node containing `pos`. */
130
+ declare function nodeAt(root: Spanned, pos: Position, inclusive?: boolean): Spanned | undefined;
131
+ /** The innermost node of one of `types` containing `pos`. */
132
+ declare function enclosing<T extends Spanned>(root: Spanned, pos: Position, types: readonly string[], inclusive?: boolean): T | undefined;
133
+ /** Walk every node under `root`, depth first. */
134
+ declare function walk(root: Spanned, visit: (node: Spanned, parent?: Spanned) => void, parent?: Spanned): void;
135
+
136
+ /** Completion inside an `import` or `export ... from`, or `undefined` when the
137
+ * cursor is not in one. */
138
+ declare function importCompletion(analyzer: Analyzer, document: TextDocument, position: Position): CompletionItem[] | undefined;
139
+ /** Go-to-definition inside a statement that names another module: the module
140
+ * string opens the module, a name jumps to where it is really declared —
141
+ * through any `export { } from` and `export *` in between. `undefined` when
142
+ * the cursor is not in such a statement, so the caller can fall back to
143
+ * ordinary definition. */
144
+ declare function importDefinition(analyzer: Analyzer, analysis: Analysis, position: Position): Location | null | undefined;
145
+ interface Declaration {
146
+ uri: string;
147
+ node: Spanned;
148
+ }
149
+ /** Where the export `name` (`"default"` for the default) of `module` is
150
+ * declared — following re-exports into the module that declares it. */
151
+ declare function exportDeclaration(analyzer: Analyzer, module: Analysis, name: string, seen?: Set<string>): Declaration | undefined;
152
+
59
153
  /** Syntax errors, scope errors and type errors, as one list. */
60
154
 
61
155
  declare function diagnostics(analysis: Analysis): Diagnostic[];
62
156
 
63
- /** Hover: the type of the thing under the cursor, as luaut would write it. */
157
+ /**
158
+ * Hover: what the thing under the cursor is, as luaut would write it.
159
+ *
160
+ * Every answer comes from the parser's own tables — binding types, the type of
161
+ * each expression, the resolved type of each type annotation — and every name
162
+ * has a node of its own to point at. Nothing is recovered from the source
163
+ * text.
164
+ */
64
165
 
65
166
  declare function hover(analysis: Analysis, position: Position): Hover | null;
66
167
 
@@ -70,7 +171,8 @@ declare function hover(analysis: Analysis, position: Position): Hover | null;
70
171
  * appear?") asked with different answers.
71
172
  */
72
173
 
73
- /** The binding referred to at `position`, if the cursor is on a variable. */
174
+ /** The binding referred to at `position`, if the cursor is on a variable
175
+ * a use of it or its declaration. */
74
176
  declare function bindingAt(analysis: Analysis, position: Position): Binding | undefined;
75
177
  declare function definition(analysis: Analysis, position: Position): Location | null;
76
178
  declare function references(analysis: Analysis, position: Position, includeDeclaration: boolean): Location[];
@@ -110,6 +212,24 @@ declare function signatureHelp(analyzer: Analyzer, document: TextDocument, posit
110
212
 
111
213
  declare function documentSymbols(analysis: Analysis): DocumentSymbol[];
112
214
 
215
+ /**
216
+ * Semantic highlighting, from the parser rather than from patterns.
217
+ *
218
+ * A TextMate grammar only sees characters, and in luaut a word's role depends
219
+ * on where it stands: `extends` is a keyword inside a type and a plain name
220
+ * elsewhere, `type Foo = ...` declares an alias while `type(x)` calls a
221
+ * builtin, and `typeof x` in a type is a query while `typeof(v)` in code is a
222
+ * call. Guessing that with regexes is how `extends (` came out coloured as a
223
+ * function call. Here every token is classified from the same lexer and AST
224
+ * the analyzer uses, so the colours cannot disagree with what the file means.
225
+ *
226
+ * The grammar still colours what is unambiguous — comments, strings, numbers,
227
+ * reserved words — so the file looks right before the server answers.
228
+ */
229
+
230
+ declare const semanticTokensLegend: SemanticTokensLegend;
231
+ declare function semanticTokens(analysis: Analysis): SemanticTokens;
232
+
113
233
  /** What members a type has — shared by completion and signature help. */
114
234
 
115
235
  interface Member {
@@ -133,51 +253,4 @@ declare function signatureLabel(signature: FunctionType): {
133
253
  parameters: string[];
134
254
  };
135
255
 
136
- /**
137
- * Position mapping and AST lookup.
138
- *
139
- * luaut spans are 1-based with an exclusive end column; LSP positions are
140
- * 0-based. Every conversion between the two lives here so the features never
141
- * do the arithmetic themselves.
142
- */
143
-
144
- /** The shape every luaut AST node shares. */
145
- interface Spanned {
146
- type?: string;
147
- line: {
148
- start: number;
149
- end: number;
150
- };
151
- column: {
152
- start: number;
153
- end: number;
154
- };
155
- }
156
- declare function toRange(node: Spanned): Range;
157
- /** A one-character range, for a diagnostic on a node with a collapsed span. */
158
- declare function toPosition(line: number, column: number): Position;
159
- /** Is `pos` inside `node`'s span? The end is exclusive, except that `inclusive`
160
- * admits a cursor sitting immediately after the node — which is where it is
161
- * while you are still typing the identifier under it. */
162
- declare function containsPosition(node: Spanned, pos: Position, inclusive?: boolean): boolean;
163
- /** Every child node of `node`, in source order-ish (declaration order of the
164
- * fields). Generic on purpose: it walks the object graph rather than knowing
165
- * the node types, so a new node kind in the parser needs no change here. */
166
- declare function children(node: Spanned): Spanned[];
167
- /** The chain of nodes containing `pos`, outermost first — the last entry is
168
- * the innermost node at the cursor and the ones before it are its ancestors.
169
- *
170
- * It descends through every child rather than only children that contain
171
- * `pos`, because a parent's span does not always cover its child's: a
172
- * binding's span is the name alone, while its type annotation sits after it.
173
- * So an ancestor in this path is a real ancestor, but not necessarily one
174
- * whose own span contains the cursor. */
175
- declare function pathAt(root: Spanned, pos: Position, inclusive?: boolean): Spanned[];
176
- /** The innermost node containing `pos`. */
177
- declare function nodeAt(root: Spanned, pos: Position, inclusive?: boolean): Spanned | undefined;
178
- /** The innermost node of one of `types` containing `pos`. */
179
- declare function enclosing<T extends Spanned>(root: Spanned, pos: Position, types: readonly string[], inclusive?: boolean): T | undefined;
180
- /** Walk every node under `root`, depth first. */
181
- declare function walk(root: Spanned, visit: (node: Spanned, parent?: Spanned) => void, parent?: Spanned): void;
182
-
183
- export { type Analysis, Analyzer, type AnalyzerOptions, type Member, type ServerOptions, type Spanned, bindingAt, children, completion, containsPosition, createServer, definition, diagnostics, documentSymbols, enclosing, highlights, hover, membersOf, nodeAt, pathAt, prepareRename, references, rename, signatureHelp, signatureLabel, signaturesOf, startServer, toPosition, toRange, walk };
256
+ export { type Analysis, Analyzer, type AnalyzerOptions, type Member, type ServerOptions, type Spanned, bindingAt, children, completion, containsPosition, createServer, definition, diagnostics, documentSymbols, enclosing, exportDeclaration, highlights, hover, importCompletion, importDefinition, membersOf, nodeAt, pathAt, pathOfUri, prepareRename, references, rename, samePath, semanticTokens, semanticTokensLegend, signatureHelp, signatureLabel, signaturesOf, startServer, toPosition, toRange, uriOfPath, walk };
package/dist/index.js CHANGED
@@ -9,22 +9,30 @@ import {
9
9
  diagnostics,
10
10
  documentSymbols,
11
11
  enclosing,
12
+ exportDeclaration,
12
13
  highlights,
13
14
  hover,
15
+ importCompletion,
16
+ importDefinition,
14
17
  membersOf,
15
18
  nodeAt,
16
19
  pathAt,
20
+ pathOfUri,
17
21
  prepareRename,
18
22
  references,
19
23
  rename,
24
+ samePath,
25
+ semanticTokens,
26
+ semanticTokensLegend,
20
27
  signatureHelp,
21
28
  signatureLabel,
22
29
  signaturesOf,
23
30
  startServer,
24
31
  toPosition,
25
32
  toRange,
33
+ uriOfPath,
26
34
  walk
27
- } from "./chunk-RHII344O.js";
35
+ } from "./chunk-HK7PKBDB.js";
28
36
  export {
29
37
  Analyzer,
30
38
  bindingAt,
@@ -36,20 +44,28 @@ export {
36
44
  diagnostics,
37
45
  documentSymbols,
38
46
  enclosing,
47
+ exportDeclaration,
39
48
  highlights,
40
49
  hover,
50
+ importCompletion,
51
+ importDefinition,
41
52
  membersOf,
42
53
  nodeAt,
43
54
  pathAt,
55
+ pathOfUri,
44
56
  prepareRename,
45
57
  references,
46
58
  rename,
59
+ samePath,
60
+ semanticTokens,
61
+ semanticTokensLegend,
47
62
  signatureHelp,
48
63
  signatureLabel,
49
64
  signaturesOf,
50
65
  startServer,
51
66
  toPosition,
52
67
  toRange,
68
+ uriOfPath,
53
69
  walk
54
70
  };
55
71
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,49 +1,53 @@
1
- {
2
- "name": "luaut-language-server",
3
- "version": "1.0.0",
4
- "description": "Language server for luaut (LSP), built on luaut-parser",
5
- "main": "./dist/index.js",
6
- "module": "./dist/index.js",
7
- "types": "./dist/index.d.ts",
8
- "files": [
9
- "dist"
10
- ],
11
- "exports": {
12
- ".": {
13
- "types": {
14
- "require": "./dist/index.d.cts",
15
- "import": "./dist/index.d.ts"
16
- },
17
- "import": "./dist/index.js",
18
- "require": "./dist/index.cjs"
19
- },
20
- "./server": {
21
- "default": "./dist/cli.js"
22
- }
23
- },
24
- "scripts": {
25
- "test": "tsx scripts/test.ts && npm run build && tsx scripts/e2e.ts",
26
- "test:unit": "tsx scripts/test.ts",
27
- "test:e2e": "tsx scripts/e2e.ts",
28
- "build": "tsup",
29
- "typecheck": "tsc --noEmit"
30
- },
31
- "keywords": [],
32
- "author": "",
33
- "license": "ISC",
34
- "type": "module",
35
- "devDependencies": {
36
- "@types/node": "^22.20.2",
37
- "tsup": "^8.5.1",
38
- "tsx": "^4.23.13",
39
- "typescript": "^5.0.4"
40
- },
41
- "dependencies": {
42
- "luaut-parser": "^1.0.0",
43
- "vscode-languageserver": "^10.1.1",
44
- "vscode-languageserver-textdocument": "^1.0.14"
45
- },
46
- "bin": {
47
- "luaut-language-server": "./dist/cli.js"
48
- }
49
- }
1
+ {
2
+ "name": "luaut-language-server",
3
+ "version": "1.1.0",
4
+ "description": "Language server for luaut (LSP), built on luaut-parser",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "exports": {
12
+ ".": {
13
+ "types": {
14
+ "require": "./dist/index.d.cts",
15
+ "import": "./dist/index.d.ts"
16
+ },
17
+ "import": "./dist/index.js",
18
+ "require": "./dist/index.cjs"
19
+ },
20
+ "./server": {
21
+ "default": "./dist/cli.js"
22
+ }
23
+ },
24
+ "scripts": {
25
+ "test": "tsx scripts/test.ts && npm run build && tsx scripts/e2e.ts",
26
+ "test:unit": "tsx scripts/test.ts",
27
+ "test:e2e": "tsx scripts/e2e.ts",
28
+ "build": "tsup",
29
+ "typecheck": "tsc --noEmit"
30
+ },
31
+ "keywords": [],
32
+ "author": "",
33
+ "license": "ISC",
34
+ "type": "module",
35
+ "devDependencies": {
36
+ "@types/node": "^22.20.2",
37
+ "tsup": "^8.5.1",
38
+ "tsx": "^4.23.13",
39
+ "typescript": "^5.0.4"
40
+ },
41
+ "dependencies": {
42
+ "luaut-parser": "^1.1.0",
43
+ "vscode-languageserver": "^10.1.1",
44
+ "vscode-languageserver-textdocument": "^1.0.14"
45
+ },
46
+ "bin": {
47
+ "luaut-language-server": "dist/cli.js"
48
+ },
49
+ "repository": {
50
+ "type": "git",
51
+ "url": "git+https://github.com/Uav3537/luaut-language-server.git"
52
+ }
53
+ }