Печать определений типов из программно созданного AST - PullRequest
0 голосов
/ 12 мая 2018

Я пытаюсь программно создать AST для сценариев для определений, созданных сторонней библиотекой, и использую этот AST для печати набора определений типов (файл .d.ts) для объявлений, которые мы имеем в синтаксисеlibrary.

Полагаясь на документацию для API компилятора и копаясь в исходных файлах для компилятора машинописи, я считаю, что у меня есть AST, который в основном корректен.Однако я не нашел способа вывести определения типов (соответствующие файлу .d.ts) для этого AST, а только печатать AST как программу для машинописи.

Мой вопрос состоит из двух частей:

  1. Есть ли способ распечатать определения типов (вывести файл .d.ts) из AST?
  2. И если да, то есть ли примеры этого?

1 Ответ

0 голосов
/ 20 февраля 2019

Вероятно, проще всего скопировать и изменить то, что сделано в функции ts.transpileModule источника TypeScript, чтобы вывести только файл объявления.

Например:

export function transpileModuleDeclaration(sourceFile: ts.SourceFile, transpileOptions: ts.TranspileOptions) {
    const diagnostics: ts.Diagnostic[] = [];
    const options = transpileOptions.compilerOptions != null ? { ...transpileOptions.compilerOptions } : ts.getDefaultCompilerOptions();

    options.isolatedModules = true;

    // in this case we only want to emit the declaration file
    options.emitDeclarationOnly = true;
    options.declaration = true;

    // this does not write anything to disk so there is no need to verify that there are no conflicts between input and output paths.
    options.suppressOutputPathCheck = true;

    // Filename can be non-ts file.
    options.allowNonTsExtensions = true;

    // We are not returning a sourceFile for lib file when asked by the program,
    // so pass --noLib to avoid reporting a file not found error.
    options.noLib = true;

    // Clear out other settings that would not be used in transpiling this module
    options.lib = undefined;
    options.types = undefined;
    options.noEmit = undefined;
    options.noEmitOnError = undefined;
    options.paths = undefined;
    options.rootDirs = undefined;
    options.composite = undefined;
    options.declarationDir = undefined;
    options.out = undefined;
    options.outFile = undefined;

    // We are not doing a full typecheck, we are not resolving the whole context,
    // so pass --noResolve to avoid reporting missing file errors.
    options.noResolve = true;

    // if jsx is specified then treat file as .tsx
    const inputFileName = transpileOptions.fileName || (options.jsx ? "module.tsx" : "module.ts");
    if (transpileOptions.moduleName) {
        sourceFile.moduleName = transpileOptions.moduleName;
    }

    // Output
    let outputText: string | undefined;

    // Create a compilerHost object to allow the compiler to read and write files
    const compilerHost: ts.CompilerHost = {
        getSourceFile: (fileName) => fileName === inputFileName.replace(/\\/g, "/") ? sourceFile : undefined,
        writeFile: (name, text) => {
            outputText = text;
        },
        getDefaultLibFileName: () => "lib.d.ts",
        useCaseSensitiveFileNames: () => false,
        getCanonicalFileName: fileName => fileName,
        getCurrentDirectory: () => "",
        getNewLine: () => options.newLine == null || options.newLine === ts.NewLineKind.LineFeed ? "\n" : "\r\n",
        fileExists: fileName => fileName === inputFileName,
        readFile: () => "",
        directoryExists: () => true,
        getDirectories: () => []
    };

    const program = ts.createProgram([inputFileName], options, compilerHost);

    if (transpileOptions.reportDiagnostics) {
        diagnostics.push(...program.getSyntacticDiagnostics(sourceFile));
        diagnostics.push(...program.getOptionsDiagnostics());
    }
    // Emit
    program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ undefined, transpileOptions.transformers);

    if (outputText === undefined)
        throw new Error("Output generation failed.");

    return { outputText, diagnostics };
}

Затем, используя его:

const file = ts.createSourceFile("test.ts", `function myFunc(a: number, b: number) {
    return a + b;
}`, ts.ScriptTarget.Latest, true);

const result = transpileModuleDeclaration(file, {});
console.log(result.outputText);

Выходы:

declare function myFunc(a: number, b: number): number;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...