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