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 all 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
2 changes: 1 addition & 1 deletion src/compiler/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ namespace ts {
const options = program.getCompilerOptions();
forEach(program.getSourceFiles(), f =>
program.isSourceFileDefaultLibrary(f) &&
!skipTypeChecking(f, options) &&
!skipTypeChecking(f, options, program) &&
removeSemanticDiagnosticsOf(state, f.path)
);
}
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@ namespace ts {
return node && getTypeArgumentConstraint(node);
},
getSuggestionDiagnostics: (file, ct) => {
if (skipTypeChecking(file, compilerOptions)) {
if (skipTypeChecking(file, compilerOptions, host)) {
return emptyArray;
}

Expand Down Expand Up @@ -30718,7 +30718,7 @@ namespace ts {
function checkSourceFileWorker(node: SourceFile) {
const links = getNodeLinks(node);
if (!(links.flags & NodeCheckFlags.TypeChecked)) {
if (skipTypeChecking(node, compilerOptions)) {
if (skipTypeChecking(node, compilerOptions, host)) {
return;
}

Expand Down
6 changes: 6 additions & 0 deletions src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,12 @@ namespace ts {
category: Diagnostics.Advanced_Options,
description: Diagnostics.Disable_size_limitations_on_JavaScript_projects
},
{
name: "disableSourceOfProjectReferenceRedirect",
type: "boolean",
category: Diagnostics.Advanced_Options,
description: Diagnostics.Disable_use_of_source_files_instead_of_declaration_files_from_referenced_projects
},
{
name: "noImplicitUseStrict",
type: "boolean",
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -4003,6 +4003,10 @@
"category": "Message",
"code": 6220
},
"Disable use of source files instead of declaration files from referenced projects.": {
"category": "Message",
"code": 6221
},

"Projects to reference": {
"category": "Message",
Expand Down
98 changes: 87 additions & 11 deletions src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,8 @@ namespace ts {
let resolvedProjectReferences: readonly (ResolvedProjectReference | undefined)[] | undefined;
let projectReferenceRedirects: Map<ResolvedProjectReference | false> | undefined;
let mapFromFileToProjectReferenceRedirects: Map<Path> | undefined;
let mapFromToProjectReferenceRedirectSource: Map<SourceOfProjectReferenceRedirect> | undefined;
const useSourceOfProjectReferenceRedirect = !!host.useSourceOfProjectReferenceRedirect && host.useSourceOfProjectReferenceRedirect();

const shouldCreateNewSourceFile = shouldProgramCreateNewSourceFiles(oldProgram, options);
// We set `structuralIsReused` to `undefined` because `tryReuseStructureFromOldProgram` calls `tryReuseStructureFromOldProgram` which checks
Expand All @@ -831,17 +833,32 @@ namespace ts {
if (!resolvedProjectReferences) {
resolvedProjectReferences = projectReferences.map(parseProjectReferenceConfigFile);
}
if (host.setResolvedProjectReferenceCallbacks) {
host.setResolvedProjectReferenceCallbacks({
getSourceOfProjectReferenceRedirect,
forEachResolvedProjectReference
});
}
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 (useSourceOfProjectReferenceRedirect) {
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 @@ -955,6 +972,7 @@ namespace ts {
getResolvedProjectReferenceToRedirect,
getResolvedProjectReferenceByPath,
forEachResolvedProjectReference,
isSourceOfProjectReferenceRedirect,
emitBuildInfo
};

Expand Down Expand Up @@ -987,9 +1005,15 @@ namespace ts {
return ts.toPath(fileName, currentDirectory, getCanonicalFileName);
}

function isValidSourceFileForEmit(file: SourceFile) {
// source file is allowed to be emitted and its not source of project reference redirect
return sourceFileMayBeEmitted(file, options, isSourceFileFromExternalLibrary, getResolvedProjectReferenceToRedirect) &&
!isSourceOfProjectReferenceRedirect(file.fileName);
}

function getCommonSourceDirectory() {
if (commonSourceDirectory === undefined) {
const emittedFiles = filter(files, file => sourceFileMayBeEmitted(file, options, isSourceFileFromExternalLibrary, getResolvedProjectReferenceToRedirect));
const emittedFiles = filter(files, file => isValidSourceFileForEmit(file));
if (options.rootDir && checkSourceFilesBelongToPath(emittedFiles, options.rootDir)) {
// If a rootDir is specified use it as the commonSourceDirectory
commonSourceDirectory = getNormalizedAbsolutePath(options.rootDir, currentDirectory);
Expand Down Expand Up @@ -1220,6 +1244,12 @@ namespace ts {
}
if (projectReferences) {
resolvedProjectReferences = projectReferences.map(parseProjectReferenceConfigFile);
if (host.setResolvedProjectReferenceCallbacks) {
host.setResolvedProjectReferenceCallbacks({
getSourceOfProjectReferenceRedirect,
forEachResolvedProjectReference
});
}
}

// check if program source files has changed in the way that can affect structure of the program
Expand Down Expand Up @@ -1403,6 +1433,13 @@ namespace ts {
for (const newSourceFile of newSourceFiles) {
const filePath = newSourceFile.path;
addFileToFilesByName(newSourceFile, filePath, newSourceFile.resolvedPath);
if (useSourceOfProjectReferenceRedirect) {
const redirectProject = getProjectReferenceRedirectProject(newSourceFile.fileName);
if (redirectProject && !(redirectProject.commandLine.options.outFile || redirectProject.commandLine.options.out)) {
const redirect = getProjectReferenceOutputName(redirectProject, newSourceFile.fileName);
addFileToFilesByName(newSourceFile, toPath(redirect), /*redirectedPath*/ undefined);
}
}
// Set the file as found during node modules search if it was found that way in old progra,
if (oldProgram.isSourceFileFromExternalLibrary(oldProgram.getSourceFileByPath(newSourceFile.resolvedPath)!)) {
sourceFilesFoundSearchingNodeModules.set(filePath, true);
Expand Down Expand Up @@ -1680,7 +1717,7 @@ namespace ts {

function getSemanticDiagnosticsForFileNoCache(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] | undefined {
return runWithCancellationToken(() => {
if (skipTypeChecking(sourceFile, options)) {
if (skipTypeChecking(sourceFile, options, program)) {
return emptyArray;
}

Expand Down Expand Up @@ -2233,6 +2270,16 @@ namespace ts {

// Get source file from normalized fileName
function findSourceFile(fileName: string, path: Path, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, refFile: RefFile | undefined, packageId: PackageId | undefined): SourceFile | undefined {
if (useSourceOfProjectReferenceRedirect) {
const source = getSourceOfProjectReferenceRedirect(fileName);
if (source) {
const file = isString(source) ?
findSourceFile(source, toPath(source), isDefaultLib, ignoreNoDefaultLib, refFile, packageId) :
undefined;
if (file) addFileToFilesByName(file, path, /*redirectedPath*/ undefined);
return file;
}
}
const originalFileName = fileName;
if (filesByName.has(path)) {
const file = filesByName.get(path);
Expand Down Expand Up @@ -2281,7 +2328,7 @@ namespace ts {
}

let redirectedPath: Path | undefined;
if (refFile) {
if (refFile && !useSourceOfProjectReferenceRedirect) {
const redirectProject = getProjectReferenceRedirectProject(fileName);
if (redirectProject) {
if (redirectProject.commandLine.options.outFile || redirectProject.commandLine.options.out) {
Expand Down Expand Up @@ -2450,6 +2497,36 @@ 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 => {
if (!fileExtensionIs(fileName, Extension.Dts) && hasTSFileExtension(fileName)) {
const outputDts = getOutputDeclarationFileName(fileName, resolvedRef.commandLine, host.useCaseSensitiveFileNames());
mapFromToProjectReferenceRedirectSource!.set(toPath(outputDts), fileName);
}
});
}
}
});
}
return mapFromToProjectReferenceRedirectSource.get(toPath(file));
}

function isSourceOfProjectReferenceRedirect(fileName: string) {
return useSourceOfProjectReferenceRedirect && !!getResolvedProjectReferenceToRedirect(fileName);
}

function forEachProjectReference<T>(
projectReferences: readonly ProjectReference[] | undefined,
resolvedProjectReferences: readonly (ResolvedProjectReference | undefined)[] | undefined,
Expand Down Expand Up @@ -2861,8 +2938,7 @@ namespace ts {
const rootPaths = arrayToSet(rootNames, toPath);
for (const file of files) {
// Ignore file that is not emitted
if (!sourceFileMayBeEmitted(file, options, isSourceFileFromExternalLibrary, getResolvedProjectReferenceToRedirect)) continue;
if (!rootPaths.has(file.path)) {
if (isValidSourceFileForEmit(file) && !rootPaths.has(file.path)) {
addProgramDiagnosticAtRefPath(
file,
rootPaths,
Expand Down
47 changes: 28 additions & 19 deletions src/compiler/sys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,33 @@ namespace ts {
}
}

function recursiveCreateDirectory(directoryPath: string, sys: System) {
const basePath = getDirectoryPath(directoryPath);
const shouldCreateParent = basePath !== "" && directoryPath !== basePath && !sys.directoryExists(basePath);
if (shouldCreateParent) {
recursiveCreateDirectory(basePath, sys);
}
if (shouldCreateParent || !sys.directoryExists(directoryPath)) {
sys.createDirectory(directoryPath);
}
}

/**
* patch writefile to create folder before writing the file
*/
/*@internal*/
export function patchWriteFileEnsuringDirectory(sys: System) {
// patch writefile to create folder before writing the file
const originalWriteFile = sys.writeFile;
sys.writeFile = (path, data, writeBom) => {
const directoryPath = getDirectoryPath(normalizeSlashes(path));
if (directoryPath && !sys.directoryExists(directoryPath)) {
recursiveCreateDirectory(directoryPath, sys);
}
originalWriteFile.call(sys, path, data, writeBom);
};
}

/*@internal*/
export type BufferEncoding = "ascii" | "utf8" | "utf-8" | "utf16le" | "ucs2" | "ucs-2" | "base64" | "latin1" | "binary" | "hex";

Expand Down Expand Up @@ -1365,17 +1392,6 @@ namespace ts {
};
}

function recursiveCreateDirectory(directoryPath: string, sys: System) {
const basePath = getDirectoryPath(directoryPath);
const shouldCreateParent = basePath !== "" && directoryPath !== basePath && !sys.directoryExists(basePath);
if (shouldCreateParent) {
recursiveCreateDirectory(basePath, sys);
}
if (shouldCreateParent || !sys.directoryExists(directoryPath)) {
sys.createDirectory(directoryPath);
}
}

let sys: System | undefined;
if (typeof ChakraHost !== "undefined") {
sys = getChakraSystem();
Expand All @@ -1387,14 +1403,7 @@ namespace ts {
}
if (sys) {
// patch writefile to create folder before writing the file
const originalWriteFile = sys.writeFile;
sys.writeFile = (path, data, writeBom) => {
const directoryPath = getDirectoryPath(normalizeSlashes(path));
if (directoryPath && !sys!.directoryExists(directoryPath)) {
recursiveCreateDirectory(directoryPath, sys!);
}
originalWriteFile.call(sys, path, data, writeBom);
};
patchWriteFileEnsuringDirectory(sys);
}
return sys!;
})();
Expand Down
15 changes: 15 additions & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3037,6 +3037,7 @@ namespace ts {
/*@internal*/ getResolvedProjectReferenceToRedirect(fileName: string): ResolvedProjectReference | undefined;
/*@internal*/ forEachResolvedProjectReference<T>(cb: (resolvedProjectReference: ResolvedProjectReference | undefined, resolvedProjectReferencePath: Path) => T | undefined): T | undefined;
/*@internal*/ getResolvedProjectReferenceByPath(projectReferencePath: Path): ResolvedProjectReference | undefined;
/*@internal*/ isSourceOfProjectReferenceRedirect(fileName: string): boolean;
/*@internal*/ getProgramBuildInfo?(): ProgramBuildInfo | undefined;
/*@internal*/ emitBuildInfo(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken): EmitResult;
}
Expand Down Expand Up @@ -3137,6 +3138,7 @@ namespace ts {
getSourceFile(fileName: string): SourceFile | undefined;
getResolvedTypeReferenceDirectives(): ReadonlyMap<ResolvedTypeReferenceDirective | undefined>;
getProjectReferenceRedirect(fileName: string): string | undefined;
isSourceOfProjectReferenceRedirect(fileName: string): boolean;

readonly redirectTargetsMap: RedirectTargetsMap;
}
Expand Down Expand Up @@ -4723,6 +4725,7 @@ namespace ts {
/* @internal */ diagnostics?: boolean;
/* @internal */ extendedDiagnostics?: boolean;
disableSizeLimit?: boolean;
disableSourceOfProjectReferenceRedirect?: boolean;
downlevelIteration?: boolean;
emitBOM?: boolean;
emitDecoratorMetadata?: boolean;
Expand Down Expand Up @@ -5251,11 +5254,23 @@ namespace ts {
/* @internal */ hasChangedAutomaticTypeDirectiveNames?: boolean;
createHash?(data: string): string;
getParsedCommandLine?(fileName: string): ParsedCommandLine | undefined;
/* @internal */ setResolvedProjectReferenceCallbacks?(callbacks: ResolvedProjectReferenceCallbacks): void;
/* @internal */ useSourceOfProjectReferenceRedirect?(): 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 interface ResolvedProjectReferenceCallbacks {
getSourceOfProjectReferenceRedirect(fileName: string): SourceOfProjectReferenceRedirect | undefined;
forEachResolvedProjectReference<T>(cb: (resolvedProjectReference: ResolvedProjectReference | undefined, resolvedProjectReferencePath: Path) => T | undefined): T | undefined;
}

/* @internal */
export const enum TransformFlags {
None = 0,
Expand Down
Loading