Skip to content

⬅️ Back to Table of Contents

📄 printAST

📊 Analysis Summary

Metric Count
🔧 Functions 6
📦 Imports 4
📐 Interfaces 2

📚 Table of Contents

🛠️ File Location:

📂 packages/rule-schema-to-typescript-types/src/printAST.ts

📦 Imports

Name Source
ASTUtils @typescript-eslint/utils
naturalCompare natural-compare
SchemaAST ./types.js
TupleAST ./types.js

Functions

printTypeAlias(aliasName: string, ast: SchemaAST): string

Parameters:

  • aliasName string
  • ast SchemaAST

Returns: string

Calls:

  • printComment
  • printAST
Code
export function printTypeAlias(aliasName: string, ast: SchemaAST): string {
  return `${printComment(ast)}type ${aliasName} = ${printAST(ast).code}`;
}

printASTWithComment(ast: SchemaAST): string

Parameters:

  • ast SchemaAST

Returns: string

Calls:

  • printAST
  • printComment
Code
export function printASTWithComment(ast: SchemaAST): string {
  const result = printAST(ast);
  return `${printComment(result)}${result.code}`;
}

printComment({ commentLines: commentLinesIn,…: { readonly commentLines?: string[] | nu…): string

Parameters:

  • { commentLines: commentLinesIn, } { readonly commentLines?: string[] | null | undefined; }

Returns: string

Calls:

  • commentLines.push
  • line.split
  • ['/**', ...commentLines.map(l => * ${l}), ' */', ''].join
  • commentLines.map
Code
function printComment({
  commentLines: commentLinesIn,
}: {
  readonly commentLines?: string[] | null | undefined;
}): string {
  if (commentLinesIn == null || commentLinesIn.length === 0) {
    return '';
  }

  const commentLines: string[] = [];
  for (const line of commentLinesIn) {
    commentLines.push(...line.split(ASTUtils.LINEBREAK_MATCHER));
  }

  if (commentLines.length === 1) {
    return `/** ${commentLines[0]} */\n`;
  }

  return ['/**', ...commentLines.map(l => ` * ${l}`), ' */', ''].join('\n');
}

printAST(ast: SchemaAST): CodeWithComments

Parameters:

  • ast SchemaAST

Returns: CodeWithComments

Calls:

  • printAndMaybeParenthesize
  • ast.properties.sort
  • naturalCompare (from natural-compare)
  • printAST
  • properties.push
  • printComment
  • properties.join
  • elements.push
  • printASTWithComment
  • elements.join
  • ast.elements .map(element => { const result = printAST(element); const code =${printComment(result)} | ${result.code}; return { code, element, }; }) // sort the union members so that we get consistent output regardless // of declaration order .sort((a, b) => compareElements(a, b)) .map(el => el.code) .join

Internal Comments:

// sort the properties so that we get consistent output regardless (x2)
// of import declaration order (x2)
// force insert a newline so prettier consistently prints all objects as multiline (x2)

Code
function printAST(ast: SchemaAST): CodeWithComments {
  switch (ast.type) {
    case 'array': {
      const code = printAndMaybeParenthesize(ast.elementType);
      return {
        code: `${code.code}[]`,
        commentLines: [...ast.commentLines, ...code.commentLines],
      };
    }

    case 'literal':
      return {
        code: ast.code,
        commentLines: ast.commentLines,
      };

    case 'object': {
      const properties = [];
      // sort the properties so that we get consistent output regardless
      // of import declaration order
      const sortedPropertyDefs = ast.properties.sort((a, b) =>
        naturalCompare(a.name, b.name),
      );
      for (const property of sortedPropertyDefs) {
        const result = printAST(property.type);
        properties.push(
          `${printComment(result)}${property.name}${
            property.optional ? '?:' : ':'
          } ${result.code}`,
        );
      }

      if (ast.indexSignature) {
        const result = printAST(ast.indexSignature);
        properties.push(`${printComment(result)}[k: string]: ${result.code}`);
      }
      return {
        // force insert a newline so prettier consistently prints all objects as multiline
        code: `{\n${properties.join(';\n')}}`,
        commentLines: ast.commentLines,
      };
    }

    case 'tuple': {
      const elements = [];
      for (const element of ast.elements) {
        elements.push(printASTWithComment(element));
      }
      if (ast.spreadType) {
        const result = printAndMaybeParenthesize(ast.spreadType);
        elements.push(`${printComment(result)}...${result.code}[]`);
      }

      return {
        code: `[${elements.join(',')}]`,
        commentLines: ast.commentLines,
      };
    }

    case 'type-reference':
      return {
        code: ast.typeName,
        commentLines: ast.commentLines,
      };

    case 'union':
      return {
        code: ast.elements
          .map(element => {
            const result = printAST(element);
            const code = `${printComment(result)} | ${result.code}`;
            return {
              code,
              element,
            };
          })
          // sort the union members so that we get consistent output regardless
          // of declaration order
          .sort((a, b) => compareElements(a, b))
          .map(el => el.code)
          .join('\n'),
        commentLines: ast.commentLines,
      };
  }
}

compareElements(a: Element, b: Element): number

Parameters:

  • a Element
  • b Element

Returns: number

Calls:

  • naturalCompare (from natural-compare)

Internal Comments:

// natural compare will sort longer tuples before shorter ones (x2)
// which is the opposite of what we want, so we sort first by length THEN (x2)
// by code to ensure shorter tuples come first (x2)

Code
function compareElements(a: Element, b: Element): number {
  if (a.element.type !== b.element.type) {
    return naturalCompare(a.code, b.code);
  }

  switch (a.element.type) {
    case 'array':
    case 'literal':
    case 'type-reference':
    case 'object':
    case 'union':
      return naturalCompare(a.code, b.code);

    case 'tuple': {
      // natural compare will sort longer tuples before shorter ones
      // which is the opposite of what we want, so we sort first by length THEN
      // by code to ensure shorter tuples come first
      const aElement = a.element;
      const bElement = b.element as TupleAST;
      if (aElement.elements.length !== bElement.elements.length) {
        return aElement.elements.length - bElement.elements.length;
      }
      return naturalCompare(a.code, b.code);
    }
  }
}

printAndMaybeParenthesize(ast: SchemaAST): CodeWithComments

Parameters:

  • ast SchemaAST

Returns: CodeWithComments

Calls:

  • printAST
Code
function printAndMaybeParenthesize(ast: SchemaAST): CodeWithComments {
  const printed = printAST(ast);
  if (ast.type === 'union') {
    return {
      code: `(${printed.code})`,
      commentLines: printed.commentLines,
    };
  }
  return {
    code: printed.code,
    commentLines: printed.commentLines,
  };
}

Interfaces

CodeWithComments

Interface Code
interface CodeWithComments {
  code: string;
  commentLines: string[];
}

Properties

Name Type Optional Description
code string not shown
commentLines string[] not shown

Element

Interface Code
interface Element {
  code: string;
  element: SchemaAST;
}

Properties

Name Type Optional Description
code string not shown
element SchemaAST not shown

Generated by Syntax Scribe