The assert that cached value of config file existance is always correct, might not be true if file watcher is not invoked before creating configured project

Fixes #29191
This commit is contained in:
Sheetal Nandi
2019-01-02 15:39:15 -08:00
parent 799656a037
commit 24cc284d19
3 changed files with 77 additions and 3 deletions

View File

@@ -1277,7 +1277,8 @@ namespace ts.server {
private setConfigFileExistenceByNewConfiguredProject(project: ConfiguredProject) {
const configFileExistenceInfo = this.getConfigFileExistenceInfo(project);
if (configFileExistenceInfo) {
Debug.assert(configFileExistenceInfo.exists);
// The existance might not be set if the file watcher is not invoked by the time config project is created by external project
configFileExistenceInfo.exists = true;
// close existing watcher
if (configFileExistenceInfo.configFileWatcherForRootOfInferredProject) {
const configFileName = project.getConfigFilePath();

View File

@@ -760,5 +760,63 @@ namespace ts.projectSystem {
assert.equal(project2.pendingReload, ConfigFileProgramReloadLevel.None); // External project referenced configured project loaded
checkProjectActualFiles(project2, [config.path, f1.path]);
});
it("handles creation of external project with jsconfig before jsconfig creation watcher is invoked", () => {
const projectLocation = `/user/username/projects/WebApplication36/WebApplication36`;
const projectFileName = `${projectLocation}/WebApplication36.csproj`;
const tsconfig: File = {
path: `${projectLocation}/tsconfig.json`,
content: "{}"
};
const files = [libFile, tsconfig];
const host = createServerHost(files);
const service = createProjectService(host);
// Create external project
service.openExternalProjects([{
projectFileName,
rootFiles: [{ fileName: tsconfig.path }],
options: { allowJs: false }
}]);
checkNumberOfProjects(service, { configuredProjects: 1 });
const configProject = service.configuredProjects.get(tsconfig.path.toLowerCase())!;
checkProjectActualFiles(configProject, [tsconfig.path]);
// write js file, open external project and open it for edit
const jsFilePath = `${projectLocation}/javascript.js`;
host.writeFile(jsFilePath, "");
service.openExternalProjects([{
projectFileName,
rootFiles: [{ fileName: tsconfig.path }, { fileName: jsFilePath }],
options: { allowJs: false }
}]);
service.applyChangesInOpenFiles([
{ fileName: jsFilePath, scriptKind: ScriptKind.JS, content: "" }
], /*changedFiles*/ undefined, /*closedFiles*/ undefined);
checkNumberOfProjects(service, { configuredProjects: 1, inferredProjects: 1 });
checkProjectActualFiles(configProject, [tsconfig.path]);
const inferredProject = service.inferredProjects[0];
checkProjectActualFiles(inferredProject, [libFile.path, jsFilePath]);
// write jsconfig file
const jsConfig: File = {
path: `${projectLocation}/jsconfig.json`,
content: "{}"
};
// Dont invoke file creation watchers as the repro suggests
host.ensureFileOrFolder(jsConfig, /*ignoreWatchInvokedWithTriggerAsFileCreate*/ true);
// Open external project
service.openExternalProjects([{
projectFileName,
rootFiles: [{ fileName: jsConfig.path }, { fileName: tsconfig.path }, { fileName: jsFilePath }],
options: { allowJs: false }
}]);
checkNumberOfProjects(service, { configuredProjects: 2, inferredProjects: 1 });
checkProjectActualFiles(configProject, [tsconfig.path]);
assert.isTrue(inferredProject.isOrphan());
const jsConfigProject = service.configuredProjects.get(jsConfig.path.toLowerCase())!;
checkProjectActualFiles(jsConfigProject, [jsConfig.path, jsFilePath, libFile.path]);
});
});
}

View File

@@ -57,8 +57,8 @@ namespace ts.projectSystem {
export const nullLogger: server.Logger = {
close: noop,
hasLevel: () => false,
loggingEnabled: () => false,
hasLevel: returnFalse,
loggingEnabled: returnFalse,
perftrc: noop,
info: noop,
msg: noop,
@@ -80,6 +80,21 @@ namespace ts.projectSystem {
return { logger, hasErrorMsg: () => hasErrorMsg };
}
export function createLoggerWritingToConsole(): server.Logger {
const { close, startGroup, endGroup, getLogFileName } = nullLogger;
return {
close,
hasLevel: returnTrue,
loggingEnabled: returnTrue,
perftrc: s => console.log(s),
info: s => console.log(s),
msg: (s, type) => console.log(`${type}:: ${s}`),
startGroup,
endGroup,
getLogFileName
};
}
export class TestTypingsInstaller extends TI.TypingsInstaller implements server.ITypingsInstaller {
protected projectService!: server.ProjectService;
constructor(