mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-04-25 15:12:12 +00:00
Support definite assignment assertion x!: i32
(#260)
This commit is contained in:
parent
e58582e9e9
commit
0bb5cb829e
@ -36,44 +36,46 @@ export enum CommonFlags {
|
||||
GET = 1 << 11,
|
||||
/** Has a `set` modifier. */
|
||||
SET = 1 << 12,
|
||||
/** Has a definite assignment assertion `!` as in `x!: i32;`. */
|
||||
DEFINITE_ASSIGNMENT = 1 << 13,
|
||||
|
||||
// Extended modifiers usually derived from basic modifiers
|
||||
|
||||
/** Is ambient, that is either declared or nested in a declared element. */
|
||||
AMBIENT = 1 << 13,
|
||||
AMBIENT = 1 << 14,
|
||||
/** Is generic. */
|
||||
GENERIC = 1 << 14,
|
||||
GENERIC = 1 << 15,
|
||||
/** Is part of a generic context. */
|
||||
GENERIC_CONTEXT = 1 << 15,
|
||||
GENERIC_CONTEXT = 1 << 16,
|
||||
/** Is an instance member. */
|
||||
INSTANCE = 1 << 16,
|
||||
INSTANCE = 1 << 17,
|
||||
/** Is a constructor. */
|
||||
CONSTRUCTOR = 1 << 17,
|
||||
CONSTRUCTOR = 1 << 18,
|
||||
/** Is an arrow function. */
|
||||
ARROW = 1 << 18,
|
||||
ARROW = 1 << 19,
|
||||
/** Is a module export. */
|
||||
MODULE_EXPORT = 1 << 19,
|
||||
MODULE_EXPORT = 1 << 20,
|
||||
/** Is a module import. */
|
||||
MODULE_IMPORT = 1 << 20,
|
||||
MODULE_IMPORT = 1 << 21,
|
||||
|
||||
// Compilation states
|
||||
|
||||
/** Is compiled. */
|
||||
COMPILED = 1 << 21,
|
||||
COMPILED = 1 << 22,
|
||||
/** Has a constant value and is therefore inlined. */
|
||||
INLINED = 1 << 22,
|
||||
INLINED = 1 << 23,
|
||||
/** Is scoped. */
|
||||
SCOPED = 1 << 23,
|
||||
SCOPED = 1 << 24,
|
||||
/** Is a trampoline. */
|
||||
TRAMPOLINE = 1 << 24,
|
||||
TRAMPOLINE = 1 << 25,
|
||||
/** Is a virtual method. */
|
||||
VIRTUAL = 1 << 25,
|
||||
VIRTUAL = 1 << 26,
|
||||
/** Is the main function. */
|
||||
MAIN = 1 << 26,
|
||||
MAIN = 1 << 27,
|
||||
|
||||
// Other
|
||||
|
||||
QUOTED = 1 << 27
|
||||
QUOTED = 1 << 28
|
||||
}
|
||||
|
||||
/** Path delimiter inserted between file system levels. */
|
||||
|
@ -29,6 +29,7 @@ export enum DiagnosticCode {
|
||||
Constructor_of_class_0_must_not_require_any_arguments = 216,
|
||||
Function_0_cannot_be_inlined_into_itself = 217,
|
||||
Cannot_access_method_0_without_calling_it_as_it_requires_this_to_be_set = 218,
|
||||
Optional_properties_are_not_supported = 219,
|
||||
Unterminated_string_literal = 1002,
|
||||
Identifier_expected = 1003,
|
||||
_0_expected = 1005,
|
||||
@ -81,6 +82,7 @@ export enum DiagnosticCode {
|
||||
Decorators_are_not_valid_here = 1206,
|
||||
_abstract_modifier_can_only_appear_on_a_class_method_or_property_declaration = 1242,
|
||||
Method_0_cannot_have_an_implementation_because_it_is_marked_abstract = 1245,
|
||||
A_definite_assignment_assertion_is_not_permitted_in_this_context = 1255,
|
||||
A_class_may_only_extend_another_class = 1311,
|
||||
A_parameter_property_cannot_be_declared_using_a_rest_parameter = 1317,
|
||||
Duplicate_identifier_0 = 2300,
|
||||
@ -149,6 +151,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
|
||||
case 216: return "Constructor of class '{0}' must not require any arguments.";
|
||||
case 217: return "Function '{0}' cannot be inlined into itself.";
|
||||
case 218: return "Cannot access method '{0}' without calling it as it requires 'this' to be set.";
|
||||
case 219: return "Optional properties are not supported.";
|
||||
case 1002: return "Unterminated string literal.";
|
||||
case 1003: return "Identifier expected.";
|
||||
case 1005: return "'{0}' expected.";
|
||||
@ -201,6 +204,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
|
||||
case 1206: return "Decorators are not valid here.";
|
||||
case 1242: return "'abstract' modifier can only appear on a class, method, or property declaration.";
|
||||
case 1245: return "Method '{0}' cannot have an implementation because it is marked abstract.";
|
||||
case 1255: return "A definite assignment assertion '!' is not permitted in this context.";
|
||||
case 1311: return "A class may only extend another class.";
|
||||
case 1317: return "A parameter property cannot be declared using a rest parameter.";
|
||||
case 2300: return "Duplicate identifier '{0}'.";
|
||||
|
@ -21,6 +21,7 @@
|
||||
"Constructor of class '{0}' must not require any arguments.": 216,
|
||||
"Function '{0}' cannot be inlined into itself.": 217,
|
||||
"Cannot access method '{0}' without calling it as it requires 'this' to be set.": 218,
|
||||
"Optional properties are not supported.": 219,
|
||||
|
||||
"Unterminated string literal.": 1002,
|
||||
"Identifier expected.": 1003,
|
||||
@ -74,6 +75,7 @@
|
||||
"Decorators are not valid here.": 1206,
|
||||
"'abstract' modifier can only appear on a class, method, or property declaration.": 1242,
|
||||
"Method '{0}' cannot have an implementation because it is marked abstract.": 1245,
|
||||
"A definite assignment assertion '!' is not permitted in this context.": 1255,
|
||||
"A class may only extend another class.": 1311,
|
||||
"A parameter property cannot be declared using a rest parameter.": 1317,
|
||||
|
||||
|
@ -990,6 +990,9 @@ export class ASTBuilder {
|
||||
this.serializeAccessModifiers(node);
|
||||
this.visitIdentifierExpression(node.name);
|
||||
var sb = this.sb;
|
||||
if (node.flags & CommonFlags.DEFINITE_ASSIGNMENT) {
|
||||
sb.push("!");
|
||||
}
|
||||
var type = node.type;
|
||||
if (type) {
|
||||
sb.push(": ");
|
||||
@ -1376,6 +1379,9 @@ export class ASTBuilder {
|
||||
this.visitIdentifierExpression(node.name);
|
||||
var type = node.type;
|
||||
var sb = this.sb;
|
||||
if (node.flags & CommonFlags.DEFINITE_ASSIGNMENT) {
|
||||
sb.push("!");
|
||||
}
|
||||
if (type) {
|
||||
sb.push(": ");
|
||||
this.visitTypeNode(type);
|
||||
|
@ -769,6 +769,9 @@ export class Parser extends DiagnosticEmitter {
|
||||
}
|
||||
var identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
|
||||
var flags = parentFlags;
|
||||
if (tn.skip(Token.EXCLAMATION)) {
|
||||
flags |= CommonFlags.DEFINITE_ASSIGNMENT;
|
||||
}
|
||||
|
||||
var type: CommonTypeNode | null = null;
|
||||
if (tn.skip(Token.COLON)) {
|
||||
@ -800,13 +803,19 @@ export class Parser extends DiagnosticEmitter {
|
||||
); // recoverable
|
||||
}
|
||||
}
|
||||
var range = Range.join(identifier.range, tn.range());
|
||||
if ((flags & CommonFlags.DEFINITE_ASSIGNMENT) && initializer) {
|
||||
this.error(
|
||||
DiagnosticCode.A_definite_assignment_assertion_is_not_permitted_in_this_context,
|
||||
range);
|
||||
}
|
||||
return Node.createVariableDeclaration(
|
||||
identifier,
|
||||
type,
|
||||
initializer,
|
||||
parentDecorators,
|
||||
flags,
|
||||
Range.join(identifier.range, tn.range())
|
||||
range
|
||||
);
|
||||
}
|
||||
|
||||
@ -1926,6 +1935,15 @@ export class Parser extends DiagnosticEmitter {
|
||||
}
|
||||
|
||||
let type: CommonTypeNode | null = null;
|
||||
if (tn.skip(Token.QUESTION)) {
|
||||
this.error(
|
||||
DiagnosticCode.Optional_properties_are_not_supported,
|
||||
tn.range(startPos, tn.pos)
|
||||
);
|
||||
}
|
||||
if (tn.skip(Token.EXCLAMATION)) {
|
||||
flags |= CommonFlags.DEFINITE_ASSIGNMENT;
|
||||
}
|
||||
if (tn.skip(Token.COLON)) {
|
||||
type = this.parseType(tn);
|
||||
if (!type) return null;
|
||||
@ -1940,13 +1958,20 @@ export class Parser extends DiagnosticEmitter {
|
||||
initializer = this.parseExpression(tn);
|
||||
if (!initializer) return null;
|
||||
}
|
||||
let range = tn.range(startPos, tn.pos);
|
||||
if ((flags & CommonFlags.DEFINITE_ASSIGNMENT) && ((flags & CommonFlags.STATIC) || isInterface || initializer)) {
|
||||
this.error(
|
||||
DiagnosticCode.A_definite_assignment_assertion_is_not_permitted_in_this_context,
|
||||
range
|
||||
);
|
||||
}
|
||||
let retField = Node.createFieldDeclaration(
|
||||
name,
|
||||
type,
|
||||
initializer,
|
||||
decorators,
|
||||
flags,
|
||||
tn.range(startPos, tn.pos)
|
||||
range
|
||||
);
|
||||
tn.skip(Token.SEMICOLON);
|
||||
return retField;
|
||||
|
9
tests/parser/definite-assignment-assertion.ts
Normal file
9
tests/parser/definite-assignment-assertion.ts
Normal file
@ -0,0 +1,9 @@
|
||||
class C {
|
||||
x!: i32;
|
||||
x!: i32 = 0;
|
||||
static x!: i32;
|
||||
}
|
||||
function f(): void {
|
||||
let x!: i32;
|
||||
let x!: i32 = 0;
|
||||
}
|
12
tests/parser/definite-assignment-assertion.ts.fixture.ts
Normal file
12
tests/parser/definite-assignment-assertion.ts.fixture.ts
Normal file
@ -0,0 +1,12 @@
|
||||
class C {
|
||||
x!: i32;
|
||||
x!: i32 = 0;
|
||||
static x!: i32;
|
||||
}
|
||||
function f(): void {
|
||||
let x!: i32;
|
||||
let x!: i32 = 0;
|
||||
}
|
||||
// ERROR 1255: "A definite assignment assertion '!' is not permitted in this context." in definite-assignment-assertion.ts:3:10
|
||||
// ERROR 1255: "A definite assignment assertion '!' is not permitted in this context." in definite-assignment-assertion.ts:4:14
|
||||
// ERROR 1255: "A definite assignment assertion '!' is not permitted in this context." in definite-assignment-assertion.ts:8:6
|
3
tests/parser/optional-property.ts
Normal file
3
tests/parser/optional-property.ts
Normal file
@ -0,0 +1,3 @@
|
||||
class C {
|
||||
x?: i32;
|
||||
}
|
4
tests/parser/optional-property.ts.fixture.ts
Normal file
4
tests/parser/optional-property.ts.fixture.ts
Normal file
@ -0,0 +1,4 @@
|
||||
class C {
|
||||
x: i32;
|
||||
}
|
||||
// ERROR 219: "Optional properties are not supported." in optional-property.ts:2:9
|
Loading…
x
Reference in New Issue
Block a user