brighterscript 1.0.0-alpha.48 → 1.0.0-alpha.49

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 (157) hide show
  1. package/README.md +7 -10
  2. package/bsconfig.schema.json +34 -7
  3. package/dist/AstValidationSegmenter.js +12 -0
  4. package/dist/AstValidationSegmenter.js.map +1 -1
  5. package/dist/BsConfig.d.ts +6 -35
  6. package/dist/CrossScopeValidator.d.ts +1 -0
  7. package/dist/CrossScopeValidator.js +28 -4
  8. package/dist/CrossScopeValidator.js.map +1 -1
  9. package/dist/DiagnosticMessages.d.ts +1 -1
  10. package/dist/DiagnosticMessages.js +20 -6
  11. package/dist/DiagnosticMessages.js.map +1 -1
  12. package/dist/LanguageServer.d.ts +3 -1
  13. package/dist/LanguageServer.js +32 -19
  14. package/dist/LanguageServer.js.map +1 -1
  15. package/dist/Program.d.ts +9 -3
  16. package/dist/Program.js +111 -74
  17. package/dist/Program.js.map +1 -1
  18. package/dist/ProgramBuilder.d.ts +0 -2
  19. package/dist/ProgramBuilder.js +10 -28
  20. package/dist/ProgramBuilder.js.map +1 -1
  21. package/dist/SymbolTable.js +3 -2
  22. package/dist/SymbolTable.js.map +1 -1
  23. package/dist/astUtils/reflection.d.ts +14 -2
  24. package/dist/astUtils/reflection.js +70 -18
  25. package/dist/astUtils/reflection.js.map +1 -1
  26. package/dist/astUtils/visitors.d.ts +2 -1
  27. package/dist/astUtils/visitors.js.map +1 -1
  28. package/dist/bscPlugin/CallExpressionInfo.js +9 -3
  29. package/dist/bscPlugin/CallExpressionInfo.js.map +1 -1
  30. package/dist/bscPlugin/completions/CompletionsProcessor.js +3 -0
  31. package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -1
  32. package/dist/bscPlugin/completions/CompletionsProcessor.spec.js +34 -1
  33. package/dist/bscPlugin/completions/CompletionsProcessor.spec.js.map +1 -1
  34. package/dist/bscPlugin/hover/HoverProcessor.spec.js +31 -0
  35. package/dist/bscPlugin/hover/HoverProcessor.spec.js.map +1 -1
  36. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +3 -0
  37. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -1
  38. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.d.ts +5 -0
  39. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js +71 -3
  40. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js.map +1 -1
  41. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js +7 -7
  42. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js.map +1 -1
  43. package/dist/bscPlugin/validation/BrsFileValidator.js +10 -2
  44. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -1
  45. package/dist/bscPlugin/validation/BrsFileValidator.spec.js +99 -0
  46. package/dist/bscPlugin/validation/BrsFileValidator.spec.js.map +1 -1
  47. package/dist/bscPlugin/validation/ScopeValidator.d.ts +1 -0
  48. package/dist/bscPlugin/validation/ScopeValidator.js +19 -4
  49. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -1
  50. package/dist/bscPlugin/validation/ScopeValidator.spec.js +334 -0
  51. package/dist/bscPlugin/validation/ScopeValidator.spec.js.map +1 -1
  52. package/dist/cli.js +11 -18
  53. package/dist/cli.js.map +1 -1
  54. package/dist/files/BrsFile.Class.spec.js +336 -200
  55. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  56. package/dist/files/BrsFile.spec.js +61 -10
  57. package/dist/files/BrsFile.spec.js.map +1 -1
  58. package/dist/files/XmlFile.d.ts +7 -0
  59. package/dist/files/XmlFile.js +36 -0
  60. package/dist/files/XmlFile.js.map +1 -1
  61. package/dist/files/XmlFile.spec.js +7 -9
  62. package/dist/files/XmlFile.spec.js.map +1 -1
  63. package/dist/files/tests/imports.spec.js +3 -3
  64. package/dist/files/tests/imports.spec.js.map +1 -1
  65. package/dist/files/tests/optionalChaning.spec.js +1 -1
  66. package/dist/files/tests/optionalChaning.spec.js.map +1 -1
  67. package/dist/interfaces.d.ts +12 -4
  68. package/dist/interfaces.js.map +1 -1
  69. package/dist/lexer/Lexer.spec.js +12 -2
  70. package/dist/lexer/Lexer.spec.js.map +1 -1
  71. package/dist/lexer/TokenKind.js +6 -3
  72. package/dist/lexer/TokenKind.js.map +1 -1
  73. package/dist/lsp/Project.js +1 -3
  74. package/dist/lsp/Project.js.map +1 -1
  75. package/dist/lsp/Project.spec.js +1 -1
  76. package/dist/lsp/Project.spec.js.map +1 -1
  77. package/dist/lsp/ProjectManager.d.ts +8 -0
  78. package/dist/lsp/ProjectManager.js +7 -5
  79. package/dist/lsp/ProjectManager.js.map +1 -1
  80. package/dist/lsp/ProjectManager.spec.js +128 -0
  81. package/dist/lsp/ProjectManager.spec.js.map +1 -1
  82. package/dist/lsp/worker/WorkerThreadProject.js +21 -16
  83. package/dist/lsp/worker/WorkerThreadProject.js.map +1 -1
  84. package/dist/lsp/worker/run.d.ts +1 -0
  85. package/dist/lsp/worker/run.js +14 -0
  86. package/dist/lsp/worker/run.js.map +1 -0
  87. package/dist/parser/AstNode.d.ts +8 -1
  88. package/dist/parser/AstNode.js +9 -0
  89. package/dist/parser/AstNode.js.map +1 -1
  90. package/dist/parser/AstNode.spec.js +1 -1
  91. package/dist/parser/AstNode.spec.js.map +1 -1
  92. package/dist/parser/Expression.d.ts +43 -0
  93. package/dist/parser/Expression.js +120 -7
  94. package/dist/parser/Expression.js.map +1 -1
  95. package/dist/parser/Parser.Class.spec.js +25 -0
  96. package/dist/parser/Parser.Class.spec.js.map +1 -1
  97. package/dist/parser/Parser.d.ts +4 -0
  98. package/dist/parser/Parser.js +117 -7
  99. package/dist/parser/Parser.js.map +1 -1
  100. package/dist/parser/Parser.spec.js +200 -1
  101. package/dist/parser/Parser.spec.js.map +1 -1
  102. package/dist/parser/Statement.d.ts +32 -1
  103. package/dist/parser/Statement.js +126 -62
  104. package/dist/parser/Statement.js.map +1 -1
  105. package/dist/parser/tests/statement/ConstStatement.spec.js +238 -0
  106. package/dist/parser/tests/statement/ConstStatement.spec.js.map +1 -1
  107. package/dist/roku-types/data.json +422 -64
  108. package/dist/roku-types/index.d.ts +50 -0
  109. package/dist/types/ArrayType.js +3 -0
  110. package/dist/types/ArrayType.js.map +1 -1
  111. package/dist/types/BscType.d.ts +4 -3
  112. package/dist/types/BscType.js +2 -4
  113. package/dist/types/BscType.js.map +1 -1
  114. package/dist/types/BscTypeKind.d.ts +2 -0
  115. package/dist/types/BscTypeKind.js +2 -0
  116. package/dist/types/BscTypeKind.js.map +1 -1
  117. package/dist/types/CallFuncableType.d.ts +24 -0
  118. package/dist/types/CallFuncableType.js +91 -0
  119. package/dist/types/CallFuncableType.js.map +1 -0
  120. package/dist/types/ComponentType.d.ts +3 -15
  121. package/dist/types/ComponentType.js +2 -56
  122. package/dist/types/ComponentType.js.map +1 -1
  123. package/dist/types/DoubleType.js +1 -1
  124. package/dist/types/DoubleType.js.map +1 -1
  125. package/dist/types/FloatType.js +1 -1
  126. package/dist/types/FloatType.js.map +1 -1
  127. package/dist/types/InlineInterfaceType.d.ts +5 -0
  128. package/dist/types/InlineInterfaceType.js +17 -0
  129. package/dist/types/InlineInterfaceType.js.map +1 -0
  130. package/dist/types/IntegerType.js +1 -1
  131. package/dist/types/IntegerType.js.map +1 -1
  132. package/dist/types/InterfaceType.d.ts +2 -2
  133. package/dist/types/InterfaceType.js +5 -4
  134. package/dist/types/InterfaceType.js.map +1 -1
  135. package/dist/types/LongIntegerType.js +1 -1
  136. package/dist/types/LongIntegerType.js.map +1 -1
  137. package/dist/types/ObjectType.d.ts +1 -0
  138. package/dist/types/ObjectType.js +3 -0
  139. package/dist/types/ObjectType.js.map +1 -1
  140. package/dist/types/ReferenceType.d.ts +3 -1
  141. package/dist/types/ReferenceType.js +41 -2
  142. package/dist/types/ReferenceType.js.map +1 -1
  143. package/dist/types/TypeStatementType.d.ts +18 -0
  144. package/dist/types/TypeStatementType.js +45 -0
  145. package/dist/types/TypeStatementType.js.map +1 -0
  146. package/dist/types/roFunctionType.d.ts +11 -0
  147. package/dist/types/roFunctionType.js +37 -0
  148. package/dist/types/roFunctionType.js.map +1 -0
  149. package/dist/types/roFunctionType.spec.d.ts +1 -0
  150. package/dist/types/roFunctionType.spec.js +20 -0
  151. package/dist/types/roFunctionType.spec.js.map +1 -0
  152. package/dist/util.d.ts +3 -94
  153. package/dist/util.js +53 -303
  154. package/dist/util.js.map +1 -1
  155. package/dist/validators/ClassValidator.js +1 -1
  156. package/dist/validators/ClassValidator.js.map +1 -1
  157. package/package.json +3 -3
package/dist/util.js CHANGED
@@ -8,7 +8,6 @@ const path = require("path");
8
8
  const roku_deploy_1 = require("roku-deploy");
9
9
  const vscode_languageserver_1 = require("vscode-languageserver");
10
10
  const vscode_uri_1 = require("vscode-uri");
11
- const xml2js = require("xml2js");
12
11
  const DiagnosticMessages_1 = require("./DiagnosticMessages");
13
12
  const interfaces_1 = require("./interfaces");
14
13
  const BooleanType_1 = require("./types/BooleanType");
@@ -125,29 +124,6 @@ class Util {
125
124
  //ensure every path has the leading pkg:/
126
125
  return 'pkg:/' + pkgPath.replace(/^pkg:\//i, '');
127
126
  }
128
- /**
129
- * Determine if the given path starts with a protocol
130
- */
131
- startsWithProtocol(path) {
132
- return !!/^[-a-z]+:\//i.exec(path);
133
- }
134
- /**
135
- * Given a pkg path of any kind, transform it to a roku-specific pkg path (i.e. "pkg:/some/path.brs")
136
- * @deprecated use `sanitizePkgPath instead. Will be removed in v1
137
- */
138
- getRokuPkgPath(pkgPath) {
139
- return this.sanitizePkgPath(pkgPath);
140
- }
141
- /**
142
- * Given a path to a file/directory, replace all path separators with the current system's version.
143
- */
144
- pathSepNormalize(filePath, separator) {
145
- if (!filePath) {
146
- return filePath;
147
- }
148
- separator = separator ? separator : path.sep;
149
- return filePath.replace(/[\\/]+/g, separator);
150
- }
151
127
  /**
152
128
  * Find the path to the config file.
153
129
  * If the config file path doesn't exist
@@ -247,18 +223,15 @@ class Util {
247
223
  result._ancestors = parentProjectPaths;
248
224
  }
249
225
  //make any paths in the config absolute (relative to the CURRENT config file)
250
- if (result.outFile) {
251
- result.outFile = path.resolve(projectFileCwd, result.outFile);
252
- }
253
226
  if (result.rootDir) {
254
227
  result.rootDir = path.resolve(projectFileCwd, result.rootDir);
255
228
  }
229
+ if (result.outDir) {
230
+ result.outDir = path.resolve(projectFileCwd, result.outDir);
231
+ }
256
232
  if (result.cwd) {
257
233
  result.cwd = path.resolve(projectFileCwd, result.cwd);
258
234
  }
259
- if (result.stagingDir) {
260
- result.stagingDir = path.resolve(projectFileCwd, result.stagingDir);
261
- }
262
235
  if (result.sourceRoot && result.resolveSourceRoot) {
263
236
  result.sourceRoot = path.resolve(projectFileCwd, result.sourceRoot);
264
237
  }
@@ -284,35 +257,6 @@ class Util {
284
257
  }
285
258
  collection[key] = [...result];
286
259
  }
287
- /**
288
- * Do work within the scope of a changed current working directory
289
- * @param targetCwd the cwd where the work should be performed
290
- * @param callback a function to call when the cwd has been changed to `targetCwd`
291
- */
292
- cwdWork(targetCwd, callback) {
293
- let originalCwd = process.cwd();
294
- if (targetCwd) {
295
- process.chdir(targetCwd);
296
- }
297
- let result;
298
- let err;
299
- try {
300
- result = callback();
301
- }
302
- catch (e) {
303
- err = e;
304
- }
305
- if (targetCwd) {
306
- process.chdir(originalCwd);
307
- }
308
- if (err) {
309
- throw err;
310
- }
311
- else {
312
- //justification: `result` is set as long as `err` is not set and vice versa
313
- return result;
314
- }
315
- }
316
260
  /**
317
261
  * Given a BsConfig object, start with defaults,
318
262
  * merge with bsconfig.json and the provided options.
@@ -344,38 +288,55 @@ class Util {
344
288
  * @param config a bsconfig object to use as the baseline for the resulting config
345
289
  */
346
290
  normalizeConfig(config) {
347
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
291
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
348
292
  config = config !== null && config !== void 0 ? config : {};
349
293
  const cwd = (_a = config.cwd) !== null && _a !== void 0 ? _a : process.cwd();
350
- const rootFolderName = path.basename(cwd);
351
- const retainStagingDir = ((_b = config.retainStagingDir) !== null && _b !== void 0 ? _b : config.retainStagingDir) === true ? true : false;
352
294
  let logLevel = logging_1.LogLevel.log;
353
295
  if (typeof config.logLevel === 'string') {
354
- logLevel = (_c = logging_1.LogLevel[config.logLevel.toLowerCase()]) !== null && _c !== void 0 ? _c : logging_1.LogLevel.log;
296
+ logLevel = (_b = logging_1.LogLevel[config.logLevel.toLowerCase()]) !== null && _b !== void 0 ? _b : logging_1.LogLevel.log;
355
297
  }
356
- let bslibDestinationDir = (_d = config.bslibDestinationDir) !== null && _d !== void 0 ? _d : 'source';
298
+ let bslibDestinationDir = (_c = config.bslibDestinationDir) !== null && _c !== void 0 ? _c : 'source';
357
299
  if (bslibDestinationDir !== 'source') {
358
300
  // strip leading and trailing slashes
359
301
  bslibDestinationDir = bslibDestinationDir.replace(/^(\/*)(.*?)(\/*)$/, '$2');
360
302
  }
303
+ let noEmit;
304
+ if ('noEmit' in config) {
305
+ noEmit = config.noEmit;
306
+ }
307
+ else if ('copyToStaging' in config) {
308
+ noEmit = !config.copyToStaging; //invert the old value
309
+ }
310
+ else {
311
+ noEmit = false; //default case
312
+ }
313
+ let outDir;
314
+ if ('outDir' in config) {
315
+ outDir = (_d = config.outDir) !== null && _d !== void 0 ? _d : './out';
316
+ }
317
+ else if ('stagingFolderPath' in config) {
318
+ outDir = config.stagingFolderPath;
319
+ }
320
+ else if ('stagingDir' in config) {
321
+ outDir = config.stagingDir;
322
+ }
323
+ else {
324
+ outDir = './out'; //default case
325
+ }
361
326
  const configWithDefaults = {
362
327
  cwd: cwd,
363
- deploy: config.deploy === true ? true : false,
364
328
  //use default files array from rokuDeploy
365
329
  files: (_e = config.files) !== null && _e !== void 0 ? _e : [...roku_deploy_1.DefaultFiles],
366
- createPackage: config.createPackage === false ? false : true,
367
- outFile: (_f = config.outFile) !== null && _f !== void 0 ? _f : `./out/${rootFolderName}.zip`,
330
+ outDir: outDir,
368
331
  sourceMap: config.sourceMap === true,
369
- username: (_g = config.username) !== null && _g !== void 0 ? _g : 'rokudev',
370
332
  watch: config.watch === true ? true : false,
371
333
  emitFullPaths: config.emitFullPaths === true ? true : false,
372
- retainStagingDir: retainStagingDir,
373
- copyToStaging: config.copyToStaging === false ? false : true,
374
- ignoreErrorCodes: (_h = config.ignoreErrorCodes) !== null && _h !== void 0 ? _h : [],
375
- diagnosticSeverityOverrides: (_j = config.diagnosticSeverityOverrides) !== null && _j !== void 0 ? _j : {},
376
- diagnosticFilters: (_k = config.diagnosticFilters) !== null && _k !== void 0 ? _k : [],
334
+ noEmit: noEmit,
335
+ ignoreErrorCodes: (_f = config.ignoreErrorCodes) !== null && _f !== void 0 ? _f : [],
336
+ diagnosticSeverityOverrides: (_g = config.diagnosticSeverityOverrides) !== null && _g !== void 0 ? _g : {},
337
+ diagnosticFilters: (_h = config.diagnosticFilters) !== null && _h !== void 0 ? _h : [],
377
338
  diagnosticFiltersV0Compatibility: config.diagnosticFiltersV0Compatibility === true ? true : false,
378
- plugins: (_l = config.plugins) !== null && _l !== void 0 ? _l : [],
339
+ plugins: (_j = config.plugins) !== null && _j !== void 0 ? _j : [],
379
340
  pruneEmptyCodeFiles: config.pruneEmptyCodeFiles === true ? true : false,
380
341
  autoImportComponentScript: config.autoImportComponentScript === true ? true : false,
381
342
  showDiagnosticsInConsole: config.showDiagnosticsInConsole === false ? false : true,
@@ -427,12 +388,6 @@ class Util {
427
388
  }
428
389
  return result;
429
390
  }
430
- /**
431
- * Split a file by newline characters (LF or CRLF)
432
- */
433
- getLines(text) {
434
- return text.split(/\r?\n/);
435
- }
436
391
  /**
437
392
  * Given an absolute path to a source file, and a target path,
438
393
  * compute the pkg path for the target relative to the source file's location
@@ -713,37 +668,6 @@ class Util {
713
668
  getSgNodeTypeName(sgNodeName) {
714
669
  return 'roSGNode' + sgNodeName;
715
670
  }
716
- /**
717
- * Parse an xml file and get back a javascript object containing its results
718
- */
719
- parseXml(text) {
720
- return new Promise((resolve, reject) => {
721
- xml2js.parseString(text, (err, data) => {
722
- if (err) {
723
- reject(err);
724
- }
725
- else {
726
- resolve(data);
727
- }
728
- });
729
- });
730
- }
731
- propertyCount(object) {
732
- let count = 0;
733
- for (let key in object) {
734
- if (object.hasOwnProperty(key)) {
735
- count++;
736
- }
737
- }
738
- return count;
739
- }
740
- padLeft(subject, totalLength, char) {
741
- totalLength = totalLength > 1000 ? 1000 : totalLength;
742
- while (subject.length < totalLength) {
743
- subject = char + subject;
744
- }
745
- return subject;
746
- }
747
671
  /**
748
672
  * Force the drive letter to lower case
749
673
  */
@@ -773,21 +697,6 @@ class Util {
773
697
  return subject;
774
698
  }
775
699
  }
776
- /**
777
- * Determine if two arrays containing primitive values are equal.
778
- * This considers order and compares by equality.
779
- */
780
- areArraysEqual(arr1, arr2) {
781
- if (arr1.length !== arr2.length) {
782
- return false;
783
- }
784
- for (let i = 0; i < arr1.length; i++) {
785
- if (arr1[i] !== arr2[i]) {
786
- return false;
787
- }
788
- }
789
- return true;
790
- }
791
700
  /**
792
701
  * Does the string appear to be a uri (i.e. does it start with `file:`)
793
702
  */
@@ -826,19 +735,6 @@ class Util {
826
735
  const normalizedPath = path.normalize(parsedPath);
827
736
  return normalizedPath;
828
737
  }
829
- /**
830
- * Get the outDir from options, taking into account cwd and absolute outFile paths
831
- */
832
- getOutDir(options) {
833
- options = this.normalizeConfig(options);
834
- let cwd = path.normalize(options.cwd ? options.cwd : process.cwd());
835
- if (path.isAbsolute(options.outFile)) {
836
- return path.dirname(options.outFile);
837
- }
838
- else {
839
- return path.normalize(path.join(cwd, path.dirname(options.outFile)));
840
- }
841
- }
842
738
  /**
843
739
  * Get paths to all files on disc that match this project's source list
844
740
  */
@@ -862,31 +758,6 @@ class Util {
862
758
  return undefined;
863
759
  }
864
760
  }
865
- /**
866
- * Walks up the chain to find the closest bsconfig.json file
867
- */
868
- async findClosestConfigFile(currentPath) {
869
- //make the path absolute
870
- currentPath = path.resolve(path.normalize(currentPath));
871
- let previousPath;
872
- //using ../ on the root of the drive results in the same file path, so that's how we know we reached the top
873
- while (previousPath !== currentPath) {
874
- previousPath = currentPath;
875
- let bsPath = path.join(currentPath, 'bsconfig.json');
876
- let brsPath = path.join(currentPath, 'brsconfig.json');
877
- if (await this.pathExists(bsPath)) {
878
- return bsPath;
879
- }
880
- else if (await this.pathExists(brsPath)) {
881
- return brsPath;
882
- }
883
- else {
884
- //walk upwards one directory
885
- currentPath = path.resolve(path.join(currentPath, '../'));
886
- }
887
- }
888
- //got to the root path, no config file exists
889
- }
890
761
  /**
891
762
  * Set a timeout for the specified milliseconds, and resolve the promise once the timeout is finished.
892
763
  * @param milliseconds the minimum number of milliseconds to sleep for
@@ -902,14 +773,6 @@ class Util {
902
773
  }
903
774
  });
904
775
  }
905
- /**
906
- * Given an array, map and then flatten
907
- * @param array the array to flatMap over
908
- * @param callback a function that is called for every array item
909
- */
910
- flatMap(array, callback) {
911
- return Array.prototype.concat.apply([], array.map(callback));
912
- }
913
776
  /**
914
777
  * Determines if the position is greater than the range. This means
915
778
  * the position does not touch the range, and has a position greater than the end
@@ -954,28 +817,6 @@ class Util {
954
817
  return undefined;
955
818
  }
956
819
  }
957
- /**
958
- * Get a location object back by extracting location information from other objects that contain location
959
- */
960
- getRange(startObj, endObj) {
961
- var _a, _b;
962
- if (!(startObj === null || startObj === void 0 ? void 0 : startObj.range) || !(endObj === null || endObj === void 0 ? void 0 : endObj.range)) {
963
- return undefined;
964
- }
965
- return exports.util.createRangeFromPositions((_a = startObj.range) === null || _a === void 0 ? void 0 : _a.start, (_b = endObj.range) === null || _b === void 0 ? void 0 : _b.end);
966
- }
967
- /**
968
- * If the two items both start on the same line
969
- */
970
- sameStartLine(first, second) {
971
- if (first && second && (first.range !== undefined) && (second.range !== undefined) &&
972
- first.range.start.line === second.range.start.line) {
973
- return true;
974
- }
975
- else {
976
- return false;
977
- }
978
- }
979
820
  /**
980
821
  * If the two items have lines that touch
981
822
  */
@@ -992,18 +833,6 @@ class Util {
992
833
  return false;
993
834
  }
994
835
  }
995
- /**
996
- * Given text with (or without) dots separating text, get the rightmost word.
997
- * (i.e. given "A.B.C", returns "C". or "B" returns "B because there's no dot)
998
- */
999
- getTextAfterFinalDot(name) {
1000
- if (name) {
1001
- let parts = name.split('.');
1002
- if (parts.length > 0) {
1003
- return parts[parts.length - 1];
1004
- }
1005
- }
1006
- }
1007
836
  /**
1008
837
  * Find a script import that the current position touches, or undefined if not found
1009
838
  */
@@ -1276,17 +1105,6 @@ class Util {
1276
1105
  character: character
1277
1106
  };
1278
1107
  }
1279
- /**
1280
- * Convert a list of tokens into a string, including their leading whitespace
1281
- */
1282
- tokensToString(tokens) {
1283
- let result = '';
1284
- //skip iterating the final token
1285
- for (let token of tokens) {
1286
- result += token.leadingWhitespace + token.text;
1287
- }
1288
- return result;
1289
- }
1290
1108
  /**
1291
1109
  * Convert a token into a BscType
1292
1110
  */
@@ -1549,12 +1367,12 @@ class Util {
1549
1367
  let hasInvalid = (0, reflection_1.isInvalidTypeLike)(leftType) || (0, reflection_1.isInvalidTypeLike)(rightType);
1550
1368
  let hasDynamic = (0, reflection_1.isDynamicType)(leftType) || (0, reflection_1.isDynamicType)(rightType);
1551
1369
  let bothDynamic = (0, reflection_1.isDynamicType)(leftType) && (0, reflection_1.isDynamicType)(rightType);
1552
- let bothNumbers = (0, reflection_1.isNumberType)(leftType) && (0, reflection_1.isNumberType)(rightType);
1553
- let hasNumber = (0, reflection_1.isNumberType)(leftType) || (0, reflection_1.isNumberType)(rightType);
1370
+ let bothNumbers = (0, reflection_1.isNumberTypeLike)(leftType) && (0, reflection_1.isNumberTypeLike)(rightType);
1371
+ let hasNumber = (0, reflection_1.isNumberTypeLike)(leftType) || (0, reflection_1.isNumberTypeLike)(rightType);
1554
1372
  let bothStrings = (0, reflection_1.isStringTypeLike)(leftType) && (0, reflection_1.isStringTypeLike)(rightType);
1555
1373
  let hasString = (0, reflection_1.isStringTypeLike)(leftType) || (0, reflection_1.isStringTypeLike)(rightType);
1556
1374
  let hasBoolean = (0, reflection_1.isBooleanTypeLike)(leftType) || (0, reflection_1.isBooleanTypeLike)(rightType);
1557
- let eitherBooleanOrNum = ((0, reflection_1.isNumberType)(leftType) || (0, reflection_1.isBooleanTypeLike)(leftType)) && ((0, reflection_1.isNumberType)(rightType) || (0, reflection_1.isBooleanTypeLike)(rightType));
1375
+ let eitherBooleanOrNum = ((0, reflection_1.isNumberTypeLike)(leftType) || (0, reflection_1.isBooleanTypeLike)(leftType)) && ((0, reflection_1.isNumberTypeLike)(rightType) || (0, reflection_1.isBooleanTypeLike)(rightType));
1558
1376
  let leftIsPrimitive = (0, reflection_1.isPrimitiveType)(leftType);
1559
1377
  let rightIsPrimitive = (0, reflection_1.isPrimitiveType)(rightType);
1560
1378
  let hasPrimitive = leftIsPrimitive || rightIsPrimitive;
@@ -1775,7 +1593,7 @@ class Util {
1775
1593
  // Math operators
1776
1594
  case TokenKind_1.TokenKind.Plus: // (`num = +num` is valid syntax)
1777
1595
  case TokenKind_1.TokenKind.Minus:
1778
- if ((0, reflection_1.isNumberType)(exprType)) {
1596
+ if ((0, reflection_1.isNumberTypeLike)(exprType)) {
1779
1597
  // a negative number will be the same type, eg, double->double, int->int, etc.
1780
1598
  return this.getUnboxedType(exprType);
1781
1599
  }
@@ -1784,7 +1602,7 @@ class Util {
1784
1602
  if ((0, reflection_1.isBooleanTypeLike)(exprType)) {
1785
1603
  return BooleanType_1.BooleanType.instance;
1786
1604
  }
1787
- else if ((0, reflection_1.isNumberType)(exprType)) {
1605
+ else if ((0, reflection_1.isNumberTypeLike)(exprType)) {
1788
1606
  //numbers can be "notted"
1789
1607
  // by default they go to ints, except longints, which stay that way
1790
1608
  if ((0, reflection_1.isLongIntegerTypeLike)(exprType)) {
@@ -2011,19 +1829,6 @@ class Util {
2011
1829
  }
2012
1830
  return result;
2013
1831
  }
2014
- /**
2015
- * Get the first locatable item found at the specified position
2016
- * @param locatables an array of items that have a `range` property
2017
- * @param position the position that the locatable must contain
2018
- */
2019
- getFirstLocatableAt(locatables, position) {
2020
- var _a;
2021
- for (let token of locatables) {
2022
- if (exports.util.rangeContains((_a = token.location) === null || _a === void 0 ? void 0 : _a.range, position)) {
2023
- return token;
2024
- }
2025
- }
2026
- }
2027
1832
  /**
2028
1833
  * Sort an array of objects that have a Range
2029
1834
  */
@@ -2068,26 +1873,6 @@ class Util {
2068
1873
  return 0;
2069
1874
  });
2070
1875
  }
2071
- /**
2072
- * Split the given text and return ranges for each chunk.
2073
- * Only works for single-line strings
2074
- */
2075
- splitGetRange(separator, text, range) {
2076
- const chunks = text.split(separator);
2077
- const result = [];
2078
- let offset = 0;
2079
- for (let chunk of chunks) {
2080
- //only keep nonzero chunks
2081
- if (chunk.length > 0) {
2082
- result.push({
2083
- text: chunk,
2084
- range: this.createRange(range.start.line, range.start.character + offset, range.end.line, range.start.character + offset + chunk.length)
2085
- });
2086
- }
2087
- offset += chunk.length + separator.length;
2088
- }
2089
- return result;
2090
- }
2091
1876
  /**
2092
1877
  * Wrap the given code in a markdown code fence (with the language)
2093
1878
  */
@@ -2159,16 +1944,6 @@ class Util {
2159
1944
  return result;
2160
1945
  /* eslint-enable no-var */
2161
1946
  }
2162
- stringJoin(strings, separator) {
2163
- var _a;
2164
- // eslint-disable-next-line no-var
2165
- var result = (_a = strings[0]) !== null && _a !== void 0 ? _a : '';
2166
- // eslint-disable-next-line no-var
2167
- for (var i = 1; i < strings.length; i++) {
2168
- result += separator + strings[i];
2169
- }
2170
- return result;
2171
- }
2172
1947
  /**
2173
1948
  * Break an expression into each part.
2174
1949
  */
@@ -2192,44 +1967,6 @@ class Util {
2192
1967
  }
2193
1968
  return parts;
2194
1969
  }
2195
- /**
2196
- * Break an expression into each part, and return any VariableExpression or DottedGet expresisons from left-to-right.
2197
- */
2198
- getDottedGetPath(expression) {
2199
- let parts = [];
2200
- let nextPart = expression;
2201
- loop: while (nextPart) {
2202
- switch (nextPart === null || nextPart === void 0 ? void 0 : nextPart.kind) {
2203
- case AstNode_1.AstNodeKind.DottedGetExpression:
2204
- parts.push(nextPart);
2205
- nextPart = nextPart.obj;
2206
- continue;
2207
- case AstNode_1.AstNodeKind.IndexedGetExpression:
2208
- case AstNode_1.AstNodeKind.XmlAttributeGetExpression:
2209
- nextPart = nextPart.obj;
2210
- parts = [];
2211
- continue;
2212
- case AstNode_1.AstNodeKind.CallExpression:
2213
- case AstNode_1.AstNodeKind.CallfuncExpression:
2214
- nextPart = nextPart.callee;
2215
- parts = [];
2216
- continue;
2217
- case AstNode_1.AstNodeKind.NewExpression:
2218
- nextPart = nextPart.call.callee;
2219
- parts = [];
2220
- continue;
2221
- case AstNode_1.AstNodeKind.TypeExpression:
2222
- nextPart = nextPart.expression;
2223
- continue;
2224
- case AstNode_1.AstNodeKind.VariableExpression:
2225
- parts.push(nextPart);
2226
- break loop;
2227
- default:
2228
- return [];
2229
- }
2230
- }
2231
- return parts.reverse();
2232
- }
2233
1970
  /**
2234
1971
  * Returns an integer if valid, or undefined. Eliminates checking for NaN
2235
1972
  */
@@ -2426,6 +2163,19 @@ class Util {
2426
2163
  crossedCallFunc: crossedCallFunc
2427
2164
  };
2428
2165
  }
2166
+ getCircularReferenceDiagnosticDetail(circularReferenceInfo, defaultName = '') {
2167
+ if (!circularReferenceInfo || !circularReferenceInfo.referenceChainNames) {
2168
+ if (defaultName) {
2169
+ return [defaultName];
2170
+ }
2171
+ return [];
2172
+ }
2173
+ if (circularReferenceInfo.referenceChainNames[0] === circularReferenceInfo.referenceChainNames[circularReferenceInfo.referenceChainNames.length - 1]) {
2174
+ // last element is same as first it will read okay
2175
+ return circularReferenceInfo.referenceChainNames;
2176
+ }
2177
+ return [...circularReferenceInfo.referenceChainNames, circularReferenceInfo.referenceChainNames[0]];
2178
+ }
2429
2179
  isInTypeExpression(expression) {
2430
2180
  //TODO: this is much faster than node.findAncestor(), but may need to be updated for "complicated" type expressions
2431
2181
  if ((0, reflection_1.isTypeExpression)(expression) ||