• 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            | PropertySignature;
544
545        function ensureType(node: HasInferredType, type: TypeNode | undefined, ignorePrivate?: boolean): TypeNode | undefined {
546            if (!ignorePrivate && hasEffectiveModifier(node, ModifierFlags.Private)) {
547                // Private nodes emit no types (except private parameter properties, whose parameter types are actually visible)
548                return;
549            }
550            if (shouldPrintWithInitializer(node)) {
551                // Literal const declarations will have an initializer ensured rather than a type
552                return;
553            }
554            if (type !== undefined && isTypeReferenceNode(type) && type.typeName.virtual) {
555                return;
556            }
557            const shouldUseResolverType = node.kind === SyntaxKind.Parameter &&
558                (resolver.isRequiredInitializedParameter(node) ||
559                 resolver.isOptionalUninitializedParameterProperty(node));
560            if (type && !shouldUseResolverType) {
561                return visitNode(type, visitDeclarationSubtree);
562            }
563            if (!getParseTreeNode(node)) {
564                return type ? visitNode(type, visitDeclarationSubtree) : factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
565            }
566            if (node.kind === SyntaxKind.SetAccessor) {
567                // 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
568                // (The inferred type here will be void, but the old declaration emitter printed `any`, so this replicates that)
569                return factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
570            }
571            errorNameNode = node.name;
572            let oldDiag: typeof getSymbolAccessibilityDiagnostic;
573            if (!suppressNewDiagnosticContexts) {
574                oldDiag = getSymbolAccessibilityDiagnostic;
575                getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(node);
576            }
577            if (node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement) {
578                return cleanup(resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker));
579            }
580            if (node.kind === SyntaxKind.Parameter
581                || node.kind === SyntaxKind.PropertyDeclaration
582                || node.kind === SyntaxKind.PropertySignature) {
583                if (isPropertySignature(node) || !node.initializer) return cleanup(resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker, shouldUseResolverType));
584                return cleanup(resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker, shouldUseResolverType) || resolver.createTypeOfExpression(node.initializer, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker));
585            }
586            return cleanup(resolver.createReturnTypeOfSignatureDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker));
587
588            function cleanup(returnValue: TypeNode | undefined) {
589                errorNameNode = undefined;
590                if (!suppressNewDiagnosticContexts) {
591                    getSymbolAccessibilityDiagnostic = oldDiag;
592                }
593                return returnValue || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
594            }
595        }
596
597        function isDeclarationAndNotVisible(node: NamedDeclaration) {
598            node = getParseTreeNode(node) as NamedDeclaration;
599            switch (node.kind) {
600                case SyntaxKind.FunctionDeclaration:
601                case SyntaxKind.ModuleDeclaration:
602                case SyntaxKind.InterfaceDeclaration:
603                case SyntaxKind.ClassDeclaration:
604                case SyntaxKind.StructDeclaration:
605                case SyntaxKind.TypeAliasDeclaration:
606                case SyntaxKind.EnumDeclaration:
607                    return !resolver.isDeclarationVisible(node);
608                // The following should be doing their own visibility checks based on filtering their members
609                case SyntaxKind.VariableDeclaration:
610                    return !getBindingNameVisible(node as VariableDeclaration);
611                case SyntaxKind.ImportEqualsDeclaration:
612                case SyntaxKind.ImportDeclaration:
613                case SyntaxKind.ExportDeclaration:
614                case SyntaxKind.ExportAssignment:
615                    return false;
616                case SyntaxKind.ClassStaticBlockDeclaration:
617                    return true;
618            }
619            return false;
620        }
621
622        // If the ExpandoFunctionDeclaration have multiple overloads, then we only need to emit properties for the last one.
623        function shouldEmitFunctionProperties(input: FunctionDeclaration) {
624            if (input.body) {
625                return true;
626            }
627
628            const overloadSignatures = input.symbol.declarations?.filter(decl => isFunctionDeclaration(decl) && !decl.body);
629            return !overloadSignatures || overloadSignatures.indexOf(input) === overloadSignatures.length - 1;
630        }
631
632        function getBindingNameVisible(elem: BindingElement | VariableDeclaration | OmittedExpression): boolean {
633            if (isOmittedExpression(elem)) {
634                return false;
635            }
636            if (isBindingPattern(elem.name)) {
637                // If any child binding pattern element has been marked visible (usually by collect linked aliases), then this is visible
638                return some(elem.name.elements, getBindingNameVisible);
639            }
640            else {
641                return resolver.isDeclarationVisible(elem);
642            }
643        }
644
645        function updateParamsList(node: Node, params: NodeArray<ParameterDeclaration>, modifierMask?: ModifierFlags) {
646            if (hasEffectiveModifier(node, ModifierFlags.Private)) {
647                return undefined!; // TODO: GH#18217
648            }
649            const newParams = map(params, p => ensureParameter(p, modifierMask));
650            if (!newParams) {
651                return undefined!; // TODO: GH#18217
652            }
653            return factory.createNodeArray(newParams, params.hasTrailingComma);
654        }
655
656        function updateAccessorParamsList(input: AccessorDeclaration, isPrivate: boolean) {
657            let newParams: ParameterDeclaration[] | undefined;
658            if (!isPrivate) {
659                const thisParameter = getThisParameter(input);
660                if (thisParameter) {
661                    newParams = [ensureParameter(thisParameter)];
662                }
663            }
664            if (isSetAccessorDeclaration(input)) {
665                let newValueParameter: ParameterDeclaration | undefined;
666                if (!isPrivate) {
667                    const valueParameter = getSetAccessorValueParameter(input);
668                    if (valueParameter) {
669                        const accessorType = getTypeAnnotationFromAllAccessorDeclarations(input, resolver.getAllAccessorDeclarations(input));
670                        newValueParameter = ensureParameter(valueParameter, /*modifierMask*/ undefined, accessorType);
671                    }
672                }
673                if (!newValueParameter) {
674                    newValueParameter = factory.createParameterDeclaration(
675                        /*modifiers*/ undefined,
676                        /*dotDotDotToken*/ undefined,
677                        "value"
678                    );
679                }
680                newParams = append(newParams, newValueParameter);
681            }
682            return factory.createNodeArray(newParams || emptyArray);
683        }
684
685        function ensureTypeParams(node: Node, params: NodeArray<TypeParameterDeclaration> | undefined) {
686            return hasEffectiveModifier(node, ModifierFlags.Private) ? undefined : visitNodes(params, visitDeclarationSubtree);
687        }
688
689        function isEnclosingDeclaration(node: Node) {
690            return isSourceFile(node)
691                || isTypeAliasDeclaration(node)
692                || isModuleDeclaration(node)
693                || isClassDeclaration(node)
694                || isStructDeclaration(node)
695                || isInterfaceDeclaration(node)
696                || isFunctionLike(node)
697                || isIndexSignatureDeclaration(node)
698                || isMappedTypeNode(node);
699        }
700
701        function checkEntityNameVisibility(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node) {
702            const visibilityResult = resolver.isEntityNameVisible(entityName, enclosingDeclaration);
703            handleSymbolAccessibilityError(visibilityResult);
704            recordTypeReferenceDirectivesIfNecessary(resolver.getTypeReferenceDirectivesForEntityName(entityName));
705        }
706
707        function preserveJsDoc<T extends Node>(updated: T, original: Node): T {
708            if (hasJSDocNodes(updated) && hasJSDocNodes(original)) {
709                updated.jsDoc = original.jsDoc;
710            }
711            return setCommentRange(updated, getCommentRange(original));
712        }
713
714        function rewriteModuleSpecifier<T extends Node>(parent: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode, input: T | undefined): T | StringLiteral {
715            if (!input) return undefined!; // TODO: GH#18217
716            resultHasExternalModuleIndicator = resultHasExternalModuleIndicator || (parent.kind !== SyntaxKind.ModuleDeclaration && parent.kind !== SyntaxKind.ImportType);
717            if (isStringLiteralLike(input)) {
718                if (isBundledEmit) {
719                    const newName = getExternalModuleNameFromDeclaration(context.getEmitHost(), resolver, parent);
720                    if (newName) {
721                        return factory.createStringLiteral(newName);
722                    }
723                }
724                else {
725                    const symbol = resolver.getSymbolOfExternalModuleSpecifier(input);
726                    if (symbol) {
727                        (exportedModulesFromDeclarationEmit || (exportedModulesFromDeclarationEmit = [])).push(symbol);
728                    }
729                }
730            }
731            return input;
732        }
733
734        function transformImportEqualsDeclaration(decl: ImportEqualsDeclaration) {
735            if (!resolver.isDeclarationVisible(decl)) return;
736            if (decl.moduleReference.kind === SyntaxKind.ExternalModuleReference) {
737                // Rewrite external module names if necessary
738                const specifier = getExternalModuleImportEqualsDeclarationExpression(decl);
739                return factory.updateImportEqualsDeclaration(
740                    decl,
741                    decl.modifiers,
742                    decl.isTypeOnly,
743                    decl.name,
744                    factory.updateExternalModuleReference(decl.moduleReference, rewriteModuleSpecifier(decl, specifier))
745                );
746            }
747            else {
748                const oldDiag = getSymbolAccessibilityDiagnostic;
749                getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(decl);
750                checkEntityNameVisibility(decl.moduleReference, enclosingDeclaration);
751                getSymbolAccessibilityDiagnostic = oldDiag;
752                return decl;
753            }
754        }
755
756        function transformImportDeclaration(decl: ImportDeclaration) {
757            if (!decl.importClause) {
758                // import "mod" - possibly needed for side effects? (global interface patches, module augmentations, etc)
759                return factory.updateImportDeclaration(
760                    decl,
761                    decl.modifiers,
762                    decl.importClause,
763                    rewriteModuleSpecifier(decl, decl.moduleSpecifier),
764                    getResolutionModeOverrideForClauseInNightly(decl.assertClause)
765                );
766            }
767            // The `importClause` visibility corresponds to the default's visibility.
768            const visibleDefaultBinding = decl.importClause && decl.importClause.name && resolver.isDeclarationVisible(decl.importClause) ? decl.importClause.name : undefined;
769            if (!decl.importClause.namedBindings) {
770                // No named bindings (either namespace or list), meaning the import is just default or should be elided
771                return visibleDefaultBinding && factory.updateImportDeclaration(decl, decl.modifiers, factory.updateImportClause(
772                    decl.importClause,
773                    decl.importClause.isTypeOnly,
774                    visibleDefaultBinding,
775                    /*namedBindings*/ undefined,
776                ), rewriteModuleSpecifier(decl, decl.moduleSpecifier), getResolutionModeOverrideForClauseInNightly(decl.assertClause));
777            }
778            if (decl.importClause.namedBindings.kind === SyntaxKind.NamespaceImport) {
779                // Namespace import (optionally with visible default)
780                const namedBindings = resolver.isDeclarationVisible(decl.importClause.namedBindings) ? decl.importClause.namedBindings : /*namedBindings*/ undefined;
781                return visibleDefaultBinding || namedBindings ? factory.updateImportDeclaration(decl, decl.modifiers, factory.updateImportClause(
782                    decl.importClause,
783                    decl.importClause.isTypeOnly,
784                    visibleDefaultBinding,
785                    namedBindings,
786                ), rewriteModuleSpecifier(decl, decl.moduleSpecifier), getResolutionModeOverrideForClauseInNightly(decl.assertClause)) : undefined;
787            }
788            // Named imports (optionally with visible default)
789            const bindingList = mapDefined(decl.importClause.namedBindings.elements, b => resolver.isDeclarationVisible(b) ? b : undefined);
790            if ((bindingList && bindingList.length) || visibleDefaultBinding) {
791                return factory.updateImportDeclaration(
792                    decl,
793                    decl.modifiers,
794                    factory.updateImportClause(
795                        decl.importClause,
796                        decl.importClause.isTypeOnly,
797                        visibleDefaultBinding,
798                        bindingList && bindingList.length ? factory.updateNamedImports(decl.importClause.namedBindings, bindingList) : undefined,
799                    ),
800                    rewriteModuleSpecifier(decl, decl.moduleSpecifier),
801                    getResolutionModeOverrideForClauseInNightly(decl.assertClause)
802                );
803            }
804            // Augmentation of export depends on import
805            if (resolver.isImportRequiredByAugmentation(decl)) {
806                return factory.updateImportDeclaration(
807                    decl,
808                    decl.modifiers,
809                    /*importClause*/ undefined,
810                    rewriteModuleSpecifier(decl, decl.moduleSpecifier),
811                    getResolutionModeOverrideForClauseInNightly(decl.assertClause)
812                );
813            }
814            // Nothing visible
815        }
816
817        function getResolutionModeOverrideForClauseInNightly(assertClause: AssertClause | undefined) {
818            const mode = getResolutionModeOverrideForClause(assertClause);
819            if (mode !== undefined) {
820                if (!isNightly()) {
821                    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));
822                }
823                return assertClause;
824            }
825            return undefined;
826        }
827
828        function transformAndReplaceLatePaintedStatements(statements: NodeArray<Statement>): NodeArray<Statement> {
829            // This is a `while` loop because `handleSymbolAccessibilityError` can see additional import aliases marked as visible during
830            // error handling which must now be included in the output and themselves checked for errors.
831            // For example:
832            // ```
833            // module A {
834            //   export module Q {}
835            //   import B = Q;
836            //   import C = B;
837            //   export import D = C;
838            // }
839            // ```
840            // 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
841            // 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
842            // dependent imports and allowing a valid declaration file output. Today, this dependent alias marking only happens for internal import aliases.
843            while (length(lateMarkedStatements)) {
844                const i = lateMarkedStatements!.shift()!;
845                if (!isLateVisibilityPaintedStatement(i)) {
846                    return Debug.fail(`Late replaced statement was found which is not handled by the declaration transformer!: ${Debug.formatSyntaxKind((i as Node).kind)}`);
847                }
848                const priorNeedsDeclare = needsDeclare;
849                needsDeclare = i.parent && isSourceFile(i.parent) && !(isExternalModule(i.parent) && isBundledEmit);
850                const result = transformTopLevelDeclaration(i);
851                needsDeclare = priorNeedsDeclare;
852                lateStatementReplacementMap.set(getOriginalNodeId(i), result);
853            }
854
855            // And lastly, we need to get the final form of all those indetermine import declarations from before and add them to the output list
856            // (and remove them from the set to examine for outter declarations)
857            return visitNodes(statements, visitLateVisibilityMarkedStatements);
858
859            function visitLateVisibilityMarkedStatements(statement: Statement) {
860                if (isLateVisibilityPaintedStatement(statement)) {
861                    const key = getOriginalNodeId(statement);
862                    if (lateStatementReplacementMap.has(key)) {
863                        const result = lateStatementReplacementMap.get(key);
864                        lateStatementReplacementMap.delete(key);
865                        if (result) {
866                            if (isArray(result) ? some(result, needsScopeMarker) : needsScopeMarker(result)) {
867                                // Top-level declarations in .d.ts files are always considered exported even without a modifier unless there's an export assignment or specifier
868                                needsScopeFixMarker = true;
869                            }
870                            if (isSourceFile(statement.parent) && (isArray(result) ? some(result, isExternalModuleIndicator) : isExternalModuleIndicator(result))) {
871                                resultHasExternalModuleIndicator = true;
872                            }
873                        }
874                        return result;
875                    }
876                }
877                return statement;
878            }
879        }
880
881        function visitDeclarationSubtree(input: Node): VisitResult<Node> {
882            if (shouldStripInternal(input)) return;
883            if (isDeclaration(input)) {
884                if (isDeclarationAndNotVisible(input)) return;
885                if (hasDynamicName(input) && !resolver.isLateBound(getParseTreeNode(input) as Declaration)) {
886                    return;
887                }
888            }
889
890            // Elide implementation signatures from overload sets
891            if (isFunctionLike(input) && resolver.isImplementationOfOverload(input)) return;
892
893            // Elide semicolon class statements
894            if (isSemicolonClassElement(input)) return;
895
896            let previousEnclosingDeclaration: typeof enclosingDeclaration;
897            if (isEnclosingDeclaration(input)) {
898                previousEnclosingDeclaration = enclosingDeclaration;
899                enclosingDeclaration = input as Declaration;
900            }
901            const oldDiag = getSymbolAccessibilityDiagnostic;
902
903            // Setup diagnostic-related flags before first potential `cleanup` call, otherwise
904            // We'd see a TDZ violation at runtime
905            const canProduceDiagnostic = canProduceDiagnostics(input);
906            const oldWithinObjectLiteralType = suppressNewDiagnosticContexts;
907            let shouldEnterSuppressNewDiagnosticsContextContext = ((input.kind === SyntaxKind.TypeLiteral || input.kind === SyntaxKind.MappedType) && input.parent.kind !== SyntaxKind.TypeAliasDeclaration);
908
909            // Emit methods which are private as properties with no type information
910            if (isMethodDeclaration(input) || isMethodSignature(input)) {
911                if (hasEffectiveModifier(input, ModifierFlags.Private)) {
912                    if (input.symbol && input.symbol.declarations && input.symbol.declarations[0] !== input) return; // Elide all but the first overload
913                    return cleanup(factory.createPropertyDeclaration(ensureModifiers(input), input.name, /*questionToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined));
914                }
915            }
916
917            if (canProduceDiagnostic && !suppressNewDiagnosticContexts) {
918                getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(input);
919            }
920
921            if (isTypeQueryNode(input)) {
922                checkEntityNameVisibility(input.exprName, enclosingDeclaration);
923            }
924
925            if (shouldEnterSuppressNewDiagnosticsContextContext) {
926                // 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.
927                suppressNewDiagnosticContexts = true;
928            }
929
930            if (isProcessedComponent(input)) {
931                switch (input.kind) {
932                    case SyntaxKind.ExpressionWithTypeArguments: {
933                        if ((isEntityName(input.expression) || isEntityNameExpression(input.expression))) {
934                            checkEntityNameVisibility(input.expression, enclosingDeclaration);
935                        }
936                        const node = visitEachChild(input, visitDeclarationSubtree, context);
937                        return cleanup(factory.updateExpressionWithTypeArguments(node, node.expression, node.typeArguments));
938                    }
939                    case SyntaxKind.TypeReference: {
940                        checkEntityNameVisibility(input.typeName, enclosingDeclaration);
941                        const node = visitEachChild(input, visitDeclarationSubtree, context);
942                        return cleanup(factory.updateTypeReferenceNode(node, node.typeName, node.typeArguments));
943                    }
944                    case SyntaxKind.ConstructSignature:
945                        return cleanup(factory.updateConstructSignature(
946                            input,
947                            ensureTypeParams(input, input.typeParameters),
948                            updateParamsList(input, input.parameters),
949                            ensureType(input, input.type)
950                        ));
951                    case SyntaxKind.Constructor: {
952                        // A constructor declaration may not have a type annotation
953                        const ctor = factory.createConstructorDeclaration(
954                            /*modifiers*/ ensureModifiers(input),
955                            updateParamsList(input, input.parameters, ModifierFlags.None),
956                            /*body*/ undefined
957                        );
958                        return cleanup(ctor);
959                    }
960                    case SyntaxKind.MethodDeclaration: {
961                        if (isPrivateIdentifier(input.name)) {
962                            return cleanup(/*returnValue*/ undefined);
963                        }
964                        let reservedDecorators = getReservedDecoratorsOfStructDeclaration(input, host);
965
966                        const sig = factory.createMethodDeclaration(
967                            concatenateDecoratorsAndModifiers(reservedDecorators, ensureModifiers(input)),
968                            /*asteriskToken*/ undefined,
969                            input.name,
970                            input.questionToken,
971                            inEtsStylesContext(input, host) ? undefined : ensureTypeParams(input, input.typeParameters),
972                            updateParamsList(input, input.parameters),
973                            ensureType(input, input.type),
974                            /*body*/ undefined
975                        );
976                        return cleanup(sig);
977                    }
978                    case SyntaxKind.GetAccessor: {
979                        if (isPrivateIdentifier(input.name)) {
980                            return cleanup(/*returnValue*/ undefined);
981                        }
982                        const accessorType = getTypeAnnotationFromAllAccessorDeclarations(input, resolver.getAllAccessorDeclarations(input));
983                        return cleanup(factory.updateGetAccessorDeclaration(
984                            input,
985                            ensureModifiers(input),
986                            input.name,
987                            updateAccessorParamsList(input, hasEffectiveModifier(input, ModifierFlags.Private)),
988                            ensureType(input, accessorType),
989                            /*body*/ undefined));
990                    }
991                    case SyntaxKind.SetAccessor: {
992                        if (isPrivateIdentifier(input.name)) {
993                            return cleanup(/*returnValue*/ undefined);
994                        }
995                        return cleanup(factory.updateSetAccessorDeclaration(
996                            input,
997                            ensureModifiers(input),
998                            input.name,
999                            updateAccessorParamsList(input, hasEffectiveModifier(input, ModifierFlags.Private)),
1000                            /*body*/ undefined));
1001                    }
1002                    case SyntaxKind.PropertyDeclaration:
1003                        if (isPrivateIdentifier(input.name)) {
1004                            return cleanup(/*returnValue*/ undefined);
1005                        }
1006                        let reservedDecorators = getReservedDecoratorsOfStructDeclaration(input, host);
1007
1008                        return cleanup(factory.updatePropertyDeclaration(
1009                            input,
1010                            concatenateDecoratorsAndModifiers(reservedDecorators, ensureModifiers(input)),
1011                            input.name,
1012                            input.questionToken,
1013                            ensureType(input, input.type),
1014                            ensureNoInitializer(input)
1015                        ));
1016                    case SyntaxKind.PropertySignature:
1017                        if (isPrivateIdentifier(input.name)) {
1018                            return cleanup(/*returnValue*/ undefined);
1019                        }
1020                        return cleanup(factory.updatePropertySignature(
1021                            input,
1022                            ensureModifiers(input),
1023                            input.name,
1024                            input.questionToken,
1025                            ensureType(input, input.type)
1026                        ));
1027                    case SyntaxKind.MethodSignature: {
1028                        if (isPrivateIdentifier(input.name)) {
1029                            return cleanup(/*returnValue*/ undefined);
1030                        }
1031                        return cleanup(factory.updateMethodSignature(
1032                            input,
1033                            ensureModifiers(input),
1034                            input.name,
1035                            input.questionToken,
1036                            ensureTypeParams(input, input.typeParameters),
1037                            updateParamsList(input, input.parameters),
1038                            ensureType(input, input.type)
1039                        ));
1040                    }
1041                    case SyntaxKind.CallSignature: {
1042                        return cleanup(factory.updateCallSignature(
1043                            input,
1044                            ensureTypeParams(input, input.typeParameters),
1045                            updateParamsList(input, input.parameters),
1046                            ensureType(input, input.type)
1047                        ));
1048                    }
1049                    case SyntaxKind.IndexSignature: {
1050                        return cleanup(factory.updateIndexSignature(
1051                            input,
1052                            ensureModifiers(input),
1053                            updateParamsList(input, input.parameters),
1054                            visitNode(input.type, visitDeclarationSubtree) || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword)
1055                        ));
1056                    }
1057                    case SyntaxKind.VariableDeclaration: {
1058                        if (isBindingPattern(input.name)) {
1059                            return recreateBindingPattern(input.name);
1060                        }
1061                        shouldEnterSuppressNewDiagnosticsContextContext = true;
1062                        suppressNewDiagnosticContexts = true; // Variable declaration types also suppress new diagnostic contexts, provided the contexts wouldn't be made for binding pattern types
1063                        return cleanup(factory.updateVariableDeclaration(input, input.name, /*exclamationToken*/ undefined, ensureType(input, input.type), ensureNoInitializer(input)));
1064                    }
1065                    case SyntaxKind.TypeParameter: {
1066                        if (isPrivateMethodTypeParameter(input) && (input.default || input.constraint)) {
1067                            return cleanup(factory.updateTypeParameterDeclaration(input, input.modifiers, input.name, /*constraint*/ undefined, /*defaultType*/ undefined));
1068                        }
1069                        return cleanup(visitEachChild(input, visitDeclarationSubtree, context));
1070                    }
1071                    case SyntaxKind.ConditionalType: {
1072                        // We have to process conditional types in a special way because for visibility purposes we need to push a new enclosingDeclaration
1073                        // just for the `infer` types in the true branch. It's an implicit declaration scope that only applies to _part_ of the type.
1074                        const checkType = visitNode(input.checkType, visitDeclarationSubtree);
1075                        const extendsType = visitNode(input.extendsType, visitDeclarationSubtree);
1076                        const oldEnclosingDecl = enclosingDeclaration;
1077                        enclosingDeclaration = input.trueType;
1078                        const trueType = visitNode(input.trueType, visitDeclarationSubtree);
1079                        enclosingDeclaration = oldEnclosingDecl;
1080                        const falseType = visitNode(input.falseType, visitDeclarationSubtree);
1081                        return cleanup(factory.updateConditionalTypeNode(input, checkType, extendsType, trueType, falseType));
1082                    }
1083                    case SyntaxKind.FunctionType: {
1084                        return cleanup(factory.updateFunctionTypeNode(input, visitNodes(input.typeParameters, visitDeclarationSubtree), updateParamsList(input, input.parameters), visitNode(input.type, visitDeclarationSubtree)));
1085                    }
1086                    case SyntaxKind.ConstructorType: {
1087                        return cleanup(factory.updateConstructorTypeNode(input, ensureModifiers(input), visitNodes(input.typeParameters, visitDeclarationSubtree), updateParamsList(input, input.parameters), visitNode(input.type, visitDeclarationSubtree)));
1088                    }
1089                    case SyntaxKind.ImportType: {
1090                        if (!isLiteralImportTypeNode(input)) return cleanup(input);
1091                        return cleanup(factory.updateImportTypeNode(
1092                            input,
1093                            factory.updateLiteralTypeNode(input.argument, rewriteModuleSpecifier(input, input.argument.literal)),
1094                            input.assertions,
1095                            input.qualifier,
1096                            visitNodes(input.typeArguments, visitDeclarationSubtree, isTypeNode),
1097                            input.isTypeOf
1098                        ));
1099                    }
1100                    default: Debug.assertNever(input, `Attempted to process unhandled node kind: ${Debug.formatSyntaxKind((input as Node).kind)}`);
1101                }
1102            }
1103
1104            if (isTupleTypeNode(input) && (getLineAndCharacterOfPosition(currentSourceFile, input.pos).line === getLineAndCharacterOfPosition(currentSourceFile, input.end).line)) {
1105                setEmitFlags(input, EmitFlags.SingleLine);
1106            }
1107
1108            return cleanup(visitEachChild(input, visitDeclarationSubtree, context));
1109
1110            function cleanup<T extends Node>(returnValue: T | undefined): T | undefined {
1111                if (returnValue && canProduceDiagnostic && hasDynamicName(input as Declaration)) {
1112                    checkName(input);
1113                }
1114                if (isEnclosingDeclaration(input)) {
1115                    enclosingDeclaration = previousEnclosingDeclaration;
1116                }
1117                if (canProduceDiagnostic && !suppressNewDiagnosticContexts) {
1118                    getSymbolAccessibilityDiagnostic = oldDiag;
1119                }
1120                if (shouldEnterSuppressNewDiagnosticsContextContext) {
1121                    suppressNewDiagnosticContexts = oldWithinObjectLiteralType;
1122                }
1123                if (returnValue === input) {
1124                    return returnValue;
1125                }
1126                return returnValue && setOriginalNode(preserveJsDoc(returnValue, input), input);
1127            }
1128        }
1129
1130        function isPrivateMethodTypeParameter(node: TypeParameterDeclaration) {
1131            return node.parent.kind === SyntaxKind.MethodDeclaration && hasEffectiveModifier(node.parent, ModifierFlags.Private);
1132        }
1133
1134        function visitDeclarationStatements(input: Node): VisitResult<Node> {
1135            if (!isPreservedDeclarationStatement(input)) {
1136                // return undefined for unmatched kinds to omit them from the tree
1137                return;
1138            }
1139            if (shouldStripInternal(input)) return;
1140
1141            switch (input.kind) {
1142                case SyntaxKind.ExportDeclaration: {
1143                    if (isSourceFile(input.parent)) {
1144                        resultHasExternalModuleIndicator = true;
1145                    }
1146                    resultHasScopeMarker = true;
1147                    // Always visible if the parent node isn't dropped for being not visible
1148                    // Rewrite external module names if necessary
1149                    return factory.updateExportDeclaration(
1150                        input,
1151                        input.modifiers,
1152                        input.isTypeOnly,
1153                        input.exportClause,
1154                        rewriteModuleSpecifier(input, input.moduleSpecifier),
1155                        getResolutionModeOverrideForClause(input.assertClause) ? input.assertClause : undefined
1156                    );
1157                }
1158                case SyntaxKind.ExportAssignment: {
1159                    // Always visible if the parent node isn't dropped for being not visible
1160                    if (isSourceFile(input.parent)) {
1161                        resultHasExternalModuleIndicator = true;
1162                    }
1163                    resultHasScopeMarker = true;
1164                    if (input.expression.kind === SyntaxKind.Identifier) {
1165                        return input;
1166                    }
1167                    else {
1168                        const newId = factory.createUniqueName("_default", GeneratedIdentifierFlags.Optimistic);
1169                        getSymbolAccessibilityDiagnostic = () => ({
1170                            diagnosticMessage: Diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0,
1171                            errorNode: input
1172                        });
1173                        errorFallbackNode = input;
1174                        const varDecl = factory.createVariableDeclaration(newId, /*exclamationToken*/ undefined, resolver.createTypeOfExpression(input.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), /*initializer*/ undefined);
1175                        errorFallbackNode = undefined;
1176                        const statement = factory.createVariableStatement(needsDeclare ? [factory.createModifier(SyntaxKind.DeclareKeyword)] : [], factory.createVariableDeclarationList([varDecl], NodeFlags.Const));
1177
1178                        preserveJsDoc(statement, input);
1179                        removeAllComments(input);
1180                        return [statement, factory.updateExportAssignment(input, input.modifiers, newId)];
1181                    }
1182                }
1183            }
1184
1185            const result = transformTopLevelDeclaration(input);
1186            // Don't actually transform yet; just leave as original node - will be elided/swapped by late pass
1187            lateStatementReplacementMap.set(getOriginalNodeId(input), result);
1188            return input;
1189        }
1190
1191        function stripExportModifiers(statement: Statement): Statement {
1192            if (isImportEqualsDeclaration(statement) || hasEffectiveModifier(statement, ModifierFlags.Default) || !canHaveModifiers(statement)) {
1193                // `export import` statements should remain as-is, as imports are _not_ implicitly exported in an ambient namespace
1194                // Likewise, `export default` classes and the like and just be `default`, so we preserve their `export` modifiers, too
1195                return statement;
1196            }
1197
1198            const modifiers = factory.createModifiersFromModifierFlags(getEffectiveModifierFlags(statement) & (ModifierFlags.All ^ ModifierFlags.Export));
1199            return factory.updateModifiers(statement, modifiers);
1200        }
1201
1202        function transformTopLevelDeclaration(input: LateVisibilityPaintedStatement) {
1203            if (lateMarkedStatements) {
1204                while (orderedRemoveItem(lateMarkedStatements, input));
1205            }
1206            if (shouldStripInternal(input)) return;
1207            switch (input.kind) {
1208                case SyntaxKind.ImportEqualsDeclaration: {
1209                    return transformImportEqualsDeclaration(input);
1210                }
1211                case SyntaxKind.ImportDeclaration: {
1212                    return transformImportDeclaration(input);
1213                }
1214            }
1215            if (isDeclaration(input) && isDeclarationAndNotVisible(input)) return;
1216
1217            // Elide implementation signatures from overload sets
1218            if (isFunctionLike(input) && resolver.isImplementationOfOverload(input)) return;
1219
1220            let previousEnclosingDeclaration: typeof enclosingDeclaration;
1221            if (isEnclosingDeclaration(input)) {
1222                previousEnclosingDeclaration = enclosingDeclaration;
1223                enclosingDeclaration = input as Declaration;
1224            }
1225
1226            const canProdiceDiagnostic = canProduceDiagnostics(input);
1227            const oldDiag = getSymbolAccessibilityDiagnostic;
1228            if (canProdiceDiagnostic) {
1229                getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(input as DeclarationDiagnosticProducing);
1230            }
1231
1232            const previousNeedsDeclare = needsDeclare;
1233            switch (input.kind) {
1234                case SyntaxKind.TypeAliasDeclaration: {
1235                    needsDeclare = false;
1236                    const clean = cleanup(factory.updateTypeAliasDeclaration(
1237                        input,
1238                        ensureModifiers(input),
1239                        input.name,
1240                        visitNodes(input.typeParameters, visitDeclarationSubtree, isTypeParameterDeclaration),
1241                        visitNode(input.type, visitDeclarationSubtree, isTypeNode)
1242                    ));
1243                    // Default factory will set illegalDecorators in updateTypeAliasDeclaration, add extra set here to avoid abnormal case.
1244                    if (isSendableFunctionOrType(input)) {
1245                        (clean as Mutable<TypeAliasDeclaration>).illegalDecorators = input.illegalDecorators;
1246                    }
1247                    needsDeclare = previousNeedsDeclare;
1248                    return clean;
1249                }
1250                case SyntaxKind.InterfaceDeclaration: {
1251                    return cleanup(factory.updateInterfaceDeclaration(
1252                        input,
1253                        ensureModifiers(input),
1254                        input.name,
1255                        ensureTypeParams(input, input.typeParameters),
1256                        transformHeritageClauses(input.heritageClauses),
1257                        visitNodes(input.members, visitDeclarationSubtree)
1258                    ));
1259                }
1260                case SyntaxKind.FunctionDeclaration: {
1261                    // Generators lose their generator-ness, excepting their return type
1262                    const clean = cleanup(factory.updateFunctionDeclaration(
1263                        input,
1264                        ensureModifiers(input),
1265                        /*asteriskToken*/ undefined,
1266                        input.name,
1267                        inEtsStylesContext(input, host) ? undefined : ensureTypeParams(input, input.typeParameters),
1268                        updateParamsList(input, input.parameters),
1269                        ensureType(input, input.type),
1270                        /*body*/ undefined
1271                    ));
1272                    if (isSendableFunctionOrType(input)) {
1273                        (clean as Mutable<FunctionDeclaration>).illegalDecorators = input.illegalDecorators;
1274                    }
1275                    else if (isInEtsFile(input)) {
1276                        const reservedDecorators = getEffectiveDecorators(input.illegalDecorators, host);
1277                        (clean as Mutable<FunctionDeclaration>).illegalDecorators = factory.createNodeArray(reservedDecorators);
1278                    }
1279                    if (clean && resolver.isExpandoFunctionDeclaration(input) && shouldEmitFunctionProperties(input)) {
1280                        const props = resolver.getPropertiesOfContainerFunction(input);
1281                        // Use parseNodeFactory so it is usable as an enclosing declaration
1282                        const fakespace = parseNodeFactory.createModuleDeclaration(/*modifiers*/ undefined, clean.name || factory.createIdentifier("_default"), factory.createModuleBlock([]), NodeFlags.Namespace);
1283                        setParent(fakespace, enclosingDeclaration as SourceFile | NamespaceDeclaration);
1284                        fakespace.locals = createSymbolTable(props);
1285                        fakespace.symbol = props[0].parent!;
1286                        const exportMappings: [Identifier, string][] = [];
1287                        let declarations: (VariableStatement | ExportDeclaration)[] = mapDefined(props, p => {
1288                            if (!p.valueDeclaration || !isPropertyAccessExpression(p.valueDeclaration)) {
1289                                return undefined; // TODO GH#33569: Handle element access expressions that created late bound names (rather than silently omitting them)
1290                            }
1291                            getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(p.valueDeclaration);
1292                            const type = resolver.createTypeOfDeclaration(p.valueDeclaration, fakespace, declarationEmitNodeBuilderFlags, symbolTracker);
1293                            getSymbolAccessibilityDiagnostic = oldDiag;
1294                            const nameStr = unescapeLeadingUnderscores(p.escapedName);
1295                            const isNonContextualKeywordName = isStringANonContextualKeyword(nameStr);
1296                            const name = isNonContextualKeywordName ? factory.getGeneratedNameForNode(p.valueDeclaration) : factory.createIdentifier(nameStr);
1297                            if (isNonContextualKeywordName) {
1298                                exportMappings.push([name, nameStr]);
1299                            }
1300                            const varDecl = factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, type, /*initializer*/ undefined);
1301                            return factory.createVariableStatement(isNonContextualKeywordName ? undefined : [factory.createToken(SyntaxKind.ExportKeyword)], factory.createVariableDeclarationList([varDecl]));
1302                        });
1303                        if (!exportMappings.length) {
1304                            declarations = mapDefined(declarations, declaration => factory.updateModifiers(declaration, ModifierFlags.None));
1305                        }
1306                        else {
1307                            declarations.push(factory.createExportDeclaration(
1308                                /*modifiers*/ undefined,
1309                                /*isTypeOnly*/ false,
1310                                factory.createNamedExports(map(exportMappings, ([gen, exp]) => {
1311                                    return factory.createExportSpecifier(/*isTypeOnly*/ false, gen, exp);
1312                                }))
1313                            ));
1314                        }
1315                        const namespaceDecl = factory.createModuleDeclaration(ensureModifiers(input), input.name!, factory.createModuleBlock(declarations), NodeFlags.Namespace);
1316                        if (!hasEffectiveModifier(clean, ModifierFlags.Default)) {
1317                            return [clean, namespaceDecl];
1318                        }
1319
1320                        const modifiers = factory.createModifiersFromModifierFlags((getEffectiveModifierFlags(clean) & ~ModifierFlags.ExportDefault) | ModifierFlags.Ambient);
1321
1322                        const cleanDeclaration = factory.updateFunctionDeclaration(
1323                            clean,
1324                            modifiers,
1325                            /*asteriskToken*/ undefined,
1326                            clean.name,
1327                            clean.typeParameters,
1328                            clean.parameters,
1329                            clean.type,
1330                            /*body*/ undefined
1331                        );
1332                        if (isInEtsFile(input)) {
1333                            const reservedDecorators = getEffectiveDecorators(clean.illegalDecorators, host);
1334                            (cleanDeclaration as Mutable<FunctionDeclaration>).illegalDecorators = factory.createNodeArray(reservedDecorators);
1335                        }
1336                        const namespaceDeclaration = factory.updateModuleDeclaration(
1337                            namespaceDecl,
1338                            modifiers,
1339                            namespaceDecl.name,
1340                            namespaceDecl.body
1341                        );
1342
1343                        const exportDefaultDeclaration = factory.createExportAssignment(
1344                            /*modifiers*/ undefined,
1345                            /*isExportEquals*/ false,
1346                            namespaceDecl.name
1347                        );
1348
1349                        if (isSourceFile(input.parent)) {
1350                            resultHasExternalModuleIndicator = true;
1351                        }
1352                        resultHasScopeMarker = true;
1353
1354                        return [cleanDeclaration, namespaceDeclaration, exportDefaultDeclaration];
1355                    }
1356                    else {
1357                        return clean;
1358                    }
1359                }
1360                case SyntaxKind.ModuleDeclaration: {
1361                    needsDeclare = false;
1362                    const inner = input.body;
1363                    if (inner && inner.kind === SyntaxKind.ModuleBlock) {
1364                        const oldNeedsScopeFix = needsScopeFixMarker;
1365                        const oldHasScopeFix = resultHasScopeMarker;
1366                        resultHasScopeMarker = false;
1367                        needsScopeFixMarker = false;
1368                        const statements = visitNodes(inner.statements, visitDeclarationStatements);
1369                        let lateStatements = transformAndReplaceLatePaintedStatements(statements);
1370                        if (input.flags & NodeFlags.Ambient) {
1371                            needsScopeFixMarker = false; // If it was `declare`'d everything is implicitly exported already, ignore late printed "privates"
1372                        }
1373                        // With the final list of statements, there are 3 possibilities:
1374                        // 1. There's an export assignment or export declaration in the namespace - do nothing
1375                        // 2. Everything is exported and there are no export assignments or export declarations - strip all export modifiers
1376                        // 3. Some things are exported, some are not, and there's no marker - add an empty marker
1377                        if (!isGlobalScopeAugmentation(input) && !hasScopeMarker(lateStatements) && !resultHasScopeMarker) {
1378                            if (needsScopeFixMarker) {
1379                                lateStatements = factory.createNodeArray([...lateStatements, createEmptyExports(factory)]);
1380                            }
1381                            else {
1382                                lateStatements = visitNodes(lateStatements, stripExportModifiers);
1383                            }
1384                        }
1385                        const body = factory.updateModuleBlock(inner, lateStatements);
1386                        needsDeclare = previousNeedsDeclare;
1387                        needsScopeFixMarker = oldNeedsScopeFix;
1388                        resultHasScopeMarker = oldHasScopeFix;
1389                        const mods = ensureModifiers(input);
1390                        return cleanup(factory.updateModuleDeclaration(
1391                            input,
1392                            mods,
1393                            isExternalModuleAugmentation(input) ? rewriteModuleSpecifier(input, input.name) : input.name,
1394                            body
1395                        ));
1396                    }
1397                    else {
1398                        needsDeclare = previousNeedsDeclare;
1399                        const mods = ensureModifiers(input);
1400                        needsDeclare = false;
1401                        visitNode(inner, visitDeclarationStatements);
1402                        // eagerly transform nested namespaces (the nesting doesn't need any elision or painting done)
1403                        const id = getOriginalNodeId(inner!); // TODO: GH#18217
1404                        const body = lateStatementReplacementMap.get(id);
1405                        lateStatementReplacementMap.delete(id);
1406                        return cleanup(factory.updateModuleDeclaration(
1407                            input,
1408                            mods,
1409                            input.name,
1410                            body as ModuleBody
1411                        ));
1412                    }
1413                }
1414                case SyntaxKind.StructDeclaration: {
1415                    errorNameNode = input.name;
1416                    errorFallbackNode = input;
1417
1418                    const decorators = ensureEtsDecorators(input, host);
1419                    const modifiers = factory.createNodeArray(ensureModifiers(input));
1420                    const typeParameters = ensureTypeParams(input, input.typeParameters);
1421                    const memberNodes = visitNodes(input.members, visitDeclarationSubtree, undefined, 1);
1422                    const members = factory.createNodeArray(memberNodes);
1423
1424                    return cleanup(factory.updateStructDeclaration(
1425                        input,
1426                        concatenateDecoratorsAndModifiers(decorators, modifiers),
1427                        input.name,
1428                        typeParameters,
1429                        /*heritageClauses*/ undefined,
1430                        members
1431                    ));
1432                }
1433                case SyntaxKind.ClassDeclaration: {
1434                    errorNameNode = input.name;
1435                    errorFallbackNode = input;
1436                    const modifiers = factory.createNodeArray(ensureModifiers(input));
1437                    const typeParameters = ensureTypeParams(input, input.typeParameters);
1438                    const ctor = getFirstConstructorWithBody(input);
1439                    let parameterProperties: readonly PropertyDeclaration[] | undefined;
1440                    if (ctor) {
1441                        const oldDiag = getSymbolAccessibilityDiagnostic;
1442                        parameterProperties = compact(flatMap(ctor.parameters, (param) => {
1443                            if (!hasSyntacticModifier(param, ModifierFlags.ParameterPropertyModifier) || shouldStripInternal(param)) return;
1444                            getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(param);
1445                            if (param.name.kind === SyntaxKind.Identifier) {
1446                                return preserveJsDoc(factory.createPropertyDeclaration(
1447                                    ensureModifiers(param),
1448                                    param.name,
1449                                    param.questionToken,
1450                                    ensureType(param, param.type),
1451                                    ensureNoInitializer(param)), param);
1452                            }
1453                            else {
1454                                // Pattern - this is currently an error, but we emit declarations for it somewhat correctly
1455                                return walkBindingPattern(param.name);
1456                            }
1457
1458                            function walkBindingPattern(pattern: BindingPattern) {
1459                                let elems: PropertyDeclaration[] | undefined;
1460                                for (const elem of pattern.elements) {
1461                                    if (isOmittedExpression(elem)) continue;
1462                                    if (isBindingPattern(elem.name)) {
1463                                        elems = concatenate(elems, walkBindingPattern(elem.name));
1464                                    }
1465                                    elems = elems || [];
1466                                    elems.push(factory.createPropertyDeclaration(
1467                                        ensureModifiers(param),
1468                                        elem.name as Identifier,
1469                                        /*questionToken*/ undefined,
1470                                        ensureType(elem, /*type*/ undefined),
1471                                        /*initializer*/ undefined
1472                                    ));
1473                                }
1474                                return elems;
1475                            }
1476                        }));
1477                        getSymbolAccessibilityDiagnostic = oldDiag;
1478                    }
1479
1480                    const hasPrivateIdentifier = some(input.members, member => !!member.name && isPrivateIdentifier(member.name));
1481                    // When the class has at least one private identifier, create a unique constant identifier to retain the nominal typing behavior
1482                    // Prevents other classes with the same public members from being used in place of the current class
1483                    const privateIdentifier = hasPrivateIdentifier ? [
1484                        factory.createPropertyDeclaration(
1485                            /*modifiers*/ undefined,
1486                            factory.createPrivateIdentifier("#private"),
1487                            /*questionToken*/ undefined,
1488                            /*type*/ undefined,
1489                            /*initializer*/ undefined
1490                        )
1491                    ] : undefined;
1492                    const memberNodes = concatenate(concatenate(privateIdentifier, parameterProperties), visitNodes(input.members, visitDeclarationSubtree));
1493                    const members = factory.createNodeArray(memberNodes);
1494
1495                    const extendsClause = getEffectiveBaseTypeNode(input);
1496                    if (extendsClause && !isEntityNameExpression(extendsClause.expression) && extendsClause.expression.kind !== SyntaxKind.NullKeyword) {
1497                        // We must add a temporary declaration for the extends clause expression
1498
1499                        const oldId = input.name ? unescapeLeadingUnderscores(input.name.escapedText) : "default";
1500                        const newId = factory.createUniqueName(`${oldId}_base`, GeneratedIdentifierFlags.Optimistic);
1501                        getSymbolAccessibilityDiagnostic = () => ({
1502                            diagnosticMessage: Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1,
1503                            errorNode: extendsClause,
1504                            typeName: input.name
1505                        });
1506                        const varDecl = factory.createVariableDeclaration(newId, /*exclamationToken*/ undefined, resolver.createTypeOfExpression(extendsClause.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), /*initializer*/ undefined);
1507                        const statement = factory.createVariableStatement(needsDeclare ? [factory.createModifier(SyntaxKind.DeclareKeyword)] : [], factory.createVariableDeclarationList([varDecl], NodeFlags.Const));
1508                        const heritageClauses = factory.createNodeArray(map(input.heritageClauses, clause => {
1509                            if (clause.token === SyntaxKind.ExtendsKeyword) {
1510                                const oldDiag = getSymbolAccessibilityDiagnostic;
1511                                getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(clause.types[0]);
1512                                const newClause = factory.updateHeritageClause(clause, map(clause.types, t => factory.updateExpressionWithTypeArguments(t, newId, visitNodes(t.typeArguments, visitDeclarationSubtree))));
1513                                getSymbolAccessibilityDiagnostic = oldDiag;
1514                                return newClause;
1515                            }
1516                            return factory.updateHeritageClause(clause, visitNodes(factory.createNodeArray(filter(clause.types, t => isEntityNameExpression(t.expression) || t.expression.kind === SyntaxKind.NullKeyword)), visitDeclarationSubtree));
1517                        }));
1518                        let reservedDecorators = getReservedDecoratorsOfEtsFile(input, host);
1519
1520                        return [statement, cleanup(factory.updateClassDeclaration(
1521                            input,
1522                            concatenateDecoratorsAndModifiers(reservedDecorators, modifiers),
1523                            input.name,
1524                            typeParameters,
1525                            heritageClauses,
1526                            members
1527                        ))!]; // TODO: GH#18217
1528                    }
1529                    else {
1530                        const heritageClauses = transformHeritageClauses(input.heritageClauses);
1531                        let reservedDecorators = getReservedDecoratorsOfEtsFile(input, host);;
1532
1533                        return cleanup(factory.updateClassDeclaration(
1534                            input,
1535                            concatenateDecoratorsAndModifiers(reservedDecorators, modifiers),
1536                            input.name,
1537                            typeParameters,
1538                            heritageClauses,
1539                            members
1540                        ));
1541                    }
1542                }
1543                case SyntaxKind.VariableStatement: {
1544                    return cleanup(transformVariableStatement(input));
1545                }
1546                case SyntaxKind.EnumDeclaration: {
1547                    return cleanup(factory.updateEnumDeclaration(input, factory.createNodeArray(ensureModifiers(input)), input.name, factory.createNodeArray(mapDefined(input.members, m => {
1548                        if (shouldStripInternal(m)) return;
1549                        // Rewrite enum values to their constants, if available
1550                        const constValue = resolver.getConstantValue(m);
1551                        return preserveJsDoc(factory.updateEnumMember(m, m.name, constValue !== undefined ? typeof constValue === "string" ? factory.createStringLiteral(constValue) : factory.createNumericLiteral(constValue) : undefined), m);
1552                    }))));
1553                }
1554            }
1555
1556            function cleanup<T extends Node>(node: T | undefined): T | undefined {
1557                if (isEnclosingDeclaration(input)) {
1558                    enclosingDeclaration = previousEnclosingDeclaration;
1559                }
1560                if (canProdiceDiagnostic) {
1561                    getSymbolAccessibilityDiagnostic = oldDiag;
1562                }
1563                if (input.kind === SyntaxKind.ModuleDeclaration) {
1564                    needsDeclare = previousNeedsDeclare;
1565                }
1566                if (node as Node === input) {
1567                    return node;
1568                }
1569                errorFallbackNode = undefined;
1570                errorNameNode = undefined;
1571                return node && setOriginalNode(preserveJsDoc(node, input), input);
1572            }
1573        }
1574
1575        function transformVariableStatement(input: VariableStatement) {
1576            if (!forEach(input.declarationList.declarations, getBindingNameVisible)) return;
1577            const nodes = visitNodes(input.declarationList.declarations, visitDeclarationSubtree);
1578            if (!length(nodes)) return;
1579            return factory.updateVariableStatement(input, factory.createNodeArray(ensureModifiers(input)), factory.updateVariableDeclarationList(input.declarationList, nodes));
1580        }
1581
1582        function recreateBindingPattern(d: BindingPattern): VariableDeclaration[] {
1583            return flatten<VariableDeclaration>(mapDefined(d.elements, e => recreateBindingElement(e)));
1584        }
1585
1586        function recreateBindingElement(e: ArrayBindingElement) {
1587            if (e.kind === SyntaxKind.OmittedExpression) {
1588                return;
1589            }
1590            if (e.name) {
1591                if (!getBindingNameVisible(e)) return;
1592                if (isBindingPattern(e.name)) {
1593                    return recreateBindingPattern(e.name);
1594                }
1595                else {
1596                    return factory.createVariableDeclaration(e.name, /*exclamationToken*/ undefined, ensureType(e, /*type*/ undefined), /*initializer*/ undefined);
1597                }
1598            }
1599        }
1600
1601        function checkName(node: DeclarationDiagnosticProducing) {
1602            let oldDiag: typeof getSymbolAccessibilityDiagnostic | undefined;
1603            if (!suppressNewDiagnosticContexts) {
1604                oldDiag = getSymbolAccessibilityDiagnostic;
1605                getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNodeName(node);
1606            }
1607            errorNameNode = (node as NamedDeclaration).name;
1608            Debug.assert(resolver.isLateBound(getParseTreeNode(node) as Declaration)); // Should only be called with dynamic names
1609            const decl = node as NamedDeclaration as LateBoundDeclaration;
1610            const entityName = decl.name.expression;
1611            checkEntityNameVisibility(entityName, enclosingDeclaration);
1612            if (!suppressNewDiagnosticContexts) {
1613                getSymbolAccessibilityDiagnostic = oldDiag!;
1614            }
1615            errorNameNode = undefined;
1616        }
1617
1618        function shouldStripInternal(node: Node) {
1619            return !!stripInternal && !!node && isInternalDeclaration(node, currentSourceFile);
1620        }
1621
1622        function isScopeMarker(node: Node) {
1623            return isExportAssignment(node) || isExportDeclaration(node);
1624        }
1625
1626        function hasScopeMarker(statements: readonly Statement[]) {
1627            return some(statements, isScopeMarker);
1628        }
1629
1630        function ensureModifiers<T extends HasModifiers>(node: T): readonly Modifier[] | undefined {
1631            const currentFlags = getEffectiveModifierFlags(node);
1632            const newFlags = ensureModifierFlags(node);
1633            if (currentFlags === newFlags) {
1634                return visitArray(node.modifiers, n => tryCast(n, isModifier), isModifier);
1635            }
1636            return factory.createModifiersFromModifierFlags(newFlags);
1637        }
1638
1639        function ensureModifierFlags(node: Node): ModifierFlags {
1640            let mask = ModifierFlags.All ^ (ModifierFlags.Public | ModifierFlags.Async | ModifierFlags.Override); // No async and override modifiers in declaration files
1641            let additions = (needsDeclare && !isAlwaysType(node)) ? ModifierFlags.Ambient : ModifierFlags.None;
1642            const parentIsFile = node.parent.kind === SyntaxKind.SourceFile;
1643            if (!parentIsFile || (isBundledEmit && parentIsFile && isExternalModule(node.parent as SourceFile))) {
1644                mask ^= ModifierFlags.Ambient;
1645                additions = ModifierFlags.None;
1646            }
1647            return maskModifierFlags(node, mask, additions);
1648        }
1649
1650        function getTypeAnnotationFromAllAccessorDeclarations(node: AccessorDeclaration, accessors: AllAccessorDeclarations) {
1651            let accessorType = getTypeAnnotationFromAccessor(node);
1652            if (!accessorType && node !== accessors.firstAccessor) {
1653                accessorType = getTypeAnnotationFromAccessor(accessors.firstAccessor);
1654                // 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
1655                getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(accessors.firstAccessor);
1656            }
1657            if (!accessorType && accessors.secondAccessor && node !== accessors.secondAccessor) {
1658                accessorType = getTypeAnnotationFromAccessor(accessors.secondAccessor);
1659                // 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
1660                getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(accessors.secondAccessor);
1661            }
1662            return accessorType;
1663        }
1664
1665        function transformHeritageClauses(nodes: NodeArray<HeritageClause> | undefined) {
1666            return factory.createNodeArray(filter(map(nodes, clause => factory.updateHeritageClause(clause, visitNodes(factory.createNodeArray(filter(clause.types, t => {
1667                return isEntityNameExpression(t.expression) || (clause.token === SyntaxKind.ExtendsKeyword && t.expression.kind === SyntaxKind.NullKeyword);
1668            })), visitDeclarationSubtree))), clause => clause.types && !!clause.types.length));
1669        }
1670    }
1671
1672    function isAlwaysType(node: Node) {
1673        if (node.kind === SyntaxKind.InterfaceDeclaration) {
1674            return true;
1675        }
1676        return false;
1677    }
1678
1679    // Elide "public" modifier, as it is the default
1680    function maskModifiers(node: Node, modifierMask?: ModifierFlags, modifierAdditions?: ModifierFlags): Modifier[] | undefined {
1681        return factory.createModifiersFromModifierFlags(maskModifierFlags(node, modifierMask, modifierAdditions));
1682    }
1683
1684    function maskModifierFlags(node: Node, modifierMask: ModifierFlags = ModifierFlags.All ^ ModifierFlags.Public, modifierAdditions: ModifierFlags = ModifierFlags.None): ModifierFlags {
1685        let flags = (getEffectiveModifierFlags(node) & modifierMask) | modifierAdditions;
1686        if (flags & ModifierFlags.Default && !(flags & ModifierFlags.Export)) {
1687            // A non-exported default is a nonsequitor - we usually try to remove all export modifiers
1688            // from statements in ambient declarations; but a default export must retain its export modifier to be syntactically valid
1689            flags ^= ModifierFlags.Export;
1690        }
1691        if (flags & ModifierFlags.Default && flags & ModifierFlags.Ambient) {
1692            flags ^= ModifierFlags.Ambient; // `declare` is never required alongside `default` (and would be an error if printed)
1693        }
1694        return flags;
1695    }
1696
1697    function getTypeAnnotationFromAccessor(accessor: AccessorDeclaration): TypeNode | undefined {
1698        if (accessor) {
1699            return accessor.kind === SyntaxKind.GetAccessor
1700                ? accessor.type // Getter - return type
1701                : accessor.parameters.length > 0
1702                    ? accessor.parameters[0].type // Setter parameter type
1703                    : undefined;
1704        }
1705    }
1706
1707    type CanHaveLiteralInitializer = VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration;
1708    function canHaveLiteralInitializer(node: Node): boolean {
1709        switch (node.kind) {
1710            case SyntaxKind.PropertyDeclaration:
1711            case SyntaxKind.PropertySignature:
1712                return !hasEffectiveModifier(node, ModifierFlags.Private);
1713            case SyntaxKind.Parameter:
1714            case SyntaxKind.VariableDeclaration:
1715                return true;
1716        }
1717        return false;
1718    }
1719
1720    type ProcessedDeclarationStatement =
1721        | FunctionDeclaration
1722        | ModuleDeclaration
1723        | ImportEqualsDeclaration
1724        | InterfaceDeclaration
1725        | ClassDeclaration
1726        | TypeAliasDeclaration
1727        | EnumDeclaration
1728        | VariableStatement
1729        | ImportDeclaration
1730        | ExportDeclaration
1731        | ExportAssignment;
1732
1733    function isPreservedDeclarationStatement(node: Node): node is ProcessedDeclarationStatement {
1734        switch (node.kind) {
1735            case SyntaxKind.FunctionDeclaration:
1736            case SyntaxKind.ModuleDeclaration:
1737            case SyntaxKind.ImportEqualsDeclaration:
1738            case SyntaxKind.InterfaceDeclaration:
1739            case SyntaxKind.ClassDeclaration:
1740            case SyntaxKind.StructDeclaration:
1741            case SyntaxKind.TypeAliasDeclaration:
1742            case SyntaxKind.EnumDeclaration:
1743            case SyntaxKind.VariableStatement:
1744            case SyntaxKind.ImportDeclaration:
1745            case SyntaxKind.ExportDeclaration:
1746            case SyntaxKind.ExportAssignment:
1747                return true;
1748        }
1749        return false;
1750    }
1751
1752    type ProcessedComponent =
1753        | ConstructSignatureDeclaration
1754        | ConstructorDeclaration
1755        | MethodDeclaration
1756        | GetAccessorDeclaration
1757        | SetAccessorDeclaration
1758        | PropertyDeclaration
1759        | PropertySignature
1760        | MethodSignature
1761        | CallSignatureDeclaration
1762        | IndexSignatureDeclaration
1763        | VariableDeclaration
1764        | TypeParameterDeclaration
1765        | ExpressionWithTypeArguments
1766        | TypeReferenceNode
1767        | ConditionalTypeNode
1768        | FunctionTypeNode
1769        | ConstructorTypeNode
1770        | ImportTypeNode;
1771
1772    function isProcessedComponent(node: Node): node is ProcessedComponent {
1773        switch (node.kind) {
1774            case SyntaxKind.ConstructSignature:
1775            case SyntaxKind.Constructor:
1776            case SyntaxKind.MethodDeclaration:
1777            case SyntaxKind.GetAccessor:
1778            case SyntaxKind.SetAccessor:
1779            case SyntaxKind.PropertyDeclaration:
1780            case SyntaxKind.PropertySignature:
1781            case SyntaxKind.MethodSignature:
1782            case SyntaxKind.CallSignature:
1783            case SyntaxKind.IndexSignature:
1784            case SyntaxKind.VariableDeclaration:
1785            case SyntaxKind.TypeParameter:
1786            case SyntaxKind.ExpressionWithTypeArguments:
1787            case SyntaxKind.TypeReference:
1788            case SyntaxKind.ConditionalType:
1789            case SyntaxKind.FunctionType:
1790            case SyntaxKind.ConstructorType:
1791            case SyntaxKind.ImportType:
1792                return true;
1793        }
1794        return false;
1795    }
1796}
1797