brighterscript 0.41.5 → 0.43.1
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 +39 -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 +3 -2
- package/dist/Scope.js +14 -14
- 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 +107 -67
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/BrsFile.spec.js +175 -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 +41 -39
- 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,17 +762,17 @@ 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,
|
|
775
|
+
let newToken = this.getTokenBefore(currentToken, TokenKind_1.TokenKind.New);
|
|
766
776
|
let result = new Map();
|
|
767
777
|
for (let [, namespace] of scope.namespaceLookup) {
|
|
768
778
|
//completionName = "NameA."
|
|
@@ -811,11 +821,11 @@ class BrsFile {
|
|
|
811
821
|
return undefined;
|
|
812
822
|
}
|
|
813
823
|
let location;
|
|
814
|
-
const nameParts = this.getPartialVariableName(token, [
|
|
824
|
+
const nameParts = this.getPartialVariableName(token, [TokenKind_1.TokenKind.New]).split('.');
|
|
815
825
|
const endName = nameParts[nameParts.length - 1].toLowerCase();
|
|
816
826
|
const namespaceName = nameParts.slice(0, -1).join('.').toLowerCase();
|
|
817
827
|
const statementHandler = (statement) => {
|
|
818
|
-
if (!location && statement.getName(
|
|
828
|
+
if (!location && statement.getName(Parser_1.ParseMode.BrighterScript).toLowerCase() === namespaceName) {
|
|
819
829
|
const namespaceItemStatementHandler = (statement) => {
|
|
820
830
|
if (!location && statement.name.text.toLowerCase() === endName) {
|
|
821
831
|
const uri = util_1.util.pathToUri(file.pathAbsolute);
|
|
@@ -841,7 +851,7 @@ class BrsFile {
|
|
|
841
851
|
* Given a current token, walk
|
|
842
852
|
*/
|
|
843
853
|
getPartialVariableName(currentToken, excludeTokens = null) {
|
|
844
|
-
let identifierAndDotKinds = [
|
|
854
|
+
let identifierAndDotKinds = [TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedLocalIdentifiers, TokenKind_1.TokenKind.Dot];
|
|
845
855
|
//consume tokens backwards until we find something other than a dot or an identifier
|
|
846
856
|
let tokens = [];
|
|
847
857
|
const parser = this.parser;
|
|
@@ -867,17 +877,17 @@ class BrsFile {
|
|
|
867
877
|
const previousToken = this.getPreviousToken(closestToken);
|
|
868
878
|
const previousTokenKind = previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind;
|
|
869
879
|
//next to matched token
|
|
870
|
-
if (!closestToken || closestToken.kind ===
|
|
880
|
+
if (!closestToken || closestToken.kind === TokenKind_1.TokenKind.Eof) {
|
|
871
881
|
return false;
|
|
872
882
|
}
|
|
873
883
|
else if (closestToken.kind === tokenKind) {
|
|
874
884
|
return true;
|
|
875
885
|
}
|
|
876
|
-
else if (closestToken.kind ===
|
|
886
|
+
else if (closestToken.kind === TokenKind_1.TokenKind.Newline || previousTokenKind === TokenKind_1.TokenKind.Newline) {
|
|
877
887
|
return false;
|
|
878
888
|
//next to an identifier, which is next to token kind
|
|
879
889
|
}
|
|
880
|
-
else if (closestToken.kind ===
|
|
890
|
+
else if (closestToken.kind === TokenKind_1.TokenKind.Identifier && previousTokenKind === tokenKind) {
|
|
881
891
|
return true;
|
|
882
892
|
}
|
|
883
893
|
else {
|
|
@@ -888,7 +898,7 @@ class BrsFile {
|
|
|
888
898
|
const index = this.parser.tokens.indexOf(currentToken);
|
|
889
899
|
for (let i = index - 1; i >= 0; i--) {
|
|
890
900
|
currentToken = this.parser.tokens[i];
|
|
891
|
-
if (currentToken.kind ===
|
|
901
|
+
if (currentToken.kind === TokenKind_1.TokenKind.Newline) {
|
|
892
902
|
break;
|
|
893
903
|
}
|
|
894
904
|
else if (currentToken.kind === tokenKind) {
|
|
@@ -908,7 +918,7 @@ class BrsFile {
|
|
|
908
918
|
let tokens = [];
|
|
909
919
|
for (let i = this.parser.tokens.indexOf(currentToken); direction === -1 ? i >= 0 : i === this.parser.tokens.length; i += direction) {
|
|
910
920
|
currentToken = this.parser.tokens[i];
|
|
911
|
-
if (currentToken.kind ===
|
|
921
|
+
if (currentToken.kind === TokenKind_1.TokenKind.Newline || currentToken.kind === tokenKind) {
|
|
912
922
|
break;
|
|
913
923
|
}
|
|
914
924
|
tokens.push(currentToken);
|
|
@@ -1052,7 +1062,7 @@ class BrsFile {
|
|
|
1052
1062
|
else {
|
|
1053
1063
|
return;
|
|
1054
1064
|
}
|
|
1055
|
-
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);
|
|
1056
1066
|
return vscode_languageserver_1.DocumentSymbol.create(name, '', symbolKind, statement.range, statement.range, children);
|
|
1057
1067
|
}
|
|
1058
1068
|
/**
|
|
@@ -1086,9 +1096,9 @@ class BrsFile {
|
|
|
1086
1096
|
else {
|
|
1087
1097
|
return symbols;
|
|
1088
1098
|
}
|
|
1089
|
-
const name = statement.getName(
|
|
1099
|
+
const name = statement.getName(Parser_1.ParseMode.BrighterScript);
|
|
1090
1100
|
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(
|
|
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));
|
|
1092
1102
|
symbols.push(symbol);
|
|
1093
1103
|
return symbols;
|
|
1094
1104
|
}
|
|
@@ -1102,8 +1112,8 @@ class BrsFile {
|
|
|
1102
1112
|
const token = this.getTokenAt(position);
|
|
1103
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
|
|
1104
1114
|
let definitionTokenTypes = [
|
|
1105
|
-
|
|
1106
|
-
|
|
1115
|
+
TokenKind_1.TokenKind.Identifier,
|
|
1116
|
+
TokenKind_1.TokenKind.StringLiteral
|
|
1107
1117
|
];
|
|
1108
1118
|
//throw out invalid tokens and the wrong kind of tokens
|
|
1109
1119
|
if (!token || !definitionTokenTypes.includes(token.kind)) {
|
|
@@ -1111,7 +1121,7 @@ class BrsFile {
|
|
|
1111
1121
|
}
|
|
1112
1122
|
let textToSearchFor = token.text.toLowerCase();
|
|
1113
1123
|
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) ===
|
|
1124
|
+
if ((previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind) === TokenKind_1.TokenKind.Callfunc) {
|
|
1115
1125
|
for (const scope of this.program.getScopes()) {
|
|
1116
1126
|
//to only get functions defined in interface methods
|
|
1117
1127
|
const callable = scope.getAllCallables().find((c) => c.callable.name.toLowerCase() === textToSearchFor); // eslint-disable-line @typescript-eslint/no-loop-func
|
|
@@ -1121,7 +1131,7 @@ class BrsFile {
|
|
|
1121
1131
|
}
|
|
1122
1132
|
return results;
|
|
1123
1133
|
}
|
|
1124
|
-
let classToken = this.getTokenBefore(token,
|
|
1134
|
+
let classToken = this.getTokenBefore(token, TokenKind_1.TokenKind.Class);
|
|
1125
1135
|
if (classToken) {
|
|
1126
1136
|
let cs = this.parser.references.classStatements.find((cs) => cs.classKeyword.range === classToken.range);
|
|
1127
1137
|
if (cs === null || cs === void 0 ? void 0 : cs.parentClassName) {
|
|
@@ -1133,7 +1143,7 @@ class BrsFile {
|
|
|
1133
1143
|
}
|
|
1134
1144
|
return results;
|
|
1135
1145
|
}
|
|
1136
|
-
if (token.kind ===
|
|
1146
|
+
if (token.kind === TokenKind_1.TokenKind.StringLiteral) {
|
|
1137
1147
|
// We need to strip off the quotes but only if present
|
|
1138
1148
|
const startIndex = textToSearchFor.startsWith('"') ? 1 : 0;
|
|
1139
1149
|
let endIndex = textToSearchFor.length;
|
|
@@ -1153,7 +1163,7 @@ class BrsFile {
|
|
|
1153
1163
|
results.push(vscode_languageserver_1.Location.create(uri, varDeclaration.nameRange));
|
|
1154
1164
|
}
|
|
1155
1165
|
}
|
|
1156
|
-
if (this.tokenFollows(token,
|
|
1166
|
+
if (this.tokenFollows(token, TokenKind_1.TokenKind.Goto)) {
|
|
1157
1167
|
for (const label of functionScope.labelStatements) {
|
|
1158
1168
|
if (label.name.toLocaleLowerCase() === textToSearchFor) {
|
|
1159
1169
|
const uri = util_1.util.pathToUri(this.pathAbsolute);
|
|
@@ -1170,7 +1180,7 @@ class BrsFile {
|
|
|
1170
1180
|
continue;
|
|
1171
1181
|
}
|
|
1172
1182
|
filesSearched.add(file);
|
|
1173
|
-
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) {
|
|
1174
1184
|
results.push(...this.getClassMemberDefinitions(textToSearchFor, file));
|
|
1175
1185
|
const namespaceDefinition = this.getNamespaceDefinitions(token, file);
|
|
1176
1186
|
if (namespaceDefinition) {
|
|
@@ -1214,14 +1224,15 @@ class BrsFile {
|
|
|
1214
1224
|
return results;
|
|
1215
1225
|
}
|
|
1216
1226
|
getHover(position) {
|
|
1227
|
+
const fence = (code) => util_1.util.mdFence(code, 'brightscript');
|
|
1217
1228
|
//get the token at the position
|
|
1218
1229
|
let token = this.getTokenAt(position);
|
|
1219
1230
|
let hoverTokenTypes = [
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
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
|
|
1225
1236
|
];
|
|
1226
1237
|
//throw out invalid tokens and the wrong kind of tokens
|
|
1227
1238
|
if (!token || !hoverTokenTypes.includes(token.kind)) {
|
|
@@ -1247,7 +1258,7 @@ class BrsFile {
|
|
|
1247
1258
|
return {
|
|
1248
1259
|
range: token.range,
|
|
1249
1260
|
//append the variable name to the front for scope
|
|
1250
|
-
contents: typeText
|
|
1261
|
+
contents: fence(typeText)
|
|
1251
1262
|
};
|
|
1252
1263
|
}
|
|
1253
1264
|
}
|
|
@@ -1255,7 +1266,7 @@ class BrsFile {
|
|
|
1255
1266
|
if (labelStatement.name.toLocaleLowerCase() === lowerTokenText) {
|
|
1256
1267
|
return {
|
|
1257
1268
|
range: token.range,
|
|
1258
|
-
contents: `${labelStatement.name}: label`
|
|
1269
|
+
contents: fence(`${labelStatement.name}: label`)
|
|
1259
1270
|
};
|
|
1260
1271
|
}
|
|
1261
1272
|
}
|
|
@@ -1269,12 +1280,41 @@ class BrsFile {
|
|
|
1269
1280
|
if (callable) {
|
|
1270
1281
|
return {
|
|
1271
1282
|
range: token.range,
|
|
1272
|
-
contents:
|
|
1283
|
+
contents: this.getCallableDocumentation(callable)
|
|
1273
1284
|
};
|
|
1274
1285
|
}
|
|
1275
1286
|
}
|
|
1276
1287
|
}
|
|
1277
1288
|
}
|
|
1289
|
+
/**
|
|
1290
|
+
* Build a hover documentation for a callable.
|
|
1291
|
+
*/
|
|
1292
|
+
getCallableDocumentation(callable) {
|
|
1293
|
+
var _a;
|
|
1294
|
+
const comments = [];
|
|
1295
|
+
const tokens = callable.file.parser.tokens;
|
|
1296
|
+
const idx = tokens.indexOf((_a = callable.functionStatement) === null || _a === void 0 ? void 0 : _a.func.functionType);
|
|
1297
|
+
for (let i = idx - 1; i >= 0; i--) {
|
|
1298
|
+
const token = tokens[i];
|
|
1299
|
+
//skip whitespace and newline chars
|
|
1300
|
+
if (token.kind === TokenKind_1.TokenKind.Comment) {
|
|
1301
|
+
comments.push(token);
|
|
1302
|
+
}
|
|
1303
|
+
else if (token.kind === TokenKind_1.TokenKind.Newline || token.kind === TokenKind_1.TokenKind.Whitespace) {
|
|
1304
|
+
//skip these tokens
|
|
1305
|
+
continue;
|
|
1306
|
+
//any other token means there are no more comments
|
|
1307
|
+
}
|
|
1308
|
+
else {
|
|
1309
|
+
break;
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
let result = util_1.util.mdFence(callable.type.toString(), 'brightscript');
|
|
1313
|
+
if (comments.length > 0) {
|
|
1314
|
+
result += '\n***\n' + comments.reverse().map(x => x.text.replace(/^('|rem)/i, '')).join('\n');
|
|
1315
|
+
}
|
|
1316
|
+
return result;
|
|
1317
|
+
}
|
|
1278
1318
|
getSignatureHelpForNamespaceMethods(callableName, dottedGetText, scope) {
|
|
1279
1319
|
var _a;
|
|
1280
1320
|
if (!dottedGetText) {
|
|
@@ -1321,12 +1361,12 @@ class BrsFile {
|
|
|
1321
1361
|
}
|
|
1322
1362
|
}
|
|
1323
1363
|
const kind = currentToken.kind;
|
|
1324
|
-
if (kind ===
|
|
1364
|
+
if (kind === TokenKind_1.TokenKind.Comment) {
|
|
1325
1365
|
// Strip off common leading characters to make it easier to read
|
|
1326
1366
|
const commentText = currentToken.text.replace(/^[' *\/]+/, '');
|
|
1327
1367
|
functionComments.unshift(commentText);
|
|
1328
1368
|
}
|
|
1329
|
-
else if (kind ===
|
|
1369
|
+
else if (kind === TokenKind_1.TokenKind.Newline) {
|
|
1330
1370
|
if (functionComments.length === 0) {
|
|
1331
1371
|
continue;
|
|
1332
1372
|
}
|
|
@@ -1385,7 +1425,7 @@ class BrsFile {
|
|
|
1385
1425
|
const classConstructor = this.getClassMethod(classStatement, 'new');
|
|
1386
1426
|
let sigHelp = classConstructor ? this.getSignatureHelpForStatement(classConstructor) : undefined;
|
|
1387
1427
|
if (sigHelp) {
|
|
1388
|
-
sigHelp.key = classStatement.getName(
|
|
1428
|
+
sigHelp.key = classStatement.getName(Parser_1.ParseMode.BrighterScript);
|
|
1389
1429
|
sigHelp.signature.label = sigHelp.signature.label.replace(/(function|sub) new/, sigHelp.key);
|
|
1390
1430
|
}
|
|
1391
1431
|
return sigHelp;
|
|
@@ -1462,7 +1502,7 @@ exports.BrsFile = BrsFile;
|
|
|
1462
1502
|
* List of completions for all valid keywords/reserved words.
|
|
1463
1503
|
* Build this list once because it won't change for the lifetime of this process
|
|
1464
1504
|
*/
|
|
1465
|
-
exports.KeywordCompletions = Object.keys(
|
|
1505
|
+
exports.KeywordCompletions = Object.keys(TokenKind_1.Keywords)
|
|
1466
1506
|
//remove any keywords with whitespace
|
|
1467
1507
|
.filter(x => !x.includes(' '))
|
|
1468
1508
|
//create completions
|