brighterscript 0.42.0 → 0.45.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/CHANGELOG.md +49 -0
- package/dist/Cache.d.ts +3 -8
- package/dist/Cache.js +9 -14
- package/dist/Cache.js.map +1 -1
- package/dist/DiagnosticMessages.d.ts +21 -1
- package/dist/DiagnosticMessages.js +20 -0
- package/dist/DiagnosticMessages.js.map +1 -1
- package/dist/LanguageServer.d.ts +1 -6
- package/dist/LanguageServer.js +3 -12
- package/dist/LanguageServer.js.map +1 -1
- package/dist/PluginInterface.d.ts +3 -3
- package/dist/PluginInterface.js +3 -0
- package/dist/PluginInterface.js.map +1 -1
- package/dist/Program.d.ts +68 -25
- package/dist/Program.js +169 -76
- package/dist/Program.js.map +1 -1
- package/dist/ProgramBuilder.js +6 -6
- package/dist/ProgramBuilder.js.map +1 -1
- package/dist/Scope.d.ts +18 -11
- package/dist/Scope.js +41 -14
- package/dist/Scope.js.map +1 -1
- package/dist/XmlScope.d.ts +3 -3
- package/dist/astUtils/AstEditor.d.ts +6 -0
- package/dist/astUtils/AstEditor.js +10 -0
- package/dist/astUtils/AstEditor.js.map +1 -1
- package/dist/astUtils/AstEditor.spec.js +37 -0
- package/dist/astUtils/AstEditor.spec.js.map +1 -1
- package/dist/astUtils/reflection.d.ts +5 -2
- package/dist/astUtils/reflection.js +14 -2
- package/dist/astUtils/reflection.js.map +1 -1
- package/dist/astUtils/reflection.spec.js +6 -6
- package/dist/astUtils/reflection.spec.js.map +1 -1
- package/dist/astUtils/visitors.d.ts +3 -1
- package/dist/astUtils/visitors.js.map +1 -1
- package/dist/astUtils/visitors.spec.js +15 -18
- package/dist/astUtils/visitors.spec.js.map +1 -1
- package/dist/bscPlugin/BscPlugin.d.ts +4 -1
- package/dist/bscPlugin/BscPlugin.js +21 -2
- package/dist/bscPlugin/BscPlugin.js.map +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +3 -3
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +18 -16
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +9 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +97 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -0
- package/dist/bscPlugin/semanticTokens/{SemanticTokensProcessor.spec.d.ts → BrsFileSemanticTokensProcessor.spec.d.ts} +0 -0
- package/dist/bscPlugin/semanticTokens/{SemanticTokensProcessor.spec.js → BrsFileSemanticTokensProcessor.spec.js} +32 -4
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -0
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.d.ts +8 -0
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js +36 -0
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js.map +1 -0
- package/dist/bscPlugin/validation/BrsFileValidator.d.ts +9 -0
- package/dist/bscPlugin/validation/BrsFileValidator.js +66 -0
- package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -0
- package/dist/bscPlugin/validation/ScopeValidator.d.ts +11 -0
- package/dist/bscPlugin/validation/ScopeValidator.js +94 -0
- package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -0
- package/dist/files/BrsFile.Class.spec.js +218 -114
- package/dist/files/BrsFile.Class.spec.js.map +1 -1
- package/dist/files/BrsFile.d.ts +27 -8
- package/dist/files/BrsFile.js +216 -95
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/BrsFile.spec.js +338 -190
- package/dist/files/BrsFile.spec.js.map +1 -1
- package/dist/files/XmlFile.d.ts +11 -5
- package/dist/files/XmlFile.js +15 -9
- package/dist/files/XmlFile.js.map +1 -1
- package/dist/files/XmlFile.spec.js +118 -114
- package/dist/files/XmlFile.spec.js.map +1 -1
- package/dist/files/tests/imports.spec.js +29 -27
- package/dist/files/tests/imports.spec.js.map +1 -1
- package/dist/index.d.ts +12 -3
- package/dist/index.js +21 -4
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +50 -9
- package/dist/lexer/Lexer.js +1 -2
- package/dist/lexer/Lexer.js.map +1 -1
- package/dist/lexer/Lexer.spec.js +470 -462
- package/dist/lexer/Lexer.spec.js.map +1 -1
- package/dist/lexer/TokenKind.d.ts +2 -0
- package/dist/lexer/TokenKind.js +5 -0
- package/dist/lexer/TokenKind.js.map +1 -1
- package/dist/parser/Expression.d.ts +1 -1
- package/dist/parser/Expression.js +10 -10
- package/dist/parser/Expression.js.map +1 -1
- package/dist/parser/Parser.Class.spec.js +32 -31
- package/dist/parser/Parser.Class.spec.js.map +1 -1
- package/dist/parser/Parser.d.ts +23 -2
- package/dist/parser/Parser.js +445 -254
- package/dist/parser/Parser.js.map +1 -1
- package/dist/parser/Parser.spec.js +86 -24
- package/dist/parser/Parser.spec.js.map +1 -1
- package/dist/parser/SGParser.spec.js +1 -1
- package/dist/parser/SGParser.spec.js.map +1 -1
- package/dist/parser/Statement.d.ts +54 -2
- package/dist/parser/Statement.js +162 -9
- package/dist/parser/Statement.js.map +1 -1
- package/dist/parser/Statement.spec.js +5 -5
- package/dist/parser/Statement.spec.js.map +1 -1
- package/dist/parser/tests/Parser.spec.d.ts +3 -3
- package/dist/parser/tests/Parser.spec.js +4 -4
- package/dist/parser/tests/Parser.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/For.spec.js +40 -40
- package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/ForEach.spec.js +22 -21
- package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/If.spec.js +100 -99
- package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/While.spec.js +25 -25
- package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
- package/dist/parser/tests/expression/Additive.spec.js +21 -21
- package/dist/parser/tests/expression/Additive.spec.js.map +1 -1
- package/dist/parser/tests/expression/ArrayLiterals.spec.js +91 -91
- package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +102 -102
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
- package/dist/parser/tests/expression/Boolean.spec.js +15 -15
- package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
- package/dist/parser/tests/expression/Call.spec.js +22 -21
- package/dist/parser/tests/expression/Call.spec.js.map +1 -1
- package/dist/parser/tests/expression/Exponential.spec.js +11 -11
- package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
- package/dist/parser/tests/expression/Function.spec.js +171 -171
- package/dist/parser/tests/expression/Function.spec.js.map +1 -1
- package/dist/parser/tests/expression/Indexing.spec.js +50 -50
- package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
- package/dist/parser/tests/expression/Multiplicative.spec.js +25 -25
- package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +17 -17
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/PrefixUnary.spec.js +26 -26
- package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
- package/dist/parser/tests/expression/Primary.spec.js +27 -27
- package/dist/parser/tests/expression/Primary.spec.js.map +1 -1
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +4 -3
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/Relational.spec.js +25 -25
- package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js +8 -8
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TernaryExpression.spec.js +7 -7
- package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
- package/dist/parser/tests/statement/AssignmentOperators.spec.js +15 -15
- package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
- package/dist/parser/tests/statement/Declaration.spec.js +20 -20
- package/dist/parser/tests/statement/Declaration.spec.js.map +1 -1
- package/dist/parser/tests/statement/Enum.spec.d.ts +1 -0
- package/dist/parser/tests/statement/Enum.spec.js +774 -0
- package/dist/parser/tests/statement/Enum.spec.js.map +1 -0
- package/dist/parser/tests/statement/Function.spec.js +121 -120
- package/dist/parser/tests/statement/Function.spec.js.map +1 -1
- package/dist/parser/tests/statement/Goto.spec.js +9 -8
- package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
- package/dist/parser/tests/statement/Increment.spec.js +22 -22
- package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
- package/dist/parser/tests/statement/InterfaceStatement.spec.js +12 -0
- package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/LibraryStatement.spec.js +7 -7
- package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/Misc.spec.js +71 -70
- package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
- package/dist/parser/tests/statement/PrintStatement.spec.js +17 -17
- package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/ReturnStatement.spec.js +33 -33
- package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/Set.spec.js +53 -53
- package/dist/parser/tests/statement/Set.spec.js.map +1 -1
- package/dist/parser/tests/statement/Stop.spec.js +7 -6
- package/dist/parser/tests/statement/Stop.spec.js.map +1 -1
- package/dist/preprocessor/Chunk.d.ts +1 -1
- package/dist/preprocessor/Preprocessor.d.ts +1 -1
- package/dist/preprocessor/Preprocessor.js +7 -7
- package/dist/preprocessor/Preprocessor.js.map +1 -1
- package/dist/types/FunctionType.d.ts +2 -2
- package/dist/types/FunctionType.js +3 -3
- package/dist/types/FunctionType.js.map +1 -1
- package/dist/types/FunctionType.spec.js +2 -2
- package/dist/types/FunctionType.spec.js.map +1 -1
- package/dist/util.d.ts +27 -1
- package/dist/util.js +96 -29
- package/dist/util.js.map +1 -1
- package/dist/validators/ClassValidator.js +20 -27
- package/dist/validators/ClassValidator.js.map +1 -1
- package/package.json +2 -1
- package/dist/astUtils/index.d.ts +0 -7
- package/dist/astUtils/index.js +0 -26
- package/dist/astUtils/index.js.map +0 -1
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.d.ts +0 -7
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js +0 -63
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js.map +0 -1
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js.map +0 -1
- package/dist/lexer/index.d.ts +0 -3
- package/dist/lexer/index.js +0 -18
- package/dist/lexer/index.js.map +0 -1
- package/dist/parser/index.d.ts +0 -3
- package/dist/parser/index.js +0 -16
- package/dist/parser/index.js.map +0 -1
- package/dist/preprocessor/index.d.ts +0 -3
- package/dist/preprocessor/index.js +0 -16
- package/dist/preprocessor/index.js.map +0 -1
package/dist/files/BrsFile.js
CHANGED
|
@@ -7,8 +7,9 @@ const chalk_1 = require("chalk");
|
|
|
7
7
|
const path = require("path");
|
|
8
8
|
const DiagnosticMessages_1 = require("../DiagnosticMessages");
|
|
9
9
|
const FunctionScope_1 = require("../FunctionScope");
|
|
10
|
-
const
|
|
11
|
-
const
|
|
10
|
+
const Lexer_1 = require("../lexer/Lexer");
|
|
11
|
+
const TokenKind_1 = require("../lexer/TokenKind");
|
|
12
|
+
const Parser_1 = require("../parser/Parser");
|
|
12
13
|
const DynamicType_1 = require("../types/DynamicType");
|
|
13
14
|
const FunctionType_1 = require("../types/FunctionType");
|
|
14
15
|
const VoidType_1 = require("../types/VoidType");
|
|
@@ -36,7 +37,12 @@ class BrsFile {
|
|
|
36
37
|
/**
|
|
37
38
|
* The parseMode used for the parser for this file
|
|
38
39
|
*/
|
|
39
|
-
this.parseMode =
|
|
40
|
+
this.parseMode = Parser_1.ParseMode.BrightScript;
|
|
41
|
+
/**
|
|
42
|
+
* Indicates whether this file needs to be validated.
|
|
43
|
+
* Files are only ever validated a single time
|
|
44
|
+
*/
|
|
45
|
+
this.isValidated = false;
|
|
40
46
|
this.diagnostics = [];
|
|
41
47
|
this.commentFlags = [];
|
|
42
48
|
this.callables = [];
|
|
@@ -57,7 +63,7 @@ class BrsFile {
|
|
|
57
63
|
//all BrighterScript files need to be transpiled
|
|
58
64
|
if ((_a = this.extension) === null || _a === void 0 ? void 0 : _a.endsWith('.bs')) {
|
|
59
65
|
this.needsTranspiled = true;
|
|
60
|
-
this.parseMode =
|
|
66
|
+
this.parseMode = Parser_1.ParseMode.BrighterScript;
|
|
61
67
|
}
|
|
62
68
|
this.isTypedef = this.extension === '.d.bs';
|
|
63
69
|
if (!this.isTypedef) {
|
|
@@ -145,11 +151,13 @@ class BrsFile {
|
|
|
145
151
|
this.diagnostics = [];
|
|
146
152
|
//if we have a typedef file, skip parsing this file
|
|
147
153
|
if (this.hasTypedef) {
|
|
154
|
+
//skip validation since the typedef is shadowing this file
|
|
155
|
+
this.isValidated = true;
|
|
148
156
|
return;
|
|
149
157
|
}
|
|
150
158
|
//tokenize the input file
|
|
151
159
|
let lexer = this.program.logger.time(Logger_1.LogLevel.debug, ['lexer.lex', chalk_1.default.green(this.pathAbsolute)], () => {
|
|
152
|
-
return
|
|
160
|
+
return Lexer_1.Lexer.scan(fileContents, {
|
|
153
161
|
includeWhitespace: false
|
|
154
162
|
});
|
|
155
163
|
});
|
|
@@ -172,32 +180,50 @@ class BrsFile {
|
|
|
172
180
|
//if the preprocessor generated tokens, use them.
|
|
173
181
|
let tokens = preprocessor.processedTokens.length > 0 ? preprocessor.processedTokens : lexer.tokens;
|
|
174
182
|
this.program.logger.time(Logger_1.LogLevel.debug, ['parser.parse', chalk_1.default.green(this.pathAbsolute)], () => {
|
|
175
|
-
this._parser =
|
|
183
|
+
this._parser = Parser_1.Parser.parse(tokens, {
|
|
176
184
|
mode: this.parseMode,
|
|
177
185
|
logger: this.program.logger
|
|
178
186
|
});
|
|
179
187
|
});
|
|
180
188
|
//absorb all lexing/preprocessing/parsing diagnostics
|
|
181
189
|
this.diagnostics.push(...lexer.diagnostics, ...preprocessor.diagnostics, ...this._parser.diagnostics);
|
|
182
|
-
//notify AST ready
|
|
183
|
-
this.program.plugins.emit('afterFileParse', this);
|
|
184
190
|
//extract all callables from this file
|
|
185
191
|
this.findCallables();
|
|
186
192
|
//find all places where a sub/function is being called
|
|
187
193
|
this.findFunctionCalls();
|
|
188
|
-
|
|
194
|
+
//register all import statements for use in the rest of the program
|
|
195
|
+
this.registerImports();
|
|
189
196
|
//attach this file to every diagnostic
|
|
190
197
|
for (let diagnostic of this.diagnostics) {
|
|
191
198
|
diagnostic.file = this;
|
|
192
199
|
}
|
|
193
200
|
}
|
|
194
201
|
catch (e) {
|
|
195
|
-
this._parser = new
|
|
202
|
+
this._parser = new Parser_1.Parser();
|
|
196
203
|
this.diagnostics.push(Object.assign({ file: this, range: util_1.util.createRange(0, 0, 0, Number.MAX_VALUE) }, DiagnosticMessages_1.DiagnosticMessages.genericParserMessage('Critical error parsing file: ' + JSON.stringify((0, serialize_error_1.serializeError)(e)))));
|
|
197
204
|
}
|
|
198
205
|
}
|
|
199
|
-
|
|
200
|
-
var _a;
|
|
206
|
+
registerImports() {
|
|
207
|
+
var _a, _b, _c, _d;
|
|
208
|
+
for (const statement of (_c = (_b = (_a = this.parser) === null || _a === void 0 ? void 0 : _a.references) === null || _b === void 0 ? void 0 : _b.importStatements) !== null && _c !== void 0 ? _c : []) {
|
|
209
|
+
//register import statements
|
|
210
|
+
if ((0, reflection_1.isImportStatement)(statement) && statement.filePathToken) {
|
|
211
|
+
this.ownScriptImports.push({
|
|
212
|
+
filePathRange: statement.filePathToken.range,
|
|
213
|
+
pkgPath: util_1.util.getPkgPathFromTarget(this.pkgPath, statement.filePath),
|
|
214
|
+
sourceFile: this,
|
|
215
|
+
text: (_d = statement.filePathToken) === null || _d === void 0 ? void 0 : _d.text
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
validate() {
|
|
221
|
+
//only validate the file if it was actually parsed (skip files containing typedefs)
|
|
222
|
+
if (!this.hasTypedef) {
|
|
223
|
+
this.validateImportStatements();
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
validateImportStatements() {
|
|
201
227
|
let topOfFileIncludeStatements = [];
|
|
202
228
|
for (let stmt of this.ast.statements) {
|
|
203
229
|
//skip comments
|
|
@@ -218,15 +244,6 @@ class BrsFile {
|
|
|
218
244
|
...this._parser.references.importStatements
|
|
219
245
|
];
|
|
220
246
|
for (let result of statements) {
|
|
221
|
-
//register import statements
|
|
222
|
-
if ((0, reflection_1.isImportStatement)(result) && result.filePathToken) {
|
|
223
|
-
this.ownScriptImports.push({
|
|
224
|
-
filePathRange: result.filePathToken.range,
|
|
225
|
-
pkgPath: util_1.util.getPkgPathFromTarget(this.pkgPath, result.filePath),
|
|
226
|
-
sourceFile: this,
|
|
227
|
-
text: (_a = result.filePathToken) === null || _a === void 0 ? void 0 : _a.text
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
247
|
//if this statement is not one of the top-of-file statements,
|
|
231
248
|
//then add a diagnostic explaining that it is invalid
|
|
232
249
|
if (!topOfFileIncludeStatements.includes(result)) {
|
|
@@ -284,7 +301,7 @@ class BrsFile {
|
|
|
284
301
|
const processor = new CommentFlagProcessor_1.CommentFlagProcessor(this, ['rem', `'`], DiagnosticMessages_1.diagnosticCodes, [DiagnosticMessages_1.DiagnosticCodeMap.unknownDiagnosticCode]);
|
|
285
302
|
this.commentFlags = [];
|
|
286
303
|
for (let token of tokens) {
|
|
287
|
-
if (token.kind ===
|
|
304
|
+
if (token.kind === TokenKind_1.TokenKind.Comment) {
|
|
288
305
|
processor.tryAdd(token.text, token.range);
|
|
289
306
|
}
|
|
290
307
|
}
|
|
@@ -374,9 +391,9 @@ class BrsFile {
|
|
|
374
391
|
}
|
|
375
392
|
functionType.setName(assignment.name.text);
|
|
376
393
|
for (let param of assignment.value.parameters) {
|
|
377
|
-
let
|
|
394
|
+
let isOptional = !!param.defaultValue;
|
|
378
395
|
//TODO compute optional parameters
|
|
379
|
-
functionType.addParameter(param.name.text, param.type,
|
|
396
|
+
functionType.addParameter(param.name.text, param.type, isOptional);
|
|
380
397
|
}
|
|
381
398
|
return functionType;
|
|
382
399
|
//literal
|
|
@@ -436,8 +453,8 @@ class BrsFile {
|
|
|
436
453
|
isRestArgument: false
|
|
437
454
|
};
|
|
438
455
|
params.push(callableParam);
|
|
439
|
-
let
|
|
440
|
-
functionType.addParameter(callableParam.name, callableParam.type,
|
|
456
|
+
let isOptional = !!param.defaultValue;
|
|
457
|
+
functionType.addParameter(callableParam.name, callableParam.type, isOptional);
|
|
441
458
|
}
|
|
442
459
|
this.callables.push({
|
|
443
460
|
isSub: statement.func.functionType.text.toLowerCase() === 'sub',
|
|
@@ -555,6 +572,20 @@ class BrsFile {
|
|
|
555
572
|
}
|
|
556
573
|
}
|
|
557
574
|
}
|
|
575
|
+
/**
|
|
576
|
+
* Find the NamespaceStatement enclosing the given position
|
|
577
|
+
* @param position
|
|
578
|
+
* @param functionScopes
|
|
579
|
+
*/
|
|
580
|
+
getNamespaceStatementForPosition(position) {
|
|
581
|
+
if (position) {
|
|
582
|
+
for (const statement of this.parser.references.namespaceStatements) {
|
|
583
|
+
if (util_1.util.rangeContains(statement.range, position)) {
|
|
584
|
+
return statement;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
}
|
|
558
589
|
/**
|
|
559
590
|
* Get completions available at the given cursor. This aggregates all values from this file and the current scope.
|
|
560
591
|
*/
|
|
@@ -570,10 +601,10 @@ class BrsFile {
|
|
|
570
601
|
//if cursor is within a comment, disable completions
|
|
571
602
|
let currentToken = this.getTokenAt(position);
|
|
572
603
|
const tokenKind = currentToken === null || currentToken === void 0 ? void 0 : currentToken.kind;
|
|
573
|
-
if (tokenKind ===
|
|
604
|
+
if (tokenKind === TokenKind_1.TokenKind.Comment) {
|
|
574
605
|
return [];
|
|
575
606
|
}
|
|
576
|
-
else if (tokenKind ===
|
|
607
|
+
else if (tokenKind === TokenKind_1.TokenKind.StringLiteral || tokenKind === TokenKind_1.TokenKind.TemplateStringQuasi) {
|
|
577
608
|
const match = /^("?)(pkg|libpkg):/.exec(currentToken.text);
|
|
578
609
|
if (match) {
|
|
579
610
|
const [, openingQuote, fileProtocol] = match;
|
|
@@ -597,38 +628,44 @@ class BrsFile {
|
|
|
597
628
|
return [];
|
|
598
629
|
}
|
|
599
630
|
}
|
|
600
|
-
|
|
631
|
+
const namespaceCompletions = this.getNamespaceCompletions(currentToken, this.parseMode, scope);
|
|
601
632
|
if (namespaceCompletions.length > 0) {
|
|
602
|
-
return namespaceCompletions;
|
|
633
|
+
return [...namespaceCompletions];
|
|
634
|
+
}
|
|
635
|
+
const enumMemberCompletions = this.getEnumMemberStatementCompletions(currentToken, this.parseMode, scope);
|
|
636
|
+
if (enumMemberCompletions.length > 0) {
|
|
637
|
+
// no other completion is valid in this case
|
|
638
|
+
return enumMemberCompletions;
|
|
603
639
|
}
|
|
604
640
|
//determine if cursor is inside a function
|
|
605
641
|
let functionScope = this.getFunctionScopeAtPosition(position);
|
|
606
642
|
if (!functionScope) {
|
|
607
643
|
//we aren't in any function scope, so return the keyword completions and namespaces
|
|
608
|
-
if (this.getTokenBefore(currentToken,
|
|
644
|
+
if (this.getTokenBefore(currentToken, TokenKind_1.TokenKind.New)) {
|
|
609
645
|
// there's a new keyword, so only class types are viable here
|
|
610
646
|
return [...this.getGlobalClassStatementCompletions(currentToken, this.parseMode)];
|
|
611
647
|
}
|
|
612
648
|
else {
|
|
613
|
-
return [
|
|
649
|
+
return [
|
|
650
|
+
...exports.KeywordCompletions,
|
|
651
|
+
...this.getGlobalClassStatementCompletions(currentToken, this.parseMode),
|
|
652
|
+
...namespaceCompletions,
|
|
653
|
+
...this.getNonNamespacedEnumStatementCompletions(currentToken, this.parseMode, scope)
|
|
654
|
+
];
|
|
614
655
|
}
|
|
615
656
|
}
|
|
616
657
|
const classNameCompletions = this.getGlobalClassStatementCompletions(currentToken, this.parseMode);
|
|
617
|
-
const newToken = this.getTokenBefore(currentToken,
|
|
658
|
+
const newToken = this.getTokenBefore(currentToken, TokenKind_1.TokenKind.New);
|
|
618
659
|
if (newToken) {
|
|
619
|
-
//we are after a new keyword; so we can only be namespaces or classes at this point
|
|
660
|
+
//we are after a new keyword; so we can only be top-level namespaces or classes at this point
|
|
620
661
|
result.push(...classNameCompletions);
|
|
621
662
|
result.push(...namespaceCompletions);
|
|
622
663
|
return result;
|
|
623
664
|
}
|
|
624
|
-
if (this.tokenFollows(currentToken,
|
|
665
|
+
if (this.tokenFollows(currentToken, TokenKind_1.TokenKind.Goto)) {
|
|
625
666
|
return this.getLabelCompletion(functionScope);
|
|
626
667
|
}
|
|
627
|
-
if (this.isPositionNextToTokenKind(position,
|
|
628
|
-
if (namespaceCompletions.length > 0) {
|
|
629
|
-
//if we matched a namespace, after a dot, it can't be anything else but something from our namespace completions
|
|
630
|
-
return namespaceCompletions;
|
|
631
|
-
}
|
|
668
|
+
if (this.isPositionNextToTokenKind(position, TokenKind_1.TokenKind.Dot)) {
|
|
632
669
|
const selfClassMemberCompletions = this.getClassMemberCompletions(position, currentToken, functionScope, scope);
|
|
633
670
|
if (selfClassMemberCompletions.size > 0) {
|
|
634
671
|
return [...selfClassMemberCompletions.values()].filter((i) => i.label !== 'new');
|
|
@@ -648,6 +685,8 @@ class BrsFile {
|
|
|
648
685
|
result.push(...namespaceCompletions);
|
|
649
686
|
//include class names
|
|
650
687
|
result.push(...classNameCompletions);
|
|
688
|
+
//include enums
|
|
689
|
+
result.push(...this.getNonNamespacedEnumStatementCompletions(currentToken, this.parseMode, scope));
|
|
651
690
|
//include the global callables
|
|
652
691
|
result.push(...scope.getCallablesAsCompletions(this.parseMode));
|
|
653
692
|
//add `m` because that's always valid within a function
|
|
@@ -670,7 +709,7 @@ class BrsFile {
|
|
|
670
709
|
kind: (0, reflection_1.isFunctionType)(variable.type) ? vscode_languageserver_1.CompletionItemKind.Function : vscode_languageserver_1.CompletionItemKind.Variable
|
|
671
710
|
});
|
|
672
711
|
}
|
|
673
|
-
if (this.parseMode ===
|
|
712
|
+
if (this.parseMode === Parser_1.ParseMode.BrighterScript) {
|
|
674
713
|
//include the first part of namespaces
|
|
675
714
|
let namespaces = scope.getAllNamespaceStatements();
|
|
676
715
|
for (let stmt of namespaces) {
|
|
@@ -700,7 +739,7 @@ class BrsFile {
|
|
|
700
739
|
let classStatement = this.getClassFromMReference(position, currentToken, functionScope);
|
|
701
740
|
let results = new Map();
|
|
702
741
|
if (classStatement) {
|
|
703
|
-
let classes = scope.getClassHierarchy(classStatement.item.getName(
|
|
742
|
+
let classes = scope.getClassHierarchy(classStatement.item.getName(Parser_1.ParseMode.BrighterScript).toLowerCase());
|
|
704
743
|
for (let cs of classes) {
|
|
705
744
|
for (let member of [...(_b = (_a = cs === null || cs === void 0 ? void 0 : cs.item) === null || _a === void 0 ? void 0 : _a.fields) !== null && _b !== void 0 ? _b : [], ...(_d = (_c = cs === null || cs === void 0 ? void 0 : cs.item) === null || _c === void 0 ? void 0 : _c.methods) !== null && _d !== void 0 ? _d : []]) {
|
|
706
745
|
if (!results.has(member.name.text.toLowerCase())) {
|
|
@@ -716,28 +755,27 @@ class BrsFile {
|
|
|
716
755
|
}
|
|
717
756
|
getClassFromMReference(position, currentToken, functionScope) {
|
|
718
757
|
let previousToken = this.getPreviousToken(currentToken);
|
|
719
|
-
if ((previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind) ===
|
|
758
|
+
if ((previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind) === TokenKind_1.TokenKind.Dot) {
|
|
720
759
|
previousToken = this.getPreviousToken(previousToken);
|
|
721
760
|
}
|
|
722
|
-
if ((previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind) ===
|
|
761
|
+
if ((previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind) === TokenKind_1.TokenKind.Identifier && (previousToken === null || previousToken === void 0 ? void 0 : previousToken.text.toLowerCase()) === 'm' && (0, reflection_1.isClassMethodStatement)(functionScope.func.functionStatement)) {
|
|
723
762
|
return { item: this.parser.references.classStatements.find((cs) => util_1.util.rangeContains(cs.range, position)), file: this };
|
|
724
763
|
}
|
|
725
764
|
return undefined;
|
|
726
765
|
}
|
|
727
766
|
getGlobalClassStatementCompletions(currentToken, parseMode) {
|
|
728
767
|
var _a;
|
|
729
|
-
if (parseMode ===
|
|
768
|
+
if (parseMode === Parser_1.ParseMode.BrightScript) {
|
|
730
769
|
return [];
|
|
731
770
|
}
|
|
732
771
|
let results = new Map();
|
|
733
|
-
let completionName = (_a = this.getPartialVariableName(currentToken, [
|
|
772
|
+
let completionName = (_a = this.getPartialVariableName(currentToken, [TokenKind_1.TokenKind.New])) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
734
773
|
if (completionName === null || completionName === void 0 ? void 0 : completionName.includes('.')) {
|
|
735
774
|
return [];
|
|
736
775
|
}
|
|
737
776
|
let scopes = this.program.getScopesForFile(this);
|
|
738
777
|
for (let scope of scopes) {
|
|
739
778
|
let classMap = scope.getClassMap();
|
|
740
|
-
// let viableKeys = [...classMap.keys()].filter((k) => k.startsWith(completionName));
|
|
741
779
|
for (const key of [...classMap.keys()]) {
|
|
742
780
|
let cs = classMap.get(key).item;
|
|
743
781
|
if (!results.has(cs.name.text)) {
|
|
@@ -750,19 +788,70 @@ class BrsFile {
|
|
|
750
788
|
}
|
|
751
789
|
return [...results.values()];
|
|
752
790
|
}
|
|
791
|
+
getNonNamespacedEnumStatementCompletions(currentToken, parseMode, scope) {
|
|
792
|
+
var _a, _b;
|
|
793
|
+
if (parseMode !== Parser_1.ParseMode.BrighterScript) {
|
|
794
|
+
return [];
|
|
795
|
+
}
|
|
796
|
+
const containingNamespaceName = ((_b = this.getNamespaceStatementForPosition((_a = currentToken === null || currentToken === void 0 ? void 0 : currentToken.range) === null || _a === void 0 ? void 0 : _a.start)) === null || _b === void 0 ? void 0 : _b.name) + '.';
|
|
797
|
+
const results = new Map();
|
|
798
|
+
const enumMap = scope.getEnumMap();
|
|
799
|
+
for (const key of [...enumMap.keys()]) {
|
|
800
|
+
const enumStatement = enumMap.get(key).item;
|
|
801
|
+
const fullName = enumStatement.fullName;
|
|
802
|
+
//if the enum is contained within our own namespace, or if it's a non-namespaced enum
|
|
803
|
+
if (fullName.startsWith(containingNamespaceName) || !fullName.includes('.')) {
|
|
804
|
+
results.set(fullName, {
|
|
805
|
+
label: enumStatement.name,
|
|
806
|
+
kind: vscode_languageserver_1.CompletionItemKind.Enum
|
|
807
|
+
});
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
return [...results.values()];
|
|
811
|
+
}
|
|
812
|
+
getEnumMemberStatementCompletions(currentToken, parseMode, scope) {
|
|
813
|
+
var _a, _b, _c, _d, _e;
|
|
814
|
+
if (parseMode === Parser_1.ParseMode.BrightScript || !currentToken) {
|
|
815
|
+
return [];
|
|
816
|
+
}
|
|
817
|
+
const results = new Map();
|
|
818
|
+
const completionName = (_a = this.getPartialVariableName(currentToken)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
819
|
+
//if we don't have a completion name, or if there's no period in the name, then this is not to the right of an enum name
|
|
820
|
+
if (!completionName || !completionName.includes('.')) {
|
|
821
|
+
return [];
|
|
822
|
+
}
|
|
823
|
+
const enumNameLower = (_b = completionName === null || completionName === void 0 ? void 0 : completionName.split(/\.(\w+)?$/)[0]) === null || _b === void 0 ? void 0 : _b.toLowerCase();
|
|
824
|
+
const namespaceNameLower = (_c = this.getNamespaceStatementForPosition(currentToken.range.end)) === null || _c === void 0 ? void 0 : _c.name.toLowerCase();
|
|
825
|
+
const enumMap = scope.getEnumMap();
|
|
826
|
+
//get the enum statement with this name (check without namespace prefix first, then with inferred namespace prefix next)
|
|
827
|
+
const enumStatement = (_e = ((_d = enumMap.get(enumNameLower)) !== null && _d !== void 0 ? _d : enumMap.get(namespaceNameLower + '.' + enumNameLower))) === null || _e === void 0 ? void 0 : _e.item;
|
|
828
|
+
//if we found an enum with this name
|
|
829
|
+
if (enumStatement) {
|
|
830
|
+
for (const member of enumStatement.getMembers()) {
|
|
831
|
+
const name = enumStatement.fullName + '.' + member.name;
|
|
832
|
+
const nameLower = name.toLowerCase();
|
|
833
|
+
results.set(nameLower, {
|
|
834
|
+
label: member.name,
|
|
835
|
+
kind: vscode_languageserver_1.CompletionItemKind.EnumMember
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
return [...results.values()];
|
|
840
|
+
}
|
|
753
841
|
getNamespaceCompletions(currentToken, parseMode, scope) {
|
|
754
842
|
//BrightScript does not support namespaces, so return an empty list in that case
|
|
755
|
-
if (parseMode ===
|
|
843
|
+
if (parseMode === Parser_1.ParseMode.BrightScript) {
|
|
756
844
|
return [];
|
|
757
845
|
}
|
|
758
|
-
|
|
759
|
-
if
|
|
846
|
+
const completionName = this.getPartialVariableName(currentToken, [TokenKind_1.TokenKind.New]);
|
|
847
|
+
//if we don't have a completion name, or if there's no period in the name, then this is not a namespaced variable
|
|
848
|
+
if (!completionName || !completionName.includes('.')) {
|
|
760
849
|
return [];
|
|
761
850
|
}
|
|
762
851
|
//remove any trailing identifer and then any trailing dot, to give us the
|
|
763
852
|
//name of its immediate parent namespace
|
|
764
|
-
let closestParentNamespaceName = completionName.replace(/\.([a-z0-9_]*)?$/gi, '');
|
|
765
|
-
let newToken = this.getTokenBefore(currentToken,
|
|
853
|
+
let closestParentNamespaceName = completionName.replace(/\.([a-z0-9_]*)?$/gi, '').toLowerCase();
|
|
854
|
+
let newToken = this.getTokenBefore(currentToken, TokenKind_1.TokenKind.New);
|
|
766
855
|
let result = new Map();
|
|
767
856
|
for (let [, namespace] of scope.namespaceLookup) {
|
|
768
857
|
//completionName = "NameA."
|
|
@@ -770,7 +859,7 @@ class BrsFile {
|
|
|
770
859
|
//NameA
|
|
771
860
|
//NameA.NameB
|
|
772
861
|
//NameA.NameB.NameC
|
|
773
|
-
if (namespace.fullName.toLowerCase() === closestParentNamespaceName
|
|
862
|
+
if (namespace.fullName.toLowerCase() === closestParentNamespaceName) {
|
|
774
863
|
//add all of this namespace's immediate child namespaces, bearing in mind if we are after a new keyword
|
|
775
864
|
for (let [, ns] of namespace.namespaces) {
|
|
776
865
|
if (!newToken || ns.statements.find((s) => (0, reflection_1.isClassStatement)(s))) {
|
|
@@ -785,20 +874,22 @@ class BrsFile {
|
|
|
785
874
|
//add function and class statement completions
|
|
786
875
|
for (let stmt of namespace.statements) {
|
|
787
876
|
if ((0, reflection_1.isClassStatement)(stmt)) {
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
});
|
|
793
|
-
}
|
|
877
|
+
result.set(stmt.name.text, {
|
|
878
|
+
label: stmt.name.text,
|
|
879
|
+
kind: vscode_languageserver_1.CompletionItemKind.Class
|
|
880
|
+
});
|
|
794
881
|
}
|
|
795
882
|
else if ((0, reflection_1.isFunctionStatement)(stmt) && !newToken) {
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
883
|
+
result.set(stmt.name.text, {
|
|
884
|
+
label: stmt.name.text,
|
|
885
|
+
kind: vscode_languageserver_1.CompletionItemKind.Function
|
|
886
|
+
});
|
|
887
|
+
}
|
|
888
|
+
else if ((0, reflection_1.isEnumStatement)(stmt) && !newToken) {
|
|
889
|
+
result.set(stmt.name, {
|
|
890
|
+
label: stmt.name,
|
|
891
|
+
kind: vscode_languageserver_1.CompletionItemKind.Enum
|
|
892
|
+
});
|
|
802
893
|
}
|
|
803
894
|
}
|
|
804
895
|
}
|
|
@@ -811,11 +902,11 @@ class BrsFile {
|
|
|
811
902
|
return undefined;
|
|
812
903
|
}
|
|
813
904
|
let location;
|
|
814
|
-
const nameParts = this.getPartialVariableName(token, [
|
|
905
|
+
const nameParts = this.getPartialVariableName(token, [TokenKind_1.TokenKind.New]).split('.');
|
|
815
906
|
const endName = nameParts[nameParts.length - 1].toLowerCase();
|
|
816
907
|
const namespaceName = nameParts.slice(0, -1).join('.').toLowerCase();
|
|
817
908
|
const statementHandler = (statement) => {
|
|
818
|
-
if (!location && statement.getName(
|
|
909
|
+
if (!location && statement.getName(Parser_1.ParseMode.BrighterScript).toLowerCase() === namespaceName) {
|
|
819
910
|
const namespaceItemStatementHandler = (statement) => {
|
|
820
911
|
if (!location && statement.name.text.toLowerCase() === endName) {
|
|
821
912
|
const uri = util_1.util.pathToUri(file.pathAbsolute);
|
|
@@ -841,7 +932,7 @@ class BrsFile {
|
|
|
841
932
|
* Given a current token, walk
|
|
842
933
|
*/
|
|
843
934
|
getPartialVariableName(currentToken, excludeTokens = null) {
|
|
844
|
-
let identifierAndDotKinds = [
|
|
935
|
+
let identifierAndDotKinds = [TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedLocalIdentifiers, TokenKind_1.TokenKind.Dot];
|
|
845
936
|
//consume tokens backwards until we find something other than a dot or an identifier
|
|
846
937
|
let tokens = [];
|
|
847
938
|
const parser = this.parser;
|
|
@@ -867,17 +958,17 @@ class BrsFile {
|
|
|
867
958
|
const previousToken = this.getPreviousToken(closestToken);
|
|
868
959
|
const previousTokenKind = previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind;
|
|
869
960
|
//next to matched token
|
|
870
|
-
if (!closestToken || closestToken.kind ===
|
|
961
|
+
if (!closestToken || closestToken.kind === TokenKind_1.TokenKind.Eof) {
|
|
871
962
|
return false;
|
|
872
963
|
}
|
|
873
964
|
else if (closestToken.kind === tokenKind) {
|
|
874
965
|
return true;
|
|
875
966
|
}
|
|
876
|
-
else if (closestToken.kind ===
|
|
967
|
+
else if (closestToken.kind === TokenKind_1.TokenKind.Newline || previousTokenKind === TokenKind_1.TokenKind.Newline) {
|
|
877
968
|
return false;
|
|
878
969
|
//next to an identifier, which is next to token kind
|
|
879
970
|
}
|
|
880
|
-
else if (closestToken.kind ===
|
|
971
|
+
else if (closestToken.kind === TokenKind_1.TokenKind.Identifier && previousTokenKind === tokenKind) {
|
|
881
972
|
return true;
|
|
882
973
|
}
|
|
883
974
|
else {
|
|
@@ -888,7 +979,7 @@ class BrsFile {
|
|
|
888
979
|
const index = this.parser.tokens.indexOf(currentToken);
|
|
889
980
|
for (let i = index - 1; i >= 0; i--) {
|
|
890
981
|
currentToken = this.parser.tokens[i];
|
|
891
|
-
if (currentToken.kind ===
|
|
982
|
+
if (currentToken.kind === TokenKind_1.TokenKind.Newline) {
|
|
892
983
|
break;
|
|
893
984
|
}
|
|
894
985
|
else if (currentToken.kind === tokenKind) {
|
|
@@ -908,7 +999,7 @@ class BrsFile {
|
|
|
908
999
|
let tokens = [];
|
|
909
1000
|
for (let i = this.parser.tokens.indexOf(currentToken); direction === -1 ? i >= 0 : i === this.parser.tokens.length; i += direction) {
|
|
910
1001
|
currentToken = this.parser.tokens[i];
|
|
911
|
-
if (currentToken.kind ===
|
|
1002
|
+
if (currentToken.kind === TokenKind_1.TokenKind.Newline || currentToken.kind === tokenKind) {
|
|
912
1003
|
break;
|
|
913
1004
|
}
|
|
914
1005
|
tokens.push(currentToken);
|
|
@@ -1052,7 +1143,7 @@ class BrsFile {
|
|
|
1052
1143
|
else {
|
|
1053
1144
|
return;
|
|
1054
1145
|
}
|
|
1055
|
-
const name = (0, reflection_1.isClassFieldStatement)(statement) ? statement.name.text : statement.getName(
|
|
1146
|
+
const name = (0, reflection_1.isClassFieldStatement)(statement) ? statement.name.text : statement.getName(Parser_1.ParseMode.BrighterScript);
|
|
1056
1147
|
return vscode_languageserver_1.DocumentSymbol.create(name, '', symbolKind, statement.range, statement.range, children);
|
|
1057
1148
|
}
|
|
1058
1149
|
/**
|
|
@@ -1086,9 +1177,9 @@ class BrsFile {
|
|
|
1086
1177
|
else {
|
|
1087
1178
|
return symbols;
|
|
1088
1179
|
}
|
|
1089
|
-
const name = statement.getName(
|
|
1180
|
+
const name = statement.getName(Parser_1.ParseMode.BrighterScript);
|
|
1090
1181
|
const uri = util_1.util.pathToUri(this.pathAbsolute);
|
|
1091
|
-
const symbol = vscode_languageserver_1.SymbolInformation.create(name, symbolKind, statement.range, uri, containerStatement === null || containerStatement === void 0 ? void 0 : containerStatement.getName(
|
|
1182
|
+
const symbol = vscode_languageserver_1.SymbolInformation.create(name, symbolKind, statement.range, uri, containerStatement === null || containerStatement === void 0 ? void 0 : containerStatement.getName(Parser_1.ParseMode.BrighterScript));
|
|
1092
1183
|
symbols.push(symbol);
|
|
1093
1184
|
return symbols;
|
|
1094
1185
|
}
|
|
@@ -1102,8 +1193,8 @@ class BrsFile {
|
|
|
1102
1193
|
const token = this.getTokenAt(position);
|
|
1103
1194
|
// While certain other tokens are allowed as local variables (AllowedLocalIdentifiers: https://github.com/rokucommunity/brighterscript/blob/master/src/lexer/TokenKind.ts#L418), these are converted by the parser to TokenKind.Identifier by the time we retrieve the token using getTokenAt
|
|
1104
1195
|
let definitionTokenTypes = [
|
|
1105
|
-
|
|
1106
|
-
|
|
1196
|
+
TokenKind_1.TokenKind.Identifier,
|
|
1197
|
+
TokenKind_1.TokenKind.StringLiteral
|
|
1107
1198
|
];
|
|
1108
1199
|
//throw out invalid tokens and the wrong kind of tokens
|
|
1109
1200
|
if (!token || !definitionTokenTypes.includes(token.kind)) {
|
|
@@ -1111,7 +1202,7 @@ class BrsFile {
|
|
|
1111
1202
|
}
|
|
1112
1203
|
let textToSearchFor = token.text.toLowerCase();
|
|
1113
1204
|
const previousToken = this.getTokenAt({ line: token.range.start.line, character: token.range.start.character });
|
|
1114
|
-
if ((previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind) ===
|
|
1205
|
+
if ((previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind) === TokenKind_1.TokenKind.Callfunc) {
|
|
1115
1206
|
for (const scope of this.program.getScopes()) {
|
|
1116
1207
|
//to only get functions defined in interface methods
|
|
1117
1208
|
const callable = scope.getAllCallables().find((c) => c.callable.name.toLowerCase() === textToSearchFor); // eslint-disable-line @typescript-eslint/no-loop-func
|
|
@@ -1121,7 +1212,7 @@ class BrsFile {
|
|
|
1121
1212
|
}
|
|
1122
1213
|
return results;
|
|
1123
1214
|
}
|
|
1124
|
-
let classToken = this.getTokenBefore(token,
|
|
1215
|
+
let classToken = this.getTokenBefore(token, TokenKind_1.TokenKind.Class);
|
|
1125
1216
|
if (classToken) {
|
|
1126
1217
|
let cs = this.parser.references.classStatements.find((cs) => cs.classKeyword.range === classToken.range);
|
|
1127
1218
|
if (cs === null || cs === void 0 ? void 0 : cs.parentClassName) {
|
|
@@ -1133,7 +1224,7 @@ class BrsFile {
|
|
|
1133
1224
|
}
|
|
1134
1225
|
return results;
|
|
1135
1226
|
}
|
|
1136
|
-
if (token.kind ===
|
|
1227
|
+
if (token.kind === TokenKind_1.TokenKind.StringLiteral) {
|
|
1137
1228
|
// We need to strip off the quotes but only if present
|
|
1138
1229
|
const startIndex = textToSearchFor.startsWith('"') ? 1 : 0;
|
|
1139
1230
|
let endIndex = textToSearchFor.length;
|
|
@@ -1153,7 +1244,7 @@ class BrsFile {
|
|
|
1153
1244
|
results.push(vscode_languageserver_1.Location.create(uri, varDeclaration.nameRange));
|
|
1154
1245
|
}
|
|
1155
1246
|
}
|
|
1156
|
-
if (this.tokenFollows(token,
|
|
1247
|
+
if (this.tokenFollows(token, TokenKind_1.TokenKind.Goto)) {
|
|
1157
1248
|
for (const label of functionScope.labelStatements) {
|
|
1158
1249
|
if (label.name.toLocaleLowerCase() === textToSearchFor) {
|
|
1159
1250
|
const uri = util_1.util.pathToUri(this.pathAbsolute);
|
|
@@ -1170,7 +1261,7 @@ class BrsFile {
|
|
|
1170
1261
|
continue;
|
|
1171
1262
|
}
|
|
1172
1263
|
filesSearched.add(file);
|
|
1173
|
-
if ((previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind) ===
|
|
1264
|
+
if ((previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind) === TokenKind_1.TokenKind.Dot && file.parseMode === Parser_1.ParseMode.BrighterScript) {
|
|
1174
1265
|
results.push(...this.getClassMemberDefinitions(textToSearchFor, file));
|
|
1175
1266
|
const namespaceDefinition = this.getNamespaceDefinitions(token, file);
|
|
1176
1267
|
if (namespaceDefinition) {
|
|
@@ -1214,14 +1305,15 @@ class BrsFile {
|
|
|
1214
1305
|
return results;
|
|
1215
1306
|
}
|
|
1216
1307
|
getHover(position) {
|
|
1308
|
+
const fence = (code) => util_1.util.mdFence(code, 'brightscript');
|
|
1217
1309
|
//get the token at the position
|
|
1218
1310
|
let token = this.getTokenAt(position);
|
|
1219
1311
|
let hoverTokenTypes = [
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1312
|
+
TokenKind_1.TokenKind.Identifier,
|
|
1313
|
+
TokenKind_1.TokenKind.Function,
|
|
1314
|
+
TokenKind_1.TokenKind.EndFunction,
|
|
1315
|
+
TokenKind_1.TokenKind.Sub,
|
|
1316
|
+
TokenKind_1.TokenKind.EndSub
|
|
1225
1317
|
];
|
|
1226
1318
|
//throw out invalid tokens and the wrong kind of tokens
|
|
1227
1319
|
if (!token || !hoverTokenTypes.includes(token.kind)) {
|
|
@@ -1247,7 +1339,7 @@ class BrsFile {
|
|
|
1247
1339
|
return {
|
|
1248
1340
|
range: token.range,
|
|
1249
1341
|
//append the variable name to the front for scope
|
|
1250
|
-
contents: typeText
|
|
1342
|
+
contents: fence(typeText)
|
|
1251
1343
|
};
|
|
1252
1344
|
}
|
|
1253
1345
|
}
|
|
@@ -1255,7 +1347,7 @@ class BrsFile {
|
|
|
1255
1347
|
if (labelStatement.name.toLocaleLowerCase() === lowerTokenText) {
|
|
1256
1348
|
return {
|
|
1257
1349
|
range: token.range,
|
|
1258
|
-
contents: `${labelStatement.name}: label`
|
|
1350
|
+
contents: fence(`${labelStatement.name}: label`)
|
|
1259
1351
|
};
|
|
1260
1352
|
}
|
|
1261
1353
|
}
|
|
@@ -1269,12 +1361,41 @@ class BrsFile {
|
|
|
1269
1361
|
if (callable) {
|
|
1270
1362
|
return {
|
|
1271
1363
|
range: token.range,
|
|
1272
|
-
contents:
|
|
1364
|
+
contents: this.getCallableDocumentation(callable)
|
|
1273
1365
|
};
|
|
1274
1366
|
}
|
|
1275
1367
|
}
|
|
1276
1368
|
}
|
|
1277
1369
|
}
|
|
1370
|
+
/**
|
|
1371
|
+
* Build a hover documentation for a callable.
|
|
1372
|
+
*/
|
|
1373
|
+
getCallableDocumentation(callable) {
|
|
1374
|
+
var _a;
|
|
1375
|
+
const comments = [];
|
|
1376
|
+
const tokens = callable.file.parser.tokens;
|
|
1377
|
+
const idx = tokens.indexOf((_a = callable.functionStatement) === null || _a === void 0 ? void 0 : _a.func.functionType);
|
|
1378
|
+
for (let i = idx - 1; i >= 0; i--) {
|
|
1379
|
+
const token = tokens[i];
|
|
1380
|
+
//skip whitespace and newline chars
|
|
1381
|
+
if (token.kind === TokenKind_1.TokenKind.Comment) {
|
|
1382
|
+
comments.push(token);
|
|
1383
|
+
}
|
|
1384
|
+
else if (token.kind === TokenKind_1.TokenKind.Newline || token.kind === TokenKind_1.TokenKind.Whitespace) {
|
|
1385
|
+
//skip these tokens
|
|
1386
|
+
continue;
|
|
1387
|
+
//any other token means there are no more comments
|
|
1388
|
+
}
|
|
1389
|
+
else {
|
|
1390
|
+
break;
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
let result = util_1.util.mdFence(callable.type.toString(), 'brightscript');
|
|
1394
|
+
if (comments.length > 0) {
|
|
1395
|
+
result += '\n***\n' + comments.reverse().map(x => x.text.replace(/^('|rem)/i, '')).join('\n');
|
|
1396
|
+
}
|
|
1397
|
+
return result;
|
|
1398
|
+
}
|
|
1278
1399
|
getSignatureHelpForNamespaceMethods(callableName, dottedGetText, scope) {
|
|
1279
1400
|
var _a;
|
|
1280
1401
|
if (!dottedGetText) {
|
|
@@ -1321,12 +1442,12 @@ class BrsFile {
|
|
|
1321
1442
|
}
|
|
1322
1443
|
}
|
|
1323
1444
|
const kind = currentToken.kind;
|
|
1324
|
-
if (kind ===
|
|
1445
|
+
if (kind === TokenKind_1.TokenKind.Comment) {
|
|
1325
1446
|
// Strip off common leading characters to make it easier to read
|
|
1326
1447
|
const commentText = currentToken.text.replace(/^[' *\/]+/, '');
|
|
1327
1448
|
functionComments.unshift(commentText);
|
|
1328
1449
|
}
|
|
1329
|
-
else if (kind ===
|
|
1450
|
+
else if (kind === TokenKind_1.TokenKind.Newline) {
|
|
1330
1451
|
if (functionComments.length === 0) {
|
|
1331
1452
|
continue;
|
|
1332
1453
|
}
|
|
@@ -1385,7 +1506,7 @@ class BrsFile {
|
|
|
1385
1506
|
const classConstructor = this.getClassMethod(classStatement, 'new');
|
|
1386
1507
|
let sigHelp = classConstructor ? this.getSignatureHelpForStatement(classConstructor) : undefined;
|
|
1387
1508
|
if (sigHelp) {
|
|
1388
|
-
sigHelp.key = classStatement.getName(
|
|
1509
|
+
sigHelp.key = classStatement.getName(Parser_1.ParseMode.BrighterScript);
|
|
1389
1510
|
sigHelp.signature.label = sigHelp.signature.label.replace(/(function|sub) new/, sigHelp.key);
|
|
1390
1511
|
}
|
|
1391
1512
|
return sigHelp;
|
|
@@ -1462,7 +1583,7 @@ exports.BrsFile = BrsFile;
|
|
|
1462
1583
|
* List of completions for all valid keywords/reserved words.
|
|
1463
1584
|
* Build this list once because it won't change for the lifetime of this process
|
|
1464
1585
|
*/
|
|
1465
|
-
exports.KeywordCompletions = Object.keys(
|
|
1586
|
+
exports.KeywordCompletions = Object.keys(TokenKind_1.Keywords)
|
|
1466
1587
|
//remove any keywords with whitespace
|
|
1467
1588
|
.filter(x => !x.includes(' '))
|
|
1468
1589
|
//create completions
|