Skip to content

⬅️ Back to Table of Contents

📄 adjacent-overload-signatures

📊 Analysis Summary

Metric Count
🔧 Functions 5
📦 Imports 5
📐 Interfaces 1
📑 Type Aliases 3

📚 Table of Contents

🛠️ File Location:

📂 packages/eslint-plugin/src/rules/adjacent-overload-signatures.ts

📤 Default Export

export default createRule({ ... })
Property Value
name 'adjacent-overload-signatures'
meta.type 'suggestion'
meta.docs.description 'Require that function overload signatures be consecutive'
meta.docs.recommended 'stylistic'
meta.messages.adjacentSignature 'All {{name}} signatures should be adjacent.'
meta.schema []
defaultOptions []

Entry point: create — documented under Functions.


📦 Imports

Name Source
TSESTree @typescript-eslint/utils
AST_NODE_TYPES @typescript-eslint/utils
createRule ../util
getNameFromMember ../util
MemberNameType ../util

Functions

create(context: any): { BlockStatement: (node: RuleNode) => void; ClassBody: (nod…

Parameters:

  • context any

Returns: { BlockStatement: (node: RuleNode) => void; ClassBody: (node: RuleNode) => void; Program: (node: RuleNode) => void; TSInterfaceBody: (node: RuleNode) => void; TSModuleBlock: (node: RuleNode) => void; TSTypeLiteral: (node: RuleNode) => void; }

Calls:

  • getMemberMethod
  • getNameFromMember (from ../util)
  • getMembers
  • members.forEach
  • seenMethods.findIndex
  • isSameMethod
  • context.report
  • seenMethods.push

Internal Comments:

/**
     * Gets the name and attribute of the member being processed.
     * @param member the member being processed.
     * @returns the name and attribute of the member or null if it's a member not relevant to the rule.
     */
// export statements (e.g. export { a };)
// have no declarations, so ignore them

Code
create(context) {
    interface Method {
      callSignature: boolean;
      name: string;
      static?: boolean;
      type: MemberNameType;
    }

    /**
     * Gets the name and attribute of the member being processed.
     * @param member the member being processed.
     * @returns the name and attribute of the member or null if it's a member not relevant to the rule.
     */
    function getMemberMethod(
      member: Member | MemberDeclaration,
    ): Method | null {
      switch (member.type) {
        case AST_NODE_TYPES.ExportDefaultDeclaration:
        case AST_NODE_TYPES.ExportNamedDeclaration: {
          // export statements (e.g. export { a };)
          // have no declarations, so ignore them
          if (!member.declaration) {
            return null;
          }

          return getMemberMethod(member.declaration);
        }
        case AST_NODE_TYPES.TSDeclareFunction:
        case AST_NODE_TYPES.FunctionDeclaration: {
          const name = member.id?.name ?? null;
          if (name == null) {
            return null;
          }
          return {
            name,
            type: MemberNameType.Normal,
            callSignature: false,
          };
        }
        case AST_NODE_TYPES.TSMethodSignature:
        case AST_NODE_TYPES.MethodDefinition:
          return {
            ...getNameFromMember(member, context.sourceCode),
            callSignature: false,
            static: member.static,
          };
        case AST_NODE_TYPES.TSCallSignatureDeclaration:
          return {
            name: 'call',
            type: MemberNameType.Normal,
            callSignature: true,
          };
        case AST_NODE_TYPES.TSConstructSignatureDeclaration:
          return {
            name: 'new',
            type: MemberNameType.Normal,
            callSignature: false,
          };
      }

      return null;
    }

    function isSameMethod(method1: Method, method2: Method | null): boolean {
      return (
        !!method2 &&
        method1.name === method2.name &&
        method1.static === method2.static &&
        method1.callSignature === method2.callSignature &&
        method1.type === method2.type
      );
    }

    function getMembers(node: RuleNode): Member[] {
      switch (node.type) {
        case AST_NODE_TYPES.ClassBody:
        case AST_NODE_TYPES.Program:
        case AST_NODE_TYPES.TSModuleBlock:
        case AST_NODE_TYPES.TSInterfaceBody:
        case AST_NODE_TYPES.BlockStatement:
          return node.body;

        case AST_NODE_TYPES.TSTypeLiteral:
          return node.members;
      }
    }

    function checkBodyForOverloadMethods(node: RuleNode): void {
      const members = getMembers(node);

      let lastMethod: Method | null = null;
      const seenMethods: Method[] = [];

      members.forEach(member => {
        const method = getMemberMethod(member);
        if (method == null) {
          lastMethod = null;
          return;
        }

        const index = seenMethods.findIndex(seenMethod =>
          isSameMethod(method, seenMethod),
        );
        if (index > -1 && !isSameMethod(method, lastMethod)) {
          context.report({
            node: member,
            messageId: 'adjacentSignature',
            data: {
              name: `${method.static ? 'static ' : ''}${method.name}`,
            },
          });
        } else if (index === -1) {
          seenMethods.push(method);
        }

        lastMethod = method;
      });
    }

    return {
      BlockStatement: checkBodyForOverloadMethods,
      ClassBody: checkBodyForOverloadMethods,
      Program: checkBodyForOverloadMethods,
      TSInterfaceBody: checkBodyForOverloadMethods,
      TSModuleBlock: checkBodyForOverloadMethods,
      TSTypeLiteral: checkBodyForOverloadMethods,
    };
  }

Internal helpers

Declared inside another function in this file.

getMemberMethod(member: Member | MemberDeclaration): Method | null

Gets the name and attribute of the member being processed.

Parameters:

  • member any: the member being processed.

Returns: undefined the name and attribute of the member or null if it's a member not relevant to the rule.

Raw JSDoc
/**
     * Gets the name and attribute of the member being processed.
     * @param member the member being processed.
     * @returns the name and attribute of the member or null if it's a member not relevant to the rule.
     */

Calls:

  • getMemberMethod
  • getNameFromMember (from ../util)

Internal Comments:

// export statements (e.g. export { a };)
// have no declarations, so ignore them

Code
function getMemberMethod(
      member: Member | MemberDeclaration,
    ): Method | null {
      switch (member.type) {
        case AST_NODE_TYPES.ExportDefaultDeclaration:
        case AST_NODE_TYPES.ExportNamedDeclaration: {
          // export statements (e.g. export { a };)
          // have no declarations, so ignore them
          if (!member.declaration) {
            return null;
          }

          return getMemberMethod(member.declaration);
        }
        case AST_NODE_TYPES.TSDeclareFunction:
        case AST_NODE_TYPES.FunctionDeclaration: {
          const name = member.id?.name ?? null;
          if (name == null) {
            return null;
          }
          return {
            name,
            type: MemberNameType.Normal,
            callSignature: false,
          };
        }
        case AST_NODE_TYPES.TSMethodSignature:
        case AST_NODE_TYPES.MethodDefinition:
          return {
            ...getNameFromMember(member, context.sourceCode),
            callSignature: false,
            static: member.static,
          };
        case AST_NODE_TYPES.TSCallSignatureDeclaration:
          return {
            name: 'call',
            type: MemberNameType.Normal,
            callSignature: true,
          };
        case AST_NODE_TYPES.TSConstructSignatureDeclaration:
          return {
            name: 'new',
            type: MemberNameType.Normal,
            callSignature: false,
          };
      }

      return null;
    }

isSameMethod(method1: Method, method2: Method | null): boolean

Parameters:

  • method1 Method
  • method2 Method | null

Returns: boolean

Code
function isSameMethod(method1: Method, method2: Method | null): boolean {
      return (
        !!method2 &&
        method1.name === method2.name &&
        method1.static === method2.static &&
        method1.callSignature === method2.callSignature &&
        method1.type === method2.type
      );
    }

getMembers(node: RuleNode): Member[]

Parameters:

  • node RuleNode

Returns: Member[]

Code
function getMembers(node: RuleNode): Member[] {
      switch (node.type) {
        case AST_NODE_TYPES.ClassBody:
        case AST_NODE_TYPES.Program:
        case AST_NODE_TYPES.TSModuleBlock:
        case AST_NODE_TYPES.TSInterfaceBody:
        case AST_NODE_TYPES.BlockStatement:
          return node.body;

        case AST_NODE_TYPES.TSTypeLiteral:
          return node.members;
      }
    }

checkBodyForOverloadMethods(node: RuleNode): void

Parameters:

  • node RuleNode

Returns: void

Calls:

  • getMembers
  • members.forEach
  • getMemberMethod
  • seenMethods.findIndex
  • isSameMethod
  • context.report
  • seenMethods.push
Code
function checkBodyForOverloadMethods(node: RuleNode): void {
      const members = getMembers(node);

      let lastMethod: Method | null = null;
      const seenMethods: Method[] = [];

      members.forEach(member => {
        const method = getMemberMethod(member);
        if (method == null) {
          lastMethod = null;
          return;
        }

        const index = seenMethods.findIndex(seenMethod =>
          isSameMethod(method, seenMethod),
        );
        if (index > -1 && !isSameMethod(method, lastMethod)) {
          context.report({
            node: member,
            messageId: 'adjacentSignature',
            data: {
              name: `${method.static ? 'static ' : ''}${method.name}`,
            },
          });
        } else if (index === -1) {
          seenMethods.push(method);
        }

        lastMethod = method;
      });
    }

Interfaces

Method

Interface Code
interface Method {
      callSignature: boolean;
      name: string;
      static?: boolean;
      type: MemberNameType;
    }

Properties

Name Type Optional Description
callSignature boolean not shown
name string not shown
static boolean not shown
type MemberNameType not shown

Type Aliases

RuleNode

type RuleNode = | TSESTree.BlockStatement
  | TSESTree.ClassBody
  | TSESTree.Program
  | TSESTree.TSInterfaceBody
  | TSESTree.TSModuleBlock
  | TSESTree.TSTypeLiteral;

Member

type Member = TSESTree.ClassElement | TSESTree.ProgramStatement | TSESTree.TypeElement;

MemberDeclaration

type MemberDeclaration = TSESTree.DefaultExportDeclarations | TSESTree.NamedExportDeclarations;

Generated by Syntax Scribe