brighterscript 1.0.0-alpha.1 → 1.0.0-alpha.13
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 +362 -248
- package/README.md +2 -2
- package/bsconfig.schema.json +1 -1
- package/dist/CodeActionUtil.d.ts +11 -2
- package/dist/CodeActionUtil.js +17 -3
- package/dist/CodeActionUtil.js.map +1 -1
- package/dist/CommentFlagProcessor.d.ts +4 -4
- package/dist/CommentFlagProcessor.js +5 -3
- package/dist/CommentFlagProcessor.js.map +1 -1
- package/dist/DependencyGraph.js.map +1 -1
- package/dist/DiagnosticCollection.js +2 -2
- package/dist/DiagnosticCollection.js.map +1 -1
- package/dist/DiagnosticFilterer.js +3 -3
- package/dist/DiagnosticFilterer.js.map +1 -1
- package/dist/DiagnosticMessages.d.ts +15 -5
- package/dist/DiagnosticMessages.js +19 -9
- package/dist/DiagnosticMessages.js.map +1 -1
- package/dist/LanguageServer.d.ts +11 -10
- package/dist/LanguageServer.js +87 -58
- package/dist/LanguageServer.js.map +1 -1
- package/dist/Logger.d.ts +2 -0
- package/dist/Logger.js +5 -3
- package/dist/Logger.js.map +1 -1
- package/dist/Program.d.ts +76 -46
- package/dist/Program.js +254 -180
- package/dist/Program.js.map +1 -1
- package/dist/ProgramBuilder.d.ts +7 -7
- package/dist/ProgramBuilder.js +37 -43
- package/dist/ProgramBuilder.js.map +1 -1
- package/dist/Scope.d.ts +33 -23
- package/dist/Scope.js +222 -147
- package/dist/Scope.js.map +1 -1
- package/dist/SemanticTokenUtils.d.ts +14 -0
- package/dist/SemanticTokenUtils.js +81 -0
- package/dist/SemanticTokenUtils.js.map +1 -0
- package/dist/SymbolTable.d.ts +9 -3
- package/dist/SymbolTable.js +40 -13
- package/dist/SymbolTable.js.map +1 -1
- package/dist/XmlScope.d.ts +7 -2
- package/dist/XmlScope.js +67 -29
- package/dist/XmlScope.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/creators.d.ts +15 -1
- package/dist/astUtils/creators.js +39 -9
- package/dist/astUtils/creators.js.map +1 -1
- package/dist/astUtils/creators.spec.js +4 -4
- package/dist/astUtils/creators.spec.js.map +1 -1
- package/dist/astUtils/index.js +1 -1
- package/dist/astUtils/reflection.d.ts +20 -8
- package/dist/astUtils/reflection.js +42 -1
- package/dist/astUtils/reflection.js.map +1 -1
- package/dist/astUtils/reflection.spec.js +115 -115
- package/dist/astUtils/reflection.spec.js.map +1 -1
- package/dist/astUtils/stackedVisitor.js.map +1 -1
- package/dist/astUtils/stackedVisitor.spec.js +13 -13
- package/dist/astUtils/stackedVisitor.spec.js.map +1 -1
- package/dist/astUtils/visitors.js +1 -1
- package/dist/astUtils/visitors.js.map +1 -1
- package/dist/astUtils/visitors.spec.js +28 -28
- package/dist/astUtils/visitors.spec.js.map +1 -1
- package/dist/astUtils/xml.d.ts +4 -3
- package/dist/astUtils/xml.js +8 -3
- package/dist/astUtils/xml.js.map +1 -1
- package/dist/bscPlugin/BscPlugin.d.ts +2 -1
- package/dist/bscPlugin/BscPlugin.js +4 -0
- package/dist/bscPlugin/BscPlugin.js.map +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +5 -6
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +30 -30
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.d.ts +7 -0
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js +63 -0
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js.map +1 -0
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.d.ts +1 -0
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js +45 -0
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js.map +1 -0
- package/dist/diagnosticUtils.d.ts +1 -0
- package/dist/diagnosticUtils.js +14 -7
- package/dist/diagnosticUtils.js.map +1 -1
- package/dist/examples/plugins/removePrint.js +2 -2
- package/dist/examples/plugins/removePrint.js.map +1 -1
- package/dist/files/BrsFile.Class.spec.js +486 -71
- package/dist/files/BrsFile.Class.spec.js.map +1 -1
- package/dist/files/BrsFile.d.ts +48 -23
- package/dist/files/BrsFile.js +403 -233
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/BrsFile.spec.js +367 -316
- package/dist/files/BrsFile.spec.js.map +1 -1
- package/dist/files/XmlFile.d.ts +13 -6
- package/dist/files/XmlFile.js +27 -21
- package/dist/files/XmlFile.js.map +1 -1
- package/dist/files/XmlFile.spec.js +274 -228
- package/dist/files/XmlFile.spec.js.map +1 -1
- package/dist/files/tests/imports.spec.js +49 -49
- package/dist/files/tests/imports.spec.js.map +1 -1
- package/dist/globalCallables.d.ts +3 -1
- package/dist/globalCallables.js +359 -87
- package/dist/globalCallables.js.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +51 -14
- package/dist/lexer/Lexer.d.ts +14 -1
- package/dist/lexer/Lexer.js +91 -21
- package/dist/lexer/Lexer.js.map +1 -1
- package/dist/lexer/Lexer.spec.js +187 -132
- package/dist/lexer/Lexer.spec.js.map +1 -1
- package/dist/lexer/Token.d.ts +2 -2
- package/dist/lexer/TokenKind.d.ts +7 -1
- package/dist/lexer/TokenKind.js +51 -3
- package/dist/lexer/TokenKind.js.map +1 -1
- package/dist/lexer/index.js +2 -1
- package/dist/lexer/index.js.map +1 -1
- package/dist/parser/BrsTranspileState.d.ts +7 -0
- package/dist/parser/BrsTranspileState.js +10 -1
- package/dist/parser/BrsTranspileState.js.map +1 -1
- package/dist/parser/Expression.d.ts +23 -5
- package/dist/parser/Expression.js +124 -75
- package/dist/parser/Expression.js.map +1 -1
- package/dist/parser/Parser.Class.spec.js +159 -60
- package/dist/parser/Parser.Class.spec.js.map +1 -1
- package/dist/parser/Parser.d.ts +114 -26
- package/dist/parser/Parser.js +471 -126
- package/dist/parser/Parser.js.map +1 -1
- package/dist/parser/Parser.spec.js +396 -235
- package/dist/parser/Parser.spec.js.map +1 -1
- package/dist/parser/SGParser.d.ts +41 -4
- package/dist/parser/SGParser.js +186 -175
- package/dist/parser/SGParser.js.map +1 -1
- package/dist/parser/SGParser.spec.js +35 -22
- package/dist/parser/SGParser.spec.js.map +1 -1
- package/dist/parser/SGTypes.d.ts +206 -38
- package/dist/parser/SGTypes.js +470 -161
- package/dist/parser/SGTypes.js.map +1 -1
- package/dist/parser/SGTypes.spec.d.ts +1 -0
- package/dist/parser/SGTypes.spec.js +351 -0
- package/dist/parser/SGTypes.spec.js.map +1 -0
- package/dist/parser/Statement.d.ts +92 -18
- package/dist/parser/Statement.js +287 -58
- package/dist/parser/Statement.js.map +1 -1
- package/dist/parser/Statement.spec.js +11 -11
- package/dist/parser/Statement.spec.js.map +1 -1
- package/dist/parser/TranspileState.d.ts +1 -1
- package/dist/parser/TranspileState.js +15 -7
- package/dist/parser/TranspileState.js.map +1 -1
- package/dist/parser/index.js +1 -1
- package/dist/parser/tests/Parser.spec.d.ts +8 -7
- package/dist/parser/tests/Parser.spec.js +12 -8
- package/dist/parser/tests/Parser.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/For.spec.js +50 -50
- package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/ForEach.spec.js +31 -31
- package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/If.spec.js +174 -156
- package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/While.spec.js +32 -32
- 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 +105 -105
- package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +148 -124
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
- package/dist/parser/tests/expression/Boolean.spec.js +17 -17
- package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
- package/dist/parser/tests/expression/Call.spec.js +30 -30
- package/dist/parser/tests/expression/Call.spec.js.map +1 -1
- package/dist/parser/tests/expression/Exponential.spec.js +16 -16
- package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
- package/dist/parser/tests/expression/Function.spec.js +247 -247
- package/dist/parser/tests/expression/Function.spec.js.map +1 -1
- package/dist/parser/tests/expression/Indexing.spec.js +73 -73
- package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
- package/dist/parser/tests/expression/Multiplicative.spec.js +36 -36
- package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +59 -47
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/PrefixUnary.spec.js +35 -35
- package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
- package/dist/parser/tests/expression/Primary.spec.js +26 -26
- package/dist/parser/tests/expression/Primary.spec.js.map +1 -1
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.d.ts +1 -0
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +170 -0
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -0
- package/dist/parser/tests/expression/Relational.spec.js +42 -42
- package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
- package/dist/parser/tests/expression/SourceLiteralExpression.spec.js +8 -8
- package/dist/parser/tests/expression/SourceLiteralExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js +12 -12
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TernaryExpression.spec.js +100 -100
- package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
- package/dist/parser/tests/statement/AssignmentOperators.spec.js +35 -35
- package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
- package/dist/parser/tests/statement/Declaration.spec.js +39 -39
- package/dist/parser/tests/statement/Declaration.spec.js.map +1 -1
- package/dist/parser/tests/statement/Dim.spec.js +21 -21
- package/dist/parser/tests/statement/Dim.spec.js.map +1 -1
- package/dist/parser/tests/statement/Function.spec.js +192 -192
- package/dist/parser/tests/statement/Function.spec.js.map +1 -1
- package/dist/parser/tests/statement/Goto.spec.js +11 -11
- package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
- package/dist/parser/tests/statement/Increment.spec.js +46 -46
- package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
- package/dist/parser/tests/statement/InterfaceStatement.spec.d.ts +1 -0
- package/dist/parser/tests/statement/InterfaceStatement.spec.js +61 -0
- package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -0
- package/dist/parser/tests/statement/LibraryStatement.spec.js +10 -10
- package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/Misc.spec.js +37 -36
- package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
- package/dist/parser/tests/statement/PrintStatement.spec.js +30 -30
- package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/ReturnStatement.spec.js +43 -43
- package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/Set.spec.js +69 -69
- package/dist/parser/tests/statement/Set.spec.js.map +1 -1
- package/dist/parser/tests/statement/Stop.spec.js +9 -9
- package/dist/parser/tests/statement/Stop.spec.js.map +1 -1
- package/dist/parser/tests/statement/Throw.spec.js +5 -5
- package/dist/parser/tests/statement/Throw.spec.js.map +1 -1
- package/dist/parser/tests/statement/TryCatch.spec.js +13 -13
- package/dist/parser/tests/statement/TryCatch.spec.js.map +1 -1
- package/dist/preprocessor/Chunk.js.map +1 -1
- package/dist/preprocessor/Manifest.d.ts +1 -1
- package/dist/preprocessor/Preprocessor.js +1 -1
- package/dist/preprocessor/Preprocessor.js.map +1 -1
- package/dist/preprocessor/Preprocessor.spec.js +49 -49
- package/dist/preprocessor/Preprocessor.spec.js.map +1 -1
- package/dist/preprocessor/PreprocessorParser.spec.js +72 -72
- package/dist/preprocessor/PreprocessorParser.spec.js.map +1 -1
- package/dist/preprocessor/index.js +1 -1
- package/dist/types/ArrayType.js +5 -4
- package/dist/types/ArrayType.js.map +1 -1
- package/dist/types/ArrayType.spec.js +8 -8
- package/dist/types/ArrayType.spec.js.map +1 -1
- package/dist/types/BooleanType.js +3 -3
- package/dist/types/BooleanType.js.map +1 -1
- package/dist/types/BooleanType.spec.js +2 -2
- package/dist/types/BooleanType.spec.js.map +1 -1
- package/dist/types/BscType.d.ts +19 -5
- package/dist/types/BscType.js +9 -0
- package/dist/types/BscType.js.map +1 -1
- package/dist/types/CustomType.d.ts +8 -5
- package/dist/types/CustomType.js +17 -6
- package/dist/types/CustomType.js.map +1 -1
- package/dist/types/DoubleType.js +8 -8
- package/dist/types/DoubleType.js.map +1 -1
- package/dist/types/DoubleType.spec.js +2 -2
- package/dist/types/DoubleType.spec.js.map +1 -1
- package/dist/types/DynamicType.js +1 -1
- package/dist/types/DynamicType.js.map +1 -1
- package/dist/types/DynamicType.spec.js +2 -2
- package/dist/types/DynamicType.spec.js.map +1 -1
- package/dist/types/FloatType.d.ts +1 -1
- package/dist/types/FloatType.js +8 -8
- package/dist/types/FloatType.js.map +1 -1
- package/dist/types/FloatType.spec.js +2 -2
- package/dist/types/FloatType.spec.js.map +1 -1
- package/dist/types/FunctionType.d.ts +5 -11
- package/dist/types/FunctionType.js +24 -13
- package/dist/types/FunctionType.js.map +1 -1
- package/dist/types/FunctionType.spec.js +11 -5
- package/dist/types/FunctionType.spec.js.map +1 -1
- package/dist/types/IntegerType.d.ts +1 -1
- package/dist/types/IntegerType.js +8 -8
- package/dist/types/IntegerType.js.map +1 -1
- package/dist/types/IntegerType.spec.js +2 -2
- package/dist/types/IntegerType.spec.js.map +1 -1
- package/dist/types/InterfaceType.d.ts +8 -2
- package/dist/types/InterfaceType.js +42 -6
- package/dist/types/InterfaceType.js.map +1 -1
- package/dist/types/InterfaceType.spec.d.ts +1 -0
- package/dist/types/InterfaceType.spec.js +174 -0
- package/dist/types/InterfaceType.spec.js.map +1 -0
- package/dist/types/InvalidType.js +4 -4
- package/dist/types/InvalidType.js.map +1 -1
- package/dist/types/InvalidType.spec.js +2 -2
- package/dist/types/InvalidType.spec.js.map +1 -1
- package/dist/types/LazyType.d.ts +9 -7
- package/dist/types/LazyType.js +22 -10
- package/dist/types/LazyType.js.map +1 -1
- package/dist/types/LongIntegerType.d.ts +1 -1
- package/dist/types/LongIntegerType.js +8 -8
- package/dist/types/LongIntegerType.js.map +1 -1
- package/dist/types/LongIntegerType.spec.js +2 -2
- package/dist/types/LongIntegerType.spec.js.map +1 -1
- package/dist/types/ObjectType.d.ts +7 -4
- package/dist/types/ObjectType.js +6 -3
- package/dist/types/ObjectType.js.map +1 -1
- package/dist/types/ObjectType.spec.js +2 -2
- package/dist/types/ObjectType.spec.js.map +1 -1
- package/dist/types/StringType.js +3 -3
- package/dist/types/StringType.js.map +1 -1
- package/dist/types/StringType.spec.js +2 -2
- package/dist/types/StringType.spec.js.map +1 -1
- package/dist/types/UninitializedType.js +3 -3
- package/dist/types/UninitializedType.js.map +1 -1
- package/dist/types/VoidType.js +3 -3
- package/dist/types/VoidType.js.map +1 -1
- package/dist/types/VoidType.spec.js +2 -2
- package/dist/types/VoidType.spec.js.map +1 -1
- package/dist/types/helpers.d.ts +42 -0
- package/dist/types/helpers.js +113 -0
- package/dist/types/helpers.js.map +1 -0
- package/dist/util.d.ts +77 -17
- package/dist/util.js +247 -59
- package/dist/util.js.map +1 -1
- package/dist/validators/ClassValidator.d.ts +5 -1
- package/dist/validators/ClassValidator.js +59 -24
- package/dist/validators/ClassValidator.js.map +1 -1
- package/package.json +13 -13
package/dist/Program.js
CHANGED
|
@@ -23,9 +23,10 @@ const reflection_1 = require("./astUtils/reflection");
|
|
|
23
23
|
const parser_1 = require("./parser");
|
|
24
24
|
const lexer_1 = require("./lexer");
|
|
25
25
|
const BscPlugin_1 = require("./bscPlugin/BscPlugin");
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
const
|
|
26
|
+
const roku_deploy_1 = require("roku-deploy");
|
|
27
|
+
const AstEditor_1 = require("./astUtils/AstEditor");
|
|
28
|
+
const bslibNonAliasedRokuModulesPkgPath = `pkg:/source/roku_modules/rokucommunity_bslib/bslib.brs`;
|
|
29
|
+
const bslibAliasedRokuModulesPkgPath = `pkg:/source/roku_modules/bslib/bslib.brs`;
|
|
29
30
|
class Program {
|
|
30
31
|
constructor(
|
|
31
32
|
/**
|
|
@@ -47,10 +48,13 @@ class Program {
|
|
|
47
48
|
*/
|
|
48
49
|
this.diagnostics = [];
|
|
49
50
|
/**
|
|
50
|
-
* A map of every file loaded
|
|
51
|
+
* A map of every file loaded ino this program, indexed by its lower-case pkgPath
|
|
51
52
|
*/
|
|
52
|
-
this.files = {};
|
|
53
53
|
this.pkgMap = {};
|
|
54
|
+
/**
|
|
55
|
+
* A map of every file loaded into this program, indexed by its lower-case srcPath
|
|
56
|
+
*/
|
|
57
|
+
this.files = {};
|
|
54
58
|
this.scopes = {};
|
|
55
59
|
/**
|
|
56
60
|
* A map of every component currently loaded into the program, indexed by the component name.
|
|
@@ -86,16 +90,16 @@ class Program {
|
|
|
86
90
|
*/
|
|
87
91
|
get bslibPkgPath() {
|
|
88
92
|
//if there's an aliased (preferred) version of bslib from roku_modules loaded into the program, use that
|
|
89
|
-
if (this.
|
|
93
|
+
if (this.getFile(bslibAliasedRokuModulesPkgPath)) {
|
|
90
94
|
return bslibAliasedRokuModulesPkgPath;
|
|
91
95
|
//if there's a non-aliased version of bslib from roku_modules, use that
|
|
92
96
|
}
|
|
93
|
-
else if (this.
|
|
97
|
+
else if (this.getFile(bslibNonAliasedRokuModulesPkgPath)) {
|
|
94
98
|
return bslibNonAliasedRokuModulesPkgPath;
|
|
95
99
|
//default to the embedded version
|
|
96
100
|
}
|
|
97
101
|
else {
|
|
98
|
-
return `source
|
|
102
|
+
return `pkg:/source/bslib.brs`;
|
|
99
103
|
}
|
|
100
104
|
}
|
|
101
105
|
get bslibPrefix() {
|
|
@@ -106,6 +110,12 @@ class Program {
|
|
|
106
110
|
return 'bslib';
|
|
107
111
|
}
|
|
108
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* Get a copy of the list of files currently loaded in the program
|
|
115
|
+
*/
|
|
116
|
+
getFiles() {
|
|
117
|
+
return Object.values(this.files);
|
|
118
|
+
}
|
|
109
119
|
addScope(scope) {
|
|
110
120
|
this.scopes[scope.name] = scope;
|
|
111
121
|
this.plugins.emit('afterScopeCreate', {
|
|
@@ -181,8 +191,8 @@ class Program {
|
|
|
181
191
|
*/
|
|
182
192
|
getUnreferencedFiles() {
|
|
183
193
|
let result = [];
|
|
184
|
-
for (let
|
|
185
|
-
|
|
194
|
+
for (let key in this.files) {
|
|
195
|
+
const file = this.files[key];
|
|
186
196
|
if (!this.fileIsIncludedInAnyScope(file)) {
|
|
187
197
|
//no scopes reference this file. add it to the list
|
|
188
198
|
result.push(file);
|
|
@@ -222,13 +232,10 @@ class Program {
|
|
|
222
232
|
/**
|
|
223
233
|
* Determine if the specified file is loaded in this program right now.
|
|
224
234
|
* @param filePath
|
|
235
|
+
* @param normalizePath should the provided path be normalized before use
|
|
225
236
|
*/
|
|
226
|
-
hasFile(filePath) {
|
|
227
|
-
|
|
228
|
-
return this.files[filePath] !== undefined;
|
|
229
|
-
}
|
|
230
|
-
getPkgPath(...args) {
|
|
231
|
-
throw new Error('Not implemented');
|
|
237
|
+
hasFile(filePath, normalizePath = true) {
|
|
238
|
+
return !!this.getFile(filePath, normalizePath);
|
|
232
239
|
}
|
|
233
240
|
/**
|
|
234
241
|
* roku filesystem is case INsensitive, so find the scope by key case insensitive
|
|
@@ -238,9 +245,6 @@ class Program {
|
|
|
238
245
|
if (!scopeName) {
|
|
239
246
|
return undefined;
|
|
240
247
|
}
|
|
241
|
-
//most scopes are xml file pkg paths. however, the ones that are not are single names like "global" and "scope",
|
|
242
|
-
//so it's safe to run the standardizePkgPath method
|
|
243
|
-
scopeName = util_1.standardizePath `${scopeName}`;
|
|
244
248
|
let key = Object.keys(this.scopes).find(x => x.toLowerCase() === scopeName.toLowerCase());
|
|
245
249
|
return this.scopes[key];
|
|
246
250
|
}
|
|
@@ -257,21 +261,52 @@ class Program {
|
|
|
257
261
|
var _a;
|
|
258
262
|
return (_a = this.getComponent(componentName)) === null || _a === void 0 ? void 0 : _a.scope;
|
|
259
263
|
}
|
|
260
|
-
|
|
261
|
-
|
|
264
|
+
/**
|
|
265
|
+
* Update internal maps with this file reference
|
|
266
|
+
*/
|
|
267
|
+
assignFile(file) {
|
|
268
|
+
this.files[file.srcPath.toLowerCase()] = file;
|
|
269
|
+
this.pkgMap[file.pkgPath.toLowerCase()] = file;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Remove this file from internal maps
|
|
273
|
+
*/
|
|
274
|
+
unassignFile(file) {
|
|
275
|
+
delete this.files[file.srcPath.toLowerCase()];
|
|
276
|
+
delete this.pkgMap[file.pkgPath.toLowerCase()];
|
|
277
|
+
}
|
|
278
|
+
setFile(fileParam, fileContents) {
|
|
279
|
+
assert.ok(fileParam, 'fileParam is required');
|
|
262
280
|
let srcPath;
|
|
263
281
|
let pkgPath;
|
|
264
282
|
if (typeof fileParam === 'string') {
|
|
265
|
-
|
|
266
|
-
|
|
283
|
+
//is a pkg path
|
|
284
|
+
if (fileParam.startsWith('pkg:/')) {
|
|
285
|
+
//srcPath is the pkgPath relative to the rootDir
|
|
286
|
+
srcPath = (0, util_1.standardizePath) `${this.options.rootDir}/${fileParam.substring(5)}`;
|
|
287
|
+
pkgPath = fileParam;
|
|
288
|
+
//is a srcPath (absolute path to src file location)
|
|
289
|
+
}
|
|
290
|
+
else if (path.isAbsolute(fileParam)) {
|
|
291
|
+
srcPath = util_1.util.standardizePath(fileParam);
|
|
292
|
+
//assume the file path is a sub path of rootDir
|
|
293
|
+
pkgPath = util_1.util.sanitizePkgPath(roku_deploy_1.util.stringReplaceInsensitive(srcPath, this.options.rootDir, ''));
|
|
294
|
+
//is destPath (path relative to rootDir and `pkg:/`)
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
srcPath = (0, util_1.standardizePath) `${this.options.rootDir}/${fileParam}`;
|
|
298
|
+
pkgPath = util_1.util.sanitizePkgPath(fileParam);
|
|
299
|
+
}
|
|
300
|
+
//is a FileObj
|
|
267
301
|
}
|
|
268
302
|
else {
|
|
269
|
-
srcPath = util_1.standardizePath `${fileParam.src}`;
|
|
270
|
-
pkgPath = util_1.
|
|
303
|
+
srcPath = (0, util_1.standardizePath) `${fileParam.src}`;
|
|
304
|
+
pkgPath = util_1.util.sanitizePkgPath(fileParam.dest);
|
|
271
305
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
assert.ok(
|
|
306
|
+
const lowerPkgPath = pkgPath.toLowerCase();
|
|
307
|
+
return this.logger.time(Logger_1.LogLevel.debug, ['program.setFile()', chalk_1.default.green(srcPath)], () => {
|
|
308
|
+
assert.ok(srcPath, 'srcPath is required');
|
|
309
|
+
assert.ok(pkgPath, 'pkgPath is required');
|
|
275
310
|
//if the file is already loaded, remove it
|
|
276
311
|
if (this.hasFile(srcPath)) {
|
|
277
312
|
this.removeFile(srcPath);
|
|
@@ -280,19 +315,18 @@ class Program {
|
|
|
280
315
|
let file;
|
|
281
316
|
const beforeFileParseEvent = {
|
|
282
317
|
program: this,
|
|
283
|
-
|
|
318
|
+
srcPath: srcPath,
|
|
284
319
|
source: fileContents
|
|
285
320
|
};
|
|
286
321
|
if (fileExtension === '.brs' || fileExtension === '.bs') {
|
|
287
322
|
let brsFile = new BrsFile_1.BrsFile(srcPath, pkgPath, this);
|
|
288
323
|
//add file to the `source` dependency list
|
|
289
|
-
if (brsFile.pkgPath.startsWith(
|
|
324
|
+
if (brsFile.pkgPath.startsWith('pkg:/source/')) {
|
|
290
325
|
this.createSourceScope();
|
|
291
326
|
this.dependencyGraph.addDependency('scope:source', brsFile.dependencyGraphKey);
|
|
292
327
|
}
|
|
293
328
|
//add the file to the program
|
|
294
|
-
this.
|
|
295
|
-
this.pkgMap[brsFile.pkgPath.toLowerCase()] = brsFile;
|
|
329
|
+
this.assignFile(brsFile);
|
|
296
330
|
this.plugins.emit('beforeFileParse', beforeFileParseEvent);
|
|
297
331
|
this.logger.time(Logger_1.LogLevel.debug, ['parse', chalk_1.default.green(srcPath)], () => {
|
|
298
332
|
brsFile.parse(beforeFileParseEvent.source);
|
|
@@ -308,11 +342,10 @@ class Program {
|
|
|
308
342
|
//is xml file
|
|
309
343
|
fileExtension === '.xml' &&
|
|
310
344
|
//resides in the components folder (Roku will only parse xml files in the components folder)
|
|
311
|
-
|
|
345
|
+
lowerPkgPath.startsWith('pkg:/components/')) {
|
|
312
346
|
let xmlFile = new XmlFile_1.XmlFile(srcPath, pkgPath, this);
|
|
347
|
+
this.assignFile(xmlFile);
|
|
313
348
|
//add the file to the program
|
|
314
|
-
this.files[srcPath] = xmlFile;
|
|
315
|
-
this.pkgMap[xmlFile.pkgPath.toLowerCase()] = xmlFile;
|
|
316
349
|
this.plugins.emit('beforeFileParse', beforeFileParseEvent);
|
|
317
350
|
this.logger.time(Logger_1.LogLevel.debug, ['parse', chalk_1.default.green(srcPath)], () => {
|
|
318
351
|
xmlFile.parse(beforeFileParseEvent.source);
|
|
@@ -330,8 +363,8 @@ class Program {
|
|
|
330
363
|
}
|
|
331
364
|
else {
|
|
332
365
|
//TODO do we actually need to implement this? Figure out how to handle img paths
|
|
333
|
-
// let genericFile = this.files[
|
|
334
|
-
//
|
|
366
|
+
// let genericFile = this.files[srcPath] = <any>{
|
|
367
|
+
// srcPath: srcPath,
|
|
335
368
|
// pkgPath: pkgPath,
|
|
336
369
|
// wasProcessed: true
|
|
337
370
|
// } as File;
|
|
@@ -351,55 +384,24 @@ class Program {
|
|
|
351
384
|
this.addScope(sourceScope);
|
|
352
385
|
}
|
|
353
386
|
}
|
|
354
|
-
/**
|
|
355
|
-
* Find the file by its absolute path. This is case INSENSITIVE, since
|
|
356
|
-
* Roku is a case insensitive file system. It is an error to have multiple files
|
|
357
|
-
* with the same path with only case being different.
|
|
358
|
-
* @param pathAbsolute
|
|
359
|
-
*/
|
|
360
|
-
getFileByPathAbsolute(pathAbsolute) {
|
|
361
|
-
pathAbsolute = util_1.standardizePath `${pathAbsolute}`;
|
|
362
|
-
for (let filePath in this.files) {
|
|
363
|
-
if (filePath.toLowerCase() === pathAbsolute.toLowerCase()) {
|
|
364
|
-
return this.files[filePath];
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
/**
|
|
369
|
-
* Get a list of files for the given (platform-normalized) pkgPath array.
|
|
370
|
-
* Missing files are just ignored.
|
|
371
|
-
*/
|
|
372
|
-
getFilesByPkgPaths(pkgPaths) {
|
|
373
|
-
return pkgPaths
|
|
374
|
-
.map(pkgPath => this.getFileByPkgPath(pkgPath))
|
|
375
|
-
.filter(file => file !== undefined);
|
|
376
|
-
}
|
|
377
|
-
/**
|
|
378
|
-
* Get a file with the specified (platform-normalized) pkg path.
|
|
379
|
-
* If not found, return undefined
|
|
380
|
-
*/
|
|
381
|
-
getFileByPkgPath(pkgPath) {
|
|
382
|
-
return this.pkgMap[pkgPath.toLowerCase()];
|
|
383
|
-
}
|
|
384
387
|
/**
|
|
385
388
|
* Remove a set of files from the program
|
|
386
|
-
* @param
|
|
389
|
+
* @param srcPaths
|
|
387
390
|
*/
|
|
388
|
-
removeFiles(
|
|
389
|
-
for (let
|
|
390
|
-
this.removeFile(
|
|
391
|
+
removeFiles(srcPaths) {
|
|
392
|
+
for (let srcPath of srcPaths) {
|
|
393
|
+
this.removeFile(srcPath);
|
|
391
394
|
}
|
|
392
395
|
}
|
|
393
396
|
/**
|
|
394
397
|
* Remove a file from the program
|
|
395
|
-
* @param
|
|
398
|
+
* @param filePath can be a srcPath, a pkgPath, or a destPath (same as pkgPath but without `pkg:/`)
|
|
399
|
+
* @param normalizePath should this function repair and standardize the path? Passing false should have a performance boost if you can guarantee your path is already sanitized
|
|
400
|
+
|
|
396
401
|
*/
|
|
397
|
-
removeFile(
|
|
398
|
-
this.logger.debug('Program.removeFile()',
|
|
399
|
-
|
|
400
|
-
throw new Error(`Path must be absolute: "${pathAbsolute}"`);
|
|
401
|
-
}
|
|
402
|
-
let file = this.getFile(pathAbsolute);
|
|
402
|
+
removeFile(filePath, normalizePath = true) {
|
|
403
|
+
this.logger.debug('Program.removeFile()', filePath);
|
|
404
|
+
let file = this.getFile(filePath, normalizePath);
|
|
403
405
|
if (file) {
|
|
404
406
|
this.plugins.emit('beforeFileDispose', {
|
|
405
407
|
program: this,
|
|
@@ -422,15 +424,14 @@ class Program {
|
|
|
422
424
|
});
|
|
423
425
|
}
|
|
424
426
|
//remove the file from the program
|
|
425
|
-
|
|
426
|
-
delete this.pkgMap[file.pkgPath.toLowerCase()];
|
|
427
|
+
this.unassignFile(file);
|
|
427
428
|
this.dependencyGraph.remove(file.dependencyGraphKey);
|
|
428
429
|
//if this is a pkg:/source file, notify the `source` scope that it has changed
|
|
429
|
-
if (file.pkgPath.startsWith(
|
|
430
|
+
if (file.pkgPath.startsWith('pkg:/source/')) {
|
|
430
431
|
this.dependencyGraph.removeDependency('scope:source', file.dependencyGraphKey);
|
|
431
432
|
}
|
|
432
433
|
//if this is a component, remove it from our components map
|
|
433
|
-
if (reflection_1.isXmlFile(file)) {
|
|
434
|
+
if ((0, reflection_1.isXmlFile)(file)) {
|
|
434
435
|
this.unregisterComponent(file);
|
|
435
436
|
}
|
|
436
437
|
this.plugins.emit('afterFileDispose', {
|
|
@@ -439,6 +440,25 @@ class Program {
|
|
|
439
440
|
});
|
|
440
441
|
}
|
|
441
442
|
}
|
|
443
|
+
/**
|
|
444
|
+
* Remove all files from the program that are in the specified folder path (recursive)
|
|
445
|
+
* @param folderSrcPath The absolute path to the folder on disk
|
|
446
|
+
* @param normalizePath should the provided path be normalized before use?
|
|
447
|
+
*/
|
|
448
|
+
removeFilesInFolder(folderSrcPath, normalizePath = true) {
|
|
449
|
+
if (normalizePath) {
|
|
450
|
+
folderSrcPath = util_1.util.standardizePath(folderSrcPath);
|
|
451
|
+
}
|
|
452
|
+
const lowerFolderSrcPath = folderSrcPath.toLowerCase();
|
|
453
|
+
for (const key in this.files) {
|
|
454
|
+
const file = this.files[key];
|
|
455
|
+
const lowerSrcPath = file.srcPath.toLowerCase();
|
|
456
|
+
//if the file path starts with the parent path and the file path does not exactly match the folder path
|
|
457
|
+
if (lowerSrcPath.toLowerCase().startsWith(lowerFolderSrcPath) && lowerSrcPath !== lowerFolderSrcPath) {
|
|
458
|
+
this.removeFile(file.srcPath, false);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
442
462
|
/**
|
|
443
463
|
* Traverse the entire project, and validate all scopes
|
|
444
464
|
* @param force - if true, then all scopes are force to validate, even if they aren't marked as dirty
|
|
@@ -500,28 +520,31 @@ class Program {
|
|
|
500
520
|
* Flag all duplicate component names
|
|
501
521
|
*/
|
|
502
522
|
detectDuplicateComponentNames() {
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
523
|
+
var _a;
|
|
524
|
+
const componentsByName = new Map();
|
|
525
|
+
for (const key in this.files) {
|
|
526
|
+
const file = this.files[key];
|
|
506
527
|
//if this is an XmlFile, and it has a valid `componentName` property
|
|
507
|
-
if (reflection_1.isXmlFile
|
|
508
|
-
|
|
509
|
-
if (
|
|
510
|
-
|
|
528
|
+
if ((0, reflection_1.isXmlFile)(file)) {
|
|
529
|
+
const componentNameLower = (_a = file.componentName) === null || _a === void 0 ? void 0 : _a.text.toLowerCase();
|
|
530
|
+
if (componentNameLower) {
|
|
531
|
+
if (!componentsByName.has(componentNameLower)) {
|
|
532
|
+
componentsByName.set(componentNameLower, [file]);
|
|
533
|
+
}
|
|
534
|
+
else {
|
|
535
|
+
componentsByName.get(componentNameLower).push(file);
|
|
536
|
+
}
|
|
511
537
|
}
|
|
512
|
-
map[lowerName].push(file);
|
|
513
538
|
}
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
for (let name in componentsByName) {
|
|
517
|
-
const xmlFiles = componentsByName[name];
|
|
539
|
+
}
|
|
540
|
+
for (const xmlFiles of componentsByName.values()) {
|
|
518
541
|
//add diagnostics for every duplicate component with this name
|
|
519
542
|
if (xmlFiles.length > 1) {
|
|
520
543
|
for (let xmlFile of xmlFiles) {
|
|
521
544
|
const { componentName } = xmlFile;
|
|
522
545
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.duplicateComponentName(componentName.text)), { range: xmlFile.componentName.range, file: xmlFile, relatedInformation: xmlFiles.filter(x => x !== xmlFile).map(x => {
|
|
523
546
|
return {
|
|
524
|
-
location: vscode_languageserver_1.Location.create(vscode_uri_1.URI.file(xmlFile.
|
|
547
|
+
location: vscode_languageserver_1.Location.create(vscode_uri_1.URI.file(xmlFile.srcPath).toString(), x.componentName.range),
|
|
525
548
|
message: 'Also defined here'
|
|
526
549
|
};
|
|
527
550
|
}) }));
|
|
@@ -542,11 +565,19 @@ class Program {
|
|
|
542
565
|
}
|
|
543
566
|
/**
|
|
544
567
|
* Get the file at the given path
|
|
545
|
-
* @param
|
|
568
|
+
* @param filePath can be a srcPath, a pkgPath, or a destPath (same as pkgPath but without `pkg:/`)
|
|
569
|
+
* @param normalizePath should this function repair and standardize the path? Passing false should have a performance boost if you can guarantee your path is already sanitized
|
|
546
570
|
*/
|
|
547
|
-
getFile(
|
|
548
|
-
|
|
549
|
-
|
|
571
|
+
getFile(filePath, normalizePath = true) {
|
|
572
|
+
if (typeof filePath !== 'string') {
|
|
573
|
+
return undefined;
|
|
574
|
+
}
|
|
575
|
+
else if (path.isAbsolute(filePath)) {
|
|
576
|
+
return this.files[(normalizePath ? util_1.util.standardizePath(filePath) : filePath).toLowerCase()];
|
|
577
|
+
}
|
|
578
|
+
else {
|
|
579
|
+
return this.pkgMap[(normalizePath ? util_1.util.sanitizePkgPath(filePath) : filePath).toLowerCase()];
|
|
580
|
+
}
|
|
550
581
|
}
|
|
551
582
|
/**
|
|
552
583
|
* Get a list of all scopes the file is loaded into
|
|
@@ -571,7 +602,7 @@ class Program {
|
|
|
571
602
|
//look through all files in scope for matches
|
|
572
603
|
for (const scope of this.getScopesForFile(originFile)) {
|
|
573
604
|
for (const file of scope.getAllFiles()) {
|
|
574
|
-
if (reflection_1.isXmlFile(file) || filesSearched.has(file)) {
|
|
605
|
+
if ((0, reflection_1.isXmlFile)(file) || filesSearched.has(file)) {
|
|
575
606
|
continue;
|
|
576
607
|
}
|
|
577
608
|
filesSearched.add(file);
|
|
@@ -594,17 +625,20 @@ class Program {
|
|
|
594
625
|
//get all function names for the xml file and parents
|
|
595
626
|
let funcNames = new Set();
|
|
596
627
|
let currentScope = scope;
|
|
597
|
-
while (reflection_1.isXmlScope(currentScope)) {
|
|
598
|
-
for (let
|
|
599
|
-
if (
|
|
600
|
-
|
|
628
|
+
while ((0, reflection_1.isXmlScope)(currentScope)) {
|
|
629
|
+
for (let member of (_b = (_a = currentScope.xmlFile.ast.component) === null || _a === void 0 ? void 0 : _a.interfaceMembers) !== null && _b !== void 0 ? _b : []) {
|
|
630
|
+
if ((0, reflection_1.isSGInterfaceFunction)(member)) {
|
|
631
|
+
const name = member.name;
|
|
632
|
+
if (!filterName || name === filterName) {
|
|
633
|
+
funcNames.add(name);
|
|
634
|
+
}
|
|
601
635
|
}
|
|
602
636
|
}
|
|
603
637
|
currentScope = currentScope.getParentScope();
|
|
604
638
|
}
|
|
605
639
|
//look through all files in scope for matches
|
|
606
640
|
for (const file of scope.getOwnFiles()) {
|
|
607
|
-
if (reflection_1.isXmlFile(file) || filesSearched.has(file)) {
|
|
641
|
+
if ((0, reflection_1.isXmlFile)(file) || filesSearched.has(file)) {
|
|
608
642
|
continue;
|
|
609
643
|
}
|
|
610
644
|
filesSearched.add(file);
|
|
@@ -620,19 +654,19 @@ class Program {
|
|
|
620
654
|
}
|
|
621
655
|
/**
|
|
622
656
|
* Find all available completion items at the given position
|
|
623
|
-
* @param
|
|
657
|
+
* @param srcPath The absolute path to the source file on disk
|
|
624
658
|
* @param lineIndex
|
|
625
659
|
* @param columnIndex
|
|
626
660
|
*/
|
|
627
|
-
getCompletions(
|
|
628
|
-
let file = this.getFile(
|
|
661
|
+
getCompletions(srcPath, position) {
|
|
662
|
+
let file = this.getFile(srcPath);
|
|
629
663
|
if (!file) {
|
|
630
664
|
return [];
|
|
631
665
|
}
|
|
632
666
|
let result = [];
|
|
633
|
-
if (reflection_1.isBrsFile(file) && file.isPositionNextToTokenKind(position, lexer_1.TokenKind.Callfunc)) {
|
|
667
|
+
if ((0, reflection_1.isBrsFile)(file) && file.parser.isPositionNextToTokenKind(position, lexer_1.TokenKind.Callfunc)) {
|
|
634
668
|
// is next to a @. callfunc invocation - must be an interface method
|
|
635
|
-
for (const scope of this.getScopes().filter((s) => reflection_1.isXmlScope(s))) {
|
|
669
|
+
for (const scope of this.getScopes().filter((s) => (0, reflection_1.isXmlScope)(s))) {
|
|
636
670
|
let fileLinks = this.getStatementsForXmlFile(scope);
|
|
637
671
|
for (let fileLink of fileLinks) {
|
|
638
672
|
result.push(scope.createCompletionFromFunctionStatement(fileLink.item));
|
|
@@ -646,7 +680,12 @@ class Program {
|
|
|
646
680
|
//if there are no scopes, include the global scope so we at least get the built-in functions
|
|
647
681
|
scopes = scopes.length > 0 ? scopes : [this.globalScope];
|
|
648
682
|
//get the completions from all scopes for this file
|
|
649
|
-
let allCompletions = util_1.util.flatMap(scopes.map(ctx =>
|
|
683
|
+
let allCompletions = util_1.util.flatMap(scopes.map(ctx => {
|
|
684
|
+
ctx.linkSymbolTable();
|
|
685
|
+
const completions = file.getCompletions(position, ctx);
|
|
686
|
+
ctx.unlinkSymbolTable();
|
|
687
|
+
return completions;
|
|
688
|
+
}), c => c);
|
|
650
689
|
//only keep completions common to every scope for this file
|
|
651
690
|
let keyCounts = {};
|
|
652
691
|
for (let completion of allCompletions) {
|
|
@@ -662,25 +701,26 @@ class Program {
|
|
|
662
701
|
* Goes through each file and builds a list of workspace symbols for the program. Used by LanguageServer's onWorkspaceSymbol functionality
|
|
663
702
|
*/
|
|
664
703
|
getWorkspaceSymbols() {
|
|
665
|
-
const
|
|
704
|
+
const result = [];
|
|
705
|
+
for (const key in this.files) {
|
|
666
706
|
const file = this.files[key];
|
|
667
|
-
if (reflection_1.isBrsFile(file)) {
|
|
668
|
-
|
|
707
|
+
if ((0, reflection_1.isBrsFile)(file)) {
|
|
708
|
+
result.push(...file.getWorkspaceSymbols());
|
|
669
709
|
}
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
return util_1.util.flatMap(results, c => c);
|
|
710
|
+
}
|
|
711
|
+
return result;
|
|
673
712
|
}
|
|
674
713
|
/**
|
|
675
714
|
* Given a position in a file, if the position is sitting on some type of identifier,
|
|
676
715
|
* go to the definition of that identifier (where this thing was first defined)
|
|
716
|
+
* @param srcPath The absolute path to the source file on disk
|
|
677
717
|
*/
|
|
678
|
-
getDefinition(
|
|
679
|
-
let file = this.getFile(
|
|
718
|
+
getDefinition(srcPath, position) {
|
|
719
|
+
let file = this.getFile(srcPath);
|
|
680
720
|
if (!file) {
|
|
681
721
|
return [];
|
|
682
722
|
}
|
|
683
|
-
if (reflection_1.isBrsFile(file)) {
|
|
723
|
+
if ((0, reflection_1.isBrsFile)(file)) {
|
|
684
724
|
return file.getDefinition(position);
|
|
685
725
|
}
|
|
686
726
|
else {
|
|
@@ -692,9 +732,12 @@ class Program {
|
|
|
692
732
|
return results;
|
|
693
733
|
}
|
|
694
734
|
}
|
|
695
|
-
|
|
735
|
+
/**
|
|
736
|
+
* @param srcPath The absolute path to the source file on disk
|
|
737
|
+
*/
|
|
738
|
+
getHover(srcPath, position) {
|
|
696
739
|
//find the file
|
|
697
|
-
let file = this.getFile(
|
|
740
|
+
let file = this.getFile(srcPath);
|
|
698
741
|
if (!file) {
|
|
699
742
|
return null;
|
|
700
743
|
}
|
|
@@ -702,10 +745,11 @@ class Program {
|
|
|
702
745
|
}
|
|
703
746
|
/**
|
|
704
747
|
* Compute code actions for the given file and range
|
|
748
|
+
* @param srcPath The absolute path to the source file on disk
|
|
705
749
|
*/
|
|
706
|
-
getCodeActions(
|
|
750
|
+
getCodeActions(srcPath, range) {
|
|
707
751
|
const codeActions = [];
|
|
708
|
-
const file = this.getFile(
|
|
752
|
+
const file = this.getFile(srcPath);
|
|
709
753
|
if (file) {
|
|
710
754
|
const diagnostics = this
|
|
711
755
|
//get all current diagnostics (filtered by diagnostic filters)
|
|
@@ -726,10 +770,26 @@ class Program {
|
|
|
726
770
|
}
|
|
727
771
|
return codeActions;
|
|
728
772
|
}
|
|
773
|
+
/**
|
|
774
|
+
* Get semantic tokens for the specified file
|
|
775
|
+
*/
|
|
776
|
+
getSemanticTokens(srcPath) {
|
|
777
|
+
const file = this.getFile(srcPath);
|
|
778
|
+
if (file) {
|
|
779
|
+
const result = [];
|
|
780
|
+
this.plugins.emit('onGetSemanticTokens', {
|
|
781
|
+
program: this,
|
|
782
|
+
file: file,
|
|
783
|
+
scopes: this.getScopesForFile(file),
|
|
784
|
+
semanticTokens: result
|
|
785
|
+
});
|
|
786
|
+
return result;
|
|
787
|
+
}
|
|
788
|
+
}
|
|
729
789
|
getSignatureHelp(filepath, position) {
|
|
730
790
|
var _a;
|
|
731
791
|
let file = this.getFile(filepath);
|
|
732
|
-
if (!file || !reflection_1.isBrsFile(file)) {
|
|
792
|
+
if (!file || !(0, reflection_1.isBrsFile)(file)) {
|
|
733
793
|
return [];
|
|
734
794
|
}
|
|
735
795
|
const results = new Map();
|
|
@@ -752,12 +812,14 @@ class Program {
|
|
|
752
812
|
//if m class reference.. then
|
|
753
813
|
//only get statements from the class I am in..
|
|
754
814
|
if (functionExpression) {
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
815
|
+
const currentToken = file.parser.getTokenAt(position);
|
|
816
|
+
for (let scope of this.getScopesForFile(file)) {
|
|
817
|
+
scope.linkSymbolTable();
|
|
818
|
+
let myClass = file.getClassFromToken(currentToken, functionExpression, scope);
|
|
819
|
+
if (myClass) {
|
|
758
820
|
let classes = scope.getClassHierarchy(myClass.item.getName(parser_1.ParseMode.BrighterScript).toLowerCase());
|
|
759
821
|
//and anything from any class in scope to a non m class
|
|
760
|
-
for (let statement of [...classes].filter((i) => reflection_1.isClassMethodStatement(i.item))) {
|
|
822
|
+
for (let statement of [...classes].filter((i) => (0, reflection_1.isClassMethodStatement)(i.item))) {
|
|
761
823
|
let sigHelp = statement.file.getSignatureHelpForStatement(statement.item);
|
|
762
824
|
if (sigHelp && !results.has[sigHelp.key]) {
|
|
763
825
|
results.set(sigHelp.key, sigHelp);
|
|
@@ -765,6 +827,7 @@ class Program {
|
|
|
765
827
|
}
|
|
766
828
|
}
|
|
767
829
|
}
|
|
830
|
+
scope.unlinkSymbolTable();
|
|
768
831
|
}
|
|
769
832
|
}
|
|
770
833
|
if (identifierInfo.dotPart) {
|
|
@@ -786,7 +849,7 @@ class Program {
|
|
|
786
849
|
}
|
|
787
850
|
}
|
|
788
851
|
else if (identifierInfo.statementType === '@.') {
|
|
789
|
-
for (const scope of this.getScopes().filter((s) => reflection_1.isXmlScope(s))) {
|
|
852
|
+
for (const scope of this.getScopes().filter((s) => (0, reflection_1.isXmlScope)(s))) {
|
|
790
853
|
let fileLinks = this.getStatementsForXmlFile(scope, identifierInfo.name);
|
|
791
854
|
for (let fileLink of fileLinks) {
|
|
792
855
|
let sigHelp = fileLink.file.getSignatureHelpForStatement(fileLink.item);
|
|
@@ -825,12 +888,12 @@ class Program {
|
|
|
825
888
|
if (!itemCounts.isArgStartFound) {
|
|
826
889
|
//try to get sig help based on the name
|
|
827
890
|
index = position.character;
|
|
828
|
-
let currentToken = file.getTokenAt(position);
|
|
891
|
+
let currentToken = file.parser.getTokenAt(position);
|
|
829
892
|
if (currentToken && currentToken.kind !== lexer_1.TokenKind.Comment) {
|
|
830
893
|
name = file.getPartialVariableName(currentToken, [lexer_1.TokenKind.New]);
|
|
831
894
|
if (!name) {
|
|
832
895
|
//try the previous token, incase we're on a bracket
|
|
833
|
-
currentToken = file.getPreviousToken(currentToken);
|
|
896
|
+
currentToken = file.parser.getPreviousToken(currentToken);
|
|
834
897
|
name = file.getPartialVariableName(currentToken, [lexer_1.TokenKind.New]);
|
|
835
898
|
}
|
|
836
899
|
if (name === null || name === void 0 ? void 0 : name.indexOf('.')) {
|
|
@@ -937,9 +1000,12 @@ class Program {
|
|
|
937
1000
|
}
|
|
938
1001
|
return itemCounts;
|
|
939
1002
|
}
|
|
940
|
-
|
|
1003
|
+
/**
|
|
1004
|
+
* @param srcPath The absolute path to the source file on disk
|
|
1005
|
+
*/
|
|
1006
|
+
getReferences(srcPath, position) {
|
|
941
1007
|
//find the file
|
|
942
|
-
let file = this.getFile(
|
|
1008
|
+
let file = this.getFile(srcPath);
|
|
943
1009
|
if (!file) {
|
|
944
1010
|
return null;
|
|
945
1011
|
}
|
|
@@ -957,8 +1023,8 @@ class Program {
|
|
|
957
1023
|
*/
|
|
958
1024
|
let resultPkgPaths = {};
|
|
959
1025
|
//restrict to only .brs files
|
|
960
|
-
for (
|
|
961
|
-
|
|
1026
|
+
for (const key in this.files) {
|
|
1027
|
+
const file = this.files[key];
|
|
962
1028
|
if (
|
|
963
1029
|
//is a BrightScript or BrighterScript file
|
|
964
1030
|
(file.extension === '.bs' || file.extension === '.brs') &&
|
|
@@ -966,14 +1032,12 @@ class Program {
|
|
|
966
1032
|
lowerSourcePkgPath !== file.pkgPath.toLowerCase()) {
|
|
967
1033
|
//add the relative path
|
|
968
1034
|
let relativePath = util_1.util.getRelativePath(sourcePkgPath, file.pkgPath).replace(/\\/g, '/');
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
if (!resultPkgPaths[lowerFilePkgPath]) {
|
|
973
|
-
resultPkgPaths[lowerFilePkgPath] = true;
|
|
1035
|
+
const lowerPkgPath = file.pkgPath.toLowerCase();
|
|
1036
|
+
if (!resultPkgPaths[lowerPkgPath]) {
|
|
1037
|
+
resultPkgPaths[lowerPkgPath] = true;
|
|
974
1038
|
result.push({
|
|
975
1039
|
label: relativePath,
|
|
976
|
-
detail: file.
|
|
1040
|
+
detail: file.srcPath,
|
|
977
1041
|
kind: vscode_languageserver_1.CompletionItemKind.File,
|
|
978
1042
|
textEdit: {
|
|
979
1043
|
newText: relativePath,
|
|
@@ -982,11 +1046,11 @@ class Program {
|
|
|
982
1046
|
});
|
|
983
1047
|
//add the absolute path
|
|
984
1048
|
result.push({
|
|
985
|
-
label:
|
|
986
|
-
detail: file.
|
|
1049
|
+
label: file.pkgPath,
|
|
1050
|
+
detail: file.srcPath,
|
|
987
1051
|
kind: vscode_languageserver_1.CompletionItemKind.File,
|
|
988
1052
|
textEdit: {
|
|
989
|
-
newText:
|
|
1053
|
+
newText: file.pkgPath,
|
|
990
1054
|
range: scriptImport.filePathRange
|
|
991
1055
|
}
|
|
992
1056
|
});
|
|
@@ -998,76 +1062,84 @@ class Program {
|
|
|
998
1062
|
/**
|
|
999
1063
|
* Transpile a single file and get the result as a string.
|
|
1000
1064
|
* This does not write anything to the file system.
|
|
1065
|
+
* @param srcPath The absolute path to the source file on disk
|
|
1001
1066
|
*/
|
|
1002
|
-
getTranspiledFileContents(
|
|
1003
|
-
let file = this.getFile(
|
|
1067
|
+
getTranspiledFileContents(srcPath) {
|
|
1068
|
+
let file = this.getFile(srcPath);
|
|
1004
1069
|
let result = file.transpile();
|
|
1005
|
-
return Object.assign(Object.assign({}, result), {
|
|
1070
|
+
return Object.assign(Object.assign({}, result), { srcPath: file.srcPath, pkgPath: file.pkgPath });
|
|
1006
1071
|
}
|
|
1007
1072
|
async transpile(fileEntries, stagingFolderPath) {
|
|
1008
|
-
// map fileEntries using their path as key
|
|
1073
|
+
// map fileEntries using their path as key to avoid excessive "find()" operations
|
|
1009
1074
|
const mappedFileEntries = fileEntries.reduce((collection, entry) => {
|
|
1010
|
-
collection[util_1.standardizePath `${entry.src}`] = entry;
|
|
1075
|
+
collection[(0, util_1.standardizePath) `${entry.src}`] = entry;
|
|
1011
1076
|
return collection;
|
|
1012
1077
|
}, {});
|
|
1013
|
-
const entries =
|
|
1014
|
-
|
|
1078
|
+
const entries = [];
|
|
1079
|
+
for (const key in this.files) {
|
|
1080
|
+
const file = this.files[key];
|
|
1081
|
+
let filePathObj = mappedFileEntries[(0, util_1.standardizePath) `${file.srcPath}`];
|
|
1015
1082
|
if (!filePathObj) {
|
|
1016
1083
|
//this file has been added in-memory, from a plugin, for example
|
|
1017
1084
|
filePathObj = {
|
|
1018
1085
|
//add an interpolated src path (since it doesn't actually exist in memory)
|
|
1019
|
-
src: `bsc:/${file.pkgPath}`,
|
|
1086
|
+
src: `bsc-in-memory:/${util_1.util.removeProtocol(file.pkgPath)}`,
|
|
1020
1087
|
dest: file.pkgPath
|
|
1021
1088
|
};
|
|
1022
1089
|
}
|
|
1023
|
-
//
|
|
1024
|
-
let outputPath = filePathObj.dest
|
|
1090
|
+
//prep the output path
|
|
1091
|
+
let outputPath = filePathObj.dest
|
|
1092
|
+
//replace any leading protocol
|
|
1093
|
+
.replace(/^[-a-z_]+:\//, '')
|
|
1094
|
+
//change any .bs file extension to .brs
|
|
1095
|
+
.replace(/\.bs$/gi, '.brs');
|
|
1025
1096
|
//prepend the staging folder path
|
|
1026
|
-
outputPath = util_1.standardizePath `${stagingFolderPath}/${outputPath}`;
|
|
1027
|
-
|
|
1097
|
+
outputPath = (0, util_1.standardizePath) `${stagingFolderPath}/${outputPath}`;
|
|
1098
|
+
entries.push({
|
|
1028
1099
|
file: file,
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1100
|
+
program: this,
|
|
1101
|
+
outputPath: outputPath,
|
|
1102
|
+
editor: new AstEditor_1.AstEditor()
|
|
1103
|
+
});
|
|
1104
|
+
}
|
|
1032
1105
|
this.plugins.emit('beforeProgramTranspile', {
|
|
1033
1106
|
program: this,
|
|
1034
1107
|
entries: entries
|
|
1035
1108
|
});
|
|
1036
1109
|
const promises = entries.map(async (entry) => {
|
|
1037
1110
|
//skip transpiling typedef files
|
|
1038
|
-
if (reflection_1.isBrsFile(entry.file) && entry.file.isTypedef) {
|
|
1111
|
+
if ((0, reflection_1.isBrsFile)(entry.file) && entry.file.isTypedef) {
|
|
1039
1112
|
return;
|
|
1040
1113
|
}
|
|
1041
|
-
this.plugins.emit('beforeFileTranspile',
|
|
1042
|
-
program: this,
|
|
1043
|
-
file: entry.file,
|
|
1044
|
-
outputPath: entry.outputPath
|
|
1045
|
-
});
|
|
1114
|
+
this.plugins.emit('beforeFileTranspile', entry);
|
|
1046
1115
|
const { file, outputPath } = entry;
|
|
1116
|
+
//if we have any edits, assume the file needs to be transpiled
|
|
1117
|
+
if (entry.editor.hasChanges) {
|
|
1118
|
+
//use the `editor` because it'll track the previous value for us and revert later on
|
|
1119
|
+
entry.editor.setProperty(file, 'needsTranspiled', true);
|
|
1120
|
+
}
|
|
1047
1121
|
const result = file.transpile();
|
|
1048
1122
|
//make sure the full dir path exists
|
|
1049
1123
|
await fsExtra.ensureDir(path.dirname(outputPath));
|
|
1050
1124
|
if (await fsExtra.pathExists(outputPath)) {
|
|
1051
|
-
throw new Error(`Error while transpiling "${file.
|
|
1125
|
+
throw new Error(`Error while transpiling "${file.srcPath}". A file already exists at "${outputPath}" and will not be overwritten.`);
|
|
1052
1126
|
}
|
|
1053
1127
|
const writeMapPromise = result.map ? fsExtra.writeFile(`${outputPath}.map`, result.map.toString()) : null;
|
|
1054
1128
|
await Promise.all([
|
|
1055
1129
|
fsExtra.writeFile(outputPath, result.code),
|
|
1056
1130
|
writeMapPromise
|
|
1057
1131
|
]);
|
|
1058
|
-
if (reflection_1.isBrsFile(file) && this.options.emitDefinitions) {
|
|
1132
|
+
if ((0, reflection_1.isBrsFile)(file) && this.options.emitDefinitions) {
|
|
1059
1133
|
const typedef = file.getTypedef();
|
|
1060
1134
|
const typedefPath = outputPath.replace(/\.brs$/i, '.d.bs');
|
|
1061
1135
|
await fsExtra.writeFile(typedefPath, typedef);
|
|
1062
1136
|
}
|
|
1063
|
-
this.plugins.emit('afterFileTranspile',
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
outputPath: entry.outputPath
|
|
1067
|
-
});
|
|
1137
|
+
this.plugins.emit('afterFileTranspile', entry);
|
|
1138
|
+
//undo all `editor` edits that may have been applied to this file.
|
|
1139
|
+
entry.editor.undoAll();
|
|
1068
1140
|
});
|
|
1069
1141
|
//if there's no bslib file already loaded into the program, copy it to the staging directory
|
|
1070
|
-
if (!this.
|
|
1142
|
+
if (!this.getFile(bslibAliasedRokuModulesPkgPath) && !this.getFile(`pkg:/source/bslib.brs`)) {
|
|
1071
1143
|
promises.push(util_1.util.copyBslibToStaging(stagingFolderPath));
|
|
1072
1144
|
}
|
|
1073
1145
|
await Promise.all(promises);
|
|
@@ -1084,7 +1156,7 @@ class Program {
|
|
|
1084
1156
|
const lowerFunctionName = functionName.toLowerCase();
|
|
1085
1157
|
//find every file with this function defined
|
|
1086
1158
|
for (const file of Object.values(this.files)) {
|
|
1087
|
-
if (reflection_1.isBrsFile(file)) {
|
|
1159
|
+
if ((0, reflection_1.isBrsFile)(file)) {
|
|
1088
1160
|
//TODO handle namespace-relative function calls
|
|
1089
1161
|
//if the file has a function with this name
|
|
1090
1162
|
if (file.parser.references.functionStatementLookup.get(lowerFunctionName) !== undefined) {
|
|
@@ -1102,7 +1174,7 @@ class Program {
|
|
|
1102
1174
|
const lowerClassName = className.toLowerCase();
|
|
1103
1175
|
//find every file with this class defined
|
|
1104
1176
|
for (const file of Object.values(this.files)) {
|
|
1105
|
-
if (reflection_1.isBrsFile(file)) {
|
|
1177
|
+
if ((0, reflection_1.isBrsFile)(file)) {
|
|
1106
1178
|
//TODO handle namespace-relative classes
|
|
1107
1179
|
//if the file has a function with this name
|
|
1108
1180
|
if (file.parser.references.classStatementLookup.get(lowerClassName) !== undefined) {
|
|
@@ -1124,7 +1196,7 @@ class Program {
|
|
|
1124
1196
|
try {
|
|
1125
1197
|
//we only load this manifest once, so do it sync to improve speed downstream
|
|
1126
1198
|
contents = fsExtra.readFileSync(manifestPath, 'utf-8');
|
|
1127
|
-
this._manifest = Manifest_1.parseManifest(contents);
|
|
1199
|
+
this._manifest = (0, Manifest_1.parseManifest)(contents);
|
|
1128
1200
|
}
|
|
1129
1201
|
catch (err) {
|
|
1130
1202
|
this._manifest = new Map();
|
|
@@ -1133,11 +1205,13 @@ class Program {
|
|
|
1133
1205
|
return this._manifest;
|
|
1134
1206
|
}
|
|
1135
1207
|
dispose() {
|
|
1136
|
-
|
|
1137
|
-
|
|
1208
|
+
var _a, _b;
|
|
1209
|
+
for (const key in this.files) {
|
|
1210
|
+
const file = this.files[key];
|
|
1211
|
+
(_a = file.dispose) === null || _a === void 0 ? void 0 : _a.call(file);
|
|
1138
1212
|
}
|
|
1139
1213
|
for (let name in this.scopes) {
|
|
1140
|
-
this.scopes[name].dispose();
|
|
1214
|
+
(_b = this.scopes[name]) === null || _b === void 0 ? void 0 : _b.dispose();
|
|
1141
1215
|
}
|
|
1142
1216
|
this.globalScope.dispose();
|
|
1143
1217
|
this.dependencyGraph.dispose();
|