brighterscript 1.0.0-alpha.41 → 1.0.0-alpha.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +78 -2
- package/dist/AstValidationSegmenter.d.ts +3 -0
- package/dist/AstValidationSegmenter.js +62 -2
- package/dist/AstValidationSegmenter.js.map +1 -1
- package/dist/BsConfig.d.ts +7 -7
- package/dist/CrossScopeValidator.js +3 -3
- package/dist/CrossScopeValidator.js.map +1 -1
- package/dist/DiagnosticFilterer.d.ts +5 -1
- package/dist/DiagnosticFilterer.js +92 -33
- package/dist/DiagnosticFilterer.js.map +1 -1
- package/dist/DiagnosticManager.js +12 -9
- package/dist/DiagnosticManager.js.map +1 -1
- package/dist/DiagnosticMessages.d.ts +374 -225
- package/dist/DiagnosticMessages.js +641 -424
- package/dist/DiagnosticMessages.js.map +1 -1
- package/dist/DiagnosticSeverityAdjuster.js +4 -0
- package/dist/DiagnosticSeverityAdjuster.js.map +1 -1
- package/dist/LanguageServer.js +0 -7
- package/dist/LanguageServer.js.map +1 -1
- package/dist/PluginInterface.js +2 -0
- package/dist/PluginInterface.js.map +1 -1
- package/dist/Program.d.ts +22 -1
- package/dist/Program.js +206 -49
- package/dist/Program.js.map +1 -1
- package/dist/SymbolTable.d.ts +3 -0
- package/dist/SymbolTable.js +19 -1
- package/dist/SymbolTable.js.map +1 -1
- package/dist/XmlScope.js +3 -6
- package/dist/XmlScope.js.map +1 -1
- package/dist/astUtils/creators.d.ts +35 -3
- package/dist/astUtils/creators.js +52 -1
- package/dist/astUtils/creators.js.map +1 -1
- package/dist/astUtils/reflection.d.ts +24 -5
- package/dist/astUtils/reflection.js +89 -19
- package/dist/astUtils/reflection.js.map +1 -1
- package/dist/astUtils/visitors.d.ts +3 -2
- package/dist/astUtils/visitors.js +37 -14
- package/dist/astUtils/visitors.js.map +1 -1
- package/dist/astUtils/visitors.spec.js +172 -6
- package/dist/astUtils/visitors.spec.js.map +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.d.ts +0 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +0 -13
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
- package/dist/bscPlugin/completions/CompletionsProcessor.d.ts +2 -1
- package/dist/bscPlugin/completions/CompletionsProcessor.js +5 -5
- package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -1
- package/dist/bscPlugin/completions/CompletionsProcessor.spec.js +106 -2
- package/dist/bscPlugin/completions/CompletionsProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/hover/HoverProcessor.spec.js +51 -3
- package/dist/bscPlugin/hover/HoverProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.d.ts +1 -0
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js +149 -0
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js.map +1 -1
- package/dist/bscPlugin/validation/BrsFileValidator.js +15 -8
- package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -1
- package/dist/bscPlugin/validation/BrsFileValidator.spec.js +170 -24
- package/dist/bscPlugin/validation/BrsFileValidator.spec.js.map +1 -1
- package/dist/bscPlugin/validation/ScopeValidator.d.ts +7 -0
- package/dist/bscPlugin/validation/ScopeValidator.js +150 -80
- package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -1
- package/dist/bscPlugin/validation/ScopeValidator.spec.js +1341 -29
- package/dist/bscPlugin/validation/ScopeValidator.spec.js.map +1 -1
- package/dist/bscPlugin/validation/XmlFileValidator.js +0 -8
- package/dist/bscPlugin/validation/XmlFileValidator.js.map +1 -1
- package/dist/diagnosticUtils.js +6 -5
- package/dist/diagnosticUtils.js.map +1 -1
- package/dist/files/BrsFile.Class.spec.js +87 -28
- package/dist/files/BrsFile.Class.spec.js.map +1 -1
- package/dist/files/BrsFile.d.ts +1 -0
- package/dist/files/BrsFile.js +20 -8
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/BrsFile.spec.js +133 -34
- package/dist/files/BrsFile.spec.js.map +1 -1
- package/dist/files/XmlFile.js +2 -2
- package/dist/files/XmlFile.js.map +1 -1
- package/dist/files/XmlFile.spec.js +3 -20
- package/dist/files/XmlFile.spec.js.map +1 -1
- package/dist/globalCallables.js +1 -1
- package/dist/index.d.ts +8 -3
- package/dist/index.js +24 -16
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +18 -0
- package/dist/interfaces.js.map +1 -1
- package/dist/lexer/Lexer.js +17 -11
- package/dist/lexer/Lexer.js.map +1 -1
- package/dist/lexer/Lexer.spec.js +21 -3
- package/dist/lexer/Lexer.spec.js.map +1 -1
- package/dist/lexer/TokenKind.d.ts +9 -0
- package/dist/lexer/TokenKind.js +11 -1
- package/dist/lexer/TokenKind.js.map +1 -1
- package/dist/parser/AstNode.d.ts +2 -1
- package/dist/parser/AstNode.js +3 -2
- package/dist/parser/AstNode.js.map +1 -1
- package/dist/parser/Expression.d.ts +22 -2
- package/dist/parser/Expression.js +84 -49
- package/dist/parser/Expression.js.map +1 -1
- package/dist/parser/Parser.Class.spec.js +3 -3
- package/dist/parser/Parser.Class.spec.js.map +1 -1
- package/dist/parser/Parser.js +73 -61
- package/dist/parser/Parser.js.map +1 -1
- package/dist/parser/Parser.spec.js +198 -15
- package/dist/parser/Parser.spec.js.map +1 -1
- package/dist/parser/SGParser.js +9 -9
- package/dist/parser/SGParser.js.map +1 -1
- package/dist/parser/SGParser.spec.js +3 -2
- package/dist/parser/SGParser.spec.js.map +1 -1
- package/dist/parser/Statement.d.ts +16 -18
- package/dist/parser/Statement.js +136 -82
- package/dist/parser/Statement.js.map +1 -1
- package/dist/parser/tests/controlFlow/If.spec.js +1 -1
- package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
- package/dist/parser/tests/expression/ArrayLiterals.spec.js +3 -3
- package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +3 -3
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
- package/dist/parser/tests/expression/Call.spec.js +9 -9
- package/dist/parser/tests/expression/Call.spec.js.map +1 -1
- package/dist/parser/tests/expression/Indexing.spec.js +3 -3
- package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js +1 -1
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TernaryExpression.spec.js +353 -71
- package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
- package/dist/parser/tests/statement/Dim.spec.js +10 -3
- package/dist/parser/tests/statement/Dim.spec.js.map +1 -1
- package/dist/parser/tests/statement/Enum.spec.js +2 -2
- package/dist/parser/tests/statement/Enum.spec.js.map +1 -1
- package/dist/parser/tests/statement/Increment.spec.js +3 -5
- package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
- package/dist/parser/tests/statement/PrintStatement.spec.js +3 -3
- package/dist/parser/tests/statement/TryCatch.spec.js +1 -1
- package/dist/parser/tests/statement/TryCatch.spec.js.map +1 -1
- package/dist/roku-types/data.json +567 -247
- package/dist/roku-types/index.d.ts +72 -42
- package/dist/types/ArrayType.d.ts +3 -0
- package/dist/types/ArrayType.js +18 -5
- package/dist/types/ArrayType.js.map +1 -1
- package/dist/types/AssociativeArrayType.d.ts +1 -0
- package/dist/types/AssociativeArrayType.js +1 -0
- package/dist/types/AssociativeArrayType.js.map +1 -1
- package/dist/types/BaseFunctionType.d.ts +1 -0
- package/dist/types/BaseFunctionType.js +1 -0
- package/dist/types/BaseFunctionType.js.map +1 -1
- package/dist/types/BooleanType.d.ts +1 -0
- package/dist/types/BooleanType.js +1 -0
- package/dist/types/BooleanType.js.map +1 -1
- package/dist/types/BscType.d.ts +8 -1
- package/dist/types/BscType.js +22 -6
- package/dist/types/BscType.js.map +1 -1
- package/dist/types/BuiltInInterfaceAdder.js +10 -6
- package/dist/types/BuiltInInterfaceAdder.js.map +1 -1
- package/dist/types/ClassType.d.ts +1 -0
- package/dist/types/ClassType.js +5 -2
- package/dist/types/ClassType.js.map +1 -1
- package/dist/types/ComponentType.d.ts +11 -4
- package/dist/types/ComponentType.js +100 -8
- package/dist/types/ComponentType.js.map +1 -1
- package/dist/types/DoubleType.d.ts +2 -0
- package/dist/types/DoubleType.js +4 -5
- package/dist/types/DoubleType.js.map +1 -1
- package/dist/types/DynamicType.d.ts +1 -0
- package/dist/types/DynamicType.js +4 -0
- package/dist/types/DynamicType.js.map +1 -1
- package/dist/types/EnumType.d.ts +2 -0
- package/dist/types/EnumType.js +20 -2
- package/dist/types/EnumType.js.map +1 -1
- package/dist/types/FloatType.d.ts +2 -0
- package/dist/types/FloatType.js +4 -5
- package/dist/types/FloatType.js.map +1 -1
- package/dist/types/FunctionType.js +2 -1
- package/dist/types/FunctionType.js.map +1 -1
- package/dist/types/InheritableType.js +8 -0
- package/dist/types/InheritableType.js.map +1 -1
- package/dist/types/IntegerType.d.ts +2 -0
- package/dist/types/IntegerType.js +4 -5
- package/dist/types/IntegerType.js.map +1 -1
- package/dist/types/InterfaceType.js +4 -1
- package/dist/types/InterfaceType.js.map +1 -1
- package/dist/types/InvalidType.d.ts +2 -1
- package/dist/types/InvalidType.js +3 -2
- package/dist/types/InvalidType.js.map +1 -1
- package/dist/types/LongIntegerType.d.ts +2 -0
- package/dist/types/LongIntegerType.js +4 -5
- package/dist/types/LongIntegerType.js.map +1 -1
- package/dist/types/ObjectType.d.ts +1 -0
- package/dist/types/ObjectType.js +1 -0
- package/dist/types/ObjectType.js.map +1 -1
- package/dist/types/ReferenceType.d.ts +20 -2
- package/dist/types/ReferenceType.js +106 -5
- package/dist/types/ReferenceType.js.map +1 -1
- package/dist/types/StringType.d.ts +1 -0
- package/dist/types/StringType.js +3 -2
- package/dist/types/StringType.js.map +1 -1
- package/dist/types/TypedFunctionType.d.ts +1 -1
- package/dist/types/TypedFunctionType.js +8 -2
- package/dist/types/TypedFunctionType.js.map +1 -1
- package/dist/types/UninitializedType.d.ts +2 -0
- package/dist/types/UninitializedType.js +5 -6
- package/dist/types/UninitializedType.js.map +1 -1
- package/dist/types/UnionType.js +8 -2
- package/dist/types/UnionType.js.map +1 -1
- package/dist/types/VoidType.d.ts +4 -1
- package/dist/types/VoidType.js +5 -0
- package/dist/types/VoidType.js.map +1 -1
- package/dist/types/helpers.js +8 -1
- package/dist/types/helpers.js.map +1 -1
- package/dist/util.d.ts +17 -6
- package/dist/util.js +320 -24
- package/dist/util.js.map +1 -1
- package/dist/validators/ClassValidator.js +13 -5
- package/dist/validators/ClassValidator.js.map +1 -1
- package/package.json +2 -2
|
@@ -173,7 +173,7 @@ describe('ScopeValidator', () => {
|
|
|
173
173
|
print input
|
|
174
174
|
end sub
|
|
175
175
|
`);
|
|
176
|
-
program.setFile('source/util.
|
|
176
|
+
program.setFile('source/util.bs', `
|
|
177
177
|
sub useCallFunc(input as roSGNodeWidget)
|
|
178
178
|
input.callFunc()
|
|
179
179
|
end sub
|
|
@@ -199,15 +199,39 @@ describe('ScopeValidator', () => {
|
|
|
199
199
|
print input
|
|
200
200
|
end sub
|
|
201
201
|
`);
|
|
202
|
-
program.setFile('source/util.
|
|
202
|
+
program.setFile('source/util.bs', `
|
|
203
|
+
sub useCallFunc(input as roSGNodeWidget, funcToCall as string)
|
|
204
|
+
input.callFunc(funcToCall, 1, 2, 3, {})
|
|
205
|
+
end sub
|
|
206
|
+
`);
|
|
207
|
+
program.validate();
|
|
208
|
+
// no error, because we can't know what function you're actually calling
|
|
209
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
210
|
+
});
|
|
211
|
+
it('checks for target args count on callfunc', () => {
|
|
212
|
+
program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
|
|
213
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
214
|
+
<component name="Widget" extends="Group">
|
|
215
|
+
<script uri="Widget.brs"/>
|
|
216
|
+
<interface>
|
|
217
|
+
<function name="someFunc" />
|
|
218
|
+
</interface>
|
|
219
|
+
</component>
|
|
220
|
+
`);
|
|
221
|
+
program.setFile('components/Widget.brs', `
|
|
222
|
+
sub someFunc(input as object)
|
|
223
|
+
print input
|
|
224
|
+
end sub
|
|
225
|
+
`);
|
|
226
|
+
program.setFile('source/util.bs', `
|
|
203
227
|
sub useCallFunc(input as roSGNodeWidget)
|
|
204
228
|
input.callFunc("someFunc", 1, 2, 3, {})
|
|
205
229
|
end sub
|
|
206
230
|
`);
|
|
207
231
|
program.validate();
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
232
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
233
|
+
DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(2, 5)
|
|
234
|
+
]);
|
|
211
235
|
});
|
|
212
236
|
it('validates against scope-defined func in inner namespace, when outer namespace has same named func', () => {
|
|
213
237
|
program.setFile('source/main.bs', `
|
|
@@ -1159,6 +1183,148 @@ describe('ScopeValidator', () => {
|
|
|
1159
1183
|
(0, testHelpers_spec_1.expectTypeToBe)(data.fieldMismatches[0].expectedType, IntegerType_1.IntegerType);
|
|
1160
1184
|
(0, testHelpers_spec_1.expectTypeToBe)(data.fieldMismatches[0].actualType, StringType_1.StringType);
|
|
1161
1185
|
});
|
|
1186
|
+
it('allows a non-built-in void function as an argument', () => {
|
|
1187
|
+
program.setFile('source/main.bs', `
|
|
1188
|
+
sub voidFunc() as void
|
|
1189
|
+
end sub
|
|
1190
|
+
|
|
1191
|
+
sub doPrint(x)
|
|
1192
|
+
print x
|
|
1193
|
+
end sub
|
|
1194
|
+
|
|
1195
|
+
sub useVoidAsArg()
|
|
1196
|
+
doPrint(voidFunc()) ' will print "invalid"
|
|
1197
|
+
end sub
|
|
1198
|
+
`);
|
|
1199
|
+
program.validate();
|
|
1200
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
1201
|
+
});
|
|
1202
|
+
it('validates a built-in void function as an argument', () => {
|
|
1203
|
+
program.setFile('source/main.bs', `
|
|
1204
|
+
sub doPrint(x)
|
|
1205
|
+
print x
|
|
1206
|
+
end sub
|
|
1207
|
+
|
|
1208
|
+
sub useVoidAsArg()
|
|
1209
|
+
arr = [1,2,3]
|
|
1210
|
+
doPrint(arr.push(4))
|
|
1211
|
+
end sub
|
|
1212
|
+
`);
|
|
1213
|
+
program.validate();
|
|
1214
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
1215
|
+
DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('uninitialized', 'dynamic').message
|
|
1216
|
+
]);
|
|
1217
|
+
});
|
|
1218
|
+
describe('default params', () => {
|
|
1219
|
+
it('generalizes EnumMembers to their parent types', () => {
|
|
1220
|
+
program.setFile('source/util.bs', `
|
|
1221
|
+
sub takesEnum(enumVal = Direction.South)
|
|
1222
|
+
print enumVal
|
|
1223
|
+
end sub
|
|
1224
|
+
|
|
1225
|
+
sub callTestFunc()
|
|
1226
|
+
takesEnum(Direction.North)
|
|
1227
|
+
end sub
|
|
1228
|
+
|
|
1229
|
+
enum Direction
|
|
1230
|
+
North
|
|
1231
|
+
South
|
|
1232
|
+
end enum
|
|
1233
|
+
`);
|
|
1234
|
+
program.validate();
|
|
1235
|
+
//should have no errors
|
|
1236
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
1237
|
+
});
|
|
1238
|
+
it('works with future declared types', () => {
|
|
1239
|
+
program.setFile('source/util.bs', `
|
|
1240
|
+
sub takesKlass(klassInstance = new Klass())
|
|
1241
|
+
print klassInstance
|
|
1242
|
+
end sub
|
|
1243
|
+
|
|
1244
|
+
sub callTestFunc()
|
|
1245
|
+
takesKlass()
|
|
1246
|
+
myKlass = new Klass()
|
|
1247
|
+
takesKlass(myKlass)
|
|
1248
|
+
end sub
|
|
1249
|
+
|
|
1250
|
+
class Klass
|
|
1251
|
+
name as string
|
|
1252
|
+
end class
|
|
1253
|
+
`);
|
|
1254
|
+
program.validate();
|
|
1255
|
+
//should have no errors
|
|
1256
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
1257
|
+
});
|
|
1258
|
+
it('validates against future declared types', () => {
|
|
1259
|
+
program.setFile('source/util.bs', `
|
|
1260
|
+
sub takesKlass(klassInstance = new Klass())
|
|
1261
|
+
print klassInstance
|
|
1262
|
+
end sub
|
|
1263
|
+
|
|
1264
|
+
sub callTestFunc()
|
|
1265
|
+
myOKlass = new OtherKlass()
|
|
1266
|
+
takesKlass(myOKlass)
|
|
1267
|
+
end sub
|
|
1268
|
+
|
|
1269
|
+
class Klass
|
|
1270
|
+
name as string
|
|
1271
|
+
end class
|
|
1272
|
+
|
|
1273
|
+
class OtherKlass
|
|
1274
|
+
name as integer
|
|
1275
|
+
end class
|
|
1276
|
+
`);
|
|
1277
|
+
program.validate();
|
|
1278
|
+
//should have no errors
|
|
1279
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
1280
|
+
DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('OtherKlass', 'Klass').message
|
|
1281
|
+
]);
|
|
1282
|
+
});
|
|
1283
|
+
it('validates against future declared types in different namespace', () => {
|
|
1284
|
+
program.setFile('source/util.bs', `
|
|
1285
|
+
sub takesKlass(klassInstance = new alpha.beta.Klass())
|
|
1286
|
+
print klassInstance
|
|
1287
|
+
end sub
|
|
1288
|
+
|
|
1289
|
+
sub callTestFunc()
|
|
1290
|
+
myOKlass = new alpha.beta.OtherKlass()
|
|
1291
|
+
takesKlass(myOKlass)
|
|
1292
|
+
end sub
|
|
1293
|
+
|
|
1294
|
+
namespace alpha.beta
|
|
1295
|
+
class Klass
|
|
1296
|
+
name as string
|
|
1297
|
+
end class
|
|
1298
|
+
|
|
1299
|
+
class OtherKlass
|
|
1300
|
+
name as integer
|
|
1301
|
+
end class
|
|
1302
|
+
end namespace
|
|
1303
|
+
`);
|
|
1304
|
+
program.validate();
|
|
1305
|
+
//should have no errors
|
|
1306
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
1307
|
+
DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('alpha.beta.OtherKlass', 'alpha.beta.Klass').message
|
|
1308
|
+
]);
|
|
1309
|
+
});
|
|
1310
|
+
it('should correctly be able to modify an array with enum initial values', () => {
|
|
1311
|
+
program.setFile('source/util.bs', `
|
|
1312
|
+
function alsoGoEast(path = [Direction.North, Direction.South])
|
|
1313
|
+
path.Push(Direction.East) ' "path" should be typed as Array<Direction>
|
|
1314
|
+
return path
|
|
1315
|
+
end function
|
|
1316
|
+
|
|
1317
|
+
enum Direction
|
|
1318
|
+
North = "North"
|
|
1319
|
+
South = "South"
|
|
1320
|
+
East = "East"
|
|
1321
|
+
West = "West"
|
|
1322
|
+
end enum
|
|
1323
|
+
`);
|
|
1324
|
+
program.validate();
|
|
1325
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
1326
|
+
});
|
|
1327
|
+
});
|
|
1162
1328
|
describe('array compatibility', () => {
|
|
1163
1329
|
it('accepts dynamic when assigning to a roArray', () => {
|
|
1164
1330
|
program.setFile('source/util.bs', `
|
|
@@ -1487,6 +1653,66 @@ describe('ScopeValidator', () => {
|
|
|
1487
1653
|
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
1488
1654
|
});
|
|
1489
1655
|
});
|
|
1656
|
+
it('allows boxed types', () => {
|
|
1657
|
+
program.setFile('source/main.bs', `
|
|
1658
|
+
function takesBoxedLongInt(x as roLongInteger)
|
|
1659
|
+
return 123456& + x
|
|
1660
|
+
end function
|
|
1661
|
+
|
|
1662
|
+
function takesLongInt(x as longInteger)
|
|
1663
|
+
return 123456& + x
|
|
1664
|
+
end function
|
|
1665
|
+
|
|
1666
|
+
sub test()
|
|
1667
|
+
long = 123456&
|
|
1668
|
+
boxedLong = createObject("roLongInteger")
|
|
1669
|
+
print takesBoxedLongInt(long)
|
|
1670
|
+
print takesBoxedLongInt(boxedLong)
|
|
1671
|
+
print takesLongInt(long)
|
|
1672
|
+
print takesLongInt(boxedLong)
|
|
1673
|
+
end sub
|
|
1674
|
+
`);
|
|
1675
|
+
program.validate();
|
|
1676
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
1677
|
+
});
|
|
1678
|
+
describe('AA args with string literal keys', () => {
|
|
1679
|
+
it('finds keys with string literal names', () => {
|
|
1680
|
+
program.setFile('source/main.bs', `
|
|
1681
|
+
interface Data
|
|
1682
|
+
id
|
|
1683
|
+
end interface
|
|
1684
|
+
|
|
1685
|
+
sub takesData(datum as Data)
|
|
1686
|
+
end sub
|
|
1687
|
+
|
|
1688
|
+
sub usesData()
|
|
1689
|
+
takesData({"id": 1234})
|
|
1690
|
+
end sub
|
|
1691
|
+
`);
|
|
1692
|
+
program.validate();
|
|
1693
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
1694
|
+
});
|
|
1695
|
+
it('validates keys with string literal names, but type is incorrect', () => {
|
|
1696
|
+
program.setFile('source/main.bs', `
|
|
1697
|
+
interface Data
|
|
1698
|
+
id as string
|
|
1699
|
+
end interface
|
|
1700
|
+
|
|
1701
|
+
sub takesData(datum as Data)
|
|
1702
|
+
end sub
|
|
1703
|
+
|
|
1704
|
+
sub usesData()
|
|
1705
|
+
takesData({"id": 1234})
|
|
1706
|
+
end sub
|
|
1707
|
+
`);
|
|
1708
|
+
program.validate();
|
|
1709
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
1710
|
+
DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('roAssociativeArray', 'Data', {
|
|
1711
|
+
fieldMismatches: [{ name: 'id', expectedType: StringType_1.StringType.instance, actualType: IntegerType_1.IntegerType.instance }]
|
|
1712
|
+
}).message
|
|
1713
|
+
]);
|
|
1714
|
+
});
|
|
1715
|
+
});
|
|
1490
1716
|
});
|
|
1491
1717
|
describe('cannotFindName', () => {
|
|
1492
1718
|
it('finds variables from assignments from member functions of primitive types', () => {
|
|
@@ -1823,6 +2049,135 @@ describe('ScopeValidator', () => {
|
|
|
1823
2049
|
program.validate();
|
|
1824
2050
|
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
1825
2051
|
});
|
|
2052
|
+
it('has an diagnostic when using a variable defined in parent function', () => {
|
|
2053
|
+
program.setFile('source/main.bs', `
|
|
2054
|
+
function parentFunction()
|
|
2055
|
+
parentVar = "test"
|
|
2056
|
+
|
|
2057
|
+
innerFunction = sub()
|
|
2058
|
+
' Attempting to use parentVar from the parent function scope
|
|
2059
|
+
print parentVar ' This should trigger a diagnostic
|
|
2060
|
+
otherFunc() ' this is fine
|
|
2061
|
+
end sub
|
|
2062
|
+
|
|
2063
|
+
innerFunction()
|
|
2064
|
+
end function
|
|
2065
|
+
|
|
2066
|
+
sub otherFunc()
|
|
2067
|
+
print "hello"
|
|
2068
|
+
end sub
|
|
2069
|
+
`);
|
|
2070
|
+
program.validate();
|
|
2071
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
2072
|
+
DiagnosticMessages_1.DiagnosticMessages.cannotFindName('parentVar')
|
|
2073
|
+
]);
|
|
2074
|
+
});
|
|
2075
|
+
it('has an diagnostic when using a param from parent function', () => {
|
|
2076
|
+
program.setFile('source/main.bs', `
|
|
2077
|
+
function parentFunction(outerVal)
|
|
2078
|
+
parentVar = "test"
|
|
2079
|
+
|
|
2080
|
+
innerFunction = sub(inner)
|
|
2081
|
+
print inner + outer
|
|
2082
|
+
end sub
|
|
2083
|
+
|
|
2084
|
+
innerFunction(2)
|
|
2085
|
+
end function
|
|
2086
|
+
`);
|
|
2087
|
+
program.validate();
|
|
2088
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
2089
|
+
DiagnosticMessages_1.DiagnosticMessages.cannotFindName('outer')
|
|
2090
|
+
]);
|
|
2091
|
+
});
|
|
2092
|
+
it('allows method call on hex literal', () => {
|
|
2093
|
+
program.setFile('source/main.bs', `
|
|
2094
|
+
function test()
|
|
2095
|
+
x = &HFF.toStr()
|
|
2096
|
+
return x
|
|
2097
|
+
end function
|
|
2098
|
+
`);
|
|
2099
|
+
program.validate();
|
|
2100
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2101
|
+
});
|
|
2102
|
+
it('allows method call on hex literal', () => {
|
|
2103
|
+
program.setFile('source/main.bs', `
|
|
2104
|
+
function test()
|
|
2105
|
+
x = &HFF.toStr()
|
|
2106
|
+
return x
|
|
2107
|
+
end function
|
|
2108
|
+
`);
|
|
2109
|
+
program.validate();
|
|
2110
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2111
|
+
});
|
|
2112
|
+
it('has no validation errors with print statement with hex followed by dot <number>', () => {
|
|
2113
|
+
program.setFile('source/main.bs', `
|
|
2114
|
+
sub test()
|
|
2115
|
+
print &hFF.123.456.5678
|
|
2116
|
+
end sub
|
|
2117
|
+
`);
|
|
2118
|
+
program.validate();
|
|
2119
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2120
|
+
});
|
|
2121
|
+
it('allows access of properties of union with invalid', () => {
|
|
2122
|
+
program.setFile('source/main.bs', `
|
|
2123
|
+
sub test()
|
|
2124
|
+
channel = invalid
|
|
2125
|
+
if true
|
|
2126
|
+
channel = {
|
|
2127
|
+
height: 123
|
|
2128
|
+
}
|
|
2129
|
+
end if
|
|
2130
|
+
|
|
2131
|
+
height = 0
|
|
2132
|
+
if channel <> invalid then
|
|
2133
|
+
height += channel.height
|
|
2134
|
+
end if
|
|
2135
|
+
end sub
|
|
2136
|
+
`);
|
|
2137
|
+
program.validate();
|
|
2138
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2139
|
+
});
|
|
2140
|
+
it('sets default arg of invalid as dynamic', () => {
|
|
2141
|
+
program.setFile('source/main.bs', `
|
|
2142
|
+
sub test(channel = invalid)
|
|
2143
|
+
if true
|
|
2144
|
+
channel = {
|
|
2145
|
+
height: 123
|
|
2146
|
+
}
|
|
2147
|
+
end if
|
|
2148
|
+
|
|
2149
|
+
height = 0
|
|
2150
|
+
if channel <> invalid then
|
|
2151
|
+
height += channel.height
|
|
2152
|
+
end if
|
|
2153
|
+
end sub
|
|
2154
|
+
`);
|
|
2155
|
+
program.validate();
|
|
2156
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2157
|
+
});
|
|
2158
|
+
it('sets assignment of function returning invalid as dynamic', () => {
|
|
2159
|
+
program.setFile('source/main.bs', `
|
|
2160
|
+
sub test()
|
|
2161
|
+
channel = noReturn()
|
|
2162
|
+
if true
|
|
2163
|
+
channel = {
|
|
2164
|
+
height: 123
|
|
2165
|
+
}
|
|
2166
|
+
end if
|
|
2167
|
+
|
|
2168
|
+
height = 0
|
|
2169
|
+
if channel <> invalid then
|
|
2170
|
+
height += channel.height
|
|
2171
|
+
end if
|
|
2172
|
+
end sub
|
|
2173
|
+
|
|
2174
|
+
sub noReturn()
|
|
2175
|
+
print "hello"
|
|
2176
|
+
end sub
|
|
2177
|
+
`);
|
|
2178
|
+
program.validate();
|
|
2179
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2180
|
+
});
|
|
1826
2181
|
});
|
|
1827
2182
|
describe('itemCannotBeUsedAsVariable', () => {
|
|
1828
2183
|
it('detects assigning to a member of a namespace outside the namespace', () => {
|
|
@@ -1840,6 +2195,40 @@ describe('ScopeValidator', () => {
|
|
|
1840
2195
|
DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable('namespace')
|
|
1841
2196
|
]);
|
|
1842
2197
|
});
|
|
2198
|
+
it('validates when trying to print a namespace', () => {
|
|
2199
|
+
program.setFile('source/main.bs', `
|
|
2200
|
+
namespace Alpha
|
|
2201
|
+
const Name = "Alpha"
|
|
2202
|
+
end namespace
|
|
2203
|
+
|
|
2204
|
+
sub main()
|
|
2205
|
+
print alpha
|
|
2206
|
+
end sub
|
|
2207
|
+
`);
|
|
2208
|
+
program.validate();
|
|
2209
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
2210
|
+
DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable('namespace')
|
|
2211
|
+
]);
|
|
2212
|
+
});
|
|
2213
|
+
it('validates when trying to pass a namespace as an arg', () => {
|
|
2214
|
+
program.setFile('source/main.bs', `
|
|
2215
|
+
namespace Alpha
|
|
2216
|
+
const Name = "Alpha"
|
|
2217
|
+
end namespace
|
|
2218
|
+
|
|
2219
|
+
sub main()
|
|
2220
|
+
someFunc(alpha)
|
|
2221
|
+
end sub
|
|
2222
|
+
|
|
2223
|
+
sub someFunc(arg)
|
|
2224
|
+
print sub
|
|
2225
|
+
end sub
|
|
2226
|
+
`);
|
|
2227
|
+
program.validate();
|
|
2228
|
+
(0, testHelpers_spec_1.expectDiagnosticsIncludes)(program, [
|
|
2229
|
+
DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable('namespace')
|
|
2230
|
+
]);
|
|
2231
|
+
});
|
|
1843
2232
|
it('detects assigning to a member of a namespace inside the namespace', () => {
|
|
1844
2233
|
program.setFile('source/main.bs', `
|
|
1845
2234
|
namespace Alpha
|
|
@@ -2262,9 +2651,47 @@ describe('ScopeValidator', () => {
|
|
|
2262
2651
|
DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('integer', 'void').message
|
|
2263
2652
|
]);
|
|
2264
2653
|
});
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2654
|
+
it('allows empty return when return as void', () => {
|
|
2655
|
+
program.setFile('source/util.bs', `
|
|
2656
|
+
function doNothing1() as void
|
|
2657
|
+
return
|
|
2658
|
+
end function
|
|
2659
|
+
|
|
2660
|
+
sub doNothing2() as void
|
|
2661
|
+
return
|
|
2662
|
+
end sub
|
|
2663
|
+
|
|
2664
|
+
sub doNothing3() as void
|
|
2665
|
+
end sub
|
|
2666
|
+
|
|
2667
|
+
sub doNothing4()
|
|
2668
|
+
return
|
|
2669
|
+
end sub
|
|
2670
|
+
|
|
2671
|
+
function doNothing5()
|
|
2672
|
+
return
|
|
2673
|
+
end function
|
|
2674
|
+
`);
|
|
2675
|
+
program.validate();
|
|
2676
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2677
|
+
});
|
|
2678
|
+
it('allows boxed types', () => {
|
|
2679
|
+
program.setFile('source/main.bs', `
|
|
2680
|
+
function getBoxedLongInt() as roLongInteger
|
|
2681
|
+
return 123456&
|
|
2682
|
+
end function
|
|
2683
|
+
|
|
2684
|
+
function getLongInt() as longInteger
|
|
2685
|
+
x = createObject("roLongInteger")
|
|
2686
|
+
return x
|
|
2687
|
+
end function
|
|
2688
|
+
`);
|
|
2689
|
+
program.validate();
|
|
2690
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2691
|
+
});
|
|
2692
|
+
});
|
|
2693
|
+
describe('returnTypeCoercionMismatch', () => {
|
|
2694
|
+
it('allows functions, subs, and "function as void/dynamic" to not have return statements', () => {
|
|
2268
2695
|
program.setFile('source/util.bs', `
|
|
2269
2696
|
function noTypeSpecified()
|
|
2270
2697
|
end function
|
|
@@ -2283,30 +2710,56 @@ describe('ScopeValidator', () => {
|
|
|
2283
2710
|
});
|
|
2284
2711
|
it('detects when a function does not have a return statement', () => {
|
|
2285
2712
|
program.setFile('source/util.bs', `
|
|
2286
|
-
function doSomething() as
|
|
2713
|
+
function doSomething() as string
|
|
2287
2714
|
end function
|
|
2288
2715
|
`);
|
|
2289
2716
|
program.validate();
|
|
2290
2717
|
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
2291
|
-
DiagnosticMessages_1.DiagnosticMessages.
|
|
2718
|
+
DiagnosticMessages_1.DiagnosticMessages.returnTypeCoercionMismatch().message
|
|
2292
2719
|
]);
|
|
2293
2720
|
});
|
|
2721
|
+
it('allows when a function does not have a return statement, but type coercsion is okay', () => {
|
|
2722
|
+
program.setFile('source/util.bs', `
|
|
2723
|
+
interface Whatever
|
|
2724
|
+
name as string
|
|
2725
|
+
end interface
|
|
2726
|
+
|
|
2727
|
+
function doSomething() as Whatever
|
|
2728
|
+
end function
|
|
2729
|
+
|
|
2730
|
+
function doSomething2() as object
|
|
2731
|
+
end function
|
|
2732
|
+
|
|
2733
|
+
function doSomething3() as integer
|
|
2734
|
+
end function
|
|
2735
|
+
|
|
2736
|
+
function doSomething4() as float
|
|
2737
|
+
end function
|
|
2738
|
+
|
|
2739
|
+
function doSomething5() as boolean
|
|
2740
|
+
end function
|
|
2741
|
+
|
|
2742
|
+
`);
|
|
2743
|
+
program.validate();
|
|
2744
|
+
// all these are ok
|
|
2745
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2746
|
+
});
|
|
2294
2747
|
it('detects when a namespaced function does not have a return statement', () => {
|
|
2295
2748
|
program.setFile('source/util.bs', `
|
|
2296
2749
|
namespace alpha
|
|
2297
|
-
function doSomething() as
|
|
2750
|
+
function doSomething() as string
|
|
2298
2751
|
end function
|
|
2299
2752
|
end namespace
|
|
2300
2753
|
`);
|
|
2301
2754
|
program.validate();
|
|
2302
2755
|
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
2303
|
-
DiagnosticMessages_1.DiagnosticMessages.
|
|
2756
|
+
DiagnosticMessages_1.DiagnosticMessages.returnTypeCoercionMismatch().message
|
|
2304
2757
|
]);
|
|
2305
2758
|
});
|
|
2306
2759
|
it('detects when an inline function does not have a return statement', () => {
|
|
2307
2760
|
program.setFile('source/util.bs', `
|
|
2308
|
-
function outer() as
|
|
2309
|
-
inner = function() as
|
|
2761
|
+
function outer() as string
|
|
2762
|
+
inner = function () as string
|
|
2310
2763
|
print "no return!"
|
|
2311
2764
|
end function
|
|
2312
2765
|
return inner()
|
|
@@ -2314,30 +2767,30 @@ describe('ScopeValidator', () => {
|
|
|
2314
2767
|
`);
|
|
2315
2768
|
program.validate();
|
|
2316
2769
|
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
2317
|
-
DiagnosticMessages_1.DiagnosticMessages.
|
|
2770
|
+
DiagnosticMessages_1.DiagnosticMessages.returnTypeCoercionMismatch().message
|
|
2318
2771
|
]);
|
|
2319
2772
|
});
|
|
2320
2773
|
it('detects when an outer function does not have a return statement', () => {
|
|
2321
2774
|
program.setFile('source/util.bs', `
|
|
2322
|
-
function outer() as
|
|
2323
|
-
inner = function() as
|
|
2324
|
-
return
|
|
2775
|
+
function outer() as string
|
|
2776
|
+
inner = function() as string
|
|
2777
|
+
return "abc"
|
|
2325
2778
|
end function
|
|
2326
2779
|
print inner()
|
|
2327
2780
|
end function
|
|
2328
2781
|
`);
|
|
2329
2782
|
program.validate();
|
|
2330
2783
|
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
2331
|
-
DiagnosticMessages_1.DiagnosticMessages.
|
|
2784
|
+
DiagnosticMessages_1.DiagnosticMessages.returnTypeCoercionMismatch().message
|
|
2332
2785
|
]);
|
|
2333
2786
|
});
|
|
2334
2787
|
it('detects when a outer function has a return statement in a branch', () => {
|
|
2335
2788
|
program.setFile('source/util.bs', `
|
|
2336
|
-
function hasBranch(x) as
|
|
2789
|
+
function hasBranch(x) as string
|
|
2337
2790
|
if x = 1
|
|
2338
|
-
return 1
|
|
2791
|
+
return "1"
|
|
2339
2792
|
else
|
|
2340
|
-
return 2
|
|
2793
|
+
return "2"
|
|
2341
2794
|
end if
|
|
2342
2795
|
end function
|
|
2343
2796
|
`);
|
|
@@ -2346,18 +2799,18 @@ describe('ScopeValidator', () => {
|
|
|
2346
2799
|
});
|
|
2347
2800
|
it('works for sub with return types with missing return', () => {
|
|
2348
2801
|
program.setFile('source/util.bs', `
|
|
2349
|
-
sub doSomething() as
|
|
2802
|
+
sub doSomething() as string
|
|
2350
2803
|
end sub
|
|
2351
2804
|
`);
|
|
2352
2805
|
program.validate();
|
|
2353
2806
|
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
2354
|
-
DiagnosticMessages_1.DiagnosticMessages.
|
|
2807
|
+
DiagnosticMessages_1.DiagnosticMessages.returnTypeCoercionMismatch().message
|
|
2355
2808
|
]);
|
|
2356
2809
|
});
|
|
2357
2810
|
it('works for sub with return types', () => {
|
|
2358
2811
|
program.setFile('source/util.bs', `
|
|
2359
|
-
sub doSomething() as
|
|
2360
|
-
return 1
|
|
2812
|
+
sub doSomething() as string
|
|
2813
|
+
return "1"
|
|
2361
2814
|
end sub
|
|
2362
2815
|
`);
|
|
2363
2816
|
program.validate();
|
|
@@ -2495,6 +2948,47 @@ describe('ScopeValidator', () => {
|
|
|
2495
2948
|
DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('string', 'integer').message
|
|
2496
2949
|
]);
|
|
2497
2950
|
});
|
|
2951
|
+
it('allows an assignment to a class field with enum initial value', () => {
|
|
2952
|
+
program.setFile('source/util.bs', `
|
|
2953
|
+
sub setDirection(k as Klass, d as Direction)
|
|
2954
|
+
k.dir = Direction.South
|
|
2955
|
+
k.dir = d
|
|
2956
|
+
end sub
|
|
2957
|
+
|
|
2958
|
+
class Klass
|
|
2959
|
+
dir = Direction.north
|
|
2960
|
+
end class
|
|
2961
|
+
|
|
2962
|
+
enum Direction
|
|
2963
|
+
north
|
|
2964
|
+
south
|
|
2965
|
+
end enum
|
|
2966
|
+
`);
|
|
2967
|
+
program.validate();
|
|
2968
|
+
//should have no errors
|
|
2969
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2970
|
+
});
|
|
2971
|
+
it('validates an assignment to a class field with enum initial value', () => {
|
|
2972
|
+
program.setFile('source/util.bs', `
|
|
2973
|
+
sub setDirection(k as Klass)
|
|
2974
|
+
k.dir = "NOT a direction"
|
|
2975
|
+
end sub
|
|
2976
|
+
|
|
2977
|
+
class Klass
|
|
2978
|
+
dir = Direction.north
|
|
2979
|
+
end class
|
|
2980
|
+
|
|
2981
|
+
enum Direction
|
|
2982
|
+
north
|
|
2983
|
+
south
|
|
2984
|
+
end enum
|
|
2985
|
+
`);
|
|
2986
|
+
program.validate();
|
|
2987
|
+
//should have errors
|
|
2988
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
2989
|
+
DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('string', 'Direction').message
|
|
2990
|
+
]);
|
|
2991
|
+
});
|
|
2498
2992
|
describe('Component fields', () => {
|
|
2499
2993
|
it('allows assigning string to font fields', () => {
|
|
2500
2994
|
program.setFile('source/util.bs', `
|
|
@@ -2805,6 +3299,98 @@ describe('ScopeValidator', () => {
|
|
|
2805
3299
|
DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('++', 'string').message
|
|
2806
3300
|
]);
|
|
2807
3301
|
});
|
|
3302
|
+
it('deals with adding int, bool and invalid', () => {
|
|
3303
|
+
program.setFile('source/util.bs', `
|
|
3304
|
+
sub doStuff()
|
|
3305
|
+
print 1 + (true + invalid)
|
|
3306
|
+
end sub
|
|
3307
|
+
|
|
3308
|
+
`);
|
|
3309
|
+
program.validate();
|
|
3310
|
+
//should have errors
|
|
3311
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
3312
|
+
DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('+', 'boolean', 'invalid').message
|
|
3313
|
+
]);
|
|
3314
|
+
});
|
|
3315
|
+
it('allows using return of a void func as a variable', () => {
|
|
3316
|
+
program.setFile('source/main.brs', `
|
|
3317
|
+
sub voidFunc() as void
|
|
3318
|
+
end sub
|
|
3319
|
+
|
|
3320
|
+
sub test()
|
|
3321
|
+
x = voidFunc()
|
|
3322
|
+
if x = invalid
|
|
3323
|
+
print "invalid"
|
|
3324
|
+
end if
|
|
3325
|
+
end sub
|
|
3326
|
+
`);
|
|
3327
|
+
program.validate();
|
|
3328
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
3329
|
+
});
|
|
3330
|
+
it('validates using return of a built-in void func as a variable', () => {
|
|
3331
|
+
program.setFile('source/main.brs', `
|
|
3332
|
+
sub test()
|
|
3333
|
+
arr = [1,2,3]
|
|
3334
|
+
x = arr.push(4)
|
|
3335
|
+
if x = invalid
|
|
3336
|
+
print "invalid"
|
|
3337
|
+
end if
|
|
3338
|
+
end sub
|
|
3339
|
+
`);
|
|
3340
|
+
program.validate();
|
|
3341
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
3342
|
+
DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('=', 'uninitialized', 'invalid').message
|
|
3343
|
+
]);
|
|
3344
|
+
});
|
|
3345
|
+
it('allows string comparisons with object', () => {
|
|
3346
|
+
program.setFile('source/main.brs', `
|
|
3347
|
+
sub test(x as object)
|
|
3348
|
+
if x <> "test"
|
|
3349
|
+
print x
|
|
3350
|
+
end if
|
|
3351
|
+
end sub
|
|
3352
|
+
`);
|
|
3353
|
+
program.validate();
|
|
3354
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
3355
|
+
});
|
|
3356
|
+
it('allows boxed types', () => {
|
|
3357
|
+
program.setFile('source/main.bs', `
|
|
3358
|
+
function math(a as rolonginteger, b as longinteger)
|
|
3359
|
+
c = a + b
|
|
3360
|
+
c = a - b
|
|
3361
|
+
c = a * b
|
|
3362
|
+
c = a / b
|
|
3363
|
+
c = a \\ b
|
|
3364
|
+
|
|
3365
|
+
d = a mod b
|
|
3366
|
+
d = a ^ b
|
|
3367
|
+
|
|
3368
|
+
a++
|
|
3369
|
+
a--
|
|
3370
|
+
a += 1
|
|
3371
|
+
a -= 1
|
|
3372
|
+
a *= 1
|
|
3373
|
+
a /= 1
|
|
3374
|
+
a \= 1
|
|
3375
|
+
a <<= 1
|
|
3376
|
+
a >>= 1
|
|
3377
|
+
|
|
3378
|
+
? 1 << (2 as roInt)
|
|
3379
|
+
? (1 as roInt) << 2
|
|
3380
|
+
? a and b
|
|
3381
|
+
? a or b
|
|
3382
|
+
|
|
3383
|
+
j = a = b
|
|
3384
|
+
j = a <> b
|
|
3385
|
+
j = a < b
|
|
3386
|
+
j = a <= b
|
|
3387
|
+
j = a > b
|
|
3388
|
+
j = a >= b
|
|
3389
|
+
end function
|
|
3390
|
+
`);
|
|
3391
|
+
program.validate();
|
|
3392
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
3393
|
+
});
|
|
2808
3394
|
});
|
|
2809
3395
|
describe('memberAccessibilityMismatch', () => {
|
|
2810
3396
|
it('should flag when accessing a private member', () => {
|
|
@@ -3056,7 +3642,7 @@ describe('ScopeValidator', () => {
|
|
|
3056
3642
|
`);
|
|
3057
3643
|
program.validate();
|
|
3058
3644
|
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
3059
|
-
DiagnosticMessages_1.DiagnosticMessages.
|
|
3645
|
+
DiagnosticMessages_1.DiagnosticMessages.cannotFindName('TypeNotThere').message
|
|
3060
3646
|
]);
|
|
3061
3647
|
});
|
|
3062
3648
|
it('validates types it cannot find in @return', () => {
|
|
@@ -3068,7 +3654,7 @@ describe('ScopeValidator', () => {
|
|
|
3068
3654
|
`);
|
|
3069
3655
|
program.validate();
|
|
3070
3656
|
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
3071
|
-
DiagnosticMessages_1.DiagnosticMessages.
|
|
3657
|
+
DiagnosticMessages_1.DiagnosticMessages.cannotFindName('TypeNotThere').message
|
|
3072
3658
|
]);
|
|
3073
3659
|
});
|
|
3074
3660
|
it('validates types it cannot find in @type', () => {
|
|
@@ -3080,7 +3666,7 @@ describe('ScopeValidator', () => {
|
|
|
3080
3666
|
`);
|
|
3081
3667
|
program.validate();
|
|
3082
3668
|
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
3083
|
-
DiagnosticMessages_1.DiagnosticMessages.
|
|
3669
|
+
DiagnosticMessages_1.DiagnosticMessages.cannotFindName('TypeNotThere').message
|
|
3084
3670
|
]);
|
|
3085
3671
|
});
|
|
3086
3672
|
});
|
|
@@ -3312,6 +3898,202 @@ describe('ScopeValidator', () => {
|
|
|
3312
3898
|
DiagnosticMessages_1.DiagnosticMessages.cannotFindName('missingBool2', undefined, 'MediaObject').message
|
|
3313
3899
|
]);
|
|
3314
3900
|
});
|
|
3901
|
+
it('rechecks source when member type of import changes', () => {
|
|
3902
|
+
// notice that width is wrongly typed as a boolean
|
|
3903
|
+
program.setFile('source/type1.bs', `
|
|
3904
|
+
interface SubType
|
|
3905
|
+
value as string
|
|
3906
|
+
end interface
|
|
3907
|
+
`);
|
|
3908
|
+
program.setFile('source/type2.bs', `
|
|
3909
|
+
interface ParentType
|
|
3910
|
+
child as Subtype
|
|
3911
|
+
end interface
|
|
3912
|
+
`);
|
|
3913
|
+
program.setFile('source/main.bs', `
|
|
3914
|
+
sub foo(input as ParentType)
|
|
3915
|
+
input.child.value = 1
|
|
3916
|
+
end sub
|
|
3917
|
+
`);
|
|
3918
|
+
program.validate();
|
|
3919
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
3920
|
+
DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('integer', 'string').message
|
|
3921
|
+
]);
|
|
3922
|
+
// fix width field type to integer
|
|
3923
|
+
program.setFile('source/type1.bs', `
|
|
3924
|
+
interface SubType
|
|
3925
|
+
value as integer
|
|
3926
|
+
end interface
|
|
3927
|
+
`);
|
|
3928
|
+
program.validate();
|
|
3929
|
+
// there should be no more errors
|
|
3930
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
3931
|
+
});
|
|
3932
|
+
it('rechecks component source when xml changes', () => {
|
|
3933
|
+
// notice that width is wrongly typed as a boolean
|
|
3934
|
+
program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
|
|
3935
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
3936
|
+
<component name="Widget" extends="Group">
|
|
3937
|
+
<script uri="Widget.bs"/>
|
|
3938
|
+
<interface>
|
|
3939
|
+
<field id="width" type="boolean" />
|
|
3940
|
+
</interface>
|
|
3941
|
+
</component>
|
|
3942
|
+
`);
|
|
3943
|
+
program.setFile('components/Widget.bs', `
|
|
3944
|
+
interface IWidget
|
|
3945
|
+
top as roSGNodeWidget
|
|
3946
|
+
data as roAssociativeArray
|
|
3947
|
+
end interface
|
|
3948
|
+
|
|
3949
|
+
sub init()
|
|
3950
|
+
(m as IWidget).top.width = 100
|
|
3951
|
+
end sub
|
|
3952
|
+
`);
|
|
3953
|
+
program.validate();
|
|
3954
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
3955
|
+
DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('integer', 'boolean').message
|
|
3956
|
+
]);
|
|
3957
|
+
// fix width field type to integer
|
|
3958
|
+
program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
|
|
3959
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
3960
|
+
<component name="Widget" extends="Group">
|
|
3961
|
+
<script uri="Widget.bs"/>
|
|
3962
|
+
<interface>
|
|
3963
|
+
<field id="width" type="integer" />
|
|
3964
|
+
</interface>
|
|
3965
|
+
</component>
|
|
3966
|
+
`);
|
|
3967
|
+
program.validate();
|
|
3968
|
+
// there should be no more errors
|
|
3969
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
3970
|
+
});
|
|
3971
|
+
it('rechecks complete file when type of typecasted m changes indirectly', () => {
|
|
3972
|
+
program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
|
|
3973
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
3974
|
+
<component name="Widget" extends="Group">
|
|
3975
|
+
<interface>
|
|
3976
|
+
<field id="width" type="boolean" />
|
|
3977
|
+
</interface>
|
|
3978
|
+
</component>
|
|
3979
|
+
`);
|
|
3980
|
+
// notice that width is wrongly typed as a boolean
|
|
3981
|
+
program.setFile('components/WidgetContainer.xml', (0, testHelpers_spec_1.trim) `
|
|
3982
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
3983
|
+
<component name="WidgetContainer" extends="Group">
|
|
3984
|
+
<script uri="WidgetContainer.bs"/>
|
|
3985
|
+
</component>
|
|
3986
|
+
`);
|
|
3987
|
+
program.setFile('components/WidgetContainerTypes.bs', `
|
|
3988
|
+
interface IWidgetContainer
|
|
3989
|
+
top as roSGNodeWidgetContainer
|
|
3990
|
+
widget as roSGNodeWidget
|
|
3991
|
+
end interface
|
|
3992
|
+
`);
|
|
3993
|
+
program.setFile('components/WidgetContainer.bs', `
|
|
3994
|
+
import "WidgetContainerTypes.bs"
|
|
3995
|
+
typecast m as IWidgetContainer
|
|
3996
|
+
|
|
3997
|
+
sub init()
|
|
3998
|
+
m.widget.width = 100
|
|
3999
|
+
end sub
|
|
4000
|
+
`);
|
|
4001
|
+
program.validate();
|
|
4002
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
4003
|
+
DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('integer', 'boolean').message
|
|
4004
|
+
]);
|
|
4005
|
+
// fix width field type to integer
|
|
4006
|
+
program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
|
|
4007
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
4008
|
+
<component name="Widget" extends="Group">
|
|
4009
|
+
<interface>
|
|
4010
|
+
<field id="width" type="integer" />
|
|
4011
|
+
</interface>
|
|
4012
|
+
</component>
|
|
4013
|
+
`);
|
|
4014
|
+
program.validate();
|
|
4015
|
+
// there should be no more errors
|
|
4016
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
4017
|
+
});
|
|
4018
|
+
it('rechecks file using callfunc when exported function type of xml changes', () => {
|
|
4019
|
+
program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
|
|
4020
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
4021
|
+
<component name="Widget" extends="Group">
|
|
4022
|
+
<script uri="Widget.bs"/>
|
|
4023
|
+
<interface>
|
|
4024
|
+
<function name="foo" />
|
|
4025
|
+
</interface>
|
|
4026
|
+
</component>
|
|
4027
|
+
`);
|
|
4028
|
+
program.setFile('components/Widget.bs', `
|
|
4029
|
+
sub foo(input as string)
|
|
4030
|
+
print input
|
|
4031
|
+
end sub
|
|
4032
|
+
`);
|
|
4033
|
+
program.setFile('source/callFoo.bs', `
|
|
4034
|
+
sub callFoo(widget as roSGNodeWidget)
|
|
4035
|
+
widget@.foo(123) ' foo expects string
|
|
4036
|
+
end sub
|
|
4037
|
+
`);
|
|
4038
|
+
program.validate();
|
|
4039
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
4040
|
+
DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('integer', 'string').message
|
|
4041
|
+
]);
|
|
4042
|
+
// fix function
|
|
4043
|
+
program.setFile('components/Widget.bs', `
|
|
4044
|
+
sub foo(input as integer)
|
|
4045
|
+
print input
|
|
4046
|
+
end sub
|
|
4047
|
+
`);
|
|
4048
|
+
program.validate();
|
|
4049
|
+
// there should be no more errors
|
|
4050
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
4051
|
+
});
|
|
4052
|
+
it('rechecks complete file when type of typecasted m in same file changes indirectly', () => {
|
|
4053
|
+
program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
|
|
4054
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
4055
|
+
<component name="Widget" extends="Group">
|
|
4056
|
+
<interface>
|
|
4057
|
+
<field id="width" type="boolean" />
|
|
4058
|
+
</interface>
|
|
4059
|
+
</component>
|
|
4060
|
+
`);
|
|
4061
|
+
// notice that width is wrongly typed as a boolean
|
|
4062
|
+
program.setFile('components/WidgetContainer.xml', (0, testHelpers_spec_1.trim) `
|
|
4063
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
4064
|
+
<component name="WidgetContainer" extends="Group">
|
|
4065
|
+
<script uri="WidgetContainer.bs"/>
|
|
4066
|
+
</component>
|
|
4067
|
+
`);
|
|
4068
|
+
program.setFile('components/WidgetContainer.bs', `
|
|
4069
|
+
typecast m as IWidgetContainer
|
|
4070
|
+
|
|
4071
|
+
interface IWidgetContainer
|
|
4072
|
+
top as roSGNodeWidgetContainer
|
|
4073
|
+
widget as roSGNodeWidget
|
|
4074
|
+
end interface
|
|
4075
|
+
|
|
4076
|
+
sub init()
|
|
4077
|
+
m.widget.width = 100
|
|
4078
|
+
end sub
|
|
4079
|
+
`);
|
|
4080
|
+
program.validate();
|
|
4081
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
4082
|
+
DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('integer', 'boolean').message
|
|
4083
|
+
]);
|
|
4084
|
+
// fix width field type to integer
|
|
4085
|
+
program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
|
|
4086
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
4087
|
+
<component name="Widget" extends="Group">
|
|
4088
|
+
<interface>
|
|
4089
|
+
<field id="width" type="integer" />
|
|
4090
|
+
</interface>
|
|
4091
|
+
</component>
|
|
4092
|
+
`);
|
|
4093
|
+
program.validate();
|
|
4094
|
+
// there should be no more errors
|
|
4095
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
4096
|
+
});
|
|
3315
4097
|
});
|
|
3316
4098
|
describe('preprocessor', () => {
|
|
3317
4099
|
it('should process class inheritance correctly', () => {
|
|
@@ -3376,5 +4158,535 @@ describe('ScopeValidator', () => {
|
|
|
3376
4158
|
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
3377
4159
|
});
|
|
3378
4160
|
});
|
|
4161
|
+
describe('callFunc', () => {
|
|
4162
|
+
it('allows access to member of return type when return type is custom node', () => {
|
|
4163
|
+
program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
|
|
4164
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
4165
|
+
<component name="Widget" extends="Group">
|
|
4166
|
+
<script uri="Widget.bs"/>
|
|
4167
|
+
<interface>
|
|
4168
|
+
<function name="getOther" />
|
|
4169
|
+
</interface>
|
|
4170
|
+
</component>
|
|
4171
|
+
`);
|
|
4172
|
+
program.setFile('components/Widget.bs', `
|
|
4173
|
+
function getOther(name as string) as roSgNodeOther
|
|
4174
|
+
other = createObject("roSgNode", "Other")
|
|
4175
|
+
other.myValue = name
|
|
4176
|
+
return other
|
|
4177
|
+
end function
|
|
4178
|
+
`);
|
|
4179
|
+
program.setFile('components/Other.xml', (0, testHelpers_spec_1.trim) `
|
|
4180
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
4181
|
+
<component name="Other" extends="Group">
|
|
4182
|
+
<interface>
|
|
4183
|
+
<field id="myValue" type="string" />
|
|
4184
|
+
</interface>
|
|
4185
|
+
</component>
|
|
4186
|
+
`);
|
|
4187
|
+
program.setFile('components/MainScene.xml', (0, testHelpers_spec_1.trim) `
|
|
4188
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
4189
|
+
<component name="MainScene" extends="Scene">
|
|
4190
|
+
<script uri="MainScene.bs"/>
|
|
4191
|
+
</component>
|
|
4192
|
+
`);
|
|
4193
|
+
program.setFile('components/MainScene.bs', `
|
|
4194
|
+
sub someFunc(widget as roSGNodeWidget)
|
|
4195
|
+
otherNode = widget@.getOther("3.14")
|
|
4196
|
+
print otherNode.myValue
|
|
4197
|
+
end sub
|
|
4198
|
+
`);
|
|
4199
|
+
program.validate();
|
|
4200
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
4201
|
+
});
|
|
4202
|
+
it('allows access to member of return type when return type is custom type', () => {
|
|
4203
|
+
program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
|
|
4204
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
4205
|
+
<component name="Widget" extends="Group">
|
|
4206
|
+
<script uri="Widget.bs"/>
|
|
4207
|
+
<interface>
|
|
4208
|
+
<function name="getOther" />
|
|
4209
|
+
</interface>
|
|
4210
|
+
</component>
|
|
4211
|
+
`);
|
|
4212
|
+
program.setFile('components/types.bs', `
|
|
4213
|
+
interface SomeIFace
|
|
4214
|
+
myValue as string
|
|
4215
|
+
end interface
|
|
4216
|
+
`);
|
|
4217
|
+
program.setFile('components/Widget.bs', `
|
|
4218
|
+
import "pkg:/components/types.bs"
|
|
4219
|
+
|
|
4220
|
+
function getOther(name as string) as SomeIFace
|
|
4221
|
+
other = {myValue: name} as SomeIface
|
|
4222
|
+
other.myValue = name
|
|
4223
|
+
return other
|
|
4224
|
+
end function
|
|
4225
|
+
`);
|
|
4226
|
+
program.setFile('components/MainScene.xml', (0, testHelpers_spec_1.trim) `
|
|
4227
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
4228
|
+
<component name="MainScene" extends="Scene">
|
|
4229
|
+
<script uri="MainScene.bs"/>
|
|
4230
|
+
</component>
|
|
4231
|
+
`);
|
|
4232
|
+
program.setFile('components/MainScene.bs', `
|
|
4233
|
+
sub someFunc(widget as roSGNodeWidget)
|
|
4234
|
+
otherNode = widget@.getOther("3.14")
|
|
4235
|
+
print otherNode.myValue
|
|
4236
|
+
end sub
|
|
4237
|
+
`);
|
|
4238
|
+
program.validate();
|
|
4239
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
4240
|
+
});
|
|
4241
|
+
it('allows access to custom type member of return type when return type is custom type', () => {
|
|
4242
|
+
program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
|
|
4243
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
4244
|
+
<component name="Widget" extends="Group">
|
|
4245
|
+
<script uri="Widget.bs"/>
|
|
4246
|
+
<interface>
|
|
4247
|
+
<function name="getOther" />
|
|
4248
|
+
</interface>
|
|
4249
|
+
</component>
|
|
4250
|
+
`);
|
|
4251
|
+
program.setFile('components/types.bs', `
|
|
4252
|
+
interface SomeIFace
|
|
4253
|
+
subFace as SubIface
|
|
4254
|
+
end interface
|
|
4255
|
+
|
|
4256
|
+
interface SubIface
|
|
4257
|
+
myValue as string
|
|
4258
|
+
end interface
|
|
4259
|
+
`);
|
|
4260
|
+
program.setFile('components/Widget.bs', `
|
|
4261
|
+
import "pkg:/components/types.bs"
|
|
4262
|
+
|
|
4263
|
+
function getOther(name as string) as SomeIFace
|
|
4264
|
+
other = {subFace: {myValue: name}} as SomeIface
|
|
4265
|
+
return other
|
|
4266
|
+
end function
|
|
4267
|
+
`);
|
|
4268
|
+
program.setFile('components/MainScene.xml', (0, testHelpers_spec_1.trim) `
|
|
4269
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
4270
|
+
<component name="MainScene" extends="Scene">
|
|
4271
|
+
<script uri="MainScene.bs"/>
|
|
4272
|
+
</component>
|
|
4273
|
+
`);
|
|
4274
|
+
program.setFile('components/MainScene.bs', `
|
|
4275
|
+
sub someFunc(widget as roSGNodeWidget)
|
|
4276
|
+
otherNode = widget@.getOther("3.14")
|
|
4277
|
+
print otherNode.subFace.myValue
|
|
4278
|
+
end sub
|
|
4279
|
+
`);
|
|
4280
|
+
program.validate();
|
|
4281
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
4282
|
+
});
|
|
4283
|
+
it('correctly finds error with using unknown member of callfunc return type when return type is custom type', () => {
|
|
4284
|
+
program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
|
|
4285
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
4286
|
+
<component name="Widget" extends="Group">
|
|
4287
|
+
<script uri="Widget.bs"/>
|
|
4288
|
+
<interface>
|
|
4289
|
+
<function name="getOther" />
|
|
4290
|
+
</interface>
|
|
4291
|
+
</component>
|
|
4292
|
+
`);
|
|
4293
|
+
program.setFile('components/types.bs', `
|
|
4294
|
+
interface SomeIFace
|
|
4295
|
+
subFace as SubIface
|
|
4296
|
+
end interface
|
|
4297
|
+
|
|
4298
|
+
interface SubIface
|
|
4299
|
+
myValue as string
|
|
4300
|
+
end interface
|
|
4301
|
+
`);
|
|
4302
|
+
program.setFile('components/Widget.bs', `
|
|
4303
|
+
import "pkg:/components/types.bs"
|
|
4304
|
+
|
|
4305
|
+
function getOther(name as string) as SomeIFace
|
|
4306
|
+
other = {subFace: {myValue: name}} as SomeIface
|
|
4307
|
+
return other
|
|
4308
|
+
end function
|
|
4309
|
+
`);
|
|
4310
|
+
program.setFile('components/MainScene.xml', (0, testHelpers_spec_1.trim) `
|
|
4311
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
4312
|
+
<component name="MainScene" extends="Scene">
|
|
4313
|
+
<script uri="MainScene.bs"/>
|
|
4314
|
+
</component>
|
|
4315
|
+
`);
|
|
4316
|
+
program.setFile('components/MainScene.bs', `
|
|
4317
|
+
sub someFunc(widget as roSGNodeWidget)
|
|
4318
|
+
otherNode = widget@.getOther("3.14")
|
|
4319
|
+
print otherNode.subFace.notIncluded
|
|
4320
|
+
end sub
|
|
4321
|
+
`);
|
|
4322
|
+
program.validate();
|
|
4323
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
4324
|
+
DiagnosticMessages_1.DiagnosticMessages.cannotFindName('notIncluded', 'SubIface.notIncluded', 'SubIface').message
|
|
4325
|
+
]);
|
|
4326
|
+
});
|
|
4327
|
+
it('catches when a non-component type has callfunc invocation', () => {
|
|
4328
|
+
program.setFile('source/test.bs', `
|
|
4329
|
+
sub printName(widget as integer)
|
|
4330
|
+
print widget@.toStr()
|
|
4331
|
+
end sub
|
|
4332
|
+
`);
|
|
4333
|
+
program.validate();
|
|
4334
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
4335
|
+
DiagnosticMessages_1.DiagnosticMessages.cannotFindCallFuncFunction('toStr', 'integer@.toStr', 'integer').message
|
|
4336
|
+
]);
|
|
4337
|
+
});
|
|
4338
|
+
it('allows to types that reference themselves', () => {
|
|
4339
|
+
program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
|
|
4340
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
4341
|
+
<component name="Widget" extends="Group">
|
|
4342
|
+
<script uri="Widget.bs"/>
|
|
4343
|
+
<interface>
|
|
4344
|
+
<function name="getList" />
|
|
4345
|
+
</interface>
|
|
4346
|
+
</component>
|
|
4347
|
+
`);
|
|
4348
|
+
program.setFile('components/types.bs', `
|
|
4349
|
+
interface LinkedList
|
|
4350
|
+
value as integer
|
|
4351
|
+
optional data as roAssociativeArray
|
|
4352
|
+
optional next as LinkedList
|
|
4353
|
+
end interface
|
|
4354
|
+
`);
|
|
4355
|
+
program.setFile('components/Widget.bs', `
|
|
4356
|
+
import "pkg:/components/types.bs"
|
|
4357
|
+
|
|
4358
|
+
function getList() as LinkedList
|
|
4359
|
+
list = {
|
|
4360
|
+
value: 1,
|
|
4361
|
+
next: {
|
|
4362
|
+
value: 2,
|
|
4363
|
+
next: {
|
|
4364
|
+
value: 3
|
|
4365
|
+
}
|
|
4366
|
+
}
|
|
4367
|
+
} as LinkedList
|
|
4368
|
+
return list
|
|
4369
|
+
end function
|
|
4370
|
+
`);
|
|
4371
|
+
program.setFile('components/MainScene.xml', (0, testHelpers_spec_1.trim) `
|
|
4372
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
4373
|
+
<component name="MainScene" extends="Scene">
|
|
4374
|
+
<script uri="MainScene.bs"/>
|
|
4375
|
+
</component>
|
|
4376
|
+
`);
|
|
4377
|
+
program.setFile('components/MainScene.bs', `
|
|
4378
|
+
sub someFunc(widget as roSGNodeWidget)
|
|
4379
|
+
list = widget@.getList()
|
|
4380
|
+
print list.next.next.value
|
|
4381
|
+
end sub
|
|
4382
|
+
`);
|
|
4383
|
+
program.validate();
|
|
4384
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
4385
|
+
});
|
|
4386
|
+
it('finds invalid func name of callfunc()', () => {
|
|
4387
|
+
program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
|
|
4388
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
4389
|
+
<component name="Widget" extends="Group">
|
|
4390
|
+
<script uri="Widget.bs"/>
|
|
4391
|
+
<interface>
|
|
4392
|
+
<function name="getName" />
|
|
4393
|
+
</interface>
|
|
4394
|
+
</component>
|
|
4395
|
+
`);
|
|
4396
|
+
program.setFile('components/Widget.bs', `
|
|
4397
|
+
function getName() as string
|
|
4398
|
+
return "John Doe"
|
|
4399
|
+
end function
|
|
4400
|
+
`);
|
|
4401
|
+
program.setFile('source/test.bs', `
|
|
4402
|
+
sub printName(widget as roSGNodeWidget)
|
|
4403
|
+
print widget.callFunc("whatever")
|
|
4404
|
+
end sub
|
|
4405
|
+
`);
|
|
4406
|
+
program.validate();
|
|
4407
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
4408
|
+
DiagnosticMessages_1.DiagnosticMessages.cannotFindCallFuncFunction('whatever', 'roSGNodeWidget@.whatever', 'roSGNodeWidget').message
|
|
4409
|
+
]);
|
|
4410
|
+
});
|
|
4411
|
+
it('finds invalid func name of @ callfunc invocation', () => {
|
|
4412
|
+
program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
|
|
4413
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
4414
|
+
<component name="Widget" extends="Group">
|
|
4415
|
+
<script uri="Widget.bs"/>
|
|
4416
|
+
<interface>
|
|
4417
|
+
<function name="getName" />
|
|
4418
|
+
</interface>
|
|
4419
|
+
</component>
|
|
4420
|
+
`);
|
|
4421
|
+
program.setFile('components/Widget.bs', `
|
|
4422
|
+
function getName() as string
|
|
4423
|
+
return "John Doe"
|
|
4424
|
+
end function
|
|
4425
|
+
`);
|
|
4426
|
+
program.setFile('source/test.bs', `
|
|
4427
|
+
sub printName(widget as roSGNodeWidget)
|
|
4428
|
+
print widget@.whatever()
|
|
4429
|
+
end sub
|
|
4430
|
+
`);
|
|
4431
|
+
program.validate();
|
|
4432
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
4433
|
+
DiagnosticMessages_1.DiagnosticMessages.cannotFindCallFuncFunction('whatever', 'roSGNodeWidget@.whatever', 'roSGNodeWidget').message
|
|
4434
|
+
]);
|
|
4435
|
+
});
|
|
4436
|
+
it('catches func name of callfunc() with spaces', () => {
|
|
4437
|
+
program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
|
|
4438
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
4439
|
+
<component name="Widget" extends="Group">
|
|
4440
|
+
<script uri="Widget.bs"/>
|
|
4441
|
+
<interface>
|
|
4442
|
+
<function name="getName" />
|
|
4443
|
+
</interface>
|
|
4444
|
+
</component>
|
|
4445
|
+
`);
|
|
4446
|
+
program.setFile('components/Widget.bs', `
|
|
4447
|
+
function getName() as string
|
|
4448
|
+
return "John Doe"
|
|
4449
|
+
end function
|
|
4450
|
+
`);
|
|
4451
|
+
program.setFile('source/test.bs', `
|
|
4452
|
+
sub printName(widget as roSGNodeWidget)
|
|
4453
|
+
print widget.callFunc("whatever the name is")
|
|
4454
|
+
end sub
|
|
4455
|
+
`);
|
|
4456
|
+
program.validate();
|
|
4457
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
4458
|
+
DiagnosticMessages_1.DiagnosticMessages.cannotFindCallFuncFunction('whatever the name is', 'roSGNodeWidget@.whatever the name is', 'roSGNodeWidget').message
|
|
4459
|
+
]);
|
|
4460
|
+
});
|
|
4461
|
+
it('validates arg type of callfunc()', () => {
|
|
4462
|
+
program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
|
|
4463
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
4464
|
+
<component name="Widget" extends="Group">
|
|
4465
|
+
<script uri="Widget.bs"/>
|
|
4466
|
+
<interface>
|
|
4467
|
+
<function name="getName" />
|
|
4468
|
+
</interface>
|
|
4469
|
+
</component>
|
|
4470
|
+
`);
|
|
4471
|
+
program.setFile('components/Widget.bs', `
|
|
4472
|
+
function getName(name as string, count as integer) as string
|
|
4473
|
+
return "John Doe"
|
|
4474
|
+
end function
|
|
4475
|
+
`);
|
|
4476
|
+
program.setFile('source/test.bs', `
|
|
4477
|
+
sub printName(widget as roSGNodeWidget)
|
|
4478
|
+
print widget.callFunc("getName", 12, "not int")
|
|
4479
|
+
end sub
|
|
4480
|
+
`);
|
|
4481
|
+
program.validate();
|
|
4482
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
4483
|
+
DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('integer', 'string').message,
|
|
4484
|
+
DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'integer').message
|
|
4485
|
+
]);
|
|
4486
|
+
});
|
|
4487
|
+
it('has no error on plain roSGNode', () => {
|
|
4488
|
+
program.setFile('source/test.bs', `
|
|
4489
|
+
sub doCallfunc(nodeName as string)
|
|
4490
|
+
node = createObject("roSgNode", nodeName)
|
|
4491
|
+
node.callfunc("someFunc", 1, 2, 3)
|
|
4492
|
+
end sub
|
|
4493
|
+
`);
|
|
4494
|
+
program.validate();
|
|
4495
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
4496
|
+
});
|
|
4497
|
+
it('has error on regular builtIn types', () => {
|
|
4498
|
+
program.setFile('source/test.bs', `
|
|
4499
|
+
sub doCallfunc()
|
|
4500
|
+
node = createObject("roSgNode", "Rectangle")
|
|
4501
|
+
node.callfunc("someFunc", 1, 2, 3)
|
|
4502
|
+
end sub
|
|
4503
|
+
`);
|
|
4504
|
+
program.validate();
|
|
4505
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
4506
|
+
DiagnosticMessages_1.DiagnosticMessages.cannotFindCallFuncFunction('someFunc', 'roSGNodeRectangle@.someFunc', 'roSGNodeRectangle')
|
|
4507
|
+
]);
|
|
4508
|
+
});
|
|
4509
|
+
it('allows callfunc on flexible types', () => {
|
|
4510
|
+
program.setFile('source/test.bs', `
|
|
4511
|
+
sub doCallfunc(obj as object, dyn as dynamic, node as roSGNode)
|
|
4512
|
+
obj.callfunc("testFunc")
|
|
4513
|
+
obj@.testFunc()
|
|
4514
|
+
|
|
4515
|
+
dyn.callfunc("testFunc")
|
|
4516
|
+
dyn@.testFunc()
|
|
4517
|
+
|
|
4518
|
+
node.callfunc("testFunc")
|
|
4519
|
+
node@.testFunc()
|
|
4520
|
+
end sub
|
|
4521
|
+
`);
|
|
4522
|
+
program.validate();
|
|
4523
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
4524
|
+
});
|
|
4525
|
+
it('allows callfunc on components from component library', () => {
|
|
4526
|
+
program.setFile('source/test.bs', `
|
|
4527
|
+
sub doCallfunc()
|
|
4528
|
+
fromComponentLibrary = CreateObject("roSGNode", "library:SomeComponent")
|
|
4529
|
+
fromComponentLibrary@.someFunc()
|
|
4530
|
+
fromComponentLibrary.callfunc("someFunc")
|
|
4531
|
+
end sub
|
|
4532
|
+
`);
|
|
4533
|
+
program.validate();
|
|
4534
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
4535
|
+
});
|
|
4536
|
+
it('allows callfunc on the dynamic result of a function call', () => {
|
|
4537
|
+
program.setFile('source/test.bs', `
|
|
4538
|
+
sub doCallfunc(nodeName)
|
|
4539
|
+
getNode(nodeName)@.someCallFunc(1,2,3)
|
|
4540
|
+
end sub
|
|
4541
|
+
|
|
4542
|
+
function getNode(nodeType)
|
|
4543
|
+
return CreateObject("roSGNode", nodeType)
|
|
4544
|
+
end function
|
|
4545
|
+
`);
|
|
4546
|
+
program.validate();
|
|
4547
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
4548
|
+
});
|
|
4549
|
+
it('validates callfunc on a known result of a function call', () => {
|
|
4550
|
+
program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
|
|
4551
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
4552
|
+
<component name="Widget" extends="Group">
|
|
4553
|
+
<script uri="Widget.bs"/>
|
|
4554
|
+
<interface>
|
|
4555
|
+
<function name="getName" />
|
|
4556
|
+
</interface>
|
|
4557
|
+
</component>
|
|
4558
|
+
`);
|
|
4559
|
+
program.setFile('components/Widget.bs', `
|
|
4560
|
+
function getName(name as string, count as integer) as string
|
|
4561
|
+
return "John Doe"
|
|
4562
|
+
end function
|
|
4563
|
+
`);
|
|
4564
|
+
program.setFile('source/test.bs', `
|
|
4565
|
+
sub doCallfunc()
|
|
4566
|
+
getWidget()@.getName("someStr", "not an int")
|
|
4567
|
+
end sub
|
|
4568
|
+
|
|
4569
|
+
function getWidget() as roSGNodeWidget
|
|
4570
|
+
return CreateObject("roSGNode", "Widget")
|
|
4571
|
+
end function
|
|
4572
|
+
`);
|
|
4573
|
+
program.validate();
|
|
4574
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
4575
|
+
DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'integer').message
|
|
4576
|
+
]);
|
|
4577
|
+
});
|
|
4578
|
+
it('validates callfunc on a known result of a callfunc call', () => {
|
|
4579
|
+
program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
|
|
4580
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
4581
|
+
<component name="Widget" extends="Group">
|
|
4582
|
+
<script uri="Widget.bs"/>
|
|
4583
|
+
<interface>
|
|
4584
|
+
<function name="getName" />
|
|
4585
|
+
<function name="getSelf" />
|
|
4586
|
+
</interface>
|
|
4587
|
+
</component>
|
|
4588
|
+
`);
|
|
4589
|
+
program.setFile('components/Widget.bs', `
|
|
4590
|
+
function getName(name as string, count as integer) as string
|
|
4591
|
+
return "John Doe"
|
|
4592
|
+
end function
|
|
4593
|
+
|
|
4594
|
+
function getSelf() as roSGNodeWidget
|
|
4595
|
+
return m.top
|
|
4596
|
+
end function
|
|
4597
|
+
`);
|
|
4598
|
+
program.setFile('source/test.bs', `
|
|
4599
|
+
sub doCallfunc(widget as roSGNodeWidget)
|
|
4600
|
+
widget@.getSelf()@.getName("someStr", "not an int")
|
|
4601
|
+
end sub
|
|
4602
|
+
`);
|
|
4603
|
+
program.validate();
|
|
4604
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
4605
|
+
DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'integer').message
|
|
4606
|
+
]);
|
|
4607
|
+
});
|
|
4608
|
+
it('respects return value of as callfunc functions', () => {
|
|
4609
|
+
program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
|
|
4610
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
4611
|
+
<component name="Widget" extends="Group">
|
|
4612
|
+
<script uri="Widget.bs"/>
|
|
4613
|
+
<interface>
|
|
4614
|
+
<function name="getInt" />
|
|
4615
|
+
</interface>
|
|
4616
|
+
</component>
|
|
4617
|
+
`);
|
|
4618
|
+
program.setFile('components/Widget.bs', `
|
|
4619
|
+
sub getInt() as integer
|
|
4620
|
+
return 1
|
|
4621
|
+
end sub
|
|
4622
|
+
`);
|
|
4623
|
+
program.setFile('source/test.bs', `
|
|
4624
|
+
sub doCallfunc(widget as roSGNodeWidget)
|
|
4625
|
+
takesInt(widget@.getInt())
|
|
4626
|
+
end sub
|
|
4627
|
+
|
|
4628
|
+
sub takesInt(number as integer)
|
|
4629
|
+
print number
|
|
4630
|
+
end sub
|
|
4631
|
+
`);
|
|
4632
|
+
program.validate();
|
|
4633
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
4634
|
+
});
|
|
4635
|
+
it('respects return value of as callfunc functions - negative case', () => {
|
|
4636
|
+
program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
|
|
4637
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
4638
|
+
<component name="Widget" extends="Group">
|
|
4639
|
+
<script uri="Widget.bs"/>
|
|
4640
|
+
<interface>
|
|
4641
|
+
<function name="getInt" />
|
|
4642
|
+
</interface>
|
|
4643
|
+
</component>
|
|
4644
|
+
`);
|
|
4645
|
+
program.setFile('components/Widget.bs', `
|
|
4646
|
+
sub getInt() as integer
|
|
4647
|
+
return 1
|
|
4648
|
+
end sub
|
|
4649
|
+
`);
|
|
4650
|
+
program.setFile('source/test.bs', `
|
|
4651
|
+
sub doCallfunc(widget as roSGNodeWidget)
|
|
4652
|
+
takesString(widget@.getInt())
|
|
4653
|
+
end sub
|
|
4654
|
+
|
|
4655
|
+
sub takesString(word as string)
|
|
4656
|
+
print word
|
|
4657
|
+
end sub
|
|
4658
|
+
`);
|
|
4659
|
+
program.validate();
|
|
4660
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
4661
|
+
DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('integer', 'string').message
|
|
4662
|
+
]);
|
|
4663
|
+
});
|
|
4664
|
+
it('allows return value of as void functions to be dynamic', () => {
|
|
4665
|
+
program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
|
|
4666
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
|
4667
|
+
<component name="Widget" extends="Group">
|
|
4668
|
+
<script uri="Widget.bs"/>
|
|
4669
|
+
<interface>
|
|
4670
|
+
<function name="noop" />
|
|
4671
|
+
</interface>
|
|
4672
|
+
</component>
|
|
4673
|
+
`);
|
|
4674
|
+
program.setFile('components/Widget.bs', `
|
|
4675
|
+
sub noop()
|
|
4676
|
+
end sub
|
|
4677
|
+
`);
|
|
4678
|
+
program.setFile('source/test.bs', `
|
|
4679
|
+
sub doCallfunc(widget as roSGNodeWidget)
|
|
4680
|
+
takesAny(widget@.noop())
|
|
4681
|
+
end sub
|
|
4682
|
+
|
|
4683
|
+
sub takesAny(anything)
|
|
4684
|
+
print anything
|
|
4685
|
+
end sub
|
|
4686
|
+
`);
|
|
4687
|
+
program.validate();
|
|
4688
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
4689
|
+
});
|
|
4690
|
+
});
|
|
3379
4691
|
});
|
|
3380
4692
|
//# sourceMappingURL=ScopeValidator.spec.js.map
|