Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
192 changes: 0 additions & 192 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -936,7 +936,6 @@ import {
ResolutionMode,
ResolvedModuleFull,
ResolvedType,
resolveTripleslashReference,
resolvingEmptyArray,
RestTypeNode,
ReturnStatement,
Expand Down Expand Up @@ -8087,14 +8086,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return file.moduleName;
}
if (!file) {
if (context.tracker.trackReferencedAmbientModule) {
const ambientDecls = filter(symbol.declarations, isAmbientModule);
if (length(ambientDecls)) {
for (const decl of ambientDecls!) {
context.tracker.trackReferencedAmbientModule(decl, symbol);
}
}
}
if (ambientModuleSymbolRegex.test(symbol.escapedName as string)) {
return (symbol.escapedName as string).substring(1, (symbol.escapedName as string).length - 1);
}
Expand Down Expand Up @@ -8206,7 +8197,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}
const lit = factory.createLiteralTypeNode(factory.createStringLiteral(specifier));
if (context.tracker.trackExternalModuleSymbolOfImportTypeNode) context.tracker.trackExternalModuleSymbolOfImportTypeNode(chain[0]);
context.approximateLength += specifier.length + 10; // specifier + import("")
if (!nonRootParts || isEntityName(nonRootParts)) {
if (nonRootParts) {
Expand Down Expand Up @@ -8789,14 +8779,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}
}
else {
if (context.tracker && context.tracker.trackExternalModuleSymbolOfImportTypeNode) {
const moduleSym = resolveExternalModuleNameWorker(lit, lit, /*moduleNotFoundError*/ undefined);
if (moduleSym) {
context.tracker.trackExternalModuleSymbolOfImportTypeNode(moduleSym);
}
}
}
return lit;
}
}
Expand Down Expand Up @@ -48227,35 +48209,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return !isPropertyName && getReferencedValueSymbol(node) === argumentsSymbol;
}

function moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean {
let moduleSymbol = resolveExternalModuleName(moduleReferenceExpression.parent, moduleReferenceExpression);
if (!moduleSymbol || isShorthandAmbientModuleSymbol(moduleSymbol)) {
// If the module is not found or is shorthand, assume that it may export a value.
return true;
}

const hasExportAssignment = hasExportAssignmentSymbol(moduleSymbol);
// if module has export assignment then 'resolveExternalModuleSymbol' will return resolved symbol for export assignment
// otherwise it will return moduleSymbol itself
moduleSymbol = resolveExternalModuleSymbol(moduleSymbol);

const symbolLinks = getSymbolLinks(moduleSymbol);
if (symbolLinks.exportsSomeValue === undefined) {
// for export assignments - check if resolved symbol for RHS is itself a value
// otherwise - check if at least one export is value
symbolLinks.exportsSomeValue = hasExportAssignment
? !!(moduleSymbol.flags & SymbolFlags.Value)
: forEachEntry(getExportsOfModule(moduleSymbol), isValue);
}

return symbolLinks.exportsSomeValue!;

function isValue(s: Symbol): boolean {
s = resolveSymbol(s);
return s && !!(getSymbolFlags(s) & SymbolFlags.Value);
}
}

function isNameOfModuleOrEnumDeclaration(node: Identifier) {
return isModuleOrEnumDeclaration(node.parent) && node === node.parent.name;
}
Expand Down Expand Up @@ -48899,26 +48852,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}

function createResolver(): EmitResolver {
// this variable and functions that use it are deliberately moved here from the outer scope
// to avoid scope pollution
const resolvedTypeReferenceDirectives = host.getResolvedTypeReferenceDirectives();
let fileToDirective: Map<string, [specifier: string, mode: ResolutionMode]>;
if (resolvedTypeReferenceDirectives) {
// populate reverse mapping: file path -> type reference directive that was resolved to this file
fileToDirective = new Map<string, [specifier: string, mode: ResolutionMode]>();
resolvedTypeReferenceDirectives.forEach(({ resolvedTypeReferenceDirective }, key, mode) => {
if (!resolvedTypeReferenceDirective?.resolvedFileName) {
return;
}
const file = host.getSourceFile(resolvedTypeReferenceDirective.resolvedFileName);
if (file) {
// Add the transitive closure of path references loaded by this file (as long as they are not)
// part of an existing type reference.
addReferencedFilesToTypeDirective(file, key, mode);
}
});
}

return {
getReferencedExportContainer,
getReferencedImportDeclaration,
Expand Down Expand Up @@ -48960,14 +48893,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
getReferencedValueDeclarations,
getTypeReferenceSerializationKind,
isOptionalParameter,
moduleExportsSomeValue,
isArgumentsLocalBinding,
getExternalModuleFileFromDeclaration: nodeIn => {
const node = getParseTreeNode(nodeIn, hasPossibleExternalModuleReference);
return node && getExternalModuleFileFromDeclaration(node);
},
getTypeReferenceDirectivesForEntityName,
getTypeReferenceDirectivesForSymbol,
isLiteralConstDeclaration,
isLateBound: (nodeIn: Declaration): nodeIn is LateBoundDeclaration => {
const node = getParseTreeNode(nodeIn, isDeclaration);
Expand All @@ -48991,7 +48921,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
getAccessor,
};
},
getSymbolOfExternalModuleSpecifier: moduleName => resolveExternalModuleNameWorker(moduleName, moduleName, /*moduleNotFoundError*/ undefined),
isBindingCapturedByNode: (node, decl) => {
const parseNode = getParseTreeNode(node);
const parseDecl = getParseTreeNode(decl);
Expand All @@ -49007,11 +48936,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return !sym.exports ? [] : nodeBuilder.symbolTableToDeclarationStatements(sym.exports, node, flags, tracker, bundled);
},
isImportRequiredByAugmentation,
tryFindAmbientModule: moduleReferenceExpression => {
const node = getParseTreeNode(moduleReferenceExpression);
const moduleSpecifier = node && isStringLiteralLike(node) ? node.text : undefined;
return moduleSpecifier !== undefined ? tryFindAmbientModule(moduleSpecifier, /*withAugmentations*/ true) : undefined;
},
};

function isImportRequiredByAugmentation(node: ImportDeclaration) {
Expand All @@ -49036,108 +48960,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
return false;
}

function isInHeritageClause(node: PropertyAccessEntityNameExpression) {
return node.parent && node.parent.kind === SyntaxKind.ExpressionWithTypeArguments && node.parent.parent && node.parent.parent.kind === SyntaxKind.HeritageClause;
}

// defined here to avoid outer scope pollution
function getTypeReferenceDirectivesForEntityName(node: EntityNameOrEntityNameExpression): [specifier: string, mode: ResolutionMode][] | undefined {
// program does not have any files with type reference directives - bail out
if (!fileToDirective) {
return undefined;
}
// computed property name should use node as value
// property access can only be used as values, or types when within an expression with type arguments inside a heritage clause
// qualified names can only be used as types\namespaces
// identifiers are treated as values only if they appear in type queries
let meaning;
if (node.parent.kind === SyntaxKind.ComputedPropertyName) {
meaning = SymbolFlags.Value | SymbolFlags.ExportValue;
}
else {
meaning = SymbolFlags.Type | SymbolFlags.Namespace;
if ((node.kind === SyntaxKind.Identifier && isInTypeQuery(node)) || (node.kind === SyntaxKind.PropertyAccessExpression && !isInHeritageClause(node))) {
meaning = SymbolFlags.Value | SymbolFlags.ExportValue;
}
}

const symbol = resolveEntityName(node, meaning, /*ignoreErrors*/ true);
return symbol && symbol !== unknownSymbol ? getTypeReferenceDirectivesForSymbol(symbol, meaning) : undefined;
}

// defined here to avoid outer scope pollution
function getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): [specifier: string, mode: ResolutionMode][] | undefined {
// program does not have any files with type reference directives - bail out
if (!fileToDirective || !isSymbolFromTypeDeclarationFile(symbol)) {
return undefined;
}
// check what declarations in the symbol can contribute to the target meaning
let typeReferenceDirectives: [specifier: string, mode: ResolutionMode][] | undefined;
for (const decl of symbol.declarations!) {
// check meaning of the local symbol to see if declaration needs to be analyzed further
if (decl.symbol && decl.symbol.flags & meaning!) {
const file = getSourceFileOfNode(decl);
const typeReferenceDirective = fileToDirective.get(file.path);
if (typeReferenceDirective) {
(typeReferenceDirectives || (typeReferenceDirectives = [])).push(typeReferenceDirective);
}
else {
// found at least one entry that does not originate from type reference directive
return undefined;
}
}
}
return typeReferenceDirectives;
}

function isSymbolFromTypeDeclarationFile(symbol: Symbol): boolean {
// bail out if symbol does not have associated declarations (i.e. this is transient symbol created for property in binding pattern)
if (!symbol.declarations) {
return false;
}

// walk the parent chain for symbols to make sure that top level parent symbol is in the global scope
// external modules cannot define or contribute to type declaration files
let current = symbol;
while (true) {
const parent = getParentOfSymbol(current);
if (parent) {
current = parent;
}
else {
break;
}
}

if (current.valueDeclaration && current.valueDeclaration.kind === SyntaxKind.SourceFile && current.flags & SymbolFlags.ValueModule) {
return false;
}

// check that at least one declaration of top level symbol originates from type declaration file
for (const decl of symbol.declarations) {
const file = getSourceFileOfNode(decl);
if (fileToDirective.has(file.path)) {
return true;
}
}
return false;
}

function addReferencedFilesToTypeDirective(file: SourceFile, key: string, mode: ResolutionMode) {
if (fileToDirective.has(file.path)) return;
fileToDirective.set(file.path, [key, mode]);
for (const { fileName } of file.referencedFiles) {
const resolvedFile = resolveTripleslashReference(fileName, file.fileName);
const referencedFile = host.getSourceFile(resolvedFile);
if (referencedFile) {
// The resolution mode of the file reference doesn't actually matter here -
// all we're recording is the fact that the file entered the compilation
// transitively via a type reference directive of {key} with mode {mode}.
addReferencedFilesToTypeDirective(referencedFile, key, mode || file.impliedNodeFormat);
}
}
}
}

function getExternalModuleFileFromDeclaration(declaration: AnyImportOrReExport | ModuleDeclaration | ImportTypeNode | ImportCall): SourceFile | undefined {
Expand Down Expand Up @@ -51499,20 +51321,6 @@ class SymbolTrackerImpl implements SymbolTracker {
}
}

trackReferencedAmbientModule(decl: ModuleDeclaration, symbol: Symbol): void {
if (this.inner?.trackReferencedAmbientModule) {
this.onDiagnosticReported();
this.inner.trackReferencedAmbientModule(decl, symbol);
}
}

trackExternalModuleSymbolOfImportTypeNode(symbol: Symbol): void {
if (this.inner?.trackExternalModuleSymbolOfImportTypeNode) {
this.onDiagnosticReported();
this.inner.trackExternalModuleSymbolOfImportTypeNode(symbol);
}
}

reportNonlocalAugmentation(containingFile: SourceFile, parentSymbol: Symbol, augmentingSymbol: Symbol): void {
if (this.inner?.reportNonlocalAugmentation) {
this.onDiagnosticReported();
Expand Down
33 changes: 14 additions & 19 deletions src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1106,20 +1106,15 @@ export const notImplementedResolver: EmitResolver = {
getReferencedValueDeclarations: notImplemented,
getTypeReferenceSerializationKind: notImplemented,
isOptionalParameter: notImplemented,
moduleExportsSomeValue: notImplemented,
isArgumentsLocalBinding: notImplemented,
getExternalModuleFileFromDeclaration: notImplemented,
getTypeReferenceDirectivesForEntityName: notImplemented,
getTypeReferenceDirectivesForSymbol: notImplemented,
isLiteralConstDeclaration: notImplemented,
getJsxFactoryEntity: notImplemented,
getJsxFragmentFactoryEntity: notImplemented,
getAllAccessorDeclarations: notImplemented,
getSymbolOfExternalModuleSpecifier: notImplemented,
isBindingCapturedByNode: notImplemented,
getDeclarationStatementsForSourceFile: notImplemented,
isImportRequiredByAugmentation: notImplemented,
tryFindAmbientModule: notImplemented,
};

const enum PipelinePhase {
Expand Down Expand Up @@ -4185,21 +4180,21 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
writeLine();
}
}
for (const directive of files) {
writeComment(`/// <reference path="${directive.fileName}" />`);
writeLine();
}
for (const directive of types) {
const resolutionMode = directive.resolutionMode && directive.resolutionMode !== currentSourceFile?.impliedNodeFormat
? `resolution-mode="${directive.resolutionMode === ModuleKind.ESNext ? "import" : "require"}"`
: "";
writeComment(`/// <reference types="${directive.fileName}" ${resolutionMode}/>`);
writeLine();
}
for (const directive of libs) {
writeComment(`/// <reference lib="${directive.fileName}" />`);
writeLine();

function writeDirectives(kind: "path" | "types" | "lib", directives: readonly FileReference[]) {
for (const directive of directives) {
const preserve = directive.preserve ? `preserve="true" ` : "";
const resolutionMode = directive.resolutionMode && directive.resolutionMode !== currentSourceFile?.impliedNodeFormat
? `resolution-mode="${directive.resolutionMode === ModuleKind.ESNext ? "import" : "require"}" `
: "";
writeComment(`/// <reference ${kind}="${directive.fileName}" ${resolutionMode}${preserve}/>`);
writeLine();
}
}

writeDirectives("path", files);
writeDirectives("types", types);
writeDirectives("lib", libs);
}

function emitSourceFileWorker(node: SourceFile) {
Expand Down
9 changes: 5 additions & 4 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10510,19 +10510,20 @@ export function processPragmasIntoFields(context: PragmaContext, reportDiagnosti
const typeReferenceDirectives = context.typeReferenceDirectives;
const libReferenceDirectives = context.libReferenceDirectives;
forEach(toArray(entryOrList) as PragmaPseudoMap["reference"][], arg => {
const { types, lib, path, ["resolution-mode"]: res } = arg.arguments;
const { types, lib, path, ["resolution-mode"]: res, preserve: _preserve } = arg.arguments;
const preserve = _preserve === "true" ? true : undefined;
if (arg.arguments["no-default-lib"] === "true") {
context.hasNoDefaultLib = true;
}
else if (types) {
const parsed = parseResolutionMode(res, types.pos, types.end, reportDiagnostic);
typeReferenceDirectives.push({ pos: types.pos, end: types.end, fileName: types.value, ...(parsed ? { resolutionMode: parsed } : {}) });
typeReferenceDirectives.push({ pos: types.pos, end: types.end, fileName: types.value, ...(parsed ? { resolutionMode: parsed } : {}), ...(preserve ? { preserve } : {}) });
}
else if (lib) {
libReferenceDirectives.push({ pos: lib.pos, end: lib.end, fileName: lib.value });
libReferenceDirectives.push({ pos: lib.pos, end: lib.end, fileName: lib.value, ...(preserve ? { preserve } : {}) });
}
else if (path) {
referencedFiles.push({ pos: path.pos, end: path.end, fileName: path.value });
referencedFiles.push({ pos: path.pos, end: path.end, fileName: path.value, ...(preserve ? { preserve } : {}) });
}
else {
reportDiagnostic(arg.range.pos, arg.range.end - arg.range.pos, Diagnostics.Invalid_reference_directive_syntax);
Expand Down
1 change: 0 additions & 1 deletion src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2630,7 +2630,6 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
getSourceFile: program.getSourceFile,
getSourceFileByPath: program.getSourceFileByPath,
getSourceFiles: program.getSourceFiles,
getLibFileFromReference: program.getLibFileFromReference,
isSourceFileFromExternalLibrary,
getResolvedProjectReferenceToRedirect,
getProjectReferenceRedirect,
Expand Down
Loading