brighterscript 1.0.0-alpha.47 → 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.
- package/README.md +7 -10
- package/bsconfig.schema.json +34 -7
- package/dist/AstValidationSegmenter.js +21 -3
- package/dist/AstValidationSegmenter.js.map +1 -1
- package/dist/BsConfig.d.ts +6 -35
- package/dist/CrossScopeValidator.d.ts +1 -0
- package/dist/CrossScopeValidator.js +28 -4
- package/dist/CrossScopeValidator.js.map +1 -1
- package/dist/DiagnosticMessages.d.ts +1 -1
- package/dist/DiagnosticMessages.js +20 -6
- package/dist/DiagnosticMessages.js.map +1 -1
- package/dist/LanguageServer.d.ts +22 -6
- package/dist/LanguageServer.js +62 -25
- package/dist/LanguageServer.js.map +1 -1
- package/dist/PluginInterface.js +4 -1
- package/dist/PluginInterface.js.map +1 -1
- package/dist/Program.d.ts +9 -3
- package/dist/Program.js +111 -74
- package/dist/Program.js.map +1 -1
- package/dist/ProgramBuilder.d.ts +0 -2
- package/dist/ProgramBuilder.js +10 -28
- package/dist/ProgramBuilder.js.map +1 -1
- package/dist/SymbolTable.js +3 -2
- package/dist/SymbolTable.js.map +1 -1
- package/dist/astUtils/reflection.d.ts +14 -2
- package/dist/astUtils/reflection.js +70 -18
- package/dist/astUtils/reflection.js.map +1 -1
- package/dist/astUtils/visitors.d.ts +2 -1
- package/dist/astUtils/visitors.js.map +1 -1
- package/dist/bscPlugin/CallExpressionInfo.js +9 -3
- package/dist/bscPlugin/CallExpressionInfo.js.map +1 -1
- package/dist/bscPlugin/completions/CompletionsProcessor.js +3 -0
- package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -1
- package/dist/bscPlugin/completions/CompletionsProcessor.spec.js +34 -1
- package/dist/bscPlugin/completions/CompletionsProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/hover/HoverProcessor.spec.js +31 -0
- package/dist/bscPlugin/hover/HoverProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +10 -4
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -1
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js +17 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.d.ts +5 -0
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js +71 -3
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js.map +1 -1
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js +7 -7
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/validation/BrsFileValidator.js +43 -14
- package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -1
- package/dist/bscPlugin/validation/BrsFileValidator.spec.js +99 -0
- package/dist/bscPlugin/validation/BrsFileValidator.spec.js.map +1 -1
- package/dist/bscPlugin/validation/ScopeValidator.d.ts +1 -0
- package/dist/bscPlugin/validation/ScopeValidator.js +19 -4
- package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -1
- package/dist/bscPlugin/validation/ScopeValidator.spec.js +372 -0
- package/dist/bscPlugin/validation/ScopeValidator.spec.js.map +1 -1
- package/dist/cli.js +11 -18
- package/dist/cli.js.map +1 -1
- package/dist/files/BrsFile.Class.spec.js +336 -200
- package/dist/files/BrsFile.Class.spec.js.map +1 -1
- package/dist/files/BrsFile.spec.js +168 -10
- package/dist/files/BrsFile.spec.js.map +1 -1
- package/dist/files/XmlFile.d.ts +7 -0
- package/dist/files/XmlFile.js +36 -0
- package/dist/files/XmlFile.js.map +1 -1
- package/dist/files/XmlFile.spec.js +7 -9
- package/dist/files/XmlFile.spec.js.map +1 -1
- package/dist/files/tests/imports.spec.js +3 -3
- package/dist/files/tests/imports.spec.js.map +1 -1
- package/dist/files/tests/optionalChaning.spec.js +1 -1
- package/dist/files/tests/optionalChaning.spec.js.map +1 -1
- package/dist/interfaces.d.ts +12 -4
- package/dist/interfaces.js.map +1 -1
- package/dist/lexer/Lexer.spec.js +12 -2
- package/dist/lexer/Lexer.spec.js.map +1 -1
- package/dist/lexer/TokenKind.js +6 -3
- package/dist/lexer/TokenKind.js.map +1 -1
- package/dist/lsp/LspProject.d.ts +17 -9
- package/dist/lsp/Project.d.ts +8 -7
- package/dist/lsp/Project.js +21 -23
- package/dist/lsp/Project.js.map +1 -1
- package/dist/lsp/Project.spec.js +44 -12
- package/dist/lsp/Project.spec.js.map +1 -1
- package/dist/lsp/ProjectManager.d.ts +31 -10
- package/dist/lsp/ProjectManager.js +130 -60
- package/dist/lsp/ProjectManager.js.map +1 -1
- package/dist/lsp/ProjectManager.spec.js +245 -115
- package/dist/lsp/ProjectManager.spec.js.map +1 -1
- package/dist/lsp/worker/WorkerThreadProject.d.ts +6 -7
- package/dist/lsp/worker/WorkerThreadProject.js +27 -21
- package/dist/lsp/worker/WorkerThreadProject.js.map +1 -1
- package/dist/lsp/worker/WorkerThreadProject.spec.js +4 -1
- package/dist/lsp/worker/WorkerThreadProject.spec.js.map +1 -1
- package/dist/lsp/worker/run.d.ts +1 -0
- package/dist/lsp/worker/run.js +14 -0
- package/dist/lsp/worker/run.js.map +1 -0
- package/dist/parser/AstNode.d.ts +8 -1
- package/dist/parser/AstNode.js +9 -0
- package/dist/parser/AstNode.js.map +1 -1
- package/dist/parser/AstNode.spec.js +1 -1
- package/dist/parser/AstNode.spec.js.map +1 -1
- package/dist/parser/Expression.d.ts +43 -0
- package/dist/parser/Expression.js +120 -7
- package/dist/parser/Expression.js.map +1 -1
- package/dist/parser/Parser.Class.spec.js +25 -0
- package/dist/parser/Parser.Class.spec.js.map +1 -1
- package/dist/parser/Parser.d.ts +4 -0
- package/dist/parser/Parser.js +117 -7
- package/dist/parser/Parser.js.map +1 -1
- package/dist/parser/Parser.spec.js +200 -1
- package/dist/parser/Parser.spec.js.map +1 -1
- package/dist/parser/Statement.d.ts +32 -1
- package/dist/parser/Statement.js +128 -64
- package/dist/parser/Statement.js.map +1 -1
- package/dist/parser/tests/statement/ConstStatement.spec.js +238 -0
- package/dist/parser/tests/statement/ConstStatement.spec.js.map +1 -1
- package/dist/roku-types/data.json +422 -64
- package/dist/roku-types/index.d.ts +50 -0
- package/dist/types/ArrayType.js +3 -0
- package/dist/types/ArrayType.js.map +1 -1
- package/dist/types/BscType.d.ts +4 -3
- package/dist/types/BscType.js +2 -4
- package/dist/types/BscType.js.map +1 -1
- package/dist/types/BscTypeKind.d.ts +2 -0
- package/dist/types/BscTypeKind.js +2 -0
- package/dist/types/BscTypeKind.js.map +1 -1
- package/dist/types/CallFuncableType.d.ts +24 -0
- package/dist/types/CallFuncableType.js +91 -0
- package/dist/types/CallFuncableType.js.map +1 -0
- package/dist/types/ComponentType.d.ts +3 -15
- package/dist/types/ComponentType.js +2 -56
- package/dist/types/ComponentType.js.map +1 -1
- package/dist/types/DoubleType.js +1 -1
- package/dist/types/DoubleType.js.map +1 -1
- package/dist/types/FloatType.js +1 -1
- package/dist/types/FloatType.js.map +1 -1
- package/dist/types/InlineInterfaceType.d.ts +5 -0
- package/dist/types/InlineInterfaceType.js +17 -0
- package/dist/types/InlineInterfaceType.js.map +1 -0
- package/dist/types/IntegerType.js +1 -1
- package/dist/types/IntegerType.js.map +1 -1
- package/dist/types/InterfaceType.d.ts +2 -2
- package/dist/types/InterfaceType.js +5 -4
- package/dist/types/InterfaceType.js.map +1 -1
- package/dist/types/LongIntegerType.js +1 -1
- package/dist/types/LongIntegerType.js.map +1 -1
- package/dist/types/ObjectType.d.ts +1 -0
- package/dist/types/ObjectType.js +3 -0
- package/dist/types/ObjectType.js.map +1 -1
- package/dist/types/ReferenceType.d.ts +3 -2
- package/dist/types/ReferenceType.js +54 -22
- package/dist/types/ReferenceType.js.map +1 -1
- package/dist/types/TypeStatementType.d.ts +18 -0
- package/dist/types/TypeStatementType.js +45 -0
- package/dist/types/TypeStatementType.js.map +1 -0
- package/dist/types/UnionType.d.ts +3 -0
- package/dist/types/UnionType.js +7 -0
- package/dist/types/UnionType.js.map +1 -1
- package/dist/types/UnionType.spec.js +43 -0
- package/dist/types/UnionType.spec.js.map +1 -1
- package/dist/types/roFunctionType.d.ts +11 -0
- package/dist/types/roFunctionType.js +37 -0
- package/dist/types/roFunctionType.js.map +1 -0
- package/dist/types/roFunctionType.spec.d.ts +1 -0
- package/dist/types/roFunctionType.spec.js +20 -0
- package/dist/types/roFunctionType.spec.js.map +1 -0
- package/dist/util.d.ts +9 -94
- package/dist/util.js +67 -305
- package/dist/util.js.map +1 -1
- package/dist/validators/ClassValidator.js +1 -1
- package/dist/validators/ClassValidator.js.map +1 -1
- package/package.json +3 -3
|
@@ -14,6 +14,7 @@ const fsExtra = require("fs-extra");
|
|
|
14
14
|
const testHelpers_spec_2 = require("../../testHelpers.spec");
|
|
15
15
|
const reflection_1 = require("../../astUtils/reflection");
|
|
16
16
|
const ScopeValidator_1 = require("./ScopeValidator");
|
|
17
|
+
const logger_1 = require("@rokucommunity/logger");
|
|
17
18
|
describe('ScopeValidator', () => {
|
|
18
19
|
let sinon = sinonImport.createSandbox();
|
|
19
20
|
let program;
|
|
@@ -1713,6 +1714,86 @@ describe('ScopeValidator', () => {
|
|
|
1713
1714
|
]);
|
|
1714
1715
|
});
|
|
1715
1716
|
});
|
|
1717
|
+
describe('inline interfaces', () => {
|
|
1718
|
+
it('allows function param with compatible interface', () => {
|
|
1719
|
+
program.setFile('source/main.bs', `
|
|
1720
|
+
sub takesInline(datum as {name as string})
|
|
1721
|
+
end sub
|
|
1722
|
+
|
|
1723
|
+
sub callsTakesInline()
|
|
1724
|
+
takesInline({age: 123, name: "test"})
|
|
1725
|
+
end sub
|
|
1726
|
+
`);
|
|
1727
|
+
program.validate();
|
|
1728
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
1729
|
+
});
|
|
1730
|
+
it('validates function param with incompatible interface', () => {
|
|
1731
|
+
program.setFile('source/main.bs', `
|
|
1732
|
+
sub takesInline(datum as {name as string})
|
|
1733
|
+
end sub
|
|
1734
|
+
|
|
1735
|
+
sub callsTakesInline()
|
|
1736
|
+
takesInline({name: 123})
|
|
1737
|
+
end sub
|
|
1738
|
+
`);
|
|
1739
|
+
program.validate();
|
|
1740
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
1741
|
+
DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('roAssociativeArray', '{name as string}', {
|
|
1742
|
+
fieldMismatches: [{ name: 'name', expectedType: StringType_1.StringType.instance, actualType: IntegerType_1.IntegerType.instance }]
|
|
1743
|
+
}).message
|
|
1744
|
+
]);
|
|
1745
|
+
});
|
|
1746
|
+
});
|
|
1747
|
+
describe('type statement types', () => {
|
|
1748
|
+
it('allows compatible type statement types to be passed to functions expecting normal types', () => {
|
|
1749
|
+
program.setFile('source/main.bs', `
|
|
1750
|
+
type number = integer or float
|
|
1751
|
+
|
|
1752
|
+
sub takesNumber(x as number)
|
|
1753
|
+
takesInteger(x)
|
|
1754
|
+
end sub
|
|
1755
|
+
|
|
1756
|
+
sub takesInteger(x as integer)
|
|
1757
|
+
print x
|
|
1758
|
+
end sub
|
|
1759
|
+
`);
|
|
1760
|
+
program.validate();
|
|
1761
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
1762
|
+
});
|
|
1763
|
+
it('disallows incompatible type statement types to be passed to functions expecting normal types', () => {
|
|
1764
|
+
program.setFile('source/main.bs', `
|
|
1765
|
+
type whatever = float or string
|
|
1766
|
+
|
|
1767
|
+
sub takesNumber(x as whatever)
|
|
1768
|
+
takesInteger(x)
|
|
1769
|
+
end sub
|
|
1770
|
+
|
|
1771
|
+
sub takesInteger(x as integer)
|
|
1772
|
+
print x
|
|
1773
|
+
end sub
|
|
1774
|
+
`);
|
|
1775
|
+
program.validate();
|
|
1776
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
1777
|
+
DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('whatever', 'integer').message
|
|
1778
|
+
]);
|
|
1779
|
+
});
|
|
1780
|
+
});
|
|
1781
|
+
it('allows using invalid as argument for typed array params', () => {
|
|
1782
|
+
program.setFile('source/main.bs', `
|
|
1783
|
+
sub takesIntArray(arr as integer[])
|
|
1784
|
+
end sub
|
|
1785
|
+
|
|
1786
|
+
sub takesStrArray(arr as string[])
|
|
1787
|
+
end sub
|
|
1788
|
+
|
|
1789
|
+
sub test()
|
|
1790
|
+
takesIntArray(invalid)
|
|
1791
|
+
takesStrArray(invalid)
|
|
1792
|
+
end sub
|
|
1793
|
+
`);
|
|
1794
|
+
program.validate();
|
|
1795
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
1796
|
+
});
|
|
1716
1797
|
});
|
|
1717
1798
|
describe('cannotFindName', () => {
|
|
1718
1799
|
it('finds variables from assignments from member functions of primitive types', () => {
|
|
@@ -2178,6 +2259,42 @@ describe('ScopeValidator', () => {
|
|
|
2178
2259
|
program.validate();
|
|
2179
2260
|
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2180
2261
|
});
|
|
2262
|
+
it('validates accessing a bad member on a type statement type', () => {
|
|
2263
|
+
program.setFile('source/main.bs', `
|
|
2264
|
+
type numberOrString = integer or string
|
|
2265
|
+
|
|
2266
|
+
function test(x as numberOrString)
|
|
2267
|
+
print x.nonExistentMember
|
|
2268
|
+
end function
|
|
2269
|
+
`);
|
|
2270
|
+
program.validate();
|
|
2271
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
2272
|
+
DiagnosticMessages_1.DiagnosticMessages.cannotFindName('nonExistentMember', 'numberOrString.nonExistentMember', 'numberOrString')
|
|
2273
|
+
]);
|
|
2274
|
+
});
|
|
2275
|
+
describe('inline interfaces', () => {
|
|
2276
|
+
it('finds members of inline interface', () => {
|
|
2277
|
+
program.setFile('source/main.bs', `
|
|
2278
|
+
sub takesInline(datum as {name as string})
|
|
2279
|
+
print datum.name.split(",")
|
|
2280
|
+
end sub
|
|
2281
|
+
|
|
2282
|
+
`);
|
|
2283
|
+
program.validate();
|
|
2284
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2285
|
+
});
|
|
2286
|
+
it('validates using invalid member name', () => {
|
|
2287
|
+
program.setFile('source/main.bs', `
|
|
2288
|
+
sub takesInline(datum as {name as string})
|
|
2289
|
+
print datum.notThere.split(",")
|
|
2290
|
+
end sub
|
|
2291
|
+
`);
|
|
2292
|
+
program.validate();
|
|
2293
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
2294
|
+
DiagnosticMessages_1.DiagnosticMessages.cannotFindName('notThere', '{name as string}.notThere', '{name as string}')
|
|
2295
|
+
]);
|
|
2296
|
+
});
|
|
2297
|
+
});
|
|
2181
2298
|
});
|
|
2182
2299
|
describe('itemCannotBeUsedAsVariable', () => {
|
|
2183
2300
|
it('detects assigning to a member of a namespace outside the namespace', () => {
|
|
@@ -2693,6 +2810,124 @@ describe('ScopeValidator', () => {
|
|
|
2693
2810
|
program.validate();
|
|
2694
2811
|
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2695
2812
|
});
|
|
2813
|
+
it('allows returning a function call', () => {
|
|
2814
|
+
const spy = sinon.spy(logger_1.Logger.prototype, 'error');
|
|
2815
|
+
program.setFile('source/main.bs', `
|
|
2816
|
+
function abc(func as function) as dynamic
|
|
2817
|
+
return func()
|
|
2818
|
+
end function
|
|
2819
|
+
`);
|
|
2820
|
+
program.validate();
|
|
2821
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2822
|
+
(0, chai_1.expect)(spy.getCalls().map(x => { var _a, _b; return (_b = (_a = x.args) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.toString(); }).filter(x => x === null || x === void 0 ? void 0 : x.includes('Error when calling plugin'))).to.eql([]);
|
|
2823
|
+
});
|
|
2824
|
+
it('allows returning a roFunction call', () => {
|
|
2825
|
+
const spy = sinon.spy(logger_1.Logger.prototype, 'error');
|
|
2826
|
+
program.setFile('source/main.bs', `
|
|
2827
|
+
function abc(func as roFunction) as dynamic
|
|
2828
|
+
return func()
|
|
2829
|
+
end function
|
|
2830
|
+
`);
|
|
2831
|
+
program.validate();
|
|
2832
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2833
|
+
(0, chai_1.expect)(spy.getCalls().map(x => { var _a, _b; return (_b = (_a = x.args) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.toString(); }).filter(x => x === null || x === void 0 ? void 0 : x.includes('Error when calling plugin'))).to.eql([]);
|
|
2834
|
+
});
|
|
2835
|
+
it('allows returning a call on an object type', () => {
|
|
2836
|
+
const spy = sinon.spy(logger_1.Logger.prototype, 'error');
|
|
2837
|
+
program.setFile('source/main.bs', `
|
|
2838
|
+
function abc(func as object) as dynamic
|
|
2839
|
+
return func()
|
|
2840
|
+
end function
|
|
2841
|
+
`);
|
|
2842
|
+
program.validate();
|
|
2843
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2844
|
+
(0, chai_1.expect)(spy.getCalls().map(x => { var _a, _b; return (_b = (_a = x.args) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.toString(); }).filter(x => x === null || x === void 0 ? void 0 : x.includes('Error when calling plugin'))).to.eql([]);
|
|
2845
|
+
});
|
|
2846
|
+
it('allows calling func returned from other func', () => {
|
|
2847
|
+
const spy = sinon.spy(logger_1.Logger.prototype, 'error');
|
|
2848
|
+
program.setFile('source/calc.bs', `
|
|
2849
|
+
sub otherFuncFirst()
|
|
2850
|
+
' forces getOperation to be referenceType called from ReferenceType
|
|
2851
|
+
end sub
|
|
2852
|
+
|
|
2853
|
+
function calc(a as dynamic, b as dynamic, op as string) as dynamic
|
|
2854
|
+
op = getOperation(op)
|
|
2855
|
+
return op(1, 2)
|
|
2856
|
+
end function
|
|
2857
|
+
|
|
2858
|
+
function getOperation(name as string) as object
|
|
2859
|
+
return {
|
|
2860
|
+
"sum": function(a as dynamic, b as dynamic) as dynamic
|
|
2861
|
+
return a + b
|
|
2862
|
+
end function
|
|
2863
|
+
}[name]
|
|
2864
|
+
end function
|
|
2865
|
+
`);
|
|
2866
|
+
program.validate();
|
|
2867
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2868
|
+
(0, chai_1.expect)(spy.getCalls().map(x => { var _a, _b; return (_b = (_a = x.args) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.toString(); }).filter(x => x === null || x === void 0 ? void 0 : x.includes('Error when calling plugin'))).to.eql([]);
|
|
2869
|
+
});
|
|
2870
|
+
it('allows returning something that matches a type statement type', () => {
|
|
2871
|
+
program.setFile('source/util.bs', `
|
|
2872
|
+
interface Person
|
|
2873
|
+
name as string
|
|
2874
|
+
age as integer
|
|
2875
|
+
end interface
|
|
2876
|
+
|
|
2877
|
+
type Wrapped = Person
|
|
2878
|
+
|
|
2879
|
+
function getWrapped() as Wrapped
|
|
2880
|
+
return {
|
|
2881
|
+
name: "Alice",
|
|
2882
|
+
age: 30
|
|
2883
|
+
}
|
|
2884
|
+
end function
|
|
2885
|
+
`);
|
|
2886
|
+
program.validate();
|
|
2887
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2888
|
+
});
|
|
2889
|
+
describe('inline interfaces', () => {
|
|
2890
|
+
it('allows returning an Associative Array that meets the interface', () => {
|
|
2891
|
+
program.setFile('source/main.bs', `
|
|
2892
|
+
function takesInline() as {id as string}
|
|
2893
|
+
return { id: "test" }
|
|
2894
|
+
end function
|
|
2895
|
+
`);
|
|
2896
|
+
program.validate();
|
|
2897
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2898
|
+
});
|
|
2899
|
+
it('allows returning a Node that meets the interface', () => {
|
|
2900
|
+
program.setFile('source/main.bs', `
|
|
2901
|
+
function takesInline() as {id as string}
|
|
2902
|
+
return createObject("roSGNode", "Poster")
|
|
2903
|
+
end function
|
|
2904
|
+
`);
|
|
2905
|
+
program.validate();
|
|
2906
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2907
|
+
});
|
|
2908
|
+
it('validates returning an AA that does not meet the interface', () => {
|
|
2909
|
+
program.setFile('source/main.bs', `
|
|
2910
|
+
function takesInline() as {id as integer}
|
|
2911
|
+
return {id: "hello"}
|
|
2912
|
+
end function
|
|
2913
|
+
`);
|
|
2914
|
+
program.validate();
|
|
2915
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
2916
|
+
DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('roAssociativeArray', '{id as integer}', {
|
|
2917
|
+
fieldMismatches: [{ name: 'id', expectedType: IntegerType_1.IntegerType.instance, actualType: StringType_1.StringType.instance }]
|
|
2918
|
+
}).message
|
|
2919
|
+
]);
|
|
2920
|
+
});
|
|
2921
|
+
});
|
|
2922
|
+
it('allows returning invalid instead of typed array', () => {
|
|
2923
|
+
program.setFile('source/main.bs', `
|
|
2924
|
+
function getNumbers() as integer[]
|
|
2925
|
+
return invalid
|
|
2926
|
+
end function
|
|
2927
|
+
`);
|
|
2928
|
+
program.validate();
|
|
2929
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2930
|
+
});
|
|
2696
2931
|
});
|
|
2697
2932
|
describe('returnTypeCoercionMismatch', () => {
|
|
2698
2933
|
it('allows functions, subs, and "function as void/dynamic" to not have return statements', () => {
|
|
@@ -3124,6 +3359,48 @@ describe('ScopeValidator', () => {
|
|
|
3124
3359
|
]);
|
|
3125
3360
|
});
|
|
3126
3361
|
});
|
|
3362
|
+
describe('inline interfaces', () => {
|
|
3363
|
+
it('allows assigning an Associative Array that meets the interface', () => {
|
|
3364
|
+
program.setFile('source/main.bs', `
|
|
3365
|
+
interface Iface
|
|
3366
|
+
inlineMember as {name as string}
|
|
3367
|
+
end interface
|
|
3368
|
+
|
|
3369
|
+
sub takesInline(someIface as Iface}
|
|
3370
|
+
someIface.inlineMember = {name: "test"}
|
|
3371
|
+
end sub
|
|
3372
|
+
`);
|
|
3373
|
+
program.validate();
|
|
3374
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
3375
|
+
});
|
|
3376
|
+
it('validates assigning an AA that does not meet the interface', () => {
|
|
3377
|
+
program.setFile('source/main.bs', `
|
|
3378
|
+
interface Iface
|
|
3379
|
+
inlineMember as {name as string}
|
|
3380
|
+
end interface
|
|
3381
|
+
|
|
3382
|
+
sub takesInline(someIface as Iface}
|
|
3383
|
+
someIface.inlineMember = {name: 123}
|
|
3384
|
+
end sub
|
|
3385
|
+
`);
|
|
3386
|
+
program.validate();
|
|
3387
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
3388
|
+
DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('roAssociativeArray', '{name as string}', {
|
|
3389
|
+
fieldMismatches: [{ name: 'name', expectedType: StringType_1.StringType.instance, actualType: IntegerType_1.IntegerType.instance }]
|
|
3390
|
+
}).message
|
|
3391
|
+
]);
|
|
3392
|
+
});
|
|
3393
|
+
it('allows assigning invalid to typed arrays', () => {
|
|
3394
|
+
program.setFile('source/main.bs', `
|
|
3395
|
+
sub test()
|
|
3396
|
+
intArray as integer[] = invalid
|
|
3397
|
+
strArray as string[] = invalid
|
|
3398
|
+
end sub
|
|
3399
|
+
`);
|
|
3400
|
+
program.validate();
|
|
3401
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
3402
|
+
});
|
|
3403
|
+
});
|
|
3127
3404
|
});
|
|
3128
3405
|
describe('operatorTypeMismatch', () => {
|
|
3129
3406
|
it('finds when the type of the lhs is not compatible with the rhs type', () => {
|
|
@@ -3403,6 +3680,35 @@ describe('ScopeValidator', () => {
|
|
|
3403
3680
|
program.validate();
|
|
3404
3681
|
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
3405
3682
|
});
|
|
3683
|
+
it('allows unions of compatible types', () => {
|
|
3684
|
+
program.setFile('source/main.bs', `
|
|
3685
|
+
function test(s as string or roString, i as integer or longinteger)
|
|
3686
|
+
s1 = s + "test"
|
|
3687
|
+
s2 = "test" + s
|
|
3688
|
+
|
|
3689
|
+
i1 = i + 5
|
|
3690
|
+
i2 = 5 + i
|
|
3691
|
+
end function
|
|
3692
|
+
`);
|
|
3693
|
+
program.validate();
|
|
3694
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
3695
|
+
});
|
|
3696
|
+
it('allows type statement type of compatible types', () => {
|
|
3697
|
+
program.setFile('source/main.bs', `
|
|
3698
|
+
type number = integer or float
|
|
3699
|
+
type MyString = string or roString
|
|
3700
|
+
|
|
3701
|
+
function test(s as MyString, i as number)
|
|
3702
|
+
s1 = s + "test"
|
|
3703
|
+
s2 = "test" + s
|
|
3704
|
+
|
|
3705
|
+
i1 = i + 5
|
|
3706
|
+
i2 = 5 + i
|
|
3707
|
+
end function
|
|
3708
|
+
`);
|
|
3709
|
+
program.validate();
|
|
3710
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
3711
|
+
});
|
|
3406
3712
|
});
|
|
3407
3713
|
describe('memberAccessibilityMismatch', () => {
|
|
3408
3714
|
it('should flag when accessing a private member', () => {
|
|
@@ -3682,6 +3988,25 @@ describe('ScopeValidator', () => {
|
|
|
3682
3988
|
]);
|
|
3683
3989
|
});
|
|
3684
3990
|
});
|
|
3991
|
+
describe('circularReferenceDetected', () => {
|
|
3992
|
+
it('finds circular references in consts', () => {
|
|
3993
|
+
program.setFile('source/main.bs', `
|
|
3994
|
+
const A = B ' this is circular-reference
|
|
3995
|
+
const B = C ' this is circular-reference
|
|
3996
|
+
const C = A ' this is circular-reference
|
|
3997
|
+
sub main()
|
|
3998
|
+
print A ' this is circular-reference
|
|
3999
|
+
end sub
|
|
4000
|
+
`);
|
|
4001
|
+
program.validate();
|
|
4002
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
4003
|
+
DiagnosticMessages_1.DiagnosticMessages.circularReferenceDetected(['B', 'C', 'B']).message,
|
|
4004
|
+
DiagnosticMessages_1.DiagnosticMessages.circularReferenceDetected(['B', 'C', 'B']).message,
|
|
4005
|
+
DiagnosticMessages_1.DiagnosticMessages.circularReferenceDetected(['B', 'C', 'B']).message,
|
|
4006
|
+
DiagnosticMessages_1.DiagnosticMessages.circularReferenceDetected(['C', 'B', 'C']).message
|
|
4007
|
+
]);
|
|
4008
|
+
});
|
|
4009
|
+
});
|
|
3685
4010
|
describe('revalidation', () => {
|
|
3686
4011
|
it('revalidates when a enum defined in a different namespace changes', () => {
|
|
3687
4012
|
program.setFile('source/file1.bs', `
|
|
@@ -4106,6 +4431,44 @@ describe('ScopeValidator', () => {
|
|
|
4106
4431
|
// there should be no more errors
|
|
4107
4432
|
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
4108
4433
|
});
|
|
4434
|
+
it('recognizes when the type of a for-each loop variable changes', () => {
|
|
4435
|
+
program.setFile('source/file1.bs', `
|
|
4436
|
+
interface FooFace
|
|
4437
|
+
prop as string
|
|
4438
|
+
end interface
|
|
4439
|
+
`);
|
|
4440
|
+
program.setFile('source/file2.bs', `
|
|
4441
|
+
function loopFooFace(input as FooFace[])
|
|
4442
|
+
out = ""
|
|
4443
|
+
for each ff in input
|
|
4444
|
+
out += ff.prop
|
|
4445
|
+
end for
|
|
4446
|
+
return out
|
|
4447
|
+
end function
|
|
4448
|
+
`);
|
|
4449
|
+
program.validate();
|
|
4450
|
+
//currently no error
|
|
4451
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
4452
|
+
// change FooFace.prop to not work in other file
|
|
4453
|
+
program.setFile('source/file1.bs', `
|
|
4454
|
+
interface FooFace
|
|
4455
|
+
prop as integer
|
|
4456
|
+
end interface
|
|
4457
|
+
`);
|
|
4458
|
+
program.validate();
|
|
4459
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
4460
|
+
DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('+=', 'string', 'integer')
|
|
4461
|
+
]);
|
|
4462
|
+
// change FooFace.prop to back to working
|
|
4463
|
+
program.setFile('source/file1.bs', `
|
|
4464
|
+
interface FooFace
|
|
4465
|
+
prop as string
|
|
4466
|
+
end interface
|
|
4467
|
+
`);
|
|
4468
|
+
program.validate();
|
|
4469
|
+
//currently no error
|
|
4470
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
4471
|
+
});
|
|
4109
4472
|
});
|
|
4110
4473
|
describe('preprocessor', () => {
|
|
4111
4474
|
it('should process class inheritance correctly', () => {
|
|
@@ -4239,6 +4602,15 @@ describe('ScopeValidator', () => {
|
|
|
4239
4602
|
DiagnosticMessages_1.DiagnosticMessages.notCallable('"string"').message
|
|
4240
4603
|
]);
|
|
4241
4604
|
});
|
|
4605
|
+
it('allows calling an object type', () => {
|
|
4606
|
+
program.setFile('source/calc.bs', `
|
|
4607
|
+
function someFunc(otherFunc as object) as dynamic
|
|
4608
|
+
return otherFunc()
|
|
4609
|
+
end function
|
|
4610
|
+
`);
|
|
4611
|
+
program.validate();
|
|
4612
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
4613
|
+
});
|
|
4242
4614
|
});
|
|
4243
4615
|
describe('callFunc', () => {
|
|
4244
4616
|
it('allows access to member of return type when return type is custom node', () => {
|