Skip to content
This repository has been archived by the owner on May 19, 2018. It is now read-only.

Commit

Permalink
Fix flow errors (#735)
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolo-ribaudo authored and hzoo committed Sep 27, 2017
1 parent 8af007d commit 664ff37
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 75 deletions.
2 changes: 2 additions & 0 deletions .flowconfig
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@
suppress_comment= \\(.\\|\n\\)*\\$FlowFixMe
suppress_comment= \\(.\\|\n\\)*\\$FlowIssue
suppress_comment= \\(.\\|\n\\)*\\$FlowIgnore
suppress_type=$FlowFixMe
suppress_type=$FlowSubtype
10 changes: 3 additions & 7 deletions src/parser/expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -1401,21 +1401,17 @@ export default class ExpressionParser extends LValParser {
}

parsePropertyName(
prop:
| N.ObjectOrClassMember
| N.ClassPrivateProperty
| N.ClassPrivateMethod
| N.TsNamedTypeElementBase,
prop: N.ObjectOrClassMember | N.ClassMember | N.TsNamedTypeElementBase,
): N.Expression | N.Identifier {
if (this.eat(tt.bracketL)) {
prop.computed = true;
(prop: $FlowSubtype<N.ObjectOrClassMember>).computed = true;
prop.key = this.parseMaybeAssign();
this.expect(tt.bracketR);
} else {
const oldInPropertyName = this.state.inPropertyName;
this.state.inPropertyName = true;
// We check if it's valid for it to be a private name when we push it.
prop.key =
(prop: $FlowFixMe).key =
this.match(tt.num) || this.match(tt.string)
? this.parseExprAtom()
: this.parseMaybePrivateName();
Expand Down
113 changes: 60 additions & 53 deletions src/parser/statement.js
Original file line number Diff line number Diff line change
Expand Up @@ -921,15 +921,12 @@ export default class StatementParser extends ExpressionParser {
member: N.ClassMember,
state: { hadConstructor: boolean },
): void {
// Use the appropriate variable to represent `member` once a more specific type is known.
const memberAny: any = member;
const method: N.ClassMethod = memberAny;
const prop: N.ClassProperty = memberAny;

let isStatic = false;
if (this.match(tt.name) && this.state.value === "static") {
const key = this.parseIdentifier(true); // eats 'static'
if (this.isClassMethod()) {
const method: N.ClassMethod = (member: any);

// a method named 'static'
method.kind = "method";
method.computed = false;
Expand All @@ -944,6 +941,8 @@ export default class StatementParser extends ExpressionParser {
);
return;
} else if (this.isClassProperty()) {
const prop: N.ClassProperty = (member: any);

// a property named 'static'
prop.computed = false;
prop.key = key;
Expand All @@ -964,16 +963,15 @@ export default class StatementParser extends ExpressionParser {
state: { hadConstructor: boolean },
isStatic: boolean,
) {
const memberAny: any = member;
const methodOrProp:
| N.ClassMethod
| N.ClassPrivateMethod
| N.ClassProperty
| N.ClassPrivateProperty = memberAny;
const method: N.ClassMethod | N.ClassPrivateMethod = memberAny;
const prop: N.ClassProperty | N.ClassPrivateProperty = memberAny;
const publicMethod: $FlowSubtype<N.ClassMethod> = member;
const privateMethod: $FlowSubtype<N.ClassPrivateMethod> = member;
const publicProp: $FlowSubtype<N.ClassMethod> = member;
const privateProp: $FlowSubtype<N.ClassPrivateMethod> = member;

methodOrProp.static = isStatic;
const method: typeof publicMethod | typeof privateMethod = publicMethod;
const publicMember: typeof publicMethod | typeof publicProp = publicMethod;

member.static = isStatic;

if (this.eat(tt.star)) {
// a generator
Expand All @@ -982,17 +980,17 @@ export default class StatementParser extends ExpressionParser {

if (method.key.type === "PrivateName") {
// Private generator method
this.pushClassPrivateMethod(classBody, method, true, false);
this.pushClassPrivateMethod(classBody, privateMethod, true, false);
return;
}

if (this.isNonstaticConstructor(method)) {
this.raise(method.key.start, "Constructor can't be a generator");
if (this.isNonstaticConstructor(publicMethod)) {
this.raise(publicMethod.key.start, "Constructor can't be a generator");
}

this.pushClassMethod(
classBody,
method,
publicMethod,
true,
false,
/* isConstructor */ false,
Expand All @@ -1001,30 +999,30 @@ export default class StatementParser extends ExpressionParser {
return;
}

const key = this.parseClassPropertyName(methodOrProp);
const key = this.parseClassPropertyName(member);
const isPrivate = key.type === "PrivateName";
// Check the key is not a computed expression or string literal.
const isSimple = key.type === "Identifier";

this.parsePostMemberNameModifiers(methodOrProp);
this.parsePostMemberNameModifiers(publicMember);

if (this.isClassMethod()) {
method.kind = "method";

if (isPrivate) {
this.pushClassPrivateMethod(classBody, method, false, false);
this.pushClassPrivateMethod(classBody, privateMethod, false, false);
return;
}

// a normal method
const isConstructor = this.isNonstaticConstructor(method);
const isConstructor = this.isNonstaticConstructor(publicMethod);

if (isConstructor) {
method.kind = "constructor";
publicMethod.kind = "constructor";

if (method.decorators) {
if (publicMethod.decorators) {
this.raise(
method.start,
publicMethod.start,
"You can't attach decorators to a class constructor",
);
}
Expand All @@ -1036,12 +1034,18 @@ export default class StatementParser extends ExpressionParser {
state.hadConstructor = true;
}

this.pushClassMethod(classBody, method, false, false, isConstructor);
this.pushClassMethod(
classBody,
publicMethod,
false,
false,
isConstructor,
);
} else if (this.isClassProperty()) {
if (isPrivate) {
this.pushClassPrivateProperty(classBody, prop);
this.pushClassPrivateProperty(classBody, privateProp);
} else {
this.pushClassProperty(classBody, prop);
this.pushClassProperty(classBody, publicProp);
}
} else if (isSimple && key.name === "async" && !this.isLineTerminator()) {
// an async method
Expand All @@ -1057,18 +1061,23 @@ export default class StatementParser extends ExpressionParser {

if (method.key.type === "PrivateName") {
// private async method
this.pushClassPrivateMethod(classBody, method, isGenerator, true);
this.pushClassPrivateMethod(
classBody,
privateMethod,
isGenerator,
true,
);
} else {
if (this.isNonstaticConstructor(method)) {
if (this.isNonstaticConstructor(publicMethod)) {
this.raise(
method.key.start,
publicMethod.key.start,
"Constructor can't be an async function",
);
}

this.pushClassMethod(
classBody,
method,
publicMethod,
isGenerator,
true,
/* isConstructor */ false,
Expand All @@ -1083,53 +1092,48 @@ export default class StatementParser extends ExpressionParser {
// a getter or setter
method.kind = key.name;
// The so-called parsed name would have been "get/set": get the real name.
this.parseClassPropertyName(method);
this.parseClassPropertyName(publicMethod);

if (method.key.type === "PrivateName") {
// private getter/setter
this.pushClassPrivateMethod(classBody, method, false, false);
this.pushClassPrivateMethod(classBody, privateMethod, false, false);
} else {
if (this.isNonstaticConstructor(method)) {
if (this.isNonstaticConstructor(publicMethod)) {
this.raise(
method.key.start,
publicMethod.key.start,
"Constructor can't have get/set modifier",
);
}
this.pushClassMethod(
classBody,
method,
publicMethod,
false,
false,
/* isConstructor */ false,
);
}

this.checkGetterSetterParamCount(method);
this.checkGetterSetterParamCount(publicMethod);
} else if (this.isLineTerminator()) {
// an uninitialized class property (due to ASI, since we don't otherwise recognize the next token)
if (isPrivate) {
this.pushClassPrivateProperty(classBody, prop);
this.pushClassPrivateProperty(classBody, privateProp);
} else {
this.pushClassProperty(classBody, prop);
this.pushClassProperty(classBody, publicProp);
}
} else {
this.unexpected();
}
}

parseClassPropertyName(
methodOrProp:
| N.ClassMethod
| N.ClassProperty
| N.ClassPrivateProperty
| N.ClassPrivateMethod,
): N.Expression | N.Identifier {
const key = this.parsePropertyName(methodOrProp);
parseClassPropertyName(member: N.ClassMember): N.Expression | N.Identifier {
const key = this.parsePropertyName(member);

if (
!methodOrProp.computed &&
methodOrProp.static &&
(key.name === "prototype" || key.value === "prototype")
!member.computed &&
member.static &&
((key: $FlowSubtype<N.Identifier>).name === "prototype" ||
(key: $FlowSubtype<N.StringLiteral>).value === "prototype")
) {
this.raise(
key.start,
Expand Down Expand Up @@ -1158,7 +1162,10 @@ export default class StatementParser extends ExpressionParser {
classBody.body.push(this.parseClassProperty(prop));
}

pushClassPrivateProperty(classBody: N.ClassBody, prop: N.ClassProperty) {
pushClassPrivateProperty(
classBody: N.ClassBody,
prop: N.ClassPrivateProperty,
) {
this.expectPlugin("classPrivateProperties", prop.key.start);
classBody.body.push(this.parseClassPrivateProperty(prop));
}
Expand All @@ -1183,7 +1190,7 @@ export default class StatementParser extends ExpressionParser {

pushClassPrivateMethod(
classBody: N.ClassBody,
method: N.ClassMethod,
method: N.ClassPrivateMethod,
isGenerator: boolean,
isAsync: boolean,
): void {
Expand Down
20 changes: 10 additions & 10 deletions src/plugins/flow.js
Original file line number Diff line number Diff line change
Expand Up @@ -1699,10 +1699,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
isAsync: boolean,
isConstructor: boolean,
): void {
if (method.variance) {
this.unexpected(method.variance.start);
if ((method: $FlowFixMe).variance) {
this.unexpected((method: $FlowFixMe).variance.start);
}
delete method.variance;
delete (method: $FlowFixMe).variance;
if (this.isRelational("<")) {
method.typeParameters = this.flowParseTypeParameterDeclaration();
}
Expand All @@ -1722,10 +1722,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
isGenerator: boolean,
isAsync: boolean,
): void {
if (method.variance) {
this.unexpected(method.variance.start);
if ((method: $FlowFixMe).variance) {
this.unexpected((method: $FlowFixMe).variance.start);
}
delete method.variance;
delete (method: $FlowFixMe).variance;
if (this.isRelational("<")) {
method.typeParameters = this.flowParseTypeParameterDeclaration();
}
Expand Down Expand Up @@ -1756,7 +1756,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}

parsePropertyName(
node: N.ObjectOrClassMember | N.TsNamedTypeElementBase,
node: N.ObjectOrClassMember | N.ClassMember | N.TsNamedTypeElementBase,
): N.Identifier {
const variance = this.flowParseVariance();
const key = super.parsePropertyName(node);
Expand All @@ -1775,10 +1775,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
isPattern: boolean,
refShorthandDefaultPos: ?Pos,
): void {
if (prop.variance) {
this.unexpected(prop.variance.start);
if ((prop: $FlowFixMe).variance) {
this.unexpected((prop: $FlowFixMe).variance.start);
}
delete prop.variance;
delete (prop: $FlowFixMe).variance;

let typeParameters;

Expand Down
12 changes: 7 additions & 5 deletions src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ export type ClassBase = HasDecorators & {

export type ClassBody = NodeBase & {
type: "ClassBody",
body: Array<ClassMember>, // TODO: $ReadOnlyArray
body: Array<ClassMember | TsIndexSignature>, // TODO: $ReadOnlyArray
};

export type ClassMemberBase = NodeBase &
Expand All @@ -638,8 +638,7 @@ export type ClassMember =
| ClassMethod
| ClassPrivateMethod
| ClassProperty
| ClassPrivateProperty
| TsIndexSignature;
| ClassPrivateProperty;

export type MethodLike =
| ObjectMethod
Expand All @@ -655,7 +654,6 @@ export type MethodBase = FunctionBase & {
export type MethodKind = "constructor" | "method" | "get" | "set";

export type ClassMethodOrDeclareMethodCommon = ClassMemberBase & {
type: "ClassMethod",
key: Expression,
kind: MethodKind,
static: boolean,
Expand All @@ -664,13 +662,16 @@ export type ClassMethodOrDeclareMethodCommon = ClassMemberBase & {

export type ClassMethod = MethodBase &
ClassMethodOrDeclareMethodCommon & {
type: "ClassMethod",
variance?: ?FlowVariance, // TODO: Not in spec
};

export type ClassPrivateMethod = NodeBase &
ClassMethodOrDeclareMethodCommon & {
ClassMethodOrDeclareMethodCommon &
MethodBase & {
type: "ClassPrivateMethod",
key: PrivateName,
computed: false,
};

export type ClassProperty = ClassMemberBase & {
Expand All @@ -690,6 +691,7 @@ export type ClassPrivateProperty = NodeBase & {
key: PrivateName,
value: ?Expression, // TODO: Not in spec that this is nullable.
static: boolean,
computed: false,
};

export type OptClassDeclaration = ClassBase &
Expand Down

0 comments on commit 664ff37

Please sign in to comment.