• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*@internal*/
2namespace ts {
3    export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, file: SourceFile | undefined): DiagnosticWithLocation[] | undefined {
4        const compilerOptions = host.getCompilerOptions();
5        const result = transformNodes(resolver, host, factory, compilerOptions, file ? [file] : filter(host.getSourceFiles(), isSourceFileNotJson), [transformDeclarations], /*allowDtsFiles*/ false);
6        return result.diagnostics;
7    }
8
9    function hasInternalAnnotation(range: CommentRange, currentSourceFile: SourceFile) {
10        const comment = currentSourceFile.text.substring(range.pos, range.end);
11        return stringContains(comment, "@internal");
12    }
13
14    export function isInternalDeclaration(node: Node, currentSourceFile: SourceFile) {
15        const parseTreeNode = getParseTreeNode(node);
16        if (parseTreeNode && parseTreeNode.kind === SyntaxKind.Parameter) {
17            const paramIdx = (parseTreeNode.parent as SignatureDeclaration).parameters.indexOf(parseTreeNode as ParameterDeclaration);
18            const previousSibling = paramIdx > 0 ? (parseTreeNode.parent as SignatureDeclaration).parameters[paramIdx - 1] : undefined;
19            const text = currentSourceFile.text;
20            const commentRanges = previousSibling
21                ? concatenate(
22                    // to handle
23                    // ... parameters, /* @internal */
24                    // public param: string
25                    getTrailingCommentRanges(text, skipTrivia(text, previousSibling.end + 1, /* stopAfterLineBreak */ false, /* stopAtComments */ true)),
26                    getLeadingCommentRanges(text, node.pos)
27                )
28                : getTrailingCommentRanges(text, skipTrivia(text, node.pos, /* stopAfterLineBreak */ false, /* stopAtComments */ true));
29            return commentRanges && commentRanges.length && hasInternalAnnotation(last(commentRanges), currentSourceFile);
30        }
31        const leadingCommentRanges = parseTreeNode && getLeadingCommentRangesOfNode(parseTreeNode, currentSourceFile);
32        return !!forEach(leadingCommentRanges, range => {
33            return hasInternalAnnotation(range, currentSourceFile);
34        });
35    }
36
37    const declarationEmitNodeBuilderFlags =
38        NodeBuilderFlags.MultilineObjectLiterals |
39        NodeBuilderFlags.WriteClassExpressionAsTypeLiteral |
40        NodeBuilderFlags.UseTypeOfFunction |
41        NodeBuilderFlags.UseStructuralFallback |
42        NodeBuilderFlags.AllowEmptyTuple |
43        NodeBuilderFlags.GenerateNamesForShadowedTypeParams |
44        NodeBuilderFlags.NoTruncation;
45
46    /**
47     * Transforms a ts file into a .d.ts or .d.ets file
48     * This process requires type information, which is retrieved through the emit resolver. Because of this,
49     * in many places this transformer assumes it will be operating on parse tree nodes directly.
50     * This means that _no transforms should be allowed to occur before this one_.
51     */
52
53    export function transformDeclarations(context: TransformationContext) {
54        const throwDiagnostic = () => Debug.fail("Diagnostic emitted without context");
55        let getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic = throwDiagnostic;
56        let needsDeclare = true;
57        let isBundledEmit = false;
58        let resultHasExternalModuleIndicator = false;
59        let needsScopeFixMarker = false;
60        let resultHasScopeMarker = false;
61        let enclosingDeclaration: Node;
62        let necessaryTypeReferences: Set<[specifier: string, mode: SourceFile["impliedNodeFormat"] | undefined]> | undefined;
63        let lateMarkedStatements: LateVisibilityPaintedStatement[] | undefined;
64        let lateStatementReplacementMap: ESMap<NodeId, VisitResult<LateVisibilityPaintedStatement | ExportAssignment>>;
65        let suppressNewDiagnosticContexts: boolean;
66        let exportedModulesFromDeclarationEmit: Symbol[] | undefined;
67
68        const { factory } = context;
69        const host = context.getEmitHost();
70        const symbolTracker: SymbolTracker = {
71            trackSymbol,
72            reportInaccessibleThisError,
73            reportInaccessibleUniqueSymbolError,
74            reportCyclicStructureError,
75            reportPrivateInBaseOfClassExpression,
76            reportLikelyUnsafeImportRequiredError,
77            reportTruncationError,
78            moduleResolverHost: host,
79            trackReferencedAmbientModule,
80            trackExternalModuleSymbolOfImportTypeNode,
81            reportNonlocalAugmentation,
82            reportNonSerializableProperty,
83            reportImportTypeNodeResolutionModeOverride,
84        };
85        let errorNameNode: DeclarationName | undefined;
86        let errorFallbackNode: Declaration | undefined;
87
88        let currentSourceFile: SourceFile;
89        let refs: ESMap<NodeId, SourceFile>;
90        let libs: ESMap<string, boolean>;
91        let emittedImports: readonly AnyImportSyntax[] | undefined; // must be declared in container so it can be `undefined` while transformer's first pass
92        const resolver = context.getEmitResolver();
93        const options = context.getCompilerOptions();
94        const { noResolve, stripInternal } = options;
95        return transformRoot;
96
97        function recordTypeReferenceDirectivesIfNecessary(typeReferenceDirectives: readonly [specifier: string, mode: SourceFile["impliedNodeFormat"] | undefined][] | undefined): void {
98            if (!typeReferenceDirectives) {
99                return;
100            }
101            necessaryTypeReferences = necessaryTypeReferences || new Set();
102            for (const ref of typeReferenceDirectives) {
103                necessaryTypeReferences.add(ref);
104            }
105        }
106
107        function trackReferencedAmbientModule(node: ModuleDeclaration, symbol: Symbol) {
108            // If it is visible via `// <reference types="..."/>`, then we should just use that
109            const directives = resolver.getTypeReferenceDirectivesForSymbol(symbol, SymbolFlags.All);
110            if (length(directives)) {
111                return recordTypeReferenceDirectivesIfNecessary(directives);
112            }
113            // Otherwise we should emit a path-based reference
114            const container = getSourceFileOfNode(node);
115            refs.set(getOriginalNodeId(container), container);
116        }
117
118        function handleSymbolAccessibilityError(symbolAccessibilityResult: SymbolAccessibilityResult) {
119            if (symbolAccessibilityResult.accessibility === SymbolAccessibility.Accessible) {
120                // Add aliases back onto the possible imports list if they're not there so we can try them again with updated visibility info
121                if (symbolAccessibilityResult && symbolAccessibilityResult.aliasesToMakeVisible) {
122                    if (!lateMarkedStatements) {
123                        lateMarkedStatements = symbolAccessibilityResult.aliasesToMakeVisible;
124                    }
125                    else {
126                        for (const ref of symbolAccessibilityResult.aliasesToMakeVisible) {
127                            pushIfUnique(lateMarkedStatements, ref);
128                        }
129                    }
130                }
131
132                // TODO: Do all these accessibility checks inside/after the first pass in the checker when declarations are enabled, if possible
133            }
134            else {
135                // Report error
136                const errorInfo = getSymbolAccessibilityDiagnostic(symbolAccessibilityResult);
137                if (errorInfo) {
138                    if (errorInfo.typeName) {
139                        context.addDiagnostic(createDiagnosticForNode(symbolAccessibilityResult.errorNode || errorInfo.errorNode,
140                            errorInfo.diagnosticMessage,
141                            getTextOfNode(errorInfo.typeName),
142                            symbolAccessibilityResult.errorSymbolName,
143                            symbolAccessibilityResult.errorModuleName));
144                    }
145                    else {
146                        context.addDiagnostic(createDiagnosticForNode(symbolAccessibilityResult.errorNode || errorInfo.errorNode,
147                            errorInfo.diagnosticMessage,
148                            symbolAccessibilityResult.errorSymbolName,
149                            symbolAccessibilityResult.errorModuleName));
150                    }
151                    return true;
152                }
153            }
154            return false;
155        }
156
157        function trackExternalModuleSymbolOfImportTypeNode(symbol: Symbol) {
158            if (!isBundledEmit) {
159                (exportedModulesFromDeclarationEmit || (exportedModulesFromDeclarationEmit = [])).push(symbol);
160            }
161        }
162
163        function trackSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags) {
164            if (symbol.flags & SymbolFlags.TypeParameter) return false;
165            const issuedDiagnostic = handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning, /*shouldComputeAliasesToMakeVisible*/ true));
166            recordTypeReferenceDirectivesIfNecessary(resolver.getTypeReferenceDirectivesForSymbol(symbol, meaning));
167            return issuedDiagnostic;
168        }
169
170        function reportPrivateInBaseOfClassExpression(propertyName: string) {
171            if (errorNameNode || errorFallbackNode) {
172                context.addDiagnostic(
173                    createDiagnosticForNode((errorNameNode || errorFallbackNode)!, Diagnostics.Property_0_of_exported_class_expression_may_not_be_private_or_protected, propertyName));
174            }
175        }
176
177        function errorDeclarationNameWithFallback() {
178            return errorNameNode ? declarationNameToString(errorNameNode) :
179                errorFallbackNode && getNameOfDeclaration(errorFallbackNode) ? declarationNameToString(getNameOfDeclaration(errorFallbackNode)) :
180                errorFallbackNode && isExportAssignment(errorFallbackNode) ? errorFallbackNode.isExportEquals ? "export=" : "default" :
181                "(Missing)"; // same fallback declarationNameToString uses when node is zero-width (ie, nameless)
182        }
183
184        function reportInaccessibleUniqueSymbolError() {
185            if (errorNameNode || errorFallbackNode) {
186                context.addDiagnostic(createDiagnosticForNode((errorNameNode || errorFallbackNode)!, Diagnostics.The_inferred_type_of_0_references_an_inaccessible_1_type_A_type_annotation_is_necessary,
187                    errorDeclarationNameWithFallback(),
188                    "unique symbol"));
189            }
190        }
191
192        function reportCyclicStructureError() {
193            if (errorNameNode || errorFallbackNode) {
194                context.addDiagnostic(createDiagnosticForNode((errorNameNode || errorFallbackNode)!, Diagnostics.The_inferred_type_of_0_references_a_type_with_a_cyclic_structure_which_cannot_be_trivially_serialized_A_type_annotation_is_necessary,
195                    errorDeclarationNameWithFallback()));
196            }
197        }
198
199        function reportInaccessibleThisError() {
200            if (errorNameNode || errorFallbackNode) {
201                context.addDiagnostic(createDiagnosticForNode((errorNameNode || errorFallbackNode)!, Diagnostics.The_inferred_type_of_0_references_an_inaccessible_1_type_A_type_annotation_is_necessary,
202                    errorDeclarationNameWithFallback(),
203                    "this"));
204            }
205        }
206
207        function reportLikelyUnsafeImportRequiredError(specifier: string) {
208            if (errorNameNode || errorFallbackNode) {
209                context.addDiagnostic(createDiagnosticForNode((errorNameNode || errorFallbackNode)!, Diagnostics.The_inferred_type_of_0_cannot_be_named_without_a_reference_to_1_This_is_likely_not_portable_A_type_annotation_is_necessary,
210                    errorDeclarationNameWithFallback(),
211                    specifier));
212            }
213        }
214
215        function reportTruncationError() {
216            if (errorNameNode || errorFallbackNode) {
217                context.addDiagnostic(createDiagnosticForNode((errorNameNode || errorFallbackNode)!, Diagnostics.The_inferred_type_of_this_node_exceeds_the_maximum_length_the_compiler_will_serialize_An_explicit_type_annotation_is_needed));
218            }
219        }
220
221        function reportNonlocalAugmentation(containingFile: SourceFile, parentSymbol: Symbol, symbol: Symbol) {
222            const primaryDeclaration = parentSymbol.declarations?.find(d => getSourceFileOfNode(d) === containingFile);
223            const augmentingDeclarations = filter(symbol.declarations, d => getSourceFileOfNode(d) !== containingFile);
224            if (primaryDeclaration && augmentingDeclarations) {
225                for (const augmentations of augmentingDeclarations) {
226                    context.addDiagnostic(addRelatedInfo(
227                        createDiagnosticForNode(augmentations, Diagnostics.Declaration_augments_declaration_in_another_file_This_cannot_be_serialized),
228                        createDiagnosticForNode(primaryDeclaration, Diagnostics.This_is_the_declaration_being_augmented_Consider_moving_the_augmenting_declaration_into_the_same_file)
229                    ));
230                }
231            }
232        }
233
234        function reportNonSerializableProperty(propertyName: string) {
235            if (errorNameNode || errorFallbackNode) {
236                context.addDiagnostic(createDiagnosticForNode((errorNameNode || errorFallbackNode)!, Diagnostics.The_type_of_this_node_cannot_be_serialized_because_its_property_0_cannot_be_serialized, propertyName));
237            }
238        }
239
240        function reportImportTypeNodeResolutionModeOverride() {
241            if (!isNightly() && (errorNameNode || errorFallbackNode)) {
242                context.addDiagnostic(createDiagnosticForNode((errorNameNode || errorFallbackNode)!, Diagnostics.The_type_of_this_expression_cannot_be_named_without_a_resolution_mode_assertion_which_is_an_unstable_feature_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next));
243            }
244        }
245
246        function transformDeclarationsForJS(sourceFile: SourceFile, bundled?: boolean) {
247            const oldDiag = getSymbolAccessibilityDiagnostic;
248            getSymbolAccessibilityDiagnostic = (s) => (s.errorNode && canProduceDiagnostics(s.errorNode) ? createGetSymbolAccessibilityDiagnosticForNode(s.errorNode)(s) : ({
249                diagnosticMessage: s.errorModuleName
250                    ? Diagnostics.Declaration_emit_for_this_file_requires_using_private_name_0_from_module_1_An_explicit_type_annotation_may_unblock_declaration_emit
251                    : Diagnostics.Declaration_emit_for_this_file_requires_using_private_name_0_An_explicit_type_annotation_may_unblock_declaration_emit,
252                errorNode: s.errorNode || sourceFile
253            }));
254            const result = resolver.getDeclarationStatementsForSourceFile(sourceFile, declarationEmitNodeBuilderFlags, symbolTracker, bundled);
255            getSymbolAccessibilityDiagnostic = oldDiag;
256            return result;
257        }
258
259        function transformRoot(node: Bundle): Bundle;
260        function transformRoot(node: SourceFile): SourceFile;
261        function transformRoot(node: SourceFile | Bundle): SourceFile | Bundle;
262        function transformRoot(node: SourceFile | Bundle) {
263            if (node.kind === SyntaxKind.SourceFile && node.isDeclarationFile) {
264                return node;
265            }
266
267            if (node.kind === SyntaxKind.Bundle) {
268                isBundledEmit = true;
269                refs = new Map();
270                libs = new Map();
271                let hasNoDefaultLib = false;
272                const bundle = factory.createBundle(map(node.sourceFiles,
273                    sourceFile => {
274                        if (sourceFile.isDeclarationFile) return undefined!; // Omit declaration files from bundle results, too // TODO: GH#18217
275                        hasNoDefaultLib = hasNoDefaultLib || sourceFile.hasNoDefaultLib;
276                        currentSourceFile = sourceFile;
277                        enclosingDeclaration = sourceFile;
278                        lateMarkedStatements = undefined;
279                        suppressNewDiagnosticContexts = false;
280                        lateStatementReplacementMap = new Map();
281                        getSymbolAccessibilityDiagnostic = throwDiagnostic;
282                        needsScopeFixMarker = false;
283                        resultHasScopeMarker = false;
284                        collectReferences(sourceFile, refs);
285                        collectLibs(sourceFile, libs);
286                        if (isExternalOrCommonJsModule(sourceFile) || isJsonSourceFile(sourceFile)) {
287                            resultHasExternalModuleIndicator = false; // unused in external module bundle emit (all external modules are within module blocks, therefore are known to be modules)
288                            needsDeclare = false;
289                            const statements = isSourceFileJS(sourceFile) ? factory.createNodeArray(transformDeclarationsForJS(sourceFile, /*bundled*/ true)) : visitNodes(sourceFile.statements, visitDeclarationStatements);
290                            const newFile = factory.updateSourceFile(sourceFile, [factory.createModuleDeclaration(
291                                [factory.createModifier(SyntaxKind.DeclareKeyword)],
292                                factory.createStringLiteral(getResolvedExternalModuleName(context.getEmitHost(), sourceFile)),
293                                factory.createModuleBlock(setTextRange(factory.createNodeArray(transformAndReplaceLatePaintedStatements(statements)), sourceFile.statements))
294                            )], /*isDeclarationFile*/ true, /*referencedFiles*/ [], /*typeReferences*/ [], /*hasNoDefaultLib*/ false, /*libReferences*/ []);
295                            return newFile;
296                        }
297                        needsDeclare = true;
298                        const updated = isSourceFileJS(sourceFile) ? factory.createNodeArray(transformDeclarationsForJS(sourceFile)) : visitNodes(sourceFile.statements, visitDeclarationStatements);
299                        return factory.updateSourceFile(sourceFile, transformAndReplaceLatePaintedStatements(updated), /*isDeclarationFile*/ true, /*referencedFiles*/ [], /*typeReferences*/ [], /*hasNoDefaultLib*/ false, /*libReferences*/ []);
300                    }
301                ), mapDefined(node.prepends, prepend => {
302                    if (prepend.kind === SyntaxKind.InputFiles) {
303                        const sourceFile = createUnparsedSourceFile(prepend, "dts", stripInternal);
304                        hasNoDefaultLib = hasNoDefaultLib || !!sourceFile.hasNoDefaultLib;
305                        collectReferences(sourceFile, refs);
306                        recordTypeReferenceDirectivesIfNecessary(map(sourceFile.typeReferenceDirectives, ref => [ref.fileName, ref.resolutionMode]));
307                        collectLibs(sourceFile, libs);
308                        return sourceFile;
309                    }
310                    return prepend;
311                }));
312                bundle.syntheticFileReferences = [];
313                bundle.syntheticTypeReferences = getFileReferencesForUsedTypeReferences();
314                bundle.syntheticLibReferences = getLibReferences();
315                bundle.hasNoDefaultLib = hasNoDefaultLib;
316                const outputFilePath = getDirectoryPath(normalizeSlashes(getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath!));
317                const referenceVisitor = mapReferencesIntoArray(bundle.syntheticFileReferences as FileReference[], outputFilePath);
318                refs.forEach(referenceVisitor);
319                return bundle;
320            }
321
322            // Single source file
323            needsDeclare = true;
324            needsScopeFixMarker = false;
325            resultHasScopeMarker = false;
326            enclosingDeclaration = node;
327            currentSourceFile = node;
328            getSymbolAccessibilityDiagnostic = throwDiagnostic;
329            isBundledEmit = false;
330            resultHasExternalModuleIndicator = false;
331            suppressNewDiagnosticContexts = false;
332            lateMarkedStatements = undefined;
333            lateStatementReplacementMap = new Map();
334            necessaryTypeReferences = undefined;
335            refs = collectReferences(currentSourceFile, new Map());
336            libs = collectLibs(currentSourceFile, new Map());
337            const references: FileReference[] = [];
338            const outputFilePath = getDirectoryPath(normalizeSlashes(getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath!));
339            const referenceVisitor = mapReferencesIntoArray(references, outputFilePath);
340            let combinedStatements: NodeArray<Statement>;
341            if (isSourceFileJS(currentSourceFile)) {
342                combinedStatements = factory.createNodeArray(transformDeclarationsForJS(node));
343                refs.forEach(referenceVisitor);
344                emittedImports = filter(combinedStatements, isAnyImportSyntax);
345            }
346            else {
347                const statements = visitNodes(node.statements, visitDeclarationStatements);
348                combinedStatements = setTextRange(factory.createNodeArray(transformAndReplaceLatePaintedStatements(statements)), node.statements);
349                refs.forEach(referenceVisitor);
350                emittedImports = filter(combinedStatements, isAnyImportSyntax);
351                if (isExternalModule(node) && (!resultHasExternalModuleIndicator || (needsScopeFixMarker && !resultHasScopeMarker))) {
352                    combinedStatements = setTextRange(factory.createNodeArray([...combinedStatements, createEmptyExports(factory)]), combinedStatements);
353                }
354            }
355            const updated = factory.updateSourceFile(node, combinedStatements, /*isDeclarationFile*/ true, references, getFileReferencesForUsedTypeReferences(), node.hasNoDefaultLib, getLibReferences());
356            updated.exportedModulesFromDeclarationEmit = exportedModulesFromDeclarationEmit;
357            return updated;
358
359            function getLibReferences() {
360                return map(arrayFrom(libs.keys()), lib => ({ fileName: lib, pos: -1, end: -1 }));
361            }
362
363            function getFileReferencesForUsedTypeReferences() {
364                return necessaryTypeReferences ? mapDefined(arrayFrom(necessaryTypeReferences.keys()), getFileReferenceForSpecifierModeTuple) : [];
365            }
366
367            function getFileReferenceForSpecifierModeTuple([typeName, mode]: [specifier: string, mode: SourceFile["impliedNodeFormat"] | undefined]): FileReference | undefined {
368                // Elide type references for which we have imports
369                if (emittedImports) {
370                    for (const importStatement of emittedImports) {
371                        if (isImportEqualsDeclaration(importStatement) && isExternalModuleReference(importStatement.moduleReference)) {
372                            const expr = importStatement.moduleReference.expression;
373                            if (isStringLiteralLike(expr) && expr.text === typeName) {
374                                return undefined;
375                            }
376                        }
377                        else if (isImportDeclaration(importStatement) && isStringLiteral(importStatement.moduleSpecifier) && importStatement.moduleSpecifier.text === typeName) {
378                            return undefined;
379                        }
380                    }
381                }
382                return { fileName: typeName, pos: -1, end: -1, ...(mode ? { resolutionMode: mode } : undefined) };
383            }
384
385            function mapReferencesIntoArray(references: FileReference[], outputFilePath: string): (file: SourceFile) => void {
386                return file => {
387                    let declFileName: string;
388                    if (file.isDeclarationFile) { // Neither decl files or js should have their refs changed
389                        declFileName = file.fileName;
390                    }
391                    else {
392                        if (isBundledEmit && contains((node as Bundle).sourceFiles, file)) return; // Omit references to files which are being merged
393                        const paths = getOutputPathsFor(file, host, /*forceDtsPaths*/ true);
394                        declFileName = paths.declarationFilePath || paths.jsFilePath || file.fileName;
395                    }
396
397                    if (declFileName) {
398                        const specifier = moduleSpecifiers.getModuleSpecifier(
399                            options,
400                            currentSourceFile,
401                            toPath(outputFilePath, host.getCurrentDirectory(), host.getCanonicalFileName),
402                            toPath(declFileName, host.getCurrentDirectory(), host.getCanonicalFileName),
403                            host,
404                        );
405                        if (!pathIsRelative(specifier)) {
406                            // If some compiler option/symlink/whatever allows access to the file containing the ambient module declaration
407                            // via a non-relative name, emit a type reference directive to that non-relative name, rather than
408                            // a relative path to the declaration file
409                            recordTypeReferenceDirectivesIfNecessary([[specifier, /*mode*/ undefined]]);
410                            return;
411                        }
412
413                        let fileName = getRelativePathToDirectoryOrUrl(
414                            outputFilePath,
415                            declFileName,
416                            host.getCurrentDirectory(),
417                            host.getCanonicalFileName,
418                            /*isAbsolutePathAnUrl*/ false
419                        );
420                        if (startsWith(fileName, "./") && hasExtension(fileName)) {
421                            fileName = fileName.substring(2);
422                        }
423
424                        // omit references to files from node_modules or oh_modules (npm may disambiguate module
425                        // references when installing this package, making the path is unreliable).
426                        if (isNodeModulesReference(fileName) || (isOhpm(options.packageManagerType) && isOHModulesReference(fileName))) {
427                            return;
428                        }
429
430                        references.push({ pos: -1, end: -1, fileName });
431                    }
432                };
433            }
434        }
435
436        function isNodeModulesReference(fileName: string): boolean {
437            return startsWith(fileName, "node_modules/") || pathContainsNodeModules(fileName);
438        }
439
440        function collectReferences(sourceFile: SourceFile | UnparsedSource, ret: ESMap<NodeId, SourceFile>) {
441            if (noResolve || (!isUnparsedSource(sourceFile) && isSourceFileJS(sourceFile))) return ret;
442            forEach(sourceFile.referencedFiles, f => {
443                const elem = host.getSourceFileFromReference(sourceFile, f);
444                if (elem) {
445                    ret.set(getOriginalNodeId(elem), elem);
446                }
447            });
448            return ret;
449        }
450
451        function collectLibs(sourceFile: SourceFile | UnparsedSource, ret: ESMap<string, boolean>) {
452            forEach(sourceFile.libReferenceDirectives, ref => {
453                const lib = host.getLibFileFromReference(ref);
454                if (lib) {
455                    ret.set(toFileNameLowerCase(ref.fileName), true);
456                }
457            });
458            return ret;
459        }
460
461        function filterBindingPatternInitializersAndRenamings(name: BindingName) {
462            if (name.kind === SyntaxKind.Identifier) {
463                return name;
464            }
465            else {
466                if (name.kind === SyntaxKind.ArrayBindingPattern) {
467                    return factory.updateArrayBindingPattern(name, visitNodes(name.elements, visitBindingElement));
468                }
469                else {
470                    return factory.updateObjectBindingPattern(name, visitNodes(name.elements, visitBindingElement));
471                }
472            }
473
474            function visitBindingElement<T extends ArrayBindingElement>(elem: T): T;
475            function visitBindingElement(elem: ArrayBindingElement): ArrayBindingElement {
476                if (elem.kind === SyntaxKind.OmittedExpression) {
477                    return elem;
478                }
479                if (elem.propertyName && isIdentifier(elem.propertyName) && isIdentifier(elem.name) && !elem.symbol.isReferenced) {
480                   // Unnecessary property renaming is forbidden in types, so remove renaming
481                    return factory.updateBindingElement(
482                        elem,
483                        elem.dotDotDotToken,
484                        /* propertyName */ undefined,
485                        elem.propertyName,
486                        shouldPrintWithInitializer(elem) ? elem.initializer : undefined
487                    );
488                }
489                return factory.updateBindingElement(
490                    elem,
491                    elem.dotDotDotToken,
492                    elem.propertyName,
493                    filterBindingPatternInitializersAndRenamings(elem.name),
494                    shouldPrintWithInitializer(elem) ? elem.initializer : undefined
495                );
496            }
497        }
498
499        function ensureParameter(p: ParameterDeclaration, modifierMask?: ModifierFlags, type?: TypeNode): ParameterDeclaration {
500            let oldDiag: typeof getSymbolAccessibilityDiagnostic | undefined;
501            if (!suppressNewDiagnosticContexts) {
502                oldDiag = getSymbolAccessibilityDiagnostic;
503                getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(p);
504            }
505            const newParam = factory.updateParameterDeclaration(
506                p,
507                maskModifiers(p, modifierMask),
508                p.dotDotDotToken,
509                filterBindingPatternInitializersAndRenamings(p.name),
510                resolver.isOptionalParameter(p) ? (p.questionToken || factory.createToken(SyntaxKind.QuestionToken)) : undefined,
511                ensureType(p, type || p.type, /*ignorePrivate*/ true), // Ignore private param props, since this type is going straight back into a param
512                ensureNoInitializer(p)
513            );
514            if (!suppressNewDiagnosticContexts) {
515                getSymbolAccessibilityDiagnostic = oldDiag!;
516            }
517            return newParam;
518        }
519
520        function shouldPrintWithInitializer(node: Node) {
521            return canHaveLiteralInitializer(node) && resolver.isLiteralConstDeclaration(getParseTreeNode(node) as CanHaveLiteralInitializer); // TODO: Make safe
522        }
523
524        function ensureNoInitializer(node: CanHaveLiteralInitializer) {
525            if (shouldPrintWithInitializer(node)) {
526                return resolver.createLiteralConstValue(getParseTreeNode(node) as CanHaveLiteralInitializer, symbolTracker); // TODO: Make safe
527            }
528            return undefined;
529        }
530
531        type HasInferredType =
532            | FunctionDeclaration
533            | MethodDeclaration
534            | GetAccessorDeclaration
535            | SetAccessorDeclaration
536            | BindingElement
537            | ConstructSignatureDeclaration
538            | VariableDeclaration
539            | MethodSignature
540            | CallSignatureDeclaration
541            | ParameterDeclaration
542            | PropertyDeclaration
543            | AnnotationPropertyDeclaration
544            | PropertySignature;
545
546        function ensureType(node: HasInferredType, type: TypeNode | undefined, ignorePrivate?: boolean): TypeNode | undefined {
547            if (!ignorePrivate && hasEffectiveModifier(node, ModifierFlags.Private)) {
548                // Private nodes emit no types (except private parameter properties, whose parameter types are actually visible)
549                return;
550            }
551            if (shouldPrintWithInitializer(node)) {
552                // Literal const declarations will have an initializer ensured rather than a type
553                return;
554            }
555            if (type !== undefined && isTypeReferenceNode(type) && type.typeName.virtual) {
556                return;
557            }
558            const shouldUseResolverType = node.kind === SyntaxKind.Parameter &&
559                (resolver.isRequiredInitializedParameter(node) ||
560                 resolver.isOptionalUninitializedParameterProperty(node));
561            if (type && !shouldUseResolverType) {
562                return visitNode(type, visitDeclarationSubtree);
563            }
564            if (!getParseTreeNode(node)) {
565                return type ? visitNode(type, visitDeclarationSubtree) : factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
566            }
567            if (node.kind === SyntaxKind.SetAccessor) {
568                // Set accessors with no associated type node (from it's param or get accessor return) are `any` since they are never contextually typed right now
569                // (The inferred type here will be void, but the old declaration emitter printed `any`, so this replicates that)
570                return factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
571            }
572            errorNameNode = node.name;
573            let oldDiag: typeof getSymbolAccessibilityDiagnostic;
574            if (!suppressNewDiagnosticContexts) {
575                oldDiag = getSymbolAccessibilityDiagnostic;
576                getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(node);
577            }
578            if (node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement) {
579                return cleanup(resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker));
580            }
581            if (node.kind === SyntaxKind.Parameter
582                || node.kind === SyntaxKind.PropertyDeclaration
583                || node.kind === SyntaxKind.PropertySignature
584                || node.kind === SyntaxKind.AnnotationPropertyDeclaration) {
585                if (isPropertySignature(node) || !node.initializer) return cleanup(resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker, shouldUseResolverType));
586                return cleanup(resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker, shouldUseResolverType) || resolver.createTypeOfExpression(node.initializer, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker));
587            }
588            return cleanup(resolver.createReturnTypeOfSignatureDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker));
589
590            function cleanup(returnValue: TypeNode | undefined) {
591                errorNameNode = undefined;
592                if (!suppressNewDiagnosticContexts) {
593                    getSymbolAccessibilityDiagnostic = oldDiag;
594                }
595                return returnValue || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
596            }
597        }
598
599        function isDeclarationAndNotVisible(node: NamedDeclaration) {
600            node = getParseTreeNode(node) as NamedDeclaration;
601            switch (node.kind) {
602                case SyntaxKind.FunctionDeclaration:
603                case SyntaxKind.ModuleDeclaration:
604                case SyntaxKind.InterfaceDeclaration:
605                case SyntaxKind.ClassDeclaration:
606                case SyntaxKind.StructDeclaration:
607                case SyntaxKind.TypeAliasDeclaration:
608                case SyntaxKind.EnumDeclaration:
609                    return !resolver.isDeclarationVisible(node);
610                // The following should be doing their own visibility checks based on filtering their members
611                case SyntaxKind.VariableDeclaration:
612                    return !getBindingNameVisible(node as VariableDeclaration);
613                case SyntaxKind.ImportEqualsDeclaration:
614                case SyntaxKind.ImportDeclaration:
615                case SyntaxKind.ExportDeclaration:
616                case SyntaxKind.ExportAssignment:
617                    return false;
618                case SyntaxKind.ClassStaticBlockDeclaration:
619                    return true;
620            }
621            return false;
622        }
623
624        // If the ExpandoFunctionDeclaration have multiple overloads, then we only need to emit properties for the last one.
625        function shouldEmitFunctionProperties(input: FunctionDeclaration) {
626            if (input.body) {
627                return true;
628            }
629
630            const overloadSignatures = input.symbol.declarations?.filter(decl => isFunctionDeclaration(decl) && !decl.body);
631            return !overloadSignatures || overloadSignatures.indexOf(input) === overloadSignatures.length - 1;
632        }
633
634        function getBindingNameVisible(elem: BindingElement | VariableDeclaration | OmittedExpression): boolean {
635            if (isOmittedExpression(elem)) {
636                return false;
637            }
638            if (isBindingPattern(elem.name)) {
639                // If any child binding pattern element has been marked visible (usually by collect linked aliases), then this is visible
640                return some(elem.name.elements, getBindingNameVisible);
641            }
642            else {
643                return resolver.isDeclarationVisible(elem);
644            }
645        }
646
647        function updateParamsList(node: Node, params: NodeArray<ParameterDeclaration>, modifierMask?: ModifierFlags) {
648            if (hasEffectiveModifier(node, ModifierFlags.Private)) {
649                return undefined!; // TODO: GH#18217
650            }
651            const newParams = map(params, p => ensureParameter(p, modifierMask));
652            if (!newParams) {
653                return undefined!; // TODO: GH#18217
654            }
655            return factory.createNodeArray(newParams, params.hasTrailingComma);
656        }
657
658        function updateAccessorParamsList(input: AccessorDeclaration, isPrivate: boolean) {
659            let newParams: ParameterDeclaration[] | undefined;
660            if (!isPrivate) {
661                const thisParameter = getThisParameter(input);
662                if (thisParameter) {
663                    newParams = [ensureParameter(thisParameter)];
664                }
665            }
666            if (isSetAccessorDeclaration(input)) {
667                let newValueParameter: ParameterDeclaration | undefined;
668                if (!isPrivate) {
669                    const valueParameter = getSetAccessorValueParameter(input);
670                    if (valueParameter) {
671                        const accessorType = getTypeAnnotationFromAllAccessorDeclarations(input, resolver.getAllAccessorDeclarations(input));
672                        newValueParameter = ensureParameter(valueParameter, /*modifierMask*/ undefined, accessorType);
673                    }
674                }
675                if (!newValueParameter) {
676                    newValueParameter = factory.createParameterDeclaration(
677                        /*modifiers*/ undefined,
678                        /*dotDotDotToken*/ undefined,
679                        "value"
680                    );
681                }
682                newParams = append(newParams, newValueParameter);
683            }
684            return factory.createNodeArray(newParams || emptyArray);
685        }
686
687        function ensureTypeParams(node: Node, params: NodeArray<TypeParameterDeclaration> | undefined) {
688            return hasEffectiveModifier(node, ModifierFlags.Private) ? undefined : visitNodes(params, visitDeclarationSubtree);
689        }
690
691        function isEnclosingDeclaration(node: Node) {
692            return isSourceFile(node)
693                || isTypeAliasDeclaration(node)
694                || isModuleDeclaration(node)
695                || isClassDeclaration(node)
696                || isStructDeclaration(node)
697                || isAnnotationDeclaration(node)
698                || isInterfaceDeclaration(node)
699                || isFunctionLike(node)
700                || isIndexSignatureDeclaration(node)
701                || isMappedTypeNode(node);
702        }
703
704        function checkEntityNameVisibility(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node) {
705            const visibilityResult = resolver.isEntityNameVisible(entityName, enclosingDeclaration);
706            handleSymbolAccessibilityError(visibilityResult);
707            recordTypeReferenceDirectivesIfNecessary(resolver.getTypeReferenceDirectivesForEntityName(entityName));
708        }
709
710        function preserveJsDoc<T extends Node>(updated: T, original: Node): T {
711            if (hasJSDocNodes(updated) && hasJSDocNodes(original)) {
712                updated.jsDoc = original.jsDoc;
713            }
714            return setCommentRange(updated, getCommentRange(original));
715        }
716
717        function rewriteModuleSpecifier<T extends Node>(parent: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode, input: T | undefined): T | StringLiteral {
718            if (!input) return undefined!; // TODO: GH#18217
719            resultHasExternalModuleIndicator = resultHasExternalModuleIndicator || (parent.kind !== SyntaxKind.ModuleDeclaration && parent.kind !== SyntaxKind.ImportType);
720            if (isStringLiteralLike(input)) {
721                if (isBundledEmit) {
722                    const newName = getExternalModuleNameFromDeclaration(context.getEmitHost(), resolver, parent);
723                    if (newName) {
724                        return factory.createStringLiteral(newName);
725                    }
726                }
727                else {
728                    const symbol = resolver.getSymbolOfExternalModuleSpecifier(input);
729                    if (symbol) {
730                        (exportedModulesFromDeclarationEmit || (exportedModulesFromDeclarationEmit = [])).push(symbol);
731                    }
732                }
733            }
734            return input;
735        }
736
737        function transformImportEqualsDeclaration(decl: ImportEqualsDeclaration) {
738            if (!resolver.isDeclarationVisible(decl)) return;
739            if (decl.moduleReference.kind === SyntaxKind.ExternalModuleReference) {
740                // Rewrite external module names if necessary
741                const specifier = getExternalModuleImportEqualsDeclarationExpression(decl);
742                return factory.updateImportEqualsDeclaration(
743                    decl,
744                    decl.modifiers,
745                    decl.isTypeOnly,
746                    decl.name,
747                    factory.updateExternalModuleReference(decl.moduleReference, rewriteModuleSpecifier(decl, specifier))
748                );
749            }
750            else {
751                const oldDiag = getSymbolAccessibilityDiagnostic;
752                getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(decl);
753                checkEntityNameVisibility(decl.moduleReference, enclosingDeclaration);
754                getSymbolAccessibilityDiagnostic = oldDiag;
755                return decl;
756            }
757        }
758
759        function transformImportDeclaration(decl: ImportDeclaration) {
760            if (!decl.importClause) {
761                // import "mod" - possibly needed for side effects? (global interface patches, module augmentations, etc)
762                return factory.updateImportDeclaration(
763                    decl,
764                    decl.modifiers,
765                    decl.importClause,
766                    rewriteModuleSpecifier(decl, decl.moduleSpecifier),
767                    getResolutionModeOverrideForClauseInNightly(decl.assertClause)
768                );
769            }
770            // The `importClause` visibility corresponds to the default's visibility.
771            const visibleDefaultBinding = decl.importClause && decl.importClause.name && resolver.isDeclarationVisible(decl.importClause) ? decl.importClause.name : undefined;
772            if (!decl.importClause.namedBindings) {
773                // No named bindings (either namespace or list), meaning the import is just default or should be elided
774                return visibleDefaultBinding && factory.updateImportDeclaration(decl, decl.modifiers, factory.updateImportClause(
775                    decl.importClause,
776                    decl.importClause.isTypeOnly,
777                    visibleDefaultBinding,
778                    /*namedBindings*/ undefined,
779                ), rewriteModuleSpecifier(decl, decl.moduleSpecifier), getResolutionModeOverrideForClauseInNightly(decl.assertClause));
780            }
781            if (decl.importClause.namedBindings.kind === SyntaxKind.NamespaceImport) {
782                // Namespace import (optionally with visible default)
783                const namedBindings = resolver.isDeclarationVisible(decl.importClause.namedBindings) ? decl.importClause.namedBindings : /*namedBindings*/ undefined;
784                return visibleDefaultBinding || namedBindings ? factory.updateImportDeclaration(decl, decl.modifiers, factory.updateImportClause(
785                    decl.importClause,
786                    decl.importClause.isTypeOnly,
787                    visibleDefaultBinding,
788                    namedBindings,
789                ), rewriteModuleSpecifier(decl, decl.moduleSpecifier), getResolutionModeOverrideForClauseInNightly(decl.assertClause)) : undefined;
790            }
791            // Named imports (optionally with visible default)
792            const bindingList = mapDefined(decl.importClause.namedBindings.elements, b => resolver.isDeclarationVisible(b) ? b : undefined);
793            if ((bindingList && bindingList.length) || visibleDefaultBinding) {
794                return factory.updateImportDeclaration(
795                    decl,
796                    decl.modifiers,
797                    factory.updateImportClause(
798                        decl.importClause,
799                        decl.importClause.isTypeOnly,
800                        visibleDefaultBinding,
801                        bindingList && bindingList.length ? factory.updateNamedImports(decl.importClause.namedBindings, bindingList) : undefined,
802                    ),
803                    rewriteModuleSpecifier(decl, decl.moduleSpecifier),
804                    getResolutionModeOverrideForClauseInNightly(decl.assertClause)
805                );
806            }
807            // Augmentation of export depends on import
808            if (resolver.isImportRequiredByAugmentation(decl)) {
809                return factory.updateImportDeclaration(
810                    decl,
811                    decl.modifiers,
812                    /*importClause*/ undefined,
813                    rewriteModuleSpecifier(decl, decl.moduleSpecifier),
814                    getResolutionModeOverrideForClauseInNightly(decl.assertClause)
815                );
816            }
817            // Nothing visible
818        }
819
820        function getResolutionModeOverrideForClauseInNightly(assertClause: AssertClause | undefined) {
821            const mode = getResolutionModeOverrideForClause(assertClause);
822            if (mode !== undefined) {
823                if (!isNightly()) {
824                    context.addDiagnostic(createDiagnosticForNode(assertClause!, Diagnostics.resolution_mode_assertions_are_unstable_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next));
825                }
826                return assertClause;
827            }
828            return undefined;
829        }
830
831        function transformAndReplaceLatePaintedStatements(statements: NodeArray<Statement>): NodeArray<Statement> {
832            // This is a `while` loop because `handleSymbolAccessibilityError` can see additional import aliases marked as visible during
833            // error handling which must now be included in the output and themselves checked for errors.
834            // For example:
835            // ```
836            // module A {
837            //   export module Q {}
838            //   import B = Q;
839            //   import C = B;
840            //   export import D = C;
841            // }
842            // ```
843            // In such a scenario, only Q and D are initially visible, but we don't consider imports as private names - instead we say they if they are referenced they must
844            // be recorded. So while checking D's visibility we mark C as visible, then we must check C which in turn marks B, completing the chain of
845            // dependent imports and allowing a valid declaration file output. Today, this dependent alias marking only happens for internal import aliases.
846            while (length(lateMarkedStatements)) {
847                const i = lateMarkedStatements!.shift()!;
848                if (!isLateVisibilityPaintedStatement(i)) {
849                    return Debug.fail(`Late replaced statement was found which is not handled by the declaration transformer!: ${Debug.formatSyntaxKind((i as Node).kind)}`);
850                }
851                const priorNeedsDeclare = needsDeclare;
852                needsDeclare = i.parent && isSourceFile(i.parent) && !(isExternalModule(i.parent) && isBundledEmit);
853                const result = transformTopLevelDeclaration(i);
854                needsDeclare = priorNeedsDeclare;
855                lateStatementReplacementMap.set(getOriginalNodeId(i), result);
856            }
857
858            // And lastly, we need to get the final form of all those indetermine import declarations from before and add them to the output list
859            // (and remove them from the set to examine for outter declarations)
860            return visitNodes(statements, visitLateVisibilityMarkedStatements);
861
862            function visitLateVisibilityMarkedStatements(statement: Statement) {
863                if (isLateVisibilityPaintedStatement(statement)) {
864                    const key = getOriginalNodeId(statement);
865                    if (lateStatementReplacementMap.has(key)) {
866                        const result = lateStatementReplacementMap.get(key);
867                        lateStatementReplacementMap.delete(key);
868                        if (result) {
869                            if (isArray(result) ? some(result, needsScopeMarker) : needsScopeMarker(result)) {
870                                // Top-level declarations in .d.ts files are always considered exported even without a modifier unless there's an export assignment or specifier
871                                needsScopeFixMarker = true;
872                            }
873                            if (isSourceFile(statement.parent) && (isArray(result) ? some(result, isExternalModuleIndicator) : isExternalModuleIndicator(result))) {
874                                resultHasExternalModuleIndicator = true;
875                            }
876                        }
877                        return result;
878                    }
879                }
880                return statement;
881            }
882        }
883
884        function visitDeclarationSubtree(input: Node): VisitResult<Node> {
885            if (shouldStripInternal(input)) return;
886            if (isDeclaration(input)) {
887                if (isDeclarationAndNotVisible(input)) return;
888                if (hasDynamicName(input) && !resolver.isLateBound(getParseTreeNode(input) as Declaration)) {
889                    return;
890                }
891            }
892
893            // Elide implementation signatures from overload sets
894            if (isFunctionLike(input) && resolver.isImplementationOfOverload(input)) return;
895
896            // Elide semicolon class statements
897            if (isSemicolonClassElement(input)) return;
898
899            let previousEnclosingDeclaration: typeof enclosingDeclaration;
900            if (isEnclosingDeclaration(input)) {
901                previousEnclosingDeclaration = enclosingDeclaration;
902                enclosingDeclaration = input as Declaration;
903            }
904            const oldDiag = getSymbolAccessibilityDiagnostic;
905
906            // Setup diagnostic-related flags before first potential `cleanup` call, otherwise
907            // We'd see a TDZ violation at runtime
908            const canProduceDiagnostic = canProduceDiagnostics(input);
909            const oldWithinObjectLiteralType = suppressNewDiagnosticContexts;
910            let shouldEnterSuppressNewDiagnosticsContextContext = ((input.kind === SyntaxKind.TypeLiteral || input.kind === SyntaxKind.MappedType) && input.parent.kind !== SyntaxKind.TypeAliasDeclaration);
911
912            // Emit methods which are private as properties with no type information
913            if (isMethodDeclaration(input) || isMethodSignature(input)) {
914                if (hasEffectiveModifier(input, ModifierFlags.Private)) {
915                    if (input.symbol && input.symbol.declarations && input.symbol.declarations[0] !== input) return; // Elide all but the first overload
916                    return cleanup(factory.createPropertyDeclaration(ensureModifiers(input), input.name, /*questionToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined));
917                }
918            }
919
920            if (canProduceDiagnostic && !suppressNewDiagnosticContexts) {
921                getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(input);
922            }
923
924            if (isTypeQueryNode(input)) {
925                checkEntityNameVisibility(input.exprName, enclosingDeclaration);
926            }
927
928            if (shouldEnterSuppressNewDiagnosticsContextContext) {
929                // We stop making new diagnostic contexts within object literal types. Unless it's an object type on the RHS of a type alias declaration. Then we do.
930                suppressNewDiagnosticContexts = true;
931            }
932
933            if (isProcessedComponent(input)) {
934                switch (input.kind) {
935                    case SyntaxKind.ExpressionWithTypeArguments: {
936                        if ((isEntityName(input.expression) || isEntityNameExpression(input.expression))) {
937                            checkEntityNameVisibility(input.expression, enclosingDeclaration);
938                        }
939                        const node = visitEachChild(input, visitDeclarationSubtree, context);
940                        return cleanup(factory.updateExpressionWithTypeArguments(node, node.expression, node.typeArguments));
941                    }
942                    case SyntaxKind.TypeReference: {
943                        checkEntityNameVisibility(input.typeName, enclosingDeclaration);
944                        const node = visitEachChild(input, visitDeclarationSubtree, context);
945                        return cleanup(factory.updateTypeReferenceNode(node, node.typeName, node.typeArguments));
946                    }
947                    case SyntaxKind.ConstructSignature:
948                        return cleanup(factory.updateConstructSignature(
949                            input,
950                            ensureTypeParams(input, input.typeParameters),
951                            updateParamsList(input, input.parameters),
952                            ensureType(input, input.type)
953                        ));
954                    case SyntaxKind.Constructor: {
955                        // A constructor declaration may not have a type annotation
956                        const ctor = factory.createConstructorDeclaration(
957                            /*modifiers*/ ensureModifiers(input),
958                            updateParamsList(input, input.parameters, ModifierFlags.None),
959                            /*body*/ undefined
960                        );
961                        return cleanup(ctor);
962                    }
963                    case SyntaxKind.MethodDeclaration: {
964                        if (isPrivateIdentifier(input.name)) {
965                            return cleanup(/*returnValue*/ undefined);
966                        }
967                        let reservedDecorators = getReservedDecoratorsOfStructDeclaration(input, host);
968
969                        const sig = factory.createMethodDeclaration(
970                            concatenateDecoratorsAndModifiers(reservedDecorators, ensureModifiers(input)),
971                            /*asteriskToken*/ undefined,
972                            input.name,
973                            input.questionToken,
974                            inEtsStylesContext(input, host) ? undefined : ensureTypeParams(input, input.typeParameters),
975                            updateParamsList(input, input.parameters),
976                            ensureType(input, input.type),
977                            /*body*/ undefined
978                        );
979                        return cleanup(sig);
980                    }
981                    case SyntaxKind.GetAccessor: {
982                        if (isPrivateIdentifier(input.name)) {
983                            return cleanup(/*returnValue*/ undefined);
984                        }
985                        const accessorType = getTypeAnnotationFromAllAccessorDeclarations(input, resolver.getAllAccessorDeclarations(input));
986                        return cleanup(factory.updateGetAccessorDeclaration(
987                            input,
988                            ensureModifiers(input),
989                            input.name,
990                            updateAccessorParamsList(input, hasEffectiveModifier(input, ModifierFlags.Private)),
991                            ensureType(input, accessorType),
992                            /*body*/ undefined));
993                    }
994                    case SyntaxKind.SetAccessor: {
995                        if (isPrivateIdentifier(input.name)) {
996                            return cleanup(/*returnValue*/ undefined);
997                        }
998                        return cleanup(factory.updateSetAccessorDeclaration(
999                            input,
1000                            ensureModifiers(input),
1001                            input.name,
1002                            updateAccessorParamsList(input, hasEffectiveModifier(input, ModifierFlags.Private)),
1003                            /*body*/ undefined));
1004                    }
1005                    case SyntaxKind.PropertyDeclaration:
1006                        if (isPrivateIdentifier(input.name)) {
1007                            return cleanup(/*returnValue*/ undefined);
1008                        }
1009                        let reservedDecorators = getReservedDecoratorsOfStructDeclaration(input, host);
1010
1011                        return cleanup(factory.updatePropertyDeclaration(
1012                            input,
1013                            concatenateDecoratorsAndModifiers(reservedDecorators, ensureModifiers(input)),
1014                            input.name,
1015                            input.questionToken,
1016                            ensureType(input, input.type),
1017                            ensureNoInitializer(input)
1018                        ));
1019                    case SyntaxKind.AnnotationPropertyDeclaration:
1020                        return cleanup(factory.updateAnnotationPropertyDeclaration(
1021                            input,
1022                            input.name,
1023                            ensureType(input, input.type),
1024                            input.initializer,
1025                        ));
1026                    case SyntaxKind.PropertySignature:
1027                        if (isPrivateIdentifier(input.name)) {
1028                            return cleanup(/*returnValue*/ undefined);
1029                        }
1030                        return cleanup(factory.updatePropertySignature(
1031                            input,
1032                            ensureModifiers(input),
1033                            input.name,
1034                            input.questionToken,
1035                            ensureType(input, input.type)
1036                        ));
1037                    case SyntaxKind.MethodSignature: {
1038                        if (isPrivateIdentifier(input.name)) {
1039                            return cleanup(/*returnValue*/ undefined);
1040                        }
1041                        return cleanup(factory.updateMethodSignature(
1042                            input,
1043                            ensureModifiers(input),
1044                            input.name,
1045                            input.questionToken,
1046                            ensureTypeParams(input, input.typeParameters),
1047                            updateParamsList(input, input.parameters),
1048                            ensureType(input, input.type)
1049                        ));
1050                    }
1051                    case SyntaxKind.CallSignature: {
1052                        return cleanup(factory.updateCallSignature(
1053                            input,
1054                            ensureTypeParams(input, input.typeParameters),
1055                            updateParamsList(input, input.parameters),
1056                            ensureType(input, input.type)
1057                        ));
1058                    }
1059                    case SyntaxKind.IndexSignature: {
1060                        return cleanup(factory.updateIndexSignature(
1061                            input,
1062                            ensureModifiers(input),
1063                            updateParamsList(input, input.parameters),
1064                            visitNode(input.type, visitDeclarationSubtree) || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword)
1065                        ));
1066                    }
1067                    case SyntaxKind.VariableDeclaration: {
1068                        if (isBindingPattern(input.name)) {
1069                            return recreateBindingPattern(input.name);
1070                        }
1071                        shouldEnterSuppressNewDiagnosticsContextContext = true;
1072                        suppressNewDiagnosticContexts = true; // Variable declaration types also suppress new diagnostic contexts, provided the contexts wouldn't be made for binding pattern types
1073                        return cleanup(factory.updateVariableDeclaration(input, input.name, /*exclamationToken*/ undefined, ensureType(input, input.type), ensureNoInitializer(input)));
1074                    }
1075                    case SyntaxKind.TypeParameter: {
1076                        if (isPrivateMethodTypeParameter(input) && (input.default || input.constraint)) {
1077                            return cleanup(factory.updateTypeParameterDeclaration(input, input.modifiers, input.name, /*constraint*/ undefined, /*defaultType*/ undefined));
1078                        }
1079                        return cleanup(visitEachChild(input, visitDeclarationSubtree, context));
1080                    }
1081                    case SyntaxKind.ConditionalType: {
1082                        // We have to process conditional types in a special way because for visibility purposes we need to push a new enclosingDeclaration
1083                        // just for the `infer` types in the true branch. It's an implicit declaration scope that only applies to _part_ of the type.
1084                        const checkType = visitNode(input.checkType, visitDeclarationSubtree);
1085                        const extendsType = visitNode(input.extendsType, visitDeclarationSubtree);
1086                        const oldEnclosingDecl = enclosingDeclaration;
1087                        enclosingDeclaration = input.trueType;
1088                        const trueType = visitNode(input.trueType, visitDeclarationSubtree);
1089                        enclosingDeclaration = oldEnclosingDecl;
1090                        const falseType = visitNode(input.falseType, visitDeclarationSubtree);
1091                        return cleanup(factory.updateConditionalTypeNode(input, checkType, extendsType, trueType, falseType));
1092                    }
1093                    case SyntaxKind.FunctionType: {
1094                        return cleanup(factory.updateFunctionTypeNode(input, visitNodes(input.typeParameters, visitDeclarationSubtree), updateParamsList(input, input.parameters), visitNode(input.type, visitDeclarationSubtree)));
1095                    }
1096                    case SyntaxKind.ConstructorType: {
1097                        return cleanup(factory.updateConstructorTypeNode(input, ensureModifiers(input), visitNodes(input.typeParameters, visitDeclarationSubtree), updateParamsList(input, input.parameters), visitNode(input.type, visitDeclarationSubtree)));
1098                    }
1099                    case SyntaxKind.ImportType: {
1100                        if (!isLiteralImportTypeNode(input)) return cleanup(input);
1101                        return cleanup(factory.updateImportTypeNode(
1102                            input,
1103                            factory.updateLiteralTypeNode(input.argument, rewriteModuleSpecifier(input, input.argument.literal)),
1104                            input.assertions,
1105                            input.qualifier,
1106                            visitNodes(input.typeArguments, visitDeclarationSubtree, isTypeNode),
1107                            input.isTypeOf
1108                        ));
1109                    }
1110                    default: Debug.assertNever(input, `Attempted to process unhandled node kind: ${Debug.formatSyntaxKind((input as Node).kind)}`);
1111                }
1112            }
1113
1114            if (isTupleTypeNode(input) && (getLineAndCharacterOfPosition(currentSourceFile, input.pos).line === getLineAndCharacterOfPosition(currentSourceFile, input.end).line)) {
1115                setEmitFlags(input, EmitFlags.SingleLine);
1116            }
1117
1118            return cleanup(visitEachChild(input, visitDeclarationSubtree, context));
1119
1120            function cleanup<T extends Node>(returnValue: T | undefined): T | undefined {
1121                if (returnValue && canProduceDiagnostic && hasDynamicName(input as Declaration)) {
1122                    checkName(input);
1123                }
1124                if (isEnclosingDeclaration(input)) {
1125                    enclosingDeclaration = previousEnclosingDeclaration;
1126                }
1127                if (canProduceDiagnostic && !suppressNewDiagnosticContexts) {
1128                    getSymbolAccessibilityDiagnostic = oldDiag;
1129                }
1130                if (shouldEnterSuppressNewDiagnosticsContextContext) {
1131                    suppressNewDiagnosticContexts = oldWithinObjectLiteralType;
1132                }
1133                if (returnValue === input) {
1134                    return returnValue;
1135                }
1136                return returnValue && setOriginalNode(preserveJsDoc(returnValue, input), input);
1137            }
1138        }
1139
1140        function isPrivateMethodTypeParameter(node: TypeParameterDeclaration) {
1141            return node.parent.kind === SyntaxKind.MethodDeclaration && hasEffectiveModifier(node.parent, ModifierFlags.Private);
1142        }
1143
1144        function visitDeclarationStatements(input: Node): VisitResult<Node> {
1145            if (!isPreservedDeclarationStatement(input)) {
1146                // return undefined for unmatched kinds to omit them from the tree
1147                return;
1148            }
1149            if (shouldStripInternal(input)) return;
1150
1151            switch (input.kind) {
1152                case SyntaxKind.ExportDeclaration: {
1153                    if (isSourceFile(input.parent)) {
1154                        resultHasExternalModuleIndicator = true;
1155                    }
1156                    resultHasScopeMarker = true;
1157                    // Always visible if the parent node isn't dropped for being not visible
1158                    // Rewrite external module names if necessary
1159                    return factory.updateExportDeclaration(
1160                        input,
1161                        input.modifiers,
1162                        input.isTypeOnly,
1163                        input.exportClause,
1164                        rewriteModuleSpecifier(input, input.moduleSpecifier),
1165                        getResolutionModeOverrideForClause(input.assertClause) ? input.assertClause : undefined
1166                    );
1167                }
1168                case SyntaxKind.ExportAssignment: {
1169                    // Always visible if the parent node isn't dropped for being not visible
1170                    if (isSourceFile(input.parent)) {
1171                        resultHasExternalModuleIndicator = true;
1172                    }
1173                    resultHasScopeMarker = true;
1174                    if (input.expression.kind === SyntaxKind.Identifier) {
1175                        return input;
1176                    }
1177                    else {
1178                        const newId = factory.createUniqueName("_default", GeneratedIdentifierFlags.Optimistic);
1179                        getSymbolAccessibilityDiagnostic = () => ({
1180                            diagnosticMessage: Diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0,
1181                            errorNode: input
1182                        });
1183                        errorFallbackNode = input;
1184                        const varDecl = factory.createVariableDeclaration(newId, /*exclamationToken*/ undefined, resolver.createTypeOfExpression(input.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), /*initializer*/ undefined);
1185                        errorFallbackNode = undefined;
1186                        const statement = factory.createVariableStatement(needsDeclare ? [factory.createModifier(SyntaxKind.DeclareKeyword)] : [], factory.createVariableDeclarationList([varDecl], NodeFlags.Const));
1187
1188                        preserveJsDoc(statement, input);
1189                        removeAllComments(input);
1190                        return [statement, factory.updateExportAssignment(input, input.modifiers, newId)];
1191                    }
1192                }
1193            }
1194
1195            const result = transformTopLevelDeclaration(input);
1196            // Don't actually transform yet; just leave as original node - will be elided/swapped by late pass
1197            lateStatementReplacementMap.set(getOriginalNodeId(input), result);
1198            return input;
1199        }
1200
1201        function stripExportModifiers(statement: Statement): Statement {
1202            if (isImportEqualsDeclaration(statement) || hasEffectiveModifier(statement, ModifierFlags.Default) || !canHaveModifiers(statement)) {
1203                // `export import` statements should remain as-is, as imports are _not_ implicitly exported in an ambient namespace
1204                // Likewise, `export default` classes and the like and just be `default`, so we preserve their `export` modifiers, too
1205                return statement;
1206            }
1207
1208            const modifiers = factory.createModifiersFromModifierFlags(getEffectiveModifierFlags(statement) & (ModifierFlags.All ^ ModifierFlags.Export));
1209            return factory.updateModifiers(statement, modifiers);
1210        }
1211
1212        function transformTopLevelDeclaration(input: LateVisibilityPaintedStatement) {
1213            if (lateMarkedStatements) {
1214                while (orderedRemoveItem(lateMarkedStatements, input));
1215            }
1216            if (shouldStripInternal(input)) return;
1217            switch (input.kind) {
1218                case SyntaxKind.ImportEqualsDeclaration: {
1219                    return transformImportEqualsDeclaration(input);
1220                }
1221                case SyntaxKind.ImportDeclaration: {
1222                    return transformImportDeclaration(input);
1223                }
1224            }
1225            if (isDeclaration(input) && isDeclarationAndNotVisible(input)) return;
1226
1227            // Elide implementation signatures from overload sets
1228            if (isFunctionLike(input) && resolver.isImplementationOfOverload(input)) return;
1229
1230            let previousEnclosingDeclaration: typeof enclosingDeclaration;
1231            if (isEnclosingDeclaration(input)) {
1232                previousEnclosingDeclaration = enclosingDeclaration;
1233                enclosingDeclaration = input as Declaration;
1234            }
1235
1236            const canProdiceDiagnostic = canProduceDiagnostics(input);
1237            const oldDiag = getSymbolAccessibilityDiagnostic;
1238            if (canProdiceDiagnostic) {
1239                getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(input as DeclarationDiagnosticProducing);
1240            }
1241
1242            const previousNeedsDeclare = needsDeclare;
1243            switch (input.kind) {
1244                case SyntaxKind.TypeAliasDeclaration: {
1245                    needsDeclare = false;
1246                    const clean = cleanup(factory.updateTypeAliasDeclaration(
1247                        input,
1248                        ensureModifiers(input),
1249                        input.name,
1250                        visitNodes(input.typeParameters, visitDeclarationSubtree, isTypeParameterDeclaration),
1251                        visitNode(input.type, visitDeclarationSubtree, isTypeNode)
1252                    ));
1253                    // Default factory will set illegalDecorators in updateTypeAliasDeclaration, add extra set here to avoid abnormal case.
1254                    if (isSendableFunctionOrType(input)) {
1255                        (clean as Mutable<TypeAliasDeclaration>).illegalDecorators = input.illegalDecorators;
1256                    }
1257                    needsDeclare = previousNeedsDeclare;
1258                    return clean;
1259                }
1260                case SyntaxKind.InterfaceDeclaration: {
1261                    return cleanup(factory.updateInterfaceDeclaration(
1262                        input,
1263                        ensureModifiers(input),
1264                        input.name,
1265                        ensureTypeParams(input, input.typeParameters),
1266                        transformHeritageClauses(input.heritageClauses),
1267                        visitNodes(input.members, visitDeclarationSubtree)
1268                    ));
1269                }
1270                case SyntaxKind.FunctionDeclaration: {
1271                    // Generators lose their generator-ness, excepting their return type
1272                    const clean = cleanup(factory.updateFunctionDeclaration(
1273                        input,
1274                        ensureModifiers(input),
1275                        /*asteriskToken*/ undefined,
1276                        input.name,
1277                        inEtsStylesContext(input, host) ? undefined : ensureTypeParams(input, input.typeParameters),
1278                        updateParamsList(input, input.parameters),
1279                        ensureType(input, input.type),
1280                        /*body*/ undefined
1281                    ));
1282                    if (isSendableFunctionOrType(input)) {
1283                        (clean as Mutable<FunctionDeclaration>).illegalDecorators = input.illegalDecorators;
1284                    }
1285                    else if (isInEtsFile(input)) {
1286                        const reservedDecorators = getEffectiveDecorators(input.illegalDecorators, host);
1287                        (clean as Mutable<FunctionDeclaration>).illegalDecorators = factory.createNodeArray(reservedDecorators);
1288                    }
1289                    if (clean && resolver.isExpandoFunctionDeclaration(input) && shouldEmitFunctionProperties(input)) {
1290                        const props = resolver.getPropertiesOfContainerFunction(input);
1291                        // Use parseNodeFactory so it is usable as an enclosing declaration
1292                        const fakespace = parseNodeFactory.createModuleDeclaration(/*modifiers*/ undefined, clean.name || factory.createIdentifier("_default"), factory.createModuleBlock([]), NodeFlags.Namespace);
1293                        setParent(fakespace, enclosingDeclaration as SourceFile | NamespaceDeclaration);
1294                        fakespace.locals = createSymbolTable(props);
1295                        fakespace.symbol = props[0].parent!;
1296                        const exportMappings: [Identifier, string][] = [];
1297                        let declarations: (VariableStatement | ExportDeclaration)[] = mapDefined(props, p => {
1298                            if (!p.valueDeclaration || !isPropertyAccessExpression(p.valueDeclaration)) {
1299                                return undefined; // TODO GH#33569: Handle element access expressions that created late bound names (rather than silently omitting them)
1300                            }
1301                            getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(p.valueDeclaration);
1302                            const type = resolver.createTypeOfDeclaration(p.valueDeclaration, fakespace, declarationEmitNodeBuilderFlags, symbolTracker);
1303                            getSymbolAccessibilityDiagnostic = oldDiag;
1304                            const nameStr = unescapeLeadingUnderscores(p.escapedName);
1305                            const isNonContextualKeywordName = isStringANonContextualKeyword(nameStr);
1306                            const name = isNonContextualKeywordName ? factory.getGeneratedNameForNode(p.valueDeclaration) : factory.createIdentifier(nameStr);
1307                            if (isNonContextualKeywordName) {
1308                                exportMappings.push([name, nameStr]);
1309                            }
1310                            const varDecl = factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, type, /*initializer*/ undefined);
1311                            return factory.createVariableStatement(isNonContextualKeywordName ? undefined : [factory.createToken(SyntaxKind.ExportKeyword)], factory.createVariableDeclarationList([varDecl]));
1312                        });
1313                        if (!exportMappings.length) {
1314                            declarations = mapDefined(declarations, declaration => factory.updateModifiers(declaration, ModifierFlags.None));
1315                        }
1316                        else {
1317                            declarations.push(factory.createExportDeclaration(
1318                                /*modifiers*/ undefined,
1319                                /*isTypeOnly*/ false,
1320                                factory.createNamedExports(map(exportMappings, ([gen, exp]) => {
1321                                    return factory.createExportSpecifier(/*isTypeOnly*/ false, gen, exp);
1322                                }))
1323                            ));
1324                        }
1325                        const namespaceDecl = factory.createModuleDeclaration(ensureModifiers(input), input.name!, factory.createModuleBlock(declarations), NodeFlags.Namespace);
1326                        if (!hasEffectiveModifier(clean, ModifierFlags.Default)) {
1327                            return [clean, namespaceDecl];
1328                        }
1329
1330                        const modifiers = factory.createModifiersFromModifierFlags((getEffectiveModifierFlags(clean) & ~ModifierFlags.ExportDefault) | ModifierFlags.Ambient);
1331
1332                        const cleanDeclaration = factory.updateFunctionDeclaration(
1333                            clean,
1334                            modifiers,
1335                            /*asteriskToken*/ undefined,
1336                            clean.name,
1337                            clean.typeParameters,
1338                            clean.parameters,
1339                            clean.type,
1340                            /*body*/ undefined
1341                        );
1342                        if (isInEtsFile(input)) {
1343                            const reservedDecorators = getEffectiveDecorators(clean.illegalDecorators, host);
1344                            (cleanDeclaration as Mutable<FunctionDeclaration>).illegalDecorators = factory.createNodeArray(reservedDecorators);
1345                        }
1346                        const namespaceDeclaration = factory.updateModuleDeclaration(
1347                            namespaceDecl,
1348                            modifiers,
1349                            namespaceDecl.name,
1350                            namespaceDecl.body
1351                        );
1352
1353                        const exportDefaultDeclaration = factory.createExportAssignment(
1354                            /*modifiers*/ undefined,
1355                            /*isExportEquals*/ false,
1356                            namespaceDecl.name
1357                        );
1358
1359                        if (isSourceFile(input.parent)) {
1360                            resultHasExternalModuleIndicator = true;
1361                        }
1362                        resultHasScopeMarker = true;
1363
1364                        return [cleanDeclaration, namespaceDeclaration, exportDefaultDeclaration];
1365                    }
1366                    else {
1367                        return clean;
1368                    }
1369                }
1370                case SyntaxKind.ModuleDeclaration: {
1371                    needsDeclare = false;
1372                    const inner = input.body;
1373                    if (inner && inner.kind === SyntaxKind.ModuleBlock) {
1374                        const oldNeedsScopeFix = needsScopeFixMarker;
1375                        const oldHasScopeFix = resultHasScopeMarker;
1376                        resultHasScopeMarker = false;
1377                        needsScopeFixMarker = false;
1378                        const statements = visitNodes(inner.statements, visitDeclarationStatements);
1379                        let lateStatements = transformAndReplaceLatePaintedStatements(statements);
1380                        if (input.flags & NodeFlags.Ambient) {
1381                            needsScopeFixMarker = false; // If it was `declare`'d everything is implicitly exported already, ignore late printed "privates"
1382                        }
1383                        // With the final list of statements, there are 3 possibilities:
1384                        // 1. There's an export assignment or export declaration in the namespace - do nothing
1385                        // 2. Everything is exported and there are no export assignments or export declarations - strip all export modifiers
1386                        // 3. Some things are exported, some are not, and there's no marker - add an empty marker
1387                        if (!isGlobalScopeAugmentation(input) && !hasScopeMarker(lateStatements) && !resultHasScopeMarker) {
1388                            if (needsScopeFixMarker) {
1389                                lateStatements = factory.createNodeArray([...lateStatements, createEmptyExports(factory)]);
1390                            }
1391                            else {
1392                                lateStatements = visitNodes(lateStatements, stripExportModifiers);
1393                            }
1394                        }
1395                        const body = factory.updateModuleBlock(inner, lateStatements);
1396                        needsDeclare = previousNeedsDeclare;
1397                        needsScopeFixMarker = oldNeedsScopeFix;
1398                        resultHasScopeMarker = oldHasScopeFix;
1399                        const mods = ensureModifiers(input);
1400                        return cleanup(factory.updateModuleDeclaration(
1401                            input,
1402                            mods,
1403                            isExternalModuleAugmentation(input) ? rewriteModuleSpecifier(input, input.name) : input.name,
1404                            body
1405                        ));
1406                    }
1407                    else {
1408                        needsDeclare = previousNeedsDeclare;
1409                        const mods = ensureModifiers(input);
1410                        needsDeclare = false;
1411                        visitNode(inner, visitDeclarationStatements);
1412                        // eagerly transform nested namespaces (the nesting doesn't need any elision or painting done)
1413                        const id = getOriginalNodeId(inner!); // TODO: GH#18217
1414                        const body = lateStatementReplacementMap.get(id);
1415                        lateStatementReplacementMap.delete(id);
1416                        return cleanup(factory.updateModuleDeclaration(
1417                            input,
1418                            mods,
1419                            input.name,
1420                            body as ModuleBody
1421                        ));
1422                    }
1423                }
1424                case SyntaxKind.StructDeclaration: {
1425                    errorNameNode = input.name;
1426                    errorFallbackNode = input;
1427
1428                    const decorators = ensureEtsDecorators(input, host);
1429                    const modifiers = factory.createNodeArray(ensureModifiers(input));
1430                    const typeParameters = ensureTypeParams(input, input.typeParameters);
1431                    const memberNodes = visitNodes(input.members, visitDeclarationSubtree, undefined, 1);
1432                    const members = factory.createNodeArray(memberNodes);
1433
1434                    return cleanup(factory.updateStructDeclaration(
1435                        input,
1436                        concatenateDecoratorsAndModifiers(decorators, modifiers),
1437                        input.name,
1438                        typeParameters,
1439                        /*heritageClauses*/ undefined,
1440                        members
1441                    ));
1442                }
1443                case SyntaxKind.AnnotationDeclaration: {
1444                    errorNameNode = input.name;
1445                    errorFallbackNode = input;
1446
1447                    const modifiers = factory.createNodeArray(ensureModifiers(input));
1448                    const memberNodes = visitNodes(input.members, visitDeclarationSubtree);
1449                    const members = factory.createNodeArray(memberNodes);
1450
1451                    return cleanup(factory.updateAnnotationDeclaration(
1452                        input,
1453                        modifiers,
1454                        input.name,
1455                        members
1456                    ));
1457                }
1458                case SyntaxKind.ClassDeclaration: {
1459                    errorNameNode = input.name;
1460                    errorFallbackNode = input;
1461                    const modifiers = factory.createNodeArray(ensureModifiers(input));
1462                    const typeParameters = ensureTypeParams(input, input.typeParameters);
1463                    const ctor = getFirstConstructorWithBody(input);
1464                    let parameterProperties: readonly PropertyDeclaration[] | undefined;
1465                    if (ctor) {
1466                        const oldDiag = getSymbolAccessibilityDiagnostic;
1467                        parameterProperties = compact(flatMap(ctor.parameters, (param) => {
1468                            if (!hasSyntacticModifier(param, ModifierFlags.ParameterPropertyModifier) || shouldStripInternal(param)) return;
1469                            getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(param);
1470                            if (param.name.kind === SyntaxKind.Identifier) {
1471                                return preserveJsDoc(factory.createPropertyDeclaration(
1472                                    ensureModifiers(param),
1473                                    param.name,
1474                                    param.questionToken,
1475                                    ensureType(param, param.type),
1476                                    ensureNoInitializer(param)), param);
1477                            }
1478                            else {
1479                                // Pattern - this is currently an error, but we emit declarations for it somewhat correctly
1480                                return walkBindingPattern(param.name);
1481                            }
1482
1483                            function walkBindingPattern(pattern: BindingPattern) {
1484                                let elems: PropertyDeclaration[] | undefined;
1485                                for (const elem of pattern.elements) {
1486                                    if (isOmittedExpression(elem)) continue;
1487                                    if (isBindingPattern(elem.name)) {
1488                                        elems = concatenate(elems, walkBindingPattern(elem.name));
1489                                    }
1490                                    elems = elems || [];
1491                                    elems.push(factory.createPropertyDeclaration(
1492                                        ensureModifiers(param),
1493                                        elem.name as Identifier,
1494                                        /*questionToken*/ undefined,
1495                                        ensureType(elem, /*type*/ undefined),
1496                                        /*initializer*/ undefined
1497                                    ));
1498                                }
1499                                return elems;
1500                            }
1501                        }));
1502                        getSymbolAccessibilityDiagnostic = oldDiag;
1503                    }
1504
1505                    const hasPrivateIdentifier = some(input.members, member => !!member.name && isPrivateIdentifier(member.name));
1506                    // When the class has at least one private identifier, create a unique constant identifier to retain the nominal typing behavior
1507                    // Prevents other classes with the same public members from being used in place of the current class
1508                    const privateIdentifier = hasPrivateIdentifier ? [
1509                        factory.createPropertyDeclaration(
1510                            /*modifiers*/ undefined,
1511                            factory.createPrivateIdentifier("#private"),
1512                            /*questionToken*/ undefined,
1513                            /*type*/ undefined,
1514                            /*initializer*/ undefined
1515                        )
1516                    ] : undefined;
1517                    const memberNodes = concatenate(concatenate(privateIdentifier, parameterProperties), visitNodes(input.members, visitDeclarationSubtree));
1518                    const members = factory.createNodeArray(memberNodes);
1519
1520                    const extendsClause = getEffectiveBaseTypeNode(input);
1521                    if (extendsClause && !isEntityNameExpression(extendsClause.expression) && extendsClause.expression.kind !== SyntaxKind.NullKeyword) {
1522                        // We must add a temporary declaration for the extends clause expression
1523
1524                        const oldId = input.name ? unescapeLeadingUnderscores(input.name.escapedText) : "default";
1525                        const newId = factory.createUniqueName(`${oldId}_base`, GeneratedIdentifierFlags.Optimistic);
1526                        getSymbolAccessibilityDiagnostic = () => ({
1527                            diagnosticMessage: Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1,
1528                            errorNode: extendsClause,
1529                            typeName: input.name
1530                        });
1531                        const varDecl = factory.createVariableDeclaration(newId, /*exclamationToken*/ undefined, resolver.createTypeOfExpression(extendsClause.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), /*initializer*/ undefined);
1532                        const statement = factory.createVariableStatement(needsDeclare ? [factory.createModifier(SyntaxKind.DeclareKeyword)] : [], factory.createVariableDeclarationList([varDecl], NodeFlags.Const));
1533                        const heritageClauses = factory.createNodeArray(map(input.heritageClauses, clause => {
1534                            if (clause.token === SyntaxKind.ExtendsKeyword) {
1535                                const oldDiag = getSymbolAccessibilityDiagnostic;
1536                                getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(clause.types[0]);
1537                                const newClause = factory.updateHeritageClause(clause, map(clause.types, t => factory.updateExpressionWithTypeArguments(t, newId, visitNodes(t.typeArguments, visitDeclarationSubtree))));
1538                                getSymbolAccessibilityDiagnostic = oldDiag;
1539                                return newClause;
1540                            }
1541                            return factory.updateHeritageClause(clause, visitNodes(factory.createNodeArray(filter(clause.types, t => isEntityNameExpression(t.expression) || t.expression.kind === SyntaxKind.NullKeyword)), visitDeclarationSubtree));
1542                        }));
1543                        let reservedDecorators = getReservedDecoratorsOfEtsFile(input, host);
1544
1545                        return [statement, cleanup(factory.updateClassDeclaration(
1546                            input,
1547                            concatenateDecoratorsAndModifiers(reservedDecorators, modifiers),
1548                            input.name,
1549                            typeParameters,
1550                            heritageClauses,
1551                            members
1552                        ))!]; // TODO: GH#18217
1553                    }
1554                    else {
1555                        const heritageClauses = transformHeritageClauses(input.heritageClauses);
1556                        let reservedDecorators = getReservedDecoratorsOfEtsFile(input, host);;
1557
1558                        return cleanup(factory.updateClassDeclaration(
1559                            input,
1560                            concatenateDecoratorsAndModifiers(reservedDecorators, modifiers),
1561                            input.name,
1562                            typeParameters,
1563                            heritageClauses,
1564                            members
1565                        ));
1566                    }
1567                }
1568                case SyntaxKind.VariableStatement: {
1569                    return cleanup(transformVariableStatement(input));
1570                }
1571                case SyntaxKind.EnumDeclaration: {
1572                    return cleanup(factory.updateEnumDeclaration(input, factory.createNodeArray(ensureModifiers(input)), input.name, factory.createNodeArray(mapDefined(input.members, m => {
1573                        if (shouldStripInternal(m)) return;
1574                        // Rewrite enum values to their constants, if available
1575                        const constValue = resolver.getConstantValue(m);
1576                        return preserveJsDoc(factory.updateEnumMember(m, m.name, constValue !== undefined ? typeof constValue === "string" ? factory.createStringLiteral(constValue) : factory.createNumericLiteral(constValue) : undefined), m);
1577                    }))));
1578                }
1579            }
1580
1581            function cleanup<T extends Node>(node: T | undefined): T | undefined {
1582                if (isEnclosingDeclaration(input)) {
1583                    enclosingDeclaration = previousEnclosingDeclaration;
1584                }
1585                if (canProdiceDiagnostic) {
1586                    getSymbolAccessibilityDiagnostic = oldDiag;
1587                }
1588                if (input.kind === SyntaxKind.ModuleDeclaration) {
1589                    needsDeclare = previousNeedsDeclare;
1590                }
1591                if (node as Node === input) {
1592                    return node;
1593                }
1594                errorFallbackNode = undefined;
1595                errorNameNode = undefined;
1596                return node && setOriginalNode(preserveJsDoc(node, input), input);
1597            }
1598        }
1599
1600        function transformVariableStatement(input: VariableStatement) {
1601            if (!forEach(input.declarationList.declarations, getBindingNameVisible)) return;
1602            const nodes = visitNodes(input.declarationList.declarations, visitDeclarationSubtree);
1603            if (!length(nodes)) return;
1604            return factory.updateVariableStatement(input, factory.createNodeArray(ensureModifiers(input)), factory.updateVariableDeclarationList(input.declarationList, nodes));
1605        }
1606
1607        function recreateBindingPattern(d: BindingPattern): VariableDeclaration[] {
1608            return flatten<VariableDeclaration>(mapDefined(d.elements, e => recreateBindingElement(e)));
1609        }
1610
1611        function recreateBindingElement(e: ArrayBindingElement) {
1612            if (e.kind === SyntaxKind.OmittedExpression) {
1613                return;
1614            }
1615            if (e.name) {
1616                if (!getBindingNameVisible(e)) return;
1617                if (isBindingPattern(e.name)) {
1618                    return recreateBindingPattern(e.name);
1619                }
1620                else {
1621                    return factory.createVariableDeclaration(e.name, /*exclamationToken*/ undefined, ensureType(e, /*type*/ undefined), /*initializer*/ undefined);
1622                }
1623            }
1624        }
1625
1626        function checkName(node: DeclarationDiagnosticProducing) {
1627            let oldDiag: typeof getSymbolAccessibilityDiagnostic | undefined;
1628            if (!suppressNewDiagnosticContexts) {
1629                oldDiag = getSymbolAccessibilityDiagnostic;
1630                getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNodeName(node);
1631            }
1632            errorNameNode = (node as NamedDeclaration).name;
1633            Debug.assert(resolver.isLateBound(getParseTreeNode(node) as Declaration)); // Should only be called with dynamic names
1634            const decl = node as NamedDeclaration as LateBoundDeclaration;
1635            const entityName = decl.name.expression;
1636            checkEntityNameVisibility(entityName, enclosingDeclaration);
1637            if (!suppressNewDiagnosticContexts) {
1638                getSymbolAccessibilityDiagnostic = oldDiag!;
1639            }
1640            errorNameNode = undefined;
1641        }
1642
1643        function shouldStripInternal(node: Node) {
1644            return !!stripInternal && !!node && isInternalDeclaration(node, currentSourceFile);
1645        }
1646
1647        function isScopeMarker(node: Node) {
1648            return isExportAssignment(node) || isExportDeclaration(node);
1649        }
1650
1651        function hasScopeMarker(statements: readonly Statement[]) {
1652            return some(statements, isScopeMarker);
1653        }
1654
1655        function ensureModifiers<T extends HasModifiers>(node: T): readonly Modifier[] | undefined {
1656            const currentFlags = getEffectiveModifierFlags(node);
1657            const newFlags = ensureModifierFlags(node);
1658            if (currentFlags === newFlags) {
1659                return visitArray(node.modifiers, n => tryCast(n, isModifier), isModifier);
1660            }
1661            return factory.createModifiersFromModifierFlags(newFlags);
1662        }
1663
1664        function ensureModifierFlags(node: Node): ModifierFlags {
1665            let mask = ModifierFlags.All ^ (ModifierFlags.Public | ModifierFlags.Async | ModifierFlags.Override); // No async and override modifiers in declaration files
1666            let additions = (needsDeclare && !isAlwaysType(node)) ? ModifierFlags.Ambient : ModifierFlags.None;
1667            const parentIsFile = node.parent.kind === SyntaxKind.SourceFile;
1668            if (!parentIsFile || (isBundledEmit && parentIsFile && isExternalModule(node.parent as SourceFile))) {
1669                mask ^= ModifierFlags.Ambient;
1670                additions = ModifierFlags.None;
1671            }
1672            return maskModifierFlags(node, mask, additions);
1673        }
1674
1675        function getTypeAnnotationFromAllAccessorDeclarations(node: AccessorDeclaration, accessors: AllAccessorDeclarations) {
1676            let accessorType = getTypeAnnotationFromAccessor(node);
1677            if (!accessorType && node !== accessors.firstAccessor) {
1678                accessorType = getTypeAnnotationFromAccessor(accessors.firstAccessor);
1679                // If we end up pulling the type from the second accessor, we also need to change the diagnostic context to get the expected error message
1680                getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(accessors.firstAccessor);
1681            }
1682            if (!accessorType && accessors.secondAccessor && node !== accessors.secondAccessor) {
1683                accessorType = getTypeAnnotationFromAccessor(accessors.secondAccessor);
1684                // If we end up pulling the type from the second accessor, we also need to change the diagnostic context to get the expected error message
1685                getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(accessors.secondAccessor);
1686            }
1687            return accessorType;
1688        }
1689
1690        function transformHeritageClauses(nodes: NodeArray<HeritageClause> | undefined) {
1691            return factory.createNodeArray(filter(map(nodes, clause => factory.updateHeritageClause(clause, visitNodes(factory.createNodeArray(filter(clause.types, t => {
1692                return isEntityNameExpression(t.expression) || (clause.token === SyntaxKind.ExtendsKeyword && t.expression.kind === SyntaxKind.NullKeyword);
1693            })), visitDeclarationSubtree))), clause => clause.types && !!clause.types.length));
1694        }
1695    }
1696
1697    function isAlwaysType(node: Node) {
1698        if (node.kind === SyntaxKind.InterfaceDeclaration) {
1699            return true;
1700        }
1701        return false;
1702    }
1703
1704    // Elide "public" modifier, as it is the default
1705    function maskModifiers(node: Node, modifierMask?: ModifierFlags, modifierAdditions?: ModifierFlags): Modifier[] | undefined {
1706        return factory.createModifiersFromModifierFlags(maskModifierFlags(node, modifierMask, modifierAdditions));
1707    }
1708
1709    function maskModifierFlags(node: Node, modifierMask: ModifierFlags = ModifierFlags.All ^ ModifierFlags.Public, modifierAdditions: ModifierFlags = ModifierFlags.None): ModifierFlags {
1710        let flags = (getEffectiveModifierFlags(node) & modifierMask) | modifierAdditions;
1711        if (flags & ModifierFlags.Default && !(flags & ModifierFlags.Export)) {
1712            // A non-exported default is a nonsequitor - we usually try to remove all export modifiers
1713            // from statements in ambient declarations; but a default export must retain its export modifier to be syntactically valid
1714            flags ^= ModifierFlags.Export;
1715        }
1716        if (flags & ModifierFlags.Default && flags & ModifierFlags.Ambient) {
1717            flags ^= ModifierFlags.Ambient; // `declare` is never required alongside `default` (and would be an error if printed)
1718        }
1719        return flags;
1720    }
1721
1722    function getTypeAnnotationFromAccessor(accessor: AccessorDeclaration): TypeNode | undefined {
1723        if (accessor) {
1724            return accessor.kind === SyntaxKind.GetAccessor
1725                ? accessor.type // Getter - return type
1726                : accessor.parameters.length > 0
1727                    ? accessor.parameters[0].type // Setter parameter type
1728                    : undefined;
1729        }
1730    }
1731
1732    type CanHaveLiteralInitializer = VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration;
1733    function canHaveLiteralInitializer(node: Node): boolean {
1734        switch (node.kind) {
1735            case SyntaxKind.PropertyDeclaration:
1736            case SyntaxKind.PropertySignature:
1737                return !hasEffectiveModifier(node, ModifierFlags.Private);
1738            case SyntaxKind.Parameter:
1739            case SyntaxKind.VariableDeclaration:
1740                return true;
1741        }
1742        return false;
1743    }
1744
1745    type ProcessedDeclarationStatement =
1746        | FunctionDeclaration
1747        | ModuleDeclaration
1748        | ImportEqualsDeclaration
1749        | InterfaceDeclaration
1750        | ClassDeclaration
1751        | TypeAliasDeclaration
1752        | EnumDeclaration
1753        | VariableStatement
1754        | ImportDeclaration
1755        | ExportDeclaration
1756        | ExportAssignment;
1757
1758    function isPreservedDeclarationStatement(node: Node): node is ProcessedDeclarationStatement {
1759        switch (node.kind) {
1760            case SyntaxKind.FunctionDeclaration:
1761            case SyntaxKind.ModuleDeclaration:
1762            case SyntaxKind.ImportEqualsDeclaration:
1763            case SyntaxKind.InterfaceDeclaration:
1764            case SyntaxKind.ClassDeclaration:
1765            case SyntaxKind.StructDeclaration:
1766            case SyntaxKind.AnnotationDeclaration:
1767            case SyntaxKind.TypeAliasDeclaration:
1768            case SyntaxKind.EnumDeclaration:
1769            case SyntaxKind.VariableStatement:
1770            case SyntaxKind.ImportDeclaration:
1771            case SyntaxKind.ExportDeclaration:
1772            case SyntaxKind.ExportAssignment:
1773                return true;
1774        }
1775        return false;
1776    }
1777
1778    type ProcessedComponent =
1779        | ConstructSignatureDeclaration
1780        | ConstructorDeclaration
1781        | MethodDeclaration
1782        | GetAccessorDeclaration
1783        | SetAccessorDeclaration
1784        | PropertyDeclaration
1785        | AnnotationPropertyDeclaration
1786        | PropertySignature
1787        | MethodSignature
1788        | CallSignatureDeclaration
1789        | IndexSignatureDeclaration
1790        | VariableDeclaration
1791        | TypeParameterDeclaration
1792        | ExpressionWithTypeArguments
1793        | TypeReferenceNode
1794        | ConditionalTypeNode
1795        | FunctionTypeNode
1796        | ConstructorTypeNode
1797        | ImportTypeNode;
1798
1799    function isProcessedComponent(node: Node): node is ProcessedComponent {
1800        switch (node.kind) {
1801            case SyntaxKind.ConstructSignature:
1802            case SyntaxKind.Constructor:
1803            case SyntaxKind.MethodDeclaration:
1804            case SyntaxKind.GetAccessor:
1805            case SyntaxKind.SetAccessor:
1806            case SyntaxKind.PropertyDeclaration:
1807            case SyntaxKind.AnnotationPropertyDeclaration:
1808            case SyntaxKind.PropertySignature:
1809            case SyntaxKind.MethodSignature:
1810            case SyntaxKind.CallSignature:
1811            case SyntaxKind.IndexSignature:
1812            case SyntaxKind.VariableDeclaration:
1813            case SyntaxKind.TypeParameter:
1814            case SyntaxKind.ExpressionWithTypeArguments:
1815            case SyntaxKind.TypeReference:
1816            case SyntaxKind.ConditionalType:
1817            case SyntaxKind.FunctionType:
1818            case SyntaxKind.ConstructorType:
1819            case SyntaxKind.ImportType:
1820                return true;
1821        }
1822        return false;
1823    }
1824}
1825