<commit_before>import * as ts from 'typescript';

export interface PropInfo {
  name: string;
  doc?: string;
}

export interface ComponentInfo {
  name: string;
  props?: PropInfo[];
}

export function findComponents(service: ts.LanguageService, fileFsPath: string): ComponentInfo[] {
  const program = service.getProgram();
  const sourceFile = program.getSourceFile(fileFsPath);
  const exportStmt = sourceFile.statements.filter(st => st.kind === ts.SyntaxKind.ExportAssignment);
  if (exportStmt.length === 0) {
    return [];
  }
  // vls will create synthetic __vueEditorBridge({ ... })
  const exportCall = (exportStmt[0] as ts.ExportAssignment).expression;
  if (exportCall.kind !== ts.SyntaxKind.CallExpression) {
    return [];
  }
  const comp = (exportCall as ts.CallExpression).arguments[0];
  const checker = program.getTypeChecker();
  const compType = checker.getTypeAtLocation(comp);
  const childComps = getPropertyTypeOfType(compType, 'components', checker);
  if (!childComps) {
    return [];
  }
  return checker.getPropertiesOfType(childComps).map(s => getCompInfo(s, checker));
}

function getCompInfo(symbol: ts.Symbol, checker: ts.TypeChecker) {
  const compType = getSymbolType(symbol, checker);
  const info: ComponentInfo = {
    name: symbol.name
  };
  if (!compType) {
    return info;
  }
  const arrayProps = getArrayProps(compType, checker);
  if (arrayProps) {
    info.props = arrayProps;
    return info;
  }<commit_msg>add component definition collection<commit_after>import * as ts from 'typescript';

export interface PropInfo {
  name: string;
  doc?: string;
}

export interface ComponentInfo {
  name: string;
  fsPath?: string;
  props?: PropInfo[];
}

export function findComponents(service: ts.LanguageService, fileFsPath: string): ComponentInfo[] {
  const program = service.getProgram();
  const sourceFile = program.getSourceFile(fileFsPath);
  const exportStmt = sourceFile.statements.filter(st => st.kind === ts.SyntaxKind.ExportAssignment);
  if (exportStmt.length === 0) {
    return [];
  }
  // vls will create synthetic __vueEditorBridge({ ... })
  const exportCall = (exportStmt[0] as ts.ExportAssignment).expression;
  if (exportCall.kind !== ts.SyntaxKind.CallExpression) {
    return [];
  }
  const comp = (exportCall as ts.CallExpression).arguments[0];
  const checker = program.getTypeChecker();
  const compType = checker.getTypeAtLocation(comp);
  const childComps = getPropertyTypeOfType(compType, 'components', checker);
  if (!childComps) {
    return [];
  }
  return checker.getPropertiesOfType(childComps).map(s => getCompInfo(s, checker));
}

function getCompInfo(symbol: ts.Symbol, checker: ts.TypeChecker) {
  const compType = getSymbolType(symbol, checker);
  const info: ComponentInfo = {
    name: symbol.name,
  };
  if (!compType) {
    return info;
  }
  if (compType.symbol && compType.symbol.declarations) {
    const declaration = compType.symbol.declarations[0];
    info.fsPath = declaration ? declaration.getSourceFile().fileName : '';
  }
  const arrayProps = getArrayProps(compType, checker);
  if (arrayProps) {
    info.props = arrayProps;
    return info;
  }
{'fraction_non_alphanumeric': 0.12630910821961283, 'fraction_numerical': 0.002221516978736909, 'mean_word_length': 4.481739130434782, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3507982', 'n_tokens_mistral': 960, 'n_tokens_neox': 969, 'n_words': 226}