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.CALL:
case NodeKind.ELEMENTACCESS:
case NodeKind.PROPERTYACCESS: return true;
case NodeKind.PROPERTYACCESS:
case NodeKind.PARENTHESIZED: return true;
}
return false;
}

View File

@ -353,7 +353,8 @@ export class ASTBuilder {
return;
}
var typeNode = <TypeNode>node;
this.visitIdentifierExpression(<IdentifierExpression>typeNode.name);
assert(typeNode.name.text.length);
this.visitIdentifierExpression(typeNode.name);
var typeArguments = typeNode.typeArguments;
if (typeArguments) {
let numTypeArguments = typeArguments.length;
@ -1081,22 +1082,24 @@ export class ASTBuilder {
var returnType = signature.returnType;
if (node.is(CommonFlags.ARROW)) {
if (body) {
if (returnType) {
if (isTypeOmitted(returnType)) {
sb.push(")");
} else {
sb.push("): ");
this.visitTypeNode(returnType);
}
sb.push(" => ");
this.visitNode(body);
} else {
if (returnType) {
sb.push(" => ");
this.visitTypeNode(returnType);
} else {
sb.push(" => void");
}
assert(!isTypeOmitted(returnType));
sb.push(" => ");
this.visitTypeNode(returnType);
}
} else {
if (returnType && !node.isAny(CommonFlags.CONSTRUCTOR | CommonFlags.SET)) {
if (
!isTypeOmitted(returnType) &&
!node.isAny(CommonFlags.CONSTRUCTOR | CommonFlags.SET)
) {
sb.push("): ");
this.visitTypeNode(returnType);
} else {
@ -1454,12 +1457,11 @@ export class ASTBuilder {
var type = node.type;
var initializer = node.initializer;
if (type) {
if (kind == ParameterKind.OPTIONAL && !initializer) {
sb.push("?: ");
} else {
if (kind == ParameterKind.OPTIONAL) sb.push("?");
if (!isTypeOmitted(type)) {
sb.push(": ");
this.visitTypeNode(type);
}
this.visitTypeNode(type);
}
if (initializer) {
sb.push(" = ");
@ -1503,3 +1505,7 @@ export class ASTBuilder {
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
case Token.CLOSEPAREN: {
if (!tn.skip(Token.EQUALS_GREATERTHAN)) {
if (
!tn.skip(Token.COLON) &&
!tn.skip(Token.EQUALS_GREATERTHAN)
) {
again = false;
break;
}
@ -3004,8 +3007,19 @@ export class Parser extends DiagnosticEmitter {
tn.reset(state);
return this.parseFunctionExpression(tn);
}
// can be both
case Token.QUESTION: // optional parameter or ternary
// optional parameter or parenthesized
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: {
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> {
constructor<T>() {}
instanceFunction(): {}
get instanceGetter<T>(a: i32): {}
instanceFunction() {}
get instanceGetter<T>(a: i32) {}
set instanceSetter<T>() {}
}
// 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) {}
}
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 typeparams<T, V extends T>(a: V | null = null): void {}
function typeparams<T, V extends T>(a?: V | null = null): void {}
@decorator()
function withdecorator(): void {}
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 restParameterMustBeLast(...a: Array<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 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

View File

@ -1,7 +1,7 @@
@binding(BindingCall.NEW, [BindingType.STRING], BindingType.OBJECT_HANDLE)
export class ExternalString {
@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();
}
@binding(BindingCall.FUNCTION, [BindingType.U32], BindingType.OBJECT_HANDLE)