Open9

TypeScriptコードリーディングメモ

tsc.tsからのコールスタック [#1]

tsc.ts
namespace ts {} // empty ts module so the module migration script knows this file depends on the `ts` project namespace
// This file actually uses arguments passed on commandline and executes it
ts.Debug.loggingHost = {
    log(_level, s) {
        ts.sys.write(`${s || ""}${ts.sys.newLine}`);
    }
};

if (ts.Debug.isDebugging) {
    ts.Debug.enableDebugInfo();
}

if (ts.sys.tryEnableSourceMapsForHost && /^development$/i.test(ts.sys.getEnvironmentVariable("NODE_ENV"))) {
    ts.sys.tryEnableSourceMapsForHost();
}

if (ts.sys.setBlocking) {
    ts.sys.setBlocking();
}

ts.executeCommandLine(ts.sys, ts.noop, ts.sys.args);
executeCommandLine.ts
@@ L200 @@
    function executeCommandLineWorker(
        sys: System,
        cb: ExecuteCommandLineCallbacks,
        commandLine: ParsedCommandLine,
    ) {
@@ L370 @@
                performCompilation(
                    sys,
                    cb,
                    reportDiagnostic,
                    { ...commandLine, options: commandLineOptions }
                );
@@ L389 @@
    export function executeCommandLine(
        system: System,
        cb: ExecuteCommandLineCallbacks,
        commandLineArgs: readonly string[],
    ) {
@@ L427 @@
            return executeCommandLineWorker(system, cb, commandLine);
@@ L516 @@
    function performCompilation(
        sys: System,
        cb: ExecuteCommandLineCallbacks,
        reportDiagnostic: DiagnosticReporter,
        config: ParsedCommandLine
    ) {
@@ L523 @@
        const host = createCompilerHostWorker(options, /*setParentPos*/ undefined, sys);
@@ L536 @@
        const program = createProgram(programOptions);
        const exitStatus = emitFilesAndReportErrorsAndGetExitStatus(
            program,
            reportDiagnostic,
            s => sys.write(s + sys.newLine),
            createReportErrorSummary(sys, options)
        );

tsc.tsからのコールスタック [#2]

src/compiler/program.ts
@@ L71 @@
    /*@internal*/
    // TODO(shkamat): update this after reworking ts build API
    export function createCompilerHostWorker(options: CompilerOptions, setParentNodes?: boolean, system = sys): CompilerHost {
@@ L77 @@
        function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile | undefined {
@@ L91 @@
            return text !== undefined ? createSourceFile(fileName, text, languageVersion, setParentNodes) : undefined;
@@ L172 @@
        const compilerHost: CompilerHost = {
            getSourceFile,
@@ L192 @@
        return compilerHost;
@@ L763 @@
    /**
     * Create a new 'Program' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions'
     * that represent a compilation unit.
     *
     * Creating a program proceeds from a set of root files, expanding the set of inputs by following imports and
     * triple-slash-reference-path directives transitively. '@types' and triple-slash-reference-types are also pulled in.
     *
     * @param createProgramOptions - The options for creating a program.
     * @returns A 'Program' object.
     */
    export function createProgram(createProgramOptions: CreateProgramOptions): Program;
    /**
     * Create a new 'Program' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions'
     * that represent a compilation unit.
     *
     * Creating a program proceeds from a set of root files, expanding the set of inputs by following imports and
     * triple-slash-reference-path directives transitively. '@types' and triple-slash-reference-types are also pulled in.
     *
     * @param rootNames - A set of root files.
     * @param options - The compiler options which should be used.
     * @param host - The host interacts with the underlying file system.
     * @param oldProgram - Reuses an old program structure.
     * @param configFileParsingDiagnostics - error during config file parsing
     * @returns A 'Program' object.
     */
    export function createProgram(rootNames: readonly string[], options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: readonly Diagnostic[]): Program;
    export function createProgram(rootNamesOrOptions: readonly string[] | CreateProgramOptions, _options?: CompilerOptions, _host?: CompilerHost, _oldProgram?: Program, _configFileParsingDiagnostics?: readonly Diagnostic[]): Program {
@@ L968 @@
            forEach(rootNames, (name, index) => processRootFile(name, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, { kind: FileIncludeKind.RootFile, index }));
@@ L1053 @@
        const program: Program = {
@@ L1055 @@
            getSourceFile,
@@ L1109 @@
        };
@@ L1131 @@
        return program;
@@ L1751 @@
        function emit(sourceFile?: SourceFile, writeFileCallback?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, transformers?: CustomTransformers, forceDtsEmit?: boolean): EmitResult {
            tracing?.push(tracing.Phase.Emit, "emit", { path: sourceFile?.path }, /*separateBeginAndEnd*/ true);
            const result = runWithCancellationToken(() => emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnlyDtsFiles, transformers, forceDtsEmit));
            tracing?.pop();
            return result;
        }
@@ L1762 @@
        function emitWorker(program: Program, sourceFile: SourceFile | undefined, writeFileCallback: WriteFileCallback | undefined, cancellationToken: CancellationToken | undefined, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers, forceDtsEmit?: boolean): EmitResult {
@@ L1780 @@
            const emitResult = emitFiles(
                emitResolver,
                getEmitHost(writeFileCallback),
                sourceFile,
                getTransformers(options, customTransformers, emitOnlyDtsFiles),
                emitOnlyDtsFiles,
                /*onlyBuildInfo*/ false,
                forceDtsEmit
            );
@@ L1795 @@
        function getSourceFile(fileName: string): SourceFile | undefined {
            return getSourceFileByPath(toPath(fileName));
        }
@@ L1799 @@
        function getSourceFileByPath(path: Path): SourceFile | undefined {
            return filesByName.get(path) || undefined;
        }
@@ L2251 @@
        function processRootFile(fileName: string, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, reason: FileIncludeReason) {
            processSourceFile(normalizePath(fileName), isDefaultLib, ignoreNoDefaultLib, /*packageId*/ undefined, reason);
        }
@@ L2410@@
        function getSourceFileFromReferenceWorker(
            fileName: string,
            getSourceFile: (fileName: string) => SourceFile | undefined,
            fail?: (diagnostic: DiagnosticMessage, ...argument: string[]) => void,
            reason?: FileIncludeReason): SourceFile | undefined {
@@ L2430 @@
                const sourceFile = getSourceFile(fileName);
@@ L2462 @@
        /** This has side effects through `findSourceFile`. */
        function processSourceFile(fileName: string, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, packageId: PackageId | undefined, reason: FileIncludeReason): void {
            getSourceFileFromReferenceWorker(
                fileName,
                fileName => findSourceFile(fileName, toPath(fileName), isDefaultLib, ignoreNoDefaultLib, reason, packageId), // TODO: GH#18217
                (diagnostic, ...args) => addFilePreprocessingFileExplainingDiagnostic(/*file*/ undefined, reason, diagnostic, args),
                reason
            );
        }
@@ L2507 @@
        // Get source file from normalized fileName
        function findSourceFile(fileName: string, path: Path, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, reason: FileIncludeReason, packageId: PackageId | undefined): SourceFile | undefined {
@@ L2514 @@
            const result = findSourceFileWorker(fileName, path, isDefaultLib, ignoreNoDefaultLib, reason, packageId);
@@ L2519 @@
        function findSourceFileWorker(fileName: string, path: Path, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, reason: FileIncludeReason, packageId: PackageId | undefined): SourceFile | undefined {
@@ L2607 @@
            // We haven't looked for this file, do so now and cache result
            const file = host.getSourceFile(
                fileName,
                options.target!,
                hostErrorMessage => addFilePreprocessingFileExplainingDiagnostic(/*file*/ undefined, reason, Diagnostics.Cannot_read_file_0_Colon_1, [fileName, hostErrorMessage]),
                shouldCreateNewSourceFile
            );
@@ L2635 @@
            addFileToFilesByName(file, path, redirectedPath);
@@ L2685 @@
        function addFileToFilesByName(file: SourceFile | undefined, path: Path, redirectedPath: Path | undefined) {
            if (redirectedPath) {
                filesByName.set(redirectedPath, file);
                filesByName.set(path, file || false);
            }
            else {
                filesByName.set(path, file);
            }
        }

tsc.tsからのコールスタック [#3]

src/compiler/parser.ts
@@ L625 @@
    export function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes = false, scriptKind?: ScriptKind): SourceFile {
@@ L635 @@
            result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind);
@@ L698 @@
    // Implement the parser as a singleton module.  We do this for perf reasons because creating
    // parser instances can actually be expensive enough to impact us on projects with many source
    // files.
    namespace Parser {
@@ L834 @@
        export function parseSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, syntaxCursor: IncrementalParser.SyntaxCursor | undefined, setParentNodes = false, scriptKind?: ScriptKind): SourceFile {
@@ L850 @@
            const result = parseSourceFileWorker(languageVersion, setParentNodes, scriptKind);
@@ L1022 @@
        function parseSourceFileWorker(languageVersion: ScriptTarget, setParentNodes: boolean, scriptKind: ScriptKind): SourceFile {
@@ L1031 @@
            nextToken();
@@ L1033 @@
            const statements = parseList(ParsingContext.SourceElements, parseStatement);
@@ L1847 @@
        // True if positioned at the start of a list element
        function isListElement(parsingContext: ParsingContext, inErrorRecovery: boolean): boolean {
            const node = currentNode(parsingContext);
            if (node) {
                return true;
            }

            switch (parsingContext) {
                case ParsingContext.SourceElements:
                case ParsingContext.BlockStatements:
                case ParsingContext.SwitchClauseStatements:
                    // If we're in error recovery, then we don't want to treat ';' as an empty statement.
                    // The problem is that ';' can show up in far too many contexts, and if we see one
                    // and assume it's a statement, then we may bail out inappropriately from whatever
                    // we're parsing.  For example, if we have a semicolon in the middle of a class, then
                    // we really don't want to assume the class is over and we're on a statement in the
                    // outer module.  We just want to consume and move on.
                    return !(token() === SyntaxKind.SemicolonToken && inErrorRecovery) && isStartOfStatement();
                case ParsingContext.SwitchClauses:
                    return token() === SyntaxKind.CaseKeyword || token() === SyntaxKind.DefaultKeyword;
                case ParsingContext.TypeMembers:
                    return lookAhead(isTypeMemberStart);
                case ParsingContext.ClassMembers:
                    // We allow semicolons as class elements (as specified by ES6) as long as we're
                    // not in error recovery.  If we're in error recovery, we don't want an errant
                    // semicolon to be treated as a class member (since they're almost always used
                    // for statements.
                    return lookAhead(isClassMemberStart) || (token() === SyntaxKind.SemicolonToken && !inErrorRecovery);
                case ParsingContext.EnumMembers:
                    // Include open bracket computed properties. This technically also lets in indexers,
                    // which would be a candidate for improved error reporting.
                    return token() === SyntaxKind.OpenBracketToken || isLiteralPropertyName();
                case ParsingContext.ObjectLiteralMembers:
                    switch (token()) {
                        case SyntaxKind.OpenBracketToken:
                        case SyntaxKind.AsteriskToken:
                        case SyntaxKind.DotDotDotToken:
                        case SyntaxKind.DotToken: // Not an object literal member, but don't want to close the object (see `tests/cases/fourslash/completionsDotInObjectLiteral.ts`)
                            return true;
                        default:
                            return isLiteralPropertyName();
                    }
                case ParsingContext.RestProperties:
                    return isLiteralPropertyName();
                case ParsingContext.ObjectBindingElements:
                    return token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.DotDotDotToken || isLiteralPropertyName();
                case ParsingContext.HeritageClauseElement:
                    // If we see `{ ... }` then only consume it as an expression if it is followed by `,` or `{`
                    // That way we won't consume the body of a class in its heritage clause.
                    if (token() === SyntaxKind.OpenBraceToken) {
                        return lookAhead(isValidHeritageClauseObjectLiteral);
                    }

                    if (!inErrorRecovery) {
                        return isStartOfLeftHandSideExpression() && !isHeritageClauseExtendsOrImplementsKeyword();
                    }
                    else {
                        // If we're in error recovery we tighten up what we're willing to match.
                        // That way we don't treat something like "this" as a valid heritage clause
                        // element during recovery.
                        return isIdentifier() && !isHeritageClauseExtendsOrImplementsKeyword();
                    }
                case ParsingContext.VariableDeclarations:
                    return isBindingIdentifierOrPrivateIdentifierOrPattern();
                case ParsingContext.ArrayBindingElements:
                    return token() === SyntaxKind.CommaToken || token() === SyntaxKind.DotDotDotToken || isBindingIdentifierOrPrivateIdentifierOrPattern();
                case ParsingContext.TypeParameters:
                    return isIdentifier();
                case ParsingContext.ArrayLiteralMembers:
                    switch (token()) {
                        case SyntaxKind.CommaToken:
                        case SyntaxKind.DotToken: // Not an array literal member, but don't want to close the array (see `tests/cases/fourslash/completionsDotInArrayLiteralInObjectLiteral.ts`)
                            return true;
                    }
                    // falls through
                case ParsingContext.ArgumentExpressions:
                    return token() === SyntaxKind.DotDotDotToken || isStartOfExpression();
                case ParsingContext.Parameters:
                    return isStartOfParameter(/*isJSDocParameter*/ false);
                case ParsingContext.JSDocParameters:
                    return isStartOfParameter(/*isJSDocParameter*/ true);
                case ParsingContext.TypeArguments:
                case ParsingContext.TupleElementTypes:
                    return token() === SyntaxKind.CommaToken || isStartOfType();
                case ParsingContext.HeritageClauses:
                    return isHeritageClause();
                case ParsingContext.ImportOrExportSpecifiers:
                    return tokenIsIdentifierOrKeyword(token());
                case ParsingContext.JsxAttributes:
                    return tokenIsIdentifierOrKeyword(token()) || token() === SyntaxKind.OpenBraceToken;
                case ParsingContext.JsxChildren:
                    return true;
            }

            return Debug.fail("Non-exhaustive case in 'isListElement'.");
        }
@@ L1997 @@
        // True if positioned at a list terminator
        function isListTerminator(kind: ParsingContext): boolean {
            if (token() === SyntaxKind.EndOfFileToken) {
                // Being at the end of the file ends all lists.
                return true;
            }

            switch (kind) {
                case ParsingContext.BlockStatements:
                case ParsingContext.SwitchClauses:
                case ParsingContext.TypeMembers:
                case ParsingContext.ClassMembers:
                case ParsingContext.EnumMembers:
                case ParsingContext.ObjectLiteralMembers:
                case ParsingContext.ObjectBindingElements:
                case ParsingContext.ImportOrExportSpecifiers:
                    return token() === SyntaxKind.CloseBraceToken;
                case ParsingContext.SwitchClauseStatements:
                    return token() === SyntaxKind.CloseBraceToken || token() === SyntaxKind.CaseKeyword || token() === SyntaxKind.DefaultKeyword;
                case ParsingContext.HeritageClauseElement:
                    return token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword;
                case ParsingContext.VariableDeclarations:
                    return isVariableDeclaratorListTerminator();
                case ParsingContext.TypeParameters:
                    // Tokens other than '>' are here for better error recovery
                    return token() === SyntaxKind.GreaterThanToken || token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword;
                case ParsingContext.ArgumentExpressions:
                    // Tokens other than ')' are here for better error recovery
                    return token() === SyntaxKind.CloseParenToken || token() === SyntaxKind.SemicolonToken;
                case ParsingContext.ArrayLiteralMembers:
                case ParsingContext.TupleElementTypes:
                case ParsingContext.ArrayBindingElements:
                    return token() === SyntaxKind.CloseBracketToken;
                case ParsingContext.JSDocParameters:
                case ParsingContext.Parameters:
                case ParsingContext.RestProperties:
                    // Tokens other than ')' and ']' (the latter for index signatures) are here for better error recovery
                    return token() === SyntaxKind.CloseParenToken || token() === SyntaxKind.CloseBracketToken /*|| token === SyntaxKind.OpenBraceToken*/;
                case ParsingContext.TypeArguments:
                    // All other tokens should cause the type-argument to terminate except comma token
                    return token() !== SyntaxKind.CommaToken;
                case ParsingContext.HeritageClauses:
                    return token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.CloseBraceToken;
                case ParsingContext.JsxAttributes:
                    return token() === SyntaxKind.GreaterThanToken || token() === SyntaxKind.SlashToken;
                case ParsingContext.JsxChildren:
                    return token() === SyntaxKind.LessThanToken && lookAhead(nextTokenIsSlash);
                default:
                    return false;
            }
        }
@@ L2087 @@
        // Parses a list of elements
        function parseList<T extends Node>(kind: ParsingContext, parseElement: () => T): NodeArray<T> {
@@ L2094 @@
            while (!isListTerminator(kind)) {
                if (isListElement(kind, /*inErrorRecovery*/ false)) {
                    list.push(parseListElement(kind, parseElement));

                    continue;
                }

                if (abortParsingListOrMoveToNextToken(kind)) {
                    break;
                }
            }

tsc.tsからのコールスタック [#4]

src/compiler/watch.ts
@@ L300 @@
    /**
     * Helper that emit files, report diagnostics and lists emitted and/or source files depending on compiler options
     */
    export function emitFilesAndReportErrors<T extends BuilderProgram>(
        program: Program | T,
        reportDiagnostic: DiagnosticReporter,
        write?: (s: string) => void,
        reportSummary?: ReportEmitErrorSummary,
        writeFile?: WriteFileCallback,
        cancellationToken?: CancellationToken,
        emitOnlyDtsFiles?: boolean,
        customTransformers?: CustomTransformers
    ) {
@@ L334 @@
        // Emit and report any errors we ran into.
        const emitResult = isListFilesOnly
            ? { emitSkipped: true, diagnostics: emptyArray }
            : program.emit(/*targetSourceFile*/ undefined, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers);
@@ L362 @@
    export function emitFilesAndReportErrorsAndGetExitStatus<T extends BuilderProgram>(
        program: Program | T,
        reportDiagnostic: DiagnosticReporter,
        write?: (s: string) => void,
        reportSummary?: ReportEmitErrorSummary,
        writeFile?: WriteFileCallback,
        cancellationToken?: CancellationToken,
        emitOnlyDtsFiles?: boolean,
        customTransformers?: CustomTransformers
    ) {
        const { emitResult, diagnostics } = emitFilesAndReportErrors(
            program,
            reportDiagnostic,
            write,
            reportSummary,
            writeFile,
            cancellationToken,
            emitOnlyDtsFiles,
            customTransformers
        );

tsc.tsからのコールスタック [#5]

emitter.ts
@@ L9 @@
    /*@internal*/
    /**
     * Iterates over the source files that are expected to have an emit output.
     *
     * @param host An EmitHost.
     * @param action The action to execute.
     * @param sourceFilesOrTargetSourceFile
     *   If an array, the full list of source files to emit.
     *   Else, calls `getSourceFilesToEmit` with the (optional) target source file to determine the list of source files to emit.
     */
    export function forEachEmittedFile<T>(
        host: EmitHost, action: (emitFileNames: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle | undefined) => T,
        sourceFilesOrTargetSourceFile?: readonly SourceFile[] | SourceFile,
        forceDtsEmit = false,
        onlyBuildInfo?: boolean,
        includeBuildInfo?: boolean) {
@@ L31 @@
                const result = action(getOutputPathsFor(bundle, host, forceDtsEmit), bundle);
@@ L298 @@
    /*@internal*/
    // targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature
    export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile | undefined, { scriptTransformers, declarationTransformers }: EmitTransformers, emitOnlyDtsFiles?: boolean, onlyBuildInfo?: boolean, forceDtsEmit?: boolean): EmitResult {
@@ L314 @@
        forEachEmittedFile(
            host,
            emitSourceFileOrBundle,
            getSourceFilesToEmit(host, targetSourceFile, forceDtsEmit),
            forceDtsEmit,
            onlyBuildInfo,
            !targetSourceFile
        );
@@ L333 @@
        function emitSourceFileOrBundle({ jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath }: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle | undefined) {
@@ L343 @@
            emitJsFileOrBundle(sourceFileOrBundle, jsFilePath, sourceMapFilePath, relativeToBuildInfo);
@@ L347 @@
            emitDeclarationFileOrBundle(sourceFileOrBundle, declarationFilePath, declarationMapPath, relativeToBuildInfo);
@@ L351 @@
            emitBuildInfo(bundleBuildInfo, buildInfoPath);
@@ L391 @@
        function emitJsFileOrBundle(
            sourceFileOrBundle: SourceFile | Bundle | undefined,
            jsFilePath: string | undefined,
            sourceMapFilePath: string | undefined,
            relativeToBuildInfo: (path: string) => string) {
@@ L405 @@
            // Transform the source files
            const transform = transformNodes(resolver, host, factory, compilerOptions, [sourceFileOrBundle], scriptTransformers, /*allowDtsFiles*/ false);
@@L422 @@
            const printer = createPrinter(printerOptions, {
                // resolver hooks
                hasGlobalName: resolver.hasGlobalName,

                // transform hooks
                onEmitNode: transform.emitNodeWithNotification,
                isEmitNotificationEnabled: transform.isEmitNotificationEnabled,
                substituteNode: transform.substituteNode,
            });
@@ L434 @@
            printSourceFileOrBundle(jsFilePath, sourceMapFilePath, transform.transformed[0], printer, compilerOptions);
@@ L531 @@
        function printSourceFileOrBundle(jsFilePath: string, sourceMapFilePath: string | undefined, sourceFileOrBundle: SourceFile | Bundle, printer: Printer, mapOptions: SourceMapOptions) {
@@ L550 @@
                printer.writeFile(sourceFile!, writer, sourceMapGenerator);
@@ L583 @@
            // Write the output file
            writeFile(host, emitterDiagnostics, jsFilePath, writer.getText(), !!compilerOptions.emitBOM, sourceFiles);
@@ L871 @@
    export function createPrinter(printerOptions: PrinterOptions = {}, handlers: PrintHandlers = {}): Printer {
@@ L1127 @@
        function writeFile(sourceFile: SourceFile, output: EmitTextWriter, sourceMapGenerator: SourceMapGenerator | undefined) {
@@ L1133 @@
            print(EmitHint.SourceFile, sourceFile, sourceFile);
@@ L1148 @@
        function print(hint: EmitHint, node: Node, sourceFile: SourceFile | undefined) {
@@ L1153 @@
            pipelineEmit(hint, node, /*parenthesizerRule*/ undefined);
@@ L1229 @@
        function pipelineEmit(emitHint: EmitHint, node: Node, parenthesizerRule?: (node: Node) => Node) {
            currentParenthesizerRule = parenthesizerRule;
            const pipelinePhase = getPipelinePhase(PipelinePhase.Notification, emitHint, node);
            pipelinePhase(emitHint, node);
            currentParenthesizerRule = undefined;
        }
@@ L1248 @@
        function getPipelinePhase(phase: PipelinePhase, emitHint: EmitHint, node: Node) {
            switch (phase) {
@@ L1273 @@
                case PipelinePhase.Emit:
                    return pipelineEmitWithHint;
@@ L1289 @@
        function pipelineEmitWithHint(hint: EmitHint, node: Node): void {
@@ L1298 @@
                pipelineEmitWithHintWorker(hint, node);
@@ L1305 @@
        function pipelineEmitWithHintWorker(hint: EmitHint, node: Node): void {
@@ L1314 @@
            if (hint === EmitHint.Unspecified) {
                switch (node.kind) {

tsc.tsからのコールスタック [#6]

transformer.ts
@@ L3 @@
    function getModuleTransformer(moduleKind: ModuleKind): TransformerFactory<SourceFile | Bundle> {
@@ L15 @@
                return transformModule;
@@ L30 @@
    export function getTransformers(compilerOptions: CompilerOptions, customTransformers?: CustomTransformers, emitOnlyDtsFiles?: boolean): EmitTransformers {
        return {
            scriptTransformers: getScriptTransformers(compilerOptions, customTransformers, emitOnlyDtsFiles),
            declarationTransformers: getDeclarationTransformers(customTransformers),
        };
    }
@@ L37 @@
    function getScriptTransformers(compilerOptions: CompilerOptions, customTransformers?: CustomTransformers, emitOnlyDtsFiles?: boolean) {
@@ L86 @@
        transformers.push(getModuleTransformer(moduleKind));
@@ L140 @@
    /**
     * Transforms an array of SourceFiles by passing them through each transformer.
     *
     * @param resolver The emit resolver provided by the checker.
     * @param host The emit host object used to interact with the file system.
     * @param options Compiler options to surface in the `TransformationContext`.
     * @param nodes An array of nodes to transform.
     * @param transforms An array of `TransformerFactory` callbacks.
     * @param allowDtsFiles A value indicating whether to allow the transformation of .d.ts files.
     */
    export function transformNodes<T extends Node>(resolver: EmitResolver | undefined, host: EmitHost | undefined, factory: NodeFactory, options: CompilerOptions, nodes: readonly T[], transformers: readonly TransformerFactory<T>[], allowDtsFiles: boolean): TransformationResult<T> {ts.Debug.log("transformer.ts ( L140) start transformNodes");
@@ L221 @@
        // Chain together and initialize each transformer.
        const transformersWithContext = transformers.map(t => t(context));
        const transformation = (node: T): T => {
            for (const transform of transformersWithContext) {
                node = transform(node);
            }
            return node;
        };
@@ L233 @@
        // Transform each node.
        const transformed: T[] = [];
        for (const node of nodes) {
            tracing?.push(tracing.Phase.Emit, "transformNodes", node.kind === SyntaxKind.SourceFile ? { path: (node as any as SourceFile).path } : { kind: node.kind, pos: node.pos, end: node.end });
            transformed.push((allowDtsFiles ? transformation : transformRoot)(node));
            tracing?.pop();
        }
module.ts
@@ L4 @@
    export function transformModule(context: TransformationContext) {
@@ L51 @@
        return chainBundle(context, transformSourceFile);
@@ L53 @@
        /**
         * Transforms the module aspects of a SourceFile.
         *
         * @param node The SourceFile node.
         */
        function transformSourceFile(node: SourceFile) {
@@ L70 @@
            // Perform the transformation.
            const transformModule = getTransformModuleDelegate(moduleKind);
            const updated = transformModule(node);
@@ L76 @@
            return updated;
utilities.ts
@@ L28 @@
    export function chainBundle(context: CoreTransformationContext, transformSourceFile: (x: SourceFile) => SourceFile): (x: SourceFile | Bundle) => SourceFile | Bundle {
        return transformSourceFileOrBundle;

        function transformSourceFileOrBundle(node: SourceFile | Bundle) {
            return node.kind === SyntaxKind.SourceFile ? transformSourceFile(node) : transformBundle(node);
        }

        function transformBundle(node: Bundle) {
            return context.factory.createBundle(map(node.sourceFiles, transformSourceFile), node.prepends);
        }
    }

tsc.tsからのコールスタック

src/compiler/scanner.ts
@@ L79 @@
    const textToKeywordObj: MapLike<KeywordSyntaxKind> = {
        abstract: SyntaxKind.AbstractKeyword,
        any: SyntaxKind.AnyKeyword,
        as: SyntaxKind.AsKeyword,
        asserts: SyntaxKind.AssertsKeyword,
        bigint: SyntaxKind.BigIntKeyword,
        boolean: SyntaxKind.BooleanKeyword,
        break: SyntaxKind.BreakKeyword,
        case: SyntaxKind.CaseKeyword,
        catch: SyntaxKind.CatchKeyword,
        class: SyntaxKind.ClassKeyword,
        continue: SyntaxKind.ContinueKeyword,
        const: SyntaxKind.ConstKeyword,
        ["" + "constructor"]: SyntaxKind.ConstructorKeyword,
        debugger: SyntaxKind.DebuggerKeyword,
        declare: SyntaxKind.DeclareKeyword,
        default: SyntaxKind.DefaultKeyword,
        delete: SyntaxKind.DeleteKeyword,
        do: SyntaxKind.DoKeyword,
        else: SyntaxKind.ElseKeyword,
        enum: SyntaxKind.EnumKeyword,
        export: SyntaxKind.ExportKeyword,
        extends: SyntaxKind.ExtendsKeyword,
        false: SyntaxKind.FalseKeyword,
        finally: SyntaxKind.FinallyKeyword,
        for: SyntaxKind.ForKeyword,
        from: SyntaxKind.FromKeyword,
        function: SyntaxKind.FunctionKeyword,
        get: SyntaxKind.GetKeyword,
        if: SyntaxKind.IfKeyword,
        implements: SyntaxKind.ImplementsKeyword,
        import: SyntaxKind.ImportKeyword,
        in: SyntaxKind.InKeyword,
        infer: SyntaxKind.InferKeyword,
        instanceof: SyntaxKind.InstanceOfKeyword,
        interface: SyntaxKind.InterfaceKeyword,
        intrinsic: SyntaxKind.IntrinsicKeyword,
        is: SyntaxKind.IsKeyword,
        keyof: SyntaxKind.KeyOfKeyword,
        let: SyntaxKind.LetKeyword,
        module: SyntaxKind.ModuleKeyword,
        namespace: SyntaxKind.NamespaceKeyword,
        never: SyntaxKind.NeverKeyword,
        new: SyntaxKind.NewKeyword,
        null: SyntaxKind.NullKeyword,
        number: SyntaxKind.NumberKeyword,
        object: SyntaxKind.ObjectKeyword,
        package: SyntaxKind.PackageKeyword,
        private: SyntaxKind.PrivateKeyword,
        protected: SyntaxKind.ProtectedKeyword,
        public: SyntaxKind.PublicKeyword,
        override: SyntaxKind.OverrideKeyword,
        readonly: SyntaxKind.ReadonlyKeyword,
        require: SyntaxKind.RequireKeyword,
        global: SyntaxKind.GlobalKeyword,
        return: SyntaxKind.ReturnKeyword,
        set: SyntaxKind.SetKeyword,
        static: SyntaxKind.StaticKeyword,
        string: SyntaxKind.StringKeyword,
        super: SyntaxKind.SuperKeyword,
        switch: SyntaxKind.SwitchKeyword,
        symbol: SyntaxKind.SymbolKeyword,
        this: SyntaxKind.ThisKeyword,
        throw: SyntaxKind.ThrowKeyword,
        true: SyntaxKind.TrueKeyword,
        try: SyntaxKind.TryKeyword,
        type: SyntaxKind.TypeKeyword,
        typeof: SyntaxKind.TypeOfKeyword,
        undefined: SyntaxKind.UndefinedKeyword,
        unique: SyntaxKind.UniqueKeyword,
        unknown: SyntaxKind.UnknownKeyword,
        var: SyntaxKind.VarKeyword,
        void: SyntaxKind.VoidKeyword,
        while: SyntaxKind.WhileKeyword,
        with: SyntaxKind.WithKeyword,
        yield: SyntaxKind.YieldKeyword,
        async: SyntaxKind.AsyncKeyword,
        await: SyntaxKind.AwaitKeyword,
        of: SyntaxKind.OfKeyword,
    };
@@ L162 @@
    const textToToken = new Map(getEntries({
        ...textToKeywordObj,
        "{": SyntaxKind.OpenBraceToken,
        "}": SyntaxKind.CloseBraceToken,
        "(": SyntaxKind.OpenParenToken,
        ")": SyntaxKind.CloseParenToken,
        "[": SyntaxKind.OpenBracketToken,
        "]": SyntaxKind.CloseBracketToken,
        ".": SyntaxKind.DotToken,
        "...": SyntaxKind.DotDotDotToken,
        ";": SyntaxKind.SemicolonToken,
        ",": SyntaxKind.CommaToken,
        "<": SyntaxKind.LessThanToken,
        ">": SyntaxKind.GreaterThanToken,
        "<=": SyntaxKind.LessThanEqualsToken,
        ">=": SyntaxKind.GreaterThanEqualsToken,
        "==": SyntaxKind.EqualsEqualsToken,
        "!=": SyntaxKind.ExclamationEqualsToken,
        "===": SyntaxKind.EqualsEqualsEqualsToken,
        "!==": SyntaxKind.ExclamationEqualsEqualsToken,
        "=>": SyntaxKind.EqualsGreaterThanToken,
        "+": SyntaxKind.PlusToken,
        "-": SyntaxKind.MinusToken,
        "**": SyntaxKind.AsteriskAsteriskToken,
        "*": SyntaxKind.AsteriskToken,
        "/": SyntaxKind.SlashToken,
        "%": SyntaxKind.PercentToken,
        "++": SyntaxKind.PlusPlusToken,
        "--": SyntaxKind.MinusMinusToken,
        "<<": SyntaxKind.LessThanLessThanToken,
        "</": SyntaxKind.LessThanSlashToken,
        ">>": SyntaxKind.GreaterThanGreaterThanToken,
        ">>>": SyntaxKind.GreaterThanGreaterThanGreaterThanToken,
        "&": SyntaxKind.AmpersandToken,
        "|": SyntaxKind.BarToken,
        "^": SyntaxKind.CaretToken,
        "!": SyntaxKind.ExclamationToken,
        "~": SyntaxKind.TildeToken,
        "&&": SyntaxKind.AmpersandAmpersandToken,
        "||": SyntaxKind.BarBarToken,
        "?": SyntaxKind.QuestionToken,
        "??": SyntaxKind.QuestionQuestionToken,
        "?.": SyntaxKind.QuestionDotToken,
        ":": SyntaxKind.ColonToken,
        "=": SyntaxKind.EqualsToken,
        "+=": SyntaxKind.PlusEqualsToken,
        "-=": SyntaxKind.MinusEqualsToken,
        "*=": SyntaxKind.AsteriskEqualsToken,
        "**=": SyntaxKind.AsteriskAsteriskEqualsToken,
        "/=": SyntaxKind.SlashEqualsToken,
        "%=": SyntaxKind.PercentEqualsToken,
        "<<=": SyntaxKind.LessThanLessThanEqualsToken,
        ">>=": SyntaxKind.GreaterThanGreaterThanEqualsToken,
        ">>>=": SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken,
        "&=": SyntaxKind.AmpersandEqualsToken,
        "|=": SyntaxKind.BarEqualsToken,
        "^=": SyntaxKind.CaretEqualsToken,
        "||=": SyntaxKind.BarBarEqualsToken,
        "&&=": SyntaxKind.AmpersandAmpersandEqualsToken,
        "??=": SyntaxKind.QuestionQuestionEqualsToken,
        "@": SyntaxKind.AtToken,
        "`": SyntaxKind.BacktickToken
    }));
ログインするとコメントできます