Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

For editing experience, use source instead of .d.ts files from project references #32028

Merged
merged 33 commits into from
Sep 24, 2019
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
d0282b7
Add test to verify when source changes
sheetalkamat Jun 13, 2019
0adab89
Use source files instead of .d.ts files from project references
sheetalkamat Jun 21, 2019
c97be16
Log the config of the project
sheetalkamat Jun 21, 2019
746b01e
Check only for .d.ts files
sheetalkamat Jun 21, 2019
ecf8751
Check for language serivice enabled when including source files
sheetalkamat Jun 21, 2019
1810288
Fix tests
sheetalkamat Jun 21, 2019
f472868
Watch generated file if it doesnt exist when trying to translate it t…
sheetalkamat Jun 25, 2019
012ecda
Add sourceOf project reference redirect to filesByName list for redir…
sheetalkamat Jun 26, 2019
2f30add
More tests
sheetalkamat Jun 26, 2019
da9260c
Create original project when location is in source of project referen…
sheetalkamat Jun 26, 2019
75bd3cd
Fix more tests
sheetalkamat Jun 27, 2019
96a8c86
Merge branch 'master' into referencesPrototypeSourceFile
sheetalkamat Jun 28, 2019
f72af3b
Verify the scenarios when d.ts directory of dependency doesnt exist
sheetalkamat Jun 28, 2019
4d13f53
Merge branch 'master' into referencesPrototypeSourceFile
sheetalkamat Jul 1, 2019
f9e4b91
Fix incorrectly exported type
sheetalkamat Jul 1, 2019
f7ea0ba
Refactoring
sheetalkamat Jul 1, 2019
b5737fc
Refactor tests so its easy to edit and reason about them
sheetalkamat Jul 2, 2019
15b68a9
Skip typechecking of source of project reference redirect
sheetalkamat Jul 1, 2019
9be475b
Refactoring
sheetalkamat Jul 3, 2019
b1fa2eb
Errors using DiagnosticsSync commands
sheetalkamat Jul 5, 2019
824c22c
Source of project reference behave as if those files cannot be emitted.
sheetalkamat Jul 8, 2019
b631850
Add option disableSourceOfProjectReferenceRedirect to disable using s…
sheetalkamat Jul 10, 2019
103fe5f
Merge branch 'master' into referencesPrototypeSourceFile
sheetalkamat Jul 11, 2019
666c4be
Merge branch 'master' into referencesPrototypeSourceFile
sheetalkamat Jul 25, 2019
4c4ddf8
Merge branch 'master' into referencesPrototypeSourceFile
sheetalkamat Aug 21, 2019
c6e502b
Verify config file errors
sheetalkamat Aug 22, 2019
076dde4
Test with --out as well
sheetalkamat Aug 22, 2019
a469fd8
Should not report that files are not part of config for files that ar…
sheetalkamat Aug 22, 2019
6e09169
Merge branch 'master' into referencesPrototypeSourceFile
sheetalkamat Aug 22, 2019
54d9ce9
Merge branch 'master' into referencesPrototypeSourceFile
sheetalkamat Sep 5, 2019
b26ca16
Merge branch 'master' into referencesPrototypeSourceFile
sheetalkamat Sep 11, 2019
432da93
Add doc comments for fileExists and directoryExists implementation
sheetalkamat Sep 23, 2019
fd3ba67
Reword the option description per feedback
sheetalkamat Sep 24, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 70 additions & 16 deletions src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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);
}
}
}
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand All @@ -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);
Expand Down Expand Up @@ -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,
Expand Down
9 changes: 9 additions & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions src/server/editorServices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down Expand Up @@ -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);
Expand Down
26 changes: 26 additions & 0 deletions src/server/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -1414,6 +1420,25 @@ namespace ts.server {
this.canonicalConfigFilePath = asNormalizedPath(projectService.toCanonicalFileName(configFileName));
}

/* @internal */
setGetSourceOfProjectReferenceRedirect(getSource: GetSourceOfProjectReferenceRedirect) {
this.getSourceOfProjectReferenceRedirect = getSource;
}

/* @internal */
useSourceInsteadOfReferenceRedirect() {
return true;
sheetalkamat marked this conversation as resolved.
Show resolved Hide resolved
}

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.
Expand All @@ -1436,6 +1461,7 @@ namespace ts.server {
default:
result = super.updateGraph();
}
this.getSourceOfProjectReferenceRedirect = undefined;
this.projectService.sendProjectLoadingFinishEvent(this);
this.projectService.sendProjectTelemetry(this);
return result;
Expand Down
6 changes: 6 additions & 0 deletions src/services/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
4 changes: 4 additions & 0 deletions src/services/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
Loading