mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge pull request #33647 from microsoft/defaultProject
Use correct default project for file if that project is opened at later time
This commit is contained in:
@@ -1533,6 +1533,14 @@ namespace ts.server {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
findDefaultConfiguredProject(info: ScriptInfo) {
|
||||
if (!info.isScriptOpen()) return undefined;
|
||||
const configFileName = this.getConfigFileNameForFile(info);
|
||||
return configFileName &&
|
||||
this.findConfiguredProjectByProjectName(configFileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function tries to search for a tsconfig.json for the given file.
|
||||
* This is different from the method the compiler uses because
|
||||
|
||||
@@ -491,21 +491,40 @@ namespace ts.server {
|
||||
case 1:
|
||||
return this.containingProjects[0];
|
||||
default:
|
||||
// if this file belongs to multiple projects, the first configured project should be
|
||||
// the default project; if no configured projects, the first external project should
|
||||
// be the default project; otherwise the first inferred project should be the default.
|
||||
// If this file belongs to multiple projects, below is the order in which default project is used
|
||||
// - for open script info, its default configured project during opening is default if info is part of it
|
||||
// - first configured project of which script info is not a source of project reference redirect
|
||||
// - first configured project
|
||||
// - first external project
|
||||
// - first inferred project
|
||||
let firstExternalProject;
|
||||
let firstConfiguredProject;
|
||||
for (const project of this.containingProjects) {
|
||||
let firstNonSourceOfProjectReferenceRedirect;
|
||||
let defaultConfiguredProject: ConfiguredProject | false | undefined;
|
||||
for (let index = 0; index < this.containingProjects.length; index++) {
|
||||
const project = this.containingProjects[index];
|
||||
if (project.projectKind === ProjectKind.Configured) {
|
||||
if (!project.isSourceOfProjectReferenceRedirect(this.fileName)) return project;
|
||||
if (!project.isSourceOfProjectReferenceRedirect(this.fileName)) {
|
||||
// If we havent found default configuredProject and
|
||||
// its not the last one, find it and use that one if there
|
||||
if (defaultConfiguredProject === undefined &&
|
||||
index !== this.containingProjects.length - 1) {
|
||||
defaultConfiguredProject = project.projectService.findDefaultConfiguredProject(this) || false;
|
||||
}
|
||||
if (defaultConfiguredProject === project) return project;
|
||||
if (!firstNonSourceOfProjectReferenceRedirect) firstNonSourceOfProjectReferenceRedirect = project;
|
||||
}
|
||||
if (!firstConfiguredProject) firstConfiguredProject = project;
|
||||
}
|
||||
else if (project.projectKind === ProjectKind.External && !firstExternalProject) {
|
||||
firstExternalProject = project;
|
||||
}
|
||||
}
|
||||
return firstConfiguredProject || firstExternalProject || this.containingProjects[0];
|
||||
return defaultConfiguredProject ||
|
||||
firstNonSourceOfProjectReferenceRedirect ||
|
||||
firstConfiguredProject ||
|
||||
firstExternalProject ||
|
||||
this.containingProjects[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
namespace ts.tscWatch {
|
||||
describe("unittests:: tsc-watch:: Emit times and Error updates in builder after program changes", () => {
|
||||
const currentDirectory = "/user/username/projects/myproject";
|
||||
const config: File = {
|
||||
path: `${currentDirectory}/tsconfig.json`,
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
content: `{}`
|
||||
};
|
||||
function getOutputFileStampAndError(host: WatchedSystem, watch: Watch, file: File) {
|
||||
@@ -83,7 +82,7 @@ namespace ts.tscWatch {
|
||||
const nonLibFiles = [...filesWithNewEmit, ...filesWithOnlyErrorRefresh, ...filesNotTouched];
|
||||
const files = [...nonLibFiles, configFile, libFile];
|
||||
const compilerOptions = (JSON.parse(configFile.content).compilerOptions || {}) as CompilerOptions;
|
||||
const host = createWatchedSystem(files, { currentDirectory });
|
||||
const host = createWatchedSystem(files, { currentDirectory: projectRoot });
|
||||
const watch = createWatchOfConfigFile("tsconfig.json", host);
|
||||
checkProgramActualFiles(watch(), [...nonLibFiles.map(f => f.path), libFile.path]);
|
||||
checkOutputErrorsInitial(host, getInitialErrors(watch));
|
||||
@@ -167,7 +166,7 @@ namespace ts.tscWatch {
|
||||
|
||||
describe("deep import changes", () => {
|
||||
const aFile: File = {
|
||||
path: `${currentDirectory}/a.ts`,
|
||||
path: `${projectRoot}/a.ts`,
|
||||
content: `import {B} from './b';
|
||||
declare var console: any;
|
||||
let b = new B();
|
||||
@@ -203,7 +202,7 @@ console.log(b.c.d);`
|
||||
|
||||
describe("updates errors when deep import file changes", () => {
|
||||
const bFile: File = {
|
||||
path: `${currentDirectory}/b.ts`,
|
||||
path: `${projectRoot}/b.ts`,
|
||||
content: `import {C} from './c';
|
||||
export class B
|
||||
{
|
||||
@@ -211,7 +210,7 @@ export class B
|
||||
}`
|
||||
};
|
||||
const cFile: File = {
|
||||
path: `${currentDirectory}/c.ts`,
|
||||
path: `${projectRoot}/c.ts`,
|
||||
content: `export class C
|
||||
{
|
||||
d = 1;
|
||||
@@ -222,7 +221,7 @@ export class B
|
||||
|
||||
describe("updates errors when deep import through declaration file changes", () => {
|
||||
const bFile: File = {
|
||||
path: `${currentDirectory}/b.d.ts`,
|
||||
path: `${projectRoot}/b.d.ts`,
|
||||
content: `import {C} from './c';
|
||||
export class B
|
||||
{
|
||||
@@ -230,7 +229,7 @@ export class B
|
||||
}`
|
||||
};
|
||||
const cFile: File = {
|
||||
path: `${currentDirectory}/c.d.ts`,
|
||||
path: `${projectRoot}/c.d.ts`,
|
||||
content: `export class C
|
||||
{
|
||||
d: number;
|
||||
@@ -242,7 +241,7 @@ export class B
|
||||
|
||||
describe("updates errors in file not exporting a deep multilevel import that changes", () => {
|
||||
const aFile: File = {
|
||||
path: `${currentDirectory}/a.ts`,
|
||||
path: `${projectRoot}/a.ts`,
|
||||
content: `export interface Point {
|
||||
name: string;
|
||||
c: Coords;
|
||||
@@ -253,13 +252,13 @@ export interface Coords {
|
||||
}`
|
||||
};
|
||||
const bFile: File = {
|
||||
path: `${currentDirectory}/b.ts`,
|
||||
path: `${projectRoot}/b.ts`,
|
||||
content: `import { Point } from "./a";
|
||||
export interface PointWrapper extends Point {
|
||||
}`
|
||||
};
|
||||
const cFile: File = {
|
||||
path: `${currentDirectory}/c.ts`,
|
||||
path: `${projectRoot}/c.ts`,
|
||||
content: `import { PointWrapper } from "./b";
|
||||
export function getPoint(): PointWrapper {
|
||||
return {
|
||||
@@ -272,12 +271,12 @@ export function getPoint(): PointWrapper {
|
||||
};`
|
||||
};
|
||||
const dFile: File = {
|
||||
path: `${currentDirectory}/d.ts`,
|
||||
path: `${projectRoot}/d.ts`,
|
||||
content: `import { getPoint } from "./c";
|
||||
getPoint().c.x;`
|
||||
};
|
||||
const eFile: File = {
|
||||
path: `${currentDirectory}/e.ts`,
|
||||
path: `${projectRoot}/e.ts`,
|
||||
content: `import "./d";`
|
||||
};
|
||||
verifyEmitAndErrorUpdates({
|
||||
@@ -301,14 +300,14 @@ getPoint().c.x;`
|
||||
|
||||
describe("updates errors when file transitively exported file changes", () => {
|
||||
const config: File = {
|
||||
path: `${currentDirectory}/tsconfig.json`,
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
files: ["app.ts"],
|
||||
compilerOptions: { baseUrl: "." }
|
||||
})
|
||||
};
|
||||
const app: File = {
|
||||
path: `${currentDirectory}/app.ts`,
|
||||
path: `${projectRoot}/app.ts`,
|
||||
content: `import { Data } from "lib2/public";
|
||||
export class App {
|
||||
public constructor() {
|
||||
@@ -317,11 +316,11 @@ export class App {
|
||||
}`
|
||||
};
|
||||
const lib2Public: File = {
|
||||
path: `${currentDirectory}/lib2/public.ts`,
|
||||
path: `${projectRoot}/lib2/public.ts`,
|
||||
content: `export * from "./data";`
|
||||
};
|
||||
const lib2Data: File = {
|
||||
path: `${currentDirectory}/lib2/data.ts`,
|
||||
path: `${projectRoot}/lib2/data.ts`,
|
||||
content: `import { ITest } from "lib1/public";
|
||||
export class Data {
|
||||
public test() {
|
||||
@@ -333,15 +332,15 @@ export class Data {
|
||||
}`
|
||||
};
|
||||
const lib1Public: File = {
|
||||
path: `${currentDirectory}/lib1/public.ts`,
|
||||
path: `${projectRoot}/lib1/public.ts`,
|
||||
content: `export * from "./tools/public";`
|
||||
};
|
||||
const lib1ToolsPublic: File = {
|
||||
path: `${currentDirectory}/lib1/tools/public.ts`,
|
||||
path: `${projectRoot}/lib1/tools/public.ts`,
|
||||
content: `export * from "./tools.interface";`
|
||||
};
|
||||
const lib1ToolsInterface: File = {
|
||||
path: `${currentDirectory}/lib1/tools/tools.interface.ts`,
|
||||
path: `${projectRoot}/lib1/tools/tools.interface.ts`,
|
||||
content: `export interface ITest {
|
||||
title: string;
|
||||
}`
|
||||
@@ -372,7 +371,7 @@ export class Data {
|
||||
|
||||
describe("when there are circular import and exports", () => {
|
||||
const lib2Data: File = {
|
||||
path: `${currentDirectory}/lib2/data.ts`,
|
||||
path: `${projectRoot}/lib2/data.ts`,
|
||||
content: `import { ITest } from "lib1/public"; import { Data2 } from "./data2";
|
||||
export class Data {
|
||||
public dat?: Data2; public test() {
|
||||
@@ -384,7 +383,7 @@ export class Data {
|
||||
}`
|
||||
};
|
||||
const lib2Data2: File = {
|
||||
path: `${currentDirectory}/lib2/data2.ts`,
|
||||
path: `${projectRoot}/lib2/data2.ts`,
|
||||
content: `import { Data } from "./data";
|
||||
export class Data2 {
|
||||
public dat?: Data;
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
namespace ts {
|
||||
export const projects = `/user/username/projects`;
|
||||
export const projectRoot = `${projects}/myproject`;
|
||||
}
|
||||
namespace ts.tscWatch {
|
||||
export import WatchedSystem = TestFSWithWatch.TestServerHost;
|
||||
export type File = TestFSWithWatch.File;
|
||||
|
||||
@@ -918,20 +918,19 @@ namespace ts.tscWatch {
|
||||
|
||||
describe("should not trigger should not trigger recompilation because of program emit", () => {
|
||||
function verifyWithOptions(options: CompilerOptions, outputFiles: readonly string[]) {
|
||||
const proj = "/user/username/projects/myproject";
|
||||
const file1: File = {
|
||||
path: `${proj}/file1.ts`,
|
||||
path: `${projectRoot}/file1.ts`,
|
||||
content: "export const c = 30;"
|
||||
};
|
||||
const file2: File = {
|
||||
path: `${proj}/src/file2.ts`,
|
||||
path: `${projectRoot}/src/file2.ts`,
|
||||
content: `import {c} from "file1"; export const d = 30;`
|
||||
};
|
||||
const tsconfig: File = {
|
||||
path: `${proj}/tsconfig.json`,
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
content: generateTSConfig(options, emptyArray, "\n")
|
||||
};
|
||||
const host = createWatchedSystem([file1, file2, libFile, tsconfig], { currentDirectory: proj });
|
||||
const host = createWatchedSystem([file1, file2, libFile, tsconfig], { currentDirectory: projectRoot });
|
||||
const watch = createWatchOfConfigFile(tsconfig.path, host, /*optionsToExtend*/ undefined, /*maxNumberOfFilesToIterateForInvalidation*/1);
|
||||
checkProgramActualFiles(watch(), [file1.path, file2.path, libFile.path]);
|
||||
|
||||
@@ -1020,9 +1019,8 @@ namespace ts.tscWatch {
|
||||
});
|
||||
|
||||
it("updates errors correctly when declaration emit is disabled in compiler options", () => {
|
||||
const currentDirectory = "/user/username/projects/myproject";
|
||||
const aFile: File = {
|
||||
path: `${currentDirectory}/a.ts`,
|
||||
path: `${projectRoot}/a.ts`,
|
||||
content: `import test from './b';
|
||||
test(4, 5);`
|
||||
};
|
||||
@@ -1031,11 +1029,11 @@ test(4, 5);`
|
||||
}
|
||||
export default test;`;
|
||||
const bFile: File = {
|
||||
path: `${currentDirectory}/b.ts`,
|
||||
path: `${projectRoot}/b.ts`,
|
||||
content: bFileContent
|
||||
};
|
||||
const tsconfigFile: File = {
|
||||
path: `${currentDirectory}/tsconfig.json`,
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
compilerOptions: {
|
||||
module: "commonjs",
|
||||
@@ -1045,7 +1043,7 @@ export default test;`;
|
||||
})
|
||||
};
|
||||
const files = [aFile, bFile, libFile, tsconfigFile];
|
||||
const host = createWatchedSystem(files, { currentDirectory });
|
||||
const host = createWatchedSystem(files, { currentDirectory: projectRoot });
|
||||
const watch = createWatchOfConfigFile("tsconfig.json", host);
|
||||
checkOutputErrorsInitial(host, emptyArray);
|
||||
|
||||
@@ -1072,22 +1070,21 @@ export default test;`;
|
||||
});
|
||||
|
||||
it("updates errors when strictNullChecks changes", () => {
|
||||
const currentDirectory = "/user/username/projects/myproject";
|
||||
const aFile: File = {
|
||||
path: `${currentDirectory}/a.ts`,
|
||||
path: `${projectRoot}/a.ts`,
|
||||
content: `declare function foo(): null | { hello: any };
|
||||
foo().hello`
|
||||
};
|
||||
const config: File = {
|
||||
path: `${currentDirectory}/tsconfig.json`,
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
content: JSON.stringify({ compilerOptions: {} })
|
||||
};
|
||||
const files = [aFile, config, libFile];
|
||||
const host = createWatchedSystem(files, { currentDirectory });
|
||||
const host = createWatchedSystem(files, { currentDirectory: projectRoot });
|
||||
const watch = createWatchOfConfigFile("tsconfig.json", host);
|
||||
checkProgramActualFiles(watch(), [aFile.path, libFile.path]);
|
||||
checkOutputErrorsInitial(host, emptyArray);
|
||||
const modifiedTimeOfAJs = host.getModifiedTime(`${currentDirectory}/a.js`);
|
||||
const modifiedTimeOfAJs = host.getModifiedTime(`${projectRoot}/a.js`);
|
||||
host.writeFile(config.path, JSON.stringify({ compilerOptions: { strictNullChecks: true } }));
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
const expectedStrictNullErrors = [
|
||||
@@ -1095,39 +1092,38 @@ foo().hello`
|
||||
];
|
||||
checkOutputErrorsIncremental(host, expectedStrictNullErrors);
|
||||
// File a need not be rewritten
|
||||
assert.equal(host.getModifiedTime(`${currentDirectory}/a.js`), modifiedTimeOfAJs);
|
||||
assert.equal(host.getModifiedTime(`${projectRoot}/a.js`), modifiedTimeOfAJs);
|
||||
host.writeFile(config.path, JSON.stringify({ compilerOptions: { strict: true, alwaysStrict: false } })); // Avoid changing 'alwaysStrict' or must re-bind
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
checkOutputErrorsIncremental(host, expectedStrictNullErrors);
|
||||
// File a need not be rewritten
|
||||
assert.equal(host.getModifiedTime(`${currentDirectory}/a.js`), modifiedTimeOfAJs);
|
||||
assert.equal(host.getModifiedTime(`${projectRoot}/a.js`), modifiedTimeOfAJs);
|
||||
host.writeFile(config.path, JSON.stringify({ compilerOptions: {} }));
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
checkOutputErrorsIncremental(host, emptyArray);
|
||||
// File a need not be rewritten
|
||||
assert.equal(host.getModifiedTime(`${currentDirectory}/a.js`), modifiedTimeOfAJs);
|
||||
assert.equal(host.getModifiedTime(`${projectRoot}/a.js`), modifiedTimeOfAJs);
|
||||
});
|
||||
|
||||
it("updates errors when ambient modules of program changes", () => {
|
||||
const currentDirectory = "/user/username/projects/myproject";
|
||||
const aFile: File = {
|
||||
path: `${currentDirectory}/a.ts`,
|
||||
path: `${projectRoot}/a.ts`,
|
||||
content: `declare module 'a' {
|
||||
type foo = number;
|
||||
}`
|
||||
};
|
||||
const config: File = {
|
||||
path: `${currentDirectory}/tsconfig.json`,
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
content: "{}"
|
||||
};
|
||||
const files = [aFile, config, libFile];
|
||||
const host = createWatchedSystem(files, { currentDirectory });
|
||||
const host = createWatchedSystem(files, { currentDirectory: projectRoot });
|
||||
const watch = createWatchOfConfigFile("tsconfig.json", host);
|
||||
checkProgramActualFiles(watch(), [aFile.path, libFile.path]);
|
||||
checkOutputErrorsInitial(host, emptyArray);
|
||||
|
||||
// Create bts with same file contents
|
||||
const bTsPath = `${currentDirectory}/b.ts`;
|
||||
const bTsPath = `${projectRoot}/b.ts`;
|
||||
host.writeFile(bTsPath, aFile.content);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
checkProgramActualFiles(watch(), [aFile.path, "b.ts", libFile.path]);
|
||||
@@ -1144,7 +1140,6 @@ foo().hello`
|
||||
});
|
||||
|
||||
describe("updates errors in lib file", () => {
|
||||
const currentDirectory = "/user/username/projects/myproject";
|
||||
const field = "fullscreen";
|
||||
const fieldWithoutReadonly = `interface Document {
|
||||
${field}: boolean;
|
||||
@@ -1166,7 +1161,7 @@ interface Document {
|
||||
const files = [aFile, libFileWithDocument];
|
||||
|
||||
function verifyLibErrors(options: CompilerOptions) {
|
||||
const host = createWatchedSystem(files, { currentDirectory });
|
||||
const host = createWatchedSystem(files, { currentDirectory: projectRoot });
|
||||
const watch = createWatchOfFilesAndCompilerOptions([aFile.path], host, options);
|
||||
checkProgramActualFiles(watch(), [aFile.path, libFile.path]);
|
||||
checkOutputErrorsInitial(host, getErrors());
|
||||
@@ -1202,7 +1197,7 @@ interface Document {
|
||||
|
||||
describe("when non module file changes", () => {
|
||||
const aFile: File = {
|
||||
path: `${currentDirectory}/a.ts`,
|
||||
path: `${projectRoot}/a.ts`,
|
||||
content: `${fieldWithoutReadonly}
|
||||
var y: number;`
|
||||
};
|
||||
@@ -1211,7 +1206,7 @@ var y: number;`
|
||||
|
||||
describe("when module file with global definitions changes", () => {
|
||||
const aFile: File = {
|
||||
path: `${currentDirectory}/a.ts`,
|
||||
path: `${projectRoot}/a.ts`,
|
||||
content: `export {}
|
||||
declare global {
|
||||
${fieldWithoutReadonly}
|
||||
@@ -1223,16 +1218,15 @@ var y: number;
|
||||
});
|
||||
|
||||
it("when skipLibCheck and skipDefaultLibCheck changes", () => {
|
||||
const currentDirectory = "/user/username/projects/myproject";
|
||||
const field = "fullscreen";
|
||||
const aFile: File = {
|
||||
path: `${currentDirectory}/a.ts`,
|
||||
path: `${projectRoot}/a.ts`,
|
||||
content: `interface Document {
|
||||
${field}: boolean;
|
||||
}`
|
||||
};
|
||||
const bFile: File = {
|
||||
path: `${currentDirectory}/b.d.ts`,
|
||||
path: `${projectRoot}/b.d.ts`,
|
||||
content: `interface Document {
|
||||
${field}: boolean;
|
||||
}`
|
||||
@@ -1245,13 +1239,13 @@ interface Document {
|
||||
}`
|
||||
};
|
||||
const configFile: File = {
|
||||
path: `${currentDirectory}/tsconfig.json`,
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
content: "{}"
|
||||
};
|
||||
|
||||
const files = [aFile, bFile, configFile, libFileWithDocument];
|
||||
|
||||
const host = createWatchedSystem(files, { currentDirectory });
|
||||
const host = createWatchedSystem(files, { currentDirectory: projectRoot });
|
||||
const watch = createWatchOfConfigFile("tsconfig.json", host);
|
||||
verifyProgramFiles();
|
||||
checkOutputErrorsInitial(host, [
|
||||
@@ -1284,18 +1278,17 @@ interface Document {
|
||||
});
|
||||
|
||||
it("reports errors correctly with isolatedModules", () => {
|
||||
const currentDirectory = "/user/username/projects/myproject";
|
||||
const aFile: File = {
|
||||
path: `${currentDirectory}/a.ts`,
|
||||
path: `${projectRoot}/a.ts`,
|
||||
content: `export const a: string = "";`
|
||||
};
|
||||
const bFile: File = {
|
||||
path: `${currentDirectory}/b.ts`,
|
||||
path: `${projectRoot}/b.ts`,
|
||||
content: `import { a } from "./a";
|
||||
const b: string = a;`
|
||||
};
|
||||
const configFile: File = {
|
||||
path: `${currentDirectory}/tsconfig.json`,
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
compilerOptions: {
|
||||
isolatedModules: true
|
||||
@@ -1305,20 +1298,20 @@ const b: string = a;`
|
||||
|
||||
const files = [aFile, bFile, libFile, configFile];
|
||||
|
||||
const host = createWatchedSystem(files, { currentDirectory });
|
||||
const host = createWatchedSystem(files, { currentDirectory: projectRoot });
|
||||
const watch = createWatchOfConfigFile("tsconfig.json", host);
|
||||
verifyProgramFiles();
|
||||
checkOutputErrorsInitial(host, emptyArray);
|
||||
assert.equal(host.readFile(`${currentDirectory}/a.js`), `"use strict";
|
||||
assert.equal(host.readFile(`${projectRoot}/a.js`), `"use strict";
|
||||
exports.__esModule = true;
|
||||
exports.a = "";
|
||||
`, "Contents of a.js");
|
||||
assert.equal(host.readFile(`${currentDirectory}/b.js`), `"use strict";
|
||||
assert.equal(host.readFile(`${projectRoot}/b.js`), `"use strict";
|
||||
exports.__esModule = true;
|
||||
var a_1 = require("./a");
|
||||
var b = a_1.a;
|
||||
`, "Contents of b.js");
|
||||
const modifiedTime = host.getModifiedTime(`${currentDirectory}/b.js`);
|
||||
const modifiedTime = host.getModifiedTime(`${projectRoot}/b.js`);
|
||||
|
||||
host.writeFile(aFile.path, `export const a: number = 1`);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
@@ -1326,11 +1319,11 @@ var b = a_1.a;
|
||||
checkOutputErrorsIncremental(host, [
|
||||
getDiagnosticOfFileFromProgram(watch(), bFile.path, bFile.content.indexOf("b"), 1, Diagnostics.Type_0_is_not_assignable_to_type_1, "number", "string")
|
||||
]);
|
||||
assert.equal(host.readFile(`${currentDirectory}/a.js`), `"use strict";
|
||||
assert.equal(host.readFile(`${projectRoot}/a.js`), `"use strict";
|
||||
exports.__esModule = true;
|
||||
exports.a = 1;
|
||||
`, "Contents of a.js");
|
||||
assert.equal(host.getModifiedTime(`${currentDirectory}/b.js`), modifiedTime, "Timestamp of b.js");
|
||||
assert.equal(host.getModifiedTime(`${projectRoot}/b.js`), modifiedTime, "Timestamp of b.js");
|
||||
|
||||
function verifyProgramFiles() {
|
||||
checkProgramActualFiles(watch(), [aFile.path, bFile.path, libFile.path]);
|
||||
@@ -1338,9 +1331,8 @@ exports.a = 1;
|
||||
});
|
||||
|
||||
it("reports errors correctly with file not in rootDir", () => {
|
||||
const currentDirectory = "/user/username/projects/myproject";
|
||||
const aFile: File = {
|
||||
path: `${currentDirectory}/a.ts`,
|
||||
path: `${projectRoot}/a.ts`,
|
||||
content: `import { x } from "../b";`
|
||||
};
|
||||
const bFile: File = {
|
||||
@@ -1348,7 +1340,7 @@ exports.a = 1;
|
||||
content: `export const x = 10;`
|
||||
};
|
||||
const configFile: File = {
|
||||
path: `${currentDirectory}/tsconfig.json`,
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
compilerOptions: {
|
||||
rootDir: ".",
|
||||
@@ -1359,10 +1351,10 @@ exports.a = 1;
|
||||
|
||||
const files = [aFile, bFile, libFile, configFile];
|
||||
|
||||
const host = createWatchedSystem(files, { currentDirectory });
|
||||
const host = createWatchedSystem(files, { currentDirectory: projectRoot });
|
||||
const watch = createWatchOfConfigFile("tsconfig.json", host);
|
||||
checkOutputErrorsInitial(host, [
|
||||
getDiagnosticOfFileFromProgram(watch(), aFile.path, aFile.content.indexOf(`"../b"`), `"../b"`.length, Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files, bFile.path, currentDirectory)
|
||||
getDiagnosticOfFileFromProgram(watch(), aFile.path, aFile.content.indexOf(`"../b"`), `"../b"`.length, Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files, bFile.path, projectRoot)
|
||||
]);
|
||||
const aContent = `
|
||||
|
||||
@@ -1370,7 +1362,7 @@ ${aFile.content}`;
|
||||
host.writeFile(aFile.path, aContent);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
checkOutputErrorsIncremental(host, [
|
||||
getDiagnosticOfFileFromProgram(watch(), aFile.path, aContent.indexOf(`"../b"`), `"../b"`.length, Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files, bFile.path, currentDirectory)
|
||||
getDiagnosticOfFileFromProgram(watch(), aFile.path, aContent.indexOf(`"../b"`), `"../b"`.length, Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files, bFile.path, projectRoot)
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -339,42 +339,40 @@ declare module "fs" {
|
||||
});
|
||||
|
||||
it("works when renaming node_modules folder that already contains @types folder", () => {
|
||||
const currentDirectory = "/user/username/projects/myproject";
|
||||
const file: File = {
|
||||
path: `${currentDirectory}/a.ts`,
|
||||
path: `${projectRoot}/a.ts`,
|
||||
content: `import * as q from "qqq";`
|
||||
};
|
||||
const module: File = {
|
||||
path: `${currentDirectory}/node_modules2/@types/qqq/index.d.ts`,
|
||||
path: `${projectRoot}/node_modules2/@types/qqq/index.d.ts`,
|
||||
content: "export {}"
|
||||
};
|
||||
const files = [file, module, libFile];
|
||||
const host = createWatchedSystem(files, { currentDirectory });
|
||||
const host = createWatchedSystem(files, { currentDirectory: projectRoot });
|
||||
const watch = createWatchOfFilesAndCompilerOptions([file.path], host);
|
||||
|
||||
checkProgramActualFiles(watch(), [file.path, libFile.path]);
|
||||
checkOutputErrorsInitial(host, [getDiagnosticModuleNotFoundOfFile(watch(), file, "qqq")]);
|
||||
checkWatchedDirectories(host, emptyArray, /*recursive*/ false);
|
||||
checkWatchedDirectories(host, [`${currentDirectory}/node_modules`, `${currentDirectory}/node_modules/@types`], /*recursive*/ true);
|
||||
checkWatchedDirectories(host, [`${projectRoot}/node_modules`, `${projectRoot}/node_modules/@types`], /*recursive*/ true);
|
||||
|
||||
host.renameFolder(`${currentDirectory}/node_modules2`, `${currentDirectory}/node_modules`);
|
||||
host.renameFolder(`${projectRoot}/node_modules2`, `${projectRoot}/node_modules`);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
checkProgramActualFiles(watch(), [file.path, libFile.path, `${currentDirectory}/node_modules/@types/qqq/index.d.ts`]);
|
||||
checkProgramActualFiles(watch(), [file.path, libFile.path, `${projectRoot}/node_modules/@types/qqq/index.d.ts`]);
|
||||
checkOutputErrorsIncremental(host, emptyArray);
|
||||
});
|
||||
|
||||
describe("ignores files/folder changes in node_modules that start with '.'", () => {
|
||||
const projectPath = "/user/username/projects/project";
|
||||
const npmCacheFile: File = {
|
||||
path: `${projectPath}/node_modules/.cache/babel-loader/89c02171edab901b9926470ba6d5677e.ts`,
|
||||
path: `${projectRoot}/node_modules/.cache/babel-loader/89c02171edab901b9926470ba6d5677e.ts`,
|
||||
content: JSON.stringify({ something: 10 })
|
||||
};
|
||||
const file1: File = {
|
||||
path: `${projectPath}/test.ts`,
|
||||
path: `${projectRoot}/test.ts`,
|
||||
content: `import { x } from "somemodule";`
|
||||
};
|
||||
const file2: File = {
|
||||
path: `${projectPath}/node_modules/somemodule/index.d.ts`,
|
||||
path: `${projectRoot}/node_modules/somemodule/index.d.ts`,
|
||||
content: `export const x = 10;`
|
||||
};
|
||||
const files = [libFile, file1, file2];
|
||||
@@ -390,7 +388,7 @@ declare module "fs" {
|
||||
});
|
||||
it("when watching node_modules as part of wild card directories in config project", () => {
|
||||
const config: File = {
|
||||
path: `${projectPath}/tsconfig.json`,
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
content: "{}"
|
||||
};
|
||||
const host = createWatchedSystem(files.concat(config));
|
||||
@@ -446,7 +444,6 @@ declare namespace myapp {
|
||||
});
|
||||
|
||||
describe("unittests:: tsc-watch:: resolutionCache:: tsc-watch with modules linked to sibling folder", () => {
|
||||
const projectRoot = "/user/username/projects/project";
|
||||
const mainPackageRoot = `${projectRoot}/main`;
|
||||
const linkedPackageRoot = `${projectRoot}/linked-package`;
|
||||
const mainFile: File = {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
namespace ts.tscWatch {
|
||||
describe("unittests:: tsc-watch:: watchAPI:: tsc-watch with custom module resolution", () => {
|
||||
const projectRoot = "/user/username/projects/project";
|
||||
const configFileJson: any = {
|
||||
compilerOptions: { module: "commonjs", resolveJsonModule: true },
|
||||
files: ["index.ts"]
|
||||
@@ -39,7 +38,6 @@ namespace ts.tscWatch {
|
||||
});
|
||||
|
||||
describe("unittests:: tsc-watch:: watchAPI:: tsc-watch expose error count to watch status reporter", () => {
|
||||
const projectRoot = "/user/username/projects/project";
|
||||
const configFileJson: any = {
|
||||
compilerOptions: { module: "commonjs" },
|
||||
files: ["index.ts"]
|
||||
|
||||
@@ -802,7 +802,6 @@ namespace ts.projectSystem {
|
||||
});
|
||||
|
||||
describe("unittests:: tsserver:: compileOnSave:: CompileOnSaveAffectedFileListRequest with and without projectFileName in request", () => {
|
||||
const projectRoot = "/user/username/projects/myproject";
|
||||
const core: File = {
|
||||
path: `${projectRoot}/core/core.ts`,
|
||||
content: "let z = 10;"
|
||||
|
||||
@@ -82,7 +82,6 @@ namespace ts.projectSystem {
|
||||
});
|
||||
|
||||
it("add and then remove a config file in a folder with loose files", () => {
|
||||
const projectRoot = "/user/username/projects/project";
|
||||
const configFile: File = {
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
content: `{
|
||||
@@ -440,7 +439,6 @@ namespace ts.projectSystem {
|
||||
});
|
||||
|
||||
it("open file become a part of configured project if it is referenced from root file", () => {
|
||||
const projectRoot = "/user/username/projects/project";
|
||||
const file1 = {
|
||||
path: `${projectRoot}/a/b/f1.ts`,
|
||||
content: "export let x = 5"
|
||||
@@ -846,6 +844,67 @@ namespace ts.projectSystem {
|
||||
const edits = project.getLanguageService().getFormattingEditsForDocument(f1.path, options);
|
||||
assert.deepEqual(edits, [{ span: createTextSpan(/*start*/ 7, /*length*/ 3), newText: " " }]);
|
||||
});
|
||||
|
||||
it("when multiple projects are open, detects correct default project", () => {
|
||||
const barConfig: File = {
|
||||
path: `${projectRoot}/bar/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
include: ["index.ts"],
|
||||
compilerOptions: {
|
||||
lib: ["dom", "es2017"]
|
||||
}
|
||||
})
|
||||
};
|
||||
const barIndex: File = {
|
||||
path: `${projectRoot}/bar/index.ts`,
|
||||
content: `
|
||||
export function bar() {
|
||||
console.log("hello world");
|
||||
}`
|
||||
};
|
||||
const fooConfig: File = {
|
||||
path: `${projectRoot}/foo/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
include: ["index.ts"],
|
||||
compilerOptions: {
|
||||
lib: ["es2017"]
|
||||
}
|
||||
})
|
||||
};
|
||||
const fooIndex: File = {
|
||||
path: `${projectRoot}/foo/index.ts`,
|
||||
content: `
|
||||
import { bar } from "bar";
|
||||
bar();`
|
||||
};
|
||||
const barSymLink: SymLink = {
|
||||
path: `${projectRoot}/foo/node_modules/bar`,
|
||||
symLink: `${projectRoot}/bar`
|
||||
};
|
||||
|
||||
const lib2017: File = {
|
||||
path: `${getDirectoryPath(libFile.path)}/lib.es2017.d.ts`,
|
||||
content: libFile.content
|
||||
};
|
||||
const libDom: File = {
|
||||
path: `${getDirectoryPath(libFile.path)}/lib.dom.d.ts`,
|
||||
content: `
|
||||
declare var console: {
|
||||
log(...args: any[]): void;
|
||||
};`
|
||||
};
|
||||
const host = createServerHost([barConfig, barIndex, fooConfig, fooIndex, barSymLink, lib2017, libDom]);
|
||||
const session = createSession(host, { canUseEvents: true, });
|
||||
openFilesForSession([fooIndex, barIndex], session);
|
||||
verifyGetErrRequest({
|
||||
session,
|
||||
host,
|
||||
expected: [
|
||||
{ file: barIndex, syntax: [], semantic: [], suggestion: [] },
|
||||
{ file: fooIndex, syntax: [], semantic: [], suggestion: [] },
|
||||
]
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("unittests:: tsserver:: ConfiguredProjects:: non-existing directories listed in config file input array", () => {
|
||||
@@ -903,13 +962,12 @@ namespace ts.projectSystem {
|
||||
});
|
||||
|
||||
it("should tolerate invalid include files that start in subDirectory", () => {
|
||||
const projectFolder = "/user/username/projects/myproject";
|
||||
const f = {
|
||||
path: `${projectFolder}/src/server/index.ts`,
|
||||
path: `${projectRoot}/src/server/index.ts`,
|
||||
content: "let x = 1"
|
||||
};
|
||||
const config = {
|
||||
path: `${projectFolder}/src/server/tsconfig.json`,
|
||||
path: `${projectRoot}/src/server/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
compiler: {
|
||||
module: "commonjs",
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
namespace ts.projectSystem {
|
||||
describe("unittests:: tsserver:: document registry in project service", () => {
|
||||
const projectRootPath = "/user/username/projects/project";
|
||||
const importModuleContent = `import {a} from "./module1"`;
|
||||
const file: File = {
|
||||
path: `${projectRootPath}/index.ts`,
|
||||
path: `${projectRoot}/index.ts`,
|
||||
content: importModuleContent
|
||||
};
|
||||
const moduleFile: File = {
|
||||
path: `${projectRootPath}/module1.d.ts`,
|
||||
path: `${projectRoot}/module1.d.ts`,
|
||||
content: "export const a: number;"
|
||||
};
|
||||
const configFile: File = {
|
||||
path: `${projectRootPath}/tsconfig.json`,
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
content: JSON.stringify({ files: ["index.ts"] })
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
namespace ts.projectSystem {
|
||||
describe("unittests:: tsserver:: events:: LargeFileReferencedEvent with large file", () => {
|
||||
const projectRoot = "/user/username/projects/project";
|
||||
|
||||
function getLargeFile(useLargeTsFile: boolean) {
|
||||
return `src/large.${useLargeTsFile ? "ts" : "js"}`;
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
namespace ts.projectSystem {
|
||||
describe("unittests:: tsserver:: events:: ProjectLoadingStart and ProjectLoadingFinish events", () => {
|
||||
const projectRoot = "/user/username/projects";
|
||||
const aTs: File = {
|
||||
path: `${projectRoot}/a/a.ts`,
|
||||
path: `${projects}/a/a.ts`,
|
||||
content: "export class A { }"
|
||||
};
|
||||
const configA: File = {
|
||||
path: `${projectRoot}/a/tsconfig.json`,
|
||||
path: `${projects}/a/tsconfig.json`,
|
||||
content: "{}"
|
||||
};
|
||||
const bTsPath = `${projectRoot}/b/b.ts`;
|
||||
const configBPath = `${projectRoot}/b/tsconfig.json`;
|
||||
const bTsPath = `${projects}/b/b.ts`;
|
||||
const configBPath = `${projects}/b/tsconfig.json`;
|
||||
const files = [libFile, aTs, configA];
|
||||
|
||||
function verifyProjectLoadingStartAndFinish(createSession: (host: TestServerHost) => {
|
||||
@@ -84,14 +83,14 @@ namespace ts.projectSystem {
|
||||
|
||||
function verify(disableSourceOfProjectReferenceRedirect?: true) {
|
||||
const aDTs: File = {
|
||||
path: `${projectRoot}/a/a.d.ts`,
|
||||
path: `${projects}/a/a.d.ts`,
|
||||
content: `export declare class A {
|
||||
}
|
||||
//# sourceMappingURL=a.d.ts.map
|
||||
`
|
||||
};
|
||||
const aDTsMap: File = {
|
||||
path: `${projectRoot}/a/a.d.ts.map`,
|
||||
path: `${projects}/a/a.d.ts.map`,
|
||||
content: `{"version":3,"file":"a.d.ts","sourceRoot":"","sources":["./a.ts"],"names":[],"mappings":"AAAA,qBAAa,CAAC;CAAI"}`
|
||||
};
|
||||
const bTs: File = {
|
||||
@@ -134,7 +133,7 @@ namespace ts.projectSystem {
|
||||
});
|
||||
|
||||
describe("with external projects and config files ", () => {
|
||||
const projectFileName = `${projectRoot}/a/project.csproj`;
|
||||
const projectFileName = `${projects}/a/project.csproj`;
|
||||
|
||||
function createSession(lazyConfiguredProjectsFromExternalProject: boolean) {
|
||||
const { session, service, verifyEvent: verifyEventWorker, getNumberOfEvents } = createSessionToVerifyEvent(files);
|
||||
|
||||
@@ -824,10 +824,9 @@ namespace ts.projectSystem {
|
||||
});
|
||||
|
||||
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 projectFileName = `${projectRoot}/WebApplication36.csproj`;
|
||||
const tsconfig: File = {
|
||||
path: `${projectLocation}/tsconfig.json`,
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
content: "{}"
|
||||
};
|
||||
const files = [libFile, tsconfig];
|
||||
@@ -845,7 +844,7 @@ namespace ts.projectSystem {
|
||||
checkProjectActualFiles(configProject, [tsconfig.path]);
|
||||
|
||||
// write js file, open external project and open it for edit
|
||||
const jsFilePath = `${projectLocation}/javascript.js`;
|
||||
const jsFilePath = `${projectRoot}/javascript.js`;
|
||||
host.writeFile(jsFilePath, "");
|
||||
service.openExternalProjects([{
|
||||
projectFileName,
|
||||
@@ -860,7 +859,7 @@ namespace ts.projectSystem {
|
||||
|
||||
// write jsconfig file
|
||||
const jsConfig: File = {
|
||||
path: `${projectLocation}/jsconfig.json`,
|
||||
path: `${projectRoot}/jsconfig.json`,
|
||||
content: "{}"
|
||||
};
|
||||
// Dont invoke file creation watchers as the repro suggests
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
namespace ts.projectSystem {
|
||||
describe("unittests:: tsserver:: Inferred projects", () => {
|
||||
it("create inferred project", () => {
|
||||
const projectRoot = "/user/username/projects/project";
|
||||
const appFile: File = {
|
||||
path: `${projectRoot}/app.ts`,
|
||||
content: `
|
||||
@@ -31,7 +30,6 @@ namespace ts.projectSystem {
|
||||
});
|
||||
|
||||
it("should use only one inferred project if 'useOneInferredProject' is set", () => {
|
||||
const projectRoot = "/user/username/projects/project";
|
||||
const file1 = {
|
||||
path: `${projectRoot}/a/b/main.ts`,
|
||||
content: "let x =1;"
|
||||
@@ -347,7 +345,6 @@ namespace ts.projectSystem {
|
||||
});
|
||||
|
||||
it("should still retain configured project created while opening the file", () => {
|
||||
const projectRoot = "/user/username/projects/project";
|
||||
const appFile: File = {
|
||||
path: `${projectRoot}/app.ts`,
|
||||
content: `const app = 20;`
|
||||
|
||||
@@ -292,42 +292,21 @@ namespace ts.projectSystem {
|
||||
// Since this is not js project so no typings are queued
|
||||
host.checkTimeoutQueueLength(0);
|
||||
|
||||
const newTimeoutId = host.getNextTimeoutId();
|
||||
const expectedSequenceId = session.getNextSeq();
|
||||
session.executeCommandSeq<protocol.GeterrRequest>({
|
||||
command: server.CommandNames.Geterr,
|
||||
arguments: {
|
||||
delay: 0,
|
||||
files: [untitledFile]
|
||||
}
|
||||
});
|
||||
host.checkTimeoutQueueLength(1);
|
||||
|
||||
// Run the last one = get error request
|
||||
host.runQueuedTimeoutCallbacks(newTimeoutId);
|
||||
|
||||
assert.isFalse(hasError());
|
||||
host.checkTimeoutQueueLength(0);
|
||||
checkErrorMessage(session, "syntaxDiag", { file: untitledFile, diagnostics: [] });
|
||||
session.clearMessages();
|
||||
|
||||
host.runQueuedImmediateCallbacks();
|
||||
assert.isFalse(hasError());
|
||||
const errorOffset = fileContent.indexOf(refPathNotFound1) + 1;
|
||||
checkErrorMessage(session, "semanticDiag", {
|
||||
file: untitledFile,
|
||||
diagnostics: [
|
||||
createDiagnostic({ line: 1, offset: errorOffset }, { line: 1, offset: errorOffset + refPathNotFound1.length }, Diagnostics.File_0_not_found, [refPathNotFound1], "error"),
|
||||
createDiagnostic({ line: 2, offset: errorOffset }, { line: 2, offset: errorOffset + refPathNotFound2.length }, Diagnostics.File_0_not_found, [refPathNotFound2.substr(2)], "error")
|
||||
]
|
||||
verifyGetErrRequest({
|
||||
session,
|
||||
host,
|
||||
expected: [{
|
||||
file: untitledFile,
|
||||
syntax: [],
|
||||
semantic: [
|
||||
createDiagnostic({ line: 1, offset: errorOffset }, { line: 1, offset: errorOffset + refPathNotFound1.length }, Diagnostics.File_0_not_found, [refPathNotFound1], "error"),
|
||||
createDiagnostic({ line: 2, offset: errorOffset }, { line: 2, offset: errorOffset + refPathNotFound2.length }, Diagnostics.File_0_not_found, [refPathNotFound2.substr(2)], "error")
|
||||
],
|
||||
suggestion: []
|
||||
}],
|
||||
onErrEvent: () => assert.isFalse(hasError())
|
||||
});
|
||||
session.clearMessages();
|
||||
|
||||
host.runQueuedImmediateCallbacks(1);
|
||||
assert.isFalse(hasError());
|
||||
checkErrorMessage(session, "suggestionDiag", { file: untitledFile, diagnostics: [] });
|
||||
checkCompleteEvent(session, 2, expectedSequenceId);
|
||||
session.clearMessages();
|
||||
}
|
||||
|
||||
it("has projectRoot", () => {
|
||||
@@ -371,27 +350,16 @@ namespace ts.projectSystem {
|
||||
verifyErrorsInApp();
|
||||
|
||||
function verifyErrorsInApp() {
|
||||
session.clearMessages();
|
||||
const expectedSequenceId = session.getNextSeq();
|
||||
session.executeCommandSeq<protocol.GeterrRequest>({
|
||||
command: server.CommandNames.Geterr,
|
||||
arguments: {
|
||||
delay: 0,
|
||||
files: [app.path]
|
||||
}
|
||||
verifyGetErrRequest({
|
||||
session,
|
||||
host,
|
||||
expected: [{
|
||||
file: app,
|
||||
syntax: [],
|
||||
semantic: [],
|
||||
suggestion: []
|
||||
}],
|
||||
});
|
||||
host.checkTimeoutQueueLengthAndRun(1);
|
||||
checkErrorMessage(session, "syntaxDiag", { file: app.path, diagnostics: [] });
|
||||
session.clearMessages();
|
||||
|
||||
host.runQueuedImmediateCallbacks();
|
||||
checkErrorMessage(session, "semanticDiag", { file: app.path, diagnostics: [] });
|
||||
session.clearMessages();
|
||||
|
||||
host.runQueuedImmediateCallbacks(1);
|
||||
checkErrorMessage(session, "suggestionDiag", { file: app.path, diagnostics: [] });
|
||||
checkCompleteEvent(session, 2, expectedSequenceId);
|
||||
session.clearMessages();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -421,7 +389,6 @@ namespace ts.projectSystem {
|
||||
});
|
||||
|
||||
it("Reports errors correctly when file referenced by inferred project root, is opened right after closing the root file", () => {
|
||||
const projectRoot = "/user/username/projects/myproject";
|
||||
const app: File = {
|
||||
path: `${projectRoot}/src/client/app.js`,
|
||||
content: ""
|
||||
@@ -451,32 +418,12 @@ namespace ts.projectSystem {
|
||||
checkErrors([serverUtilities.path, app.path]);
|
||||
|
||||
function checkErrors(openFiles: [string, string]) {
|
||||
const expectedSequenceId = session.getNextSeq();
|
||||
session.executeCommandSeq<protocol.GeterrRequest>({
|
||||
command: protocol.CommandTypes.Geterr,
|
||||
arguments: {
|
||||
delay: 0,
|
||||
files: openFiles
|
||||
}
|
||||
verifyGetErrRequest({
|
||||
session,
|
||||
host,
|
||||
expected: openFiles.map(file => ({ file, syntax: [], semantic: [], suggestion: [] })),
|
||||
existingTimeouts: 2
|
||||
});
|
||||
|
||||
for (const openFile of openFiles) {
|
||||
session.clearMessages();
|
||||
host.checkTimeoutQueueLength(3);
|
||||
host.runQueuedTimeoutCallbacks(host.getNextTimeoutId() - 1);
|
||||
|
||||
checkErrorMessage(session, "syntaxDiag", { file: openFile, diagnostics: [] });
|
||||
session.clearMessages();
|
||||
|
||||
host.runQueuedImmediateCallbacks();
|
||||
checkErrorMessage(session, "semanticDiag", { file: openFile, diagnostics: [] });
|
||||
session.clearMessages();
|
||||
|
||||
host.runQueuedImmediateCallbacks(1);
|
||||
checkErrorMessage(session, "suggestionDiag", { file: openFile, diagnostics: [] });
|
||||
}
|
||||
checkCompleteEvent(session, 2, expectedSequenceId);
|
||||
session.clearMessages();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -531,36 +478,19 @@ declare module '@custom/plugin' {
|
||||
|
||||
function checkErrors() {
|
||||
host.checkTimeoutQueueLength(0);
|
||||
const expectedSequenceId = session.getNextSeq();
|
||||
session.executeCommandSeq<protocol.GeterrRequest>({
|
||||
command: server.CommandNames.Geterr,
|
||||
arguments: {
|
||||
delay: 0,
|
||||
files: [aFile.path],
|
||||
}
|
||||
verifyGetErrRequest({
|
||||
session,
|
||||
host,
|
||||
expected: [{
|
||||
file: aFile,
|
||||
syntax: [],
|
||||
semantic: [],
|
||||
suggestion: [
|
||||
createDiagnostic({ line: 1, offset: 1 }, { line: 1, offset: 44 }, Diagnostics._0_is_declared_but_its_value_is_never_read, ["myModule"], "suggestion", /*reportsUnnecessary*/ true),
|
||||
createDiagnostic({ line: 2, offset: 10 }, { line: 2, offset: 13 }, Diagnostics._0_is_declared_but_its_value_is_never_read, ["foo"], "suggestion", /*reportsUnnecessary*/ true)
|
||||
]
|
||||
}]
|
||||
});
|
||||
|
||||
host.checkTimeoutQueueLengthAndRun(1);
|
||||
|
||||
checkErrorMessage(session, "syntaxDiag", { file: aFile.path, diagnostics: [] }, /*isMostRecent*/ true);
|
||||
session.clearMessages();
|
||||
|
||||
host.runQueuedImmediateCallbacks(1);
|
||||
|
||||
checkErrorMessage(session, "semanticDiag", { file: aFile.path, diagnostics: [] });
|
||||
session.clearMessages();
|
||||
|
||||
host.runQueuedImmediateCallbacks(1);
|
||||
|
||||
checkErrorMessage(session, "suggestionDiag", {
|
||||
file: aFile.path,
|
||||
diagnostics: [
|
||||
createDiagnostic({ line: 1, offset: 1 }, { line: 1, offset: 44 }, Diagnostics._0_is_declared_but_its_value_is_never_read, ["myModule"], "suggestion", /*reportsUnnecessary*/ true),
|
||||
createDiagnostic({ line: 2, offset: 10 }, { line: 2, offset: 13 }, Diagnostics._0_is_declared_but_its_value_is_never_read, ["foo"], "suggestion", /*reportsUnnecessary*/ true)
|
||||
],
|
||||
});
|
||||
checkCompleteEvent(session, 2, expectedSequenceId);
|
||||
session.clearMessages();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
namespace ts.projectSystem {
|
||||
describe("unittests:: tsserver:: with project references and compile on save", () => {
|
||||
const projectLocation = "/user/username/projects/myproject";
|
||||
const dependecyLocation = `${projectLocation}/dependency`;
|
||||
const usageLocation = `${projectLocation}/usage`;
|
||||
const dependecyLocation = `${projectRoot}/dependency`;
|
||||
const usageLocation = `${projectRoot}/usage`;
|
||||
const dependencyTs: File = {
|
||||
path: `${dependecyLocation}/fns.ts`,
|
||||
content: `export function fn1() { }
|
||||
@@ -294,7 +293,7 @@ exports.fn2 = fn2;
|
||||
${appendJs}`
|
||||
},
|
||||
{
|
||||
path: `${projectLocation}/decls/fns.d.ts`,
|
||||
path: `${projectRoot}/decls/fns.d.ts`,
|
||||
content: `export declare function fn1(): void;
|
||||
export declare function fn2(): void;
|
||||
${appendDts}`
|
||||
|
||||
@@ -1,48 +1,92 @@
|
||||
namespace ts.projectSystem {
|
||||
describe("unittests:: tsserver:: with project references and error reporting", () => {
|
||||
const projectLocation = "/user/username/projects/myproject";
|
||||
const dependecyLocation = `${projectLocation}/dependency`;
|
||||
const usageLocation = `${projectLocation}/usage`;
|
||||
export interface GetErrDiagnostics {
|
||||
file: string | File;
|
||||
syntax?: protocol.Diagnostic[];
|
||||
semantic?: protocol.Diagnostic[];
|
||||
suggestion?: protocol.Diagnostic[];
|
||||
}
|
||||
export interface VerifyGetErrRequestBase {
|
||||
session: TestSession;
|
||||
host: TestServerHost;
|
||||
onErrEvent?: () => void;
|
||||
existingTimeouts?: number;
|
||||
}
|
||||
export interface VerifyGetErrRequest extends VerifyGetErrRequestBase {
|
||||
expected: readonly GetErrDiagnostics[];
|
||||
}
|
||||
export function verifyGetErrRequest(request: VerifyGetErrRequest) {
|
||||
const { session, expected } = request;
|
||||
session.clearMessages();
|
||||
const expectedSequenceId = session.getNextSeq();
|
||||
session.executeCommandSeq<protocol.GeterrRequest>({
|
||||
command: protocol.CommandTypes.Geterr,
|
||||
arguments: {
|
||||
delay: 0,
|
||||
files: expected.map(f => filePath(f.file))
|
||||
}
|
||||
});
|
||||
checkAllErrors({ ...request, expectedSequenceId });
|
||||
}
|
||||
|
||||
interface CheckErrorsInFile {
|
||||
session: TestSession;
|
||||
host: TestServerHost;
|
||||
expected: GetErrDiagnostics;
|
||||
expectedSequenceId?: number;
|
||||
export interface CheckAllErrors extends VerifyGetErrRequest {
|
||||
expectedSequenceId: number;
|
||||
}
|
||||
function checkAllErrors({ expected, expectedSequenceId, ...rest }: CheckAllErrors) {
|
||||
for (let i = 0; i < expected.length; i++) {
|
||||
checkErrorsInFile({
|
||||
...rest,
|
||||
expected: expected[i],
|
||||
expectedSequenceId: i === expected.length - 1 ? expectedSequenceId : undefined,
|
||||
});
|
||||
}
|
||||
function checkErrorsInFile({ session, host, expected: { file, syntax, semantic, suggestion }, expectedSequenceId }: CheckErrorsInFile) {
|
||||
}
|
||||
|
||||
function filePath(file: string | File) {
|
||||
return isString(file) ? file : file.path;
|
||||
}
|
||||
interface CheckErrorsInFile extends VerifyGetErrRequestBase {
|
||||
expected: GetErrDiagnostics;
|
||||
expectedSequenceId?: number;
|
||||
}
|
||||
function checkErrorsInFile({
|
||||
session, host, onErrEvent, existingTimeouts, expectedSequenceId,
|
||||
expected: { file, syntax, semantic, suggestion },
|
||||
}: CheckErrorsInFile) {
|
||||
onErrEvent = onErrEvent || noop;
|
||||
if (existingTimeouts !== undefined) {
|
||||
host.checkTimeoutQueueLength(existingTimeouts + 1);
|
||||
host.runQueuedTimeoutCallbacks(host.getNextTimeoutId() - 1);
|
||||
}
|
||||
else {
|
||||
host.checkTimeoutQueueLengthAndRun(1);
|
||||
checkErrorMessage(session, "syntaxDiag", { file: file.path, diagnostics: syntax });
|
||||
}
|
||||
if (syntax) {
|
||||
onErrEvent();
|
||||
checkErrorMessage(session, "syntaxDiag", { file: filePath(file), diagnostics: syntax });
|
||||
}
|
||||
if (semantic) {
|
||||
session.clearMessages();
|
||||
|
||||
host.runQueuedImmediateCallbacks(1);
|
||||
checkErrorMessage(session, "semanticDiag", { file: file.path, diagnostics: semantic });
|
||||
onErrEvent();
|
||||
checkErrorMessage(session, "semanticDiag", { file: filePath(file), diagnostics: semantic });
|
||||
}
|
||||
if (suggestion) {
|
||||
session.clearMessages();
|
||||
|
||||
host.runQueuedImmediateCallbacks(1);
|
||||
checkErrorMessage(session, "suggestionDiag", { file: file.path, diagnostics: suggestion });
|
||||
if (expectedSequenceId !== undefined) {
|
||||
checkCompleteEvent(session, 2, expectedSequenceId);
|
||||
}
|
||||
session.clearMessages();
|
||||
onErrEvent();
|
||||
checkErrorMessage(session, "suggestionDiag", { file: filePath(file), diagnostics: suggestion });
|
||||
}
|
||||
if (expectedSequenceId !== undefined) {
|
||||
checkCompleteEvent(session, syntax || semantic || suggestion ? 2 : 1, expectedSequenceId);
|
||||
}
|
||||
session.clearMessages();
|
||||
}
|
||||
|
||||
interface CheckAllErrors {
|
||||
session: TestSession;
|
||||
host: TestServerHost;
|
||||
expected: readonly GetErrDiagnostics[];
|
||||
expectedSequenceId: number;
|
||||
}
|
||||
function checkAllErrors({ session, host, expected, expectedSequenceId }: CheckAllErrors) {
|
||||
for (let i = 0; i < expected.length; i++) {
|
||||
checkErrorsInFile({
|
||||
session,
|
||||
host,
|
||||
expected: expected[i],
|
||||
expectedSequenceId: i === expected.length - 1 ? expectedSequenceId : undefined
|
||||
});
|
||||
}
|
||||
}
|
||||
describe("unittests:: tsserver:: with project references and error reporting", () => {
|
||||
const dependecyLocation = `${projectRoot}/dependency`;
|
||||
const usageLocation = `${projectRoot}/usage`;
|
||||
|
||||
function verifyErrorsUsingGeterr({ allFiles, openFiles, expectedGetErr }: VerifyScenario) {
|
||||
it("verifies the errors in open file", () => {
|
||||
@@ -50,18 +94,7 @@ namespace ts.projectSystem {
|
||||
const session = createSession(host, { canUseEvents: true, });
|
||||
openFilesForSession(openFiles(), session);
|
||||
|
||||
session.clearMessages();
|
||||
const expectedSequenceId = session.getNextSeq();
|
||||
const expected = expectedGetErr();
|
||||
session.executeCommandSeq<protocol.GeterrRequest>({
|
||||
command: protocol.CommandTypes.Geterr,
|
||||
arguments: {
|
||||
delay: 0,
|
||||
files: expected.map(f => f.file.path)
|
||||
}
|
||||
});
|
||||
|
||||
checkAllErrors({ session, host, expected, expectedSequenceId });
|
||||
verifyGetErrRequest({ session, host, expected: expectedGetErr() });
|
||||
});
|
||||
}
|
||||
|
||||
@@ -96,27 +129,27 @@ namespace ts.projectSystem {
|
||||
const actualSyntax = session.executeCommandSeq<protocol.SyntacticDiagnosticsSyncRequest>({
|
||||
command: protocol.CommandTypes.SyntacticDiagnosticsSync,
|
||||
arguments: {
|
||||
file: file.path,
|
||||
file: filePath(file),
|
||||
projectFileName: project
|
||||
}
|
||||
}).response as protocol.Diagnostic[];
|
||||
assert.deepEqual(actualSyntax, syntax, `Syntax diagnostics for file: ${file.path}, project: ${project}`);
|
||||
assert.deepEqual(actualSyntax, syntax, `Syntax diagnostics for file: ${filePath(file)}, project: ${project}`);
|
||||
const actualSemantic = session.executeCommandSeq<protocol.SemanticDiagnosticsSyncRequest>({
|
||||
command: protocol.CommandTypes.SemanticDiagnosticsSync,
|
||||
arguments: {
|
||||
file: file.path,
|
||||
file: filePath(file),
|
||||
projectFileName: project
|
||||
}
|
||||
}).response as protocol.Diagnostic[];
|
||||
assert.deepEqual(actualSemantic, semantic, `Semantic diagnostics for file: ${file.path}, project: ${project}`);
|
||||
assert.deepEqual(actualSemantic, semantic, `Semantic diagnostics for file: ${filePath(file)}, project: ${project}`);
|
||||
const actualSuggestion = session.executeCommandSeq<protocol.SuggestionDiagnosticsSyncRequest>({
|
||||
command: protocol.CommandTypes.SuggestionDiagnosticsSync,
|
||||
arguments: {
|
||||
file: file.path,
|
||||
file: filePath(file),
|
||||
projectFileName: project
|
||||
}
|
||||
}).response as protocol.Diagnostic[];
|
||||
assert.deepEqual(actualSuggestion, suggestion, `Suggestion diagnostics for file: ${file.path}, project: ${project}`);
|
||||
assert.deepEqual(actualSuggestion, suggestion, `Suggestion diagnostics for file: ${filePath(file)}, project: ${project}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -140,12 +173,6 @@ namespace ts.projectSystem {
|
||||
});
|
||||
}
|
||||
|
||||
interface GetErrDiagnostics {
|
||||
file: File;
|
||||
syntax: protocol.Diagnostic[];
|
||||
semantic: protocol.Diagnostic[];
|
||||
suggestion: protocol.Diagnostic[];
|
||||
}
|
||||
interface GetErrForProjectDiagnostics {
|
||||
project: string;
|
||||
errors: readonly GetErrDiagnostics[];
|
||||
|
||||
@@ -92,10 +92,9 @@ namespace ts.projectSystem {
|
||||
});
|
||||
|
||||
describe("with main and depedency project", () => {
|
||||
const projectLocation = "/user/username/projects/myproject";
|
||||
const dependecyLocation = `${projectLocation}/dependency`;
|
||||
const dependecyDeclsLocation = `${projectLocation}/decls`;
|
||||
const mainLocation = `${projectLocation}/main`;
|
||||
const dependecyLocation = `${projectRoot}/dependency`;
|
||||
const dependecyDeclsLocation = `${projectRoot}/decls`;
|
||||
const mainLocation = `${projectRoot}/main`;
|
||||
const dependencyTs: File = {
|
||||
path: `${dependecyLocation}/FnS.ts`,
|
||||
content: `export function fn1() { }
|
||||
@@ -137,11 +136,11 @@ fn5();
|
||||
};
|
||||
|
||||
const randomFile: File = {
|
||||
path: `${projectLocation}/random/random.ts`,
|
||||
path: `${projectRoot}/random/random.ts`,
|
||||
content: "let a = 10;"
|
||||
};
|
||||
const randomConfig: File = {
|
||||
path: `${projectLocation}/random/tsconfig.json`,
|
||||
path: `${projectRoot}/random/tsconfig.json`,
|
||||
content: "{}"
|
||||
};
|
||||
const dtsLocation = `${dependecyDeclsLocation}/FnS.d.ts`;
|
||||
@@ -1302,9 +1301,8 @@ function foo() {
|
||||
});
|
||||
|
||||
it("reusing d.ts files from composite and non composite projects", () => {
|
||||
const projectLocation = "/user/username/projects/myproject";
|
||||
const configA: File = {
|
||||
path: `${projectLocation}/compositea/tsconfig.json`,
|
||||
path: `${projectRoot}/compositea/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
@@ -1316,27 +1314,27 @@ function foo() {
|
||||
})
|
||||
};
|
||||
const aTs: File = {
|
||||
path: `${projectLocation}/compositea/a.ts`,
|
||||
path: `${projectRoot}/compositea/a.ts`,
|
||||
content: `import { b } from "@ref/compositeb/b";`
|
||||
};
|
||||
const a2Ts: File = {
|
||||
path: `${projectLocation}/compositea/a2.ts`,
|
||||
path: `${projectRoot}/compositea/a2.ts`,
|
||||
content: `export const x = 10;`
|
||||
};
|
||||
const configB: File = {
|
||||
path: `${projectLocation}/compositeb/tsconfig.json`,
|
||||
path: `${projectRoot}/compositeb/tsconfig.json`,
|
||||
content: configA.content
|
||||
};
|
||||
const bTs: File = {
|
||||
path: `${projectLocation}/compositeb/b.ts`,
|
||||
path: `${projectRoot}/compositeb/b.ts`,
|
||||
content: "export function b() {}"
|
||||
};
|
||||
const bDts: File = {
|
||||
path: `${projectLocation}/dist/compositeb/b.d.ts`,
|
||||
path: `${projectRoot}/dist/compositeb/b.d.ts`,
|
||||
content: "export declare function b(): void;"
|
||||
};
|
||||
const configC: File = {
|
||||
path: `${projectLocation}/compositec/tsconfig.json`,
|
||||
path: `${projectRoot}/compositec/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
@@ -1349,7 +1347,7 @@ function foo() {
|
||||
})
|
||||
};
|
||||
const cTs: File = {
|
||||
path: `${projectLocation}/compositec/c.ts`,
|
||||
path: `${projectRoot}/compositec/c.ts`,
|
||||
content: aTs.content
|
||||
};
|
||||
const files = [libFile, aTs, a2Ts, configA, bDts, bTs, configB, cTs, configC];
|
||||
|
||||
@@ -1209,17 +1209,16 @@ var x = 10;`
|
||||
});
|
||||
|
||||
it("requests are done on file on pendingReload but has svc for previous version", () => {
|
||||
const projectLocation = "/user/username/projects/project";
|
||||
const file1: File = {
|
||||
path: `${projectLocation}/src/file1.ts`,
|
||||
path: `${projectRoot}/src/file1.ts`,
|
||||
content: `import { y } from "./file2"; let x = 10;`
|
||||
};
|
||||
const file2: File = {
|
||||
path: `${projectLocation}/src/file2.ts`,
|
||||
path: `${projectRoot}/src/file2.ts`,
|
||||
content: "export let y = 10;"
|
||||
};
|
||||
const config: File = {
|
||||
path: `${projectLocation}/tsconfig.json`,
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
content: "{}"
|
||||
};
|
||||
const files = [file1, file2, libFile, config];
|
||||
@@ -1309,20 +1308,19 @@ var x = 10;`
|
||||
});
|
||||
|
||||
it("Orphan source files are handled correctly on watch trigger", () => {
|
||||
const projectLocation = "/user/username/projects/project";
|
||||
const file1: File = {
|
||||
path: `${projectLocation}/src/file1.ts`,
|
||||
path: `${projectRoot}/src/file1.ts`,
|
||||
content: `export let x = 10;`
|
||||
};
|
||||
const file2: File = {
|
||||
path: `${projectLocation}/src/file2.ts`,
|
||||
path: `${projectRoot}/src/file2.ts`,
|
||||
content: "export let y = 10;"
|
||||
};
|
||||
const configContent1 = JSON.stringify({
|
||||
files: ["src/file1.ts", "src/file2.ts"]
|
||||
});
|
||||
const config: File = {
|
||||
path: `${projectLocation}/tsconfig.json`,
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
content: configContent1
|
||||
};
|
||||
const files = [file1, file2, libFile, config];
|
||||
@@ -1445,36 +1443,17 @@ var x = 10;`
|
||||
// Actually trigger the file move
|
||||
host.reloadFS(files);
|
||||
host.checkTimeoutQueueLength(2);
|
||||
const fileBErrorTimeoutId = host.getNextTimeoutId();
|
||||
|
||||
session.executeCommandSeq<protocol.GeterrRequest>({
|
||||
command: protocol.CommandTypes.Geterr,
|
||||
arguments: {
|
||||
files: [fileB.path, fileSubA.path],
|
||||
delay: 0
|
||||
}
|
||||
verifyGetErrRequest({
|
||||
session,
|
||||
host,
|
||||
expected: [
|
||||
{ file: fileB, syntax: [], semantic: [], suggestion: [] },
|
||||
{ file: fileSubA },
|
||||
],
|
||||
existingTimeouts: 2,
|
||||
onErrEvent: () => assert.isFalse(hasErrorMsg())
|
||||
});
|
||||
const getErrSeqId = session.getSeq();
|
||||
host.checkTimeoutQueueLength(3);
|
||||
|
||||
session.clearMessages();
|
||||
host.runQueuedTimeoutCallbacks(fileBErrorTimeoutId);
|
||||
checkErrorMessage(session, "syntaxDiag", { file: fileB.path, diagnostics: [] });
|
||||
|
||||
session.clearMessages();
|
||||
host.runQueuedImmediateCallbacks();
|
||||
checkErrorMessage(session, "semanticDiag", { file: fileB.path, diagnostics: [] });
|
||||
|
||||
session.clearMessages();
|
||||
const fileSubAErrorTimeoutId = host.getNextTimeoutId();
|
||||
host.runQueuedImmediateCallbacks();
|
||||
checkErrorMessage(session, "suggestionDiag", { file: fileB.path, diagnostics: [] });
|
||||
|
||||
session.clearMessages();
|
||||
host.checkTimeoutQueueLength(3);
|
||||
host.runQueuedTimeoutCallbacks(fileSubAErrorTimeoutId);
|
||||
checkCompleteEvent(session, 1, getErrSeqId);
|
||||
assert.isFalse(hasErrorMsg());
|
||||
|
||||
function openFile(file: File) {
|
||||
openFilesForSession([{ file, projectRootPath }], session);
|
||||
|
||||
@@ -149,34 +149,20 @@ namespace ts.projectSystem {
|
||||
}
|
||||
});
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
session.clearMessages();
|
||||
const expectedSequenceId = session.getNextSeq();
|
||||
session.executeCommandSeq<protocol.GeterrRequest>({
|
||||
command: server.CommandNames.Geterr,
|
||||
arguments: {
|
||||
delay: 0,
|
||||
files: [file1.path]
|
||||
}
|
||||
});
|
||||
|
||||
host.checkTimeoutQueueLengthAndRun(1);
|
||||
checkErrorMessage(session, "syntaxDiag", { file: file1.path, diagnostics: [] });
|
||||
session.clearMessages();
|
||||
|
||||
host.runQueuedImmediateCallbacks();
|
||||
const startOffset = file1.content.indexOf('"') + 1;
|
||||
checkErrorMessage(session, "semanticDiag", {
|
||||
file: file1.path,
|
||||
diagnostics: [
|
||||
createDiagnostic({ line: 1, offset: startOffset }, { line: 1, offset: startOffset + '"pad"'.length }, Diagnostics.Cannot_find_module_0, ["pad"])
|
||||
],
|
||||
verifyGetErrRequest({
|
||||
session,
|
||||
host,
|
||||
expected: [{
|
||||
file: file1,
|
||||
syntax: [],
|
||||
semantic: [
|
||||
createDiagnostic({ line: 1, offset: startOffset }, { line: 1, offset: startOffset + '"pad"'.length }, Diagnostics.Cannot_find_module_0, ["pad"])
|
||||
],
|
||||
suggestion: []
|
||||
}]
|
||||
});
|
||||
session.clearMessages();
|
||||
|
||||
host.runQueuedImmediateCallbacks(1);
|
||||
checkErrorMessage(session, "suggestionDiag", { file: file1.path, diagnostics: [] });
|
||||
checkCompleteEvent(session, 2, expectedSequenceId);
|
||||
session.clearMessages();
|
||||
|
||||
const padIndex: File = {
|
||||
path: `${folderPath}/node_modules/@types/pad/index.d.ts`,
|
||||
@@ -213,40 +199,22 @@ namespace ts.projectSystem {
|
||||
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
session.clearMessages();
|
||||
const expectedSequenceId = session.getNextSeq();
|
||||
host.checkTimeoutQueueLengthAndRun(2);
|
||||
|
||||
checkProjectUpdatedInBackgroundEvent(session, [file.path]);
|
||||
session.clearMessages();
|
||||
|
||||
session.executeCommandSeq<protocol.GeterrRequest>({
|
||||
command: server.CommandNames.Geterr,
|
||||
arguments: {
|
||||
delay: 0,
|
||||
files: [file.path],
|
||||
}
|
||||
verifyGetErrRequest({
|
||||
session,
|
||||
host,
|
||||
expected: [{
|
||||
file,
|
||||
syntax: [],
|
||||
semantic: [],
|
||||
suggestion: [
|
||||
createDiagnostic({ line: 1, offset: 12 }, { line: 1, offset: 13 }, Diagnostics._0_is_declared_but_its_value_is_never_read, ["p"], "suggestion", /*reportsUnnecessary*/ true),
|
||||
]
|
||||
}]
|
||||
});
|
||||
|
||||
host.checkTimeoutQueueLengthAndRun(1);
|
||||
|
||||
checkErrorMessage(session, "syntaxDiag", { file: file.path, diagnostics: [] }, /*isMostRecent*/ true);
|
||||
session.clearMessages();
|
||||
|
||||
host.runQueuedImmediateCallbacks(1);
|
||||
|
||||
checkErrorMessage(session, "semanticDiag", { file: file.path, diagnostics: [] });
|
||||
session.clearMessages();
|
||||
|
||||
host.runQueuedImmediateCallbacks(1);
|
||||
|
||||
checkErrorMessage(session, "suggestionDiag", {
|
||||
file: file.path,
|
||||
diagnostics: [
|
||||
createDiagnostic({ line: 1, offset: 12 }, { line: 1, offset: 13 }, Diagnostics._0_is_declared_but_its_value_is_never_read, ["p"], "suggestion", /*reportsUnnecessary*/ true),
|
||||
],
|
||||
});
|
||||
checkCompleteEvent(session, 2, expectedSequenceId);
|
||||
session.clearMessages();
|
||||
});
|
||||
|
||||
it("disable suggestion diagnostics", () => {
|
||||
@@ -273,31 +241,19 @@ namespace ts.projectSystem {
|
||||
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
session.clearMessages();
|
||||
const expectedSequenceId = session.getNextSeq();
|
||||
host.checkTimeoutQueueLengthAndRun(2);
|
||||
|
||||
checkProjectUpdatedInBackgroundEvent(session, [file.path]);
|
||||
session.clearMessages();
|
||||
|
||||
session.executeCommandSeq<protocol.GeterrRequest>({
|
||||
command: server.CommandNames.Geterr,
|
||||
arguments: {
|
||||
delay: 0,
|
||||
files: [file.path],
|
||||
}
|
||||
verifyGetErrRequest({
|
||||
session,
|
||||
host,
|
||||
expected: [{
|
||||
file,
|
||||
syntax: [],
|
||||
semantic: []
|
||||
}]
|
||||
});
|
||||
|
||||
host.checkTimeoutQueueLengthAndRun(1);
|
||||
|
||||
checkErrorMessage(session, "syntaxDiag", { file: file.path, diagnostics: [] }, /*isMostRecent*/ true);
|
||||
session.clearMessages();
|
||||
|
||||
host.runQueuedImmediateCallbacks(1);
|
||||
|
||||
checkErrorMessage(session, "semanticDiag", { file: file.path, diagnostics: [] });
|
||||
// No suggestion event, we're done.
|
||||
checkCompleteEvent(session, 2, expectedSequenceId);
|
||||
session.clearMessages();
|
||||
});
|
||||
|
||||
it("suppressed diagnostic events", () => {
|
||||
@@ -494,9 +450,8 @@ namespace ts.projectSystem {
|
||||
});
|
||||
|
||||
describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem module resolution caching", () => {
|
||||
const projectLocation = "/user/username/projects/myproject";
|
||||
const configFile: File = {
|
||||
path: `${projectLocation}/tsconfig.json`,
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
content: JSON.stringify({ compilerOptions: { traceResolution: true } })
|
||||
};
|
||||
|
||||
@@ -603,7 +558,7 @@ namespace ts.projectSystem {
|
||||
}
|
||||
|
||||
function verifyWatchesWithConfigFile(host: TestServerHost, files: File[], openFile: File, extraExpectedDirectories?: readonly string[]) {
|
||||
const expectedRecursiveDirectories = arrayToSet([projectLocation, `${projectLocation}/${nodeModulesAtTypes}`, ...(extraExpectedDirectories || emptyArray)]);
|
||||
const expectedRecursiveDirectories = arrayToSet([projectRoot, `${projectRoot}/${nodeModulesAtTypes}`, ...(extraExpectedDirectories || emptyArray)]);
|
||||
checkWatchedFiles(host, mapDefined(files, f => {
|
||||
if (f === openFile) {
|
||||
return undefined;
|
||||
@@ -622,11 +577,11 @@ namespace ts.projectSystem {
|
||||
describe("from files in same folder", () => {
|
||||
function getFiles(fileContent: string) {
|
||||
const file1: File = {
|
||||
path: `${projectLocation}/src/file1.ts`,
|
||||
path: `${projectRoot}/src/file1.ts`,
|
||||
content: fileContent
|
||||
};
|
||||
const file2: File = {
|
||||
path: `${projectLocation}/src/file2.ts`,
|
||||
path: `${projectRoot}/src/file2.ts`,
|
||||
content: fileContent
|
||||
};
|
||||
return { file1, file2 };
|
||||
@@ -637,7 +592,7 @@ namespace ts.projectSystem {
|
||||
const module2Name = "../module2";
|
||||
const fileContent = `import { module1 } from "${module1Name}";import { module2 } from "${module2Name}";`;
|
||||
const { file1, file2 } = getFiles(fileContent);
|
||||
const { module1, module2 } = getModules(`${projectLocation}/src/module1.ts`, `${projectLocation}/module2.ts`);
|
||||
const { module1, module2 } = getModules(`${projectRoot}/src/module1.ts`, `${projectRoot}/module2.ts`);
|
||||
const files = [module1, module2, file1, file2, configFile, libFile];
|
||||
const host = createServerHost(files);
|
||||
const resolutionTrace = createHostModuleResolutionTrace(host);
|
||||
@@ -660,12 +615,12 @@ namespace ts.projectSystem {
|
||||
});
|
||||
|
||||
it("non relative module name", () => {
|
||||
const expectedNonRelativeDirectories = [`${projectLocation}/node_modules`, `${projectLocation}/src`];
|
||||
const expectedNonRelativeDirectories = [`${projectRoot}/node_modules`, `${projectRoot}/src`];
|
||||
const module1Name = "module1";
|
||||
const module2Name = "module2";
|
||||
const fileContent = `import { module1 } from "${module1Name}";import { module2 } from "${module2Name}";`;
|
||||
const { file1, file2 } = getFiles(fileContent);
|
||||
const { module1, module2 } = getModules(`${projectLocation}/src/node_modules/module1/index.ts`, `${projectLocation}/node_modules/module2/index.ts`);
|
||||
const { module1, module2 } = getModules(`${projectRoot}/src/node_modules/module1/index.ts`, `${projectRoot}/node_modules/module2/index.ts`);
|
||||
const files = [module1, module2, file1, file2, configFile, libFile];
|
||||
const host = createServerHost(files);
|
||||
const resolutionTrace = createHostModuleResolutionTrace(host);
|
||||
@@ -691,19 +646,19 @@ namespace ts.projectSystem {
|
||||
describe("from files in different folders", () => {
|
||||
function getFiles(fileContent1: string, fileContent2 = fileContent1, fileContent3 = fileContent1, fileContent4 = fileContent1) {
|
||||
const file1: File = {
|
||||
path: `${projectLocation}/product/src/file1.ts`,
|
||||
path: `${projectRoot}/product/src/file1.ts`,
|
||||
content: fileContent1
|
||||
};
|
||||
const file2: File = {
|
||||
path: `${projectLocation}/product/src/feature/file2.ts`,
|
||||
path: `${projectRoot}/product/src/feature/file2.ts`,
|
||||
content: fileContent2
|
||||
};
|
||||
const file3: File = {
|
||||
path: `${projectLocation}/product/test/src/file3.ts`,
|
||||
path: `${projectRoot}/product/test/src/file3.ts`,
|
||||
content: fileContent3
|
||||
};
|
||||
const file4: File = {
|
||||
path: `${projectLocation}/product/test/file4.ts`,
|
||||
path: `${projectRoot}/product/test/file4.ts`,
|
||||
content: fileContent4
|
||||
};
|
||||
return { file1, file2, file3, file4 };
|
||||
@@ -721,7 +676,7 @@ namespace ts.projectSystem {
|
||||
const fileContent3 = `import { module1 } from "${module5Name}";import { module2 } from "${module4Name}";`;
|
||||
const fileContent4 = `import { module1 } from "${module6Name}";import { module2 } from "${module2Name}";`;
|
||||
const { file1, file2, file3, file4 } = getFiles(fileContent1, fileContent2, fileContent3, fileContent4);
|
||||
const { module1, module2 } = getModules(`${projectLocation}/product/src/module1.ts`, `${projectLocation}/product/module2.ts`);
|
||||
const { module1, module2 } = getModules(`${projectRoot}/product/src/module1.ts`, `${projectRoot}/product/module2.ts`);
|
||||
const files = [module1, module2, file1, file2, file3, file4, configFile, libFile];
|
||||
const host = createServerHost(files);
|
||||
const resolutionTrace = createHostModuleResolutionTrace(host);
|
||||
@@ -753,12 +708,12 @@ namespace ts.projectSystem {
|
||||
});
|
||||
|
||||
it("non relative module name", () => {
|
||||
const expectedNonRelativeDirectories = [`${projectLocation}/node_modules`, `${projectLocation}/product`];
|
||||
const expectedNonRelativeDirectories = [`${projectRoot}/node_modules`, `${projectRoot}/product`];
|
||||
const module1Name = "module1";
|
||||
const module2Name = "module2";
|
||||
const fileContent = `import { module1 } from "${module1Name}";import { module2 } from "${module2Name}";`;
|
||||
const { file1, file2, file3, file4 } = getFiles(fileContent);
|
||||
const { module1, module2 } = getModules(`${projectLocation}/product/node_modules/module1/index.ts`, `${projectLocation}/node_modules/module2/index.ts`);
|
||||
const { module1, module2 } = getModules(`${projectRoot}/product/node_modules/module1/index.ts`, `${projectRoot}/node_modules/module2/index.ts`);
|
||||
const files = [module1, module2, file1, file2, file3, file4, configFile, libFile];
|
||||
const host = createServerHost(files);
|
||||
const resolutionTrace = createHostModuleResolutionTrace(host);
|
||||
@@ -768,8 +723,8 @@ namespace ts.projectSystem {
|
||||
getExpectedNonRelativeModuleResolutionTrace(host, file1, module2, module2Name, expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file2, module1, module1Name, getDirectoryPath(file1.path), expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file2, module2, module2Name, getDirectoryPath(file1.path), expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file4, module1, module1Name, `${projectLocation}/product`, expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file4, module2, module2Name, `${projectLocation}/product`, expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file4, module1, module1Name, `${projectRoot}/product`, expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file4, module2, module2Name, `${projectRoot}/product`, expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file3, module1, module1Name, getDirectoryPath(file4.path), expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file3, module2, module2Name, getDirectoryPath(file4.path), expectedTrace);
|
||||
verifyTrace(resolutionTrace, expectedTrace);
|
||||
@@ -797,7 +752,7 @@ namespace ts.projectSystem {
|
||||
const file4Name = "../test/file4";
|
||||
const importModuleContent = `import { module1 } from "${module1Name}";import { module2 } from "${module2Name}";`;
|
||||
const { file1, file2, file3, file4 } = getFiles(`import "${file2Name}"; import "${file4Name}"; import "${file3Name}"; ${importModuleContent}`, importModuleContent, importModuleContent, importModuleContent);
|
||||
const { module1, module2 } = getModules(`${projectLocation}/product/node_modules/module1/index.ts`, `${projectLocation}/node_modules/module2/index.ts`);
|
||||
const { module1, module2 } = getModules(`${projectRoot}/product/node_modules/module1/index.ts`, `${projectRoot}/node_modules/module2/index.ts`);
|
||||
const files = [module1, module2, file1, file2, file3, file4, libFile];
|
||||
const host = createServerHost(files);
|
||||
const resolutionTrace = createHostModuleResolutionTrace(host);
|
||||
@@ -811,19 +766,19 @@ namespace ts.projectSystem {
|
||||
getExpectedNonRelativeModuleResolutionTrace(host, file1, module2, module2Name, expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file2, module1, module1Name, getDirectoryPath(file1.path), expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file2, module2, module2Name, getDirectoryPath(file1.path), expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file4, module1, module1Name, `${projectLocation}/product`, expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file4, module2, module2Name, `${projectLocation}/product`, expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file4, module1, module1Name, `${projectRoot}/product`, expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file4, module2, module2Name, `${projectRoot}/product`, expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file3, module1, module1Name, getDirectoryPath(file4.path), expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file3, module2, module2Name, getDirectoryPath(file4.path), expectedTrace);
|
||||
verifyTrace(resolutionTrace, expectedTrace);
|
||||
|
||||
const currentDirectory = getDirectoryPath(file1.path);
|
||||
const watchedFiles = mapDefined(files, f => f === file1 || f.path.indexOf("/node_modules/") !== -1 ? undefined : f.path)
|
||||
.concat(getConfigFilesToWatch(`${projectLocation}/product/src`));
|
||||
.concat(getConfigFilesToWatch(`${projectRoot}/product/src`));
|
||||
const watchedRecursiveDirectories = getTypeRootsFromLocation(currentDirectory).concat([
|
||||
`${currentDirectory}/node_modules`, `${currentDirectory}/feature`, `${projectLocation}/product/${nodeModules}`,
|
||||
`${projectLocation}/${nodeModules}`, `${projectLocation}/product/test/${nodeModules}`,
|
||||
`${projectLocation}/product/test/src/${nodeModules}`
|
||||
`${currentDirectory}/node_modules`, `${currentDirectory}/feature`, `${projectRoot}/product/${nodeModules}`,
|
||||
`${projectRoot}/${nodeModules}`, `${projectRoot}/product/test/${nodeModules}`,
|
||||
`${projectRoot}/product/test/src/${nodeModules}`
|
||||
]);
|
||||
checkWatches();
|
||||
|
||||
@@ -852,7 +807,6 @@ namespace ts.projectSystem {
|
||||
});
|
||||
|
||||
describe("when watching directories for failed lookup locations in amd resolution", () => {
|
||||
const projectRoot = "/user/username/projects/project";
|
||||
const nodeFile: File = {
|
||||
path: `${projectRoot}/src/typings/node.d.ts`,
|
||||
content: `
|
||||
@@ -928,17 +882,16 @@ export const x = 10;`
|
||||
});
|
||||
|
||||
describe("ignores files/folder changes in node_modules that start with '.'", () => {
|
||||
const projectPath = "/user/username/projects/project";
|
||||
const npmCacheFile: File = {
|
||||
path: `${projectPath}/node_modules/.cache/babel-loader/89c02171edab901b9926470ba6d5677e.ts`,
|
||||
path: `${projectRoot}/node_modules/.cache/babel-loader/89c02171edab901b9926470ba6d5677e.ts`,
|
||||
content: JSON.stringify({ something: 10 })
|
||||
};
|
||||
const file1: File = {
|
||||
path: `${projectPath}/test.ts`,
|
||||
path: `${projectRoot}/test.ts`,
|
||||
content: `import { x } from "somemodule";`
|
||||
};
|
||||
const file2: File = {
|
||||
path: `${projectPath}/node_modules/somemodule/index.d.ts`,
|
||||
path: `${projectRoot}/node_modules/somemodule/index.d.ts`,
|
||||
content: `export const x = 10;`
|
||||
};
|
||||
it("when watching node_modules in inferred project for failed lookup/closed script infos", () => {
|
||||
@@ -957,7 +910,7 @@ export const x = 10;`
|
||||
});
|
||||
it("when watching node_modules as part of wild card directories in config project", () => {
|
||||
const config: File = {
|
||||
path: `${projectPath}/tsconfig.json`,
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
content: "{}"
|
||||
};
|
||||
const files = [libFile, file1, file2, config];
|
||||
@@ -976,15 +929,15 @@ export const x = 10;`
|
||||
|
||||
describe("avoid unnecessary invalidation", () => {
|
||||
it("unnecessary lookup invalidation on save", () => {
|
||||
const expectedNonRelativeDirectories = [`${projectLocation}/node_modules`, `${projectLocation}/src`];
|
||||
const expectedNonRelativeDirectories = [`${projectRoot}/node_modules`, `${projectRoot}/src`];
|
||||
const module1Name = "module1";
|
||||
const module2Name = "module2";
|
||||
const fileContent = `import { module1 } from "${module1Name}";import { module2 } from "${module2Name}";`;
|
||||
const file1: File = {
|
||||
path: `${projectLocation}/src/file1.ts`,
|
||||
path: `${projectRoot}/src/file1.ts`,
|
||||
content: fileContent
|
||||
};
|
||||
const { module1, module2 } = getModules(`${projectLocation}/src/node_modules/module1/index.ts`, `${projectLocation}/node_modules/module2/index.ts`);
|
||||
const { module1, module2 } = getModules(`${projectRoot}/src/node_modules/module1/index.ts`, `${projectRoot}/node_modules/module2/index.ts`);
|
||||
const files = [module1, module2, file1, configFile, libFile];
|
||||
const host = createServerHost(files);
|
||||
const resolutionTrace = createHostModuleResolutionTrace(host);
|
||||
|
||||
@@ -149,34 +149,16 @@ new C();`
|
||||
const filesInProjectWithResolvedModule = [...filesInProjectWithUnresolvedModule, recongnizerTextDistTypingFile.path];
|
||||
|
||||
function verifyErrors(session: TestSession, semanticErrors: protocol.Diagnostic[]) {
|
||||
session.clearMessages();
|
||||
const expectedSequenceId = session.getNextSeq();
|
||||
session.executeCommandSeq<protocol.GeterrRequest>({
|
||||
command: server.CommandNames.Geterr,
|
||||
arguments: {
|
||||
delay: 0,
|
||||
files: [recognizersDateTimeSrcFile.path],
|
||||
}
|
||||
verifyGetErrRequest({
|
||||
session,
|
||||
host: session.testhost,
|
||||
expected: [{
|
||||
file: recognizersDateTimeSrcFile,
|
||||
syntax: [],
|
||||
semantic: semanticErrors,
|
||||
suggestion: []
|
||||
}]
|
||||
});
|
||||
|
||||
const host = session.testhost;
|
||||
host.checkTimeoutQueueLengthAndRun(1);
|
||||
|
||||
checkErrorMessage(session, "syntaxDiag", { file: recognizersDateTimeSrcFile.path, diagnostics: [] });
|
||||
session.clearMessages();
|
||||
|
||||
host.runQueuedImmediateCallbacks(1);
|
||||
|
||||
checkErrorMessage(session, "semanticDiag", { file: recognizersDateTimeSrcFile.path, diagnostics: semanticErrors });
|
||||
session.clearMessages();
|
||||
|
||||
host.runQueuedImmediateCallbacks(1);
|
||||
|
||||
checkErrorMessage(session, "suggestionDiag", {
|
||||
file: recognizersDateTimeSrcFile.path,
|
||||
diagnostics: [],
|
||||
});
|
||||
checkCompleteEvent(session, 2, expectedSequenceId);
|
||||
}
|
||||
|
||||
function verifyWatchedFilesAndDirectories(host: TestServerHost, files: string[], recursiveDirectories: ReadonlyMap<number>, nonRecursiveDirectories: string[]) {
|
||||
|
||||
@@ -15,7 +15,6 @@ namespace ts.projectSystem {
|
||||
}
|
||||
|
||||
it("works when file is removed and added with different content", () => {
|
||||
const projectRoot = "/user/username/projects/myproject";
|
||||
const app: File = {
|
||||
path: `${projectRoot}/app.ts`,
|
||||
content: "console.log('Hello world');"
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
namespace ts.projectSystem {
|
||||
describe("unittests:: tsserver:: typeReferenceDirectives", () => {
|
||||
it("when typeReferenceDirective contains UpperCasePackage", () => {
|
||||
const projectLocation = "/user/username/projects/myproject";
|
||||
const libProjectLocation = `${projectLocation}/lib`;
|
||||
const libProjectLocation = `${projectRoot}/lib`;
|
||||
const typeLib: File = {
|
||||
path: `${libProjectLocation}/@types/UpperCasePackage/index.d.ts`,
|
||||
content: `declare class BrokenTest {
|
||||
@@ -20,7 +19,7 @@ declare class TestLib {
|
||||
test(): void;
|
||||
}`
|
||||
};
|
||||
const testProjectLocation = `${projectLocation}/test`;
|
||||
const testProjectLocation = `${projectRoot}/test`;
|
||||
const testFile: File = {
|
||||
path: `${testProjectLocation}/test.ts`,
|
||||
content: `class TestClass1 {
|
||||
@@ -58,8 +57,7 @@ declare class TestLib {
|
||||
});
|
||||
|
||||
it("when typeReferenceDirective is relative path and in a sibling folder", () => {
|
||||
const projectRootPath = "/user/username/projects/browser-addon";
|
||||
const projectPath = `${projectRootPath}/background`;
|
||||
const projectPath = `${projectRoot}/background`;
|
||||
const file: File = {
|
||||
path: `${projectPath}/a.ts`,
|
||||
content: "let x = 10;"
|
||||
@@ -75,7 +73,7 @@ declare class TestLib {
|
||||
})
|
||||
};
|
||||
const filesystem: File = {
|
||||
path: `${projectRootPath}/typedefs/filesystem.d.ts`,
|
||||
path: `${projectRoot}/typedefs/filesystem.d.ts`,
|
||||
content: `interface LocalFileSystem { someProperty: string; }`
|
||||
};
|
||||
const files = [file, tsconfig, filesystem, libFile];
|
||||
|
||||
@@ -994,7 +994,6 @@ namespace ts.projectSystem {
|
||||
});
|
||||
|
||||
it("should redo resolution that resolved to '.js' file after typings are installed", () => {
|
||||
const projects = `/user/username/projects`;
|
||||
const file: TestFSWithWatch.File = {
|
||||
path: `${projects}/a/b/app.js`,
|
||||
content: `
|
||||
|
||||
Reference in New Issue
Block a user