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