[flow] Explicit inexact objects with ... (#8884)

This commit is contained in:
Jordan Brown
2018-10-29 16:09:17 -04:00
committed by Brian Ng
parent d942d47e10
commit e4929e11f6
77 changed files with 1181 additions and 86 deletions

View File

@@ -463,7 +463,13 @@ export default (superClass: Class<Parser>): Class<Parser> =>
} while (this.eat(tt.comma));
}
node.body = this.flowParseObjectType(isClass, false, false, isClass);
node.body = this.flowParseObjectType({
allowStatic: isClass,
allowExact: false,
allowSpread: false,
allowProto: isClass,
allowInexact: false,
});
}
flowParseInterfaceExtends(): N.FlowInterfaceExtends {
@@ -656,7 +662,13 @@ export default (superClass: Class<Parser>): Class<Parser> =>
} while (this.eat(tt.comma));
}
node.body = this.flowParseObjectType(false, false, false, false);
node.body = this.flowParseObjectType({
allowStatic: false,
allowExact: false,
allowSpread: false,
allowProto: false,
allowInexact: false,
});
return this.finishNode(node, "InterfaceTypeAnnotation");
}
@@ -754,12 +766,19 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return this.finishNode(node, "ObjectTypeCallProperty");
}
flowParseObjectType(
flowParseObjectType({
allowStatic,
allowExact,
allowSpread,
allowProto,
allowInexact,
}: {
allowStatic: boolean,
allowExact: boolean,
allowSpread: boolean,
allowProto: boolean,
): N.FlowObjectTypeAnnotation {
allowInexact: boolean,
}): N.FlowObjectTypeAnnotation {
const oldInType = this.state.inType;
this.state.inType = true;
@@ -772,6 +791,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
let endDelim;
let exact;
let inexact = false;
if (allowExact && this.match(tt.braceBarL)) {
this.expect(tt.braceBarL);
endDelim = tt.braceBarR;
@@ -852,16 +872,21 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
}
nodeStart.properties.push(
this.flowParseObjectTypeProperty(
node,
isStatic,
protoStart,
variance,
kind,
allowSpread,
),
const propOrInexact = this.flowParseObjectTypeProperty(
node,
isStatic,
protoStart,
variance,
kind,
allowSpread,
allowInexact,
);
if (propOrInexact === null) {
inexact = true;
} else {
nodeStart.properties.push(propOrInexact);
}
}
this.flowObjectTypeSemicolon();
@@ -869,6 +894,15 @@ export default (superClass: Class<Parser>): Class<Parser> =>
this.expect(endDelim);
/* The inexact flag should only be added on ObjectTypeAnnotations that
* are not the body of an interface, declare interface, or declare class.
* Since spreads are only allowed in objec types, checking that is
* sufficient here.
*/
if (allowSpread) {
nodeStart.inexact = inexact;
}
const out = this.finishNode(nodeStart, "ObjectTypeAnnotation");
this.state.inType = oldInType;
@@ -883,7 +917,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
variance: ?N.FlowVariance,
kind: string,
allowSpread: boolean,
): N.FlowObjectTypeProperty | N.FlowObjectTypeSpreadProperty {
allowInexact: boolean,
): (N.FlowObjectTypeProperty | N.FlowObjectTypeSpreadProperty) | null {
if (this.match(tt.ellipsis)) {
if (!allowSpread) {
this.unexpected(
@@ -901,8 +936,30 @@ export default (superClass: Class<Parser>): Class<Parser> =>
);
}
this.expect(tt.ellipsis);
node.argument = this.flowParseType();
const isInexactToken = this.eat(tt.comma) || this.eat(tt.semi);
if (this.match(tt.braceR)) {
if (allowInexact) return null;
this.unexpected(
null,
"Explicit inexact syntax is only allowed inside inexact objects",
);
}
if (this.match(tt.braceBarR)) {
this.unexpected(
null,
"Explicit inexact syntax cannot appear inside an explicit exact object type",
);
}
if (isInexactToken) {
this.unexpected(
null,
"Explicit inexact syntax must appear at the end of an inexact object",
);
}
node.argument = this.flowParseType();
return this.finishNode(node, "ObjectTypeSpreadProperty");
} else {
node.key = this.flowParseObjectPropertyKey();
@@ -1146,10 +1203,22 @@ export default (superClass: Class<Parser>): Class<Parser> =>
);
case tt.braceL:
return this.flowParseObjectType(false, false, true, false);
return this.flowParseObjectType({
allowStatic: false,
allowExact: false,
allowSpread: true,
allowProto: false,
allowInexact: true,
});
case tt.braceBarL:
return this.flowParseObjectType(false, true, true, false);
return this.flowParseObjectType({
allowStatic: false,
allowExact: true,
allowSpread: true,
allowProto: false,
allowInexact: false,
});
case tt.bracketL:
return this.flowParseTupleType();