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