mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-15 11:35:42 -06:00
Use source files instead of .d.ts files from project references
This commit is contained in:
parent
d0282b75a1
commit
0adab8934a
@ -813,6 +813,8 @@ namespace ts {
|
||||
let resolvedProjectReferences: ReadonlyArray<ResolvedProjectReference | undefined> | undefined;
|
||||
let projectReferenceRedirects: Map<ResolvedProjectReference | false> | undefined;
|
||||
let mapFromFileToProjectReferenceRedirects: Map<Path> | undefined;
|
||||
let mapFromToProjectReferenceRedirectSource: Map<SourceOfProjectReferenceRedirect> | undefined;
|
||||
const useSourceOfReference = host.useSourceInsteadOfReferenceRedirect && host.useSourceInsteadOfReferenceRedirect();
|
||||
|
||||
const shouldCreateNewSourceFile = shouldProgramCreateNewSourceFiles(oldProgram, options);
|
||||
const structuralIsReused = tryReuseStructureFromOldProgram();
|
||||
@ -824,17 +826,29 @@ namespace ts {
|
||||
if (!resolvedProjectReferences) {
|
||||
resolvedProjectReferences = projectReferences.map(parseProjectReferenceConfigFile);
|
||||
}
|
||||
if (host.setGetSourceOfProjectReferenceRedirect) {
|
||||
host.setGetSourceOfProjectReferenceRedirect(getSourceOfProjectReferenceRedirect);
|
||||
}
|
||||
if (rootNames.length) {
|
||||
for (const parsedRef of resolvedProjectReferences) {
|
||||
if (!parsedRef) continue;
|
||||
const out = parsedRef.commandLine.options.outFile || parsedRef.commandLine.options.out;
|
||||
if (out) {
|
||||
processSourceFile(changeExtension(out, ".d.ts"), /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined);
|
||||
if (useSourceOfReference) {
|
||||
if (out || getEmitModuleKind(parsedRef.commandLine.options) === ModuleKind.None) {
|
||||
for (const fileName of parsedRef.commandLine.fileNames) {
|
||||
processSourceFile(fileName, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (getEmitModuleKind(parsedRef.commandLine.options) === ModuleKind.None) {
|
||||
for (const fileName of parsedRef.commandLine.fileNames) {
|
||||
if (!fileExtensionIs(fileName, Extension.Dts) && hasTSFileExtension(fileName)) {
|
||||
processSourceFile(getOutputDeclarationFileName(fileName, parsedRef.commandLine, !host.useCaseSensitiveFileNames()), /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined);
|
||||
else {
|
||||
if (out) {
|
||||
processSourceFile(changeExtension(out, ".d.ts"), /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined);
|
||||
}
|
||||
else if (getEmitModuleKind(parsedRef.commandLine.options) === ModuleKind.None) {
|
||||
for (const fileName of parsedRef.commandLine.fileNames) {
|
||||
if (!fileExtensionIs(fileName, Extension.Dts) && hasTSFileExtension(fileName)) {
|
||||
processSourceFile(getOutputDeclarationFileName(fileName, parsedRef.commandLine, !host.useCaseSensitiveFileNames()), /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1212,6 +1226,9 @@ namespace ts {
|
||||
}
|
||||
if (projectReferences) {
|
||||
resolvedProjectReferences = projectReferences.map(parseProjectReferenceConfigFile);
|
||||
if (host.setGetSourceOfProjectReferenceRedirect) {
|
||||
host.setGetSourceOfProjectReferenceRedirect(getSourceOfProjectReferenceRedirect);
|
||||
}
|
||||
}
|
||||
|
||||
// check if program source files has changed in the way that can affect structure of the program
|
||||
@ -2220,6 +2237,14 @@ namespace ts {
|
||||
|
||||
// Get source file from normalized fileName
|
||||
function findSourceFile(fileName: string, path: Path, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, refFile: SourceFile, refPos: number, refEnd: number, packageId: PackageId | undefined): SourceFile | undefined {
|
||||
if (useSourceOfReference) {
|
||||
const source = getSourceOfProjectReferenceRedirect(fileName);
|
||||
if (source) {
|
||||
return isString(source) ?
|
||||
findSourceFile(source, toPath(source), isDefaultLib, ignoreNoDefaultLib, refFile, refPos, refEnd, packageId) :
|
||||
undefined;
|
||||
}
|
||||
}
|
||||
const originalFileName = fileName;
|
||||
if (filesByName.has(path)) {
|
||||
const file = filesByName.get(path);
|
||||
@ -2267,7 +2292,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
let redirectedPath: Path | undefined;
|
||||
if (refFile) {
|
||||
if (refFile && !useSourceOfReference) {
|
||||
const redirectProject = getProjectReferenceRedirectProject(fileName);
|
||||
if (redirectProject) {
|
||||
if (redirectProject.commandLine.options.outFile || redirectProject.commandLine.options.out) {
|
||||
@ -2286,15 +2311,20 @@ namespace ts {
|
||||
}
|
||||
|
||||
// We haven't looked for this file, do so now and cache result
|
||||
const file = host.getSourceFile(fileName, options.target!, hostErrorMessage => { // TODO: GH#18217
|
||||
if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) {
|
||||
fileProcessingDiagnostics.add(createFileDiagnostic(refFile, refPos, refEnd - refPos,
|
||||
Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage));
|
||||
}
|
||||
else {
|
||||
fileProcessingDiagnostics.add(createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage));
|
||||
}
|
||||
}, shouldCreateNewSourceFile);
|
||||
const file = host.getSourceFile(
|
||||
fileName,
|
||||
options.target!,
|
||||
hostErrorMessage => { // TODO: GH#18217
|
||||
if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) {
|
||||
fileProcessingDiagnostics.add(createFileDiagnostic(refFile, refPos, refEnd - refPos,
|
||||
Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage));
|
||||
}
|
||||
else {
|
||||
fileProcessingDiagnostics.add(createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage));
|
||||
}
|
||||
},
|
||||
shouldCreateNewSourceFile
|
||||
);
|
||||
|
||||
if (packageId) {
|
||||
const packageIdKey = packageIdToString(packageId);
|
||||
@ -2424,6 +2454,30 @@ namespace ts {
|
||||
});
|
||||
}
|
||||
|
||||
function getSourceOfProjectReferenceRedirect(file: string) {
|
||||
if (!isDeclarationFileName(file)) return undefined;
|
||||
if (mapFromToProjectReferenceRedirectSource === undefined) {
|
||||
mapFromToProjectReferenceRedirectSource = createMap();
|
||||
forEachResolvedProjectReference(resolvedRef => {
|
||||
if (resolvedRef) {
|
||||
const out = resolvedRef.commandLine.options.outFile || resolvedRef.commandLine.options.out;
|
||||
if (out) {
|
||||
// Dont know which source file it means so return true?
|
||||
const outputDts = changeExtension(out, Extension.Dts);
|
||||
mapFromToProjectReferenceRedirectSource!.set(toPath(outputDts), true);
|
||||
}
|
||||
else {
|
||||
forEach(resolvedRef.commandLine.fileNames, fileName => {
|
||||
const outputDts = getOutputDeclarationFileName(fileName, resolvedRef.commandLine, host.useCaseSensitiveFileNames());
|
||||
mapFromToProjectReferenceRedirectSource!.set(toPath(outputDts), fileName);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return mapFromToProjectReferenceRedirectSource.get(toPath(file));
|
||||
}
|
||||
|
||||
function forEachProjectReference<T>(
|
||||
projectReferences: ReadonlyArray<ProjectReference> | undefined,
|
||||
resolvedProjectReferences: ReadonlyArray<ResolvedProjectReference | undefined> | undefined,
|
||||
|
||||
@ -5166,11 +5166,20 @@ namespace ts {
|
||||
/* @internal */ hasChangedAutomaticTypeDirectiveNames?: boolean;
|
||||
createHash?(data: string): string;
|
||||
getParsedCommandLine?(fileName: string): ParsedCommandLine | undefined;
|
||||
/* @internal */ setGetSourceOfProjectReferenceRedirect?(getSource: GetSourceOfProjectReferenceRedirect): void;
|
||||
/* @internal */ useSourceInsteadOfReferenceRedirect?(): boolean;
|
||||
|
||||
// TODO: later handle this in better way in builder host instead once the api for tsbuild finalizes and doesn't use compilerHost as base
|
||||
/*@internal*/createDirectory?(directory: string): void;
|
||||
}
|
||||
|
||||
/** true if --out otherwise source file name */
|
||||
/*@internal*/
|
||||
export type SourceOfProjectReferenceRedirect = string | true ;
|
||||
|
||||
/*@internal*/
|
||||
export type GetSourceOfProjectReferenceRedirect = (fileName: string) => SourceOfProjectReferenceRedirect | undefined;
|
||||
|
||||
/* @internal */
|
||||
export const enum TransformFlags {
|
||||
None = 0,
|
||||
|
||||
@ -1798,7 +1798,7 @@ namespace ts.server {
|
||||
let scriptInfo: ScriptInfo | NormalizedPath;
|
||||
let path: Path;
|
||||
// Use the project's fileExists so that it can use caching instead of reaching to disk for the query
|
||||
if (!isDynamic && !project.fileExists(newRootFile)) {
|
||||
if (!isDynamic && !project.fileExistsWithCache(newRootFile)) {
|
||||
path = normalizedPathToPath(normalizedPath, this.currentDirectory, this.toCanonicalFileName);
|
||||
const existingValue = projectRootFilesMap.get(path)!;
|
||||
if (isScriptInfo(existingValue)) {
|
||||
@ -1831,7 +1831,7 @@ namespace ts.server {
|
||||
projectRootFilesMap.forEach((value, path) => {
|
||||
if (!newRootScriptInfoMap.has(path)) {
|
||||
if (isScriptInfo(value)) {
|
||||
project.removeFile(value, project.fileExists(path), /*detachFromProject*/ true);
|
||||
project.removeFile(value, project.fileExistsWithCache(path), /*detachFromProject*/ true);
|
||||
}
|
||||
else {
|
||||
projectRootFilesMap.delete(path);
|
||||
|
||||
@ -381,6 +381,11 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
fileExists(file: string): boolean {
|
||||
return this.fileExistsWithCache(file);
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
fileExistsWithCache(file: string): boolean {
|
||||
// As an optimization, don't hit the disks for files we already know don't exist
|
||||
// (because we're watching for their creation).
|
||||
const path = this.toPath(file);
|
||||
@ -1369,6 +1374,7 @@ namespace ts.server {
|
||||
configFileWatcher: FileWatcher | undefined;
|
||||
private directoriesWatchedForWildcards: Map<WildcardDirectoryWatcher> | undefined;
|
||||
readonly canonicalConfigFilePath: NormalizedPath;
|
||||
private getSourceOfProjectReferenceRedirect: GetSourceOfProjectReferenceRedirect | undefined;
|
||||
|
||||
/* @internal */
|
||||
pendingReload: ConfigFileProgramReloadLevel | undefined;
|
||||
@ -1414,6 +1420,25 @@ namespace ts.server {
|
||||
this.canonicalConfigFilePath = asNormalizedPath(projectService.toCanonicalFileName(configFileName));
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
setGetSourceOfProjectReferenceRedirect(getSource: GetSourceOfProjectReferenceRedirect) {
|
||||
this.getSourceOfProjectReferenceRedirect = getSource;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
useSourceInsteadOfReferenceRedirect() {
|
||||
return true;
|
||||
}
|
||||
|
||||
fileExists(file: string): boolean {
|
||||
// Project references go to source file instead of .d.ts file
|
||||
if (this.getSourceOfProjectReferenceRedirect) {
|
||||
const source = this.getSourceOfProjectReferenceRedirect(file);
|
||||
if (source) return isString(source) ? super.fileExists(source) : true;
|
||||
}
|
||||
return super.fileExists(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the project has reload from disk pending, it reloads (and then updates graph as part of that) instead of just updating the graph
|
||||
* @returns: true if set of files in the project stays the same and false - otherwise.
|
||||
@ -1436,6 +1461,7 @@ namespace ts.server {
|
||||
default:
|
||||
result = super.updateGraph();
|
||||
}
|
||||
this.getSourceOfProjectReferenceRedirect = undefined;
|
||||
this.projectService.sendProjectLoadingFinishEvent(this);
|
||||
this.projectService.sendProjectTelemetry(this);
|
||||
return result;
|
||||
|
||||
@ -1245,6 +1245,12 @@ namespace ts {
|
||||
return host.resolveTypeReferenceDirectives!(typeReferenceDirectiveNames, containingFile, redirectedReference);
|
||||
};
|
||||
}
|
||||
if (host.setGetSourceOfProjectReferenceRedirect) {
|
||||
compilerHost.setGetSourceOfProjectReferenceRedirect = getSource => host.setGetSourceOfProjectReferenceRedirect!(getSource);
|
||||
}
|
||||
if (host.useSourceInsteadOfReferenceRedirect) {
|
||||
compilerHost.useSourceInsteadOfReferenceRedirect = () => host.useSourceInsteadOfReferenceRedirect!();
|
||||
}
|
||||
|
||||
const documentRegistryBucketKey = documentRegistry.getKeyForCompilationSettings(newSettings);
|
||||
const options: CreateProgramOptions = {
|
||||
|
||||
@ -236,6 +236,10 @@ namespace ts {
|
||||
getDocumentPositionMapper?(generatedFileName: string, sourceFileName?: string): DocumentPositionMapper | undefined;
|
||||
/* @internal */
|
||||
getSourceFileLike?(fileName: string): SourceFileLike | undefined;
|
||||
/* @internal */
|
||||
setGetSourceOfProjectReferenceRedirect?(getSource: GetSourceOfProjectReferenceRedirect): void;
|
||||
/* @internal */
|
||||
useSourceInsteadOfReferenceRedirect?(): boolean;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
||||
@ -8546,11 +8546,13 @@ declare namespace ts.server {
|
||||
private typeAcquisition;
|
||||
private directoriesWatchedForWildcards;
|
||||
readonly canonicalConfigFilePath: NormalizedPath;
|
||||
private getSourceOfProjectReferenceRedirect;
|
||||
/** Ref count to the project when opened from external project */
|
||||
private externalProjectRefCount;
|
||||
private projectErrors;
|
||||
private projectReferences;
|
||||
protected isInitialLoadPending: () => boolean;
|
||||
fileExists(file: string): boolean;
|
||||
/**
|
||||
* If the project has reload from disk pending, it reloads (and then updates graph as part of that) instead of just updating the graph
|
||||
* @returns: true if set of files in the project stays the same and false - otherwise.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user