export default function parseTS()

in modules/material-parser/src/parse/ts/index.ts [479:609]


export default function parseTS(filePath: string, args: IParseArgs): ComponentDoc[] {
  if (!filePath) return [];

  let basePath = args.moduleDir || args.workDir || path.dirname(filePath);
  let tsConfigPath = findConfig('tsconfig.json', { cwd: basePath }); // path.resolve(basePath, 'tsconfig.json')
  if (
    !tsConfigPath ||
    !existsSync(tsConfigPath) ||
    (args.accesser === 'online' && tsConfigPath === 'tsconfig.json')
  ) {
    tsConfigPath = defaultTsConfigPath;
  } else {
    basePath = path.dirname(tsConfigPath);
  }

  log('ts config path is', tsConfigPath);
  const { config, error } = ts.readConfigFile(tsConfigPath, (filename) =>
    readFileSync(filename, 'utf8'));

  if (error !== undefined) {
    const errorText = `Cannot load custom tsconfig.json from provided path: ${tsConfigPath}, with error code: ${error.code}, message: ${error.messageText}`;
    throw new Error(errorText);
  }

  const { options, errors } = ts.parseJsonConfigFileContent(
    config,
    ts.sys,
    basePath,
    {},
    tsConfigPath,
  );

  if (errors && errors.length) {
    throw errors[0];
  }
  log('ts config is', options);
  // const filePaths = Array.isArray(filePathOrPaths) ? filePathOrPaths : [filePathOrPaths];
  generateDTS(args);
  const program = ts.createProgram([filePath], options);

  const parser = new MyParser(program, {});

  const checker = program.getTypeChecker();

  const result = [filePath]
    .map((fPath) => program.getSourceFile(fPath))
    .filter((sourceFile) => typeof sourceFile !== 'undefined')
    .reduce((docs: any[], sourceFile) => {
      const moduleSymbol = checker.getSymbolAtLocation(sourceFile as ts.Node);

      if (!moduleSymbol) {
        return docs;
      }

      const exportSymbols = checker.getExportsOfModule(moduleSymbol);

      for (let index = 0; index < exportSymbols.length; index++) {
        const sym: SymbolWithMeta = exportSymbols[index];
        const name = sym.getName();
        if (blacklistNames.includes(name)) {
          continue;
        }

        // polyfill valueDeclaration
        sym.valueDeclaration =
          sym.valueDeclaration || (Array.isArray(sym.declarations) && sym.declarations[0]);

        if (!sym.valueDeclaration) {
          continue;
        }
        const info = parser.getComponentInfo(sym, sourceFile);
        if (info === null) {
          continue;
        }
        const exportName = sym.meta && sym.meta.exportName;
        const meta = {
          subName: exportName ? name : '',
          exportName: exportName || name,
        };
        if (docs.find((x) => isEqual(x.meta, meta))) {
          continue;
        }
        docs.push({
          ...info,
          meta,
        });
        // find sub components
        if (!!sym.declarations && sym.declarations.length === 0) {
          continue;
        }

        const type = checker.getTypeOfSymbolAtLocation(
          sym,
          sym.valueDeclaration || sym.declarations[0],
        );
        Array.prototype.push.apply(
          exportSymbols,
          type.getProperties().map((x: SymbolWithMeta) => {
            x.meta = { exportName: name };
            return x;
          }),
        );
      }

      return docs;
    }, []);
  const coms = result.reduce((res: any[], info: any) => {
    if (!info || !info.props || isEmpty(info.props)) return res;
    const props = Object.keys(info.props).reduce((acc: any[], name) => {
      // omit aria related properties temporarily
      if (name.startsWith('aria-')) {
        return acc;
      }
      try {
        const item: any = transformItem(name, info.props[name]);
        acc.push(item);
      } catch (e) {
        log(e);
      }
      return acc;
    }, []);
    const exportName = info?.meta?.exportName;
    res.push({
      componentName: getComponentName(exportName, info.displayName),
      props,
      meta: info.meta || {},
    });
    return res;
  }, []);
  return coms;
}