Skip to content

Commit 7d50455

Browse files
authored
Do not perserve references in declaration emit, unless preserve=true (#57681)
1 parent ede8ad8 commit 7d50455

File tree

377 files changed

+1077
-1183
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

377 files changed

+1077
-1183
lines changed

src/compiler/checker.ts

-192
Original file line numberDiff line numberDiff line change
@@ -936,7 +936,6 @@ import {
936936
ResolutionMode,
937937
ResolvedModuleFull,
938938
ResolvedType,
939-
resolveTripleslashReference,
940939
resolvingEmptyArray,
941940
RestTypeNode,
942941
ReturnStatement,
@@ -8087,14 +8086,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
80878086
return file.moduleName;
80888087
}
80898088
if (!file) {
8090-
if (context.tracker.trackReferencedAmbientModule) {
8091-
const ambientDecls = filter(symbol.declarations, isAmbientModule);
8092-
if (length(ambientDecls)) {
8093-
for (const decl of ambientDecls!) {
8094-
context.tracker.trackReferencedAmbientModule(decl, symbol);
8095-
}
8096-
}
8097-
}
80988089
if (ambientModuleSymbolRegex.test(symbol.escapedName as string)) {
80998090
return (symbol.escapedName as string).substring(1, (symbol.escapedName as string).length - 1);
81008091
}
@@ -8206,7 +8197,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
82068197
}
82078198
}
82088199
const lit = factory.createLiteralTypeNode(factory.createStringLiteral(specifier));
8209-
if (context.tracker.trackExternalModuleSymbolOfImportTypeNode) context.tracker.trackExternalModuleSymbolOfImportTypeNode(chain[0]);
82108200
context.approximateLength += specifier.length + 10; // specifier + import("")
82118201
if (!nonRootParts || isEntityName(nonRootParts)) {
82128202
if (nonRootParts) {
@@ -8789,14 +8779,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
87898779
}
87908780
}
87918781
}
8792-
else {
8793-
if (context.tracker && context.tracker.trackExternalModuleSymbolOfImportTypeNode) {
8794-
const moduleSym = resolveExternalModuleNameWorker(lit, lit, /*moduleNotFoundError*/ undefined);
8795-
if (moduleSym) {
8796-
context.tracker.trackExternalModuleSymbolOfImportTypeNode(moduleSym);
8797-
}
8798-
}
8799-
}
88008782
return lit;
88018783
}
88028784
}
@@ -48227,35 +48209,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4822748209
return !isPropertyName && getReferencedValueSymbol(node) === argumentsSymbol;
4822848210
}
4822948211

48230-
function moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean {
48231-
let moduleSymbol = resolveExternalModuleName(moduleReferenceExpression.parent, moduleReferenceExpression);
48232-
if (!moduleSymbol || isShorthandAmbientModuleSymbol(moduleSymbol)) {
48233-
// If the module is not found or is shorthand, assume that it may export a value.
48234-
return true;
48235-
}
48236-
48237-
const hasExportAssignment = hasExportAssignmentSymbol(moduleSymbol);
48238-
// if module has export assignment then 'resolveExternalModuleSymbol' will return resolved symbol for export assignment
48239-
// otherwise it will return moduleSymbol itself
48240-
moduleSymbol = resolveExternalModuleSymbol(moduleSymbol);
48241-
48242-
const symbolLinks = getSymbolLinks(moduleSymbol);
48243-
if (symbolLinks.exportsSomeValue === undefined) {
48244-
// for export assignments - check if resolved symbol for RHS is itself a value
48245-
// otherwise - check if at least one export is value
48246-
symbolLinks.exportsSomeValue = hasExportAssignment
48247-
? !!(moduleSymbol.flags & SymbolFlags.Value)
48248-
: forEachEntry(getExportsOfModule(moduleSymbol), isValue);
48249-
}
48250-
48251-
return symbolLinks.exportsSomeValue!;
48252-
48253-
function isValue(s: Symbol): boolean {
48254-
s = resolveSymbol(s);
48255-
return s && !!(getSymbolFlags(s) & SymbolFlags.Value);
48256-
}
48257-
}
48258-
4825948212
function isNameOfModuleOrEnumDeclaration(node: Identifier) {
4826048213
return isModuleOrEnumDeclaration(node.parent) && node === node.parent.name;
4826148214
}
@@ -48899,26 +48852,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4889948852
}
4890048853

4890148854
function createResolver(): EmitResolver {
48902-
// this variable and functions that use it are deliberately moved here from the outer scope
48903-
// to avoid scope pollution
48904-
const resolvedTypeReferenceDirectives = host.getResolvedTypeReferenceDirectives();
48905-
let fileToDirective: Map<string, [specifier: string, mode: ResolutionMode]>;
48906-
if (resolvedTypeReferenceDirectives) {
48907-
// populate reverse mapping: file path -> type reference directive that was resolved to this file
48908-
fileToDirective = new Map<string, [specifier: string, mode: ResolutionMode]>();
48909-
resolvedTypeReferenceDirectives.forEach(({ resolvedTypeReferenceDirective }, key, mode) => {
48910-
if (!resolvedTypeReferenceDirective?.resolvedFileName) {
48911-
return;
48912-
}
48913-
const file = host.getSourceFile(resolvedTypeReferenceDirective.resolvedFileName);
48914-
if (file) {
48915-
// Add the transitive closure of path references loaded by this file (as long as they are not)
48916-
// part of an existing type reference.
48917-
addReferencedFilesToTypeDirective(file, key, mode);
48918-
}
48919-
});
48920-
}
48921-
4892248855
return {
4892348856
getReferencedExportContainer,
4892448857
getReferencedImportDeclaration,
@@ -48960,14 +48893,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4896048893
getReferencedValueDeclarations,
4896148894
getTypeReferenceSerializationKind,
4896248895
isOptionalParameter,
48963-
moduleExportsSomeValue,
4896448896
isArgumentsLocalBinding,
4896548897
getExternalModuleFileFromDeclaration: nodeIn => {
4896648898
const node = getParseTreeNode(nodeIn, hasPossibleExternalModuleReference);
4896748899
return node && getExternalModuleFileFromDeclaration(node);
4896848900
},
48969-
getTypeReferenceDirectivesForEntityName,
48970-
getTypeReferenceDirectivesForSymbol,
4897148901
isLiteralConstDeclaration,
4897248902
isLateBound: (nodeIn: Declaration): nodeIn is LateBoundDeclaration => {
4897348903
const node = getParseTreeNode(nodeIn, isDeclaration);
@@ -48991,7 +48921,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4899148921
getAccessor,
4899248922
};
4899348923
},
48994-
getSymbolOfExternalModuleSpecifier: moduleName => resolveExternalModuleNameWorker(moduleName, moduleName, /*moduleNotFoundError*/ undefined),
4899548924
isBindingCapturedByNode: (node, decl) => {
4899648925
const parseNode = getParseTreeNode(node);
4899748926
const parseDecl = getParseTreeNode(decl);
@@ -49007,11 +48936,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4900748936
return !sym.exports ? [] : nodeBuilder.symbolTableToDeclarationStatements(sym.exports, node, flags, tracker, bundled);
4900848937
},
4900948938
isImportRequiredByAugmentation,
49010-
tryFindAmbientModule: moduleReferenceExpression => {
49011-
const node = getParseTreeNode(moduleReferenceExpression);
49012-
const moduleSpecifier = node && isStringLiteralLike(node) ? node.text : undefined;
49013-
return moduleSpecifier !== undefined ? tryFindAmbientModule(moduleSpecifier, /*withAugmentations*/ true) : undefined;
49014-
},
4901548939
};
4901648940

4901748941
function isImportRequiredByAugmentation(node: ImportDeclaration) {
@@ -49036,108 +48960,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4903648960
}
4903748961
return false;
4903848962
}
49039-
49040-
function isInHeritageClause(node: PropertyAccessEntityNameExpression) {
49041-
return node.parent && node.parent.kind === SyntaxKind.ExpressionWithTypeArguments && node.parent.parent && node.parent.parent.kind === SyntaxKind.HeritageClause;
49042-
}
49043-
49044-
// defined here to avoid outer scope pollution
49045-
function getTypeReferenceDirectivesForEntityName(node: EntityNameOrEntityNameExpression): [specifier: string, mode: ResolutionMode][] | undefined {
49046-
// program does not have any files with type reference directives - bail out
49047-
if (!fileToDirective) {
49048-
return undefined;
49049-
}
49050-
// computed property name should use node as value
49051-
// property access can only be used as values, or types when within an expression with type arguments inside a heritage clause
49052-
// qualified names can only be used as types\namespaces
49053-
// identifiers are treated as values only if they appear in type queries
49054-
let meaning;
49055-
if (node.parent.kind === SyntaxKind.ComputedPropertyName) {
49056-
meaning = SymbolFlags.Value | SymbolFlags.ExportValue;
49057-
}
49058-
else {
49059-
meaning = SymbolFlags.Type | SymbolFlags.Namespace;
49060-
if ((node.kind === SyntaxKind.Identifier && isInTypeQuery(node)) || (node.kind === SyntaxKind.PropertyAccessExpression && !isInHeritageClause(node))) {
49061-
meaning = SymbolFlags.Value | SymbolFlags.ExportValue;
49062-
}
49063-
}
49064-
49065-
const symbol = resolveEntityName(node, meaning, /*ignoreErrors*/ true);
49066-
return symbol && symbol !== unknownSymbol ? getTypeReferenceDirectivesForSymbol(symbol, meaning) : undefined;
49067-
}
49068-
49069-
// defined here to avoid outer scope pollution
49070-
function getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): [specifier: string, mode: ResolutionMode][] | undefined {
49071-
// program does not have any files with type reference directives - bail out
49072-
if (!fileToDirective || !isSymbolFromTypeDeclarationFile(symbol)) {
49073-
return undefined;
49074-
}
49075-
// check what declarations in the symbol can contribute to the target meaning
49076-
let typeReferenceDirectives: [specifier: string, mode: ResolutionMode][] | undefined;
49077-
for (const decl of symbol.declarations!) {
49078-
// check meaning of the local symbol to see if declaration needs to be analyzed further
49079-
if (decl.symbol && decl.symbol.flags & meaning!) {
49080-
const file = getSourceFileOfNode(decl);
49081-
const typeReferenceDirective = fileToDirective.get(file.path);
49082-
if (typeReferenceDirective) {
49083-
(typeReferenceDirectives || (typeReferenceDirectives = [])).push(typeReferenceDirective);
49084-
}
49085-
else {
49086-
// found at least one entry that does not originate from type reference directive
49087-
return undefined;
49088-
}
49089-
}
49090-
}
49091-
return typeReferenceDirectives;
49092-
}
49093-
49094-
function isSymbolFromTypeDeclarationFile(symbol: Symbol): boolean {
49095-
// bail out if symbol does not have associated declarations (i.e. this is transient symbol created for property in binding pattern)
49096-
if (!symbol.declarations) {
49097-
return false;
49098-
}
49099-
49100-
// walk the parent chain for symbols to make sure that top level parent symbol is in the global scope
49101-
// external modules cannot define or contribute to type declaration files
49102-
let current = symbol;
49103-
while (true) {
49104-
const parent = getParentOfSymbol(current);
49105-
if (parent) {
49106-
current = parent;
49107-
}
49108-
else {
49109-
break;
49110-
}
49111-
}
49112-
49113-
if (current.valueDeclaration && current.valueDeclaration.kind === SyntaxKind.SourceFile && current.flags & SymbolFlags.ValueModule) {
49114-
return false;
49115-
}
49116-
49117-
// check that at least one declaration of top level symbol originates from type declaration file
49118-
for (const decl of symbol.declarations) {
49119-
const file = getSourceFileOfNode(decl);
49120-
if (fileToDirective.has(file.path)) {
49121-
return true;
49122-
}
49123-
}
49124-
return false;
49125-
}
49126-
49127-
function addReferencedFilesToTypeDirective(file: SourceFile, key: string, mode: ResolutionMode) {
49128-
if (fileToDirective.has(file.path)) return;
49129-
fileToDirective.set(file.path, [key, mode]);
49130-
for (const { fileName } of file.referencedFiles) {
49131-
const resolvedFile = resolveTripleslashReference(fileName, file.fileName);
49132-
const referencedFile = host.getSourceFile(resolvedFile);
49133-
if (referencedFile) {
49134-
// The resolution mode of the file reference doesn't actually matter here -
49135-
// all we're recording is the fact that the file entered the compilation
49136-
// transitively via a type reference directive of {key} with mode {mode}.
49137-
addReferencedFilesToTypeDirective(referencedFile, key, mode || file.impliedNodeFormat);
49138-
}
49139-
}
49140-
}
4914148963
}
4914248964

4914348965
function getExternalModuleFileFromDeclaration(declaration: AnyImportOrReExport | ModuleDeclaration | ImportTypeNode | ImportCall): SourceFile | undefined {
@@ -51499,20 +51321,6 @@ class SymbolTrackerImpl implements SymbolTracker {
5149951321
}
5150051322
}
5150151323

51502-
trackReferencedAmbientModule(decl: ModuleDeclaration, symbol: Symbol): void {
51503-
if (this.inner?.trackReferencedAmbientModule) {
51504-
this.onDiagnosticReported();
51505-
this.inner.trackReferencedAmbientModule(decl, symbol);
51506-
}
51507-
}
51508-
51509-
trackExternalModuleSymbolOfImportTypeNode(symbol: Symbol): void {
51510-
if (this.inner?.trackExternalModuleSymbolOfImportTypeNode) {
51511-
this.onDiagnosticReported();
51512-
this.inner.trackExternalModuleSymbolOfImportTypeNode(symbol);
51513-
}
51514-
}
51515-
5151651324
reportNonlocalAugmentation(containingFile: SourceFile, parentSymbol: Symbol, augmentingSymbol: Symbol): void {
5151751325
if (this.inner?.reportNonlocalAugmentation) {
5151851326
this.onDiagnosticReported();

src/compiler/emitter.ts

+14-19
Original file line numberDiff line numberDiff line change
@@ -1106,20 +1106,15 @@ export const notImplementedResolver: EmitResolver = {
11061106
getReferencedValueDeclarations: notImplemented,
11071107
getTypeReferenceSerializationKind: notImplemented,
11081108
isOptionalParameter: notImplemented,
1109-
moduleExportsSomeValue: notImplemented,
11101109
isArgumentsLocalBinding: notImplemented,
11111110
getExternalModuleFileFromDeclaration: notImplemented,
1112-
getTypeReferenceDirectivesForEntityName: notImplemented,
1113-
getTypeReferenceDirectivesForSymbol: notImplemented,
11141111
isLiteralConstDeclaration: notImplemented,
11151112
getJsxFactoryEntity: notImplemented,
11161113
getJsxFragmentFactoryEntity: notImplemented,
11171114
getAllAccessorDeclarations: notImplemented,
1118-
getSymbolOfExternalModuleSpecifier: notImplemented,
11191115
isBindingCapturedByNode: notImplemented,
11201116
getDeclarationStatementsForSourceFile: notImplemented,
11211117
isImportRequiredByAugmentation: notImplemented,
1122-
tryFindAmbientModule: notImplemented,
11231118
};
11241119

11251120
const enum PipelinePhase {
@@ -4185,21 +4180,21 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
41854180
writeLine();
41864181
}
41874182
}
4188-
for (const directive of files) {
4189-
writeComment(`/// <reference path="${directive.fileName}" />`);
4190-
writeLine();
4191-
}
4192-
for (const directive of types) {
4193-
const resolutionMode = directive.resolutionMode && directive.resolutionMode !== currentSourceFile?.impliedNodeFormat
4194-
? `resolution-mode="${directive.resolutionMode === ModuleKind.ESNext ? "import" : "require"}"`
4195-
: "";
4196-
writeComment(`/// <reference types="${directive.fileName}" ${resolutionMode}/>`);
4197-
writeLine();
4198-
}
4199-
for (const directive of libs) {
4200-
writeComment(`/// <reference lib="${directive.fileName}" />`);
4201-
writeLine();
4183+
4184+
function writeDirectives(kind: "path" | "types" | "lib", directives: readonly FileReference[]) {
4185+
for (const directive of directives) {
4186+
const preserve = directive.preserve ? `preserve="true" ` : "";
4187+
const resolutionMode = directive.resolutionMode && directive.resolutionMode !== currentSourceFile?.impliedNodeFormat
4188+
? `resolution-mode="${directive.resolutionMode === ModuleKind.ESNext ? "import" : "require"}" `
4189+
: "";
4190+
writeComment(`/// <reference ${kind}="${directive.fileName}" ${resolutionMode}${preserve}/>`);
4191+
writeLine();
4192+
}
42024193
}
4194+
4195+
writeDirectives("path", files);
4196+
writeDirectives("types", types);
4197+
writeDirectives("lib", libs);
42034198
}
42044199

42054200
function emitSourceFileWorker(node: SourceFile) {

src/compiler/parser.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -10510,19 +10510,20 @@ export function processPragmasIntoFields(context: PragmaContext, reportDiagnosti
1051010510
const typeReferenceDirectives = context.typeReferenceDirectives;
1051110511
const libReferenceDirectives = context.libReferenceDirectives;
1051210512
forEach(toArray(entryOrList) as PragmaPseudoMap["reference"][], arg => {
10513-
const { types, lib, path, ["resolution-mode"]: res } = arg.arguments;
10513+
const { types, lib, path, ["resolution-mode"]: res, preserve: _preserve } = arg.arguments;
10514+
const preserve = _preserve === "true" ? true : undefined;
1051410515
if (arg.arguments["no-default-lib"] === "true") {
1051510516
context.hasNoDefaultLib = true;
1051610517
}
1051710518
else if (types) {
1051810519
const parsed = parseResolutionMode(res, types.pos, types.end, reportDiagnostic);
10519-
typeReferenceDirectives.push({ pos: types.pos, end: types.end, fileName: types.value, ...(parsed ? { resolutionMode: parsed } : {}) });
10520+
typeReferenceDirectives.push({ pos: types.pos, end: types.end, fileName: types.value, ...(parsed ? { resolutionMode: parsed } : {}), ...(preserve ? { preserve } : {}) });
1052010521
}
1052110522
else if (lib) {
10522-
libReferenceDirectives.push({ pos: lib.pos, end: lib.end, fileName: lib.value });
10523+
libReferenceDirectives.push({ pos: lib.pos, end: lib.end, fileName: lib.value, ...(preserve ? { preserve } : {}) });
1052310524
}
1052410525
else if (path) {
10525-
referencedFiles.push({ pos: path.pos, end: path.end, fileName: path.value });
10526+
referencedFiles.push({ pos: path.pos, end: path.end, fileName: path.value, ...(preserve ? { preserve } : {}) });
1052610527
}
1052710528
else {
1052810529
reportDiagnostic(arg.range.pos, arg.range.end - arg.range.pos, Diagnostics.Invalid_reference_directive_syntax);

src/compiler/program.ts

-1
Original file line numberDiff line numberDiff line change
@@ -2630,7 +2630,6 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
26302630
getSourceFile: program.getSourceFile,
26312631
getSourceFileByPath: program.getSourceFileByPath,
26322632
getSourceFiles: program.getSourceFiles,
2633-
getLibFileFromReference: program.getLibFileFromReference,
26342633
isSourceFileFromExternalLibrary,
26352634
getResolvedProjectReferenceToRedirect,
26362635
getProjectReferenceRedirect,

0 commit comments

Comments
 (0)