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