-
-
Notifications
You must be signed in to change notification settings - Fork 258
Property variance type annotations for Flow plugin #161
Conversation
Non-method properties and indexers of object types, declare class, and interfaces can be "positive" or "negative." Class fields, but again not methods, can also have variance. This PR generalizes the variance annotations for type parameters into a new node type, and reuses that node for those properties. The code for object types is reused for interfaces and declare classes. The changes there are straightfoward. The code for class fields is reused for object literals, which do not support variance annotations (currently). This code is a bit sketchy, because we always parse variance annotations in the `parsePropertyName` extension, then error in a the subsequent parse phase for object literals (`parseObjPropValue`) or class methods (`parseClassMethod`).
babel/babylon#161 adds parsing support for property variance annotations. This PR adds the necessary node type for the new Variance node and generate support for all the positions where variance can now appear.
Tests fail due to missing babel support, which is added in the referenced PR to Babel. Is it possible to bump these versions in lock step, or do I need to break up this change into multiple steps? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, just two minor nitpicks
} else if (this.state.value === "-") { | ||
variance.kind = "minus"; | ||
} | ||
this.eat(tt.plusMin); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could simplify that here and do this.eat(tt.plusMin)
already in the if ()
and remove this line then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That actually slightly changes the behavior here, because calling eat
in the conditional expression advances the parser, so when I call startNode
the start position is off by one.
I could also write this, but I think don't think it's clearly better:
let variance = this.startNode();
if (this.eat(tt.plusMin)) {
// ...
} else {
variance = null;
}
return variance;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will change the eat(plusMin)
to next()
, which will hopefully clarify the intent better. The tests do exercise the node positioning, so regression is unlikely here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I see, sorry.
@@ -380,6 +379,10 @@ pp.flowParseObjectType = function (allowStatic, allowExact) { | |||
} | |||
if (this.isRelational("<") || this.match(tt.parenL)) { | |||
// This is a method property | |||
if (variance) { | |||
this.unexpected(variance.start); | |||
variance = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't makes sense as this.unexpected()
throws anyway. Maybe we want to assignment after the diff, although not sure if necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! These two assignments are totally bogus :P
Heads up, I'm going to change this to roll back the addition of a new variance node. Instead, I will continue to use the |
Adding a new node type, specifically changing the TypeParameter node's variance property to be node-valued, is a breaking change. We might choose to make this breaking change in a later version.
Current coverage is 94.55% (diff: 97.29%)
|
OK, I removed the new node type, so this is no longer a breaking change. In order to preserve the existing error messages, I needed to pass around the position of the variance annotation out-of-band, which is a bit hacky, because we need to be careful to clean up after ourselves with In the future, when Babel approaches a major version and we can make the breaking change, I'd like to go back to having a separate node type for variance annotations. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One minor thing I'm unsure but else looks good now. After we merge this, I can create a new PR with the breaking change for the next major bump.
@@ -1052,9 +1055,10 @@ export default function (instance) { | |||
instance.extend("parseObjPropValue", function (inner) { | |||
return function (prop) { | |||
if (prop.variance) { | |||
this.unexpected(prop.variance.start); | |||
this.unexpected(prop.start); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be prop.variancePos
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Yup. In this case they are one-in-the-same, but this should definitely be variancePos
for clarity. We wouldn't need variancePos
except for static properties on classes, which share the same AST building code.
) * Add variance node type and generate property variance annotations babel/babylon#161 adds parsing support for property variance annotations. This PR adds the necessary node type for the new Variance node and generate support for all the positions where variance can now appear. * Variance is no longer a separate node type This diff also adds tests to class properties and to the flow-strip-types transform. * Add test + fix for edge case with variance and class proeprties
* Property variance type annotations for Flow plugin Non-method properties and indexers of object types, declare class, and interfaces can be "positive" or "negative." Class fields, but again not methods, can also have variance. This PR generalizes the variance annotations for type parameters into a new node type, and reuses that node for those properties. The code for object types is reused for interfaces and declare classes. The changes there are straightfoward. The code for class fields is reused for object literals, which do not support variance annotations (currently). This code is a bit sketchy, because we always parse variance annotations in the `parsePropertyName` extension, then error in a the subsequent parse phase for object literals (`parseObjPropValue`) or class methods (`parseClassMethod`). * Remove bogus unreachable code, clarify variance parsing conditional * Don't use a new node type for variance annotations Adding a new node type, specifically changing the TypeParameter node's variance property to be node-valued, is a breaking change. We might choose to make this breaking change in a later version. * s/start/variancePos
…bel#4697) * Add variance node type and generate property variance annotations babel/babylon#161 adds parsing support for property variance annotations. This PR adds the necessary node type for the new Variance node and generate support for all the positions where variance can now appear. * Variance is no longer a separate node type This diff also adds tests to class properties and to the flow-strip-types transform. * Add test + fix for edge case with variance and class proeprties
Non-method properties and indexers of object types, declare class, and
interfaces can be "positive" or "negative." Class fields, but again not
methods, can also have variance.
This PR generalizes the variance annotations for type parameters into a
new node type, and reuses that node for those properties.
The code for object types is reused for interfaces and declare classes.
The changes there are straightfoward.
The code for class fields is reused for object literals, which do not
support variance annotations (currently). This code is a bit sketchy,
because we always parse variance annotations in the
parsePropertyName
extension, then error in a the subsequent parse phase for object
literals (
parseObjPropValue
) or class methods (parseClassMethod
).