Skip to content

[breaking] Make Identifier an "atomic" node #9545

@nicolo-ribaudo

Description

@nicolo-ribaudo

Identifiers can have different properties totally unrelated to their "Identifierness":

  • optional (e.g. in function f(a?) {} with Flow)
  • typeAnnotation (e.g. in var a: string; with Flow/TypeScript)
  • decorators (e.g. in function 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 to prop in obj.prop? Or optional to label in break label;?

I propose creating a new node, AnnotatedPattern (name suggestions are welcome), like this:

defineType("AnnotatedPattern", {
  builder: ["pattern", "typeAnnotation", "optional", "decorators"],
  visitor: ["pattern", "typeAnnotation", "decorators"],
  aliases: ["PatternLike", "LVal"],
  fields: {
    pattern: {
      validate: assertNodeType("PatternLike"),
    },
    typeAnnotation: {
      validate: assertNodeType("TypeAnnotation", "TSTypeAnnotation"),
      optional: true,
    },
    optional: {
      validate: assertValueType("boolean"), // Only valid if pattern is an identifier
      optional: true,
    },
    decorators: {
      validate: chain(
        assertValueType("array"),
        assertEach(assertNodeType("Decorator")),
      ),
      optional: true,
    },
  },
});

AnnotatedPattern would be accepted in function parameters and in variable declarations. typeAnnotation & co would then be removed from destructuring patterns.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions