Skip to content

Refactor: Create a matcher utility to facilitate rule creation #26

Open
@thiagomini

Description

@thiagomini

Description

Manipulating and querying ASTs is inherently a complex problem. Often, we need to perform consecutive checks for children's properties, including their type and value. This leads to repetitive, not-so-readable code. Here's an example of such code:

if (ASTUtils.isVariableDeclarator(parent)) {
    const init = parent.init;
    let type: ProviderType | undefined;
    if (init?.type === AST_NODE_TYPES.ObjectExpression) {
      const properties = init.properties;
      for (const property of properties) {
        if (property.type === AST_NODE_TYPES.Property) {
          type = providerTypeOfProperty(property);
        }
      }
    }

    return type;
  }

And here's how this could be replaced with TS-Pattern

  return match(node)
    .with(
      {
        parent: {
          init: {
            type: AST_NODE_TYPES.ObjectExpression,
            properties: P.select(),
          },
          type: P.when(ASTUtils.isVariableDeclarator),
        },
      },
      (properties) => {
        for (const property of properties) {
          if (property.type === AST_NODE_TYPES.Property) {
            const type = providerTypeOfProperty(property);
            if (type) {
              return type;
            }
          }
        }
      }
    )
    .otherwise(() => undefined);

This second approach is more declarative and makes it easier to grasp the expected node structure. Moreover, we can select parts of the matched node with the P.select() function and make use of it in the following callback function.

Acceptance Criteria

Initially, it would suffice to implement a match(node) function that accepts two additional methods:

with(structure, callback | value) - matches with given object structure, and returns either the value or the callback's returned value
when(function, callback | value) - matches with the given matching function, and returns either the value or the callback's returned value

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions