New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[breaking] Make Identifier an "atomic" node #9545
Comments
Are function params and variable declarations the only cases where we currently know there are issues? One alternative would be to move the I worry that |
That would work. I don't think that "would make the AST less polymorphic" is a good argument because it just moves the polymorphism down to the child of Also, TypeScript matches this proposal: https://astexplorer.net/#/gist/8ab88f26fe8714059fdc05d3387d5810/d97b0ed36c10c8101b6dec439cc1171624ec0b62 We also have the |
Defining a new node type represents a significant breaking change for us when compared to the base ESTree spec, which can cause us all manner of issues with existing ESLint rules expecting a certain structure. It's not an insurmountable problem, but it's definitely something to consider. I prefer the idea of hoisting the type annotation up to where it belongs, as opposed to defining a new node type. This is how typescript does it, and it seems to work well: var foo: string;
// VariableDeclaration:
// - name: Identifier
// - type: StringKeyword
var {bar}: {bar: string};
// VariableDeclaration:
// - name: ObjectBindingPattern
// - type: TypeLiteral
var [bar]: [string];
// VariableDeclaration:
// - name: ArrayBindingPattern
// - type: TupleType
function foo(
@deco arg?: number,
// Parameter:
// - name: Identifier
// - type: NumberKeyword
// - optional: true
// - decorators: [Decorator]
arg2?,
// Parameter:
// - name: Identifier
// - optional: true
) {}
@deco
class Foo {
// ClassDeclaration
// - name: Identifier
// - decorators: [Decorator]
@deco
constructor(@deco private a: string) {}
// Parameter:
// - name: Identifier
// - type: StringKeyword
// - modifiers: [PrivateKeyword]
// - decorators: [Decorator]
@deco
prop: string;
// PropertyDeclaration:
// - name: Identifier
// - type: StringKeyword
// - decorators: [Decorator]
@deco
prop?: string;
// PropertyDeclaration:
// - name: Identifier
// - type: StringKeyword
// - optional: true
// - decorators: [Decorator]
prop?;
// PropertyDeclaration:
// - name: Identifier
// - optional: true
}
interface Foo {
prop: string;
// PropertySignature:
// name: Identifier
// type: StringKeyword
prop?: string;
// PropertySignature:
// - name: Identifier
// - type: StringKeyword
// - optional: true
} |
Our AST is not compatible with ESTree already. We have a separate parser mode that we use when parsing for ESLint and that can always keep the existing behavior.
The issue at the moment is that, for function params, there is no place to hoist to, we only have |
Note that, when the parser plugin |
I was experimenting with this plugin and found a problem with flow:
where do you suggest to store the type annotation in this case? |
what in the sam hill is that syntax?!? It looks like flow completely ignores the type that's provided there: const [a: number, b: string, c: boolean] = ['a', true, 1];
a.toLocaleLowerCase(); // a === string
b - 1 // b === boolean
c.toFixed(); // c === number
const arr: string[] = [];
const [d: number] = arr;
d.toLocaleLowerCase(); I think that's probably some legacy syntax or something that the parser allows "just because"? |
Quoting response from someone on the flow team:
Adding a bit more after some discussion: They're going to discuss this internally and figure out what they want to do. So right now - consider it "valid syntax", as it could either turn into an error, or supported as valid type information. If they go down the latter route, they don't want to make it an error only to make it valid not long after, for obvious reasons. |
@bradzacher thanks for investigating! |
I was thinking again about this in the context of #14694. Either having a new node as I proposed in the original issue, or something like #9545 (comment), would have probably prevented that problem from happening. |
Now it is no longer a valid syntax and is reported as an error in flow.js (from v0.176.0 to the latest). |
Identifier
s can have different properties totally unrelated to their "Identifierness":optional
(e.g. infunction f(a?) {}
with Flow)typeAnnotation
(e.g. invar a: string;
with Flow/TypeScript)decorators
(e.g. infunction f(@dec a) {}
with TypeScript)Every other "atom" (e.g. strings, numbers, ...) don't have child nodes. Additionally, it makes it impossible to get the actual identifier name start/end position, because in
foo: string
foo
isn't represented by anything. Example: AST Explorer.Also, these properties don't make sense in many places: what does it mean if I add
typeAnnotation
toprop
inobj.prop
? Oroptional
tolabel
inbreak label;
?I propose creating a new node,
AnnotatedPattern
(name suggestions are welcome), like this:AnnotatedPattern
would be accepted in function parameters and in variable declarations.typeAnnotation
& co would then be removed from destructuring patterns.The text was updated successfully, but these errors were encountered: