Skip to content

⬅️ Back to Table of Contents

📄 printAST.ts

📊 Analysis Summary

Metric Count
🔧 Functions 6
📦 Imports 3
📊 Variables & Constants 6
📐 Interfaces 2

📚 Table of Contents

🛠️ File Location:

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

📦 Imports

Name Source
naturalCompare natural-compare
AST ./types
TupleAST ./types

Variables & Constants

Name Type Kind Value Exported
commentLines string[] const []
properties any[] const []
elements any[] const []
code string const ${printComment(result)} | ${result.code}
aElement TupleAST const a.element
bElement TupleAST const b.element as TupleAST

Functions

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

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

printASTWithComment(ast: AST): string

Code
export function printASTWithComment(ast: AST): string {
  const result = printAST(ast);
  return `${printComment(result)}${result.code}`;
}
  • Parameters:
  • ast: AST
  • Return Type: string
  • Calls:
  • printAST
  • printComment

`printComment({

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

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('\n'));
  }

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

  return ['/**', ...commentLines.map(l => ` * ${l}`), ' */', ''].join('\n');
}
  • Parameters:
  • { commentLines: commentLinesIn, }: { readonly commentLines?: string[] | null | undefined; }
  • Return Type: string
  • Calls:
  • commentLines.push
  • line.split
  • ['/**', ...commentLines.map(l => * ${l}), ' */', ''].join
  • commentLines.map

printAST(ast: AST): CodeWithComments

Code
function printAST(ast: AST): CodeWithComments {
  switch (ast.type) {
    case 'array': {
      const code = printAndMaybeParenthesise(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 = printAndMaybeParenthesise(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,
      };
  }
}
  • Parameters:
  • ast: AST
  • Return Type: CodeWithComments
  • Calls:
  • printAndMaybeParenthesise
  • 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)
    

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

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);
    }
  }
}
  • Parameters:
  • a: Element
  • b: Element
  • Return Type: 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)
    

printAndMaybeParenthesise(ast: AST): CodeWithComments

Code
function printAndMaybeParenthesise(ast: AST): CodeWithComments {
  const printed = printAST(ast);
  if (ast.type === 'union') {
    return {
      code: `(${printed.code})`,
      commentLines: printed.commentLines,
    };
  }
  return {
    code: printed.code,
    commentLines: printed.commentLines,
  };
}
  • Parameters:
  • ast: AST
  • Return Type: CodeWithComments
  • Calls:
  • printAST

Interfaces

CodeWithComments

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

Properties

Name Type Optional Description
code string
commentLines string[]

Element

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

Properties

Name Type Optional Description
code string
element AST