brighterscript 0.41.4 → 0.43.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 +38 -0
- package/dist/LanguageServer.js +0 -9
- package/dist/LanguageServer.js.map +1 -1
- package/dist/Program.d.ts +1 -1
- package/dist/Program.js +45 -10
- package/dist/Program.js.map +1 -1
- package/dist/ProgramBuilder.js +3 -3
- package/dist/ProgramBuilder.js.map +1 -1
- package/dist/Scope.d.ts +6 -5
- package/dist/Scope.js +33 -32
- package/dist/Scope.js.map +1 -1
- package/dist/astUtils/AstEditor.d.ts +27 -0
- package/dist/astUtils/AstEditor.js +97 -0
- package/dist/astUtils/AstEditor.js.map +1 -0
- package/dist/astUtils/AstEditor.spec.d.ts +1 -0
- package/dist/astUtils/AstEditor.spec.js +133 -0
- package/dist/astUtils/AstEditor.spec.js.map +1 -0
- package/dist/astUtils/reflection.d.ts +2 -1
- package/dist/astUtils/reflection.js +6 -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.spec.js +13 -16
- package/dist/astUtils/visitors.spec.js.map +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +3 -3
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js +4 -4
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js.map +1 -1
- package/dist/files/BrsFile.Class.spec.js +182 -78
- package/dist/files/BrsFile.Class.spec.js.map +1 -1
- package/dist/files/BrsFile.d.ts +11 -5
- package/dist/files/BrsFile.js +111 -77
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/BrsFile.spec.js +150 -101
- package/dist/files/BrsFile.spec.js.map +1 -1
- package/dist/files/XmlFile.d.ts +1 -0
- package/dist/files/XmlFile.js +9 -8
- package/dist/files/XmlFile.js.map +1 -1
- package/dist/files/XmlFile.spec.js +42 -40
- package/dist/files/XmlFile.spec.js.map +1 -1
- package/dist/files/tests/imports.spec.js +6 -4
- package/dist/files/tests/imports.spec.js.map +1 -1
- package/dist/globalCallables.d.ts +3 -1
- package/dist/globalCallables.js +200 -100
- package/dist/globalCallables.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 +49 -4
- package/dist/lexer/Lexer.js +1 -2
- package/dist/lexer/Lexer.js.map +1 -1
- package/dist/lexer/Lexer.spec.js +462 -462
- package/dist/lexer/Lexer.spec.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 +13 -1
- package/dist/parser/Parser.js +355 -253
- 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/Statement.d.ts +2 -2
- package/dist/parser/Statement.js +8 -8
- package/dist/parser/Statement.js.map +1 -1
- package/dist/parser/Statement.spec.js +4 -4
- 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 +30 -18
- 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 +3 -2
- 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 +7 -7
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TernaryExpression.spec.js +6 -6
- 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/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/util.d.ts +5 -1
- package/dist/util.js +43 -33
- 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/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,7 @@ 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;
|
|
40
41
|
this.diagnostics = [];
|
|
41
42
|
this.commentFlags = [];
|
|
42
43
|
this.callables = [];
|
|
@@ -57,7 +58,7 @@ class BrsFile {
|
|
|
57
58
|
//all BrighterScript files need to be transpiled
|
|
58
59
|
if ((_a = this.extension) === null || _a === void 0 ? void 0 : _a.endsWith('.bs')) {
|
|
59
60
|
this.needsTranspiled = true;
|
|
60
|
-
this.parseMode =
|
|
61
|
+
this.parseMode = Parser_1.ParseMode.BrighterScript;
|
|
61
62
|
}
|
|
62
63
|
this.isTypedef = this.extension === '.d.bs';
|
|
63
64
|
if (!this.isTypedef) {
|
|
@@ -149,7 +150,7 @@ class BrsFile {
|
|
|
149
150
|
}
|
|
150
151
|
//tokenize the input file
|
|
151
152
|
let lexer = this.program.logger.time(Logger_1.LogLevel.debug, ['lexer.lex', chalk_1.default.green(this.pathAbsolute)], () => {
|
|
152
|
-
return
|
|
153
|
+
return Lexer_1.Lexer.scan(fileContents, {
|
|
153
154
|
includeWhitespace: false
|
|
154
155
|
});
|
|
155
156
|
});
|
|
@@ -172,32 +173,50 @@ class BrsFile {
|
|
|
172
173
|
//if the preprocessor generated tokens, use them.
|
|
173
174
|
let tokens = preprocessor.processedTokens.length > 0 ? preprocessor.processedTokens : lexer.tokens;
|
|
174
175
|
this.program.logger.time(Logger_1.LogLevel.debug, ['parser.parse', chalk_1.default.green(this.pathAbsolute)], () => {
|
|
175
|
-
this._parser =
|
|
176
|
+
this._parser = Parser_1.Parser.parse(tokens, {
|
|
176
177
|
mode: this.parseMode,
|
|
177
178
|
logger: this.program.logger
|
|
178
179
|
});
|
|
179
180
|
});
|
|
180
181
|
//absorb all lexing/preprocessing/parsing diagnostics
|
|
181
182
|
this.diagnostics.push(...lexer.diagnostics, ...preprocessor.diagnostics, ...this._parser.diagnostics);
|
|
182
|
-
//notify AST ready
|
|
183
|
-
this.program.plugins.emit('afterFileParse', this);
|
|
184
183
|
//extract all callables from this file
|
|
185
184
|
this.findCallables();
|
|
186
185
|
//find all places where a sub/function is being called
|
|
187
186
|
this.findFunctionCalls();
|
|
188
|
-
|
|
187
|
+
//register all import statements for use in the rest of the program
|
|
188
|
+
this.registerImports();
|
|
189
189
|
//attach this file to every diagnostic
|
|
190
190
|
for (let diagnostic of this.diagnostics) {
|
|
191
191
|
diagnostic.file = this;
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
194
|
catch (e) {
|
|
195
|
-
this._parser = new
|
|
195
|
+
this._parser = new Parser_1.Parser();
|
|
196
196
|
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
197
|
}
|
|
198
198
|
}
|
|
199
|
-
|
|
200
|
-
var _a;
|
|
199
|
+
registerImports() {
|
|
200
|
+
var _a, _b, _c, _d;
|
|
201
|
+
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 : []) {
|
|
202
|
+
//register import statements
|
|
203
|
+
if ((0, reflection_1.isImportStatement)(statement) && statement.filePathToken) {
|
|
204
|
+
this.ownScriptImports.push({
|
|
205
|
+
filePathRange: statement.filePathToken.range,
|
|
206
|
+
pkgPath: util_1.util.getPkgPathFromTarget(this.pkgPath, statement.filePath),
|
|
207
|
+
sourceFile: this,
|
|
208
|
+
text: (_d = statement.filePathToken) === null || _d === void 0 ? void 0 : _d.text
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
validate() {
|
|
214
|
+
//only validate the file if it was actually parsed (skip files containing typedefs)
|
|
215
|
+
if (!this.hasTypedef) {
|
|
216
|
+
this.validateImportStatements();
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
validateImportStatements() {
|
|
201
220
|
let topOfFileIncludeStatements = [];
|
|
202
221
|
for (let stmt of this.ast.statements) {
|
|
203
222
|
//skip comments
|
|
@@ -218,15 +237,6 @@ class BrsFile {
|
|
|
218
237
|
...this._parser.references.importStatements
|
|
219
238
|
];
|
|
220
239
|
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
240
|
//if this statement is not one of the top-of-file statements,
|
|
231
241
|
//then add a diagnostic explaining that it is invalid
|
|
232
242
|
if (!topOfFileIncludeStatements.includes(result)) {
|
|
@@ -284,7 +294,7 @@ class BrsFile {
|
|
|
284
294
|
const processor = new CommentFlagProcessor_1.CommentFlagProcessor(this, ['rem', `'`], DiagnosticMessages_1.diagnosticCodes, [DiagnosticMessages_1.DiagnosticCodeMap.unknownDiagnosticCode]);
|
|
285
295
|
this.commentFlags = [];
|
|
286
296
|
for (let token of tokens) {
|
|
287
|
-
if (token.kind ===
|
|
297
|
+
if (token.kind === TokenKind_1.TokenKind.Comment) {
|
|
288
298
|
processor.tryAdd(token.text, token.range);
|
|
289
299
|
}
|
|
290
300
|
}
|
|
@@ -570,10 +580,10 @@ class BrsFile {
|
|
|
570
580
|
//if cursor is within a comment, disable completions
|
|
571
581
|
let currentToken = this.getTokenAt(position);
|
|
572
582
|
const tokenKind = currentToken === null || currentToken === void 0 ? void 0 : currentToken.kind;
|
|
573
|
-
if (tokenKind ===
|
|
583
|
+
if (tokenKind === TokenKind_1.TokenKind.Comment) {
|
|
574
584
|
return [];
|
|
575
585
|
}
|
|
576
|
-
else if (tokenKind ===
|
|
586
|
+
else if (tokenKind === TokenKind_1.TokenKind.StringLiteral || tokenKind === TokenKind_1.TokenKind.TemplateStringQuasi) {
|
|
577
587
|
const match = /^("?)(pkg|libpkg):/.exec(currentToken.text);
|
|
578
588
|
if (match) {
|
|
579
589
|
const [, openingQuote, fileProtocol] = match;
|
|
@@ -605,7 +615,7 @@ class BrsFile {
|
|
|
605
615
|
let functionScope = this.getFunctionScopeAtPosition(position);
|
|
606
616
|
if (!functionScope) {
|
|
607
617
|
//we aren't in any function scope, so return the keyword completions and namespaces
|
|
608
|
-
if (this.getTokenBefore(currentToken,
|
|
618
|
+
if (this.getTokenBefore(currentToken, TokenKind_1.TokenKind.New)) {
|
|
609
619
|
// there's a new keyword, so only class types are viable here
|
|
610
620
|
return [...this.getGlobalClassStatementCompletions(currentToken, this.parseMode)];
|
|
611
621
|
}
|
|
@@ -614,17 +624,17 @@ class BrsFile {
|
|
|
614
624
|
}
|
|
615
625
|
}
|
|
616
626
|
const classNameCompletions = this.getGlobalClassStatementCompletions(currentToken, this.parseMode);
|
|
617
|
-
const newToken = this.getTokenBefore(currentToken,
|
|
627
|
+
const newToken = this.getTokenBefore(currentToken, TokenKind_1.TokenKind.New);
|
|
618
628
|
if (newToken) {
|
|
619
629
|
//we are after a new keyword; so we can only be namespaces or classes at this point
|
|
620
630
|
result.push(...classNameCompletions);
|
|
621
631
|
result.push(...namespaceCompletions);
|
|
622
632
|
return result;
|
|
623
633
|
}
|
|
624
|
-
if (this.tokenFollows(currentToken,
|
|
634
|
+
if (this.tokenFollows(currentToken, TokenKind_1.TokenKind.Goto)) {
|
|
625
635
|
return this.getLabelCompletion(functionScope);
|
|
626
636
|
}
|
|
627
|
-
if (this.isPositionNextToTokenKind(position,
|
|
637
|
+
if (this.isPositionNextToTokenKind(position, TokenKind_1.TokenKind.Dot)) {
|
|
628
638
|
if (namespaceCompletions.length > 0) {
|
|
629
639
|
//if we matched a namespace, after a dot, it can't be anything else but something from our namespace completions
|
|
630
640
|
return namespaceCompletions;
|
|
@@ -670,7 +680,7 @@ class BrsFile {
|
|
|
670
680
|
kind: (0, reflection_1.isFunctionType)(variable.type) ? vscode_languageserver_1.CompletionItemKind.Function : vscode_languageserver_1.CompletionItemKind.Variable
|
|
671
681
|
});
|
|
672
682
|
}
|
|
673
|
-
if (this.parseMode ===
|
|
683
|
+
if (this.parseMode === Parser_1.ParseMode.BrighterScript) {
|
|
674
684
|
//include the first part of namespaces
|
|
675
685
|
let namespaces = scope.getAllNamespaceStatements();
|
|
676
686
|
for (let stmt of namespaces) {
|
|
@@ -700,7 +710,7 @@ class BrsFile {
|
|
|
700
710
|
let classStatement = this.getClassFromMReference(position, currentToken, functionScope);
|
|
701
711
|
let results = new Map();
|
|
702
712
|
if (classStatement) {
|
|
703
|
-
let classes = scope.getClassHierarchy(classStatement.item.getName(
|
|
713
|
+
let classes = scope.getClassHierarchy(classStatement.item.getName(Parser_1.ParseMode.BrighterScript).toLowerCase());
|
|
704
714
|
for (let cs of classes) {
|
|
705
715
|
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
716
|
if (!results.has(member.name.text.toLowerCase())) {
|
|
@@ -716,21 +726,21 @@ class BrsFile {
|
|
|
716
726
|
}
|
|
717
727
|
getClassFromMReference(position, currentToken, functionScope) {
|
|
718
728
|
let previousToken = this.getPreviousToken(currentToken);
|
|
719
|
-
if ((previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind) ===
|
|
729
|
+
if ((previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind) === TokenKind_1.TokenKind.Dot) {
|
|
720
730
|
previousToken = this.getPreviousToken(previousToken);
|
|
721
731
|
}
|
|
722
|
-
if ((previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind) ===
|
|
732
|
+
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
733
|
return { item: this.parser.references.classStatements.find((cs) => util_1.util.rangeContains(cs.range, position)), file: this };
|
|
724
734
|
}
|
|
725
735
|
return undefined;
|
|
726
736
|
}
|
|
727
737
|
getGlobalClassStatementCompletions(currentToken, parseMode) {
|
|
728
738
|
var _a;
|
|
729
|
-
if (parseMode ===
|
|
739
|
+
if (parseMode === Parser_1.ParseMode.BrightScript) {
|
|
730
740
|
return [];
|
|
731
741
|
}
|
|
732
742
|
let results = new Map();
|
|
733
|
-
let completionName = (_a = this.getPartialVariableName(currentToken, [
|
|
743
|
+
let completionName = (_a = this.getPartialVariableName(currentToken, [TokenKind_1.TokenKind.New])) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
734
744
|
if (completionName === null || completionName === void 0 ? void 0 : completionName.includes('.')) {
|
|
735
745
|
return [];
|
|
736
746
|
}
|
|
@@ -752,21 +762,19 @@ class BrsFile {
|
|
|
752
762
|
}
|
|
753
763
|
getNamespaceCompletions(currentToken, parseMode, scope) {
|
|
754
764
|
//BrightScript does not support namespaces, so return an empty list in that case
|
|
755
|
-
if (parseMode ===
|
|
765
|
+
if (parseMode === Parser_1.ParseMode.BrightScript) {
|
|
756
766
|
return [];
|
|
757
767
|
}
|
|
758
|
-
let completionName = this.getPartialVariableName(currentToken, [
|
|
768
|
+
let completionName = this.getPartialVariableName(currentToken, [TokenKind_1.TokenKind.New]);
|
|
759
769
|
if (!completionName) {
|
|
760
770
|
return [];
|
|
761
771
|
}
|
|
762
772
|
//remove any trailing identifer and then any trailing dot, to give us the
|
|
763
773
|
//name of its immediate parent namespace
|
|
764
774
|
let closestParentNamespaceName = completionName.replace(/\.([a-z0-9_]*)?$/gi, '');
|
|
765
|
-
let newToken = this.getTokenBefore(currentToken,
|
|
766
|
-
let namespaceLookup = scope.namespaceLookup;
|
|
775
|
+
let newToken = this.getTokenBefore(currentToken, TokenKind_1.TokenKind.New);
|
|
767
776
|
let result = new Map();
|
|
768
|
-
for (let
|
|
769
|
-
let namespace = namespaceLookup[key.toLowerCase()];
|
|
777
|
+
for (let [, namespace] of scope.namespaceLookup) {
|
|
770
778
|
//completionName = "NameA."
|
|
771
779
|
//completionName = "NameA.Na
|
|
772
780
|
//NameA
|
|
@@ -774,8 +782,7 @@ class BrsFile {
|
|
|
774
782
|
//NameA.NameB.NameC
|
|
775
783
|
if (namespace.fullName.toLowerCase() === closestParentNamespaceName.toLowerCase()) {
|
|
776
784
|
//add all of this namespace's immediate child namespaces, bearing in mind if we are after a new keyword
|
|
777
|
-
for (let
|
|
778
|
-
const ns = namespace.namespaces[childKey];
|
|
785
|
+
for (let [, ns] of namespace.namespaces) {
|
|
779
786
|
if (!newToken || ns.statements.find((s) => (0, reflection_1.isClassStatement)(s))) {
|
|
780
787
|
if (!result.has(ns.lastPartName)) {
|
|
781
788
|
result.set(ns.lastPartName, {
|
|
@@ -814,11 +821,11 @@ class BrsFile {
|
|
|
814
821
|
return undefined;
|
|
815
822
|
}
|
|
816
823
|
let location;
|
|
817
|
-
const nameParts = this.getPartialVariableName(token, [
|
|
824
|
+
const nameParts = this.getPartialVariableName(token, [TokenKind_1.TokenKind.New]).split('.');
|
|
818
825
|
const endName = nameParts[nameParts.length - 1].toLowerCase();
|
|
819
826
|
const namespaceName = nameParts.slice(0, -1).join('.').toLowerCase();
|
|
820
827
|
const statementHandler = (statement) => {
|
|
821
|
-
if (!location && statement.getName(
|
|
828
|
+
if (!location && statement.getName(Parser_1.ParseMode.BrighterScript).toLowerCase() === namespaceName) {
|
|
822
829
|
const namespaceItemStatementHandler = (statement) => {
|
|
823
830
|
if (!location && statement.name.text.toLowerCase() === endName) {
|
|
824
831
|
const uri = util_1.util.pathToUri(file.pathAbsolute);
|
|
@@ -844,7 +851,7 @@ class BrsFile {
|
|
|
844
851
|
* Given a current token, walk
|
|
845
852
|
*/
|
|
846
853
|
getPartialVariableName(currentToken, excludeTokens = null) {
|
|
847
|
-
let identifierAndDotKinds = [
|
|
854
|
+
let identifierAndDotKinds = [TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedLocalIdentifiers, TokenKind_1.TokenKind.Dot];
|
|
848
855
|
//consume tokens backwards until we find something other than a dot or an identifier
|
|
849
856
|
let tokens = [];
|
|
850
857
|
const parser = this.parser;
|
|
@@ -870,17 +877,17 @@ class BrsFile {
|
|
|
870
877
|
const previousToken = this.getPreviousToken(closestToken);
|
|
871
878
|
const previousTokenKind = previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind;
|
|
872
879
|
//next to matched token
|
|
873
|
-
if (!closestToken || closestToken.kind ===
|
|
880
|
+
if (!closestToken || closestToken.kind === TokenKind_1.TokenKind.Eof) {
|
|
874
881
|
return false;
|
|
875
882
|
}
|
|
876
883
|
else if (closestToken.kind === tokenKind) {
|
|
877
884
|
return true;
|
|
878
885
|
}
|
|
879
|
-
else if (closestToken.kind ===
|
|
886
|
+
else if (closestToken.kind === TokenKind_1.TokenKind.Newline || previousTokenKind === TokenKind_1.TokenKind.Newline) {
|
|
880
887
|
return false;
|
|
881
888
|
//next to an identifier, which is next to token kind
|
|
882
889
|
}
|
|
883
|
-
else if (closestToken.kind ===
|
|
890
|
+
else if (closestToken.kind === TokenKind_1.TokenKind.Identifier && previousTokenKind === tokenKind) {
|
|
884
891
|
return true;
|
|
885
892
|
}
|
|
886
893
|
else {
|
|
@@ -891,7 +898,7 @@ class BrsFile {
|
|
|
891
898
|
const index = this.parser.tokens.indexOf(currentToken);
|
|
892
899
|
for (let i = index - 1; i >= 0; i--) {
|
|
893
900
|
currentToken = this.parser.tokens[i];
|
|
894
|
-
if (currentToken.kind ===
|
|
901
|
+
if (currentToken.kind === TokenKind_1.TokenKind.Newline) {
|
|
895
902
|
break;
|
|
896
903
|
}
|
|
897
904
|
else if (currentToken.kind === tokenKind) {
|
|
@@ -911,7 +918,7 @@ class BrsFile {
|
|
|
911
918
|
let tokens = [];
|
|
912
919
|
for (let i = this.parser.tokens.indexOf(currentToken); direction === -1 ? i >= 0 : i === this.parser.tokens.length; i += direction) {
|
|
913
920
|
currentToken = this.parser.tokens[i];
|
|
914
|
-
if (currentToken.kind ===
|
|
921
|
+
if (currentToken.kind === TokenKind_1.TokenKind.Newline || currentToken.kind === tokenKind) {
|
|
915
922
|
break;
|
|
916
923
|
}
|
|
917
924
|
tokens.push(currentToken);
|
|
@@ -937,7 +944,7 @@ class BrsFile {
|
|
|
937
944
|
//find the first scope that contains this namespace
|
|
938
945
|
let scopes = this.program.getScopesForFile(this);
|
|
939
946
|
for (let scope of scopes) {
|
|
940
|
-
if (scope.namespaceLookup
|
|
947
|
+
if (scope.namespaceLookup.has(lowerName)) {
|
|
941
948
|
return true;
|
|
942
949
|
}
|
|
943
950
|
}
|
|
@@ -955,7 +962,7 @@ class BrsFile {
|
|
|
955
962
|
if (lowerCalleeName) {
|
|
956
963
|
let scopes = this.program.getScopesForFile(this);
|
|
957
964
|
for (let scope of scopes) {
|
|
958
|
-
let namespace = scope.namespaceLookup
|
|
965
|
+
let namespace = scope.namespaceLookup.get(namespaceName.toLowerCase());
|
|
959
966
|
if (namespace.functionStatements[lowerCalleeName]) {
|
|
960
967
|
return true;
|
|
961
968
|
}
|
|
@@ -1055,7 +1062,7 @@ class BrsFile {
|
|
|
1055
1062
|
else {
|
|
1056
1063
|
return;
|
|
1057
1064
|
}
|
|
1058
|
-
const name = (0, reflection_1.isClassFieldStatement)(statement) ? statement.name.text : statement.getName(
|
|
1065
|
+
const name = (0, reflection_1.isClassFieldStatement)(statement) ? statement.name.text : statement.getName(Parser_1.ParseMode.BrighterScript);
|
|
1059
1066
|
return vscode_languageserver_1.DocumentSymbol.create(name, '', symbolKind, statement.range, statement.range, children);
|
|
1060
1067
|
}
|
|
1061
1068
|
/**
|
|
@@ -1089,9 +1096,9 @@ class BrsFile {
|
|
|
1089
1096
|
else {
|
|
1090
1097
|
return symbols;
|
|
1091
1098
|
}
|
|
1092
|
-
const name = statement.getName(
|
|
1099
|
+
const name = statement.getName(Parser_1.ParseMode.BrighterScript);
|
|
1093
1100
|
const uri = util_1.util.pathToUri(this.pathAbsolute);
|
|
1094
|
-
const symbol = vscode_languageserver_1.SymbolInformation.create(name, symbolKind, statement.range, uri, containerStatement === null || containerStatement === void 0 ? void 0 : containerStatement.getName(
|
|
1101
|
+
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));
|
|
1095
1102
|
symbols.push(symbol);
|
|
1096
1103
|
return symbols;
|
|
1097
1104
|
}
|
|
@@ -1105,8 +1112,8 @@ class BrsFile {
|
|
|
1105
1112
|
const token = this.getTokenAt(position);
|
|
1106
1113
|
// 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
|
|
1107
1114
|
let definitionTokenTypes = [
|
|
1108
|
-
|
|
1109
|
-
|
|
1115
|
+
TokenKind_1.TokenKind.Identifier,
|
|
1116
|
+
TokenKind_1.TokenKind.StringLiteral
|
|
1110
1117
|
];
|
|
1111
1118
|
//throw out invalid tokens and the wrong kind of tokens
|
|
1112
1119
|
if (!token || !definitionTokenTypes.includes(token.kind)) {
|
|
@@ -1114,7 +1121,7 @@ class BrsFile {
|
|
|
1114
1121
|
}
|
|
1115
1122
|
let textToSearchFor = token.text.toLowerCase();
|
|
1116
1123
|
const previousToken = this.getTokenAt({ line: token.range.start.line, character: token.range.start.character });
|
|
1117
|
-
if ((previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind) ===
|
|
1124
|
+
if ((previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind) === TokenKind_1.TokenKind.Callfunc) {
|
|
1118
1125
|
for (const scope of this.program.getScopes()) {
|
|
1119
1126
|
//to only get functions defined in interface methods
|
|
1120
1127
|
const callable = scope.getAllCallables().find((c) => c.callable.name.toLowerCase() === textToSearchFor); // eslint-disable-line @typescript-eslint/no-loop-func
|
|
@@ -1124,7 +1131,7 @@ class BrsFile {
|
|
|
1124
1131
|
}
|
|
1125
1132
|
return results;
|
|
1126
1133
|
}
|
|
1127
|
-
let classToken = this.getTokenBefore(token,
|
|
1134
|
+
let classToken = this.getTokenBefore(token, TokenKind_1.TokenKind.Class);
|
|
1128
1135
|
if (classToken) {
|
|
1129
1136
|
let cs = this.parser.references.classStatements.find((cs) => cs.classKeyword.range === classToken.range);
|
|
1130
1137
|
if (cs === null || cs === void 0 ? void 0 : cs.parentClassName) {
|
|
@@ -1136,7 +1143,7 @@ class BrsFile {
|
|
|
1136
1143
|
}
|
|
1137
1144
|
return results;
|
|
1138
1145
|
}
|
|
1139
|
-
if (token.kind ===
|
|
1146
|
+
if (token.kind === TokenKind_1.TokenKind.StringLiteral) {
|
|
1140
1147
|
// We need to strip off the quotes but only if present
|
|
1141
1148
|
const startIndex = textToSearchFor.startsWith('"') ? 1 : 0;
|
|
1142
1149
|
let endIndex = textToSearchFor.length;
|
|
@@ -1156,7 +1163,7 @@ class BrsFile {
|
|
|
1156
1163
|
results.push(vscode_languageserver_1.Location.create(uri, varDeclaration.nameRange));
|
|
1157
1164
|
}
|
|
1158
1165
|
}
|
|
1159
|
-
if (this.tokenFollows(token,
|
|
1166
|
+
if (this.tokenFollows(token, TokenKind_1.TokenKind.Goto)) {
|
|
1160
1167
|
for (const label of functionScope.labelStatements) {
|
|
1161
1168
|
if (label.name.toLocaleLowerCase() === textToSearchFor) {
|
|
1162
1169
|
const uri = util_1.util.pathToUri(this.pathAbsolute);
|
|
@@ -1173,7 +1180,7 @@ class BrsFile {
|
|
|
1173
1180
|
continue;
|
|
1174
1181
|
}
|
|
1175
1182
|
filesSearched.add(file);
|
|
1176
|
-
if ((previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind) ===
|
|
1183
|
+
if ((previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind) === TokenKind_1.TokenKind.Dot && file.parseMode === Parser_1.ParseMode.BrighterScript) {
|
|
1177
1184
|
results.push(...this.getClassMemberDefinitions(textToSearchFor, file));
|
|
1178
1185
|
const namespaceDefinition = this.getNamespaceDefinitions(token, file);
|
|
1179
1186
|
if (namespaceDefinition) {
|
|
@@ -1217,14 +1224,15 @@ class BrsFile {
|
|
|
1217
1224
|
return results;
|
|
1218
1225
|
}
|
|
1219
1226
|
getHover(position) {
|
|
1227
|
+
const fence = (code) => util_1.util.mdFence(code, 'brightscript');
|
|
1220
1228
|
//get the token at the position
|
|
1221
1229
|
let token = this.getTokenAt(position);
|
|
1222
1230
|
let hoverTokenTypes = [
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1231
|
+
TokenKind_1.TokenKind.Identifier,
|
|
1232
|
+
TokenKind_1.TokenKind.Function,
|
|
1233
|
+
TokenKind_1.TokenKind.EndFunction,
|
|
1234
|
+
TokenKind_1.TokenKind.Sub,
|
|
1235
|
+
TokenKind_1.TokenKind.EndSub
|
|
1228
1236
|
];
|
|
1229
1237
|
//throw out invalid tokens and the wrong kind of tokens
|
|
1230
1238
|
if (!token || !hoverTokenTypes.includes(token.kind)) {
|
|
@@ -1250,7 +1258,7 @@ class BrsFile {
|
|
|
1250
1258
|
return {
|
|
1251
1259
|
range: token.range,
|
|
1252
1260
|
//append the variable name to the front for scope
|
|
1253
|
-
contents: typeText
|
|
1261
|
+
contents: fence(typeText)
|
|
1254
1262
|
};
|
|
1255
1263
|
}
|
|
1256
1264
|
}
|
|
@@ -1258,7 +1266,7 @@ class BrsFile {
|
|
|
1258
1266
|
if (labelStatement.name.toLocaleLowerCase() === lowerTokenText) {
|
|
1259
1267
|
return {
|
|
1260
1268
|
range: token.range,
|
|
1261
|
-
contents: `${labelStatement.name}: label`
|
|
1269
|
+
contents: fence(`${labelStatement.name}: label`)
|
|
1262
1270
|
};
|
|
1263
1271
|
}
|
|
1264
1272
|
}
|
|
@@ -1272,21 +1280,47 @@ class BrsFile {
|
|
|
1272
1280
|
if (callable) {
|
|
1273
1281
|
return {
|
|
1274
1282
|
range: token.range,
|
|
1275
|
-
contents:
|
|
1283
|
+
contents: this.getCallableDocumentation(callable)
|
|
1276
1284
|
};
|
|
1277
1285
|
}
|
|
1278
1286
|
}
|
|
1279
1287
|
}
|
|
1280
1288
|
}
|
|
1289
|
+
/**
|
|
1290
|
+
* Build a hover documentation for a callable.
|
|
1291
|
+
*/
|
|
1292
|
+
getCallableDocumentation(callable) {
|
|
1293
|
+
const comments = [];
|
|
1294
|
+
const tokens = callable.file.parser.tokens;
|
|
1295
|
+
const idx = tokens.indexOf(callable.functionStatement.func.functionType);
|
|
1296
|
+
for (let i = idx - 1; i >= 0; i--) {
|
|
1297
|
+
const token = tokens[i];
|
|
1298
|
+
//skip whitespace and newline chars
|
|
1299
|
+
if (token.kind === TokenKind_1.TokenKind.Comment) {
|
|
1300
|
+
comments.push(token);
|
|
1301
|
+
}
|
|
1302
|
+
else if (token.kind === TokenKind_1.TokenKind.Newline || token.kind === TokenKind_1.TokenKind.Whitespace) {
|
|
1303
|
+
//skip these tokens
|
|
1304
|
+
continue;
|
|
1305
|
+
//any other token means there are no more comments
|
|
1306
|
+
}
|
|
1307
|
+
else {
|
|
1308
|
+
break;
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
let result = util_1.util.mdFence(callable.type.toString(), 'brightscript');
|
|
1312
|
+
if (comments.length > 0) {
|
|
1313
|
+
result += '\n***\n' + comments.reverse().map(x => x.text.replace(/^('|rem)/i, '')).join('\n');
|
|
1314
|
+
}
|
|
1315
|
+
return result;
|
|
1316
|
+
}
|
|
1281
1317
|
getSignatureHelpForNamespaceMethods(callableName, dottedGetText, scope) {
|
|
1282
1318
|
var _a;
|
|
1283
1319
|
if (!dottedGetText) {
|
|
1284
1320
|
return [];
|
|
1285
1321
|
}
|
|
1286
|
-
let namespaceLookup = scope.namespaceLookup;
|
|
1287
1322
|
let resultsMap = new Map();
|
|
1288
|
-
for (let
|
|
1289
|
-
let namespace = namespaceLookup[key.toLowerCase()];
|
|
1323
|
+
for (let [, namespace] of scope.namespaceLookup) {
|
|
1290
1324
|
//completionName = "NameA."
|
|
1291
1325
|
//completionName = "NameA.Na
|
|
1292
1326
|
//NameA
|
|
@@ -1326,12 +1360,12 @@ class BrsFile {
|
|
|
1326
1360
|
}
|
|
1327
1361
|
}
|
|
1328
1362
|
const kind = currentToken.kind;
|
|
1329
|
-
if (kind ===
|
|
1363
|
+
if (kind === TokenKind_1.TokenKind.Comment) {
|
|
1330
1364
|
// Strip off common leading characters to make it easier to read
|
|
1331
1365
|
const commentText = currentToken.text.replace(/^[' *\/]+/, '');
|
|
1332
1366
|
functionComments.unshift(commentText);
|
|
1333
1367
|
}
|
|
1334
|
-
else if (kind ===
|
|
1368
|
+
else if (kind === TokenKind_1.TokenKind.Newline) {
|
|
1335
1369
|
if (functionComments.length === 0) {
|
|
1336
1370
|
continue;
|
|
1337
1371
|
}
|
|
@@ -1390,7 +1424,7 @@ class BrsFile {
|
|
|
1390
1424
|
const classConstructor = this.getClassMethod(classStatement, 'new');
|
|
1391
1425
|
let sigHelp = classConstructor ? this.getSignatureHelpForStatement(classConstructor) : undefined;
|
|
1392
1426
|
if (sigHelp) {
|
|
1393
|
-
sigHelp.key = classStatement.getName(
|
|
1427
|
+
sigHelp.key = classStatement.getName(Parser_1.ParseMode.BrighterScript);
|
|
1394
1428
|
sigHelp.signature.label = sigHelp.signature.label.replace(/(function|sub) new/, sigHelp.key);
|
|
1395
1429
|
}
|
|
1396
1430
|
return sigHelp;
|
|
@@ -1467,7 +1501,7 @@ exports.BrsFile = BrsFile;
|
|
|
1467
1501
|
* List of completions for all valid keywords/reserved words.
|
|
1468
1502
|
* Build this list once because it won't change for the lifetime of this process
|
|
1469
1503
|
*/
|
|
1470
|
-
exports.KeywordCompletions = Object.keys(
|
|
1504
|
+
exports.KeywordCompletions = Object.keys(TokenKind_1.Keywords)
|
|
1471
1505
|
//remove any keywords with whitespace
|
|
1472
1506
|
.filter(x => !x.includes(' '))
|
|
1473
1507
|
//create completions
|