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/README.md +123 -100
- package/dist/chunk-HK7PKBDB.js +1535 -0
- package/dist/chunk-HK7PKBDB.js.map +1 -0
- package/dist/cli.cjs +945 -161
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/index.cjs +961 -161
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +136 -63
- package/dist/index.d.ts +136 -63
- package/dist/index.js +17 -1
- package/package.json +53 -49
- package/dist/chunk-RHII344O.js +0 -733
- package/dist/chunk-RHII344O.js.map +0 -1
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 {
|
|
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
|
|
34
|
-
*
|
|
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
|
-
/**
|
|
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 {
|
|
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
|
|
34
|
-
*
|
|
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
|
-
/**
|
|
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-
|
|
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.
|
|
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.
|
|
43
|
-
"vscode-languageserver": "^10.1.1",
|
|
44
|
-
"vscode-languageserver-textdocument": "^1.0.14"
|
|
45
|
-
},
|
|
46
|
-
"bin": {
|
|
47
|
-
"luaut-language-server": "
|
|
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
|
+
}
|