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