Skip to content

⬅️ Back to Table of Contents

📄 naming-convention

📊 Analysis Summary

Metric Count
🔧 Functions 31
📦 Imports 15
📊 Variables & Constants 1
📑 Type Aliases 2

📚 Table of Contents

🛠️ File Location:

📂 packages/eslint-plugin/src/rules/naming-convention.ts

📤 Default Export

export default createRule<Options, MessageIds>({ ... })
Property Value
name 'naming-convention'
meta.type 'suggestion'
meta.docs.description 'Enforce naming conventions for everything across a codebase'
meta.docs.frozen true
meta.docs.requiresTypeChecking true
meta.messages.doesNotMatchFormat '{{type}} name {{name}} must match one of the following formats: {{formats}}'
meta.messages.doesNotMatchFormatTrimmed '{{type}} name {{name}} trimmed as {{processedName}} must match one of the following formats: {{formats}}'
meta.messages.missingAffix '{{type}} name {{name}} must have one of the following {{position}}es: {{affixes}}'
meta.messages.missingUnderscore '{{type}} name {{name}} must have {{count}} {{position}} underscore(s).'
meta.messages.satisfyCustom '{{type}} name {{name}} must {{regexMatch}} the RegExp: {{regex}}'
meta.messages.unexpectedUnderscore '{{type}} name {{name}} must not have a {{position}} underscore.'
meta.schema SCHEMA
defaultOptions defaultCamelCaseAllTheThingsConfig

Entry point: create — documented under Functions.


📦 Imports

Name Source
TSESTree @typescript-eslint/utils
ScriptTarget typescript
PatternVisitor @typescript-eslint/scope-manager
AST_NODE_TYPES @typescript-eslint/utils
TSESLint @typescript-eslint/utils
Context ./naming-convention-utils
Selector ./naming-convention-utils
ValidatorFunction ./naming-convention-utils
_requiresQuoting ../util
collectVariables ../util
createRule ../util
getParserServices ../util
Modifiers ./naming-convention-utils
parseOptions ./naming-convention-utils
SCHEMA ./naming-convention-utils

Variables & Constants

Name Type Kind Value Exported
defaultCamelCaseAllTheThing... Options const [ { format: ['camelCase'], leadingUnderscore: 'allow', selector: 'default', t...

Functions

create(contextWithoutDefaults: any): { [k: string]: (node: Parameters<(node: Parameters<NonNulla…

Parameters:

  • contextWithoutDefaults any

Returns: { [k: string]: (node: Parameters<(node: Parameters<NonNullable<TSESLint.RuleListener[string]>>[0], validator: ValidatorFunction) => void>[0]) => void; }

Calls:

  • Object.setPrototypeOf
  • parseOptions (from ./naming-convention-utils)
  • getParserServices(context, true).program?.getCompilerOptions
  • requiresQuoting
  • modifiers.add
  • validator
  • collectVariables (from ../util)
  • scope.set.get
  • unusedVariables.has
  • Boolean
  • context.sourceCode.getScope
  • isGlobal
  • isExported
  • isUnused
  • getIdentifiersFromPattern
  • baseModifiers.add
  • identifiers.forEach
  • isDestructured
  • isAsyncVariableIdentifier
  • getMemberModifiers
  • handleMember
  • [ ':matches(PropertyDefinition, TSAbstractPropertyDefinition)[computed = false][value.type = "ArrowFunctionExpression"]', ':matches(PropertyDefinition, TSAbstractPropertyDefinition)[computed = false][value.type = "FunctionExpression"]', ':matches(PropertyDefinition, TSAbstractPropertyDefinition)[computed = false][value.type = "TSEmptyBodyFunctionExpression"]', ':matches(MethodDefinition, TSAbstractMethodDefinition)[computed = false][kind = "method"]', ].join
  • isAsyncMemberOrProperty
  • [ 'MethodDefinition[computed = false]:matches([kind = "get"], [kind = "set"])', 'TSAbstractMethodDefinition[computed = false]:matches([kind="get"], [kind="set"])', ].join
  • [ 'Property[computed = false][kind = "init"][value.type = "ArrowFunctionExpression"]', 'Property[computed = false][kind = "init"][value.type = "FunctionExpression"]', 'Property[computed = false][kind = "init"][value.type = "TSEmptyBodyFunctionExpression"]', ].join
  • [ 'TSMethodSignature[computed = false]', 'TSPropertySignature[computed = false][typeAnnotation.typeAnnotation.type = "TSFunctionType"]', ].join
  • [ AST_NODE_TYPES.AccessorProperty, AST_NODE_TYPES.TSAbstractAccessorProperty, ].join
  • node.params.forEach
  • Object.fromEntries
  • Object.entries(selectors).map
  • handler

Internal Comments:

// `const { x }` (x2)
// does not match `const { x: y }` (x2)
// `const { x = 2 }`
// does not match const `{ x: y = 2 }`
// #region import (x2)
// functions create their own nested scope (x2)
// #endregion (x4)
// #region variable (x2)
// Handle `import { default as Foo }`
// #region function (x2)
// #endregion function (x2)
// #region parameter (x2)
// #endregion parameter (x2)
// #region parameterProperty (x2)
// #endregion parameterProperty (x2)
// #region property (x2)
// #endregion property (x2)
// #region method (x2)
// #endregion method (x2)
// #region accessor (x2)
// #endregion accessor (x2)
// #region autoAccessor (x2)
// #endregion autoAccessor (x2)
// #region enumMember (x2)
// computed is optional, so can't do [computed = false] (x2)
// classes create their own nested scope (x2)
// #endregion enumMember (x2)
// #region class (x2)
// enums create their own nested scope (x2)
// #endregion class (x2)
// #region interface (x2)
// #endregion interface (x2)
// #region typeAlias (x2)
// #endregion typeAlias (x2)
// #region enum (x2)
// #endregion enum (x2)
// #region typeParameter (x2)

Code
create(contextWithoutDefaults) {
    const context =
      contextWithoutDefaults.options.length > 0
        ? contextWithoutDefaults
        : // only apply the defaults when the user provides no config
          (Object.setPrototypeOf(
            {
              options: defaultCamelCaseAllTheThingsConfig,
            },
            contextWithoutDefaults,
          ) as Context);

    const validators = parseOptions(context);

    const compilerOptions =
      getParserServices(context, true).program?.getCompilerOptions() ?? {};
    function handleMember(
      validator: ValidatorFunction,
      node:
        | TSESTree.AccessorPropertyNonComputedName
        | TSESTree.MethodDefinitionNonComputedName
        | TSESTree.PropertyDefinitionNonComputedName
        | TSESTree.PropertyNonComputedName
        | TSESTree.TSAbstractMethodDefinitionNonComputedName
        | TSESTree.TSAbstractPropertyDefinitionNonComputedName
        | TSESTree.TSMethodSignatureNonComputedName
        | TSESTree.TSPropertySignatureNonComputedName,
      modifiers: Set<Modifiers>,
    ): void {
      const key = node.key;
      if (requiresQuoting(key, compilerOptions.target)) {
        modifiers.add(Modifiers.requiresQuotes);
      }

      validator(key, modifiers);
    }

    function getMemberModifiers(
      node:
        | TSESTree.AccessorProperty
        | TSESTree.MethodDefinition
        | TSESTree.PropertyDefinition
        | TSESTree.TSAbstractAccessorProperty
        | TSESTree.TSAbstractMethodDefinition
        | TSESTree.TSAbstractPropertyDefinition
        | TSESTree.TSParameterProperty,
    ): Set<Modifiers> {
      const modifiers = new Set<Modifiers>();
      if ('key' in node && node.key.type === AST_NODE_TYPES.PrivateIdentifier) {
        modifiers.add(Modifiers['#private']);
      } else if (node.accessibility) {
        modifiers.add(Modifiers[node.accessibility]);
      } else {
        modifiers.add(Modifiers.public);
      }
      if (node.static) {
        modifiers.add(Modifiers.static);
      }
      if ('readonly' in node && node.readonly) {
        modifiers.add(Modifiers.readonly);
      }
      if ('override' in node && node.override) {
        modifiers.add(Modifiers.override);
      }
      if (
        node.type === AST_NODE_TYPES.TSAbstractPropertyDefinition ||
        node.type === AST_NODE_TYPES.TSAbstractMethodDefinition ||
        node.type === AST_NODE_TYPES.TSAbstractAccessorProperty
      ) {
        modifiers.add(Modifiers.abstract);
      }

      return modifiers;
    }

    const { unusedVariables } = collectVariables(context);
    function isUnused(
      name: string,
      initialScope: TSESLint.Scope.Scope | null,
    ): boolean {
      let variable: TSESLint.Scope.Variable | null = null;
      let scope: TSESLint.Scope.Scope | null = initialScope;
      while (scope) {
        variable = scope.set.get(name) ?? null;
        if (variable) {
          break;
        }
        scope = scope.upper;
      }
      if (!variable) {
        return false;
      }

      return unusedVariables.has(variable);
    }

    function isDestructured(id: TSESTree.Identifier): boolean {
      return (
        // `const { x }`
        // does not match `const { x: y }`
        (id.parent.type === AST_NODE_TYPES.Property && id.parent.shorthand) ||
        // `const { x = 2 }`
        // does not match const `{ x: y = 2 }`
        (id.parent.type === AST_NODE_TYPES.AssignmentPattern &&
          id.parent.parent.type === AST_NODE_TYPES.Property &&
          id.parent.parent.shorthand)
      );
    }

    function isAsyncMemberOrProperty(
      propertyOrMemberNode:
        | TSESTree.MethodDefinitionNonComputedName
        | TSESTree.PropertyDefinitionNonComputedName
        | TSESTree.PropertyNonComputedName
        | TSESTree.TSAbstractMethodDefinitionNonComputedName
        | TSESTree.TSAbstractPropertyDefinitionNonComputedName
        | TSESTree.TSMethodSignatureNonComputedName,
    ): boolean {
      return Boolean(
        'value' in propertyOrMemberNode &&
        propertyOrMemberNode.value &&
        'async' in propertyOrMemberNode.value &&
        propertyOrMemberNode.value.async,
      );
    }

    function isAsyncVariableIdentifier(id: TSESTree.Identifier): boolean {
      return Boolean(
        ('async' in id.parent && id.parent.async) ||
        ('init' in id.parent &&
          id.parent.init &&
          'async' in id.parent.init &&
          id.parent.init.async),
      );
    }

    const selectors: {
      readonly [k in keyof TSESLint.RuleListener]: Readonly<{
        handler: (
          node: Parameters<NonNullable<TSESLint.RuleListener[k]>>[0],
          validator: ValidatorFunction,
        ) => void;
        validator: ValidatorFunction;
      }>;
    } = {
      // #region import

      'FunctionDeclaration, TSDeclareFunction, FunctionExpression': {
        handler: (
          node:
            | TSESTree.FunctionDeclaration
            | TSESTree.FunctionExpression
            | TSESTree.TSDeclareFunction,
          validator,
        ): void => {
          if (node.id == null) {
            return;
          }

          const modifiers = new Set<Modifiers>();
          // functions create their own nested scope
          const scope = context.sourceCode.getScope(node).upper;

          if (isGlobal(scope)) {
            modifiers.add(Modifiers.global);
          }

          if (isExported(node, node.id.name, scope)) {
            modifiers.add(Modifiers.exported);
          }

          if (isUnused(node.id.name, scope)) {
            modifiers.add(Modifiers.unused);
          }

          if (node.async) {
            modifiers.add(Modifiers.async);
          }

          validator(node.id, modifiers);
        },
        validator: validators.function,
      },

      // #endregion

      // #region variable

      'ImportDefaultSpecifier, ImportNamespaceSpecifier, ImportSpecifier': {
        handler: (
          node:
            | TSESTree.ImportDefaultSpecifier
            | TSESTree.ImportNamespaceSpecifier
            | TSESTree.ImportSpecifier,
          validator,
        ): void => {
          const modifiers = new Set<Modifiers>();

          switch (node.type) {
            case AST_NODE_TYPES.ImportDefaultSpecifier:
              modifiers.add(Modifiers.default);
              break;
            case AST_NODE_TYPES.ImportNamespaceSpecifier:
              modifiers.add(Modifiers.namespace);
              break;
            case AST_NODE_TYPES.ImportSpecifier:
              // Handle `import { default as Foo }`
              if (
                node.imported.type === AST_NODE_TYPES.Identifier &&
                node.imported.name !== 'default'
              ) {
                return;
              }
              modifiers.add(Modifiers.default);
              break;
          }

          validator(node.local, modifiers);
        },
        validator: validators.import,
      },

      // #endregion

      // #region function

      VariableDeclarator: {
        handler: (node, validator): void => {
          const identifiers = getIdentifiersFromPattern(node.id);

          const baseModifiers = new Set<Modifiers>();
          const parent = node.parent;
          if (parent.kind === 'const') {
            baseModifiers.add(Modifiers.const);
          }

          if (isGlobal(context.sourceCode.getScope(node))) {
            baseModifiers.add(Modifiers.global);
          }

          identifiers.forEach(id => {
            const modifiers = new Set(baseModifiers);

            if (isDestructured(id)) {
              modifiers.add(Modifiers.destructured);
            }

            const scope = context.sourceCode.getScope(id);
            if (isExported(parent, id.name, scope)) {
              modifiers.add(Modifiers.exported);
            }

            if (isUnused(id.name, scope)) {
              modifiers.add(Modifiers.unused);
            }

            if (isAsyncVariableIdentifier(id)) {
              modifiers.add(Modifiers.async);
            }

            validator(id, modifiers);
          });
        },
        validator: validators.variable,
      },

      // #endregion function

      // #region parameter
      ':matches(PropertyDefinition, TSAbstractPropertyDefinition)[computed = false][value.type != "ArrowFunctionExpression"][value.type != "FunctionExpression"][value.type != "TSEmptyBodyFunctionExpression"]':
        {
          handler: (
            node:
              | TSESTree.PropertyDefinitionNonComputedName
              | TSESTree.TSAbstractPropertyDefinitionNonComputedName,
            validator,
          ): void => {
            const modifiers = getMemberModifiers(node);
            handleMember(validator, node, modifiers);
          },
          validator: validators.classProperty,
        },

      // #endregion parameter

      // #region parameterProperty

      ':not(ObjectPattern) > Property[computed = false][kind = "init"][value.type != "ArrowFunctionExpression"][value.type != "FunctionExpression"][value.type != "TSEmptyBodyFunctionExpression"]':
        {
          handler: (
            node: TSESTree.PropertyNonComputedName,
            validator,
          ): void => {
            const modifiers = new Set<Modifiers>([Modifiers.public]);
            handleMember(validator, node, modifiers);
          },
          validator: validators.objectLiteralProperty,
        },

      // #endregion parameterProperty

      // #region property

      [[
        ':matches(PropertyDefinition, TSAbstractPropertyDefinition)[computed = false][value.type = "ArrowFunctionExpression"]',
        ':matches(PropertyDefinition, TSAbstractPropertyDefinition)[computed = false][value.type = "FunctionExpression"]',
        ':matches(PropertyDefinition, TSAbstractPropertyDefinition)[computed = false][value.type = "TSEmptyBodyFunctionExpression"]',
        ':matches(MethodDefinition, TSAbstractMethodDefinition)[computed = false][kind = "method"]',
      ].join(', ')]: {
        handler: (
          node:
            | TSESTree.MethodDefinitionNonComputedName
            | TSESTree.PropertyDefinitionNonComputedName
            | TSESTree.TSAbstractMethodDefinitionNonComputedName
            | TSESTree.TSAbstractPropertyDefinitionNonComputedName,
          validator,
        ): void => {
          const modifiers = getMemberModifiers(node);

          if (isAsyncMemberOrProperty(node)) {
            modifiers.add(Modifiers.async);
          }

          handleMember(validator, node, modifiers);
        },
        validator: validators.classMethod,
      },

      [[
        'MethodDefinition[computed = false]:matches([kind = "get"], [kind = "set"])',
        'TSAbstractMethodDefinition[computed = false]:matches([kind="get"], [kind="set"])',
      ].join(', ')]: {
        handler: (
          node: TSESTree.MethodDefinitionNonComputedName,
          validator,
        ): void => {
          const modifiers = getMemberModifiers(node);
          handleMember(validator, node, modifiers);
        },
        validator: validators.classicAccessor,
      },

      [[
        'Property[computed = false][kind = "init"][value.type = "ArrowFunctionExpression"]',
        'Property[computed = false][kind = "init"][value.type = "FunctionExpression"]',
        'Property[computed = false][kind = "init"][value.type = "TSEmptyBodyFunctionExpression"]',
      ].join(', ')]: {
        handler: (
          node:
            | TSESTree.PropertyNonComputedName
            | TSESTree.TSMethodSignatureNonComputedName,
          validator,
        ): void => {
          const modifiers = new Set<Modifiers>([Modifiers.public]);

          if (isAsyncMemberOrProperty(node)) {
            modifiers.add(Modifiers.async);
          }

          handleMember(validator, node, modifiers);
        },
        validator: validators.objectLiteralMethod,
      },

      // #endregion property

      // #region method

      [[
        'TSMethodSignature[computed = false]',
        'TSPropertySignature[computed = false][typeAnnotation.typeAnnotation.type = "TSFunctionType"]',
      ].join(', ')]: {
        handler: (
          node:
            | TSESTree.TSMethodSignatureNonComputedName
            | TSESTree.TSPropertySignatureNonComputedName,
          validator,
        ): void => {
          const modifiers = new Set<Modifiers>([Modifiers.public]);
          handleMember(validator, node, modifiers);
        },
        validator: validators.typeMethod,
      },

      [[
        AST_NODE_TYPES.AccessorProperty,
        AST_NODE_TYPES.TSAbstractAccessorProperty,
      ].join(', ')]: {
        handler: (
          node: TSESTree.AccessorPropertyNonComputedName,
          validator,
        ): void => {
          const modifiers = getMemberModifiers(node);
          handleMember(validator, node, modifiers);
        },
        validator: validators.autoAccessor,
      },

      'FunctionDeclaration, TSDeclareFunction, TSEmptyBodyFunctionExpression, FunctionExpression, ArrowFunctionExpression':
        {
          handler: (
            node:
              | TSESTree.ArrowFunctionExpression
              | TSESTree.FunctionDeclaration
              | TSESTree.FunctionExpression
              | TSESTree.TSDeclareFunction
              | TSESTree.TSEmptyBodyFunctionExpression,
            validator,
          ): void => {
            node.params.forEach(param => {
              if (param.type === AST_NODE_TYPES.TSParameterProperty) {
                return;
              }

              const identifiers = getIdentifiersFromPattern(param);

              identifiers.forEach(i => {
                const modifiers = new Set<Modifiers>();

                if (isDestructured(i)) {
                  modifiers.add(Modifiers.destructured);
                }

                if (isUnused(i.name, context.sourceCode.getScope(i))) {
                  modifiers.add(Modifiers.unused);
                }

                validator(i, modifiers);
              });
            });
          },
          validator: validators.parameter,
        },

      // #endregion method

      // #region accessor

      'Property[computed = false]:matches([kind = "get"], [kind = "set"])': {
        handler: (node: TSESTree.PropertyNonComputedName, validator): void => {
          const modifiers = new Set<Modifiers>([Modifiers.public]);
          handleMember(validator, node, modifiers);
        },
        validator: validators.classicAccessor,
      },

      TSParameterProperty: {
        handler: (node, validator): void => {
          const modifiers = getMemberModifiers(node);

          const identifiers = getIdentifiersFromPattern(node.parameter);

          identifiers.forEach(i => {
            validator(i, modifiers);
          });
        },
        validator: validators.parameterProperty,
      },

      // #endregion accessor

      // #region autoAccessor

      'TSPropertySignature[computed = false][typeAnnotation.typeAnnotation.type != "TSFunctionType"]':
        {
          handler: (
            node: TSESTree.TSPropertySignatureNonComputedName,
            validator,
          ): void => {
            const modifiers = new Set<Modifiers>([Modifiers.public]);
            if (node.readonly) {
              modifiers.add(Modifiers.readonly);
            }

            handleMember(validator, node, modifiers);
          },
          validator: validators.typeProperty,
        },

      // #endregion autoAccessor

      // #region enumMember

      // computed is optional, so can't do [computed = false]
      'ClassDeclaration, ClassExpression': {
        handler: (
          node: TSESTree.ClassDeclaration | TSESTree.ClassExpression,
          validator,
        ): void => {
          const id = node.id;
          if (id == null) {
            return;
          }

          const modifiers = new Set<Modifiers>();
          // classes create their own nested scope
          const scope = context.sourceCode.getScope(node).upper;

          if (node.abstract) {
            modifiers.add(Modifiers.abstract);
          }

          if (isExported(node, id.name, scope)) {
            modifiers.add(Modifiers.exported);
          }

          if (isUnused(id.name, scope)) {
            modifiers.add(Modifiers.unused);
          }

          validator(id, modifiers);
        },
        validator: validators.class,
      },

      // #endregion enumMember

      // #region class

      TSEnumDeclaration: {
        handler: (node, validator): void => {
          const modifiers = new Set<Modifiers>();
          // enums create their own nested scope
          const scope = context.sourceCode.getScope(node).upper;

          if (isExported(node, node.id.name, scope)) {
            modifiers.add(Modifiers.exported);
          }

          if (isUnused(node.id.name, scope)) {
            modifiers.add(Modifiers.unused);
          }

          validator(node.id, modifiers);
        },
        validator: validators.enum,
      },

      // #endregion class

      // #region interface

      TSEnumMember: {
        handler: (node: TSESTree.TSEnumMember, validator): void => {
          const id = node.id;
          const modifiers = new Set<Modifiers>();

          if (requiresQuoting(id, compilerOptions.target)) {
            modifiers.add(Modifiers.requiresQuotes);
          }

          validator(id, modifiers);
        },
        validator: validators.enumMember,
      },

      // #endregion interface

      // #region typeAlias

      TSInterfaceDeclaration: {
        handler: (node, validator): void => {
          const modifiers = new Set<Modifiers>();
          const scope = context.sourceCode.getScope(node);

          if (isExported(node, node.id.name, scope)) {
            modifiers.add(Modifiers.exported);
          }

          if (isUnused(node.id.name, scope)) {
            modifiers.add(Modifiers.unused);
          }

          validator(node.id, modifiers);
        },
        validator: validators.interface,
      },

      // #endregion typeAlias

      // #region enum

      TSTypeAliasDeclaration: {
        handler: (node, validator): void => {
          const modifiers = new Set<Modifiers>();
          const scope = context.sourceCode.getScope(node);

          if (isExported(node, node.id.name, scope)) {
            modifiers.add(Modifiers.exported);
          }

          if (isUnused(node.id.name, scope)) {
            modifiers.add(Modifiers.unused);
          }

          validator(node.id, modifiers);
        },
        validator: validators.typeAlias,
      },

      // #endregion enum

      // #region typeParameter

      'TSTypeParameterDeclaration > TSTypeParameter': {
        handler: (node: TSESTree.TSTypeParameter, validator): void => {
          const modifiers = new Set<Modifiers>();
          const scope = context.sourceCode.getScope(node);

          if (isUnused(node.name.name, scope)) {
            modifiers.add(Modifiers.unused);
          }

          validator(node.name, modifiers);
        },
        validator: validators.typeParameter,
      },

      // #endregion typeParameter
    };

    return Object.fromEntries(
      Object.entries(selectors).map(([selector, { handler, validator }]) => {
        return [
          selector,
          (node: Parameters<typeof handler>[0]): void => {
            handler(node as never, validator);
          },
        ] as const;
      }),
    );
  }

getIdentifiersFromPattern(pattern: TSESTree.DestructuringPattern): TSESTree.Identifier[]

Parameters:

  • pattern TSESTree.DestructuringPattern

Returns: TSESTree.Identifier[]

Calls:

  • identifiers.push
  • visitor.visit
Code
function getIdentifiersFromPattern(
  pattern: TSESTree.DestructuringPattern,
): TSESTree.Identifier[] {
  const identifiers: TSESTree.Identifier[] = [];
  const visitor = new PatternVisitor({}, pattern, id => identifiers.push(id));
  visitor.visit(pattern);
  return identifiers;
}

isExported(node: TSESTree.Node | undefined, name: string, scope: TSESLint.Scope.Scope | null): boolean

Parameters:

  • node TSESTree.Node | undefined
  • name string
  • scope TSESLint.Scope.Scope | null

Returns: boolean

Calls:

  • scope.set.get
Code
function isExported(
  node: TSESTree.Node | undefined,
  name: string,
  scope: TSESLint.Scope.Scope | null,
): boolean {
  if (
    node?.parent?.type === AST_NODE_TYPES.ExportDefaultDeclaration ||
    node?.parent?.type === AST_NODE_TYPES.ExportNamedDeclaration
  ) {
    return true;
  }

  if (scope == null) {
    return false;
  }

  const variable = scope.set.get(name);
  if (variable) {
    for (const ref of variable.references) {
      const refParent = ref.identifier.parent;
      if (
        refParent.type === AST_NODE_TYPES.ExportDefaultDeclaration ||
        refParent.type === AST_NODE_TYPES.ExportSpecifier
      ) {
        return true;
      }
    }
  }

  return false;
}

isGlobal(scope: TSESLint.Scope.Scope | null): boolean

Parameters:

  • scope TSESLint.Scope.Scope | null

Returns: boolean

Code
function isGlobal(scope: TSESLint.Scope.Scope | null): boolean {
  if (scope == null) {
    return false;
  }

  return (
    scope.type === TSESLint.Scope.ScopeType.global ||
    scope.type === TSESLint.Scope.ScopeType.module
  );
}

requiresQuoting(node: TSESTree.Identifier | TSESTree.Literal …, target: ScriptTarget | undefined): boolean

Parameters:

  • node TSESTree.Identifier | TSESTree.Literal | TSESTree.PrivateIdentifier
  • target ScriptTarget | undefined

Returns: boolean

Calls:

  • _requiresQuoting (from ../util)
Code
function requiresQuoting(
  node: TSESTree.Identifier | TSESTree.Literal | TSESTree.PrivateIdentifier,
  target: ScriptTarget | undefined,
): boolean {
  const name =
    node.type === AST_NODE_TYPES.Identifier ||
    node.type === AST_NODE_TYPES.PrivateIdentifier
      ? node.name
      : `${node.value}`;
  return _requiresQuoting(name, target);
}

Internal helpers

Declared inside another function in this file.

handleMember(validator: ValidatorFunction, node: | TSESTree.AccessorPropertyNonComputedN…, modifiers: Set<Modifiers>): void

Parameters:

  • validator ValidatorFunction
  • node | TSESTree.AccessorPropertyNonComputedName | TSESTree.MethodDefinitionNonComputedName | TSESTree.PropertyDefinitionNonComputedName | TSESTree.PropertyNonComputedName | TSESTree.TSAbstractMethodDefinitionNonComputedName | TSESTree.TSAbstractPropertyDefinitionNonComputedName | TSESTree.TSMethodSignatureNonComputedName | TSESTree.TSPropertySignatureNonComputedName
  • modifiers Set<Modifiers>

Returns: void

Calls:

  • requiresQuoting
  • modifiers.add
  • validator
Code
function handleMember(
      validator: ValidatorFunction,
      node:
        | TSESTree.AccessorPropertyNonComputedName
        | TSESTree.MethodDefinitionNonComputedName
        | TSESTree.PropertyDefinitionNonComputedName
        | TSESTree.PropertyNonComputedName
        | TSESTree.TSAbstractMethodDefinitionNonComputedName
        | TSESTree.TSAbstractPropertyDefinitionNonComputedName
        | TSESTree.TSMethodSignatureNonComputedName
        | TSESTree.TSPropertySignatureNonComputedName,
      modifiers: Set<Modifiers>,
    ): void {
      const key = node.key;
      if (requiresQuoting(key, compilerOptions.target)) {
        modifiers.add(Modifiers.requiresQuotes);
      }

      validator(key, modifiers);
    }

getMemberModifiers(node: | TSESTree.AccessorProperty | TSESTree.…): Set<Modifiers>

Parameters:

  • node | TSESTree.AccessorProperty | TSESTree.MethodDefinition | TSESTree.PropertyDefinition | TSESTree.TSAbstractAccessorProperty | TSESTree.TSAbstractMethodDefinition | TSESTree.TSAbstractPropertyDefinition | TSESTree.TSParameterProperty

Returns: Set<Modifiers>

Calls:

  • modifiers.add
Code
function getMemberModifiers(
      node:
        | TSESTree.AccessorProperty
        | TSESTree.MethodDefinition
        | TSESTree.PropertyDefinition
        | TSESTree.TSAbstractAccessorProperty
        | TSESTree.TSAbstractMethodDefinition
        | TSESTree.TSAbstractPropertyDefinition
        | TSESTree.TSParameterProperty,
    ): Set<Modifiers> {
      const modifiers = new Set<Modifiers>();
      if ('key' in node && node.key.type === AST_NODE_TYPES.PrivateIdentifier) {
        modifiers.add(Modifiers['#private']);
      } else if (node.accessibility) {
        modifiers.add(Modifiers[node.accessibility]);
      } else {
        modifiers.add(Modifiers.public);
      }
      if (node.static) {
        modifiers.add(Modifiers.static);
      }
      if ('readonly' in node && node.readonly) {
        modifiers.add(Modifiers.readonly);
      }
      if ('override' in node && node.override) {
        modifiers.add(Modifiers.override);
      }
      if (
        node.type === AST_NODE_TYPES.TSAbstractPropertyDefinition ||
        node.type === AST_NODE_TYPES.TSAbstractMethodDefinition ||
        node.type === AST_NODE_TYPES.TSAbstractAccessorProperty
      ) {
        modifiers.add(Modifiers.abstract);
      }

      return modifiers;
    }

isUnused(name: string, initialScope: TSESLint.Scope.Scope | null): boolean

Parameters:

  • name string
  • initialScope TSESLint.Scope.Scope | null

Returns: boolean

Calls:

  • scope.set.get
  • unusedVariables.has
Code
function isUnused(
      name: string,
      initialScope: TSESLint.Scope.Scope | null,
    ): boolean {
      let variable: TSESLint.Scope.Variable | null = null;
      let scope: TSESLint.Scope.Scope | null = initialScope;
      while (scope) {
        variable = scope.set.get(name) ?? null;
        if (variable) {
          break;
        }
        scope = scope.upper;
      }
      if (!variable) {
        return false;
      }

      return unusedVariables.has(variable);
    }

isDestructured(id: TSESTree.Identifier): boolean

Parameters:

  • id TSESTree.Identifier

Returns: boolean

Internal Comments:

// `const { x }` (x2)
// does not match `const { x: y }` (x2)
// `const { x = 2 }`
// does not match const `{ x: y = 2 }`

Code
function isDestructured(id: TSESTree.Identifier): boolean {
      return (
        // `const { x }`
        // does not match `const { x: y }`
        (id.parent.type === AST_NODE_TYPES.Property && id.parent.shorthand) ||
        // `const { x = 2 }`
        // does not match const `{ x: y = 2 }`
        (id.parent.type === AST_NODE_TYPES.AssignmentPattern &&
          id.parent.parent.type === AST_NODE_TYPES.Property &&
          id.parent.parent.shorthand)
      );
    }

isAsyncMemberOrProperty(propertyOrMemberNode: | TSESTree.MethodDefinitionNonComputedN…): boolean

Parameters:

  • propertyOrMemberNode | TSESTree.MethodDefinitionNonComputedName | TSESTree.PropertyDefinitionNonComputedName | TSESTree.PropertyNonComputedName | TSESTree.TSAbstractMethodDefinitionNonComputedName | TSESTree.TSAbstractPropertyDefinitionNonComputedName | TSESTree.TSMethodSignatureNonComputedName

Returns: boolean

Calls:

  • Boolean
Code
function isAsyncMemberOrProperty(
      propertyOrMemberNode:
        | TSESTree.MethodDefinitionNonComputedName
        | TSESTree.PropertyDefinitionNonComputedName
        | TSESTree.PropertyNonComputedName
        | TSESTree.TSAbstractMethodDefinitionNonComputedName
        | TSESTree.TSAbstractPropertyDefinitionNonComputedName
        | TSESTree.TSMethodSignatureNonComputedName,
    ): boolean {
      return Boolean(
        'value' in propertyOrMemberNode &&
        propertyOrMemberNode.value &&
        'async' in propertyOrMemberNode.value &&
        propertyOrMemberNode.value.async,
      );
    }

isAsyncVariableIdentifier(id: TSESTree.Identifier): boolean

Parameters:

  • id TSESTree.Identifier

Returns: boolean

Calls:

  • Boolean
Code
function isAsyncVariableIdentifier(id: TSESTree.Identifier): boolean {
      return Boolean(
        ('async' in id.parent && id.parent.async) ||
        ('init' in id.parent &&
          id.parent.init &&
          'async' in id.parent.init &&
          id.parent.init.async),
      );
    }

FunctionDeclaration, TSDeclareFunction, FunctionExpression.handler(node: | TSESTree.FunctionDeclaration | TSESTr…, validator: ValidatorFunction): void

Parameters:

  • node | TSESTree.FunctionDeclaration | TSESTree.FunctionExpression | TSESTree.TSDeclareFunction
  • validator ValidatorFunction

Returns: void

Calls:

  • context.sourceCode.getScope
  • isGlobal
  • modifiers.add
  • isExported
  • isUnused
  • validator

Internal Comments:

// functions create their own nested scope (x2)

Code
(
          node:
            | TSESTree.FunctionDeclaration
            | TSESTree.FunctionExpression
            | TSESTree.TSDeclareFunction,
          validator,
        ): void => {
          if (node.id == null) {
            return;
          }

          const modifiers = new Set<Modifiers>();
          // functions create their own nested scope
          const scope = context.sourceCode.getScope(node).upper;

          if (isGlobal(scope)) {
            modifiers.add(Modifiers.global);
          }

          if (isExported(node, node.id.name, scope)) {
            modifiers.add(Modifiers.exported);
          }

          if (isUnused(node.id.name, scope)) {
            modifiers.add(Modifiers.unused);
          }

          if (node.async) {
            modifiers.add(Modifiers.async);
          }

          validator(node.id, modifiers);
        }

ImportDefaultSpecifier, ImportNamespaceSpecifier, ImportSpecifier.handler(node: | TSESTree.ImportDefaultSpecifier | TSE…, validator: ValidatorFunction): void

Parameters:

  • node | TSESTree.ImportDefaultSpecifier | TSESTree.ImportNamespaceSpecifier | TSESTree.ImportSpecifier
  • validator ValidatorFunction

Returns: void

Calls:

  • modifiers.add
  • validator

Internal Comments:

// Handle `import { default as Foo }`

Code
(
          node:
            | TSESTree.ImportDefaultSpecifier
            | TSESTree.ImportNamespaceSpecifier
            | TSESTree.ImportSpecifier,
          validator,
        ): void => {
          const modifiers = new Set<Modifiers>();

          switch (node.type) {
            case AST_NODE_TYPES.ImportDefaultSpecifier:
              modifiers.add(Modifiers.default);
              break;
            case AST_NODE_TYPES.ImportNamespaceSpecifier:
              modifiers.add(Modifiers.namespace);
              break;
            case AST_NODE_TYPES.ImportSpecifier:
              // Handle `import { default as Foo }`
              if (
                node.imported.type === AST_NODE_TYPES.Identifier &&
                node.imported.name !== 'default'
              ) {
                return;
              }
              modifiers.add(Modifiers.default);
              break;
          }

          validator(node.local, modifiers);
        }

VariableDeclarator.handler(node: any, validator: ValidatorFunction): void

Parameters:

  • node any
  • validator ValidatorFunction

Returns: void

Calls:

  • getIdentifiersFromPattern
  • baseModifiers.add
  • isGlobal
  • context.sourceCode.getScope
  • identifiers.forEach
  • isDestructured
  • modifiers.add
  • isExported
  • isUnused
  • isAsyncVariableIdentifier
  • validator
Code
(node, validator): void => {
          const identifiers = getIdentifiersFromPattern(node.id);

          const baseModifiers = new Set<Modifiers>();
          const parent = node.parent;
          if (parent.kind === 'const') {
            baseModifiers.add(Modifiers.const);
          }

          if (isGlobal(context.sourceCode.getScope(node))) {
            baseModifiers.add(Modifiers.global);
          }

          identifiers.forEach(id => {
            const modifiers = new Set(baseModifiers);

            if (isDestructured(id)) {
              modifiers.add(Modifiers.destructured);
            }

            const scope = context.sourceCode.getScope(id);
            if (isExported(parent, id.name, scope)) {
              modifiers.add(Modifiers.exported);
            }

            if (isUnused(id.name, scope)) {
              modifiers.add(Modifiers.unused);
            }

            if (isAsyncVariableIdentifier(id)) {
              modifiers.add(Modifiers.async);
            }

            validator(id, modifiers);
          });
        }

:matches(PropertyDefinition, TSAbstractPropertyDefinition)[computed = false][value.type != ArrowFunctionExpression][value.type != FunctionExpression][value.type != TSEmptyBodyFunctionExpression].handler(…): void

Parameters:

  • node | TSESTree.PropertyDefinitionNonComputedName | TSESTree.TSAbstractPropertyDefinitionNonComputedName
  • validator ValidatorFunction

Returns: void

Calls:

  • getMemberModifiers
  • handleMember
Code
(
            node:
              | TSESTree.PropertyDefinitionNonComputedName
              | TSESTree.TSAbstractPropertyDefinitionNonComputedName,
            validator,
          ): void => {
            const modifiers = getMemberModifiers(node);
            handleMember(validator, node, modifiers);
          }

:not(ObjectPattern) > Property[computed = false][kind = init][value.type != ArrowFunctionExpression][value.type != FunctionExpression][value.type != TSEmptyBodyFunctionExpression].handler(…): void

Parameters:

  • node TSESTree.PropertyNonComputedName
  • validator ValidatorFunction

Returns: void

Calls:

  • handleMember
Code
(
            node: TSESTree.PropertyNonComputedName,
            validator,
          ): void => {
            const modifiers = new Set<Modifiers>([Modifiers.public]);
            handleMember(validator, node, modifiers);
          }

selectors.handler(node: | TSESTree.MethodDefinitionNonComputedN…, validator: ValidatorFunction): void

Parameters:

  • node | TSESTree.MethodDefinitionNonComputedName | TSESTree.PropertyDefinitionNonComputedName | TSESTree.TSAbstractMethodDefinitionNonComputedName | TSESTree.TSAbstractPropertyDefinitionNonComputedName
  • validator ValidatorFunction

Returns: void

Calls:

  • getMemberModifiers
  • isAsyncMemberOrProperty
  • modifiers.add
  • handleMember
Code
(
          node:
            | TSESTree.MethodDefinitionNonComputedName
            | TSESTree.PropertyDefinitionNonComputedName
            | TSESTree.TSAbstractMethodDefinitionNonComputedName
            | TSESTree.TSAbstractPropertyDefinitionNonComputedName,
          validator,
        ): void => {
          const modifiers = getMemberModifiers(node);

          if (isAsyncMemberOrProperty(node)) {
            modifiers.add(Modifiers.async);
          }

          handleMember(validator, node, modifiers);
        }

selectors.handler(node: TSESTree.MethodDefinitionNonComputedName, validator: ValidatorFunction): void

Parameters:

  • node TSESTree.MethodDefinitionNonComputedName
  • validator ValidatorFunction

Returns: void

Calls:

  • getMemberModifiers
  • handleMember
Code
(
          node: TSESTree.MethodDefinitionNonComputedName,
          validator,
        ): void => {
          const modifiers = getMemberModifiers(node);
          handleMember(validator, node, modifiers);
        }

selectors.handler(node: | TSESTree.PropertyNonComputedName | TS…, validator: ValidatorFunction): void

Parameters:

  • node | TSESTree.PropertyNonComputedName | TSESTree.TSMethodSignatureNonComputedName
  • validator ValidatorFunction

Returns: void

Calls:

  • isAsyncMemberOrProperty
  • modifiers.add
  • handleMember
Code
(
          node:
            | TSESTree.PropertyNonComputedName
            | TSESTree.TSMethodSignatureNonComputedName,
          validator,
        ): void => {
          const modifiers = new Set<Modifiers>([Modifiers.public]);

          if (isAsyncMemberOrProperty(node)) {
            modifiers.add(Modifiers.async);
          }

          handleMember(validator, node, modifiers);
        }

selectors.handler(node: | TSESTree.TSMethodSignatureNonComputed…, validator: ValidatorFunction): void

Parameters:

  • node | TSESTree.TSMethodSignatureNonComputedName | TSESTree.TSPropertySignatureNonComputedName
  • validator ValidatorFunction

Returns: void

Calls:

  • handleMember
Code
(
          node:
            | TSESTree.TSMethodSignatureNonComputedName
            | TSESTree.TSPropertySignatureNonComputedName,
          validator,
        ): void => {
          const modifiers = new Set<Modifiers>([Modifiers.public]);
          handleMember(validator, node, modifiers);
        }

selectors.handler(node: TSESTree.AccessorPropertyNonComputedName, validator: ValidatorFunction): void

Parameters:

  • node TSESTree.AccessorPropertyNonComputedName
  • validator ValidatorFunction

Returns: void

Calls:

  • getMemberModifiers
  • handleMember
Code
(
          node: TSESTree.AccessorPropertyNonComputedName,
          validator,
        ): void => {
          const modifiers = getMemberModifiers(node);
          handleMember(validator, node, modifiers);
        }

FunctionDeclaration, TSDeclareFunction, TSEmptyBodyFunctionExpression, FunctionExpression, ArrowFunctionExpression.handler(…): void

Parameters:

  • node | TSESTree.ArrowFunctionExpression | TSESTree.FunctionDeclaration | TSESTree.FunctionExpression | TSESTree.TSDeclareFunction | TSESTree.TSEmptyBodyFunctionExpression
  • validator ValidatorFunction

Returns: void

Calls:

  • node.params.forEach
  • getIdentifiersFromPattern
  • identifiers.forEach
  • isDestructured
  • modifiers.add
  • isUnused
  • context.sourceCode.getScope
  • validator
Code
(
            node:
              | TSESTree.ArrowFunctionExpression
              | TSESTree.FunctionDeclaration
              | TSESTree.FunctionExpression
              | TSESTree.TSDeclareFunction
              | TSESTree.TSEmptyBodyFunctionExpression,
            validator,
          ): void => {
            node.params.forEach(param => {
              if (param.type === AST_NODE_TYPES.TSParameterProperty) {
                return;
              }

              const identifiers = getIdentifiersFromPattern(param);

              identifiers.forEach(i => {
                const modifiers = new Set<Modifiers>();

                if (isDestructured(i)) {
                  modifiers.add(Modifiers.destructured);
                }

                if (isUnused(i.name, context.sourceCode.getScope(i))) {
                  modifiers.add(Modifiers.unused);
                }

                validator(i, modifiers);
              });
            });
          }

Property[computed = false]:matches([kind = get], [kind = set]).handler(node: TSESTree.PropertyNonComputedName, validator: ValidatorFunction): void

Parameters:

  • node TSESTree.PropertyNonComputedName
  • validator ValidatorFunction

Returns: void

Calls:

  • handleMember
Code
(node: TSESTree.PropertyNonComputedName, validator): void => {
          const modifiers = new Set<Modifiers>([Modifiers.public]);
          handleMember(validator, node, modifiers);
        }

TSParameterProperty.handler(node: any, validator: ValidatorFunction): void

Parameters:

  • node any
  • validator ValidatorFunction

Returns: void

Calls:

  • getMemberModifiers
  • getIdentifiersFromPattern
  • identifiers.forEach
  • validator
Code
(node, validator): void => {
          const modifiers = getMemberModifiers(node);

          const identifiers = getIdentifiersFromPattern(node.parameter);

          identifiers.forEach(i => {
            validator(i, modifiers);
          });
        }

TSPropertySignature[computed = false][typeAnnotation.typeAnnotation.type != TSFunctionType].handler(…): void

Parameters:

  • node TSESTree.TSPropertySignatureNonComputedName
  • validator ValidatorFunction

Returns: void

Calls:

  • modifiers.add
  • handleMember
Code
(
            node: TSESTree.TSPropertySignatureNonComputedName,
            validator,
          ): void => {
            const modifiers = new Set<Modifiers>([Modifiers.public]);
            if (node.readonly) {
              modifiers.add(Modifiers.readonly);
            }

            handleMember(validator, node, modifiers);
          }

ClassDeclaration, ClassExpression.handler(node: TSESTree.ClassDeclaration | TSESTree.Cl…, validator: ValidatorFunction): void

Parameters:

  • node TSESTree.ClassDeclaration | TSESTree.ClassExpression
  • validator ValidatorFunction

Returns: void

Calls:

  • context.sourceCode.getScope
  • modifiers.add
  • isExported
  • isUnused
  • validator

Internal Comments:

// classes create their own nested scope (x2)

Code
(
          node: TSESTree.ClassDeclaration | TSESTree.ClassExpression,
          validator,
        ): void => {
          const id = node.id;
          if (id == null) {
            return;
          }

          const modifiers = new Set<Modifiers>();
          // classes create their own nested scope
          const scope = context.sourceCode.getScope(node).upper;

          if (node.abstract) {
            modifiers.add(Modifiers.abstract);
          }

          if (isExported(node, id.name, scope)) {
            modifiers.add(Modifiers.exported);
          }

          if (isUnused(id.name, scope)) {
            modifiers.add(Modifiers.unused);
          }

          validator(id, modifiers);
        }

TSEnumDeclaration.handler(node: any, validator: ValidatorFunction): void

Parameters:

  • node any
  • validator ValidatorFunction

Returns: void

Calls:

  • context.sourceCode.getScope
  • isExported
  • modifiers.add
  • isUnused
  • validator

Internal Comments:

// enums create their own nested scope (x2)

Code
(node, validator): void => {
          const modifiers = new Set<Modifiers>();
          // enums create their own nested scope
          const scope = context.sourceCode.getScope(node).upper;

          if (isExported(node, node.id.name, scope)) {
            modifiers.add(Modifiers.exported);
          }

          if (isUnused(node.id.name, scope)) {
            modifiers.add(Modifiers.unused);
          }

          validator(node.id, modifiers);
        }

TSEnumMember.handler(node: TSESTree.TSEnumMember, validator: ValidatorFunction): void

Parameters:

  • node TSESTree.TSEnumMember
  • validator ValidatorFunction

Returns: void

Calls:

  • requiresQuoting
  • modifiers.add
  • validator
Code
(node: TSESTree.TSEnumMember, validator): void => {
          const id = node.id;
          const modifiers = new Set<Modifiers>();

          if (requiresQuoting(id, compilerOptions.target)) {
            modifiers.add(Modifiers.requiresQuotes);
          }

          validator(id, modifiers);
        }

TSInterfaceDeclaration.handler(node: any, validator: ValidatorFunction): void

Parameters:

  • node any
  • validator ValidatorFunction

Returns: void

Calls:

  • context.sourceCode.getScope
  • isExported
  • modifiers.add
  • isUnused
  • validator
Code
(node, validator): void => {
          const modifiers = new Set<Modifiers>();
          const scope = context.sourceCode.getScope(node);

          if (isExported(node, node.id.name, scope)) {
            modifiers.add(Modifiers.exported);
          }

          if (isUnused(node.id.name, scope)) {
            modifiers.add(Modifiers.unused);
          }

          validator(node.id, modifiers);
        }

TSTypeAliasDeclaration.handler(node: any, validator: ValidatorFunction): void

Parameters:

  • node any
  • validator ValidatorFunction

Returns: void

Calls:

  • context.sourceCode.getScope
  • isExported
  • modifiers.add
  • isUnused
  • validator
Code
(node, validator): void => {
          const modifiers = new Set<Modifiers>();
          const scope = context.sourceCode.getScope(node);

          if (isExported(node, node.id.name, scope)) {
            modifiers.add(Modifiers.exported);
          }

          if (isUnused(node.id.name, scope)) {
            modifiers.add(Modifiers.unused);
          }

          validator(node.id, modifiers);
        }

TSTypeParameterDeclaration > TSTypeParameter.handler(node: TSESTree.TSTypeParameter, validator: ValidatorFunction): void

Parameters:

  • node TSESTree.TSTypeParameter
  • validator ValidatorFunction

Returns: void

Calls:

  • context.sourceCode.getScope
  • isUnused
  • modifiers.add
  • validator
Code
(node: TSESTree.TSTypeParameter, validator): void => {
          const modifiers = new Set<Modifiers>();
          const scope = context.sourceCode.getScope(node);

          if (isUnused(node.name.name, scope)) {
            modifiers.add(Modifiers.unused);
          }

          validator(node.name, modifiers);
        }

Type Aliases

MessageIds

type MessageIds = | 'doesNotMatchFormat'
  | 'doesNotMatchFormatTrimmed'
  | 'missingAffix'
  | 'missingUnderscore'
  | 'satisfyCustom'
  | 'unexpectedUnderscore';

Options

type Options = Selector[];

Generated by Syntax Scribe