Skip to content

Commit

Permalink
[flow] Explicit inexact objects with ... (#8884)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbrown215 authored and existentialism committed Oct 29, 2018
1 parent d942d47 commit e4929e1
Show file tree
Hide file tree
Showing 77 changed files with 1,181 additions and 86 deletions.
103 changes: 86 additions & 17 deletions packages/babel-parser/src/plugins/flow.js
Expand Up @@ -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 {
Expand Down Expand Up @@ -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");
}
Expand Down Expand Up @@ -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;

Expand All @@ -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;
Expand Down Expand Up @@ -852,23 +872,37 @@ 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();
}

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;
Expand All @@ -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(
Expand All @@ -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();
Expand Down Expand Up @@ -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();
Expand Down
Expand Up @@ -156,7 +156,8 @@
"properties": [],
"indexers": [],
"internalSlots": [],
"exact": false
"exact": false,
"inexact": false
}
}
},
Expand Down
Expand Up @@ -156,7 +156,8 @@
"properties": [],
"indexers": [],
"internalSlots": [],
"exact": false
"exact": false,
"inexact": false
}
}
},
Expand Down
Expand Up @@ -308,7 +308,8 @@
],
"indexers": [],
"internalSlots": [],
"exact": false
"exact": false,
"inexact": false
}
}
},
Expand Down
Expand Up @@ -256,7 +256,8 @@
"properties": [],
"indexers": [],
"internalSlots": [],
"exact": false
"exact": false,
"inexact": false
}
}
},
Expand Down
Expand Up @@ -239,7 +239,8 @@
],
"indexers": [],
"internalSlots": [],
"exact": false
"exact": false,
"inexact": false
}
}
],
Expand Down
Expand Up @@ -239,7 +239,8 @@
],
"indexers": [],
"internalSlots": [],
"exact": false
"exact": false,
"inexact": false
}
}
],
Expand Down
Expand Up @@ -146,7 +146,8 @@
],
"indexers": [],
"internalSlots": [],
"exact": false
"exact": false,
"inexact": false
}
}
}
Expand Down
Expand Up @@ -192,7 +192,8 @@
],
"indexers": [],
"internalSlots": [],
"exact": false
"exact": false,
"inexact": false
}
}
}
Expand Down
Expand Up @@ -243,7 +243,8 @@
}
],
"internalSlots": [],
"exact": false
"exact": false,
"inexact": false
}
}
],
Expand Down
Expand Up @@ -422,7 +422,8 @@
"properties": [],
"indexers": [],
"internalSlots": [],
"exact": false
"exact": false,
"inexact": false
}
}
],
Expand Down
@@ -0,0 +1,4 @@
//@flow
declare class A {
...;
}
@@ -0,0 +1,5 @@
{
"sourceType": "module",
"plugins": ["jsx", "flow"],
"throws": "Spread operator cannot appear in class or interface definitions (3:2)"
}
@@ -0,0 +1,5 @@
//@flow
declare class B {
foo: number;
...;
}
@@ -0,0 +1,5 @@
{
"sourceType": "module",
"plugins": ["jsx", "flow"],
"throws": "Spread operator cannot appear in class or interface definitions (4:2)"
}
@@ -0,0 +1,5 @@
//@flow
declare class C {
...;
foo: number;
}
@@ -0,0 +1,5 @@
{
"sourceType": "module",
"plugins": ["jsx", "flow"],
"throws": "Spread operator cannot appear in class or interface definitions (3:2)"
}
@@ -0,0 +1,6 @@
//@flow
declare class D {
foo: number;
...;
bar: number;
}
@@ -0,0 +1,5 @@
{
"sourceType": "module",
"plugins": ["jsx", "flow"],
"throws": "Spread operator cannot appear in class or interface definitions (4:2)"
}
@@ -0,0 +1,5 @@
//@flow
interface F {
foo: number;
...;
}
@@ -0,0 +1,5 @@
{
"sourceType": "module",
"plugins": ["jsx", "flow"],
"throws": "Spread operator cannot appear in class or interface definitions (4:2)"
}
@@ -0,0 +1,5 @@
//@flow
interface G {
...;
foo: number;
}
@@ -0,0 +1,5 @@
{
"sourceType": "module",
"plugins": ["jsx", "flow"],
"throws": "Spread operator cannot appear in class or interface definitions (3:2)"
}
@@ -0,0 +1,6 @@
//@flow
interface H {
foo: number;
...;
bar: number;
}
@@ -0,0 +1,5 @@
{
"sourceType": "module",
"plugins": ["jsx", "flow"],
"throws": "Spread operator cannot appear in class or interface definitions (4:2)"
}
@@ -0,0 +1,2 @@
//@flow
type T = {| foo: number, ... |}
@@ -0,0 +1,5 @@
{
"sourceType": "module",
"plugins": ["jsx", "flow"],
"throws": "Explicit inexact syntax cannot appear inside an explicit exact object type (2:29)"
}
@@ -0,0 +1,2 @@
//@flow
type T = {..., foo: number};
@@ -0,0 +1,5 @@
{
"sourceType": "module",
"plugins": ["jsx", "flow"],
"throws": "Explicit inexact syntax must appear at the end of an inexact object (2:15)"
}
@@ -0,0 +1,4 @@
//@flow
type T = {...};
type U = {x: number, ...};
type V = {x: number, ...V, ...U};

0 comments on commit e4929e1

Please sign in to comment.