Fix some array function parsing and serialization issues

Quite similar to #256 and also uses its test, but also fixes the serializer and doesn't try to parse an untyped 'x => x'.
This commit is contained in:
dcodeIO 2018-10-04 09:53:47 +02:00
parent 59e2a63b83
commit 63d4579118
12 changed files with 68 additions and 26 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -117,7 +117,8 @@ export function nodeIsCallable(kind: NodeKind): bool {
case NodeKind.IDENTIFIER: case NodeKind.IDENTIFIER:
case NodeKind.CALL: case NodeKind.CALL:
case NodeKind.ELEMENTACCESS: case NodeKind.ELEMENTACCESS:
case NodeKind.PROPERTYACCESS: return true; case NodeKind.PROPERTYACCESS:
case NodeKind.PARENTHESIZED: return true;
} }
return false; return false;
} }

View File

@ -353,7 +353,8 @@ export class ASTBuilder {
return; return;
} }
var typeNode = <TypeNode>node; var typeNode = <TypeNode>node;
this.visitIdentifierExpression(<IdentifierExpression>typeNode.name); assert(typeNode.name.text.length);
this.visitIdentifierExpression(typeNode.name);
var typeArguments = typeNode.typeArguments; var typeArguments = typeNode.typeArguments;
if (typeArguments) { if (typeArguments) {
let numTypeArguments = typeArguments.length; let numTypeArguments = typeArguments.length;
@ -1081,22 +1082,24 @@ export class ASTBuilder {
var returnType = signature.returnType; var returnType = signature.returnType;
if (node.is(CommonFlags.ARROW)) { if (node.is(CommonFlags.ARROW)) {
if (body) { if (body) {
if (returnType) { if (isTypeOmitted(returnType)) {
sb.push(")");
} else {
sb.push("): "); sb.push("): ");
this.visitTypeNode(returnType); this.visitTypeNode(returnType);
} }
sb.push(" => "); sb.push(" => ");
this.visitNode(body); this.visitNode(body);
} else { } else {
if (returnType) { assert(!isTypeOmitted(returnType));
sb.push(" => "); sb.push(" => ");
this.visitTypeNode(returnType); this.visitTypeNode(returnType);
} else {
sb.push(" => void");
}
} }
} else { } else {
if (returnType && !node.isAny(CommonFlags.CONSTRUCTOR | CommonFlags.SET)) { if (
!isTypeOmitted(returnType) &&
!node.isAny(CommonFlags.CONSTRUCTOR | CommonFlags.SET)
) {
sb.push("): "); sb.push("): ");
this.visitTypeNode(returnType); this.visitTypeNode(returnType);
} else { } else {
@ -1454,13 +1457,12 @@ export class ASTBuilder {
var type = node.type; var type = node.type;
var initializer = node.initializer; var initializer = node.initializer;
if (type) { if (type) {
if (kind == ParameterKind.OPTIONAL && !initializer) { if (kind == ParameterKind.OPTIONAL) sb.push("?");
sb.push("?: "); if (!isTypeOmitted(type)) {
} else {
sb.push(": "); sb.push(": ");
}
this.visitTypeNode(type); this.visitTypeNode(type);
} }
}
if (initializer) { if (initializer) {
sb.push(" = "); sb.push(" = ");
this.visitNode(initializer); this.visitNode(initializer);
@ -1503,3 +1505,7 @@ export class ASTBuilder {
return ret; return ret;
} }
} }
function isTypeOmitted(type: CommonTypeNode): bool {
return type.kind == NodeKind.TYPE && !changetype<TypeNode>(type).name.text.length;
}

View File

@ -2993,7 +2993,10 @@ export class Parser extends DiagnosticEmitter {
// if we got here, check for arrow // if we got here, check for arrow
case Token.CLOSEPAREN: { case Token.CLOSEPAREN: {
if (!tn.skip(Token.EQUALS_GREATERTHAN)) { if (
!tn.skip(Token.COLON) &&
!tn.skip(Token.EQUALS_GREATERTHAN)
) {
again = false; again = false;
break; break;
} }
@ -3004,8 +3007,19 @@ export class Parser extends DiagnosticEmitter {
tn.reset(state); tn.reset(state);
return this.parseFunctionExpression(tn); return this.parseFunctionExpression(tn);
} }
// can be both // optional parameter or parenthesized
case Token.QUESTION: // optional parameter or ternary case Token.QUESTION: {
if (
tn.skip(Token.COLON) || // optional parameter with type
tn.skip(Token.COMMA) || // optional parameter without type
tn.skip(Token.CLOSEPAREN) // last optional parameter without type
) {
tn.reset(state);
return this.parseFunctionExpression(tn);
}
again = false; // parenthesized
break;
}
case Token.COMMA: { case Token.COMMA: {
break; // continue break; // continue
} }

View File

@ -0,0 +1,10 @@
// array function
(x): i32 => x;
(x: i32) => x;
(x?) => x;
(x?, y?) => x;
(x?: i32) => x;
// not an array function
(b ? x : y);
(b ? f : g)();

View File

@ -0,0 +1,11 @@
(x): i32 => x;
(x: i32) => x;
(x?) => x;
(x?, y?) => x;
(x?: i32) => x;
(b ? x : y);
(b ? f : g)();
// ERROR 1110: "Type expected." in arrow-functions.ts:3:8
// ERROR 1110: "Type expected." in arrow-functions.ts:4:4
// ERROR 1110: "Type expected." in arrow-functions.ts:5:8
// ERROR 1110: "Type expected." in arrow-functions.ts:6:9

View File

@ -9,8 +9,8 @@ export class Valid<T> {
} }
export class Invalid<T> { export class Invalid<T> {
constructor<T>() {} constructor<T>() {}
instanceFunction(): {} instanceFunction() {}
get instanceGetter<T>(a: i32): {} get instanceGetter<T>(a: i32) {}
set instanceSetter<T>() {} set instanceSetter<T>() {}
} }
// ERROR 1092: "Type parameters cannot appear on a constructor declaration." in class.ts:13:13 // ERROR 1092: "Type parameters cannot appear on a constructor declaration." in class.ts:13:13

View File

@ -4,5 +4,5 @@ class MyClass {
constructor(a: i32, b: i32) {} constructor(a: i32, b: i32) {}
} }
class MyClassImplicit { class MyClassImplicit {
constructor(public a: i32, private readonly b: i32 = 2, c: i32 = 3) {} constructor(public a: i32, private readonly b?: i32 = 2, c?: i32 = 3) {}
} }

View File

@ -1,5 +1,5 @@
function simple(): void {} function simple(): void {}
function typeparams<T, V extends T>(a: V | null = null): void {} function typeparams<T, V extends T>(a?: V | null = null): void {}
@decorator() @decorator()
function withdecorator(): void {} function withdecorator(): void {}
function withthis(this: i32): i32 { function withthis(this: i32): i32 {

View File

@ -2,7 +2,7 @@ function restValid(a: i32, ...b: Array<i32>): void {}
function optionalValid(a: i32, b?: i32): void {} function optionalValid(a: i32, b?: i32): void {}
function restParameterMustBeLast(...a: Array<i32>, b: i32): void {} function restParameterMustBeLast(...a: Array<i32>, b: i32): void {}
function optionalCannotPrecedeRequired(a?: i32, b: i32): void {} function optionalCannotPrecedeRequired(a?: i32, b: i32): void {}
function optionalWithInitializerCannotPrecedeRequired(a: i32 = 1, b: i32): void {} function optionalWithInitializerCannotPrecedeRequired(a?: i32 = 1, b: i32): void {}
// ERROR 1014: "A rest parameter must be last in a parameter list." in parameter-order.ts:5:36 // ERROR 1014: "A rest parameter must be last in a parameter list." in parameter-order.ts:5:36
// ERROR 1016: "A required parameter cannot follow an optional parameter." in parameter-order.ts:8:48 // ERROR 1016: "A required parameter cannot follow an optional parameter." in parameter-order.ts:8:48
// ERROR 1016: "A required parameter cannot follow an optional parameter." in parameter-order.ts:11:66 // ERROR 1016: "A required parameter cannot follow an optional parameter." in parameter-order.ts:11:66

View File

@ -1,7 +1,7 @@
@binding(BindingCall.NEW, [BindingType.STRING], BindingType.OBJECT_HANDLE) @binding(BindingCall.NEW, [BindingType.STRING], BindingType.OBJECT_HANDLE)
export class ExternalString { export class ExternalString {
@binding(BindingCall.FUNCTION, [BindingType.U32, BindingType.U32], BindingType.OBJECT_HANDLE) @binding(BindingCall.FUNCTION, [BindingType.U32, BindingType.U32], BindingType.OBJECT_HANDLE)
static fromCharCode(char: u16, schar: u16 = <u16>-1): String { static fromCharCode(char: u16, schar?: u16 = <u16>-1): String {
return unreachable(); return unreachable();
} }
@binding(BindingCall.FUNCTION, [BindingType.U32], BindingType.OBJECT_HANDLE) @binding(BindingCall.FUNCTION, [BindingType.U32], BindingType.OBJECT_HANDLE)