brighterscript 0.41.2 → 1.0.0-alpha.12

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.
Files changed (170) hide show
  1. package/CHANGELOG.md +112 -0
  2. package/README.md +2 -2
  3. package/dist/DiagnosticCollection.js +2 -2
  4. package/dist/DiagnosticCollection.js.map +1 -1
  5. package/dist/DiagnosticFilterer.js +2 -2
  6. package/dist/DiagnosticFilterer.js.map +1 -1
  7. package/dist/DiagnosticMessages.d.ts +6 -1
  8. package/dist/DiagnosticMessages.js +5 -0
  9. package/dist/DiagnosticMessages.js.map +1 -1
  10. package/dist/LanguageServer.d.ts +8 -2
  11. package/dist/LanguageServer.js +50 -44
  12. package/dist/LanguageServer.js.map +1 -1
  13. package/dist/Program.d.ts +61 -45
  14. package/dist/Program.js +305 -188
  15. package/dist/Program.js.map +1 -1
  16. package/dist/ProgramBuilder.d.ts +7 -7
  17. package/dist/ProgramBuilder.js +60 -51
  18. package/dist/ProgramBuilder.js.map +1 -1
  19. package/dist/Scope.d.ts +42 -19
  20. package/dist/Scope.js +261 -129
  21. package/dist/Scope.js.map +1 -1
  22. package/dist/SymbolTable.d.ts +73 -0
  23. package/dist/SymbolTable.js +157 -0
  24. package/dist/SymbolTable.js.map +1 -0
  25. package/dist/XmlScope.d.ts +5 -0
  26. package/dist/XmlScope.js +66 -28
  27. package/dist/XmlScope.js.map +1 -1
  28. package/dist/astUtils/creators.d.ts +15 -1
  29. package/dist/astUtils/creators.js +39 -9
  30. package/dist/astUtils/creators.js.map +1 -1
  31. package/dist/astUtils/reflection.d.ts +28 -16
  32. package/dist/astUtils/reflection.js +52 -30
  33. package/dist/astUtils/reflection.js.map +1 -1
  34. package/dist/astUtils/reflection.spec.js +3 -3
  35. package/dist/astUtils/reflection.spec.js.map +1 -1
  36. package/dist/astUtils/visitors.spec.js +12 -13
  37. package/dist/astUtils/visitors.spec.js.map +1 -1
  38. package/dist/astUtils/xml.d.ts +3 -3
  39. package/dist/astUtils/xml.js +2 -2
  40. package/dist/astUtils/xml.js.map +1 -1
  41. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +5 -6
  42. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  43. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +24 -22
  44. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
  45. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js +2 -2
  46. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js.map +1 -1
  47. package/dist/examples/plugins/removePrint.js +1 -1
  48. package/dist/examples/plugins/removePrint.js.map +1 -1
  49. package/dist/files/BrsFile.Class.spec.js +356 -41
  50. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  51. package/dist/files/BrsFile.d.ts +55 -37
  52. package/dist/files/BrsFile.js +430 -399
  53. package/dist/files/BrsFile.js.map +1 -1
  54. package/dist/files/BrsFile.spec.js +199 -158
  55. package/dist/files/BrsFile.spec.js.map +1 -1
  56. package/dist/files/XmlFile.d.ts +20 -9
  57. package/dist/files/XmlFile.js +36 -31
  58. package/dist/files/XmlFile.js.map +1 -1
  59. package/dist/files/XmlFile.spec.js +113 -113
  60. package/dist/files/XmlFile.spec.js.map +1 -1
  61. package/dist/files/tests/imports.spec.js +32 -32
  62. package/dist/files/tests/imports.spec.js.map +1 -1
  63. package/dist/globalCallables.js +17 -6
  64. package/dist/globalCallables.js.map +1 -1
  65. package/dist/interfaces.d.ts +155 -39
  66. package/dist/parser/BrsTranspileState.d.ts +7 -0
  67. package/dist/parser/BrsTranspileState.js +10 -1
  68. package/dist/parser/BrsTranspileState.js.map +1 -1
  69. package/dist/parser/Expression.d.ts +23 -12
  70. package/dist/parser/Expression.js +45 -30
  71. package/dist/parser/Expression.js.map +1 -1
  72. package/dist/parser/Parser.Class.spec.js +100 -1
  73. package/dist/parser/Parser.Class.spec.js.map +1 -1
  74. package/dist/parser/Parser.d.ts +118 -5
  75. package/dist/parser/Parser.js +398 -37
  76. package/dist/parser/Parser.js.map +1 -1
  77. package/dist/parser/Parser.spec.js +404 -7
  78. package/dist/parser/Parser.spec.js.map +1 -1
  79. package/dist/parser/SGParser.d.ts +41 -4
  80. package/dist/parser/SGParser.js +185 -174
  81. package/dist/parser/SGParser.js.map +1 -1
  82. package/dist/parser/SGParser.spec.js +17 -4
  83. package/dist/parser/SGParser.spec.js.map +1 -1
  84. package/dist/parser/SGTypes.d.ts +203 -38
  85. package/dist/parser/SGTypes.js +464 -160
  86. package/dist/parser/SGTypes.js.map +1 -1
  87. package/dist/parser/SGTypes.spec.d.ts +1 -0
  88. package/dist/parser/SGTypes.spec.js +351 -0
  89. package/dist/parser/SGTypes.spec.js.map +1 -0
  90. package/dist/parser/Statement.d.ts +37 -26
  91. package/dist/parser/Statement.js +81 -20
  92. package/dist/parser/Statement.js.map +1 -1
  93. package/dist/parser/Statement.spec.js +5 -5
  94. package/dist/parser/Statement.spec.js.map +1 -1
  95. package/dist/parser/TranspileState.d.ts +1 -1
  96. package/dist/parser/TranspileState.js +15 -7
  97. package/dist/parser/TranspileState.js.map +1 -1
  98. package/dist/parser/tests/controlFlow/ForEach.spec.js +5 -4
  99. package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
  100. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +1 -1
  101. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
  102. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +1 -1
  103. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -1
  104. package/dist/parser/tests/expression/TemplateStringExpression.spec.js +1 -1
  105. package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
  106. package/dist/parser/tests/expression/TernaryExpression.spec.js +1 -1
  107. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
  108. package/dist/types/ArrayType.d.ts +1 -0
  109. package/dist/types/ArrayType.js +23 -19
  110. package/dist/types/ArrayType.js.map +1 -1
  111. package/dist/types/BooleanType.d.ts +3 -2
  112. package/dist/types/BooleanType.js +6 -3
  113. package/dist/types/BooleanType.js.map +1 -1
  114. package/dist/types/BscType.d.ts +19 -4
  115. package/dist/types/BscType.js +9 -0
  116. package/dist/types/BscType.js.map +1 -1
  117. package/dist/types/CustomType.d.ts +8 -5
  118. package/dist/types/CustomType.js +12 -12
  119. package/dist/types/CustomType.js.map +1 -1
  120. package/dist/types/DoubleType.d.ts +1 -0
  121. package/dist/types/DoubleType.js +11 -11
  122. package/dist/types/DoubleType.js.map +1 -1
  123. package/dist/types/DynamicType.d.ts +1 -0
  124. package/dist/types/DynamicType.js +4 -0
  125. package/dist/types/DynamicType.js.map +1 -1
  126. package/dist/types/FloatType.d.ts +2 -1
  127. package/dist/types/FloatType.js +11 -11
  128. package/dist/types/FloatType.js.map +1 -1
  129. package/dist/types/FunctionType.d.ts +13 -10
  130. package/dist/types/FunctionType.js +34 -18
  131. package/dist/types/FunctionType.js.map +1 -1
  132. package/dist/types/FunctionType.spec.js +8 -2
  133. package/dist/types/FunctionType.spec.js.map +1 -1
  134. package/dist/types/IntegerType.d.ts +2 -1
  135. package/dist/types/IntegerType.js +11 -11
  136. package/dist/types/IntegerType.js.map +1 -1
  137. package/dist/types/InvalidType.d.ts +3 -2
  138. package/dist/types/InvalidType.js +7 -4
  139. package/dist/types/InvalidType.js.map +1 -1
  140. package/dist/types/LazyType.d.ts +17 -0
  141. package/dist/types/LazyType.js +44 -0
  142. package/dist/types/LazyType.js.map +1 -0
  143. package/dist/types/LongIntegerType.d.ts +2 -1
  144. package/dist/types/LongIntegerType.js +11 -11
  145. package/dist/types/LongIntegerType.js.map +1 -1
  146. package/dist/types/ObjectType.d.ts +6 -2
  147. package/dist/types/ObjectType.js +9 -3
  148. package/dist/types/ObjectType.js.map +1 -1
  149. package/dist/types/StringType.d.ts +3 -2
  150. package/dist/types/StringType.js +6 -3
  151. package/dist/types/StringType.js.map +1 -1
  152. package/dist/types/UninitializedType.d.ts +4 -2
  153. package/dist/types/UninitializedType.js +8 -3
  154. package/dist/types/UninitializedType.js.map +1 -1
  155. package/dist/types/VoidType.d.ts +3 -2
  156. package/dist/types/VoidType.js +6 -3
  157. package/dist/types/VoidType.js.map +1 -1
  158. package/dist/types/helpers.d.ts +42 -0
  159. package/dist/types/helpers.js +113 -0
  160. package/dist/types/helpers.js.map +1 -0
  161. package/dist/util.d.ts +68 -15
  162. package/dist/util.js +193 -45
  163. package/dist/util.js.map +1 -1
  164. package/dist/validators/ClassValidator.d.ts +5 -1
  165. package/dist/validators/ClassValidator.js +31 -17
  166. package/dist/validators/ClassValidator.js.map +1 -1
  167. package/package.json +1 -1
  168. package/dist/FunctionScope.d.ts +0 -27
  169. package/dist/FunctionScope.js +0 -49
  170. package/dist/FunctionScope.js.map +0 -1
@@ -11,6 +11,7 @@ const util_1 = require("../util");
11
11
  const fsExtra = require("fs-extra");
12
12
  const BrsTranspileState_1 = require("../parser/BrsTranspileState");
13
13
  const assert_1 = require("assert");
14
+ const reflection_1 = require("../astUtils/reflection");
14
15
  let sinon = sinonImport.createSandbox();
15
16
  describe('BrsFile BrighterScript classes', () => {
16
17
  let tmpPath = (0, util_1.standardizePath) `${process.cwd()}/.tmp`;
@@ -29,10 +30,10 @@ describe('BrsFile BrighterScript classes', () => {
29
30
  fsExtra.emptyDirSync(tmpPath);
30
31
  });
31
32
  function addFile(relativePath, text) {
32
- return program.addOrReplaceFile({ src: `${rootDir}/${relativePath}`, dest: relativePath }, text);
33
+ return program.setFile({ src: `${rootDir}/${relativePath}`, dest: relativePath }, text);
33
34
  }
34
35
  it('detects all classes after parse', () => {
35
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
36
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
36
37
  class Animal
37
38
  end class
38
39
  class Duck
@@ -43,7 +44,7 @@ describe('BrsFile BrighterScript classes', () => {
43
44
  (0, chai_1.expect)(file.parser.references.classStatements.map(x => x.getName(Parser_1.ParseMode.BrighterScript)).sort()).to.eql(['Animal', 'Duck']);
44
45
  });
45
46
  it('does not cause errors with incomplete class statement', () => {
46
- program.addOrReplaceFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
47
+ program.setFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
47
48
  class
48
49
  `);
49
50
  program.validate();
@@ -51,7 +52,7 @@ describe('BrsFile BrighterScript classes', () => {
51
52
  });
52
53
  it('catches child class missing super call in constructor', () => {
53
54
  var _a;
54
- program.addOrReplaceFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
55
+ program.setFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
55
56
  class Person
56
57
  sub new()
57
58
  end sub
@@ -66,7 +67,7 @@ describe('BrsFile BrighterScript classes', () => {
66
67
  });
67
68
  it('access modifier is option for override', () => {
68
69
  var _a;
69
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
70
+ let file = program.setFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
70
71
  class Animal
71
72
  sub move()
72
73
  end sub
@@ -85,7 +86,7 @@ describe('BrsFile BrighterScript classes', () => {
85
86
  });
86
87
  it('supports various namespace configurations', () => {
87
88
  var _a;
88
- program.addOrReplaceFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
89
+ program.setFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
89
90
  class Animal
90
91
  sub new()
91
92
  bigBird = new Birds.Bird()
@@ -110,7 +111,7 @@ describe('BrsFile BrighterScript classes', () => {
110
111
  describe('super', () => {
111
112
  it('always requires super call in child constructor', () => {
112
113
  var _a;
113
- program.addOrReplaceFile('source/main.bs', `
114
+ program.setFile('source/main.bs', `
114
115
  class Bird
115
116
  end class
116
117
  class Duck extends Bird
@@ -123,7 +124,7 @@ describe('BrsFile BrighterScript classes', () => {
123
124
  });
124
125
  it('requires super call in child when parent has own `new` method', () => {
125
126
  var _a;
126
- program.addOrReplaceFile('source/main.bs', `
127
+ program.setFile('source/main.bs', `
127
128
  class Bird
128
129
  sub new()
129
130
  end sub
@@ -138,7 +139,7 @@ describe('BrsFile BrighterScript classes', () => {
138
139
  });
139
140
  it('allows non-`m` expressions and statements before the super call', () => {
140
141
  var _a;
141
- program.addOrReplaceFile('source/main.bs', `
142
+ program.setFile('source/main.bs', `
142
143
  class Bird
143
144
  sub new(name)
144
145
  end sub
@@ -156,7 +157,7 @@ describe('BrsFile BrighterScript classes', () => {
156
157
  (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).to.be.undefined;
157
158
  });
158
159
  it('allows non-`m` expressions and statements before the super call', () => {
159
- program.addOrReplaceFile('source/main.bs', `
160
+ program.setFile('source/main.bs', `
160
161
  class Bird
161
162
  sub new(name)
162
163
  end sub
@@ -164,7 +165,7 @@ describe('BrsFile BrighterScript classes', () => {
164
165
  class Duck extends Bird
165
166
  sub new()
166
167
  m.name = m.name + "Duck"
167
- super()
168
+ super(m.name)
168
169
  end sub
169
170
  end class
170
171
  `);
@@ -357,6 +358,9 @@ describe('BrsFile BrighterScript classes', () => {
357
358
  class Animal
358
359
  sub new(name as string)
359
360
  end sub
361
+
362
+ sub DoSomething()
363
+ end sub
360
364
  end class
361
365
 
362
366
  class Duck extends Animal
@@ -370,6 +374,8 @@ describe('BrsFile BrighterScript classes', () => {
370
374
  instance = {}
371
375
  instance.new = sub(name as string)
372
376
  end sub
377
+ instance.DoSomething = sub()
378
+ end sub
373
379
  return instance
374
380
  end function
375
381
  function Animal(name as string)
@@ -661,7 +667,7 @@ describe('BrsFile BrighterScript classes', () => {
661
667
  });
662
668
  it('detects using `new` keyword on non-classes', () => {
663
669
  var _a;
664
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
670
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
665
671
  sub quack()
666
672
  end sub
667
673
  sub main()
@@ -673,7 +679,7 @@ describe('BrsFile BrighterScript classes', () => {
673
679
  });
674
680
  it('detects missing call to super', () => {
675
681
  var _a;
676
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
682
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
677
683
  class Animal
678
684
  sub new()
679
685
  end sub
@@ -688,7 +694,7 @@ describe('BrsFile BrighterScript classes', () => {
688
694
  });
689
695
  it.skip('detects calls to unknown m methods', () => {
690
696
  var _a;
691
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
697
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
692
698
  class Animal
693
699
  sub new()
694
700
  m.methodThatDoesNotExist()
@@ -699,7 +705,7 @@ describe('BrsFile BrighterScript classes', () => {
699
705
  (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.methodDoesNotExistOnType('methodThatDoesNotExist', 'Animal'));
700
706
  });
701
707
  it('detects duplicate member names', () => {
702
- program.addOrReplaceFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
708
+ program.setFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
703
709
  class Animal
704
710
  public name
705
711
  public name
@@ -724,7 +730,7 @@ describe('BrsFile BrighterScript classes', () => {
724
730
  (0, chai_1.expect)(diagnostics).to.eql([Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.duplicateIdentifier('name')), { range: vscode_languageserver_1.Range.create(3, 23, 3, 27) }), Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.duplicateIdentifier('name')), { range: vscode_languageserver_1.Range.create(4, 27, 4, 31) }), Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.duplicateIdentifier('age')), { range: vscode_languageserver_1.Range.create(8, 27, 8, 30) }), Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.duplicateIdentifier('age')), { range: vscode_languageserver_1.Range.create(10, 23, 10, 26) })]);
725
731
  });
726
732
  it('detects mismatched member type in child class', () => {
727
- program.addOrReplaceFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
733
+ program.setFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
728
734
  class Animal
729
735
  public name
730
736
  end class
@@ -738,7 +744,7 @@ describe('BrsFile BrighterScript classes', () => {
738
744
  (0, chai_1.expect)(program.getDiagnostics().map(x => x.message).sort()[0]).to.eql(DiagnosticMessages_1.DiagnosticMessages.classChildMemberDifferentMemberTypeThanAncestor('method', 'field', 'Animal').message);
739
745
  });
740
746
  it('allows untyped overridden field in child class', () => {
741
- program.addOrReplaceFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
747
+ program.setFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
742
748
  class Animal
743
749
  public name
744
750
  end class
@@ -750,7 +756,7 @@ describe('BrsFile BrighterScript classes', () => {
750
756
  (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
751
757
  });
752
758
  it('allows overridden property name in child class', () => {
753
- program.addOrReplaceFile('source/main.bs', `
759
+ program.setFile('source/main.bs', `
754
760
  class Bird
755
761
  public name = "bird"
756
762
  end class
@@ -762,7 +768,7 @@ describe('BrsFile BrighterScript classes', () => {
762
768
  (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
763
769
  });
764
770
  it('flags incompatible child field type changes', () => {
765
- program.addOrReplaceFile('source/main.bs', `
771
+ program.setFile('source/main.bs', `
766
772
  class Bird
767
773
  public age = 12
768
774
  public name = "bird"
@@ -783,7 +789,7 @@ describe('BrsFile BrighterScript classes', () => {
783
789
  ]);
784
790
  });
785
791
  it('detects overridden methods without override keyword', () => {
786
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
792
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
787
793
  class Animal
788
794
  sub speak()
789
795
  end sub
@@ -797,7 +803,7 @@ describe('BrsFile BrighterScript classes', () => {
797
803
  (0, chai_1.expect)(program.getDiagnostics()[0]).to.exist.and.to.include(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingOverrideKeyword('Animal')));
798
804
  });
799
805
  it('detects overridden methods with different visibility', () => {
800
- program.addOrReplaceFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
806
+ program.setFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
801
807
  class Animal
802
808
  sub speakInPublic()
803
809
  end sub
@@ -821,7 +827,7 @@ describe('BrsFile BrighterScript classes', () => {
821
827
  (0, chai_1.expect)(program.getDiagnostics()[2]).to.exist.and.to.include(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.mismatchedOverriddenMemberVisibility('Duck', 'speakWithFamily', 'public', 'private', 'Animal')));
822
828
  });
823
829
  it('allows overridden methods with matching visibility', () => {
824
- program.addOrReplaceFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
830
+ program.setFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
825
831
  class Animal
826
832
  sub speakInPublic()
827
833
  end sub
@@ -843,7 +849,7 @@ describe('BrsFile BrighterScript classes', () => {
843
849
  (0, chai_1.expect)(program.getDiagnostics()).to.be.empty;
844
850
  });
845
851
  it('detects extending unknown parent class', () => {
846
- program.addOrReplaceFile('source/main.brs', `
852
+ program.setFile('source/main.brs', `
847
853
  class Duck extends Animal
848
854
  sub speak()
849
855
  end sub
@@ -854,7 +860,7 @@ describe('BrsFile BrighterScript classes', () => {
854
860
  });
855
861
  it('catches newable class without namespace name', () => {
856
862
  var _a;
857
- program.addOrReplaceFile('source/main.bs', `
863
+ program.setFile('source/main.bs', `
858
864
  namespace NameA.NameB
859
865
  class Duck
860
866
  end class
@@ -869,7 +875,7 @@ describe('BrsFile BrighterScript classes', () => {
869
875
  });
870
876
  it('supports newable class namespace inference', () => {
871
877
  var _a;
872
- program.addOrReplaceFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
878
+ program.setFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
873
879
  namespace NameA.NameB
874
880
  class Duck
875
881
  end class
@@ -883,7 +889,7 @@ describe('BrsFile BrighterScript classes', () => {
883
889
  });
884
890
  it('catches extending unknown namespaced class', () => {
885
891
  var _a;
886
- program.addOrReplaceFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
892
+ program.setFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
887
893
  namespace NameA.NameB
888
894
  class Animal
889
895
  end class
@@ -896,7 +902,7 @@ describe('BrsFile BrighterScript classes', () => {
896
902
  });
897
903
  it('supports omitting namespace prefix for items in same namespace', () => {
898
904
  var _a;
899
- program.addOrReplaceFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
905
+ program.setFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
900
906
  namespace NameA.NameB
901
907
  class Animal
902
908
  end class
@@ -909,7 +915,7 @@ describe('BrsFile BrighterScript classes', () => {
909
915
  });
910
916
  it('catches duplicate root-level class declarations', () => {
911
917
  var _a;
912
- program.addOrReplaceFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
918
+ program.setFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
913
919
  class Animal
914
920
  end class
915
921
  class Animal
@@ -919,7 +925,7 @@ describe('BrsFile BrighterScript classes', () => {
919
925
  });
920
926
  it('catches duplicate namespace-level class declarations', () => {
921
927
  var _a;
922
- program.addOrReplaceFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
928
+ program.setFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
923
929
  namespace NameA.NameB
924
930
  class Animal
925
931
  end class
@@ -931,7 +937,7 @@ describe('BrsFile BrighterScript classes', () => {
931
937
  });
932
938
  it('catches namespaced class name which is the same as a global class', () => {
933
939
  var _a;
934
- program.addOrReplaceFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
940
+ program.setFile({ src: `${rootDir}/source/main.bs`, dest: 'source/main.bs' }, `
935
941
  namespace NameA.NameB
936
942
  class Animal
937
943
  end class
@@ -944,7 +950,7 @@ describe('BrsFile BrighterScript classes', () => {
944
950
  });
945
951
  it('catches class with same name as function', () => {
946
952
  var _a;
947
- program.addOrReplaceFile('source/main.bs', `
953
+ program.setFile('source/main.bs', `
948
954
  class Animal
949
955
  end class
950
956
  sub Animal()
@@ -955,7 +961,7 @@ describe('BrsFile BrighterScript classes', () => {
955
961
  });
956
962
  it('catches class with same name (but different case) as function', () => {
957
963
  var _a;
958
- program.addOrReplaceFile('source/main.bs', `
964
+ program.setFile('source/main.bs', `
959
965
  class ANIMAL
960
966
  end class
961
967
  sub animal()
@@ -966,7 +972,7 @@ describe('BrsFile BrighterScript classes', () => {
966
972
  });
967
973
  it('catches variable with same name as class', () => {
968
974
  var _a;
969
- program.addOrReplaceFile('source/main.bs', `
975
+ program.setFile('source/main.bs', `
970
976
  class Animal
971
977
  end class
972
978
  sub main()
@@ -977,7 +983,7 @@ describe('BrsFile BrighterScript classes', () => {
977
983
  (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.localVarSameNameAsClass('Animal').message);
978
984
  });
979
985
  it('allows extending classes with more than one dot in the filename', () => {
980
- program.addOrReplaceFile('source/testclass.bs', `
986
+ program.setFile('source/testclass.bs', `
981
987
  class Foo
982
988
  end class
983
989
 
@@ -987,14 +993,14 @@ describe('BrsFile BrighterScript classes', () => {
987
993
  end sub
988
994
  end class
989
995
  `);
990
- program.addOrReplaceFile('source/testclass_no_testdot.bs', `
996
+ program.setFile('source/testclass_no_testdot.bs', `
991
997
  class BarNoDot extends Foo
992
998
  sub new()
993
999
  super()
994
1000
  end sub
995
1001
  end class
996
1002
  `);
997
- program.addOrReplaceFile('source/testclass.dot.bs', `
1003
+ program.setFile('source/testclass.dot.bs', `
998
1004
  class BarDot extends Foo
999
1005
  sub new()
1000
1006
  super()
@@ -1005,7 +1011,7 @@ describe('BrsFile BrighterScript classes', () => {
1005
1011
  (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1006
1012
  });
1007
1013
  it('computes correct super index for grandchild class', () => {
1008
- program.addOrReplaceFile('source/main.bs', `
1014
+ program.setFile('source/main.bs', `
1009
1015
  sub Main()
1010
1016
  c = new App.ClassC()
1011
1017
  end sub
@@ -1043,7 +1049,7 @@ describe('BrsFile BrighterScript classes', () => {
1043
1049
  `, 'trim', 'source/App.ClassC.bs');
1044
1050
  });
1045
1051
  it('computes correct super index for namespaced child class and global parent class', () => {
1046
- program.addOrReplaceFile('source/ClassA.bs', `
1052
+ program.setFile('source/ClassA.bs', `
1047
1053
  class ClassA
1048
1054
  end class
1049
1055
  `);
@@ -1069,7 +1075,7 @@ describe('BrsFile BrighterScript classes', () => {
1069
1075
  `, 'trim', 'source/App.ClassB.bs');
1070
1076
  });
1071
1077
  it('does not crash when parent class is missing', () => {
1072
- const file = program.addOrReplaceFile('source/ClassB.bs', `
1078
+ const file = program.setFile('source/ClassB.bs', `
1073
1079
  class ClassB extends ClassA
1074
1080
  end class
1075
1081
  `);
@@ -1077,8 +1083,317 @@ describe('BrsFile BrighterScript classes', () => {
1077
1083
  file.parser.references.classStatements[0].getParentClassIndex(new BrsTranspileState_1.BrsTranspileState(file));
1078
1084
  });
1079
1085
  });
1086
+ describe('getHover', () => {
1087
+ const animalClassCode = `
1088
+ class Animal
1089
+ kind as string
1090
+ isHungry as boolean
1091
+
1092
+ sub new(kind as string)
1093
+ m.kind = kind
1094
+ m.isHungry = true ' born hungry
1095
+ end sub
1096
+
1097
+ sub eat(foodAmount as integer)
1098
+ if foodAmount > 100
1099
+ m.isHungry = false
1100
+ end if
1101
+ end sub
1102
+
1103
+ sub sleep()
1104
+ m.isHungry = false
1105
+ end sub
1106
+
1107
+ end class
1108
+
1109
+ class Dog extends Animal
1110
+ breed as string
1111
+ sub new(breed as string)
1112
+ super("Dog")
1113
+ m.breed = breed
1114
+ end sub
1115
+
1116
+ sub snooze()
1117
+ m.sleep()
1118
+ end sub
1119
+ end class
1120
+
1121
+ class DogHouse
1122
+ puppy as Dog
1123
+ sub new(pup as Dog)
1124
+ m.puppy = pup
1125
+ end sub
1126
+ end class
1127
+
1128
+ sub main()
1129
+ snoopy = new Dog("Beagle")
1130
+ biplane = new DogHouse(snoopy)
1131
+ print snoopy.kind ' Dog
1132
+ print snoopy.breed ' Beagle
1133
+ print snoopy.isHungry ' true
1134
+ feedAnimal(biplane.puppy)
1135
+ print snoopy.isHungry ' false
1136
+ end sub
1137
+
1138
+ sub feedAnimal(beast as Animal)
1139
+ beast.eat(100)
1140
+ end sub
1141
+ `;
1142
+ it('correctly parses the file', () => {
1143
+ program.setFile('source/animal.bs', animalClassCode);
1144
+ program.validate();
1145
+ (0, chai_1.expect)(program.getDiagnostics().length).to.equal(0);
1146
+ });
1147
+ it('gets the correct text for m', () => {
1148
+ let animalCode = program.setFile('source/animal.bs', animalClassCode);
1149
+ program.validate();
1150
+ let hover = animalCode.getHover(vscode_languageserver_1.Position.create(6, 17));
1151
+ (0, chai_1.expect)(hover).to.exist;
1152
+ (0, chai_1.expect)(hover.contents).to.equal('m as Animal');
1153
+ hover = animalCode.getHover(vscode_languageserver_1.Position.create(26, 17));
1154
+ (0, chai_1.expect)(hover).to.exist;
1155
+ (0, chai_1.expect)(hover.contents).to.equal('m as Dog');
1156
+ });
1157
+ it('gets the correct text for m.field', () => {
1158
+ let animalCode = program.setFile('source/animal.bs', animalClassCode);
1159
+ program.validate();
1160
+ let hover = animalCode.getHover(vscode_languageserver_1.Position.create(6, 19));
1161
+ (0, chai_1.expect)(hover).to.exist;
1162
+ (0, chai_1.expect)(hover.contents).to.equal('Animal.kind as string');
1163
+ hover = animalCode.getHover(vscode_languageserver_1.Position.create(26, 19));
1164
+ (0, chai_1.expect)(hover).to.exist;
1165
+ (0, chai_1.expect)(hover.contents).to.equal('Dog.breed as string');
1166
+ });
1167
+ it('gets the correct text for m.method', () => {
1168
+ let animalCode = program.setFile('source/animal.bs', animalClassCode);
1169
+ program.validate();
1170
+ let hover = animalCode.getHover(vscode_languageserver_1.Position.create(30, 21));
1171
+ (0, chai_1.expect)(hover).to.exist;
1172
+ (0, chai_1.expect)(hover.contents).to.equal('sub Animal.sleep() as void');
1173
+ });
1174
+ it('gets the correct text for obj.field', () => {
1175
+ let animalCode = program.setFile('source/animal.brs', animalClassCode);
1176
+ program.validate();
1177
+ let hover = animalCode.getHover(vscode_languageserver_1.Position.create(46, 29));
1178
+ (0, chai_1.expect)(hover).to.exist;
1179
+ //TODO TYPES: This should probably say 'Animal.isHungry ...' because that field is defined in Animal
1180
+ (0, chai_1.expect)(hover.contents).to.equal('Dog.isHungry as boolean');
1181
+ });
1182
+ it('gets the correct text for obj.method', () => {
1183
+ let animalCode = program.setFile('source/animal.bs', animalClassCode);
1184
+ program.validate();
1185
+ let hover = animalCode.getHover(vscode_languageserver_1.Position.create(52, 21));
1186
+ (0, chai_1.expect)(hover).to.exist;
1187
+ (0, chai_1.expect)(hover.contents).to.equal('sub Animal.eat(foodAmount as integer) as void');
1188
+ });
1189
+ });
1190
+ describe('getHover class members', () => {
1191
+ const testCode = `
1192
+ class Foo
1193
+ sub new(name as string)
1194
+ end sub
1195
+ end class
1196
+
1197
+ class Bar
1198
+ sub doSomething()
1199
+ myFoo = new Foo()
1200
+ end sub
1201
+
1202
+ function getInt() as integer
1203
+ return 1
1204
+ end function
1205
+ end class
1206
+
1207
+ class Buz
1208
+ myInt as integer
1209
+ sub new(i as integer)
1210
+ myInt = i
1211
+ end sub
1212
+ end class
1213
+
1214
+ class Bee extends Buz
1215
+ sub new(i as integer)
1216
+ super(i)
1217
+ end sub
1218
+
1219
+ sub varSameNameAsMember()
1220
+ myInt = 4567
1221
+ print myInt ' should not print m.myInt
1222
+ end sub
1223
+ end class`;
1224
+ it('correctly parses the file', () => {
1225
+ program.setFile('source/fooBar.bs', testCode);
1226
+ program.validate();
1227
+ (0, chai_1.expect)(program.getDiagnostics().length).to.equal(0);
1228
+ });
1229
+ it('gets the correct text for new Class()', () => {
1230
+ let file = program.setFile('source/fooBar.bs', testCode);
1231
+ program.validate();
1232
+ let hover = file.getHover(vscode_languageserver_1.Position.create(8, 34)); // new Foo("hello")
1233
+ (0, chai_1.expect)(hover).to.exist;
1234
+ (0, chai_1.expect)(hover.contents).to.equal('new Foo(name as string)');
1235
+ });
1236
+ it('gets the correct text for created object', () => {
1237
+ let file = program.setFile('source/fooBar.bs', testCode);
1238
+ program.validate();
1239
+ let hover = file.getHover(vscode_languageserver_1.Position.create(8, 23)); // myFoo
1240
+ (0, chai_1.expect)(hover).to.exist;
1241
+ (0, chai_1.expect)(hover.contents).to.equal('myFoo as Foo');
1242
+ });
1243
+ it('gets the correct text for class declaration', () => {
1244
+ let file = program.setFile('source/fooBar.bs', testCode);
1245
+ program.validate();
1246
+ let hover = file.getHover(vscode_languageserver_1.Position.create(6, 21)); // class Bar
1247
+ (0, chai_1.expect)(hover).to.exist;
1248
+ (0, chai_1.expect)(hover.contents).to.equal('class Bar');
1249
+ });
1250
+ it('gets the correct text for class method declaration', () => {
1251
+ let file = program.setFile('source/fooBar.bs', testCode);
1252
+ program.validate();
1253
+ let hover = file.getHover(vscode_languageserver_1.Position.create(11, 29)); // getInt
1254
+ (0, chai_1.expect)(hover).to.exist;
1255
+ (0, chai_1.expect)(hover.contents).to.equal('function Bar.getInt() as integer');
1256
+ });
1257
+ it('gets the correct text for class field declaration', () => {
1258
+ let file = program.setFile('source/fooBar.bs', testCode);
1259
+ program.validate();
1260
+ let hover = file.getHover(vscode_languageserver_1.Position.create(17, 20)); // myInt
1261
+ (0, chai_1.expect)(hover).to.exist;
1262
+ (0, chai_1.expect)(hover.contents).to.equal('Buz.myInt as integer');
1263
+ });
1264
+ it('gets the correct text for super() call', () => {
1265
+ let file = program.setFile('source/fooBar.bs', testCode);
1266
+ program.validate();
1267
+ let hover = file.getHover(vscode_languageserver_1.Position.create(25, 23)); // super() in Bee.new
1268
+ (0, chai_1.expect)(hover).to.exist;
1269
+ (0, chai_1.expect)(hover.contents).to.equal('new Buz(i as integer)');
1270
+ });
1271
+ it('gets the correct text for variable with same name as a member', () => {
1272
+ let file = program.setFile('source/fooBar.bs', testCode);
1273
+ program.validate();
1274
+ let hover = file.getHover(vscode_languageserver_1.Position.create(29, 23)); // myInt in Bee.varSameNameAsMember
1275
+ (0, chai_1.expect)(hover).to.exist;
1276
+ (0, chai_1.expect)(hover.contents).to.equal('myInt as integer');
1277
+ });
1278
+ });
1279
+ describe('getSymbolTypeFromToken', () => {
1280
+ const testClassCode = `
1281
+ class KlassA
1282
+ function getInt() as integer
1283
+ return 1
1284
+ end function
1285
+
1286
+ sub printInt(i as integer)
1287
+ print i
1288
+ end sub
1289
+ end class
1290
+
1291
+ class KlassB
1292
+
1293
+ function getA() as KlassA
1294
+ return new KlassA()
1295
+ end function
1296
+ end class
1297
+
1298
+ class KlassC
1299
+ public b as KlassB
1300
+
1301
+ sub new()
1302
+ m.b = new KlassB()
1303
+ end sub
1304
+ end class
1305
+
1306
+ sub main()
1307
+ c = new KlassC()
1308
+ a = c.b.getA()
1309
+ num = c.b.getA().getInt()
1310
+ c.b.getA().printInt(num)
1311
+ end sub
1312
+ `;
1313
+ it('correctly parses the file', () => {
1314
+ program.setFile('source/klassTest.bs', testClassCode);
1315
+ program.validate();
1316
+ (0, chai_1.expect)(program.getDiagnostics().length).to.equal(0);
1317
+ });
1318
+ describe('finding tokens', () => {
1319
+ let klassCode;
1320
+ let mainScope;
1321
+ beforeEach(() => {
1322
+ klassCode = program.setFile('source/klassTest.bs', testClassCode);
1323
+ const scopes = program.getScopesForFile(klassCode);
1324
+ (0, chai_1.expect)(scopes.length).to.eql(1);
1325
+ mainScope = scopes[0];
1326
+ mainScope.linkSymbolTable();
1327
+ });
1328
+ afterEach(() => {
1329
+ mainScope.unlinkSymbolTable();
1330
+ });
1331
+ it('gets correct class for m', () => {
1332
+ var _a;
1333
+ const position = vscode_languageserver_1.Position.create(22, 17); // 'm' from m.b = new KlassB()
1334
+ const token = klassCode.parser.getTokenAt(position);
1335
+ (0, chai_1.expect)(token.text).to.equal('m');
1336
+ const func = klassCode.getFunctionExpressionAtPosition(position);
1337
+ let klass = (_a = klassCode.getClassFromToken(token, func, mainScope)) === null || _a === void 0 ? void 0 : _a.item;
1338
+ (0, chai_1.expect)(klass).to.exist;
1339
+ (0, chai_1.expect)(klass.getName(Parser_1.ParseMode.BrighterScript)).to.equal('KlassC');
1340
+ });
1341
+ it('gets correct class for fieldMember', () => {
1342
+ var _a;
1343
+ const position = vscode_languageserver_1.Position.create(22, 19); // 'b' from m.b = new KlassB()
1344
+ const token = klassCode.parser.getTokenAt(position);
1345
+ (0, chai_1.expect)(token.text).to.equal('b');
1346
+ const func = klassCode.getFunctionExpressionAtPosition(position);
1347
+ let klass = (_a = klassCode.getClassFromToken(token, func, mainScope)) === null || _a === void 0 ? void 0 : _a.item;
1348
+ (0, chai_1.expect)(klass).to.exist;
1349
+ (0, chai_1.expect)(klass.getName(Parser_1.ParseMode.BrighterScript)).to.equal('KlassB');
1350
+ });
1351
+ it('gets correct class for variable', () => {
1352
+ var _a;
1353
+ const position = vscode_languageserver_1.Position.create(28, 17); // 'c' from c.b.getA().getInt()
1354
+ const token = klassCode.parser.getTokenAt(position);
1355
+ (0, chai_1.expect)(token.text).to.equal('c');
1356
+ const func = klassCode.getFunctionExpressionAtPosition(position);
1357
+ let klass = (_a = klassCode.getClassFromToken(token, func, mainScope)) === null || _a === void 0 ? void 0 : _a.item;
1358
+ (0, chai_1.expect)(klass).to.exist;
1359
+ (0, chai_1.expect)(klass.getName(Parser_1.ParseMode.BrighterScript)).to.equal('KlassC');
1360
+ });
1361
+ it('gets correct class for variable field', () => {
1362
+ var _a;
1363
+ const position = vscode_languageserver_1.Position.create(28, 19); // 'b' from c.b.getA()
1364
+ const token = klassCode.parser.getTokenAt(position);
1365
+ (0, chai_1.expect)(token.text).to.equal('b');
1366
+ const func = klassCode.getFunctionExpressionAtPosition(position);
1367
+ let klass = (_a = klassCode.getClassFromToken(token, func, mainScope)) === null || _a === void 0 ? void 0 : _a.item;
1368
+ (0, chai_1.expect)(klass).to.exist;
1369
+ (0, chai_1.expect)(klass.getName(Parser_1.ParseMode.BrighterScript)).to.equal('KlassB');
1370
+ });
1371
+ it('gets type and return class for variable function field', () => {
1372
+ const position = vscode_languageserver_1.Position.create(28, 23); // 'getA' from c.b.getA()
1373
+ const token = klassCode.parser.getTokenAt(position);
1374
+ (0, chai_1.expect)(token.text).to.equal('getA');
1375
+ const func = klassCode.getFunctionExpressionAtPosition(position);
1376
+ let { type, symbolContainer } = klassCode.getSymbolTypeFromToken(token, func, mainScope);
1377
+ (0, chai_1.expect)(type).to.exist;
1378
+ (0, chai_1.expect)((0, reflection_1.isFunctionType)(type)).to.be.true;
1379
+ (0, chai_1.expect)(symbolContainer).to.exist;
1380
+ (0, chai_1.expect)((0, reflection_1.isCustomType)(symbolContainer)).to.be.true;
1381
+ (0, chai_1.expect)(symbolContainer.name).to.equal('KlassA');
1382
+ });
1383
+ it('gets type and class for field from return value of function', () => {
1384
+ const position = vscode_languageserver_1.Position.create(29, 30); // 'getInt' from c.b.getA().getInt()
1385
+ const token = klassCode.parser.getTokenAt(position);
1386
+ (0, chai_1.expect)(token.text).to.equal('getInt');
1387
+ const func = klassCode.getFunctionExpressionAtPosition(position);
1388
+ let { type, symbolContainer } = klassCode.getSymbolTypeFromToken(token, func, mainScope);
1389
+ (0, chai_1.expect)(type).to.exist;
1390
+ (0, chai_1.expect)((0, reflection_1.isFunctionType)(type)).to.be.true;
1391
+ (0, chai_1.expect)(symbolContainer).to.be.undefined; // getInt() returns integer - no class reference at this point
1392
+ });
1393
+ });
1394
+ });
1080
1395
  it('does not crash when child has field with same name as sub in parent', () => {
1081
- program.addOrReplaceFile('source/main.bs', `
1396
+ program.setFile('source/main.bs', `
1082
1397
  class Parent
1083
1398
  public function helloWorld()
1084
1399
  end function
@@ -1090,7 +1405,7 @@ describe('BrsFile BrighterScript classes', () => {
1090
1405
  program.validate();
1091
1406
  });
1092
1407
  it('does not crash when child has method with same name as field in parent', () => {
1093
- program.addOrReplaceFile('source/main.bs', `
1408
+ program.setFile('source/main.bs', `
1094
1409
  class Parent
1095
1410
  public helloWorld as string
1096
1411
  end class