@thigasdevelopment/luam 0.19.12 → 1.0.0
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/luam.mjs +670 -89
- package/package.json +1 -1
package/luam.mjs
CHANGED
|
@@ -3161,6 +3161,7 @@ var DEFAULT_COMPILER_OPTIONS = {
|
|
|
3161
3161
|
oop: false,
|
|
3162
3162
|
noUnusedLocals: false,
|
|
3163
3163
|
noUnusedParameters: false,
|
|
3164
|
+
noImplicitGlobals: false,
|
|
3164
3165
|
warningsAsErrors: false
|
|
3165
3166
|
};
|
|
3166
3167
|
var DEFAULT_SOURCE_MAPPING = {
|
|
@@ -3838,7 +3839,21 @@ function parseTypeName(stream) {
|
|
|
3838
3839
|
}
|
|
3839
3840
|
return { kind: "type-name", name: token.value, typeArguments, position: token.position };
|
|
3840
3841
|
}
|
|
3842
|
+
function parseOptionalParameterType(stream) {
|
|
3843
|
+
const name = stream.next().value;
|
|
3844
|
+
const marker = stream.next();
|
|
3845
|
+
stream.next();
|
|
3846
|
+
const annotation = parseTypeAnnotation(stream);
|
|
3847
|
+
if (annotation.kind === "type-optional") {
|
|
3848
|
+
stream.report("parse-redundant-optional", 'The marker on the name already allows "nil". Remove the "?" after the type.', annotation.position);
|
|
3849
|
+
}
|
|
3850
|
+
const element = annotation.kind === "type-optional" ? annotation.element : annotation;
|
|
3851
|
+
return { name, annotation: { kind: "type-optional", element, position: marker.position } };
|
|
3852
|
+
}
|
|
3841
3853
|
function parseParameterType(stream) {
|
|
3854
|
+
if (stream.check("identifier") && stream.checkAhead(1, "operator", "?") && stream.checkAhead(2, "punctuation", ":")) {
|
|
3855
|
+
return parseOptionalParameterType(stream);
|
|
3856
|
+
}
|
|
3842
3857
|
let name = null;
|
|
3843
3858
|
if (stream.check("identifier") && stream.checkAhead(1, "punctuation", ":")) {
|
|
3844
3859
|
name = stream.next().value;
|
|
@@ -3889,7 +3904,7 @@ function parseGroupedType(stream) {
|
|
|
3889
3904
|
return { kind: "type-tuple", elements, position: position2 };
|
|
3890
3905
|
}
|
|
3891
3906
|
function parseObjectMember(stream) {
|
|
3892
|
-
const token = stream.
|
|
3907
|
+
const token = stream.expectMemberKey();
|
|
3893
3908
|
const annotation = parseNamedAnnotation(stream, "field");
|
|
3894
3909
|
if (annotation === null) {
|
|
3895
3910
|
throw stream.error(`Key "${token.value}" of an object type requires a type annotation.`, "parse-invalid-type");
|
|
@@ -4034,9 +4049,16 @@ var TokenStream = class {
|
|
|
4034
4049
|
index = 0;
|
|
4035
4050
|
erased = [];
|
|
4036
4051
|
spans = /* @__PURE__ */ new Map();
|
|
4052
|
+
breaksIndexAtNewline = false;
|
|
4037
4053
|
constructor(tokens) {
|
|
4038
4054
|
this.tokens = tokens;
|
|
4039
4055
|
}
|
|
4056
|
+
stopIndexAtNewline(active) {
|
|
4057
|
+
this.breaksIndexAtNewline = active;
|
|
4058
|
+
}
|
|
4059
|
+
indexContinues(bracket) {
|
|
4060
|
+
return !this.breaksIndexAtNewline || this.index === 0 || bracket.position.line === this.peek(-1).end.line;
|
|
4061
|
+
}
|
|
4040
4062
|
peek(offset = 0) {
|
|
4041
4063
|
const token = this.tokens[Math.min(this.index + offset, this.tokens.length - 1)];
|
|
4042
4064
|
return token;
|
|
@@ -4127,6 +4149,33 @@ var TokenStream = class {
|
|
|
4127
4149
|
const token = this.peek(offset);
|
|
4128
4150
|
return token.kind === "identifier" || token.kind === "keyword" && isLuamKeyword(token.value);
|
|
4129
4151
|
}
|
|
4152
|
+
checkMemberKey(offset = 0) {
|
|
4153
|
+
return this.checkName(offset) || this.peek(offset).kind === "punctuation" && this.peek(offset).value === "[";
|
|
4154
|
+
}
|
|
4155
|
+
expectMemberKey() {
|
|
4156
|
+
if (!this.check("punctuation", "[")) {
|
|
4157
|
+
return this.expectName();
|
|
4158
|
+
}
|
|
4159
|
+
const open = this.next();
|
|
4160
|
+
const literal2 = this.current();
|
|
4161
|
+
if (literal2.kind !== "string") {
|
|
4162
|
+
throw this.error(`Expected a quoted key but found "${this.describeCurrent()}".`, "parse-unexpected-token");
|
|
4163
|
+
}
|
|
4164
|
+
this.next();
|
|
4165
|
+
const close = this.expect("punctuation", "]");
|
|
4166
|
+
return { ...literal2, position: open.position, end: close.end };
|
|
4167
|
+
}
|
|
4168
|
+
reservedNameAt(subject, offset = 0) {
|
|
4169
|
+
const token = this.peek(offset);
|
|
4170
|
+
const next = this.peek(offset + 1);
|
|
4171
|
+
const continues = next.kind === "punctuation" && (next.value === "," || next.value === ")" || next.value === ":") || next.kind === "operator" && (next.value === "?" || next.value === "=");
|
|
4172
|
+
if (token.kind !== "keyword" || !continues) {
|
|
4173
|
+
return null;
|
|
4174
|
+
}
|
|
4175
|
+
const message = `"${token.value}" is a reserved word and cannot name a ${subject}. Rename it \u2014 a property of the same name is still legal, so "value.${token.value}" keeps working.`;
|
|
4176
|
+
this.report("parse-reserved-name", message, token.position);
|
|
4177
|
+
return this.next();
|
|
4178
|
+
}
|
|
4130
4179
|
expectName() {
|
|
4131
4180
|
if (this.checkName()) {
|
|
4132
4181
|
return this.next();
|
|
@@ -4214,7 +4263,8 @@ function parseParameter(stream) {
|
|
|
4214
4263
|
}
|
|
4215
4264
|
return { name: name2, annotation, isVararg: true, position: token.position };
|
|
4216
4265
|
}
|
|
4217
|
-
const
|
|
4266
|
+
const reserved = stream.reservedNameAt("parameter");
|
|
4267
|
+
const name = reserved === null ? stream.expect("identifier").value : reserved.value;
|
|
4218
4268
|
return { name, annotation: parseNamedAnnotation(stream, "parameter"), isVararg: false, position: token.position };
|
|
4219
4269
|
}
|
|
4220
4270
|
function parseParameters(stream) {
|
|
@@ -4406,6 +4456,12 @@ function parsePrimary(stream) {
|
|
|
4406
4456
|
stream.expect("punctuation", ")");
|
|
4407
4457
|
return { kind: "group-expression", expression, position: token.position };
|
|
4408
4458
|
}
|
|
4459
|
+
if (token.kind === "keyword" && isLuamKeyword(token.value)) {
|
|
4460
|
+
const message = `"${token.value}" is a reserved word and cannot be read as a value. Rename the declaration \u2014 a property of the same name is still legal, so "value.${token.value}" keeps working.`;
|
|
4461
|
+
stream.report("parse-reserved-name", message, token.position);
|
|
4462
|
+
stream.next();
|
|
4463
|
+
return { kind: "identifier", name: token.value, position: token.position };
|
|
4464
|
+
}
|
|
4409
4465
|
throw stream.error(`Unexpected "${stream.describeCurrent()}" in expression.`, "parse-unexpected-token");
|
|
4410
4466
|
}
|
|
4411
4467
|
function parseArguments(stream) {
|
|
@@ -4440,6 +4496,9 @@ function parseSuffixed(stream) {
|
|
|
4440
4496
|
continue;
|
|
4441
4497
|
}
|
|
4442
4498
|
if (token.kind === "punctuation" && token.value === "[") {
|
|
4499
|
+
if (!stream.indexContinues(token)) {
|
|
4500
|
+
return expression;
|
|
4501
|
+
}
|
|
4443
4502
|
stream.next();
|
|
4444
4503
|
const index = parseExpression(stream);
|
|
4445
4504
|
stream.expect("punctuation", "]");
|
|
@@ -4622,7 +4681,11 @@ function isDeclarationStart(stream) {
|
|
|
4622
4681
|
if (token.value === "class") {
|
|
4623
4682
|
return isClassHeader(stream, offset);
|
|
4624
4683
|
}
|
|
4625
|
-
|
|
4684
|
+
if (token.value === "interface") {
|
|
4685
|
+
const after = skipTypeParameters(stream, offset + 2);
|
|
4686
|
+
return stream.checkAhead(after, "punctuation", "{") || stream.checkAhead(after, "keyword", "extends");
|
|
4687
|
+
}
|
|
4688
|
+
return stream.checkAhead(offset + 2, "punctuation", "{");
|
|
4626
4689
|
}
|
|
4627
4690
|
function skipDecoratorArguments(stream) {
|
|
4628
4691
|
let depth = 0;
|
|
@@ -4692,6 +4755,14 @@ function parseBraceClassMethod(stream, token, decorators, isStatic) {
|
|
|
4692
4755
|
function parseFieldAnnotation(stream) {
|
|
4693
4756
|
return parseNamedAnnotation(stream, "field");
|
|
4694
4757
|
}
|
|
4758
|
+
function parseFieldValue(stream) {
|
|
4759
|
+
stream.stopIndexAtNewline(true);
|
|
4760
|
+
try {
|
|
4761
|
+
return parseExpression(stream);
|
|
4762
|
+
} finally {
|
|
4763
|
+
stream.stopIndexAtNewline(false);
|
|
4764
|
+
}
|
|
4765
|
+
}
|
|
4695
4766
|
function expectClassFieldBoundary(stream, token) {
|
|
4696
4767
|
const current = stream.current();
|
|
4697
4768
|
const delimiter = current.kind === "punctuation" && (current.value === "}" || current.value === ";" || current.value === ",");
|
|
@@ -4717,7 +4788,7 @@ function parseStaticModifier(stream) {
|
|
|
4717
4788
|
function parseClassMember(stream) {
|
|
4718
4789
|
const decorators = parseDecorators(stream);
|
|
4719
4790
|
const isStatic = parseStaticModifier(stream);
|
|
4720
|
-
const token = stream.
|
|
4791
|
+
const token = stream.expectMemberKey();
|
|
4721
4792
|
if (stream.check("punctuation", "(")) {
|
|
4722
4793
|
stream.report("parse-class-method-form", `Write class member "${token.value}" as "${token.value} = function (...) ... end".`, token.position);
|
|
4723
4794
|
return parseBraceClassMethod(stream, token, decorators, isStatic);
|
|
@@ -4726,7 +4797,7 @@ function parseClassMember(stream) {
|
|
|
4726
4797
|
return parseClassMethod(stream, token, decorators, isStatic);
|
|
4727
4798
|
}
|
|
4728
4799
|
const annotation = parseFieldAnnotation(stream);
|
|
4729
|
-
const value = stream.match("operator", "=") ?
|
|
4800
|
+
const value = stream.match("operator", "=") ? parseFieldValue(stream) : null;
|
|
4730
4801
|
expectClassFieldBoundary(stream, token);
|
|
4731
4802
|
return { kind: "class-field", name: token.value, annotation, value, decorators, isStatic, position: token.position };
|
|
4732
4803
|
}
|
|
@@ -4739,6 +4810,7 @@ function parseClassModifiers(stream, declaration) {
|
|
|
4739
4810
|
}
|
|
4740
4811
|
do {
|
|
4741
4812
|
declaration.interfaces.push(stream.expect("identifier").value);
|
|
4813
|
+
declaration.interfaceArguments.push(parseTypeArguments(stream));
|
|
4742
4814
|
} while (stream.match("punctuation", ","));
|
|
4743
4815
|
}
|
|
4744
4816
|
}
|
|
@@ -4754,6 +4826,7 @@ function parseClassDeclaration(stream, decorators) {
|
|
|
4754
4826
|
superClass: null,
|
|
4755
4827
|
superClassArguments: [],
|
|
4756
4828
|
interfaces: [],
|
|
4829
|
+
interfaceArguments: [],
|
|
4757
4830
|
members: [],
|
|
4758
4831
|
decorators,
|
|
4759
4832
|
position: position2
|
|
@@ -4780,7 +4853,7 @@ function parseClassDeclaration(stream, decorators) {
|
|
|
4780
4853
|
return declaration;
|
|
4781
4854
|
}
|
|
4782
4855
|
function parseInterfaceMember(stream) {
|
|
4783
|
-
const token = stream.
|
|
4856
|
+
const token = stream.expectMemberKey();
|
|
4784
4857
|
if (stream.check("punctuation", "(")) {
|
|
4785
4858
|
const parameters = parseParameters(stream);
|
|
4786
4859
|
const returnAnnotation = parseOptionalAnnotation(stream);
|
|
@@ -4796,6 +4869,7 @@ function parseInterfaceDeclaration(stream) {
|
|
|
4796
4869
|
const checkpoint = stream.checkpoint();
|
|
4797
4870
|
const position2 = stream.next().position;
|
|
4798
4871
|
const name = stream.expect("identifier").value;
|
|
4872
|
+
const typeParameters = parseTypeParameters(stream);
|
|
4799
4873
|
const superInterfaces = [];
|
|
4800
4874
|
const members = [];
|
|
4801
4875
|
if (stream.match("keyword", "extends")) {
|
|
@@ -4818,7 +4892,15 @@ function parseInterfaceDeclaration(stream) {
|
|
|
4818
4892
|
}
|
|
4819
4893
|
}
|
|
4820
4894
|
stream.expect("punctuation", "}");
|
|
4821
|
-
const declaration = {
|
|
4895
|
+
const declaration = {
|
|
4896
|
+
kind: "interface-declaration",
|
|
4897
|
+
name,
|
|
4898
|
+
typeParameters: typeParameters.names,
|
|
4899
|
+
typeConstraints: typeParameters.constraints,
|
|
4900
|
+
superInterfaces,
|
|
4901
|
+
members,
|
|
4902
|
+
position: position2
|
|
4903
|
+
};
|
|
4822
4904
|
stream.eraseFrom(checkpoint, "declaration");
|
|
4823
4905
|
return declaration;
|
|
4824
4906
|
}
|
|
@@ -4879,7 +4961,7 @@ function parseExpressionList(stream) {
|
|
|
4879
4961
|
return values;
|
|
4880
4962
|
}
|
|
4881
4963
|
function parseDeclarator(stream) {
|
|
4882
|
-
const token = stream.expect("identifier");
|
|
4964
|
+
const token = stream.reservedNameAt("local") ?? stream.expect("identifier");
|
|
4883
4965
|
return { name: token.value, annotation: parseNamedAnnotation(stream, "local"), position: token.position };
|
|
4884
4966
|
}
|
|
4885
4967
|
function parseLocalStatement(stream, position2) {
|
|
@@ -4973,7 +5055,30 @@ function invalidStatement(stream, target, start) {
|
|
|
4973
5055
|
const message = `${subject} is not a statement. Assign it with "=", pass it to a call, or remove the line.`;
|
|
4974
5056
|
return stream.errorAt(message, "parse-invalid-statement", start.position, start.end);
|
|
4975
5057
|
}
|
|
5058
|
+
function parseGlobalDeclaration(stream) {
|
|
5059
|
+
const marked = stream.checkAhead(1, "operator", "?") && stream.checkAhead(2, "punctuation", ":");
|
|
5060
|
+
if (!stream.check("identifier") || !marked && !stream.checkAhead(1, "punctuation", ":")) {
|
|
5061
|
+
return null;
|
|
5062
|
+
}
|
|
5063
|
+
const point = stream.speculate();
|
|
5064
|
+
try {
|
|
5065
|
+
const declaration = parseDeclarator(stream);
|
|
5066
|
+
if (declaration.annotation !== null && stream.match("operator", "=")) {
|
|
5067
|
+
return { kind: "global-statement", declaration, values: parseExpressionList(stream), position: declaration.position };
|
|
5068
|
+
}
|
|
5069
|
+
} catch (error) {
|
|
5070
|
+
if (!(error instanceof ParserError)) {
|
|
5071
|
+
throw error;
|
|
5072
|
+
}
|
|
5073
|
+
}
|
|
5074
|
+
stream.rewind(point);
|
|
5075
|
+
return null;
|
|
5076
|
+
}
|
|
4976
5077
|
function parseExpressionStatement(stream) {
|
|
5078
|
+
const declaration = parseGlobalDeclaration(stream);
|
|
5079
|
+
if (declaration !== null) {
|
|
5080
|
+
return declaration;
|
|
5081
|
+
}
|
|
4977
5082
|
const start = stream.current();
|
|
4978
5083
|
const position2 = start.position;
|
|
4979
5084
|
const targets = [parseSuffixed(stream)];
|
|
@@ -5001,7 +5106,8 @@ function parseKeywordStatement(stream, value) {
|
|
|
5001
5106
|
if (stream.check("keyword", "function")) {
|
|
5002
5107
|
return parseFunctionDeclaration(stream, true);
|
|
5003
5108
|
}
|
|
5004
|
-
|
|
5109
|
+
const isEnum = stream.check("keyword", "enum") && stream.checkAhead(1, "identifier");
|
|
5110
|
+
return isEnum ? parseEnumDeclaration(stream, true) : parseLocalStatement(stream, token.position);
|
|
5005
5111
|
}
|
|
5006
5112
|
if (value === "function") {
|
|
5007
5113
|
return parseFunctionDeclaration(stream, false);
|
|
@@ -5266,10 +5372,21 @@ function isEmptyLiteral(type) {
|
|
|
5266
5372
|
return type.kind === "record" && type.isLiteral === true && type.members.size === 0;
|
|
5267
5373
|
}
|
|
5268
5374
|
function widenInferred(type) {
|
|
5375
|
+
if (type.kind === "array") {
|
|
5376
|
+
return createArray(widenInferred(type.element));
|
|
5377
|
+
}
|
|
5378
|
+
if (type.kind === "union") {
|
|
5379
|
+
return createUnion(type.options.map(widenInferred));
|
|
5380
|
+
}
|
|
5269
5381
|
if (type.kind !== "record" || type.isLiteral !== true) {
|
|
5270
5382
|
return widenLiteral(type);
|
|
5271
5383
|
}
|
|
5272
|
-
|
|
5384
|
+
if (type.members.size === 0) {
|
|
5385
|
+
return TABLE_TYPE;
|
|
5386
|
+
}
|
|
5387
|
+
const widened = new Map([...type.members].map(([name, member]) => [name, widenInferred(member)]));
|
|
5388
|
+
const record2 = createObjectType(widened);
|
|
5389
|
+
return record2.kind === "record" ? { ...record2, isInferred: true } : record2;
|
|
5273
5390
|
}
|
|
5274
5391
|
function createFunction(parameters, returnType, minimumArguments2, isVariadic = false, parameterNames, variadicType) {
|
|
5275
5392
|
return {
|
|
@@ -5428,7 +5545,7 @@ function isFunctionAssignable(source, target, options) {
|
|
|
5428
5545
|
return target.returnType.kind === "void" || isAssignable(source.returnType, target.returnType, options);
|
|
5429
5546
|
}
|
|
5430
5547
|
function isMapAssignable(source, target, options) {
|
|
5431
|
-
if (source.kind === "table") {
|
|
5548
|
+
if (source.kind === "table" || isEmptyLiteral(source)) {
|
|
5432
5549
|
return true;
|
|
5433
5550
|
}
|
|
5434
5551
|
if (source.kind === "array") {
|
|
@@ -5741,6 +5858,9 @@ var COMPILER_OPTION_FIELDS = [
|
|
|
5741
5858
|
}),
|
|
5742
5859
|
field("oop", BOOLEAN_TYPE, "Enables the MTA OOP API in the checker and the generated meta.xml.", { defaultValue: DEFAULT_COMPILER_OPTIONS.oop }),
|
|
5743
5860
|
field("noUnusedLocals", BOOLEAN_TYPE, "Reports local declarations that are never read.", { defaultValue: DEFAULT_COMPILER_OPTIONS.noUnusedLocals }),
|
|
5861
|
+
field("noImplicitGlobals", BOOLEAN_TYPE, "Reports an assignment that creates a global the project never declares.", {
|
|
5862
|
+
defaultValue: DEFAULT_COMPILER_OPTIONS.noImplicitGlobals
|
|
5863
|
+
}),
|
|
5744
5864
|
field("noUnusedParameters", BOOLEAN_TYPE, "Reports function and method parameters that are never read.", {
|
|
5745
5865
|
defaultValue: DEFAULT_COMPILER_OPTIONS.noUnusedParameters
|
|
5746
5866
|
}),
|
|
@@ -6802,6 +6922,7 @@ function readCompilerOptions(value) {
|
|
|
6802
6922
|
strict: flag(source, "strict", DEFAULT_COMPILER_OPTIONS.strict),
|
|
6803
6923
|
oop: flag(source, "oop", DEFAULT_COMPILER_OPTIONS.oop),
|
|
6804
6924
|
noUnusedLocals: flag(source, "noUnusedLocals", DEFAULT_COMPILER_OPTIONS.noUnusedLocals),
|
|
6925
|
+
noImplicitGlobals: flag(source, "noImplicitGlobals", DEFAULT_COMPILER_OPTIONS.noImplicitGlobals),
|
|
6805
6926
|
noUnusedParameters: flag(source, "noUnusedParameters", DEFAULT_COMPILER_OPTIONS.noUnusedParameters),
|
|
6806
6927
|
warningsAsErrors: flag(source, "warningsAsErrors", DEFAULT_COMPILER_OPTIONS.warningsAsErrors)
|
|
6807
6928
|
};
|
|
@@ -6978,7 +7099,7 @@ import { tmpdir } from "node:os";
|
|
|
6978
7099
|
import { join as join2 } from "node:path";
|
|
6979
7100
|
|
|
6980
7101
|
// src/cli/version.ts
|
|
6981
|
-
var VERSION = true ? "0.
|
|
7102
|
+
var VERSION = true ? "1.0.0" : "0.0.0-dev";
|
|
6982
7103
|
var PROGRAM_NAME = "luam";
|
|
6983
7104
|
var PROGRAM_DESCRIPTION = "luam \u2014 the Luam compiler for Multi Theft Auto resources.";
|
|
6984
7105
|
|
|
@@ -7042,7 +7163,7 @@ function runEditorCommand(command, args) {
|
|
|
7042
7163
|
}
|
|
7043
7164
|
|
|
7044
7165
|
// src/editor/editor-service.ts
|
|
7045
|
-
var EXTENSION_ID = "
|
|
7166
|
+
var EXTENSION_ID = "luam.luam";
|
|
7046
7167
|
var SUPPORTED_EDITORS = [
|
|
7047
7168
|
{ id: "vscode", name: "Visual Studio Code", command: "code" },
|
|
7048
7169
|
{ id: "vscode-insiders", name: "Visual Studio Code Insiders", command: "code-insiders" },
|
|
@@ -8862,12 +8983,13 @@ var TEST_DECLARATIONS = [
|
|
|
8862
8983
|
|
|
8863
8984
|
// ../compiler/src/checker/ambient.ts
|
|
8864
8985
|
var EVENT_NAME_PREFIX = "event:";
|
|
8865
|
-
var EMPTY_AMBIENT = { classes: [], interfaces: [], enums: [], globals: [], events: [] };
|
|
8986
|
+
var EMPTY_AMBIENT = { classes: [], interfaces: [], enums: [], aliases: [], globals: [], events: [] };
|
|
8866
8987
|
function ambientFromRegistry(registry) {
|
|
8867
8988
|
return {
|
|
8868
8989
|
classes: registry.allClasses(),
|
|
8869
8990
|
interfaces: registry.allInterfaces(),
|
|
8870
8991
|
enums: registry.allEnums().filter((info) => info.isLocal !== true),
|
|
8992
|
+
aliases: registry.allAliases(),
|
|
8871
8993
|
globals: registry.allGlobals(),
|
|
8872
8994
|
events: registry.allEvents()
|
|
8873
8995
|
};
|
|
@@ -8885,6 +9007,7 @@ function ownDeclarations(registry, ambient) {
|
|
|
8885
9007
|
classes: withoutNames(all.classes, ambient.classes),
|
|
8886
9008
|
interfaces: withoutNames(all.interfaces, ambient.interfaces),
|
|
8887
9009
|
enums: withoutNames(all.enums, ambient.enums),
|
|
9010
|
+
aliases: withoutNames(all.aliases, ambient.aliases),
|
|
8888
9011
|
globals: withoutNames(all.globals, ambient.globals),
|
|
8889
9012
|
events: withoutNames(all.events, ambient.events)
|
|
8890
9013
|
};
|
|
@@ -8903,6 +9026,7 @@ function mergeAmbient(sources) {
|
|
|
8903
9026
|
classes: mergeByName(sources.map((source) => source.classes)),
|
|
8904
9027
|
interfaces: mergeByName(sources.map((source) => source.interfaces)),
|
|
8905
9028
|
enums: mergeByName(sources.map((source) => source.enums)),
|
|
9029
|
+
aliases: mergeByName(sources.map((source) => source.aliases)),
|
|
8906
9030
|
globals: mergeByName(sources.map((source) => source.globals)),
|
|
8907
9031
|
events: mergeByName(sources.map((source) => source.events))
|
|
8908
9032
|
};
|
|
@@ -8977,6 +9101,9 @@ function declareAll(catalog, environment, source) {
|
|
|
8977
9101
|
function isAvailableIn(declared, environment) {
|
|
8978
9102
|
return declared === "shared" || declared === environment;
|
|
8979
9103
|
}
|
|
9104
|
+
function isVisibleIn(declared, environment) {
|
|
9105
|
+
return environment === "shared" || isAvailableIn(declared, environment);
|
|
9106
|
+
}
|
|
8980
9107
|
|
|
8981
9108
|
// ../compiler/src/checker/api-types.ts
|
|
8982
9109
|
var PRIMITIVES = {
|
|
@@ -9195,6 +9322,9 @@ var MAX_DEPTH = 32;
|
|
|
9195
9322
|
function classSubstitutions(info, typeArguments) {
|
|
9196
9323
|
return new Map(info.typeParameters.map((parameter, index) => [parameter, typeArguments[index] ?? ANY_TYPE]));
|
|
9197
9324
|
}
|
|
9325
|
+
function parameterSubstitutions(typeParameters, typeArguments) {
|
|
9326
|
+
return new Map(typeParameters.map((parameter, index) => [parameter, typeArguments[index] ?? ANY_TYPE]));
|
|
9327
|
+
}
|
|
9198
9328
|
function parentSubstitutions(registry, info, current) {
|
|
9199
9329
|
const parent = info.superClass === null ? null : registry.lookupClass(info.superClass);
|
|
9200
9330
|
if (parent === null) {
|
|
@@ -9222,7 +9352,15 @@ function substitutionsFor(registry, receiver, owner) {
|
|
|
9222
9352
|
}
|
|
9223
9353
|
return /* @__PURE__ */ new Map();
|
|
9224
9354
|
}
|
|
9355
|
+
function interfaceSubstitutions(registry, receiver) {
|
|
9356
|
+
const contract = registry.lookupInterface(receiver.name);
|
|
9357
|
+
return contract === null ? null : parameterSubstitutions(contract.typeParameters, receiver.typeArguments ?? []);
|
|
9358
|
+
}
|
|
9225
9359
|
function specializeMember(context, receiver, member, property) {
|
|
9360
|
+
const contract = interfaceSubstitutions(context.declarations, receiver);
|
|
9361
|
+
if (contract !== null) {
|
|
9362
|
+
return contract.size === 0 ? member : { ...member, type: substituteType(member.type, contract) };
|
|
9363
|
+
}
|
|
9226
9364
|
const owner = context.declarations.lookupMemberOwner(receiver.name, property);
|
|
9227
9365
|
if (owner === null || owner === receiver.name) {
|
|
9228
9366
|
const own = context.declarations.lookupClass(receiver.name);
|
|
@@ -9307,6 +9445,11 @@ function reportConstraintViolations(context, owner, typeParameters, typeConstrai
|
|
|
9307
9445
|
});
|
|
9308
9446
|
}
|
|
9309
9447
|
function checkTypeConstraints(context, name, typeArguments, position2) {
|
|
9448
|
+
const contract = context.declarations.lookupInterface(name);
|
|
9449
|
+
if (contract !== null) {
|
|
9450
|
+
reportConstraintViolations(context, `interface "${name}"`, contract.typeParameters, contract.typeConstraints, typeArguments, position2);
|
|
9451
|
+
return;
|
|
9452
|
+
}
|
|
9310
9453
|
const info = context.declarations.lookupClass(name);
|
|
9311
9454
|
if (info === null) {
|
|
9312
9455
|
return;
|
|
@@ -12233,10 +12376,14 @@ var MTA_EXACT = {
|
|
|
12233
12376
|
client: MTA_CLIENT_GLOBALS
|
|
12234
12377
|
};
|
|
12235
12378
|
function globalsFor(environment) {
|
|
12236
|
-
|
|
12379
|
+
const resolved2 = /* @__PURE__ */ new Map();
|
|
12380
|
+
for (const declaration of DECLARATIONS) {
|
|
12237
12381
|
const exact = findDeclaration(declaration.name, environment);
|
|
12238
|
-
|
|
12239
|
-
|
|
12382
|
+
if (exact !== null && !resolved2.has(exact.name)) {
|
|
12383
|
+
resolved2.set(exact.name, exact);
|
|
12384
|
+
}
|
|
12385
|
+
}
|
|
12386
|
+
return [...resolved2.values()];
|
|
12240
12387
|
}
|
|
12241
12388
|
function findDeclaration(name, environment) {
|
|
12242
12389
|
const declaration = BY_NAME.get(name);
|
|
@@ -12244,7 +12391,7 @@ function findDeclaration(name, environment) {
|
|
|
12244
12391
|
return declaration ?? null;
|
|
12245
12392
|
}
|
|
12246
12393
|
if (!isAvailableIn(declaration.environment, environment)) {
|
|
12247
|
-
return null;
|
|
12394
|
+
return environment === "shared" ? declaration : null;
|
|
12248
12395
|
}
|
|
12249
12396
|
if (declaration.source !== "mta") {
|
|
12250
12397
|
return declaration;
|
|
@@ -14049,11 +14196,15 @@ var DeclarationRegistry = class {
|
|
|
14049
14196
|
classes = /* @__PURE__ */ new Map();
|
|
14050
14197
|
interfaces = /* @__PURE__ */ new Map();
|
|
14051
14198
|
enums = /* @__PURE__ */ new Map();
|
|
14199
|
+
aliases = /* @__PURE__ */ new Map();
|
|
14052
14200
|
globals = /* @__PURE__ */ new Map();
|
|
14053
14201
|
events = /* @__PURE__ */ new Map();
|
|
14054
14202
|
declareGlobal(info) {
|
|
14055
14203
|
this.globals.set(info.name, info);
|
|
14056
14204
|
}
|
|
14205
|
+
lookupGlobal(name) {
|
|
14206
|
+
return this.globals.get(name) ?? null;
|
|
14207
|
+
}
|
|
14057
14208
|
allGlobals() {
|
|
14058
14209
|
return [...this.globals.values()];
|
|
14059
14210
|
}
|
|
@@ -14089,6 +14240,15 @@ var DeclarationRegistry = class {
|
|
|
14089
14240
|
declareEnum(info) {
|
|
14090
14241
|
this.enums.set(info.name, info);
|
|
14091
14242
|
}
|
|
14243
|
+
declareAlias(info) {
|
|
14244
|
+
this.aliases.set(info.name, info);
|
|
14245
|
+
}
|
|
14246
|
+
lookupAlias(name) {
|
|
14247
|
+
return this.aliases.get(name) ?? null;
|
|
14248
|
+
}
|
|
14249
|
+
allAliases() {
|
|
14250
|
+
return [...this.aliases.values()];
|
|
14251
|
+
}
|
|
14092
14252
|
lookupEnum(name) {
|
|
14093
14253
|
return this.enums.get(name) ?? null;
|
|
14094
14254
|
}
|
|
@@ -14229,6 +14389,7 @@ function buildRegistry() {
|
|
|
14229
14389
|
superClass: declaration.parent,
|
|
14230
14390
|
superArguments: [],
|
|
14231
14391
|
interfaces: [],
|
|
14392
|
+
interfaceArguments: [],
|
|
14232
14393
|
members,
|
|
14233
14394
|
statics: /* @__PURE__ */ new Map(),
|
|
14234
14395
|
position: MTA_POSITION
|
|
@@ -14435,6 +14596,11 @@ var CheckContext = class {
|
|
|
14435
14596
|
ambientClasses = /* @__PURE__ */ new Set();
|
|
14436
14597
|
ambientInterfaces = /* @__PURE__ */ new Set();
|
|
14437
14598
|
ambientEnums = /* @__PURE__ */ new Set();
|
|
14599
|
+
ambientAliases = /* @__PURE__ */ new Set();
|
|
14600
|
+
ambientGlobals = /* @__PURE__ */ new Set();
|
|
14601
|
+
obligations = /* @__PURE__ */ new Map();
|
|
14602
|
+
blockDepth = 0;
|
|
14603
|
+
noImplicitGlobals = false;
|
|
14438
14604
|
constructor(mode, environment, ambient = EMPTY_AMBIENT, project = EMPTY_PROJECT_DECLARATIONS, oop = false) {
|
|
14439
14605
|
this.mode = mode;
|
|
14440
14606
|
this.environment = environment;
|
|
@@ -14510,6 +14676,24 @@ var CheckContext = class {
|
|
|
14510
14676
|
isAmbientEnum(name) {
|
|
14511
14677
|
return this.ambientEnums.has(name);
|
|
14512
14678
|
}
|
|
14679
|
+
isAmbientAlias(name) {
|
|
14680
|
+
return this.ambientAliases.has(name);
|
|
14681
|
+
}
|
|
14682
|
+
isAmbientGlobal(name) {
|
|
14683
|
+
return this.ambientGlobals.has(name);
|
|
14684
|
+
}
|
|
14685
|
+
openRecordObligation(obligation) {
|
|
14686
|
+
this.obligations.set(obligation.path, obligation);
|
|
14687
|
+
}
|
|
14688
|
+
recordObligation(path) {
|
|
14689
|
+
return this.obligations.get(path) ?? null;
|
|
14690
|
+
}
|
|
14691
|
+
closeRecordObligation(path) {
|
|
14692
|
+
this.obligations.delete(path);
|
|
14693
|
+
}
|
|
14694
|
+
recordObligationPaths() {
|
|
14695
|
+
return [...this.obligations.keys()];
|
|
14696
|
+
}
|
|
14513
14697
|
noteExternalReference(name, position2) {
|
|
14514
14698
|
if (!this.externalReferences.has(name)) {
|
|
14515
14699
|
this.externalReferences.set(name, position2);
|
|
@@ -14679,19 +14863,28 @@ var CheckContext = class {
|
|
|
14679
14863
|
assignability() {
|
|
14680
14864
|
return { allowNil: this.allowNil, resolveNominal: (name) => this.nominalShape(name) };
|
|
14681
14865
|
}
|
|
14682
|
-
|
|
14866
|
+
resolveValueAnnotation(annotation, subject) {
|
|
14867
|
+
const resolved2 = this.resolveAnnotation(annotation);
|
|
14868
|
+
if (resolved2.kind !== "tuple") {
|
|
14869
|
+
return resolved2;
|
|
14870
|
+
}
|
|
14871
|
+
const message = `A parenthesised list like "${typeToString(resolved2)}" is a return shape and cannot type ${subject}. Name one type instead.`;
|
|
14872
|
+
this.report("check-tuple-position", message, annotation.position);
|
|
14873
|
+
return firstValueOf(resolved2);
|
|
14874
|
+
}
|
|
14875
|
+
expectAssignable(source, target, position2, subject, printed = target) {
|
|
14683
14876
|
if (isAssignable(source, target, this.assignability())) {
|
|
14684
14877
|
return;
|
|
14685
14878
|
}
|
|
14686
14879
|
const received = isLiteralType(target) || target.kind === "union" ? source : widenLiteral(source);
|
|
14687
|
-
const message = `${subject} expects "${typeToString(
|
|
14880
|
+
const message = `${subject} expects "${typeToString(printed)}" but received "${typeToString(received)}".`;
|
|
14688
14881
|
const hint = `${nilHint(source, target, this.mode)}${missingKeyHint(source, target, (name) => this.nominalShape(name))}`;
|
|
14689
14882
|
this.report("check-type-mismatch", `${message}${hint}`, position2);
|
|
14690
14883
|
}
|
|
14691
14884
|
declareProject(project) {
|
|
14692
14885
|
for (const declaration of project.globals) {
|
|
14693
14886
|
this.projectEnvironments.set(declaration.name, declaration.environment);
|
|
14694
|
-
if (
|
|
14887
|
+
if (isVisibleIn(declaration.environment, this.environment)) {
|
|
14695
14888
|
const symbol = { name: declaration.name, type: descriptorToType(declaration.type), isLocal: false, position: PROJECT_POSITION };
|
|
14696
14889
|
this.binder.declareGlobal(symbol);
|
|
14697
14890
|
}
|
|
@@ -14712,7 +14905,14 @@ var CheckContext = class {
|
|
|
14712
14905
|
this.declarations.declareEnum(info);
|
|
14713
14906
|
this.binder.declareGlobal({ name: info.name, type: createNamed(info.name), isLocal: false, position: info.position });
|
|
14714
14907
|
}
|
|
14908
|
+
for (const info of ambient.aliases) {
|
|
14909
|
+
this.ambientAliases.add(info.name);
|
|
14910
|
+
this.binder.declareAlias(info.name, info.type, info.typeParameters);
|
|
14911
|
+
this.declarations.declareAlias(info);
|
|
14912
|
+
}
|
|
14715
14913
|
for (const info of ambient.globals) {
|
|
14914
|
+
this.ambientGlobals.add(info.name);
|
|
14915
|
+
this.declarations.declareGlobal(info);
|
|
14716
14916
|
this.binder.declareGlobal({ name: info.name, type: info.type, isLocal: false, position: info.position });
|
|
14717
14917
|
}
|
|
14718
14918
|
for (const info of ambient.events) {
|
|
@@ -14732,18 +14932,20 @@ var CheckContext = class {
|
|
|
14732
14932
|
return createMap(this.resolveAnnotation(key), this.resolveAnnotation(value));
|
|
14733
14933
|
}
|
|
14734
14934
|
resolveClassAnnotation(name, typeArguments, position2) {
|
|
14735
|
-
const
|
|
14935
|
+
const declaredInterface = this.declarations.lookupInterface(name);
|
|
14936
|
+
const owner = declaredInterface === null ? "Class" : "Interface";
|
|
14937
|
+
const declared = declaredInterface?.typeParameters ?? this.declarations.lookupClass(name)?.typeParameters ?? [];
|
|
14736
14938
|
const resolved2 = typeArguments.map((argument) => this.resolveAnnotation(argument));
|
|
14737
14939
|
if (declared.length === 0) {
|
|
14738
14940
|
return createNamed(name);
|
|
14739
14941
|
}
|
|
14740
14942
|
if (resolved2.length !== declared.length) {
|
|
14741
14943
|
const expected = declared.length === 1 ? "1 type argument" : `${declared.length} type arguments`;
|
|
14742
|
-
this.report("check-generic-arity",
|
|
14944
|
+
this.report("check-generic-arity", `${owner} "${name}" expects ${expected} but received ${resolved2.length}.`, position2);
|
|
14743
14945
|
}
|
|
14744
14946
|
const specialized = createNamed(name, declared.map((unused, index) => resolved2[index] ?? ANY_TYPE));
|
|
14745
14947
|
if (namedNesting(specialized) > MAX_GENERIC_DEPTH) {
|
|
14746
|
-
const message =
|
|
14948
|
+
const message = `${owner} "${name}" is nested more than ${MAX_GENERIC_DEPTH} levels deep here. Name the inner type with a "type" alias.`;
|
|
14747
14949
|
this.report("check-generic-depth", message, position2);
|
|
14748
14950
|
return createNamed(name);
|
|
14749
14951
|
}
|
|
@@ -14789,6 +14991,7 @@ var ALLOWED = /* @__PURE__ */ new Set([
|
|
|
14789
14991
|
var LABELS = {
|
|
14790
14992
|
"local-statement": 'A "local" declaration',
|
|
14791
14993
|
"assignment-statement": "An assignment",
|
|
14994
|
+
"global-statement": "A global declaration",
|
|
14792
14995
|
"call-statement": "A call",
|
|
14793
14996
|
"return-statement": 'A "return"',
|
|
14794
14997
|
"break-statement": 'A "break"',
|
|
@@ -14848,6 +15051,7 @@ function statementExpressions(statement) {
|
|
|
14848
15051
|
switch (statement.kind) {
|
|
14849
15052
|
case "local-statement":
|
|
14850
15053
|
case "return-statement":
|
|
15054
|
+
case "global-statement":
|
|
14851
15055
|
return statement.values;
|
|
14852
15056
|
case "assignment-statement":
|
|
14853
15057
|
return [...statement.targets, ...statement.values];
|
|
@@ -14995,18 +15199,28 @@ function checkContract(context, info, contract, member) {
|
|
|
14995
15199
|
const message = `${subject} expects "${typeToString(member.type)}" from interface "${contract}" but is "${typeToString(actual.type)}".`;
|
|
14996
15200
|
context.report("check-unimplemented-interface", message, actual.position);
|
|
14997
15201
|
}
|
|
15202
|
+
function contractName(name, typeArguments) {
|
|
15203
|
+
return typeArguments.length === 0 ? name : `${name}<${typeArguments.map(typeToString).join(", ")}>`;
|
|
15204
|
+
}
|
|
14998
15205
|
function checkInterfaces(context, info) {
|
|
14999
|
-
|
|
15206
|
+
info.interfaces.forEach((name, index) => {
|
|
15000
15207
|
const contract = context.declarations.lookupInterface(name);
|
|
15001
15208
|
if (contract === null) {
|
|
15002
15209
|
context.noteExternalReference(name, info.position);
|
|
15003
15210
|
context.report("check-unknown-interface", `Class "${info.name}" implements "${name}", which is not defined.`, info.position);
|
|
15004
|
-
|
|
15211
|
+
return;
|
|
15005
15212
|
}
|
|
15213
|
+
const typeArguments = info.interfaceArguments[index] ?? [];
|
|
15214
|
+
if (contract.typeParameters.length > 0 && typeArguments.length !== contract.typeParameters.length) {
|
|
15215
|
+
const expected = contract.typeParameters.length === 1 ? "1 type argument" : `${contract.typeParameters.length} type arguments`;
|
|
15216
|
+
context.report("check-generic-arity", `Interface "${name}" expects ${expected} but received ${typeArguments.length}.`, info.position);
|
|
15217
|
+
}
|
|
15218
|
+
const substitutions = parameterSubstitutions(contract.typeParameters, typeArguments);
|
|
15219
|
+
const label2 = contractName(name, typeArguments);
|
|
15006
15220
|
for (const member of context.declarations.collectInterfaceContract(contract.name)) {
|
|
15007
|
-
checkContract(context, info,
|
|
15221
|
+
checkContract(context, info, label2, substitutions.size === 0 ? member : { ...member, type: substituteType(member.type, substitutions) });
|
|
15008
15222
|
}
|
|
15009
|
-
}
|
|
15223
|
+
});
|
|
15010
15224
|
}
|
|
15011
15225
|
function checkOverrides(context, info, statement) {
|
|
15012
15226
|
for (const member of statement.members) {
|
|
@@ -15615,6 +15829,7 @@ function statementExpressions2(statement) {
|
|
|
15615
15829
|
switch (statement.kind) {
|
|
15616
15830
|
case "local-statement":
|
|
15617
15831
|
case "return-statement":
|
|
15832
|
+
case "global-statement":
|
|
15618
15833
|
return statement.values;
|
|
15619
15834
|
case "assignment-statement":
|
|
15620
15835
|
return [...statement.targets, ...statement.values];
|
|
@@ -15672,6 +15887,9 @@ function addTargets(statement, paths) {
|
|
|
15672
15887
|
if (statement.kind === "local-statement") {
|
|
15673
15888
|
statement.declarations.forEach((declaration) => paths.add(declaration.name));
|
|
15674
15889
|
}
|
|
15890
|
+
if (statement.kind === "global-statement") {
|
|
15891
|
+
paths.add(statement.declaration.name);
|
|
15892
|
+
}
|
|
15675
15893
|
}
|
|
15676
15894
|
function collectPaths(body, paths) {
|
|
15677
15895
|
for (const statement of body) {
|
|
@@ -19083,21 +19301,42 @@ function eventHandler(name, environment) {
|
|
|
19083
19301
|
return MTA_EVENT_SIGNATURES[environment][name] ?? null;
|
|
19084
19302
|
}
|
|
19085
19303
|
|
|
19086
|
-
// ../compiler/src/checker/environment-
|
|
19087
|
-
var EVENT_FUNCTIONS = /* @__PURE__ */ new Set(["addEventHandler", "removeEventHandler", "triggerEvent"]);
|
|
19304
|
+
// ../compiler/src/checker/environment-message.ts
|
|
19088
19305
|
function scopeLabel(environment) {
|
|
19089
19306
|
return environment === "shared" ? "shared" : `${environment}-only`;
|
|
19090
19307
|
}
|
|
19308
|
+
function unavailableTail(environment) {
|
|
19309
|
+
return `is not available in a "${environment}" file.`;
|
|
19310
|
+
}
|
|
19311
|
+
function unusableTail(environment) {
|
|
19312
|
+
return `cannot be used in a "${environment}" file.`;
|
|
19313
|
+
}
|
|
19314
|
+
function reportEnvironment(context, code, message, position2) {
|
|
19315
|
+
if (context.environment === "shared") {
|
|
19316
|
+
return;
|
|
19317
|
+
}
|
|
19318
|
+
context.report(code, message, position2);
|
|
19319
|
+
}
|
|
19320
|
+
|
|
19321
|
+
// ../compiler/src/checker/environment-checks.ts
|
|
19322
|
+
var EVENT_FUNCTIONS = /* @__PURE__ */ new Set(["addEventHandler", "removeEventHandler", "triggerEvent"]);
|
|
19323
|
+
function reportProject(context, name, declared, position2) {
|
|
19324
|
+
const message = `"${name}" is declared by the project, is ${scopeLabel(declared)}, and ${unavailableTail(context.environment)}`;
|
|
19325
|
+
reportEnvironment(context, "check-environment-api", message, position2);
|
|
19326
|
+
}
|
|
19327
|
+
function reportApi(context, name, declared, position2) {
|
|
19328
|
+
const message = `API "${name}" is ${scopeLabel(declared)} and ${unavailableTail(context.environment)}`;
|
|
19329
|
+
reportEnvironment(context, "check-environment-api", message, position2);
|
|
19330
|
+
}
|
|
19091
19331
|
function checkGlobalReference(context, name, position2) {
|
|
19092
19332
|
if (name === "self") {
|
|
19093
|
-
const
|
|
19094
|
-
context.report("check-invalid-self",
|
|
19333
|
+
const message = 'A "self" is only bound inside a class method or a "function Name:method()"; here it reads a global that is "nil".';
|
|
19334
|
+
context.report("check-invalid-self", message, position2);
|
|
19095
19335
|
return;
|
|
19096
19336
|
}
|
|
19097
19337
|
const project = context.projectEnvironmentOf(name);
|
|
19098
19338
|
if (project !== null) {
|
|
19099
|
-
|
|
19100
|
-
context.report("check-environment-api", message2, position2);
|
|
19339
|
+
reportProject(context, name, project, position2);
|
|
19101
19340
|
return;
|
|
19102
19341
|
}
|
|
19103
19342
|
const declared = declarationEnvironment(name);
|
|
@@ -19105,8 +19344,26 @@ function checkGlobalReference(context, name, position2) {
|
|
|
19105
19344
|
context.noteExternalReference(name, position2);
|
|
19106
19345
|
return;
|
|
19107
19346
|
}
|
|
19108
|
-
|
|
19109
|
-
|
|
19347
|
+
reportApi(context, name, declared, position2);
|
|
19348
|
+
}
|
|
19349
|
+
function checkSharedReference(context, name, position2) {
|
|
19350
|
+
if (context.environment !== "shared" || context.moduleGlobals.has(name)) {
|
|
19351
|
+
return;
|
|
19352
|
+
}
|
|
19353
|
+
const project = context.projectEnvironmentOf(name);
|
|
19354
|
+
if (project !== null) {
|
|
19355
|
+
if (project !== "shared") {
|
|
19356
|
+
reportProject(context, name, project, position2);
|
|
19357
|
+
}
|
|
19358
|
+
return;
|
|
19359
|
+
}
|
|
19360
|
+
if (!context.binder.isBuiltinReference(name)) {
|
|
19361
|
+
return;
|
|
19362
|
+
}
|
|
19363
|
+
const declared = declarationEnvironment(name);
|
|
19364
|
+
if (declared !== null && declared !== "shared") {
|
|
19365
|
+
reportApi(context, name, declared, position2);
|
|
19366
|
+
}
|
|
19110
19367
|
}
|
|
19111
19368
|
function eventName(expression) {
|
|
19112
19369
|
const argument = expression.args[0];
|
|
@@ -19125,8 +19382,8 @@ function checkEventUsage(context, expression) {
|
|
|
19125
19382
|
if (name === null || custom?.environment === "shared" || custom?.environment === context.environment || declared === null || declared === context.environment) {
|
|
19126
19383
|
return;
|
|
19127
19384
|
}
|
|
19128
|
-
const message = `Event "${name}" is ${scopeLabel(declared)} and
|
|
19129
|
-
context
|
|
19385
|
+
const message = `Event "${name}" is ${scopeLabel(declared)} and ${unusableTail(context.environment)}`;
|
|
19386
|
+
reportEnvironment(context, "check-environment-event", message, expression.position);
|
|
19130
19387
|
}
|
|
19131
19388
|
|
|
19132
19389
|
// ../mta-types/src/event-call-semantics.ts
|
|
@@ -19307,6 +19564,136 @@ function withoutSelfParameter(signature2) {
|
|
|
19307
19564
|
return createFunction(signature2.parameters.slice(1), signature2.returnType, minimum, signature2.isVariadic, names.slice(1), signature2.variadicType);
|
|
19308
19565
|
}
|
|
19309
19566
|
|
|
19567
|
+
// ../compiler/src/checker/record-completion.ts
|
|
19568
|
+
function recordShapeOf(context, type) {
|
|
19569
|
+
if (type.kind === "record") {
|
|
19570
|
+
return type;
|
|
19571
|
+
}
|
|
19572
|
+
if (type.kind !== "named") {
|
|
19573
|
+
return null;
|
|
19574
|
+
}
|
|
19575
|
+
const shape = context.assignability().resolveNominal?.(type.name) ?? null;
|
|
19576
|
+
return shape === null ? null : { kind: "record", name: type.name, origin: null, members: shape.members };
|
|
19577
|
+
}
|
|
19578
|
+
function pendingKeys(context, source, target) {
|
|
19579
|
+
if (source.kind !== "record" || source.isLiteral !== true) {
|
|
19580
|
+
return null;
|
|
19581
|
+
}
|
|
19582
|
+
const shape = recordShapeOf(context, target);
|
|
19583
|
+
if (shape === null) {
|
|
19584
|
+
return null;
|
|
19585
|
+
}
|
|
19586
|
+
const missing2 = /* @__PURE__ */ new Map();
|
|
19587
|
+
const options = context.assignability();
|
|
19588
|
+
for (const [name, member] of shape.members) {
|
|
19589
|
+
const written = source.members.get(name);
|
|
19590
|
+
if (written === void 0) {
|
|
19591
|
+
if (member.kind !== "optional") {
|
|
19592
|
+
missing2.set(name, member);
|
|
19593
|
+
}
|
|
19594
|
+
continue;
|
|
19595
|
+
}
|
|
19596
|
+
if (!isAssignable(written, member, options)) {
|
|
19597
|
+
return null;
|
|
19598
|
+
}
|
|
19599
|
+
}
|
|
19600
|
+
for (const name of source.members.keys()) {
|
|
19601
|
+
if (!shape.members.has(name)) {
|
|
19602
|
+
return null;
|
|
19603
|
+
}
|
|
19604
|
+
}
|
|
19605
|
+
return missing2.size === 0 ? null : missing2;
|
|
19606
|
+
}
|
|
19607
|
+
function deferRecordCompletion(context, target, source, declared, subject, position2) {
|
|
19608
|
+
const path = pathOf2(target);
|
|
19609
|
+
if (path === null) {
|
|
19610
|
+
return false;
|
|
19611
|
+
}
|
|
19612
|
+
const missing2 = pendingKeys(context, source, declared);
|
|
19613
|
+
if (missing2 === null) {
|
|
19614
|
+
return false;
|
|
19615
|
+
}
|
|
19616
|
+
context.openRecordObligation({
|
|
19617
|
+
path,
|
|
19618
|
+
subject,
|
|
19619
|
+
source,
|
|
19620
|
+
target: declared,
|
|
19621
|
+
missing: missing2,
|
|
19622
|
+
discharged: 0,
|
|
19623
|
+
depth: context.blockDepth,
|
|
19624
|
+
line: position2.line,
|
|
19625
|
+
position: position2
|
|
19626
|
+
});
|
|
19627
|
+
return true;
|
|
19628
|
+
}
|
|
19629
|
+
function reportIncompleteRecord(context, obligation, position2) {
|
|
19630
|
+
if (obligation.discharged === 0) {
|
|
19631
|
+
context.closeRecordObligation(obligation.path);
|
|
19632
|
+
context.expectAssignable(obligation.source, obligation.target, obligation.position, obligation.subject);
|
|
19633
|
+
return;
|
|
19634
|
+
}
|
|
19635
|
+
const keys = [...obligation.missing.keys()].map((key) => `"${key}"`);
|
|
19636
|
+
const label2 = keys.length === 1 ? `Key ${keys[0]} is` : `Keys ${keys.join(", ")} are`;
|
|
19637
|
+
const built = `The table built on line ${obligation.line} is used before it is complete.`;
|
|
19638
|
+
const message = `${obligation.subject} expects "${typeToString(obligation.target)}". ${label2} never assigned. ${built}`;
|
|
19639
|
+
context.report("check-incomplete-record", message, position2);
|
|
19640
|
+
context.closeRecordObligation(obligation.path);
|
|
19641
|
+
}
|
|
19642
|
+
function dischargeRecordKey(context, target, valueType, position2) {
|
|
19643
|
+
if (target.kind !== "member-expression") {
|
|
19644
|
+
return false;
|
|
19645
|
+
}
|
|
19646
|
+
const path = pathOf2(target.object);
|
|
19647
|
+
const obligation = path === null ? null : context.recordObligation(path);
|
|
19648
|
+
if (obligation === null || obligation.depth !== context.blockDepth) {
|
|
19649
|
+
return false;
|
|
19650
|
+
}
|
|
19651
|
+
const expected = obligation.missing.get(target.property);
|
|
19652
|
+
if (expected === void 0) {
|
|
19653
|
+
return false;
|
|
19654
|
+
}
|
|
19655
|
+
context.expectAssignable(valueType, expected, position2, `Key "${target.property}"`);
|
|
19656
|
+
obligation.missing.delete(target.property);
|
|
19657
|
+
obligation.discharged += 1;
|
|
19658
|
+
if (obligation.missing.size === 0) {
|
|
19659
|
+
context.closeRecordObligation(obligation.path);
|
|
19660
|
+
}
|
|
19661
|
+
return true;
|
|
19662
|
+
}
|
|
19663
|
+
function extendInferredRecord(context, target, valueType) {
|
|
19664
|
+
if (target.kind !== "member-expression" || target.object.kind !== "identifier") {
|
|
19665
|
+
return false;
|
|
19666
|
+
}
|
|
19667
|
+
const symbol = context.binder.lookup(target.object.name);
|
|
19668
|
+
if (symbol === null || symbol.type.kind !== "record" || symbol.type.isInferred !== true || symbol.type.members.has(target.property)) {
|
|
19669
|
+
return false;
|
|
19670
|
+
}
|
|
19671
|
+
const members = new Map(symbol.type.members);
|
|
19672
|
+
members.set(target.property, widenInferred(valueType));
|
|
19673
|
+
const extended = createObjectType(members);
|
|
19674
|
+
symbol.type = extended.kind === "record" ? { ...extended, isInferred: true } : extended;
|
|
19675
|
+
return true;
|
|
19676
|
+
}
|
|
19677
|
+
function escapesRecordObligation(context, expression) {
|
|
19678
|
+
const path = pathOf2(expression);
|
|
19679
|
+
const obligation = path === null ? null : context.recordObligation(path);
|
|
19680
|
+
if (obligation !== null) {
|
|
19681
|
+
reportIncompleteRecord(context, obligation, expression.position);
|
|
19682
|
+
}
|
|
19683
|
+
}
|
|
19684
|
+
function settleRecordObligations(context, opened) {
|
|
19685
|
+
for (const path of context.recordObligationPaths()) {
|
|
19686
|
+
if (opened.has(path)) {
|
|
19687
|
+
continue;
|
|
19688
|
+
}
|
|
19689
|
+
const obligation = context.recordObligation(path);
|
|
19690
|
+
if (obligation === null) {
|
|
19691
|
+
continue;
|
|
19692
|
+
}
|
|
19693
|
+
reportIncompleteRecord(context, obligation, obligation.position);
|
|
19694
|
+
}
|
|
19695
|
+
}
|
|
19696
|
+
|
|
19310
19697
|
// ../compiler/src/checker/resource-exports.ts
|
|
19311
19698
|
var RESOURCE_LOOKUP = "getResourceFromName";
|
|
19312
19699
|
var EXPORTS_TABLE = "exports";
|
|
@@ -19516,9 +19903,6 @@ function isElementType(name) {
|
|
|
19516
19903
|
|
|
19517
19904
|
// ../compiler/src/checker/oop-members.ts
|
|
19518
19905
|
var OOP_HINT = 'Set "compiler = { oop = true }" in .luam.manifest to enable the MTA OOP API.';
|
|
19519
|
-
function scopeLabel2(environment) {
|
|
19520
|
-
return environment === "shared" ? "shared" : `${environment}-only`;
|
|
19521
|
-
}
|
|
19522
19906
|
function isMtaElementName(declarations, className) {
|
|
19523
19907
|
if (!isElementType(className)) {
|
|
19524
19908
|
return false;
|
|
@@ -19536,6 +19920,14 @@ function reportDisabled(context, className, name, position2) {
|
|
|
19536
19920
|
const subject = `"${className}.${name}" is part of the MTA OOP API, which this project does not enable.`;
|
|
19537
19921
|
context.report("check-oop-disabled", `${subject} Call "${member.procedural}" instead. ${OOP_HINT}`, position2);
|
|
19538
19922
|
}
|
|
19923
|
+
function acceptsMember(context, className, name, member, position2) {
|
|
19924
|
+
if (member.environment === void 0 || isAvailableIn(member.environment, context.environment)) {
|
|
19925
|
+
return true;
|
|
19926
|
+
}
|
|
19927
|
+
const subject = `"${className}.${name}" wraps "${member.procedural}", which is ${scopeLabel(member.environment)}`;
|
|
19928
|
+
reportEnvironment(context, "check-environment-api", `${subject} and ${unavailableTail(context.environment)}`, position2);
|
|
19929
|
+
return context.environment === "shared";
|
|
19930
|
+
}
|
|
19539
19931
|
function isMtaClassReference(context, className) {
|
|
19540
19932
|
return isMtaClass(className) && context.binder.lookup(className) === null && context.declarations.lookupClass(className) === null && context.declarations.lookupInterface(className) === null;
|
|
19541
19933
|
}
|
|
@@ -19551,12 +19943,7 @@ function resolveMtaStaticMember(context, className, name, position2) {
|
|
|
19551
19943
|
reportDisabled(context, className, name, position2);
|
|
19552
19944
|
return null;
|
|
19553
19945
|
}
|
|
19554
|
-
|
|
19555
|
-
const subject = `"${className}.${name}" wraps "${member.procedural}", which is ${scopeLabel2(member.environment)}`;
|
|
19556
|
-
context.report("check-environment-api", `${subject} and is not available in a "${context.environment}" file.`, position2);
|
|
19557
|
-
return null;
|
|
19558
|
-
}
|
|
19559
|
-
return member;
|
|
19946
|
+
return acceptsMember(context, className, name, member, position2) ? member : null;
|
|
19560
19947
|
}
|
|
19561
19948
|
function resolveMtaConstructor(context, className, position2) {
|
|
19562
19949
|
const constructor = mtaConstructor(className);
|
|
@@ -19571,9 +19958,11 @@ function resolveMtaConstructor(context, className, position2) {
|
|
|
19571
19958
|
return null;
|
|
19572
19959
|
}
|
|
19573
19960
|
if (!isAvailableIn(constructor.environment, context.environment)) {
|
|
19574
|
-
const subject = `"${className}(...)" is ${
|
|
19575
|
-
context
|
|
19576
|
-
|
|
19961
|
+
const subject = `"${className}(...)" is ${scopeLabel(constructor.environment)}`;
|
|
19962
|
+
reportEnvironment(context, "check-environment-api", `${subject} and ${unavailableTail(context.environment)}`, position2);
|
|
19963
|
+
if (context.environment !== "shared") {
|
|
19964
|
+
return null;
|
|
19965
|
+
}
|
|
19577
19966
|
}
|
|
19578
19967
|
return constructor.type;
|
|
19579
19968
|
}
|
|
@@ -19593,12 +19982,7 @@ function resolveMtaMember(context, className, name, position2) {
|
|
|
19593
19982
|
reportUnknown(context, className, name, position2);
|
|
19594
19983
|
return null;
|
|
19595
19984
|
}
|
|
19596
|
-
|
|
19597
|
-
const subject = `"${className}.${name}" wraps "${member.procedural}", which is ${scopeLabel2(member.environment)}`;
|
|
19598
|
-
context.report("check-environment-api", `${subject} and is not available in a "${context.environment}" file.`, position2);
|
|
19599
|
-
return null;
|
|
19600
|
-
}
|
|
19601
|
-
return member;
|
|
19985
|
+
return acceptsMember(context, className, name, member, position2) ? member : null;
|
|
19602
19986
|
}
|
|
19603
19987
|
|
|
19604
19988
|
// ../compiler/src/checker/members.ts
|
|
@@ -19724,7 +20108,9 @@ function resolveNamedMember(context, receiver, expression) {
|
|
|
19724
20108
|
if (contract === null) {
|
|
19725
20109
|
return null;
|
|
19726
20110
|
}
|
|
19727
|
-
const
|
|
20111
|
+
const substitutions = parameterSubstitutions(contract.typeParameters, receiver.typeArguments ?? []);
|
|
20112
|
+
const collected = context.declarations.collectMembers(name).map((entry) => substitutions.size === 0 ? entry : { ...entry, type: substituteType(entry.type, substitutions) });
|
|
20113
|
+
const members = new Map(collected.map((entry) => [entry.name, entry]));
|
|
19728
20114
|
return checkInterfaceMember(context, name, members, expression);
|
|
19729
20115
|
}
|
|
19730
20116
|
function reportUnknownMethod(context, receiver, callee, method, position2) {
|
|
@@ -19892,6 +20278,39 @@ function checkUnary(context, operator, operand, expression) {
|
|
|
19892
20278
|
return context.record(expression, NUMBER_TYPE);
|
|
19893
20279
|
}
|
|
19894
20280
|
|
|
20281
|
+
// ../compiler/src/checker/shadowing.ts
|
|
20282
|
+
var HELPER_TARGETS = new Map(
|
|
20283
|
+
NATIVE_EXTENSIONS.map((extension) => [
|
|
20284
|
+
extension.target,
|
|
20285
|
+
extension.style === "call" ? `${extension.receiver}.${extension.property}(...)` : `${extension.receiver}.${extension.property}`
|
|
20286
|
+
])
|
|
20287
|
+
);
|
|
20288
|
+
var SUPPRESSION = 'Rename the declaration, or record the new signature in a ".d.luam" file so later calls are checked against it.';
|
|
20289
|
+
function reportShadowedGlobal(context, name, position2) {
|
|
20290
|
+
if (context.isDeclarationFile || !context.binder.isBuiltinReference(name)) {
|
|
20291
|
+
return;
|
|
20292
|
+
}
|
|
20293
|
+
const message = `"${name}" is an API this environment declares. Later calls are still checked against the declared signature, not this one. ${SUPPRESSION}`;
|
|
20294
|
+
context.warn("check-shadowed-api", message, position2);
|
|
20295
|
+
}
|
|
20296
|
+
function reportShadowedHelper(context, library, member, position2) {
|
|
20297
|
+
if (context.isDeclarationFile || !isLibrary(library) || findLibraryMember(library, member) === null) {
|
|
20298
|
+
return;
|
|
20299
|
+
}
|
|
20300
|
+
const target = `${library}.${member}`;
|
|
20301
|
+
const rewrite = HELPER_TARGETS.get(target);
|
|
20302
|
+
const lowered = rewrite === void 0 ? "" : ` The extension "${rewrite}" lowers to it.`;
|
|
20303
|
+
const message = `"${target}" is part of the standard library this build models.${lowered} Later calls are still checked against the declared signature, not this one. ${SUPPRESSION}`;
|
|
20304
|
+
context.warn("check-shadowed-helper", message, position2);
|
|
20305
|
+
}
|
|
20306
|
+
function reportImplicitGlobal(context, name, position2) {
|
|
20307
|
+
if (context.isDeclarationFile || !context.noImplicitGlobals) {
|
|
20308
|
+
return;
|
|
20309
|
+
}
|
|
20310
|
+
const message = `"${name}" is not declared anywhere this file can reach, so this assignment creates a global. Declare it with "local", annotate it as a global, or describe it in a ".d.luam" file.`;
|
|
20311
|
+
context.warn("check-implicit-global", message, position2);
|
|
20312
|
+
}
|
|
20313
|
+
|
|
19895
20314
|
// ../compiler/src/checker/union-members.ts
|
|
19896
20315
|
function isShapeOption(context, option) {
|
|
19897
20316
|
if (option.kind === "record") {
|
|
@@ -20113,8 +20532,12 @@ function negatedFacts(context, condition) {
|
|
|
20113
20532
|
// ../compiler/src/checker/control-flow.ts
|
|
20114
20533
|
var ITERATOR_FUNCTIONS = /* @__PURE__ */ new Set(["pairs", "ipairs"]);
|
|
20115
20534
|
function checkBlock(context, body) {
|
|
20535
|
+
const opened = new Set(context.recordObligationPaths());
|
|
20116
20536
|
context.binder.pushScope();
|
|
20537
|
+
context.blockDepth += 1;
|
|
20117
20538
|
checkStatements(context, body);
|
|
20539
|
+
context.blockDepth -= 1;
|
|
20540
|
+
settleRecordObligations(context, opened);
|
|
20118
20541
|
const declared = context.binder.currentScopeNames();
|
|
20119
20542
|
context.binder.popScope();
|
|
20120
20543
|
for (const name of declared) {
|
|
@@ -20309,7 +20732,9 @@ function minimumArguments(context, parameters) {
|
|
|
20309
20732
|
function buildFunctionType(context, parameters, returnAnnotation, contextual = null) {
|
|
20310
20733
|
const isVariadic = parameters.some((parameter) => parameter.isVararg);
|
|
20311
20734
|
const named2 = parameters.filter((parameter) => !parameter.isVararg);
|
|
20312
|
-
const types = named2.map(
|
|
20735
|
+
const types = named2.map(
|
|
20736
|
+
(parameter, index) => parameter.annotation === null ? contextual?.parameters[index] ?? ANY_TYPE : context.resolveValueAnnotation(parameter.annotation, "a parameter")
|
|
20737
|
+
);
|
|
20313
20738
|
const names = named2.map((parameter) => parameter.name);
|
|
20314
20739
|
return createFunction(types, context.resolveAnnotation(returnAnnotation), minimumArguments(context, parameters), isVariadic, names);
|
|
20315
20740
|
}
|
|
@@ -20354,7 +20779,11 @@ function checkFunctionBody(context, parameters, returnAnnotation, body, signatur
|
|
|
20354
20779
|
parameterIndex += 1;
|
|
20355
20780
|
}
|
|
20356
20781
|
}
|
|
20782
|
+
const opened = new Set(context.recordObligationPaths());
|
|
20783
|
+
context.blockDepth += 1;
|
|
20357
20784
|
checkStatements(context, body);
|
|
20785
|
+
context.blockDepth -= 1;
|
|
20786
|
+
settleRecordObligations(context, opened);
|
|
20358
20787
|
const declared = context.currentReturnType();
|
|
20359
20788
|
if (declared !== null && context.flowState.reachable && !toleratesFallthrough(declared)) {
|
|
20360
20789
|
reportMissingReturn(context, declared, position2);
|
|
@@ -20383,9 +20812,11 @@ function checkLocal(context, statement) {
|
|
|
20383
20812
|
context.binder.declare({ name: declaration.name, type: inferred, isLocal: true, position: declaration.position, origin: "local" });
|
|
20384
20813
|
return;
|
|
20385
20814
|
}
|
|
20386
|
-
const declared = context.
|
|
20387
|
-
|
|
20388
|
-
|
|
20815
|
+
const declared = context.resolveValueAnnotation(declaration.annotation, "a local");
|
|
20816
|
+
const subject = `Variable "${declaration.name}"`;
|
|
20817
|
+
const deferred = value !== void 0 && deferRecordCompletion(context, { kind: "identifier", name: declaration.name, position: declaration.position }, valueType, declared, subject, value.position);
|
|
20818
|
+
if (value !== void 0 && !deferred) {
|
|
20819
|
+
context.expectAssignable(valueType, declared, value.position, subject);
|
|
20389
20820
|
}
|
|
20390
20821
|
context.binder.declare({ name: declaration.name, type: declared, isLocal: true, position: declaration.position, origin: "local" });
|
|
20391
20822
|
if (value !== void 0) {
|
|
@@ -20404,6 +20835,13 @@ function checkCompoundOperand(context, operator, type, position2) {
|
|
|
20404
20835
|
context.report("check-invalid-operand", `Operator "${operator}" cannot be applied to "${typeToString(type)}".`, position2);
|
|
20405
20836
|
}
|
|
20406
20837
|
}
|
|
20838
|
+
var DELETABLE_CONTAINERS = /* @__PURE__ */ new Set(["map", "array", "table"]);
|
|
20839
|
+
function deletesContainerKey(context, target, valueType) {
|
|
20840
|
+
if (valueType.kind !== "nil" || target.kind !== "index-expression" && target.kind !== "member-expression") {
|
|
20841
|
+
return false;
|
|
20842
|
+
}
|
|
20843
|
+
return DELETABLE_CONTAINERS.has(context.typeOf(target.object).kind);
|
|
20844
|
+
}
|
|
20407
20845
|
function recordAssignedFact(context, path, valueType, declared) {
|
|
20408
20846
|
if (path === null || valueType.kind === "any") {
|
|
20409
20847
|
return;
|
|
@@ -20420,9 +20858,12 @@ function checkAssignment(context, statement) {
|
|
|
20420
20858
|
if (assigned !== null) {
|
|
20421
20859
|
context.forgetNarrowing(assigned);
|
|
20422
20860
|
}
|
|
20423
|
-
const targetType = checkExpression(context, target);
|
|
20424
20861
|
const valueType = valueTypes[index] ?? NIL_TYPE;
|
|
20425
20862
|
const value = valueAt(statement.values, valueTypes, index);
|
|
20863
|
+
if (value !== void 0 && extendInferredRecord(context, target, valueType)) {
|
|
20864
|
+
return;
|
|
20865
|
+
}
|
|
20866
|
+
const targetType = checkExpression(context, target);
|
|
20426
20867
|
if (target.kind === "member-expression") {
|
|
20427
20868
|
const object = context.typeOf(target.object);
|
|
20428
20869
|
const frame = context.currentClassMethod();
|
|
@@ -20441,16 +20882,54 @@ function checkAssignment(context, statement) {
|
|
|
20441
20882
|
return;
|
|
20442
20883
|
}
|
|
20443
20884
|
if (target.kind === "identifier" && context.binder.lookup(target.name) === null) {
|
|
20885
|
+
reportImplicitGlobal(context, target.name, target.position);
|
|
20444
20886
|
context.declareModuleGlobal({ name: target.name, type: valueType, isLocal: false, position: target.position });
|
|
20445
20887
|
return;
|
|
20446
20888
|
}
|
|
20889
|
+
if (!context.insideFunction()) {
|
|
20890
|
+
reportShadowedAssignment(context, target);
|
|
20891
|
+
}
|
|
20447
20892
|
const declared = target.kind === "identifier" ? context.binder.lookup(target.name)?.type ?? targetType : targetType;
|
|
20893
|
+
if (deletesContainerKey(context, target, valueType)) {
|
|
20894
|
+
return;
|
|
20895
|
+
}
|
|
20896
|
+
if (value !== void 0 && dischargeRecordKey(context, target, valueType, value.position)) {
|
|
20897
|
+
return;
|
|
20898
|
+
}
|
|
20899
|
+
const path = pathOf2(target);
|
|
20900
|
+
if (path !== null) {
|
|
20901
|
+
context.closeRecordObligation(path);
|
|
20902
|
+
}
|
|
20903
|
+
if (value !== void 0 && deferRecordCompletion(context, target, valueType, declared, "Assignment", value.position)) {
|
|
20904
|
+
return;
|
|
20905
|
+
}
|
|
20448
20906
|
if (value !== void 0) {
|
|
20449
20907
|
context.expectAssignable(valueType, declared, value.position, "Assignment");
|
|
20450
20908
|
}
|
|
20451
20909
|
recordAssignedFact(context, pathOf2(target), valueType, declared);
|
|
20452
20910
|
});
|
|
20453
20911
|
}
|
|
20912
|
+
function rootIdentifier(expression) {
|
|
20913
|
+
if (expression.kind === "identifier") {
|
|
20914
|
+
return expression.name;
|
|
20915
|
+
}
|
|
20916
|
+
return expression.kind === "member-expression" || expression.kind === "index-expression" ? rootIdentifier(expression.object) : null;
|
|
20917
|
+
}
|
|
20918
|
+
function reportShadowedAssignment(context, target) {
|
|
20919
|
+
if (target.kind !== "identifier") {
|
|
20920
|
+
const root = rootIdentifier(target);
|
|
20921
|
+
if (root !== null && context.binder.lookup(root) === null) {
|
|
20922
|
+
reportImplicitGlobal(context, root, target.position);
|
|
20923
|
+
}
|
|
20924
|
+
}
|
|
20925
|
+
if (target.kind === "identifier") {
|
|
20926
|
+
reportShadowedGlobal(context, target.name, target.position);
|
|
20927
|
+
return;
|
|
20928
|
+
}
|
|
20929
|
+
if (target.kind === "member-expression" && target.object.kind === "identifier") {
|
|
20930
|
+
reportShadowedHelper(context, target.object.name, target.property, target.position);
|
|
20931
|
+
}
|
|
20932
|
+
}
|
|
20454
20933
|
function checkFunctionDeclaration(context, statement) {
|
|
20455
20934
|
const built = buildFunctionType(context, statement.parameters, statement.returnAnnotation);
|
|
20456
20935
|
const type = applyTypeParameters(context, built, statement.typeParameters, statement.typeConstraints);
|
|
@@ -20459,9 +20938,13 @@ function checkFunctionDeclaration(context, statement) {
|
|
|
20459
20938
|
if (statement.isLocal) {
|
|
20460
20939
|
context.binder.declare({ ...symbol, origin: "local" });
|
|
20461
20940
|
} else {
|
|
20941
|
+
reportShadowedGlobal(context, statement.name.name, statement.position);
|
|
20462
20942
|
context.declareModuleGlobal(symbol);
|
|
20463
20943
|
}
|
|
20464
20944
|
}
|
|
20945
|
+
if (!statement.isLocal && statement.name.kind !== "identifier") {
|
|
20946
|
+
reportShadowedAssignment(context, statement.name);
|
|
20947
|
+
}
|
|
20465
20948
|
context.record(statement.name, type);
|
|
20466
20949
|
checkFunctionBody(context, statement.parameters, statement.returnAnnotation, statement.body, type, statement.isMethod ? ANY_TYPE : null, statement.position);
|
|
20467
20950
|
}
|
|
@@ -20514,7 +20997,34 @@ function checkDeclareStatement(context, statement) {
|
|
|
20514
20997
|
}
|
|
20515
20998
|
const type = context.resolveAnnotation(statement.annotation);
|
|
20516
20999
|
context.declareModuleGlobal({ name: statement.name, type, isLocal: false, position: statement.position });
|
|
20517
|
-
context.declarations.declareGlobal({ name: statement.name, type, position: statement.position });
|
|
21000
|
+
context.declarations.declareGlobal({ name: statement.name, type, isDeclared: true, position: statement.position });
|
|
21001
|
+
}
|
|
21002
|
+
function checkGlobalStatement(context, statement) {
|
|
21003
|
+
const declaration = statement.declaration;
|
|
21004
|
+
const declared = declaration.annotation === null ? ANY_TYPE : context.resolveValueAnnotation(declaration.annotation, "a global");
|
|
21005
|
+
const valueTypes = checkValueList(context, statement.values);
|
|
21006
|
+
const value = valueAt(statement.values, valueTypes, 0);
|
|
21007
|
+
if (context.insideFunction()) {
|
|
21008
|
+
const message = `A type on global "${declaration.name}" is only valid at the top level of a file. Assign it without the annotation here.`;
|
|
21009
|
+
context.report("check-global-annotation-scope", message, statement.position);
|
|
21010
|
+
return;
|
|
21011
|
+
}
|
|
21012
|
+
const existing = context.declarations.lookupGlobal(declaration.name);
|
|
21013
|
+
const contract = existing !== null && existing.isDeclared === true ? existing.type : declared;
|
|
21014
|
+
if (existing !== null && existing.isDeclared !== true) {
|
|
21015
|
+
context.report("check-duplicate-global", `Global "${declaration.name}" is already declared with a type.`, statement.position);
|
|
21016
|
+
}
|
|
21017
|
+
if (value !== void 0) {
|
|
21018
|
+
context.expectAssignable(valueTypes[0] ?? NIL_TYPE, contract, value.position, `Global "${declaration.name}"`);
|
|
21019
|
+
}
|
|
21020
|
+
context.forgetNarrowing(declaration.name);
|
|
21021
|
+
context.declareModuleGlobal({ name: declaration.name, type: contract, isLocal: false, position: declaration.position });
|
|
21022
|
+
if (existing === null) {
|
|
21023
|
+
context.declarations.declareGlobal({ name: declaration.name, type: contract, position: declaration.position });
|
|
21024
|
+
}
|
|
21025
|
+
if (value !== void 0) {
|
|
21026
|
+
recordAssignedFact(context, declaration.name, valueTypes[0] ?? NIL_TYPE, contract);
|
|
21027
|
+
}
|
|
20518
21028
|
}
|
|
20519
21029
|
function checkStatement(context, statement) {
|
|
20520
21030
|
switch (statement.kind) {
|
|
@@ -20522,6 +21032,8 @@ function checkStatement(context, statement) {
|
|
|
20522
21032
|
return checkLocal(context, statement);
|
|
20523
21033
|
case "assignment-statement":
|
|
20524
21034
|
return checkAssignment(context, statement);
|
|
21035
|
+
case "global-statement":
|
|
21036
|
+
return checkGlobalStatement(context, statement);
|
|
20525
21037
|
case "call-statement":
|
|
20526
21038
|
checkExpression(context, statement.expression);
|
|
20527
21039
|
return;
|
|
@@ -20548,11 +21060,15 @@ function checkStatement(context, statement) {
|
|
|
20548
21060
|
case "generic-for-statement":
|
|
20549
21061
|
return checkGenericFor(context, statement);
|
|
20550
21062
|
case "type-alias-statement": {
|
|
20551
|
-
const resolved2 = context.
|
|
21063
|
+
const resolved2 = context.resolveValueAnnotation(statement.annotation, "a type alias");
|
|
20552
21064
|
const shape = statement.annotation.kind === "type-object" || statement.annotation.kind === "type-intersection";
|
|
20553
21065
|
const named2 = shape ? renameRecord(resolved2, statement.name) : resolved2;
|
|
21066
|
+
if (context.isAmbientAlias(statement.name)) {
|
|
21067
|
+
context.report("check-duplicate-type", `Type "${statement.name}" is already defined.`, statement.position);
|
|
21068
|
+
}
|
|
20554
21069
|
context.noteTypeParameters(statement.typeParameters);
|
|
20555
21070
|
context.binder.declareAlias(statement.name, named2, statement.typeParameters);
|
|
21071
|
+
context.declarations.declareAlias({ name: statement.name, typeParameters: statement.typeParameters, type: named2, position: statement.position });
|
|
20556
21072
|
return;
|
|
20557
21073
|
}
|
|
20558
21074
|
case "declare-statement":
|
|
@@ -20590,6 +21106,19 @@ function templateLiteralText(segments) {
|
|
|
20590
21106
|
return segments.map((segment) => segment.kind === "text" ? segment.value : `\${${segment.value}}`).join("");
|
|
20591
21107
|
}
|
|
20592
21108
|
|
|
21109
|
+
// ../compiler/src/checker/value-distribution.ts
|
|
21110
|
+
function distributeValueTypes(types) {
|
|
21111
|
+
const distributed = [];
|
|
21112
|
+
types.forEach((type, index) => {
|
|
21113
|
+
if (index === types.length - 1) {
|
|
21114
|
+
distributed.push(...valuesOf(type));
|
|
21115
|
+
return;
|
|
21116
|
+
}
|
|
21117
|
+
distributed.push(firstValueOf(type));
|
|
21118
|
+
});
|
|
21119
|
+
return distributed;
|
|
21120
|
+
}
|
|
21121
|
+
|
|
20593
21122
|
// ../compiler/src/checker/expressions.ts
|
|
20594
21123
|
var NAME_PATH_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/;
|
|
20595
21124
|
var EXTENSION_RESULTS = {
|
|
@@ -20633,7 +21162,8 @@ function checkMember(context, expression) {
|
|
|
20633
21162
|
checkExpression(context, expression.object);
|
|
20634
21163
|
return context.record(expression, library);
|
|
20635
21164
|
}
|
|
20636
|
-
const
|
|
21165
|
+
const received = checkExpression(context, expression.object);
|
|
21166
|
+
const objectType = received.kind === "optional" ? received.element : received;
|
|
20637
21167
|
if (objectType.kind === "record") {
|
|
20638
21168
|
return context.record(expression, resolveRecordMember(context, objectType, expression));
|
|
20639
21169
|
}
|
|
@@ -20656,26 +21186,44 @@ function checkMember(context, expression) {
|
|
|
20656
21186
|
}
|
|
20657
21187
|
return context.record(expression, extension === null ? ANY_TYPE : EXTENSION_RESULTS[extension.result]);
|
|
20658
21188
|
}
|
|
21189
|
+
function spreadsUnknownArity(args, argumentTypes) {
|
|
21190
|
+
if (args.length === 0 || args.length !== argumentTypes.length) {
|
|
21191
|
+
return false;
|
|
21192
|
+
}
|
|
21193
|
+
return args[args.length - 1]?.kind === "call-expression" && argumentTypes[argumentTypes.length - 1]?.kind === "any";
|
|
21194
|
+
}
|
|
21195
|
+
function resolveKeyedMember(context, objectType, expression) {
|
|
21196
|
+
if (expression.index.kind !== "string-literal" || objectType.kind !== "record" && objectType.kind !== "named") {
|
|
21197
|
+
return null;
|
|
21198
|
+
}
|
|
21199
|
+
const access = { kind: "member-expression", object: expression.object, property: expression.index.value, position: expression.index.position };
|
|
21200
|
+
return objectType.kind === "record" ? resolveRecordMember(context, objectType, access) : resolveNamedMember(context, objectType, access);
|
|
21201
|
+
}
|
|
20659
21202
|
function countArguments2(total) {
|
|
20660
21203
|
return total === 1 ? "1 argument" : `${total} arguments`;
|
|
20661
21204
|
}
|
|
20662
21205
|
function checkSignature(context, args, declared, position2, owner = "This call", typeArguments = []) {
|
|
20663
21206
|
const argumentTypes = checkValueList(context, args, declared.parameters);
|
|
20664
21207
|
const signature2 = specializeCall(context, owner, declared, argumentTypes, typeArguments, position2);
|
|
20665
|
-
|
|
21208
|
+
const spreads = spreadsUnknownArity(args, argumentTypes);
|
|
21209
|
+
const fixed = spreads ? argumentTypes.length - 1 : argumentTypes.length;
|
|
21210
|
+
if (!spreads && argumentTypes.length < signature2.minimumArguments) {
|
|
20666
21211
|
const message = `This call expects at least ${countArguments2(signature2.minimumArguments)} but received ${argumentTypes.length}.`;
|
|
20667
21212
|
context.report("check-argument-count", message, position2);
|
|
20668
21213
|
}
|
|
20669
|
-
if (!signature2.isVariadic &&
|
|
21214
|
+
if (!signature2.isVariadic && fixed > signature2.parameters.length) {
|
|
20670
21215
|
const message = `This call expects at most ${countArguments2(signature2.parameters.length)} but received ${argumentTypes.length}.`;
|
|
20671
21216
|
context.report("check-argument-count", message, position2);
|
|
20672
21217
|
}
|
|
20673
21218
|
signature2.parameters.forEach((parameter, index) => {
|
|
20674
21219
|
const argumentType = argumentTypes[index];
|
|
20675
21220
|
const argument = args[index];
|
|
20676
|
-
if (argumentType
|
|
20677
|
-
|
|
21221
|
+
if (argumentType === void 0 || argument === void 0) {
|
|
21222
|
+
return;
|
|
20678
21223
|
}
|
|
21224
|
+
const optional = index >= signature2.minimumArguments && parameter.kind !== "optional";
|
|
21225
|
+
const expected = optional ? createOptional(parameter) : parameter;
|
|
21226
|
+
context.expectAssignable(argumentType, expected, argument.position, `Argument ${index + 1}`, parameter);
|
|
20679
21227
|
});
|
|
20680
21228
|
if (signature2.isVariadic && signature2.variadicType !== void 0) {
|
|
20681
21229
|
for (let index = signature2.parameters.length; index < argumentTypes.length; index += 1) {
|
|
@@ -20688,6 +21236,20 @@ function checkSignature(context, args, declared, position2, owner = "This call",
|
|
|
20688
21236
|
}
|
|
20689
21237
|
return signature2.returnType;
|
|
20690
21238
|
}
|
|
21239
|
+
function reportClassReceiver(context, name, method, position2) {
|
|
21240
|
+
if (context.declarations.lookupStaticMember(name, method) !== null) {
|
|
21241
|
+
const message2 = `Call the static member "${method}" as "${name}.${method}(...)". A class value has no "self" to pass.`;
|
|
21242
|
+
context.report("check-static-receiver", message2, position2);
|
|
21243
|
+
return;
|
|
21244
|
+
}
|
|
21245
|
+
if (context.declarations.lookupMember(name, method) === null) {
|
|
21246
|
+
const message2 = `Call the static member "${method}" as "${name}.${method}(...)". A class value has no "self" to pass.`;
|
|
21247
|
+
context.report("check-static-receiver", message2, position2);
|
|
21248
|
+
return;
|
|
21249
|
+
}
|
|
21250
|
+
const message = `The receiver here is the class "${name}" itself, and "${method}" is one of its instance members. Create an instance \u2014 "local value = new ${name}()" \u2014 and call "value:${method}(...)", or read the member from a value of that class. Where the class and its single instance share one name, give the instance its own name.`;
|
|
21251
|
+
context.report("check-class-receiver", message, position2);
|
|
21252
|
+
}
|
|
20691
21253
|
function callOwner(expression) {
|
|
20692
21254
|
const name = expression.method ?? (expression.callee.kind === "identifier" ? expression.callee.name : null);
|
|
20693
21255
|
return name === null ? "This call" : `Function "${name}"`;
|
|
@@ -20759,9 +21321,7 @@ function checkCall(context, expression) {
|
|
|
20759
21321
|
return context.record(expression, checkSignature(context, expression.args, constructor, expression.position));
|
|
20760
21322
|
}
|
|
20761
21323
|
if (expression.method !== null && expression.callee.kind === "identifier" && isUserClassReference(context, expression.callee.name)) {
|
|
20762
|
-
|
|
20763
|
-
const message = `Call the static member "${expression.method}" as "${name}.${expression.method}(...)". A class value has no "self" to pass.`;
|
|
20764
|
-
context.report("check-static-receiver", message, expression.position);
|
|
21324
|
+
reportClassReceiver(context, expression.callee.name, expression.method, expression.position);
|
|
20765
21325
|
checkValueList(context, expression.args);
|
|
20766
21326
|
return context.record(expression, ANY_TYPE);
|
|
20767
21327
|
}
|
|
@@ -20840,6 +21400,8 @@ function checkMultiValueExpression(context, expression, expected = null) {
|
|
|
20840
21400
|
const symbol = context.binder.lookup(expression.name);
|
|
20841
21401
|
if (symbol === null) {
|
|
20842
21402
|
checkGlobalReference(context, expression.name, expression.position);
|
|
21403
|
+
} else {
|
|
21404
|
+
checkSharedReference(context, expression.name, expression.position);
|
|
20843
21405
|
}
|
|
20844
21406
|
if (symbol === null || symbol.isLocal !== true) {
|
|
20845
21407
|
context.noteGlobalReference(expression.name);
|
|
@@ -20855,6 +21417,10 @@ function checkMultiValueExpression(context, expression, expected = null) {
|
|
|
20855
21417
|
context.expectAssignable(indexType, objectType.key, expression.index.position, "Key");
|
|
20856
21418
|
return context.record(expression, objectType.value);
|
|
20857
21419
|
}
|
|
21420
|
+
const keyed = resolveKeyedMember(context, objectType, expression);
|
|
21421
|
+
if (keyed !== null) {
|
|
21422
|
+
return context.record(expression, keyed);
|
|
21423
|
+
}
|
|
20858
21424
|
return context.record(expression, objectType.kind === "array" ? objectType.element : ANY_TYPE);
|
|
20859
21425
|
}
|
|
20860
21426
|
case "call-expression":
|
|
@@ -20884,16 +21450,12 @@ function checkExpression(context, expression, expected = null) {
|
|
|
20884
21450
|
return firstValueOf(checkMultiValueExpression(context, expression, expected));
|
|
20885
21451
|
}
|
|
20886
21452
|
function checkValueList(context, values, expected = []) {
|
|
20887
|
-
const types =
|
|
20888
|
-
values.forEach((value, index) => {
|
|
21453
|
+
const types = values.map((value, index) => {
|
|
20889
21454
|
const type = checkMultiValueExpression(context, value, expected[index] ?? null);
|
|
20890
|
-
|
|
20891
|
-
|
|
20892
|
-
return;
|
|
20893
|
-
}
|
|
20894
|
-
types.push(firstValueOf(type));
|
|
21455
|
+
escapesRecordObligation(context, value);
|
|
21456
|
+
return type;
|
|
20895
21457
|
});
|
|
20896
|
-
return types;
|
|
21458
|
+
return distributeValueTypes(types);
|
|
20897
21459
|
}
|
|
20898
21460
|
|
|
20899
21461
|
// ../compiler/src/checker/classes.ts
|
|
@@ -20902,7 +21464,7 @@ function fieldType(context, member) {
|
|
|
20902
21464
|
if (member.annotation === null) {
|
|
20903
21465
|
return valueType === null ? ANY_TYPE : widenInferred(valueType);
|
|
20904
21466
|
}
|
|
20905
|
-
const declared = context.
|
|
21467
|
+
const declared = context.resolveValueAnnotation(member.annotation, "a field");
|
|
20906
21468
|
if (valueType !== null && member.value !== null) {
|
|
20907
21469
|
context.expectAssignable(valueType, declared, member.value.position, `Field "${member.name}"`);
|
|
20908
21470
|
}
|
|
@@ -20996,6 +21558,7 @@ function declareBuilder(context, info, statement) {
|
|
|
20996
21558
|
superClass: null,
|
|
20997
21559
|
superArguments: [],
|
|
20998
21560
|
interfaces: [],
|
|
21561
|
+
interfaceArguments: [],
|
|
20999
21562
|
members,
|
|
21000
21563
|
statics: /* @__PURE__ */ new Map(),
|
|
21001
21564
|
position: statement.position
|
|
@@ -21023,8 +21586,9 @@ function checkMethodBody(context, info, member) {
|
|
|
21023
21586
|
context.popClassMethod();
|
|
21024
21587
|
}
|
|
21025
21588
|
function assignSuperClass(context, info, statement) {
|
|
21026
|
-
|
|
21027
|
-
info.
|
|
21589
|
+
const resolved2 = resolveSuperClass(context, statement);
|
|
21590
|
+
info.superClass = resolved2 ?? statement.superClass;
|
|
21591
|
+
info.hasUnresolvedParent = statement.superClass !== null && resolved2 === null;
|
|
21028
21592
|
}
|
|
21029
21593
|
function resolveSuperClass(context, statement) {
|
|
21030
21594
|
if (statement.superClass === null) {
|
|
@@ -21066,6 +21630,7 @@ function declareClassInfo(context, statement) {
|
|
|
21066
21630
|
superClass: null,
|
|
21067
21631
|
superArguments: [],
|
|
21068
21632
|
interfaces: statement.interfaces,
|
|
21633
|
+
interfaceArguments: statement.interfaceArguments.map((args) => args.map((argument) => context.resolveAnnotation(argument))),
|
|
21069
21634
|
members: /* @__PURE__ */ new Map(),
|
|
21070
21635
|
statics: /* @__PURE__ */ new Map(),
|
|
21071
21636
|
position: statement.position
|
|
@@ -21104,6 +21669,7 @@ function checkInterfaceDeclaration(context, statement) {
|
|
|
21104
21669
|
context.report("check-duplicate-interface", `Interface "${statement.name}" is already defined.`, statement.position);
|
|
21105
21670
|
return;
|
|
21106
21671
|
}
|
|
21672
|
+
context.noteTypeParameters(statement.typeParameters);
|
|
21107
21673
|
const members = /* @__PURE__ */ new Map();
|
|
21108
21674
|
for (const name of new Set(statement.superInterfaces)) {
|
|
21109
21675
|
const parent = context.declarations.lookupInterface(name);
|
|
@@ -21120,7 +21686,7 @@ function checkInterfaceDeclaration(context, statement) {
|
|
|
21120
21686
|
context.report("check-duplicate-interface-parent", `Interface "${statement.name}" extends the same interface more than once.`, statement.position);
|
|
21121
21687
|
}
|
|
21122
21688
|
for (const member of statement.members) {
|
|
21123
|
-
const type = member.kind === "interface-field" ? context.
|
|
21689
|
+
const type = member.kind === "interface-field" ? context.resolveValueAnnotation(member.annotation, "a member") : buildFunctionType(context, member.parameters, member.returnAnnotation);
|
|
21124
21690
|
const info = { name: member.name, type, isMethod: member.kind === "interface-method", position: member.position };
|
|
21125
21691
|
if (members.has(member.name)) {
|
|
21126
21692
|
context.report("check-duplicate-interface-member", `Interface "${statement.name}" declares member "${member.name}" more than once.`, member.position);
|
|
@@ -21141,6 +21707,8 @@ function checkInterfaceDeclaration(context, statement) {
|
|
|
21141
21707
|
}
|
|
21142
21708
|
context.declarations.declareInterface({
|
|
21143
21709
|
name: statement.name,
|
|
21710
|
+
typeParameters: statement.typeParameters,
|
|
21711
|
+
typeConstraints: statement.typeConstraints.map((constraint) => constraint === null ? null : context.resolveAnnotation(constraint)),
|
|
21144
21712
|
superInterfaces: statement.superInterfaces,
|
|
21145
21713
|
members,
|
|
21146
21714
|
position: statement.position
|
|
@@ -21263,12 +21831,14 @@ function check(program2, mode, environment = DEFAULT_ENVIRONMENT, options = {})
|
|
|
21263
21831
|
const ambient = options.ambient ?? EMPTY_AMBIENT;
|
|
21264
21832
|
const project = options.project ?? EMPTY_PROJECT_DECLARATIONS;
|
|
21265
21833
|
const context = new CheckContext(mode, environment, ambient, project, options.oop === true);
|
|
21834
|
+
context.noImplicitGlobals = options.noImplicitGlobals === true;
|
|
21266
21835
|
context.isDeclarationFile = options.isDeclarationFile === true;
|
|
21267
21836
|
context.contracts = options.contracts ?? [];
|
|
21268
21837
|
const structure = context.isDeclarationFile ? checkDeclarationFile(program2.body) : checkJumps(program2.body);
|
|
21269
21838
|
const directives = collectDirectives(program2.body, { isDeclarationFile: context.isDeclarationFile });
|
|
21270
21839
|
predeclareModule(context, program2.body);
|
|
21271
21840
|
checkStatements(context, program2.body);
|
|
21841
|
+
settleRecordObligations(context, /* @__PURE__ */ new Set());
|
|
21272
21842
|
reportUnknownTypes(context);
|
|
21273
21843
|
reportUnusedSymbols(context, options.noUnusedLocals === true, options.noUnusedParameters === true);
|
|
21274
21844
|
const external = externalReferences(context);
|
|
@@ -21641,13 +22211,17 @@ function emitExpression(state, expression, limit = 0) {
|
|
|
21641
22211
|
}
|
|
21642
22212
|
|
|
21643
22213
|
// ../compiler/src/emitter/classes.ts
|
|
22214
|
+
var BARE_KEY = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
22215
|
+
function emitMemberKey(name) {
|
|
22216
|
+
return BARE_KEY.test(name) ? name : `[${emitString(name)}]`;
|
|
22217
|
+
}
|
|
21644
22218
|
function emitMethod(state, className, member) {
|
|
21645
22219
|
const self = { name: "self", annotation: null, isVararg: false, position: member.position };
|
|
21646
22220
|
if (member.generated !== void 0) {
|
|
21647
22221
|
return emitGeneratedMethod(state, className, member);
|
|
21648
22222
|
}
|
|
21649
22223
|
const parameters = member.isStatic ? member.parameters : [self, ...member.parameters];
|
|
21650
|
-
return withSymbol(state, `${className}${member.isStatic ? "." : ":"}${member.name}`, () => emitFunctionBody(state, parameters, member.body, `${member.name} = function`));
|
|
22224
|
+
return withSymbol(state, `${className}${member.isStatic ? "." : ":"}${member.name}`, () => emitFunctionBody(state, parameters, member.body, `${emitMemberKey(member.name)} = function`));
|
|
21651
22225
|
}
|
|
21652
22226
|
function emitGeneratedMethod(state, className, member) {
|
|
21653
22227
|
const fields = member.generated?.fields ?? [];
|
|
@@ -21733,7 +22307,7 @@ function emitMembers(state, statement) {
|
|
|
21733
22307
|
continue;
|
|
21734
22308
|
}
|
|
21735
22309
|
const value = member.value === null ? "nil" : emitExpression(state, member.value);
|
|
21736
|
-
entries3.push(indentLine(state, `${markSource(state, member.position.line, statement.name)}${member.name} = ${value}`));
|
|
22310
|
+
entries3.push(indentLine(state, `${markSource(state, member.position.line, statement.name)}${emitMemberKey(member.name)} = ${value}`));
|
|
21737
22311
|
}
|
|
21738
22312
|
for (const generated of state.generatedMembers.get(statement) ?? []) {
|
|
21739
22313
|
entries3.push(indentLine(state, `${markSource(state, generated.position.line, `${statement.name}:${generated.name}`)}${emitMethod(state, statement.name, generated)}`));
|
|
@@ -21926,6 +22500,8 @@ function emitStatement(state, statement) {
|
|
|
21926
22500
|
return emitLocal(state, statement);
|
|
21927
22501
|
case "assignment-statement":
|
|
21928
22502
|
return emitAssignment(state, statement);
|
|
22503
|
+
case "global-statement":
|
|
22504
|
+
return `${statement.declaration.name} = ${statement.values.map((value) => emitExpression(state, value)).join(", ")}`;
|
|
21929
22505
|
case "call-statement":
|
|
21930
22506
|
return emitExpression(state, statement.expression);
|
|
21931
22507
|
case "function-declaration":
|
|
@@ -22133,6 +22709,9 @@ function nestedBlocks(statement) {
|
|
|
22133
22709
|
case "assignment-statement":
|
|
22134
22710
|
fromExpressions([...statement.targets, ...statement.values], blocks);
|
|
22135
22711
|
break;
|
|
22712
|
+
case "global-statement":
|
|
22713
|
+
fromExpressions(statement.values, blocks);
|
|
22714
|
+
break;
|
|
22136
22715
|
case "call-statement":
|
|
22137
22716
|
fromExpression(statement.expression, blocks);
|
|
22138
22717
|
break;
|
|
@@ -22824,6 +23403,7 @@ function compile(source, options = {}) {
|
|
|
22824
23403
|
isDeclarationFile,
|
|
22825
23404
|
oop: settings.oop,
|
|
22826
23405
|
noUnusedLocals: settings.noUnusedLocals,
|
|
23406
|
+
noImplicitGlobals: settings.noImplicitGlobals,
|
|
22827
23407
|
noUnusedParameters: settings.noUnusedParameters
|
|
22828
23408
|
});
|
|
22829
23409
|
const diagnostics = sortDiagnostics([...parsed.diagnostics, ...resolved2.diagnostics, ...checked.diagnostics]);
|
|
@@ -23067,11 +23647,12 @@ function createDependencyGraph(nodes) {
|
|
|
23067
23647
|
|
|
23068
23648
|
// ../compiler/src/project/ambient-scope.ts
|
|
23069
23649
|
function optionsKey(options) {
|
|
23070
|
-
|
|
23650
|
+
const flags = [options.strict ? "strict" : "", options.oop ? "oop" : "", options.noUnusedLocals ? "nul" : "", options.noUnusedParameters ? "nup" : ""];
|
|
23651
|
+
return `${flags.join("|")}|${options.noImplicitGlobals ? "nig" : ""}`;
|
|
23071
23652
|
}
|
|
23072
23653
|
function declaresNothing(declarations) {
|
|
23073
|
-
const { classes, interfaces, enums, globals, events } = declarations;
|
|
23074
|
-
return classes.length === 0 && interfaces.length === 0 && enums.length === 0 && globals.length === 0 && events.length === 0;
|
|
23654
|
+
const { classes, interfaces, enums, aliases, globals, events } = declarations;
|
|
23655
|
+
return classes.length === 0 && interfaces.length === 0 && enums.length === 0 && aliases.length === 0 && globals.length === 0 && events.length === 0;
|
|
23075
23656
|
}
|
|
23076
23657
|
function sharedEnums(collected) {
|
|
23077
23658
|
const declared = new Set(collected.flatMap((entry) => entry.declarations.enums.map((enumeration) => enumeration.name)));
|