brighterscript 1.0.0-alpha.2 → 1.0.0-alpha.20
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 +542 -253
- package/README.md +30 -9
- package/bsconfig.schema.json +13 -1
- package/dist/BsConfig.d.ts +4 -0
- package/dist/Cache.d.ts +3 -8
- package/dist/Cache.js +9 -14
- package/dist/Cache.js.map +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 +5 -4
- package/dist/DependencyGraph.js.map +1 -1
- package/dist/DiagnosticFilterer.js +1 -1
- package/dist/DiagnosticFilterer.js.map +1 -1
- package/dist/DiagnosticMessages.d.ts +59 -4
- package/dist/DiagnosticMessages.js +65 -7
- package/dist/DiagnosticMessages.js.map +1 -1
- package/dist/LanguageServer.d.ts +4 -14
- package/dist/LanguageServer.js +40 -26
- package/dist/LanguageServer.js.map +1 -1
- package/dist/Logger.d.ts +2 -0
- package/dist/Logger.js +10 -8
- package/dist/Logger.js.map +1 -1
- package/dist/PluginInterface.d.ts +7 -3
- package/dist/PluginInterface.js +9 -0
- package/dist/PluginInterface.js.map +1 -1
- package/dist/Program.d.ts +43 -25
- package/dist/Program.js +180 -82
- package/dist/Program.js.map +1 -1
- package/dist/ProgramBuilder.d.ts +4 -0
- package/dist/ProgramBuilder.js +30 -14
- package/dist/ProgramBuilder.js.map +1 -1
- package/dist/Scope.d.ts +100 -28
- package/dist/Scope.js +382 -154
- 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 +10 -4
- package/dist/SymbolTable.js +40 -13
- package/dist/SymbolTable.js.map +1 -1
- package/dist/XmlScope.d.ts +8 -3
- package/dist/XmlScope.js +65 -27
- package/dist/XmlScope.js.map +1 -1
- package/dist/astUtils/AstEditor.d.ts +33 -0
- package/dist/astUtils/AstEditor.js +107 -0
- package/dist/astUtils/AstEditor.js.map +1 -0
- package/dist/{types/FunctionType.spec.d.ts → astUtils/AstEditor.spec.d.ts} +0 -0
- package/dist/astUtils/AstEditor.spec.js +170 -0
- package/dist/astUtils/AstEditor.spec.js.map +1 -0
- package/dist/astUtils/creators.d.ts +24 -6
- package/dist/astUtils/creators.js +130 -19
- package/dist/astUtils/creators.js.map +1 -1
- package/dist/astUtils/creators.spec.js +14 -4
- package/dist/astUtils/creators.spec.js.map +1 -1
- package/dist/astUtils/reflection.d.ts +27 -8
- package/dist/astUtils/reflection.js +66 -1
- package/dist/astUtils/reflection.js.map +1 -1
- package/dist/astUtils/reflection.spec.js +130 -119
- 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.d.ts +17 -2
- package/dist/astUtils/visitors.js +2 -2
- package/dist/astUtils/visitors.js.map +1 -1
- package/dist/astUtils/visitors.spec.js +31 -29
- 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 +7 -1
- package/dist/bscPlugin/BscPlugin.js +28 -0
- package/dist/bscPlugin/BscPlugin.js.map +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +4 -4
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +26 -26
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +9 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +97 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.d.ts +1 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js +73 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -0
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.d.ts +8 -0
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js +52 -0
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js.map +1 -0
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.d.ts +1 -0
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js +32 -0
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js.map +1 -0
- package/dist/bscPlugin/validation/BrsFileValidator.d.ts +9 -0
- package/dist/bscPlugin/validation/BrsFileValidator.js +66 -0
- package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -0
- package/dist/bscPlugin/validation/ScopeValidator.d.ts +29 -0
- package/dist/bscPlugin/validation/ScopeValidator.js +183 -0
- package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -0
- package/dist/cli.js +9 -3
- package/dist/cli.js.map +1 -1
- package/dist/diagnosticUtils.d.ts +1 -0
- package/dist/diagnosticUtils.js +15 -8
- package/dist/diagnosticUtils.js.map +1 -1
- package/dist/examples/plugins/removePrint.js +12 -14
- package/dist/examples/plugins/removePrint.js.map +1 -1
- package/dist/files/BrsFile.Class.spec.js +634 -145
- package/dist/files/BrsFile.Class.spec.js.map +1 -1
- package/dist/files/BrsFile.d.ts +62 -30
- package/dist/files/BrsFile.js +683 -335
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/BrsFile.spec.js +1055 -449
- package/dist/files/BrsFile.spec.js.map +1 -1
- package/dist/files/XmlFile.d.ts +11 -10
- package/dist/files/XmlFile.js +33 -26
- package/dist/files/XmlFile.js.map +1 -1
- package/dist/files/XmlFile.spec.js +302 -237
- package/dist/files/XmlFile.spec.js.map +1 -1
- package/dist/files/tests/imports.spec.js +44 -42
- package/dist/files/tests/imports.spec.js.map +1 -1
- package/dist/files/tests/optionalChaning.spec.d.ts +1 -0
- package/dist/files/tests/optionalChaning.spec.js +88 -0
- package/dist/files/tests/optionalChaning.spec.js.map +1 -0
- package/dist/globalCallables.d.ts +3 -1
- package/dist/globalCallables.js +424 -152
- package/dist/globalCallables.js.map +1 -1
- package/dist/index.d.ts +13 -3
- package/dist/index.js +23 -4
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +129 -16
- package/dist/lexer/Lexer.d.ts +19 -1
- package/dist/lexer/Lexer.js +127 -21
- package/dist/lexer/Lexer.js.map +1 -1
- package/dist/lexer/Lexer.spec.js +657 -536
- package/dist/lexer/Lexer.spec.js.map +1 -1
- package/dist/lexer/Token.d.ts +2 -2
- package/dist/lexer/TokenKind.d.ts +13 -1
- package/dist/lexer/TokenKind.js +60 -3
- package/dist/lexer/TokenKind.js.map +1 -1
- package/dist/parser/BrsTranspileState.d.ts +7 -0
- package/dist/parser/BrsTranspileState.js +9 -0
- package/dist/parser/BrsTranspileState.js.map +1 -1
- package/dist/parser/Expression.d.ts +150 -34
- package/dist/parser/Expression.js +337 -150
- package/dist/parser/Expression.js.map +1 -1
- package/dist/parser/Parser.Class.spec.js +189 -89
- package/dist/parser/Parser.Class.spec.js.map +1 -1
- package/dist/parser/Parser.d.ts +152 -29
- package/dist/parser/Parser.js +1095 -501
- package/dist/parser/Parser.js.map +1 -1
- package/dist/parser/Parser.spec.js +687 -266
- 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 +194 -40
- package/dist/parser/Statement.js +597 -160
- 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/tests/Parser.spec.d.ts +10 -9
- package/dist/parser/tests/Parser.spec.js +15 -11
- package/dist/parser/tests/Parser.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/For.spec.js +60 -60
- package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/ForEach.spec.js +40 -39
- package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/If.spec.js +213 -194
- package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/While.spec.js +37 -37
- package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
- package/dist/parser/tests/expression/Additive.spec.js +30 -30
- package/dist/parser/tests/expression/Additive.spec.js.map +1 -1
- package/dist/parser/tests/expression/ArrayLiterals.spec.js +119 -119
- package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +162 -138
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
- package/dist/parser/tests/expression/Boolean.spec.js +24 -24
- package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
- package/dist/parser/tests/expression/Call.spec.js +41 -40
- package/dist/parser/tests/expression/Call.spec.js.map +1 -1
- package/dist/parser/tests/expression/Exponential.spec.js +17 -17
- package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
- package/dist/parser/tests/expression/Function.spec.js +256 -256
- package/dist/parser/tests/expression/Function.spec.js.map +1 -1
- package/dist/parser/tests/expression/Indexing.spec.js +87 -87
- package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
- package/dist/parser/tests/expression/Multiplicative.spec.js +37 -37
- package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +75 -63
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/PrefixUnary.spec.js +41 -41
- package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
- package/dist/parser/tests/expression/Primary.spec.js +41 -41
- 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 +171 -0
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -0
- package/dist/parser/tests/expression/Relational.spec.js +43 -43
- package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
- package/dist/parser/tests/expression/SourceLiteralExpression.spec.js +9 -9
- package/dist/parser/tests/expression/SourceLiteralExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js +28 -28
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TernaryExpression.spec.js +102 -102
- package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
- package/dist/parser/tests/statement/AssignmentOperators.spec.js +36 -36
- package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
- package/dist/parser/tests/statement/Declaration.spec.js +44 -44
- 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/Enum.spec.d.ts +1 -0
- package/dist/parser/tests/statement/Enum.spec.js +840 -0
- package/dist/parser/tests/statement/Enum.spec.js.map +1 -0
- package/dist/parser/tests/statement/For.spec.d.ts +1 -0
- package/dist/parser/tests/statement/For.spec.js +46 -0
- package/dist/parser/tests/statement/For.spec.js.map +1 -0
- package/dist/parser/tests/statement/ForEach.spec.d.ts +1 -0
- package/dist/parser/tests/statement/ForEach.spec.js +37 -0
- package/dist/parser/tests/statement/ForEach.spec.js.map +1 -0
- package/dist/parser/tests/statement/Function.spec.js +198 -197
- package/dist/parser/tests/statement/Function.spec.js.map +1 -1
- package/dist/parser/tests/statement/Goto.spec.js +15 -14
- package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
- package/dist/parser/tests/statement/Increment.spec.js +50 -50
- 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 +254 -0
- package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -0
- package/dist/parser/tests/statement/LibraryStatement.spec.js +17 -17
- package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/Misc.spec.js +108 -106
- package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
- package/dist/parser/tests/statement/PrintStatement.spec.js +40 -40
- package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/ReturnStatement.spec.js +46 -46
- package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/Set.spec.js +83 -83
- package/dist/parser/tests/statement/Set.spec.js.map +1 -1
- package/dist/parser/tests/statement/Stop.spec.js +12 -11
- 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 +15 -13
- package/dist/parser/tests/statement/TryCatch.spec.js.map +1 -1
- package/dist/preprocessor/Chunk.d.ts +1 -1
- package/dist/preprocessor/Chunk.js.map +1 -1
- package/dist/preprocessor/Manifest.d.ts +5 -5
- package/dist/preprocessor/Manifest.js +14 -35
- package/dist/preprocessor/Manifest.js.map +1 -1
- package/dist/preprocessor/Manifest.spec.d.ts +1 -0
- package/dist/preprocessor/Manifest.spec.js +78 -103
- package/dist/preprocessor/Manifest.spec.js.map +1 -1
- package/dist/preprocessor/Preprocessor.d.ts +1 -1
- package/dist/preprocessor/Preprocessor.js +8 -8
- 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/roku-types/data.json +21891 -0
- package/dist/roku-types/index.d.ts +6776 -0
- package/dist/roku-types/index.js +11 -0
- package/dist/roku-types/index.js.map +1 -0
- package/dist/types/ArrayType.d.ts +8 -5
- package/dist/types/ArrayType.js +52 -12
- package/dist/types/ArrayType.js.map +1 -1
- package/dist/types/ArrayType.spec.js +72 -11
- package/dist/types/ArrayType.spec.js.map +1 -1
- package/dist/types/BooleanType.d.ts +4 -2
- package/dist/types/BooleanType.js +9 -4
- package/dist/types/BooleanType.js.map +1 -1
- package/dist/types/BooleanType.spec.js +5 -3
- package/dist/types/BooleanType.spec.js.map +1 -1
- package/dist/types/BscType.d.ts +20 -5
- package/dist/types/BscType.js +24 -0
- package/dist/types/BscType.js.map +1 -1
- package/dist/types/CustomType.d.ts +8 -6
- package/dist/types/CustomType.js +20 -11
- package/dist/types/CustomType.js.map +1 -1
- package/dist/types/DoubleType.d.ts +2 -0
- package/dist/types/DoubleType.js +14 -9
- package/dist/types/DoubleType.js.map +1 -1
- package/dist/types/DoubleType.spec.js +5 -3
- package/dist/types/DoubleType.spec.js.map +1 -1
- package/dist/types/DynamicType.d.ts +2 -0
- package/dist/types/DynamicType.js +6 -2
- 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 +2 -0
- package/dist/types/FloatType.js +14 -9
- package/dist/types/FloatType.js.map +1 -1
- package/dist/types/FloatType.spec.js +4 -2
- package/dist/types/FloatType.spec.js.map +1 -1
- package/dist/types/FunctionType.d.ts +7 -31
- package/dist/types/FunctionType.js +11 -57
- package/dist/types/FunctionType.js.map +1 -1
- package/dist/types/IntegerType.d.ts +2 -0
- package/dist/types/IntegerType.js +14 -9
- package/dist/types/IntegerType.js.map +1 -1
- package/dist/types/IntegerType.spec.js +5 -3
- package/dist/types/IntegerType.spec.js.map +1 -1
- package/dist/types/InterfaceType.d.ts +13 -4
- package/dist/types/InterfaceType.js +48 -8
- package/dist/types/InterfaceType.js.map +1 -1
- package/dist/types/InterfaceType.spec.d.ts +1 -0
- package/dist/types/InterfaceType.spec.js +194 -0
- package/dist/types/InterfaceType.spec.js.map +1 -0
- package/dist/types/InvalidType.d.ts +4 -2
- package/dist/types/InvalidType.js +10 -5
- package/dist/types/InvalidType.js.map +1 -1
- package/dist/types/InvalidType.spec.js +4 -2
- package/dist/types/InvalidType.spec.js.map +1 -1
- package/dist/types/LazyType.d.ts +8 -7
- package/dist/types/LazyType.js +22 -10
- package/dist/types/LazyType.js.map +1 -1
- package/dist/types/LongIntegerType.d.ts +2 -0
- package/dist/types/LongIntegerType.js +14 -9
- package/dist/types/LongIntegerType.js.map +1 -1
- package/dist/types/LongIntegerType.spec.js +4 -2
- package/dist/types/LongIntegerType.spec.js.map +1 -1
- package/dist/types/ObjectType.d.ts +8 -4
- package/dist/types/ObjectType.js +9 -4
- 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.d.ts +4 -2
- package/dist/types/StringType.js +9 -4
- package/dist/types/StringType.js.map +1 -1
- package/dist/types/StringType.spec.js +4 -2
- package/dist/types/StringType.spec.js.map +1 -1
- package/dist/types/TypedFunctionType.d.ts +28 -0
- package/dist/types/TypedFunctionType.js +88 -0
- package/dist/types/TypedFunctionType.js.map +1 -0
- package/dist/types/TypedFunctionType.spec.d.ts +1 -0
- package/dist/types/TypedFunctionType.spec.js +37 -0
- package/dist/types/TypedFunctionType.spec.js.map +1 -0
- package/dist/types/UninitializedType.js +3 -3
- package/dist/types/UninitializedType.js.map +1 -1
- package/dist/types/VoidType.d.ts +4 -2
- package/dist/types/VoidType.js +8 -4
- 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 +118 -0
- package/dist/types/helpers.js.map +1 -0
- package/dist/util.d.ts +87 -16
- package/dist/util.js +339 -94
- package/dist/util.js.map +1 -1
- package/dist/validators/ClassValidator.d.ts +19 -2
- package/dist/validators/ClassValidator.js +163 -102
- package/dist/validators/ClassValidator.js.map +1 -1
- package/package.json +26 -15
- 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 -17
- 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/types/FunctionType.spec.js +0 -23
- package/dist/types/FunctionType.spec.js.map +0 -1
package/dist/files/BrsFile.js
CHANGED
|
@@ -6,10 +6,11 @@ const vscode_languageserver_1 = require("vscode-languageserver");
|
|
|
6
6
|
const chalk_1 = require("chalk");
|
|
7
7
|
const path = require("path");
|
|
8
8
|
const DiagnosticMessages_1 = require("../DiagnosticMessages");
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
9
|
+
const Token_1 = require("../lexer/Token");
|
|
10
|
+
const Lexer_1 = require("../lexer/Lexer");
|
|
11
|
+
const TokenKind_1 = require("../lexer/TokenKind");
|
|
12
|
+
const Parser_1 = require("../parser/Parser");
|
|
13
|
+
const DynamicType_1 = require("../types/DynamicType");
|
|
13
14
|
const util_1 = require("../util");
|
|
14
15
|
const BrsTranspileState_1 = require("../parser/BrsTranspileState");
|
|
15
16
|
const Preprocessor_1 = require("../preprocessor/Preprocessor");
|
|
@@ -18,6 +19,9 @@ const serialize_error_1 = require("serialize-error");
|
|
|
18
19
|
const reflection_1 = require("../astUtils/reflection");
|
|
19
20
|
const visitors_1 = require("../astUtils/visitors");
|
|
20
21
|
const CommentFlagProcessor_1 = require("../CommentFlagProcessor");
|
|
22
|
+
const BscType_1 = require("../types/BscType");
|
|
23
|
+
const UninitializedType_1 = require("../types/UninitializedType");
|
|
24
|
+
const InvalidType_1 = require("../types/InvalidType");
|
|
21
25
|
/**
|
|
22
26
|
* Holds all details about this file within the scope of the whole program
|
|
23
27
|
*/
|
|
@@ -38,30 +42,27 @@ class BrsFile {
|
|
|
38
42
|
/**
|
|
39
43
|
* The parseMode used for the parser for this file
|
|
40
44
|
*/
|
|
41
|
-
this.parseMode =
|
|
45
|
+
this.parseMode = Parser_1.ParseMode.BrightScript;
|
|
42
46
|
/**
|
|
43
47
|
* Indicates whether this file needs to be validated.
|
|
48
|
+
* Files are only ever validated a single time
|
|
44
49
|
*/
|
|
45
50
|
this.isValidated = false;
|
|
46
51
|
this.diagnostics = [];
|
|
47
52
|
this.commentFlags = [];
|
|
48
53
|
this.callables = [];
|
|
49
54
|
this.functionCalls = [];
|
|
50
|
-
/**
|
|
51
|
-
* files referenced by import statements
|
|
52
|
-
*/
|
|
53
|
-
this.ownScriptImports = [];
|
|
54
55
|
/**
|
|
55
56
|
* Does this file need to be transpiled?
|
|
56
57
|
*/
|
|
57
58
|
this.needsTranspiled = false;
|
|
58
|
-
this.srcPath = util_1.standardizePath `${this.srcPath}`;
|
|
59
|
+
this.srcPath = (0, util_1.standardizePath) `${this.srcPath}`;
|
|
59
60
|
this.dependencyGraphKey = this.pkgPath.toLowerCase();
|
|
60
61
|
this.extension = util_1.util.getExtension(this.srcPath);
|
|
61
62
|
//all BrighterScript files need to be transpiled
|
|
62
63
|
if ((_a = this.extension) === null || _a === void 0 ? void 0 : _a.endsWith('.bs')) {
|
|
63
64
|
this.needsTranspiled = true;
|
|
64
|
-
this.parseMode =
|
|
65
|
+
this.parseMode = Parser_1.ParseMode.BrighterScript;
|
|
65
66
|
}
|
|
66
67
|
this.isTypedef = this.extension === '.d.bs';
|
|
67
68
|
if (!this.isTypedef) {
|
|
@@ -79,21 +80,34 @@ class BrsFile {
|
|
|
79
80
|
this.diagnostics.push(...diagnostics);
|
|
80
81
|
}
|
|
81
82
|
/**
|
|
82
|
-
*
|
|
83
|
+
* files referenced by import statements
|
|
83
84
|
*/
|
|
84
|
-
get
|
|
85
|
-
|
|
85
|
+
get ownScriptImports() {
|
|
86
|
+
var _a, _b;
|
|
87
|
+
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
88
|
+
const result = (_b = (_a = this._parser) === null || _a === void 0 ? void 0 : _a.references['cache'].getOrAdd('BrsFile_ownScriptImports', () => {
|
|
89
|
+
var _a, _b, _c, _d;
|
|
90
|
+
const result = [];
|
|
91
|
+
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 : []) {
|
|
92
|
+
//register import statements
|
|
93
|
+
if ((0, reflection_1.isImportStatement)(statement) && statement.filePathToken) {
|
|
94
|
+
result.push({
|
|
95
|
+
filePathRange: statement.filePathToken.range,
|
|
96
|
+
pkgPath: util_1.util.getPkgPathFromTarget(this.pkgPath, statement.filePath),
|
|
97
|
+
sourceFile: this,
|
|
98
|
+
text: (_d = statement.filePathToken) === null || _d === void 0 ? void 0 : _d.text
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return result;
|
|
103
|
+
})) !== null && _b !== void 0 ? _b : [];
|
|
104
|
+
return result;
|
|
86
105
|
}
|
|
87
106
|
/**
|
|
88
|
-
*
|
|
89
|
-
* @param position
|
|
107
|
+
* The AST for this file
|
|
90
108
|
*/
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (util_1.util.rangeContains(token.range, position)) {
|
|
94
|
-
return token;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
109
|
+
get ast() {
|
|
110
|
+
return this.parser.ast;
|
|
97
111
|
}
|
|
98
112
|
get parser() {
|
|
99
113
|
if (!this._parser) {
|
|
@@ -119,9 +133,8 @@ class BrsFile {
|
|
|
119
133
|
* Also notify the dependency graph of our current dependencies so other dependents can be notified.
|
|
120
134
|
*/
|
|
121
135
|
attachDependencyGraph(dependencyGraph) {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
136
|
+
var _a;
|
|
137
|
+
(_a = this.unsubscribeFromDependencyGraph) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
125
138
|
//event that fires anytime a dependency changes
|
|
126
139
|
this.unsubscribeFromDependencyGraph = dependencyGraph.onchange(this.dependencyGraphKey, () => {
|
|
127
140
|
this.resolveTypedef();
|
|
@@ -143,11 +156,13 @@ class BrsFile {
|
|
|
143
156
|
this.diagnostics = [];
|
|
144
157
|
//if we have a typedef file, skip parsing this file
|
|
145
158
|
if (this.hasTypedef) {
|
|
159
|
+
//skip validation since the typedef is shadowing this file
|
|
160
|
+
this.isValidated = true;
|
|
146
161
|
return;
|
|
147
162
|
}
|
|
148
163
|
//tokenize the input file
|
|
149
164
|
let lexer = this.program.logger.time(Logger_1.LogLevel.debug, ['lexer.lex', chalk_1.default.green(this.srcPath)], () => {
|
|
150
|
-
return
|
|
165
|
+
return Lexer_1.Lexer.scan(fileContents, {
|
|
151
166
|
includeWhitespace: false
|
|
152
167
|
});
|
|
153
168
|
});
|
|
@@ -170,7 +185,7 @@ class BrsFile {
|
|
|
170
185
|
//if the preprocessor generated tokens, use them.
|
|
171
186
|
let tokens = preprocessor.processedTokens.length > 0 ? preprocessor.processedTokens : lexer.tokens;
|
|
172
187
|
this.program.logger.time(Logger_1.LogLevel.debug, ['parser.parse', chalk_1.default.green(this.srcPath)], () => {
|
|
173
|
-
this._parser =
|
|
188
|
+
this._parser = Parser_1.Parser.parse(tokens, {
|
|
174
189
|
mode: this.parseMode,
|
|
175
190
|
logger: this.program.logger
|
|
176
191
|
});
|
|
@@ -181,28 +196,31 @@ class BrsFile {
|
|
|
181
196
|
this.findCallables();
|
|
182
197
|
//find all places where a sub/function is being called
|
|
183
198
|
this.findFunctionCalls();
|
|
184
|
-
this.findAndValidateImportAndImportStatements();
|
|
185
199
|
//attach this file to every diagnostic
|
|
186
200
|
for (let diagnostic of this.diagnostics) {
|
|
187
201
|
diagnostic.file = this;
|
|
188
202
|
}
|
|
189
203
|
}
|
|
190
204
|
catch (e) {
|
|
191
|
-
this._parser = new
|
|
192
|
-
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(serialize_error_1.serializeError(e)))));
|
|
205
|
+
this._parser = new Parser_1.Parser();
|
|
206
|
+
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)))));
|
|
193
207
|
}
|
|
194
208
|
}
|
|
195
|
-
validate() {
|
|
196
|
-
|
|
197
|
-
|
|
209
|
+
validate() {
|
|
210
|
+
//only validate the file if it was actually parsed (skip files containing typedefs)
|
|
211
|
+
if (!this.hasTypedef) {
|
|
212
|
+
this.validateImportStatements();
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
validateImportStatements() {
|
|
198
216
|
let topOfFileIncludeStatements = [];
|
|
199
217
|
for (let stmt of this.ast.statements) {
|
|
200
218
|
//skip comments
|
|
201
|
-
if (reflection_1.isCommentStatement(stmt)) {
|
|
219
|
+
if ((0, reflection_1.isCommentStatement)(stmt)) {
|
|
202
220
|
continue;
|
|
203
221
|
}
|
|
204
222
|
//if we found a non-library statement, this statement is not at the top of the file
|
|
205
|
-
if (reflection_1.isLibraryStatement(stmt) || reflection_1.isImportStatement(stmt)) {
|
|
223
|
+
if ((0, reflection_1.isLibraryStatement)(stmt) || (0, reflection_1.isImportStatement)(stmt)) {
|
|
206
224
|
topOfFileIncludeStatements.push(stmt);
|
|
207
225
|
}
|
|
208
226
|
else {
|
|
@@ -215,22 +233,13 @@ class BrsFile {
|
|
|
215
233
|
...this._parser.references.importStatements
|
|
216
234
|
];
|
|
217
235
|
for (let result of statements) {
|
|
218
|
-
//register import statements
|
|
219
|
-
if (reflection_1.isImportStatement(result) && result.filePathToken) {
|
|
220
|
-
this.ownScriptImports.push({
|
|
221
|
-
filePathRange: result.filePathToken.range,
|
|
222
|
-
pkgPath: util_1.util.getPkgPathFromTarget(this.pkgPath, result.filePath),
|
|
223
|
-
sourceFile: this,
|
|
224
|
-
text: (_a = result.filePathToken) === null || _a === void 0 ? void 0 : _a.text
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
236
|
//if this statement is not one of the top-of-file statements,
|
|
228
237
|
//then add a diagnostic explaining that it is invalid
|
|
229
238
|
if (!topOfFileIncludeStatements.includes(result)) {
|
|
230
|
-
if (reflection_1.isLibraryStatement(result)) {
|
|
239
|
+
if ((0, reflection_1.isLibraryStatement)(result)) {
|
|
231
240
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile()), { range: result.range, file: this }));
|
|
232
241
|
}
|
|
233
|
-
else if (reflection_1.isImportStatement(result)) {
|
|
242
|
+
else if ((0, reflection_1.isImportStatement)(result)) {
|
|
234
243
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.importStatementMustBeDeclaredAtTopOfFile()), { range: result.range, file: this }));
|
|
235
244
|
}
|
|
236
245
|
}
|
|
@@ -281,7 +290,7 @@ class BrsFile {
|
|
|
281
290
|
const processor = new CommentFlagProcessor_1.CommentFlagProcessor(this, ['rem', `'`], DiagnosticMessages_1.diagnosticCodes, [DiagnosticMessages_1.DiagnosticCodeMap.unknownDiagnosticCode]);
|
|
282
291
|
this.commentFlags = [];
|
|
283
292
|
for (let token of tokens) {
|
|
284
|
-
if (token.kind ===
|
|
293
|
+
if (token.kind === TokenKind_1.TokenKind.Comment) {
|
|
285
294
|
processor.tryAdd(token.text, token.range);
|
|
286
295
|
}
|
|
287
296
|
}
|
|
@@ -291,31 +300,14 @@ class BrsFile {
|
|
|
291
300
|
findCallables() {
|
|
292
301
|
var _a;
|
|
293
302
|
for (let statement of (_a = this.parser.references.functionStatements) !== null && _a !== void 0 ? _a : []) {
|
|
294
|
-
let functionType =
|
|
303
|
+
let functionType = statement.func.getFunctionType();
|
|
295
304
|
functionType.setName(statement.name.text);
|
|
296
|
-
functionType.isSub = statement.func.functionType.text.toLowerCase() === 'sub';
|
|
297
|
-
if (functionType.isSub) {
|
|
298
|
-
functionType.returnType = new VoidType_1.VoidType();
|
|
299
|
-
}
|
|
300
|
-
//extract the parameters
|
|
301
|
-
let params = [];
|
|
302
|
-
for (let param of statement.func.parameters) {
|
|
303
|
-
let callableParam = {
|
|
304
|
-
name: param.name.text,
|
|
305
|
-
type: param.type,
|
|
306
|
-
isOptional: !!param.defaultValue,
|
|
307
|
-
isRestArgument: false
|
|
308
|
-
};
|
|
309
|
-
params.push(callableParam);
|
|
310
|
-
let isRequired = !param.defaultValue;
|
|
311
|
-
functionType.addParameter(callableParam.name, callableParam.type, isRequired);
|
|
312
|
-
}
|
|
313
305
|
this.callables.push({
|
|
314
306
|
isSub: statement.func.functionType.text.toLowerCase() === 'sub',
|
|
315
307
|
name: statement.name.text,
|
|
316
308
|
nameRange: statement.name.range,
|
|
317
309
|
file: this,
|
|
318
|
-
params: params,
|
|
310
|
+
params: functionType.params,
|
|
319
311
|
range: statement.func.range,
|
|
320
312
|
type: functionType,
|
|
321
313
|
getName: statement.getName.bind(statement),
|
|
@@ -325,21 +317,24 @@ class BrsFile {
|
|
|
325
317
|
}
|
|
326
318
|
}
|
|
327
319
|
findFunctionCalls() {
|
|
320
|
+
var _a;
|
|
328
321
|
this.functionCalls = [];
|
|
329
322
|
//for every function in the file
|
|
330
323
|
for (let func of this._parser.references.functionExpressions) {
|
|
331
324
|
//for all function calls in this function
|
|
332
325
|
for (let expression of func.callExpressions) {
|
|
333
326
|
if (
|
|
334
|
-
//filter out
|
|
335
|
-
expression.callee.
|
|
336
|
-
//filter out method calls on
|
|
337
|
-
expression.callee.
|
|
327
|
+
//filter out method calls on method calls for now (i.e. getSomething().getSomethingElse())
|
|
328
|
+
expression.callee.callee ||
|
|
329
|
+
//filter out method calls on regexp literals for now
|
|
330
|
+
(0, reflection_1.isRegexLiteralExpression)((_a = expression.callee) === null || _a === void 0 ? void 0 : _a.obj) ||
|
|
338
331
|
//filter out callees without a name (immediately-invoked function expressions)
|
|
339
332
|
!expression.callee.name) {
|
|
340
333
|
continue;
|
|
341
334
|
}
|
|
342
|
-
|
|
335
|
+
//Flag dotted function invocations (i.e. object.doSomething())
|
|
336
|
+
const dottedInvocation = expression.callee.obj;
|
|
337
|
+
let functionName = expression.callee.name;
|
|
343
338
|
//callee is the name of the function being called
|
|
344
339
|
let callee = expression.callee;
|
|
345
340
|
let columnIndexBegin = callee.range.start.character;
|
|
@@ -347,7 +342,7 @@ class BrsFile {
|
|
|
347
342
|
let args = [];
|
|
348
343
|
//TODO convert if stmts to use instanceof instead
|
|
349
344
|
for (let arg of expression.args) {
|
|
350
|
-
let
|
|
345
|
+
let inferredType = (0, Parser_1.getBscTypeFromExpression)(arg, func);
|
|
351
346
|
let argText = '';
|
|
352
347
|
// Get the text to display for the arg
|
|
353
348
|
if (arg.token) {
|
|
@@ -355,24 +350,28 @@ class BrsFile {
|
|
|
355
350
|
//is a function call being passed into argument
|
|
356
351
|
}
|
|
357
352
|
else if (arg.name) {
|
|
358
|
-
if (
|
|
353
|
+
if ((0, Token_1.isToken)(arg.name)) {
|
|
359
354
|
argText = arg.name.text;
|
|
360
355
|
}
|
|
361
356
|
}
|
|
362
357
|
else if (arg.value) {
|
|
363
358
|
/* istanbul ignore next: TODO figure out why value is undefined sometimes */
|
|
364
359
|
if (arg.value.value) {
|
|
365
|
-
|
|
360
|
+
if (arg.value.value.toString) {
|
|
361
|
+
argText = arg.value.value.toString();
|
|
362
|
+
}
|
|
366
363
|
}
|
|
367
364
|
//wrap the value in quotes because that's how it appears in the code
|
|
368
|
-
if (reflection_1.isStringType(
|
|
365
|
+
if (argText && (0, reflection_1.isStringType)(inferredType)) {
|
|
369
366
|
argText = '"' + argText + '"';
|
|
370
367
|
}
|
|
371
368
|
}
|
|
372
369
|
args.push({
|
|
373
370
|
range: arg.range,
|
|
374
|
-
type:
|
|
375
|
-
text: argText
|
|
371
|
+
type: inferredType,
|
|
372
|
+
text: argText,
|
|
373
|
+
expression: arg,
|
|
374
|
+
typeToken: undefined
|
|
376
375
|
});
|
|
377
376
|
}
|
|
378
377
|
let functionCall = {
|
|
@@ -381,8 +380,8 @@ class BrsFile {
|
|
|
381
380
|
file: this,
|
|
382
381
|
name: functionName,
|
|
383
382
|
nameRange: util_1.util.createRange(callee.range.start.line, columnIndexBegin, callee.range.start.line, columnIndexEnd),
|
|
384
|
-
|
|
385
|
-
|
|
383
|
+
args: args,
|
|
384
|
+
isDottedInvocation: dottedInvocation
|
|
386
385
|
};
|
|
387
386
|
this.functionCalls.push(functionCall);
|
|
388
387
|
}
|
|
@@ -408,10 +407,25 @@ class BrsFile {
|
|
|
408
407
|
}
|
|
409
408
|
}
|
|
410
409
|
}
|
|
410
|
+
/**
|
|
411
|
+
* Find the NamespaceStatement enclosing the given position
|
|
412
|
+
* @param position
|
|
413
|
+
* @param functionScopes
|
|
414
|
+
*/
|
|
415
|
+
getNamespaceStatementForPosition(position) {
|
|
416
|
+
if (position) {
|
|
417
|
+
for (const statement of this.parser.references.namespaceStatements) {
|
|
418
|
+
if (util_1.util.rangeContains(statement.range, position)) {
|
|
419
|
+
return statement;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
411
424
|
/**
|
|
412
425
|
* Get completions available at the given cursor. This aggregates all values from this file and the current scope.
|
|
413
426
|
*/
|
|
414
427
|
getCompletions(position, scope) {
|
|
428
|
+
var _a;
|
|
415
429
|
let result = [];
|
|
416
430
|
//a map of lower-case names of all added options
|
|
417
431
|
let names = {};
|
|
@@ -421,12 +435,12 @@ class BrsFile {
|
|
|
421
435
|
return this.program.getScriptImportCompletions(this.pkgPath, scriptImport);
|
|
422
436
|
}
|
|
423
437
|
//if cursor is within a comment, disable completions
|
|
424
|
-
let currentToken = this.getTokenAt(position);
|
|
438
|
+
let currentToken = this.parser.getTokenAt(position);
|
|
425
439
|
const tokenKind = currentToken === null || currentToken === void 0 ? void 0 : currentToken.kind;
|
|
426
|
-
if (tokenKind ===
|
|
440
|
+
if (tokenKind === TokenKind_1.TokenKind.Comment) {
|
|
427
441
|
return [];
|
|
428
442
|
}
|
|
429
|
-
else if (tokenKind ===
|
|
443
|
+
else if (tokenKind === TokenKind_1.TokenKind.StringLiteral || tokenKind === TokenKind_1.TokenKind.TemplateStringQuasi) {
|
|
430
444
|
const match = /^("?)(pkg|libpkg):/.exec(currentToken.text);
|
|
431
445
|
if (match) {
|
|
432
446
|
const [, openingQuote, fileProtocol] = match;
|
|
@@ -450,43 +464,56 @@ class BrsFile {
|
|
|
450
464
|
return [];
|
|
451
465
|
}
|
|
452
466
|
}
|
|
453
|
-
|
|
467
|
+
const namespaceCompletions = this.getNamespaceCompletions(currentToken, this.parseMode, scope);
|
|
454
468
|
if (namespaceCompletions.length > 0) {
|
|
455
|
-
return namespaceCompletions;
|
|
469
|
+
return [...namespaceCompletions];
|
|
470
|
+
}
|
|
471
|
+
const enumMemberCompletions = this.getEnumMemberStatementCompletions(currentToken, this.parseMode, scope);
|
|
472
|
+
if (enumMemberCompletions.length > 0) {
|
|
473
|
+
// no other completion is valid in this case
|
|
474
|
+
return enumMemberCompletions;
|
|
456
475
|
}
|
|
457
476
|
//determine if cursor is inside a function
|
|
458
477
|
let functionExpression = this.getFunctionExpressionAtPosition(position);
|
|
459
478
|
if (!functionExpression) {
|
|
460
479
|
//we aren't in any function scope, so return the keyword completions and namespaces
|
|
461
|
-
if (this.getTokenBefore(currentToken,
|
|
480
|
+
if (this.parser.getTokenBefore(currentToken, TokenKind_1.TokenKind.New)) {
|
|
462
481
|
// there's a new keyword, so only class types are viable here
|
|
463
|
-
return [...this.getGlobalClassStatementCompletions(currentToken, this.parseMode)];
|
|
482
|
+
return [...this.getGlobalClassStatementCompletions(currentToken, this.parseMode, scope)];
|
|
464
483
|
}
|
|
465
484
|
else {
|
|
466
|
-
return [
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
485
|
+
return [
|
|
486
|
+
...exports.KeywordCompletions,
|
|
487
|
+
...this.getGlobalClassStatementCompletions(currentToken, this.parseMode, scope),
|
|
488
|
+
...namespaceCompletions,
|
|
489
|
+
...this.getNonNamespacedEnumStatementCompletions(currentToken, this.parseMode, scope),
|
|
490
|
+
...this.getGlobalInterfaceStatementCompletions(currentToken, this.parseMode, scope)
|
|
491
|
+
];
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
const classNameCompletions = this.getGlobalClassStatementCompletions(currentToken, this.parseMode, scope);
|
|
495
|
+
const interfaceNameCompletions = this.getGlobalInterfaceStatementCompletions(currentToken, this.parseMode, scope);
|
|
496
|
+
const newToken = this.parser.getTokenBefore(currentToken, TokenKind_1.TokenKind.New);
|
|
471
497
|
if (newToken) {
|
|
472
|
-
//we are after a new keyword; so we can only be namespaces or classes at this point
|
|
498
|
+
//we are after a new keyword; so we can only be top-level namespaces or classes at this point
|
|
473
499
|
result.push(...classNameCompletions);
|
|
474
500
|
result.push(...namespaceCompletions);
|
|
475
501
|
return result;
|
|
476
502
|
}
|
|
477
|
-
if (this.tokenFollows(currentToken,
|
|
503
|
+
if (this.parser.tokenFollows(currentToken, TokenKind_1.TokenKind.Goto)) {
|
|
478
504
|
return this.getLabelCompletion(functionExpression);
|
|
479
505
|
}
|
|
480
|
-
if (this.isPositionNextToTokenKind(position,
|
|
481
|
-
if (namespaceCompletions.length > 0) {
|
|
482
|
-
//if we matched a namespace, after a dot, it can't be anything else but something from our namespace completions
|
|
483
|
-
return namespaceCompletions;
|
|
484
|
-
}
|
|
506
|
+
if (this.parser.isPositionNextToTokenKind(position, TokenKind_1.TokenKind.Dot)) {
|
|
485
507
|
const selfClassMemberCompletions = this.getClassMemberCompletions(position, currentToken, functionExpression, scope);
|
|
486
508
|
if (selfClassMemberCompletions.size > 0) {
|
|
487
509
|
return [...selfClassMemberCompletions.values()].filter((i) => i.label !== 'new');
|
|
488
510
|
}
|
|
489
|
-
|
|
511
|
+
const tokenLookup = this.getSymbolTypeFromToken(currentToken, functionExpression, scope);
|
|
512
|
+
if ((_a = tokenLookup.symbolContainer) === null || _a === void 0 ? void 0 : _a.memberTable) {
|
|
513
|
+
return this.getCompletionsFromSymbolTable(tokenLookup.symbolContainer.memberTable);
|
|
514
|
+
}
|
|
515
|
+
const foundClassLink = this.getClassFromTokenLookup(tokenLookup, scope);
|
|
516
|
+
if (!foundClassLink) {
|
|
490
517
|
//and anything from any class in scope to a non m class
|
|
491
518
|
let classMemberCompletions = scope.getAllClassMemberCompletions();
|
|
492
519
|
result.push(...classMemberCompletions.values());
|
|
@@ -501,6 +528,10 @@ class BrsFile {
|
|
|
501
528
|
result.push(...namespaceCompletions);
|
|
502
529
|
//include class names
|
|
503
530
|
result.push(...classNameCompletions);
|
|
531
|
+
//include interfaces
|
|
532
|
+
result.push(...interfaceNameCompletions);
|
|
533
|
+
//include enums
|
|
534
|
+
result.push(...this.getNonNamespacedEnumStatementCompletions(currentToken, this.parseMode, scope));
|
|
504
535
|
//include the global callables
|
|
505
536
|
result.push(...scope.getCallablesAsCompletions(this.parseMode));
|
|
506
537
|
//add `m` because that's always valid within a function
|
|
@@ -511,22 +542,24 @@ class BrsFile {
|
|
|
511
542
|
names.m = true;
|
|
512
543
|
result.push(...exports.KeywordCompletions);
|
|
513
544
|
//include local variables
|
|
514
|
-
for (let symbol of functionExpression.symbolTable.
|
|
545
|
+
for (let symbol of functionExpression.symbolTable.getOwnSymbols()) {
|
|
515
546
|
const symbolNameLower = symbol.name.toLowerCase();
|
|
516
547
|
//skip duplicate variable names
|
|
517
548
|
if (names[symbolNameLower]) {
|
|
518
549
|
continue;
|
|
519
550
|
}
|
|
520
551
|
names[symbolNameLower] = true;
|
|
552
|
+
// TODO TYPES (This may be a performance hit?)
|
|
553
|
+
// const foundType = getTypeFromContext(symbol.type, { scope: scope, file: this });
|
|
521
554
|
result.push({
|
|
522
555
|
//TODO does this work?
|
|
523
556
|
label: symbol.name,
|
|
524
|
-
//TODO find type for local vars
|
|
557
|
+
//TODO TYPES find type for local vars - SEE above
|
|
525
558
|
kind: vscode_languageserver_1.CompletionItemKind.Variable
|
|
526
|
-
// kind: isFunctionType(
|
|
559
|
+
// kind: isFunctionType(foundType) ? CompletionItemKind.Function : CompletionItemKind.Variable
|
|
527
560
|
});
|
|
528
561
|
}
|
|
529
|
-
if (this.parseMode ===
|
|
562
|
+
if (this.parseMode === Parser_1.ParseMode.BrighterScript) {
|
|
530
563
|
//include the first part of namespaces
|
|
531
564
|
let namespaces = scope.getAllNamespaceStatements();
|
|
532
565
|
for (let stmt of namespaces) {
|
|
@@ -545,6 +578,14 @@ class BrsFile {
|
|
|
545
578
|
}
|
|
546
579
|
return result;
|
|
547
580
|
}
|
|
581
|
+
getCompletionsFromSymbolTable(symbolTable) {
|
|
582
|
+
return symbolTable.getAllSymbols().map(bscType => {
|
|
583
|
+
return {
|
|
584
|
+
label: bscType.name,
|
|
585
|
+
kind: (0, reflection_1.isTypedFunctionType)(bscType.type) ? vscode_languageserver_1.CompletionItemKind.Method : vscode_languageserver_1.CompletionItemKind.Field
|
|
586
|
+
};
|
|
587
|
+
});
|
|
588
|
+
}
|
|
548
589
|
getLabelCompletion(func) {
|
|
549
590
|
return func.labelStatements.map(label => ({
|
|
550
591
|
label: label.tokens.identifier.text,
|
|
@@ -552,17 +593,17 @@ class BrsFile {
|
|
|
552
593
|
}));
|
|
553
594
|
}
|
|
554
595
|
getClassMemberCompletions(position, currentToken, functionExpression, scope) {
|
|
555
|
-
var _a, _b;
|
|
556
|
-
let classStatement = this.
|
|
596
|
+
var _a, _b, _c, _d;
|
|
597
|
+
let classStatement = this.getClassFromToken(currentToken, functionExpression, scope);
|
|
557
598
|
let results = new Map();
|
|
558
599
|
if (classStatement) {
|
|
559
|
-
let classes = scope.getClassHierarchy(classStatement.item.getName(
|
|
600
|
+
let classes = scope.getClassHierarchy(classStatement.item.getName(Parser_1.ParseMode.BrighterScript).toLowerCase());
|
|
560
601
|
for (let cs of classes) {
|
|
561
|
-
for (let member of [...(_a = cs === null || cs === void 0 ? void 0 : cs.item) === null || _a === void 0 ? void 0 : _a.fields, ...(
|
|
602
|
+
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 : []]) {
|
|
562
603
|
if (!results.has(member.name.text.toLowerCase())) {
|
|
563
604
|
results.set(member.name.text.toLowerCase(), {
|
|
564
605
|
label: member.name.text,
|
|
565
|
-
kind: reflection_1.isClassFieldStatement(member) ? vscode_languageserver_1.CompletionItemKind.Field : vscode_languageserver_1.CompletionItemKind.
|
|
606
|
+
kind: (0, reflection_1.isClassFieldStatement)(member) ? vscode_languageserver_1.CompletionItemKind.Field : vscode_languageserver_1.CompletionItemKind.Method
|
|
566
607
|
});
|
|
567
608
|
}
|
|
568
609
|
}
|
|
@@ -570,69 +611,392 @@ class BrsFile {
|
|
|
570
611
|
}
|
|
571
612
|
return results;
|
|
572
613
|
}
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
614
|
+
/**
|
|
615
|
+
* Gets the class (if any) of a given token based on the scope
|
|
616
|
+
* @param currentToken token in question
|
|
617
|
+
* @param functionExpression current functionExpression
|
|
618
|
+
* @param scope the current scope
|
|
619
|
+
* @returns A fileLink of the ClassStatement, if it is a class, otherwise undefined
|
|
620
|
+
*/
|
|
621
|
+
getClassFromToken(currentToken, functionExpression, scope) {
|
|
622
|
+
const tokenLookup = this.getSymbolTypeFromToken(currentToken, functionExpression, scope);
|
|
623
|
+
return this.getClassFromTokenLookup(tokenLookup, scope);
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* Gets the class (if any) of a given token based on the scope
|
|
627
|
+
* @param currentToken token in question
|
|
628
|
+
* @param functionExpression current functionExpression
|
|
629
|
+
* @param scope the current scope
|
|
630
|
+
* @returns A fileLink of the ClassStatement, if it is a class, otherwise undefined
|
|
631
|
+
*/
|
|
632
|
+
getClassFromTokenLookup(tokenLookup, scope) {
|
|
633
|
+
const currentClass = tokenLookup === null || tokenLookup === void 0 ? void 0 : tokenLookup.symbolContainer;
|
|
634
|
+
if ((0, reflection_1.isClassStatement)(currentClass)) {
|
|
635
|
+
return { item: currentClass, file: this };
|
|
577
636
|
}
|
|
578
|
-
if ((
|
|
579
|
-
|
|
637
|
+
else if ((0, reflection_1.isCustomType)(currentClass)) {
|
|
638
|
+
const foundClass = scope.getClass(currentClass.name);
|
|
639
|
+
if (foundClass) {
|
|
640
|
+
return { item: foundClass, file: this };
|
|
641
|
+
}
|
|
580
642
|
}
|
|
581
643
|
return undefined;
|
|
582
644
|
}
|
|
583
|
-
|
|
645
|
+
findNamespaceFromTokenChain(originalTokenChain, scope) {
|
|
646
|
+
let namespaceTokens = [];
|
|
647
|
+
let startsWithNamespace = '';
|
|
648
|
+
let namespaceContainer;
|
|
649
|
+
let tokenChain = [...originalTokenChain];
|
|
650
|
+
while (tokenChain[0] && tokenChain[0].usage === Parser_1.TokenUsage.Direct) {
|
|
651
|
+
const namespaceNameToCheck = `${startsWithNamespace}${startsWithNamespace.length > 0 ? '.' : ''}${tokenChain[0].token.text}`.toLowerCase();
|
|
652
|
+
const foundNamespace = scope.namespaceLookup.get(namespaceNameToCheck);
|
|
653
|
+
if (foundNamespace) {
|
|
654
|
+
namespaceContainer = foundNamespace;
|
|
655
|
+
namespaceTokens.push(tokenChain[0].token);
|
|
656
|
+
startsWithNamespace = namespaceTokens.map(token => token.text).join('.');
|
|
657
|
+
tokenChain.shift();
|
|
658
|
+
}
|
|
659
|
+
else {
|
|
660
|
+
break;
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
if (namespaceTokens.length > 0) {
|
|
664
|
+
namespaceContainer = scope.namespaceLookup.get(startsWithNamespace.toLowerCase());
|
|
665
|
+
}
|
|
666
|
+
return { namespaceContainer: namespaceContainer, tokenChain: tokenChain };
|
|
667
|
+
}
|
|
668
|
+
checkForSpecialClassSymbol(currentToken, scope, func) {
|
|
669
|
+
var _a;
|
|
670
|
+
const containingClass = this.parser.getContainingClass(currentToken);
|
|
671
|
+
let symbolType;
|
|
672
|
+
let currentClassRef;
|
|
673
|
+
const currentTokenLower = currentToken.text.toLowerCase();
|
|
674
|
+
const typeContext = { file: this, scope: scope, position: currentToken.range.start };
|
|
675
|
+
if (containingClass) {
|
|
676
|
+
// Special cases for a single token inside a class
|
|
677
|
+
let expandedText = '';
|
|
678
|
+
let useExpandedTextOnly = false;
|
|
679
|
+
if (containingClass.name === currentToken) {
|
|
680
|
+
symbolType = containingClass.getThisBscType();
|
|
681
|
+
expandedText = `class ${containingClass.getName(Parser_1.ParseMode.BrighterScript)}`;
|
|
682
|
+
useExpandedTextOnly = true;
|
|
683
|
+
currentClassRef = containingClass;
|
|
684
|
+
}
|
|
685
|
+
else if (currentTokenLower === 'm') {
|
|
686
|
+
symbolType = containingClass.getThisBscType();
|
|
687
|
+
expandedText = currentToken.text;
|
|
688
|
+
currentClassRef = containingClass;
|
|
689
|
+
}
|
|
690
|
+
else if (currentTokenLower === 'super') {
|
|
691
|
+
symbolType = (0, BscType_1.getTypeFromContext)(containingClass.symbolTable.getSymbolType(currentTokenLower, true, typeContext), typeContext);
|
|
692
|
+
if ((0, reflection_1.isTypedFunctionType)(symbolType)) {
|
|
693
|
+
currentClassRef = scope.getParentClass(containingClass);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
else if (((_a = func === null || func === void 0 ? void 0 : func.functionStatement) === null || _a === void 0 ? void 0 : _a.name) === currentToken) {
|
|
697
|
+
// check if this is a method declaration
|
|
698
|
+
currentClassRef = containingClass;
|
|
699
|
+
symbolType = containingClass === null || containingClass === void 0 ? void 0 : containingClass.memberTable.getSymbolType(currentTokenLower, true, { file: this, scope: scope });
|
|
700
|
+
expandedText = [containingClass.getName(Parser_1.ParseMode.BrighterScript), currentToken.text].join('.');
|
|
701
|
+
}
|
|
702
|
+
else if (!func) {
|
|
703
|
+
// check if this is a field declaration
|
|
704
|
+
currentClassRef = containingClass;
|
|
705
|
+
symbolType = containingClass === null || containingClass === void 0 ? void 0 : containingClass.memberTable.getSymbolType(currentTokenLower, true, { file: this, scope: scope });
|
|
706
|
+
expandedText = [containingClass.getName(Parser_1.ParseMode.BrighterScript), currentToken.text].join('.');
|
|
707
|
+
}
|
|
708
|
+
if (symbolType) {
|
|
709
|
+
return { type: symbolType, expandedTokenText: expandedText, symbolContainer: currentClassRef, useExpandedTextOnly: useExpandedTextOnly };
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
checkForSpecialCaseToken(nameSpacedTokenChain, functionExpression, scope) {
|
|
714
|
+
var _a;
|
|
715
|
+
const tokenChain = (_a = nameSpacedTokenChain.tokenChain) !== null && _a !== void 0 ? _a : [];
|
|
716
|
+
if (nameSpacedTokenChain.namespaceContainer && tokenChain.length === 0) {
|
|
717
|
+
//currentToken was part of a namespace
|
|
718
|
+
return {
|
|
719
|
+
type: null,
|
|
720
|
+
expandedTokenText: `namespace ${nameSpacedTokenChain.namespaceContainer.fullName}`,
|
|
721
|
+
useExpandedTextOnly: true
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
const specialCase = tokenChain.length === 1 ? this.checkForSpecialClassSymbol(tokenChain[0].token, scope, functionExpression) : null;
|
|
725
|
+
if (specialCase) {
|
|
726
|
+
return specialCase;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
/**
|
|
730
|
+
* Checks previous tokens for the start of a symbol chain (eg. m.property.subProperty.method())
|
|
731
|
+
* @param currentToken The token to check
|
|
732
|
+
* @param functionExpression The current function context
|
|
733
|
+
* @param scope use this scope for finding class maps
|
|
734
|
+
* @returns the BscType, expanded text (e.g <Class.field>) and classStatement (if available) for the token
|
|
735
|
+
*/
|
|
736
|
+
getSymbolTypeFromToken(currentToken, functionExpression, scope) {
|
|
737
|
+
var _a, _b, _c, _d, _e;
|
|
738
|
+
if (!scope || !currentToken) {
|
|
739
|
+
return undefined;
|
|
740
|
+
}
|
|
741
|
+
const cachedSymbolData = scope.symbolCache.get(currentToken);
|
|
742
|
+
if (cachedSymbolData) {
|
|
743
|
+
return cachedSymbolData;
|
|
744
|
+
}
|
|
745
|
+
const tokenChainResponse = this.parser.getTokenChain(currentToken);
|
|
746
|
+
if (tokenChainResponse.includesUnknowableTokenType) {
|
|
747
|
+
const symbolData = { type: new DynamicType_1.DynamicType(), expandedTokenText: currentToken.text };
|
|
748
|
+
scope.symbolCache.set(currentToken, symbolData);
|
|
749
|
+
return symbolData;
|
|
750
|
+
}
|
|
751
|
+
const nameSpacedTokenChain = this.findNamespaceFromTokenChain(tokenChainResponse.chain, scope);
|
|
752
|
+
const specialCase = this.checkForSpecialCaseToken(nameSpacedTokenChain, functionExpression, scope);
|
|
753
|
+
if (specialCase) {
|
|
754
|
+
scope.symbolCache.set(currentToken, specialCase);
|
|
755
|
+
return specialCase;
|
|
756
|
+
}
|
|
757
|
+
const tokenChain = nameSpacedTokenChain.tokenChain;
|
|
758
|
+
let symbolContainer = this.parser.getContainingAA(currentToken) || this.parser.getContainingClass(currentToken);
|
|
759
|
+
let currentSymbolTable = (_b = (_a = nameSpacedTokenChain.namespaceContainer) === null || _a === void 0 ? void 0 : _a.symbolTable) !== null && _b !== void 0 ? _b : functionExpression === null || functionExpression === void 0 ? void 0 : functionExpression.symbolTable;
|
|
760
|
+
let tokenFoundCount = 0;
|
|
761
|
+
let symbolTypeBeforeReference;
|
|
762
|
+
let symbolType;
|
|
763
|
+
let tokenText = [];
|
|
764
|
+
let justReturnDynamic = false;
|
|
765
|
+
const typeContext = { file: this, scope: scope, position: (_c = tokenChain[0]) === null || _c === void 0 ? void 0 : _c.token.range.start };
|
|
766
|
+
for (const tokenChainMember of tokenChain) {
|
|
767
|
+
const token = tokenChainMember === null || tokenChainMember === void 0 ? void 0 : tokenChainMember.token;
|
|
768
|
+
const tokenUsage = tokenChainMember === null || tokenChainMember === void 0 ? void 0 : tokenChainMember.usage;
|
|
769
|
+
const tokenLowerText = token.text.toLowerCase();
|
|
770
|
+
if (tokenLowerText === 'super' && (0, reflection_1.isClassStatement)(symbolContainer) && tokenFoundCount === 0) {
|
|
771
|
+
/// Special cases for first item in chain inside a class
|
|
772
|
+
symbolContainer = scope === null || scope === void 0 ? void 0 : scope.getParentClass(symbolContainer);
|
|
773
|
+
currentSymbolTable = (_d = symbolContainer) === null || _d === void 0 ? void 0 : _d.memberTable;
|
|
774
|
+
if (symbolContainer && currentSymbolTable) {
|
|
775
|
+
tokenText.push(symbolContainer.getName(Parser_1.ParseMode.BrighterScript));
|
|
776
|
+
tokenFoundCount++;
|
|
777
|
+
continue;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
if (!currentSymbolTable) {
|
|
781
|
+
// uh oh... no symbol table to continue to check
|
|
782
|
+
break;
|
|
783
|
+
}
|
|
784
|
+
symbolType = currentSymbolTable.getSymbolType(tokenLowerText, true, typeContext);
|
|
785
|
+
if (tokenFoundCount === 0 && !symbolType) {
|
|
786
|
+
//check for global callable
|
|
787
|
+
symbolType = (_e = scope.getGlobalCallableByName(tokenLowerText)) === null || _e === void 0 ? void 0 : _e.type;
|
|
788
|
+
}
|
|
789
|
+
if (symbolType) {
|
|
790
|
+
// found this symbol, and it's valid. increase found counter
|
|
791
|
+
tokenFoundCount++;
|
|
792
|
+
}
|
|
793
|
+
symbolTypeBeforeReference = symbolType;
|
|
794
|
+
if ((0, reflection_1.isTypedFunctionType)(symbolType)) {
|
|
795
|
+
// this is a function, and it is in the start or middle of the chain
|
|
796
|
+
// the next symbol to check will be the return value of this function
|
|
797
|
+
symbolType = (0, BscType_1.getTypeFromContext)(symbolType.returnType, typeContext);
|
|
798
|
+
if (tokenFoundCount < tokenChain.length) {
|
|
799
|
+
// We still have more tokens, but remember the last known reference
|
|
800
|
+
symbolTypeBeforeReference = symbolType;
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
if ((0, reflection_1.isArrayType)(symbolType) && tokenUsage === Parser_1.TokenUsage.ArrayReference) {
|
|
804
|
+
symbolType = (0, BscType_1.getTypeFromContext)(symbolType.getDefaultType(typeContext), typeContext);
|
|
805
|
+
}
|
|
806
|
+
if (symbolType === null || symbolType === void 0 ? void 0 : symbolType.memberTable) {
|
|
807
|
+
if ((0, reflection_1.isCustomType)(symbolType) || (0, reflection_1.isInterfaceType)(symbolType)) {
|
|
808
|
+
// we're currently looking at a customType or interface, that has it's own symbol table
|
|
809
|
+
// use the name of the custom type
|
|
810
|
+
// TODO TYPES: get proper parent name for methods/fields defined in super classes
|
|
811
|
+
tokenText.push(tokenChain.length === 1 ? token.text : symbolType.name);
|
|
812
|
+
}
|
|
813
|
+
else {
|
|
814
|
+
justReturnDynamic = true;
|
|
815
|
+
tokenText.push(token.text);
|
|
816
|
+
}
|
|
817
|
+
symbolContainer = symbolType;
|
|
818
|
+
currentSymbolTable = symbolContainer === null || symbolContainer === void 0 ? void 0 : symbolContainer.memberTable;
|
|
819
|
+
}
|
|
820
|
+
else if ((0, reflection_1.isObjectType)(symbolType) || (0, reflection_1.isArrayType)(symbolType) || (0, reflection_1.isDynamicType)(symbolType)) {
|
|
821
|
+
// this is an object that has no member table
|
|
822
|
+
// this could happen if a parameter is marked as object
|
|
823
|
+
// assume all fields are dynamic
|
|
824
|
+
symbolContainer = undefined;
|
|
825
|
+
tokenText.push(token.text);
|
|
826
|
+
justReturnDynamic = true;
|
|
827
|
+
break;
|
|
828
|
+
}
|
|
829
|
+
else {
|
|
830
|
+
// No further symbol tables were found
|
|
831
|
+
symbolContainer = undefined;
|
|
832
|
+
tokenText.push(token.text);
|
|
833
|
+
break;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
if (tokenText.length > 2) {
|
|
837
|
+
// TokenText is used for hovers. We only need the last two tokens for a hover
|
|
838
|
+
// So in a long chain (e.g. klass.getData()[0].anotherKlass.property), the hover
|
|
839
|
+
// for the last token should just be "AnotherKlass.property", not the whole chain
|
|
840
|
+
tokenText = tokenText.slice(-2);
|
|
841
|
+
}
|
|
842
|
+
let expandedTokenText = tokenText.join('.');
|
|
843
|
+
let backUpReturnType;
|
|
844
|
+
if (tokenFoundCount === tokenChain.length) {
|
|
845
|
+
// did we complete the chain? if so, we have a valid token at the end
|
|
846
|
+
const symbolData = { type: symbolTypeBeforeReference, expandedTokenText: tokenText.join('.'), symbolContainer: symbolContainer };
|
|
847
|
+
scope.symbolCache.set(currentToken, symbolData);
|
|
848
|
+
return symbolData;
|
|
849
|
+
}
|
|
850
|
+
if ((0, reflection_1.isDynamicType)(symbolTypeBeforeReference) || (0, reflection_1.isArrayType)(symbolTypeBeforeReference) || justReturnDynamic) {
|
|
851
|
+
// last type in chain is dynamic... so currentToken could be anything.
|
|
852
|
+
backUpReturnType = new DynamicType_1.DynamicType();
|
|
853
|
+
expandedTokenText = currentToken.text;
|
|
854
|
+
}
|
|
855
|
+
else if ((0, reflection_1.isPrimitiveType)(symbolTypeBeforeReference)) {
|
|
856
|
+
// last type in chain is dynamic... so currentToken could be anything.
|
|
857
|
+
backUpReturnType = new DynamicType_1.DynamicType();
|
|
858
|
+
expandedTokenText = currentToken.text;
|
|
859
|
+
}
|
|
860
|
+
else if (tokenChain.length === 1) {
|
|
861
|
+
// variable that has not been assigned
|
|
862
|
+
expandedTokenText = currentToken.text;
|
|
863
|
+
backUpReturnType = new UninitializedType_1.UninitializedType();
|
|
864
|
+
}
|
|
865
|
+
else if (tokenFoundCount === tokenChain.length - 1) {
|
|
866
|
+
// member field that is not known
|
|
867
|
+
if (symbolContainer) {
|
|
868
|
+
backUpReturnType = new InvalidType_1.InvalidType();
|
|
869
|
+
}
|
|
870
|
+
else {
|
|
871
|
+
// TODO TYPES: once we have stricter object/node member type checking, we could say this is invalid, but until then, call it dynamic
|
|
872
|
+
backUpReturnType = new DynamicType_1.DynamicType();
|
|
873
|
+
expandedTokenText = currentToken.text;
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
const symbolData = { type: backUpReturnType, expandedTokenText: expandedTokenText };
|
|
877
|
+
scope.symbolCache.set(currentToken, symbolData);
|
|
878
|
+
return symbolData;
|
|
879
|
+
}
|
|
880
|
+
getGlobalClassStatementCompletions(currentToken, parseMode, scope) {
|
|
584
881
|
var _a;
|
|
585
|
-
if (parseMode ===
|
|
882
|
+
if (parseMode === Parser_1.ParseMode.BrightScript) {
|
|
586
883
|
return [];
|
|
587
884
|
}
|
|
588
885
|
let results = new Map();
|
|
589
|
-
let completionName = (_a = this.getPartialVariableName(currentToken, [
|
|
886
|
+
let completionName = (_a = this.getPartialVariableName(currentToken, [TokenKind_1.TokenKind.New])) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
590
887
|
if (completionName === null || completionName === void 0 ? void 0 : completionName.includes('.')) {
|
|
591
888
|
return [];
|
|
592
889
|
}
|
|
593
|
-
let
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
890
|
+
let classMap = scope.getClassMap();
|
|
891
|
+
// let viableKeys = [...classMap.keys()].filter((k) => k.startsWith(completionName));
|
|
892
|
+
for (const key of [...classMap.keys()]) {
|
|
893
|
+
let cs = classMap.get(key).item;
|
|
894
|
+
if (!results.has(cs.name.text)) {
|
|
895
|
+
results.set(cs.name.text, {
|
|
896
|
+
label: cs.name.text,
|
|
897
|
+
kind: vscode_languageserver_1.CompletionItemKind.Class
|
|
898
|
+
});
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
return [...results.values()];
|
|
902
|
+
}
|
|
903
|
+
getNonNamespacedEnumStatementCompletions(currentToken, parseMode, scope) {
|
|
904
|
+
var _a, _b;
|
|
905
|
+
if (parseMode !== Parser_1.ParseMode.BrighterScript) {
|
|
906
|
+
return [];
|
|
907
|
+
}
|
|
908
|
+
const containingNamespaceName = ((_b = this.getNamespaceStatementForPosition((_a = currentToken === null || currentToken === void 0 ? void 0 : currentToken.range) === null || _a === void 0 ? void 0 : _a.start)) === null || _b === void 0 ? void 0 : _b.name) + '.';
|
|
909
|
+
const results = new Map();
|
|
910
|
+
const enumMap = scope.getEnumMap();
|
|
911
|
+
for (const key of [...enumMap.keys()]) {
|
|
912
|
+
const enumStatement = enumMap.get(key).item;
|
|
913
|
+
const fullName = enumStatement.fullName;
|
|
914
|
+
//if the enum is contained within our own namespace, or if it's a non-namespaced enum
|
|
915
|
+
if (fullName.startsWith(containingNamespaceName) || !fullName.includes('.')) {
|
|
916
|
+
results.set(fullName, {
|
|
917
|
+
label: enumStatement.name,
|
|
918
|
+
kind: vscode_languageserver_1.CompletionItemKind.Enum
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
return [...results.values()];
|
|
923
|
+
}
|
|
924
|
+
getEnumMemberStatementCompletions(currentToken, parseMode, scope) {
|
|
925
|
+
var _a, _b, _c, _d, _e;
|
|
926
|
+
if (parseMode === Parser_1.ParseMode.BrightScript || !currentToken) {
|
|
927
|
+
return [];
|
|
928
|
+
}
|
|
929
|
+
const results = new Map();
|
|
930
|
+
const completionName = (_a = this.getPartialVariableName(currentToken)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
931
|
+
//if we don't have a completion name, or if there's no period in the name, then this is not to the right of an enum name
|
|
932
|
+
if (!completionName || !completionName.includes('.')) {
|
|
933
|
+
return [];
|
|
934
|
+
}
|
|
935
|
+
const enumNameLower = (_b = completionName === null || completionName === void 0 ? void 0 : completionName.split(/\.(\w+)?$/)[0]) === null || _b === void 0 ? void 0 : _b.toLowerCase();
|
|
936
|
+
const namespaceNameLower = (_c = this.getNamespaceStatementForPosition(currentToken.range.end)) === null || _c === void 0 ? void 0 : _c.name.toLowerCase();
|
|
937
|
+
const enumMap = scope.getEnumMap();
|
|
938
|
+
//get the enum statement with this name (check without namespace prefix first, then with inferred namespace prefix next)
|
|
939
|
+
const enumStatement = (_e = ((_d = enumMap.get(enumNameLower)) !== null && _d !== void 0 ? _d : enumMap.get(namespaceNameLower + '.' + enumNameLower))) === null || _e === void 0 ? void 0 : _e.item;
|
|
940
|
+
//if we found an enum with this name
|
|
941
|
+
if (enumStatement) {
|
|
942
|
+
for (const member of enumStatement.getMembers()) {
|
|
943
|
+
const name = enumStatement.fullName + '.' + member.name;
|
|
944
|
+
const nameLower = name.toLowerCase();
|
|
945
|
+
results.set(nameLower, {
|
|
946
|
+
label: member.name,
|
|
947
|
+
kind: vscode_languageserver_1.CompletionItemKind.EnumMember
|
|
948
|
+
});
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
return [...results.values()];
|
|
952
|
+
}
|
|
953
|
+
getGlobalInterfaceStatementCompletions(currentToken, parseMode, scope) {
|
|
954
|
+
var _a;
|
|
955
|
+
if (parseMode === Parser_1.ParseMode.BrightScript) {
|
|
956
|
+
return [];
|
|
957
|
+
}
|
|
958
|
+
let results = new Map();
|
|
959
|
+
let completionName = (_a = this.getPartialVariableName(currentToken, [TokenKind_1.TokenKind.New])) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
960
|
+
if (completionName === null || completionName === void 0 ? void 0 : completionName.includes('.')) {
|
|
961
|
+
return [];
|
|
962
|
+
}
|
|
963
|
+
let ifaceMap = scope.getInterfaceMap();
|
|
964
|
+
for (const key of [...ifaceMap.keys()]) {
|
|
965
|
+
let cs = ifaceMap.get(key).item;
|
|
966
|
+
if (!results.has(cs.name.text)) {
|
|
967
|
+
results.set(cs.name.text, {
|
|
968
|
+
label: cs.name.text,
|
|
969
|
+
kind: vscode_languageserver_1.CompletionItemKind.Interface
|
|
970
|
+
});
|
|
605
971
|
}
|
|
606
972
|
}
|
|
607
973
|
return [...results.values()];
|
|
608
974
|
}
|
|
609
975
|
getNamespaceCompletions(currentToken, parseMode, scope) {
|
|
610
976
|
//BrightScript does not support namespaces, so return an empty list in that case
|
|
611
|
-
if (parseMode ===
|
|
977
|
+
if (parseMode === Parser_1.ParseMode.BrightScript) {
|
|
612
978
|
return [];
|
|
613
979
|
}
|
|
614
|
-
|
|
615
|
-
if
|
|
980
|
+
const completionName = this.getPartialVariableName(currentToken, [TokenKind_1.TokenKind.New]);
|
|
981
|
+
//if we don't have a completion name, or if there's no period in the name, then this is not a namespaced variable
|
|
982
|
+
if (!completionName || !completionName.includes('.')) {
|
|
616
983
|
return [];
|
|
617
984
|
}
|
|
618
985
|
//remove any trailing identifer and then any trailing dot, to give us the
|
|
619
986
|
//name of its immediate parent namespace
|
|
620
|
-
let closestParentNamespaceName = completionName.replace(/\.([a-z0-9_]*)?$/gi, '');
|
|
621
|
-
let newToken = this.getTokenBefore(currentToken,
|
|
622
|
-
let namespaceLookup = scope.namespaceLookup;
|
|
987
|
+
let closestParentNamespaceName = completionName.replace(/\.([a-z0-9_]*)?$/gi, '').toLowerCase();
|
|
988
|
+
let newToken = this.parser.getTokenBefore(currentToken, TokenKind_1.TokenKind.New);
|
|
623
989
|
let result = new Map();
|
|
624
|
-
for (let
|
|
625
|
-
let namespace = namespaceLookup[key.toLowerCase()];
|
|
990
|
+
for (let [, namespace] of scope.namespaceLookup) {
|
|
626
991
|
//completionName = "NameA."
|
|
627
992
|
//completionName = "NameA.Na
|
|
628
993
|
//NameA
|
|
629
994
|
//NameA.NameB
|
|
630
995
|
//NameA.NameB.NameC
|
|
631
|
-
if (namespace.fullName.toLowerCase() === closestParentNamespaceName
|
|
996
|
+
if (namespace.fullName.toLowerCase() === closestParentNamespaceName) {
|
|
632
997
|
//add all of this namespace's immediate child namespaces, bearing in mind if we are after a new keyword
|
|
633
|
-
for (let
|
|
634
|
-
|
|
635
|
-
if (!newToken || ns.statements.find((s) => reflection_1.isClassStatement(s))) {
|
|
998
|
+
for (let [, ns] of namespace.namespaces) {
|
|
999
|
+
if (!newToken || ns.statements.find((s) => (0, reflection_1.isClassStatement)(s))) {
|
|
636
1000
|
if (!result.has(ns.lastPartName)) {
|
|
637
1001
|
result.set(ns.lastPartName, {
|
|
638
1002
|
label: ns.lastPartName,
|
|
@@ -643,21 +1007,23 @@ class BrsFile {
|
|
|
643
1007
|
}
|
|
644
1008
|
//add function and class statement completions
|
|
645
1009
|
for (let stmt of namespace.statements) {
|
|
646
|
-
if (reflection_1.isClassStatement(stmt)) {
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
});
|
|
652
|
-
}
|
|
1010
|
+
if ((0, reflection_1.isClassStatement)(stmt)) {
|
|
1011
|
+
result.set(stmt.name.text, {
|
|
1012
|
+
label: stmt.name.text,
|
|
1013
|
+
kind: vscode_languageserver_1.CompletionItemKind.Class
|
|
1014
|
+
});
|
|
653
1015
|
}
|
|
654
|
-
else if (reflection_1.isFunctionStatement(stmt) && !newToken) {
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
1016
|
+
else if ((0, reflection_1.isFunctionStatement)(stmt) && !newToken) {
|
|
1017
|
+
result.set(stmt.name.text, {
|
|
1018
|
+
label: stmt.name.text,
|
|
1019
|
+
kind: vscode_languageserver_1.CompletionItemKind.Function
|
|
1020
|
+
});
|
|
1021
|
+
}
|
|
1022
|
+
else if ((0, reflection_1.isEnumStatement)(stmt) && !newToken) {
|
|
1023
|
+
result.set(stmt.name, {
|
|
1024
|
+
label: stmt.name,
|
|
1025
|
+
kind: vscode_languageserver_1.CompletionItemKind.Enum
|
|
1026
|
+
});
|
|
661
1027
|
}
|
|
662
1028
|
}
|
|
663
1029
|
}
|
|
@@ -670,18 +1036,18 @@ class BrsFile {
|
|
|
670
1036
|
return undefined;
|
|
671
1037
|
}
|
|
672
1038
|
let location;
|
|
673
|
-
const nameParts = this.getPartialVariableName(token, [
|
|
1039
|
+
const nameParts = this.getPartialVariableName(token, [TokenKind_1.TokenKind.New]).split('.');
|
|
674
1040
|
const endName = nameParts[nameParts.length - 1].toLowerCase();
|
|
675
1041
|
const namespaceName = nameParts.slice(0, -1).join('.').toLowerCase();
|
|
676
1042
|
const statementHandler = (statement) => {
|
|
677
|
-
if (!location && statement.getName(
|
|
1043
|
+
if (!location && statement.getName(Parser_1.ParseMode.BrighterScript).toLowerCase() === namespaceName) {
|
|
678
1044
|
const namespaceItemStatementHandler = (statement) => {
|
|
679
1045
|
if (!location && statement.name.text.toLowerCase() === endName) {
|
|
680
1046
|
const uri = util_1.util.pathToUri(file.srcPath);
|
|
681
1047
|
location = vscode_languageserver_1.Location.create(uri, statement.range);
|
|
682
1048
|
}
|
|
683
1049
|
};
|
|
684
|
-
file.parser.ast.walk(visitors_1.createVisitor({
|
|
1050
|
+
file.parser.ast.walk((0, visitors_1.createVisitor)({
|
|
685
1051
|
ClassStatement: namespaceItemStatementHandler,
|
|
686
1052
|
FunctionStatement: namespaceItemStatementHandler
|
|
687
1053
|
}), {
|
|
@@ -689,7 +1055,7 @@ class BrsFile {
|
|
|
689
1055
|
});
|
|
690
1056
|
}
|
|
691
1057
|
};
|
|
692
|
-
file.parser.ast.walk(visitors_1.createVisitor({
|
|
1058
|
+
file.parser.ast.walk((0, visitors_1.createVisitor)({
|
|
693
1059
|
NamespaceStatement: statementHandler
|
|
694
1060
|
}), {
|
|
695
1061
|
walkMode: visitors_1.WalkMode.visitStatements
|
|
@@ -700,7 +1066,7 @@ class BrsFile {
|
|
|
700
1066
|
* Given a current token, walk
|
|
701
1067
|
*/
|
|
702
1068
|
getPartialVariableName(currentToken, excludeTokens = null) {
|
|
703
|
-
let identifierAndDotKinds = [
|
|
1069
|
+
let identifierAndDotKinds = [TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedLocalIdentifiers, TokenKind_1.TokenKind.Dot];
|
|
704
1070
|
//consume tokens backwards until we find something other than a dot or an identifier
|
|
705
1071
|
let tokens = [];
|
|
706
1072
|
const parser = this.parser;
|
|
@@ -721,79 +1087,21 @@ class BrsFile {
|
|
|
721
1087
|
return undefined;
|
|
722
1088
|
}
|
|
723
1089
|
}
|
|
724
|
-
isPositionNextToTokenKind(position, tokenKind) {
|
|
725
|
-
const closestToken = this.getClosestToken(position);
|
|
726
|
-
const previousToken = this.getPreviousToken(closestToken);
|
|
727
|
-
const previousTokenKind = previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind;
|
|
728
|
-
//next to matched token
|
|
729
|
-
if (!closestToken || closestToken.kind === lexer_1.TokenKind.Eof) {
|
|
730
|
-
return false;
|
|
731
|
-
}
|
|
732
|
-
else if (closestToken.kind === tokenKind) {
|
|
733
|
-
return true;
|
|
734
|
-
}
|
|
735
|
-
else if (closestToken.kind === lexer_1.TokenKind.Newline || previousTokenKind === lexer_1.TokenKind.Newline) {
|
|
736
|
-
return false;
|
|
737
|
-
//next to an identifier, which is next to token kind
|
|
738
|
-
}
|
|
739
|
-
else if (closestToken.kind === lexer_1.TokenKind.Identifier && previousTokenKind === tokenKind) {
|
|
740
|
-
return true;
|
|
741
|
-
}
|
|
742
|
-
else {
|
|
743
|
-
return false;
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
getTokenBefore(currentToken, tokenKind) {
|
|
747
|
-
const index = this.parser.tokens.indexOf(currentToken);
|
|
748
|
-
for (let i = index - 1; i >= 0; i--) {
|
|
749
|
-
currentToken = this.parser.tokens[i];
|
|
750
|
-
if (currentToken.kind === lexer_1.TokenKind.Newline) {
|
|
751
|
-
break;
|
|
752
|
-
}
|
|
753
|
-
else if (currentToken.kind === tokenKind) {
|
|
754
|
-
return currentToken;
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
return undefined;
|
|
758
|
-
}
|
|
759
|
-
tokenFollows(currentToken, tokenKind) {
|
|
760
|
-
const index = this.parser.tokens.indexOf(currentToken);
|
|
761
|
-
if (index > 0) {
|
|
762
|
-
return this.parser.tokens[index - 1].kind === tokenKind;
|
|
763
|
-
}
|
|
764
|
-
return false;
|
|
765
|
-
}
|
|
766
|
-
getTokensUntil(currentToken, tokenKind, direction = -1) {
|
|
767
|
-
let tokens = [];
|
|
768
|
-
for (let i = this.parser.tokens.indexOf(currentToken); direction === -1 ? i >= 0 : i === this.parser.tokens.length; i += direction) {
|
|
769
|
-
currentToken = this.parser.tokens[i];
|
|
770
|
-
if (currentToken.kind === lexer_1.TokenKind.Newline || currentToken.kind === tokenKind) {
|
|
771
|
-
break;
|
|
772
|
-
}
|
|
773
|
-
tokens.push(currentToken);
|
|
774
|
-
}
|
|
775
|
-
return tokens;
|
|
776
|
-
}
|
|
777
|
-
getPreviousToken(token) {
|
|
778
|
-
const parser = this.parser;
|
|
779
|
-
let idx = parser.tokens.indexOf(token);
|
|
780
|
-
return parser.tokens[idx - 1];
|
|
781
|
-
}
|
|
782
1090
|
/**
|
|
783
1091
|
* Find the first scope that has a namespace with this name.
|
|
784
1092
|
* Returns false if no namespace was found with that name
|
|
785
1093
|
*/
|
|
786
1094
|
calleeStartsWithNamespace(callee) {
|
|
787
1095
|
let left = callee;
|
|
788
|
-
while (reflection_1.isDottedGetExpression(left)) {
|
|
1096
|
+
while ((0, reflection_1.isDottedGetExpression)(left)) {
|
|
789
1097
|
left = left.obj;
|
|
790
1098
|
}
|
|
791
|
-
if (reflection_1.isVariableExpression(left)) {
|
|
1099
|
+
if ((0, reflection_1.isVariableExpression)(left)) {
|
|
792
1100
|
let lowerName = left.name.text.toLowerCase();
|
|
793
1101
|
//find the first scope that contains this namespace
|
|
794
1102
|
let scopes = this.program.getScopesForFile(this);
|
|
795
1103
|
for (let scope of scopes) {
|
|
796
|
-
if (scope.namespaceLookup
|
|
1104
|
+
if (scope.namespaceLookup.has(lowerName)) {
|
|
797
1105
|
return true;
|
|
798
1106
|
}
|
|
799
1107
|
}
|
|
@@ -806,12 +1114,12 @@ class BrsFile {
|
|
|
806
1114
|
calleeIsKnownNamespaceFunction(callee, namespaceName) {
|
|
807
1115
|
var _a, _b;
|
|
808
1116
|
//if we have a variable and a namespace
|
|
809
|
-
if (reflection_1.isVariableExpression(callee) && namespaceName) {
|
|
1117
|
+
if ((0, reflection_1.isVariableExpression)(callee) && namespaceName) {
|
|
810
1118
|
let lowerCalleeName = (_b = (_a = callee === null || callee === void 0 ? void 0 : callee.name) === null || _a === void 0 ? void 0 : _a.text) === null || _b === void 0 ? void 0 : _b.toLowerCase();
|
|
811
1119
|
if (lowerCalleeName) {
|
|
812
1120
|
let scopes = this.program.getScopesForFile(this);
|
|
813
1121
|
for (let scope of scopes) {
|
|
814
|
-
let namespace = scope.namespaceLookup
|
|
1122
|
+
let namespace = scope.namespaceLookup.get(namespaceName.toLowerCase());
|
|
815
1123
|
if (namespace.functionStatements[lowerCalleeName]) {
|
|
816
1124
|
return true;
|
|
817
1125
|
}
|
|
@@ -820,28 +1128,6 @@ class BrsFile {
|
|
|
820
1128
|
}
|
|
821
1129
|
return false;
|
|
822
1130
|
}
|
|
823
|
-
/**
|
|
824
|
-
* Get the token closest to the position. if no token is found, the previous token is returned
|
|
825
|
-
* @param position
|
|
826
|
-
* @param tokens
|
|
827
|
-
*/
|
|
828
|
-
getClosestToken(position) {
|
|
829
|
-
let tokens = this.parser.tokens;
|
|
830
|
-
for (let i = 0; i < tokens.length; i++) {
|
|
831
|
-
let token = tokens[i];
|
|
832
|
-
if (util_1.util.rangeContains(token.range, position)) {
|
|
833
|
-
return token;
|
|
834
|
-
}
|
|
835
|
-
//if the position less than this token range, then this position touches no token,
|
|
836
|
-
if (util_1.util.positionIsGreaterThanRange(position, token.range) === false) {
|
|
837
|
-
let t = tokens[i - 1];
|
|
838
|
-
//return the token or the first token
|
|
839
|
-
return t ? t : tokens[0];
|
|
840
|
-
}
|
|
841
|
-
}
|
|
842
|
-
//return the last token
|
|
843
|
-
return tokens[tokens.length - 1];
|
|
844
|
-
}
|
|
845
1131
|
/**
|
|
846
1132
|
* Builds a list of document symbols for this file. Used by LanguageServer's onDocumentSymbol functionality
|
|
847
1133
|
*/
|
|
@@ -881,16 +1167,16 @@ class BrsFile {
|
|
|
881
1167
|
getDocumentSymbol(statement) {
|
|
882
1168
|
let symbolKind;
|
|
883
1169
|
const children = [];
|
|
884
|
-
if (reflection_1.isFunctionStatement(statement)) {
|
|
1170
|
+
if ((0, reflection_1.isFunctionStatement)(statement)) {
|
|
885
1171
|
symbolKind = vscode_languageserver_1.SymbolKind.Function;
|
|
886
1172
|
}
|
|
887
|
-
else if (reflection_1.isClassMethodStatement(statement)) {
|
|
1173
|
+
else if ((0, reflection_1.isClassMethodStatement)(statement)) {
|
|
888
1174
|
symbolKind = vscode_languageserver_1.SymbolKind.Method;
|
|
889
1175
|
}
|
|
890
|
-
else if (reflection_1.isClassFieldStatement(statement)) {
|
|
1176
|
+
else if ((0, reflection_1.isClassFieldStatement)(statement)) {
|
|
891
1177
|
symbolKind = vscode_languageserver_1.SymbolKind.Field;
|
|
892
1178
|
}
|
|
893
|
-
else if (reflection_1.isNamespaceStatement(statement)) {
|
|
1179
|
+
else if ((0, reflection_1.isNamespaceStatement)(statement)) {
|
|
894
1180
|
symbolKind = vscode_languageserver_1.SymbolKind.Namespace;
|
|
895
1181
|
for (const childStatement of statement.body.statements) {
|
|
896
1182
|
const symbol = this.getDocumentSymbol(childStatement);
|
|
@@ -899,7 +1185,7 @@ class BrsFile {
|
|
|
899
1185
|
}
|
|
900
1186
|
}
|
|
901
1187
|
}
|
|
902
|
-
else if (reflection_1.isClassStatement(statement)) {
|
|
1188
|
+
else if ((0, reflection_1.isClassStatement)(statement)) {
|
|
903
1189
|
symbolKind = vscode_languageserver_1.SymbolKind.Class;
|
|
904
1190
|
for (const childStatement of statement.body) {
|
|
905
1191
|
const symbol = this.getDocumentSymbol(childStatement);
|
|
@@ -911,7 +1197,7 @@ class BrsFile {
|
|
|
911
1197
|
else {
|
|
912
1198
|
return;
|
|
913
1199
|
}
|
|
914
|
-
const name = reflection_1.isClassFieldStatement(statement) ? statement.name.text : statement.getName(
|
|
1200
|
+
const name = (0, reflection_1.isClassFieldStatement)(statement) ? statement.name.text : statement.getName(Parser_1.ParseMode.BrighterScript);
|
|
915
1201
|
return vscode_languageserver_1.DocumentSymbol.create(name, '', symbolKind, statement.range, statement.range, children);
|
|
916
1202
|
}
|
|
917
1203
|
/**
|
|
@@ -920,13 +1206,13 @@ class BrsFile {
|
|
|
920
1206
|
generateWorkspaceSymbols(statement, containerStatement) {
|
|
921
1207
|
let symbolKind;
|
|
922
1208
|
const symbols = [];
|
|
923
|
-
if (reflection_1.isFunctionStatement(statement)) {
|
|
1209
|
+
if ((0, reflection_1.isFunctionStatement)(statement)) {
|
|
924
1210
|
symbolKind = vscode_languageserver_1.SymbolKind.Function;
|
|
925
1211
|
}
|
|
926
|
-
else if (reflection_1.isClassMethodStatement(statement)) {
|
|
1212
|
+
else if ((0, reflection_1.isClassMethodStatement)(statement)) {
|
|
927
1213
|
symbolKind = vscode_languageserver_1.SymbolKind.Method;
|
|
928
1214
|
}
|
|
929
|
-
else if (reflection_1.isNamespaceStatement(statement)) {
|
|
1215
|
+
else if ((0, reflection_1.isNamespaceStatement)(statement)) {
|
|
930
1216
|
symbolKind = vscode_languageserver_1.SymbolKind.Namespace;
|
|
931
1217
|
for (const childStatement of statement.body.statements) {
|
|
932
1218
|
for (const symbol of this.generateWorkspaceSymbols(childStatement, statement)) {
|
|
@@ -934,7 +1220,7 @@ class BrsFile {
|
|
|
934
1220
|
}
|
|
935
1221
|
}
|
|
936
1222
|
}
|
|
937
|
-
else if (reflection_1.isClassStatement(statement)) {
|
|
1223
|
+
else if ((0, reflection_1.isClassStatement)(statement)) {
|
|
938
1224
|
symbolKind = vscode_languageserver_1.SymbolKind.Class;
|
|
939
1225
|
for (const childStatement of statement.body) {
|
|
940
1226
|
for (const symbol of this.generateWorkspaceSymbols(childStatement, statement)) {
|
|
@@ -945,9 +1231,9 @@ class BrsFile {
|
|
|
945
1231
|
else {
|
|
946
1232
|
return symbols;
|
|
947
1233
|
}
|
|
948
|
-
const name = statement.getName(
|
|
1234
|
+
const name = statement.getName(Parser_1.ParseMode.BrighterScript);
|
|
949
1235
|
const uri = util_1.util.pathToUri(this.srcPath);
|
|
950
|
-
const symbol = vscode_languageserver_1.SymbolInformation.create(name, symbolKind, statement.range, uri, containerStatement === null || containerStatement === void 0 ? void 0 : containerStatement.getName(
|
|
1236
|
+
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));
|
|
951
1237
|
symbols.push(symbol);
|
|
952
1238
|
return symbols;
|
|
953
1239
|
}
|
|
@@ -958,19 +1244,19 @@ class BrsFile {
|
|
|
958
1244
|
getDefinition(position) {
|
|
959
1245
|
let results = [];
|
|
960
1246
|
//get the token at the position
|
|
961
|
-
const token = this.getTokenAt(position);
|
|
1247
|
+
const token = this.parser.getTokenAt(position);
|
|
962
1248
|
// 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
|
|
963
1249
|
let definitionTokenTypes = [
|
|
964
|
-
|
|
965
|
-
|
|
1250
|
+
TokenKind_1.TokenKind.Identifier,
|
|
1251
|
+
TokenKind_1.TokenKind.StringLiteral
|
|
966
1252
|
];
|
|
967
1253
|
//throw out invalid tokens and the wrong kind of tokens
|
|
968
1254
|
if (!token || !definitionTokenTypes.includes(token.kind)) {
|
|
969
1255
|
return results;
|
|
970
1256
|
}
|
|
971
1257
|
let textToSearchFor = token.text.toLowerCase();
|
|
972
|
-
const previousToken = this.getTokenAt({ line: token.range.start.line, character: token.range.start.character });
|
|
973
|
-
if ((previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind) ===
|
|
1258
|
+
const previousToken = this.parser.getTokenAt({ line: token.range.start.line, character: token.range.start.character });
|
|
1259
|
+
if ((previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind) === TokenKind_1.TokenKind.Callfunc) {
|
|
974
1260
|
for (const scope of this.program.getScopes()) {
|
|
975
1261
|
//to only get functions defined in interface methods
|
|
976
1262
|
const callable = scope.getAllCallables().find((c) => c.callable.name.toLowerCase() === textToSearchFor); // eslint-disable-line @typescript-eslint/no-loop-func
|
|
@@ -980,7 +1266,7 @@ class BrsFile {
|
|
|
980
1266
|
}
|
|
981
1267
|
return results;
|
|
982
1268
|
}
|
|
983
|
-
let classToken = this.getTokenBefore(token,
|
|
1269
|
+
let classToken = this.parser.getTokenBefore(token, TokenKind_1.TokenKind.Class);
|
|
984
1270
|
if (classToken) {
|
|
985
1271
|
let cs = this.parser.references.classStatements.find((cs) => cs.classKeyword.range === classToken.range);
|
|
986
1272
|
if (cs === null || cs === void 0 ? void 0 : cs.parentClassName) {
|
|
@@ -992,7 +1278,7 @@ class BrsFile {
|
|
|
992
1278
|
}
|
|
993
1279
|
return results;
|
|
994
1280
|
}
|
|
995
|
-
if (token.kind ===
|
|
1281
|
+
if (token.kind === TokenKind_1.TokenKind.StringLiteral) {
|
|
996
1282
|
// We need to strip off the quotes but only if present
|
|
997
1283
|
const startIndex = textToSearchFor.startsWith('"') ? 1 : 0;
|
|
998
1284
|
let endIndex = textToSearchFor.length;
|
|
@@ -1002,20 +1288,22 @@ class BrsFile {
|
|
|
1002
1288
|
textToSearchFor = textToSearchFor.substring(startIndex, endIndex);
|
|
1003
1289
|
}
|
|
1004
1290
|
const func = this.getFunctionExpressionAtPosition(position);
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
results.push(vscode_languageserver_1.Location.create(uri, symbol.range));
|
|
1012
|
-
}
|
|
1013
|
-
}
|
|
1014
|
-
if (this.tokenFollows(token, lexer_1.TokenKind.Goto)) {
|
|
1015
|
-
for (const label of func.labelStatements) {
|
|
1016
|
-
if (label.tokens.identifier.text.toLocaleLowerCase() === textToSearchFor) {
|
|
1291
|
+
if (func) {
|
|
1292
|
+
//look through local variables first
|
|
1293
|
+
//find any variable with this name
|
|
1294
|
+
for (const symbol of func.symbolTable.getOwnSymbols()) {
|
|
1295
|
+
//we found a variable declaration with this token text
|
|
1296
|
+
if (symbol.name.toLowerCase() === textToSearchFor) {
|
|
1017
1297
|
const uri = util_1.util.pathToUri(this.srcPath);
|
|
1018
|
-
results.push(vscode_languageserver_1.Location.create(uri,
|
|
1298
|
+
results.push(vscode_languageserver_1.Location.create(uri, symbol.range));
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
if (this.parser.tokenFollows(token, TokenKind_1.TokenKind.Goto)) {
|
|
1302
|
+
for (const label of func.labelStatements) {
|
|
1303
|
+
if (label.tokens.identifier.text.toLocaleLowerCase() === textToSearchFor) {
|
|
1304
|
+
const uri = util_1.util.pathToUri(this.srcPath);
|
|
1305
|
+
results.push(vscode_languageserver_1.Location.create(uri, label.tokens.identifier.range));
|
|
1306
|
+
}
|
|
1019
1307
|
}
|
|
1020
1308
|
}
|
|
1021
1309
|
}
|
|
@@ -1023,11 +1311,11 @@ class BrsFile {
|
|
|
1023
1311
|
//look through all files in scope for matches
|
|
1024
1312
|
for (const scope of this.program.getScopesForFile(this)) {
|
|
1025
1313
|
for (const file of scope.getAllFiles()) {
|
|
1026
|
-
if (reflection_1.isXmlFile(file) || filesSearched.has(file)) {
|
|
1314
|
+
if ((0, reflection_1.isXmlFile)(file) || filesSearched.has(file)) {
|
|
1027
1315
|
continue;
|
|
1028
1316
|
}
|
|
1029
1317
|
filesSearched.add(file);
|
|
1030
|
-
if ((previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind) ===
|
|
1318
|
+
if ((previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind) === TokenKind_1.TokenKind.Dot && file.parseMode === Parser_1.ParseMode.BrighterScript) {
|
|
1031
1319
|
results.push(...this.getClassMemberDefinitions(textToSearchFor, file));
|
|
1032
1320
|
const namespaceDefinition = this.getNamespaceDefinitions(token, file);
|
|
1033
1321
|
if (namespaceDefinition) {
|
|
@@ -1040,7 +1328,7 @@ class BrsFile {
|
|
|
1040
1328
|
results.push(vscode_languageserver_1.Location.create(uri, statement.range));
|
|
1041
1329
|
}
|
|
1042
1330
|
};
|
|
1043
|
-
file.parser.ast.walk(visitors_1.createVisitor({
|
|
1331
|
+
file.parser.ast.walk((0, visitors_1.createVisitor)({
|
|
1044
1332
|
FunctionStatement: statementHandler
|
|
1045
1333
|
}), {
|
|
1046
1334
|
walkMode: visitors_1.WalkMode.visitStatements
|
|
@@ -1062,7 +1350,7 @@ class BrsFile {
|
|
|
1062
1350
|
results.push(vscode_languageserver_1.Location.create(util_1.util.pathToUri(file.srcPath), statement.range));
|
|
1063
1351
|
}
|
|
1064
1352
|
};
|
|
1065
|
-
file.parser.ast.walk(visitors_1.createVisitor({
|
|
1353
|
+
file.parser.ast.walk((0, visitors_1.createVisitor)({
|
|
1066
1354
|
ClassMethodStatement: statementHandler,
|
|
1067
1355
|
ClassFieldStatement: fieldStatementHandler
|
|
1068
1356
|
}), {
|
|
@@ -1071,15 +1359,16 @@ class BrsFile {
|
|
|
1071
1359
|
return results;
|
|
1072
1360
|
}
|
|
1073
1361
|
getHover(position) {
|
|
1074
|
-
var _a;
|
|
1362
|
+
var _a, _b, _c;
|
|
1363
|
+
const fence = (code) => util_1.util.mdFence(code, 'brightscript');
|
|
1075
1364
|
//get the token at the position
|
|
1076
|
-
let token = this.getTokenAt(position);
|
|
1365
|
+
let token = this.parser.getTokenAt(position);
|
|
1077
1366
|
let hoverTokenTypes = [
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1367
|
+
TokenKind_1.TokenKind.Identifier,
|
|
1368
|
+
TokenKind_1.TokenKind.Function,
|
|
1369
|
+
TokenKind_1.TokenKind.EndFunction,
|
|
1370
|
+
TokenKind_1.TokenKind.Sub,
|
|
1371
|
+
TokenKind_1.TokenKind.EndSub
|
|
1083
1372
|
];
|
|
1084
1373
|
//throw out invalid tokens and the wrong kind of tokens
|
|
1085
1374
|
if (!token || !hoverTokenTypes.includes(token.kind)) {
|
|
@@ -1089,63 +1378,114 @@ class BrsFile {
|
|
|
1089
1378
|
//look through local variables first
|
|
1090
1379
|
{
|
|
1091
1380
|
const func = this.getFunctionExpressionAtPosition(position);
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1381
|
+
if (func) {
|
|
1382
|
+
// this identifier could possibly be a class field, so no function expression is available
|
|
1383
|
+
for (const labelStatement of (_a = func === null || func === void 0 ? void 0 : func.labelStatements) !== null && _a !== void 0 ? _a : []) {
|
|
1384
|
+
if (labelStatement.tokens.identifier.text.toLocaleLowerCase() === lowerTokenText) {
|
|
1385
|
+
return {
|
|
1386
|
+
range: token.range,
|
|
1387
|
+
contents: `${labelStatement.tokens.identifier.text}: label`
|
|
1388
|
+
};
|
|
1389
|
+
}
|
|
1098
1390
|
}
|
|
1099
1391
|
}
|
|
1100
|
-
const typeTexts =
|
|
1101
|
-
|
|
1392
|
+
const typeTexts = new Set();
|
|
1393
|
+
const fileScopes = this.program.getScopesForFile(this).sort((a, b) => { var _a; return (_a = a.dependencyGraphKey) === null || _a === void 0 ? void 0 : _a.localeCompare(b.dependencyGraphKey); });
|
|
1394
|
+
const callables = [];
|
|
1395
|
+
for (const scope of fileScopes) {
|
|
1102
1396
|
scope.linkSymbolTable();
|
|
1103
|
-
|
|
1104
|
-
|
|
1397
|
+
const typeContext = { file: this, scope: scope, position: position };
|
|
1398
|
+
const typeTextPair = this.getSymbolTypeFromToken(token, func, scope);
|
|
1399
|
+
if (typeTextPair) {
|
|
1105
1400
|
let scopeTypeText = '';
|
|
1106
|
-
if (reflection_1.
|
|
1107
|
-
scopeTypeText = type.toString();
|
|
1401
|
+
if ((0, reflection_1.isTypedFunctionType)(typeTextPair.type)) {
|
|
1402
|
+
scopeTypeText = (_b = typeTextPair.type) === null || _b === void 0 ? void 0 : _b.toString(typeContext);
|
|
1403
|
+
//keep unique references to the callables for this function
|
|
1404
|
+
if (!typeTexts.has(scopeTypeText)) {
|
|
1405
|
+
callables.push(scope.getCallableByName(lowerTokenText));
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
else if (typeTextPair.useExpandedTextOnly) {
|
|
1409
|
+
scopeTypeText = typeTextPair.expandedTokenText;
|
|
1108
1410
|
}
|
|
1109
1411
|
else {
|
|
1110
|
-
scopeTypeText = `${
|
|
1412
|
+
scopeTypeText = `${typeTextPair.expandedTokenText} as ${(_c = typeTextPair.type) === null || _c === void 0 ? void 0 : _c.toString(typeContext)}`;
|
|
1111
1413
|
}
|
|
1112
|
-
if (
|
|
1113
|
-
typeTexts.
|
|
1414
|
+
if (scopeTypeText) {
|
|
1415
|
+
typeTexts.add(scopeTypeText);
|
|
1114
1416
|
}
|
|
1115
1417
|
}
|
|
1116
1418
|
scope.unlinkSymbolTable();
|
|
1117
1419
|
}
|
|
1118
|
-
|
|
1119
|
-
|
|
1420
|
+
if (callables.length === typeTexts.size) {
|
|
1421
|
+
//this is a function in all scopes, so build the function hover
|
|
1422
|
+
return {
|
|
1423
|
+
range: token.range,
|
|
1424
|
+
contents: this.getCallableDocumentation([...typeTexts], callables)
|
|
1425
|
+
};
|
|
1426
|
+
}
|
|
1427
|
+
else if ((typeTexts === null || typeTexts === void 0 ? void 0 : typeTexts.size) > 0) {
|
|
1428
|
+
const typeText = [...typeTexts].join(' | ');
|
|
1120
1429
|
return {
|
|
1121
1430
|
range: token.range,
|
|
1122
|
-
contents: typeText
|
|
1431
|
+
contents: fence(typeText)
|
|
1123
1432
|
};
|
|
1124
1433
|
}
|
|
1125
1434
|
}
|
|
1126
|
-
//look through all callables in relevant scopes
|
|
1127
|
-
{
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1435
|
+
// //look through all callables in relevant scopes
|
|
1436
|
+
// {
|
|
1437
|
+
// let scopes = this.program.getScopesForFile(this);
|
|
1438
|
+
// for (let scope of scopes) {
|
|
1439
|
+
// let callable = scope.getCallableByName(lowerTokenText);
|
|
1440
|
+
// if (callable) {
|
|
1441
|
+
// return {
|
|
1442
|
+
// range: token.range,
|
|
1443
|
+
// contents: this.getCallableDocumentation(callables)
|
|
1444
|
+
// };
|
|
1445
|
+
// }
|
|
1446
|
+
// }
|
|
1447
|
+
// }
|
|
1448
|
+
}
|
|
1449
|
+
/**
|
|
1450
|
+
* Build a hover documentation for a callable.
|
|
1451
|
+
*/
|
|
1452
|
+
getCallableDocumentation(typeTexts, callables) {
|
|
1453
|
+
var _a;
|
|
1454
|
+
const callable = callables[0];
|
|
1455
|
+
const typeText = typeTexts[0];
|
|
1456
|
+
const comments = [];
|
|
1457
|
+
const tokens = callable === null || callable === void 0 ? void 0 : callable.file.parser.tokens;
|
|
1458
|
+
const idx = tokens === null || tokens === void 0 ? void 0 : tokens.indexOf((_a = callable.functionStatement) === null || _a === void 0 ? void 0 : _a.func.functionType);
|
|
1459
|
+
for (let i = idx - 1; i >= 0; i--) {
|
|
1460
|
+
const token = tokens[i];
|
|
1461
|
+
//skip whitespace and newline chars
|
|
1462
|
+
if (token.kind === TokenKind_1.TokenKind.Comment) {
|
|
1463
|
+
comments.push(token);
|
|
1464
|
+
}
|
|
1465
|
+
else if (token.kind === TokenKind_1.TokenKind.Newline || token.kind === TokenKind_1.TokenKind.Whitespace) {
|
|
1466
|
+
//skip these tokens
|
|
1467
|
+
continue;
|
|
1468
|
+
//any other token means there are no more comments
|
|
1469
|
+
}
|
|
1470
|
+
else {
|
|
1471
|
+
break;
|
|
1137
1472
|
}
|
|
1138
1473
|
}
|
|
1474
|
+
//message indicating if there are variations. example: (+3 variations) if there are 4 unique function signatures
|
|
1475
|
+
const multiText = callables.length > 1 ? ` (+${callables.length - 1} variations)` : '';
|
|
1476
|
+
let result = util_1.util.mdFence(typeText + multiText, 'brightscript');
|
|
1477
|
+
if (comments.length > 0) {
|
|
1478
|
+
result += '\n***\n' + comments.reverse().map(x => x.text.replace(/^('|rem)/i, '')).join('\n');
|
|
1479
|
+
}
|
|
1480
|
+
return result;
|
|
1139
1481
|
}
|
|
1140
1482
|
getSignatureHelpForNamespaceMethods(callableName, dottedGetText, scope) {
|
|
1141
1483
|
var _a;
|
|
1142
1484
|
if (!dottedGetText) {
|
|
1143
1485
|
return [];
|
|
1144
1486
|
}
|
|
1145
|
-
let namespaceLookup = scope.namespaceLookup;
|
|
1146
1487
|
let resultsMap = new Map();
|
|
1147
|
-
for (let
|
|
1148
|
-
let namespace = namespaceLookup[key.toLowerCase()];
|
|
1488
|
+
for (let [, namespace] of scope.namespaceLookup) {
|
|
1149
1489
|
//completionName = "NameA."
|
|
1150
1490
|
//completionName = "NameA.Na
|
|
1151
1491
|
//NameA
|
|
@@ -1154,7 +1494,7 @@ class BrsFile {
|
|
|
1154
1494
|
if (namespace.fullName.toLowerCase() === dottedGetText.toLowerCase()) {
|
|
1155
1495
|
//add function and class statement completions
|
|
1156
1496
|
for (let stmt of namespace.statements) {
|
|
1157
|
-
if (reflection_1.isFunctionStatement(stmt) && stmt.name.text.toLowerCase() === callableName.toLowerCase()) {
|
|
1497
|
+
if ((0, reflection_1.isFunctionStatement)(stmt) && stmt.name.text.toLowerCase() === callableName.toLowerCase()) {
|
|
1158
1498
|
const result = (_a = namespace.file) === null || _a === void 0 ? void 0 : _a.getSignatureHelpForStatement(stmt);
|
|
1159
1499
|
if (!resultsMap.has(result.key)) {
|
|
1160
1500
|
resultsMap.set(result.key, result);
|
|
@@ -1166,16 +1506,16 @@ class BrsFile {
|
|
|
1166
1506
|
return [...resultsMap.values()];
|
|
1167
1507
|
}
|
|
1168
1508
|
getSignatureHelpForStatement(statement) {
|
|
1169
|
-
if (!reflection_1.isFunctionStatement(statement) && !reflection_1.isClassMethodStatement(statement)) {
|
|
1509
|
+
if (!(0, reflection_1.isFunctionStatement)(statement) && !(0, reflection_1.isClassMethodStatement)(statement)) {
|
|
1170
1510
|
return undefined;
|
|
1171
1511
|
}
|
|
1172
1512
|
const func = statement.func;
|
|
1173
1513
|
const funcStartPosition = func.range.start;
|
|
1174
1514
|
// Get function comments in reverse order
|
|
1175
|
-
let currentToken = this.getTokenAt(funcStartPosition);
|
|
1515
|
+
let currentToken = this.parser.getTokenAt(funcStartPosition);
|
|
1176
1516
|
let functionComments = [];
|
|
1177
1517
|
while (currentToken) {
|
|
1178
|
-
currentToken = this.getPreviousToken(currentToken);
|
|
1518
|
+
currentToken = this.parser.getPreviousToken(currentToken);
|
|
1179
1519
|
if (!currentToken) {
|
|
1180
1520
|
break;
|
|
1181
1521
|
}
|
|
@@ -1185,12 +1525,12 @@ class BrsFile {
|
|
|
1185
1525
|
}
|
|
1186
1526
|
}
|
|
1187
1527
|
const kind = currentToken.kind;
|
|
1188
|
-
if (kind ===
|
|
1528
|
+
if (kind === TokenKind_1.TokenKind.Comment) {
|
|
1189
1529
|
// Strip off common leading characters to make it easier to read
|
|
1190
1530
|
const commentText = currentToken.text.replace(/^[' *\/]+/, '');
|
|
1191
1531
|
functionComments.unshift(commentText);
|
|
1192
1532
|
}
|
|
1193
|
-
else if (kind ===
|
|
1533
|
+
else if (kind === TokenKind_1.TokenKind.Newline) {
|
|
1194
1534
|
if (functionComments.length === 0) {
|
|
1195
1535
|
continue;
|
|
1196
1536
|
}
|
|
@@ -1212,14 +1552,15 @@ class BrsFile {
|
|
|
1212
1552
|
params.push(vscode_languageserver_1.ParameterInformation.create(param.name.text));
|
|
1213
1553
|
key += param.name.text;
|
|
1214
1554
|
}
|
|
1215
|
-
const label = util_1.util.getTextForRange(lines,
|
|
1555
|
+
const label = util_1.util.getTextForRange(lines, func.functionDeclarationRange).trim();
|
|
1216
1556
|
const signature = vscode_languageserver_1.SignatureInformation.create(label, documentation, ...params);
|
|
1217
1557
|
const index = 1;
|
|
1218
1558
|
return { key: key, signature: signature, index: index };
|
|
1219
1559
|
}
|
|
1220
1560
|
getClassMethod(classStatement, name, walkParents = true) {
|
|
1221
1561
|
var _a;
|
|
1222
|
-
//TODO - would like to write this with
|
|
1562
|
+
//TODO - would like to write this with getClassHierarchy; but got stuck on working out the scopes to use... :(
|
|
1563
|
+
//TODO types - this could be solved with symbolTable?
|
|
1223
1564
|
let statement;
|
|
1224
1565
|
const statementHandler = (e) => {
|
|
1225
1566
|
if (!statement && e.name.text.toLowerCase() === name.toLowerCase()) {
|
|
@@ -1227,7 +1568,7 @@ class BrsFile {
|
|
|
1227
1568
|
}
|
|
1228
1569
|
};
|
|
1229
1570
|
while (classStatement) {
|
|
1230
|
-
classStatement.walk(visitors_1.createVisitor({
|
|
1571
|
+
classStatement.walk((0, visitors_1.createVisitor)({
|
|
1231
1572
|
ClassMethodStatement: statementHandler
|
|
1232
1573
|
}), {
|
|
1233
1574
|
walkMode: visitors_1.WalkMode.visitStatements
|
|
@@ -1249,24 +1590,24 @@ class BrsFile {
|
|
|
1249
1590
|
const classConstructor = this.getClassMethod(classStatement, 'new');
|
|
1250
1591
|
let sigHelp = classConstructor ? this.getSignatureHelpForStatement(classConstructor) : undefined;
|
|
1251
1592
|
if (sigHelp) {
|
|
1252
|
-
sigHelp.key = classStatement.getName(
|
|
1593
|
+
sigHelp.key = classStatement.getName(Parser_1.ParseMode.BrighterScript);
|
|
1253
1594
|
sigHelp.signature.label = sigHelp.signature.label.replace(/(function|sub) new/, sigHelp.key);
|
|
1254
1595
|
}
|
|
1255
1596
|
return sigHelp;
|
|
1256
1597
|
}
|
|
1257
1598
|
getReferences(position) {
|
|
1258
|
-
const callSiteToken = this.getTokenAt(position);
|
|
1599
|
+
const callSiteToken = this.parser.getTokenAt(position);
|
|
1259
1600
|
let locations = [];
|
|
1260
1601
|
const searchFor = callSiteToken.text.toLowerCase();
|
|
1261
1602
|
const scopes = this.program.getScopesForFile(this);
|
|
1262
1603
|
for (const scope of scopes) {
|
|
1263
1604
|
const processedFiles = new Set();
|
|
1264
1605
|
for (const file of scope.getAllFiles()) {
|
|
1265
|
-
if (reflection_1.isXmlFile(file) || processedFiles.has(file)) {
|
|
1606
|
+
if ((0, reflection_1.isXmlFile)(file) || processedFiles.has(file)) {
|
|
1266
1607
|
continue;
|
|
1267
1608
|
}
|
|
1268
1609
|
processedFiles.add(file);
|
|
1269
|
-
file.ast.walk(visitors_1.createVisitor({
|
|
1610
|
+
file.ast.walk((0, visitors_1.createVisitor)({
|
|
1270
1611
|
VariableExpression: (e) => {
|
|
1271
1612
|
if (e.name.text.toLowerCase() === searchFor) {
|
|
1272
1613
|
locations.push(vscode_languageserver_1.Location.create(util_1.util.pathToUri(file.srcPath), e.range));
|
|
@@ -1317,8 +1658,15 @@ class BrsFile {
|
|
|
1317
1658
|
return programNode.toString();
|
|
1318
1659
|
}
|
|
1319
1660
|
dispose() {
|
|
1320
|
-
var _a;
|
|
1661
|
+
var _a, _b;
|
|
1321
1662
|
(_a = this._parser) === null || _a === void 0 ? void 0 : _a.dispose();
|
|
1663
|
+
//unsubscribe from any DependencyGraph subscriptions
|
|
1664
|
+
(_b = this.unsubscribeFromDependencyGraph) === null || _b === void 0 ? void 0 : _b.call(this);
|
|
1665
|
+
//deleting these properties result in lower memory usage (garbage collection is magic!)
|
|
1666
|
+
delete this.fileContents;
|
|
1667
|
+
delete this._parser;
|
|
1668
|
+
delete this.callables;
|
|
1669
|
+
delete this.functionCalls;
|
|
1322
1670
|
}
|
|
1323
1671
|
}
|
|
1324
1672
|
exports.BrsFile = BrsFile;
|
|
@@ -1326,7 +1674,7 @@ exports.BrsFile = BrsFile;
|
|
|
1326
1674
|
* List of completions for all valid keywords/reserved words.
|
|
1327
1675
|
* Build this list once because it won't change for the lifetime of this process
|
|
1328
1676
|
*/
|
|
1329
|
-
exports.KeywordCompletions = Object.keys(
|
|
1677
|
+
exports.KeywordCompletions = Object.keys(TokenKind_1.Keywords)
|
|
1330
1678
|
//remove any keywords with whitespace
|
|
1331
1679
|
.filter(x => !x.includes(' '))
|
|
1332
1680
|
//create completions
|