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

Property variance type annotations for Flow plugin #161

Merged
merged 4 commits into from
Oct 14, 2016

Conversation

samwgoldman
Copy link
Contributor

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).

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`).
samwgoldman added a commit to samwgoldman/babel that referenced this pull request Oct 8, 2016
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.
@samwgoldman
Copy link
Contributor Author

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?

Copy link
Member

@danez danez left a 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);
Copy link
Member

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.

Copy link
Contributor Author

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;

Copy link
Contributor Author

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.

Copy link
Member

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;
Copy link
Member

@danez danez Oct 8, 2016

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.

Copy link
Contributor Author

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

@samwgoldman
Copy link
Contributor Author

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 "plus" | "minus" | null format that currently exists for type parameters.

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.
@codecov-io
Copy link

codecov-io commented Oct 11, 2016

Current coverage is 94.55% (diff: 97.29%)

No coverage report found for master at 2697bfd.

Powered by Codecov. Last update 2697bfd...a4c9e8f

@samwgoldman
Copy link
Contributor Author

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 delete.

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.

Copy link
Member

@danez danez left a 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);
Copy link
Member

@danez danez Oct 12, 2016

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?

Copy link
Contributor Author

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.

@danez danez merged commit 26809e8 into babel:master Oct 14, 2016
hzoo pushed a commit to babel/babel that referenced this pull request Oct 21, 2016
)

* 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
kristofdegrave pushed a commit to kristofdegrave/babylon that referenced this pull request Oct 27, 2016
* 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
panagosg7 pushed a commit to panagosg7/babel that referenced this pull request Jan 17, 2017
…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
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants