ast-grep

How to match router objects with a specific key attribute


example:I want to match all router leaf nodes that do not contain children.

I tried these methods, but they didn't work. Why?

rule:
  kind: object
  all:
    - kind: property_identifier
      regex: ^path$
    - kind: property_identifier
      regex: ^name$
    - kind: property_identifier
      regex: ^component$
  not:
    kind: property_identifier
    regex: ^children$

this is playground demo: rule of playground

I expect to match the following data:

routes = [
  {
    path: '/home',
    name: 'home',
    component: HomeComponent,
  },
  // is detail leaf nodes
  {
    path: '/detail-a',
    name: 'DetailA',
    component: () => import('./DetailA'),
    meta: {},
  },
  {
    path: '/detail-b',
    name: 'DetailB',
    component: () => import('./DetailB'),
  },
  // is order leaf nodes
  {
    path: '/order-a',
    name: 'OrderA',
    component: () => import('./OrderA'),
    meta: {},
  },
  {
    path: '/order-b',
    name: 'OrderB',
    component: () => import('./OrderA'),
    meta: {},
  },
]

Solution

  • Thanks for using ast-grep.

    The problem of your rule is not using has and misunderstanding of all.

    Let's break it down. First

    rule:
      kind: object
      all:
      - kind: property_identifier
        regex: ^path$
    

    Will never match anything. According to the doc of rule object,

    A node will match a rule if and only if it satisfies all fields in the rule object.

    Thus an AST node can not be both object and property_identifier

    Instead, has can be used to match an object that has a specific property_identifier.

    rule:
      kind: object
      all:
      - has:
          kind: property_identifier
          regex: ^path$
          stopBy: end
    

    Note you also need to add more property_identifier constraints to the rule. A rule like has: { all: [...]} will not work. This is because an AST node cannot has a child or a descendant that satisfies all conditions.

    Instead, it should match an object matching all the conditions that has children of certain kinds.

    Finally, the rule can be used with not to exclude children field.

    rule:
      kind: object
      all:
      - has:
          kind: property_identifier
          regex: ^path$
          stopBy: end
      - has:
          kind: property_identifier
          regex: ^name$
          stopBy: end
      - has:
          kind: property_identifier
          regex: ^component$
          stopBy: end
      not:
        has: 
          kind: property_identifier
          regex: ^children$
          stopBy: end
    

    The final playground for the rule.