mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 16:38:05 -06:00
Merge pull request #19730 from Microsoft/fileNotOnDisk
Handles script infos that dont exist on the disk and are opened with non-rooted disk path
This commit is contained in:
commit
ddbd654ecd
@ -437,6 +437,50 @@ namespace ts.projectSystem {
|
||||
verifyDiagnostics(actual, []);
|
||||
}
|
||||
|
||||
function assertEvent(actualOutput: string, expectedEvent: protocol.Event, host: TestServerHost) {
|
||||
assert.equal(actualOutput, server.formatMessage(expectedEvent, nullLogger, Utils.byteLength, host.newLine));
|
||||
}
|
||||
|
||||
function checkErrorMessage(host: TestServerHost, eventName: "syntaxDiag" | "semanticDiag", diagnostics: protocol.DiagnosticEventBody) {
|
||||
const outputs = host.getOutput();
|
||||
assert.isTrue(outputs.length >= 1, outputs.toString());
|
||||
const event: protocol.Event = {
|
||||
seq: 0,
|
||||
type: "event",
|
||||
event: eventName,
|
||||
body: diagnostics
|
||||
};
|
||||
assertEvent(outputs[0], event, host);
|
||||
}
|
||||
|
||||
function checkCompleteEvent(host: TestServerHost, numberOfCurrentEvents: number, expectedSequenceId: number) {
|
||||
const outputs = host.getOutput();
|
||||
assert.equal(outputs.length, numberOfCurrentEvents, outputs.toString());
|
||||
const event: protocol.RequestCompletedEvent = {
|
||||
seq: 0,
|
||||
type: "event",
|
||||
event: "requestCompleted",
|
||||
body: {
|
||||
request_seq: expectedSequenceId
|
||||
}
|
||||
};
|
||||
assertEvent(outputs[numberOfCurrentEvents - 1], event, host);
|
||||
}
|
||||
|
||||
function checkProjectUpdatedInBackgroundEvent(host: TestServerHost, openFiles: string[]) {
|
||||
const outputs = host.getOutput();
|
||||
assert.equal(outputs.length, 1, outputs.toString());
|
||||
const event: protocol.ProjectsUpdatedInBackgroundEvent = {
|
||||
seq: 0,
|
||||
type: "event",
|
||||
event: "projectsUpdatedInBackground",
|
||||
body: {
|
||||
openFiles
|
||||
}
|
||||
};
|
||||
assertEvent(outputs[0], event, host);
|
||||
}
|
||||
|
||||
describe("tsserverProjectSystem", () => {
|
||||
const commonFile1: FileOrFolder = {
|
||||
path: "/a/b/commonFile1.ts",
|
||||
@ -2744,6 +2788,87 @@ namespace ts.projectSystem {
|
||||
const project = projectService.findProject(corruptedConfig.path);
|
||||
checkProjectRootFiles(project, [file1.path]);
|
||||
});
|
||||
|
||||
describe("when opening new file that doesnt exist on disk yet", () => {
|
||||
function verifyNonExistentFile(useProjectRoot: boolean) {
|
||||
const host = createServerHost([libFile]);
|
||||
let hasError = false;
|
||||
const errLogger: server.Logger = {
|
||||
close: noop,
|
||||
hasLevel: () => true,
|
||||
loggingEnabled: () => true,
|
||||
perftrc: noop,
|
||||
info: noop,
|
||||
msg: (_s, type) => {
|
||||
if (type === server.Msg.Err) {
|
||||
hasError = true;
|
||||
}
|
||||
},
|
||||
startGroup: noop,
|
||||
endGroup: noop,
|
||||
getLogFileName: (): string => undefined
|
||||
};
|
||||
const session = createSession(host, { canUseEvents: true, logger: errLogger, useInferredProjectPerProjectRoot: true });
|
||||
|
||||
const folderPath = "/user/someuser/projects/someFolder";
|
||||
const projectService = session.getProjectService();
|
||||
const untitledFile = "untitled:Untitled-1";
|
||||
session.executeCommandSeq<protocol.OpenRequest>({
|
||||
command: server.CommandNames.Open,
|
||||
arguments: {
|
||||
file: untitledFile,
|
||||
fileContent: "",
|
||||
scriptKindName: "JS",
|
||||
projectRootPath: useProjectRoot ? folderPath : undefined
|
||||
}
|
||||
});
|
||||
checkNumberOfProjects(projectService, { inferredProjects: 1 });
|
||||
const infoForUntitledAtProjectRoot = projectService.getScriptInfoForPath(`${folderPath.toLowerCase()}/${untitledFile.toLowerCase()}` as Path);
|
||||
const infoForUnitiledAtRoot = projectService.getScriptInfoForPath(`/${untitledFile.toLowerCase()}` as Path);
|
||||
if (useProjectRoot) {
|
||||
assert.isDefined(infoForUntitledAtProjectRoot);
|
||||
assert.isUndefined(infoForUnitiledAtRoot);
|
||||
}
|
||||
else {
|
||||
assert.isDefined(infoForUnitiledAtRoot);
|
||||
assert.isUndefined(infoForUntitledAtProjectRoot);
|
||||
}
|
||||
host.checkTimeoutQueueLength(2);
|
||||
|
||||
const newTimeoutId = host.getNextTimeoutId();
|
||||
const expectedSequenceId = session.getNextSeq();
|
||||
session.executeCommandSeq<protocol.GeterrRequest>({
|
||||
command: server.CommandNames.Geterr,
|
||||
arguments: {
|
||||
delay: 0,
|
||||
files: [untitledFile]
|
||||
}
|
||||
});
|
||||
host.checkTimeoutQueueLength(3);
|
||||
|
||||
// Run the last one = get error request
|
||||
host.runQueuedTimeoutCallbacks(newTimeoutId);
|
||||
|
||||
assert.isFalse(hasError);
|
||||
host.checkTimeoutQueueLength(2);
|
||||
checkErrorMessage(host, "syntaxDiag", { file: untitledFile, diagnostics: [] });
|
||||
host.clearOutput();
|
||||
|
||||
host.runQueuedImmediateCallbacks();
|
||||
assert.isFalse(hasError);
|
||||
checkErrorMessage(host, "semanticDiag", { file: untitledFile, diagnostics: [] });
|
||||
|
||||
checkCompleteEvent(host, 2, expectedSequenceId);
|
||||
}
|
||||
|
||||
it("has projectRoot", () => {
|
||||
verifyNonExistentFile(/*useProjectRoot*/ true);
|
||||
});
|
||||
|
||||
it("does not have projectRoot", () => {
|
||||
verifyNonExistentFile(/*useProjectRoot*/ false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("autoDiscovery", () => {
|
||||
@ -3446,50 +3571,6 @@ namespace ts.projectSystem {
|
||||
verifyNoDiagnostics(diags);
|
||||
});
|
||||
|
||||
function assertEvent(actualOutput: string, expectedEvent: protocol.Event, host: TestServerHost) {
|
||||
assert.equal(actualOutput, server.formatMessage(expectedEvent, nullLogger, Utils.byteLength, host.newLine));
|
||||
}
|
||||
|
||||
function checkErrorMessage(host: TestServerHost, eventName: "syntaxDiag" | "semanticDiag", diagnostics: protocol.DiagnosticEventBody) {
|
||||
const outputs = host.getOutput();
|
||||
assert.isTrue(outputs.length >= 1, outputs.toString());
|
||||
const event: protocol.Event = {
|
||||
seq: 0,
|
||||
type: "event",
|
||||
event: eventName,
|
||||
body: diagnostics
|
||||
};
|
||||
assertEvent(outputs[0], event, host);
|
||||
}
|
||||
|
||||
function checkCompleteEvent(host: TestServerHost, numberOfCurrentEvents: number, expectedSequenceId: number) {
|
||||
const outputs = host.getOutput();
|
||||
assert.equal(outputs.length, numberOfCurrentEvents, outputs.toString());
|
||||
const event: protocol.RequestCompletedEvent = {
|
||||
seq: 0,
|
||||
type: "event",
|
||||
event: "requestCompleted",
|
||||
body: {
|
||||
request_seq: expectedSequenceId
|
||||
}
|
||||
};
|
||||
assertEvent(outputs[numberOfCurrentEvents - 1], event, host);
|
||||
}
|
||||
|
||||
function checkProjectUpdatedInBackgroundEvent(host: TestServerHost, openFiles: string[]) {
|
||||
const outputs = host.getOutput();
|
||||
assert.equal(outputs.length, 1, outputs.toString());
|
||||
const event: protocol.ProjectsUpdatedInBackgroundEvent = {
|
||||
seq: 0,
|
||||
type: "event",
|
||||
event: "projectsUpdatedInBackground",
|
||||
body: {
|
||||
openFiles
|
||||
}
|
||||
};
|
||||
assertEvent(outputs[0], event, host);
|
||||
}
|
||||
|
||||
it("npm install @types works", () => {
|
||||
const folderPath = "/a/b/projects/temp";
|
||||
const file1: FileOrFolder = {
|
||||
|
||||
@ -182,6 +182,10 @@ interface Array<T> {}`
|
||||
private map: TimeOutCallback[] = [];
|
||||
private nextId = 1;
|
||||
|
||||
getNextId() {
|
||||
return this.nextId;
|
||||
}
|
||||
|
||||
register(cb: (...args: any[]) => void, args: any[]) {
|
||||
const timeoutId = this.nextId;
|
||||
this.nextId++;
|
||||
@ -203,7 +207,13 @@ interface Array<T> {}`
|
||||
return n;
|
||||
}
|
||||
|
||||
invoke() {
|
||||
invoke(invokeKey?: number) {
|
||||
if (invokeKey) {
|
||||
this.map[invokeKey]();
|
||||
delete this.map[invokeKey];
|
||||
return;
|
||||
}
|
||||
|
||||
// Note: invoking a callback may result in new callbacks been queued,
|
||||
// so do not clear the entire callback list regardless. Only remove the
|
||||
// ones we have invoked.
|
||||
@ -553,6 +563,10 @@ interface Array<T> {}`
|
||||
return this.timeoutCallbacks.register(callback, args);
|
||||
}
|
||||
|
||||
getNextTimeoutId() {
|
||||
return this.timeoutCallbacks.getNextId();
|
||||
}
|
||||
|
||||
clearTimeout(timeoutId: any): void {
|
||||
this.timeoutCallbacks.unregister(timeoutId);
|
||||
}
|
||||
@ -567,9 +581,9 @@ interface Array<T> {}`
|
||||
assert.equal(callbacksCount, expected, `expected ${expected} timeout callbacks queued but found ${callbacksCount}.`);
|
||||
}
|
||||
|
||||
runQueuedTimeoutCallbacks() {
|
||||
runQueuedTimeoutCallbacks(timeoutId?: number) {
|
||||
try {
|
||||
this.timeoutCallbacks.invoke();
|
||||
this.timeoutCallbacks.invoke(timeoutId);
|
||||
}
|
||||
catch (e) {
|
||||
if (e.message === this.existMessage) {
|
||||
|
||||
@ -355,6 +355,10 @@ namespace ts.server {
|
||||
* Open files: with value being project root path, and key being Path of the file that is open
|
||||
*/
|
||||
readonly openFiles = createMap<NormalizedPath>();
|
||||
/**
|
||||
* Map of open files that are opened without complete path but have projectRoot as current directory
|
||||
*/
|
||||
private readonly openFilesWithNonRootedDiskPath = createMap<ScriptInfo>();
|
||||
|
||||
private compilerOptionsForInferredProjects: CompilerOptions;
|
||||
private compilerOptionsForInferredProjectsPerProjectRoot = createMap<CompilerOptions>();
|
||||
@ -932,12 +936,16 @@ namespace ts.server {
|
||||
// Closing file should trigger re-reading the file content from disk. This is
|
||||
// because the user may chose to discard the buffer content before saving
|
||||
// to the disk, and the server's version of the file can be out of sync.
|
||||
info.close();
|
||||
const fileExists = this.host.fileExists(info.fileName);
|
||||
info.close(fileExists);
|
||||
this.stopWatchingConfigFilesForClosedScriptInfo(info);
|
||||
|
||||
this.openFiles.delete(info.path);
|
||||
const canonicalFileName = this.toCanonicalFileName(info.fileName);
|
||||
if (this.openFilesWithNonRootedDiskPath.get(canonicalFileName) === info) {
|
||||
this.openFilesWithNonRootedDiskPath.delete(canonicalFileName);
|
||||
}
|
||||
|
||||
const fileExists = this.host.fileExists(info.fileName);
|
||||
|
||||
// collect all projects that should be removed
|
||||
let projectsToRemove: Project[];
|
||||
@ -1537,7 +1545,7 @@ namespace ts.server {
|
||||
else {
|
||||
const scriptKind = propertyReader.getScriptKind(f, this.hostConfiguration.extraFileExtensions);
|
||||
const hasMixedContent = propertyReader.hasMixedContent(f, this.hostConfiguration.extraFileExtensions);
|
||||
scriptInfo = this.getOrCreateScriptInfoNotOpenedByClientForNormalizedPath(normalizedPath, scriptKind, hasMixedContent, project.directoryStructureHost);
|
||||
scriptInfo = this.getOrCreateScriptInfoNotOpenedByClientForNormalizedPath(normalizedPath, project.currentDirectory, scriptKind, hasMixedContent, project.directoryStructureHost);
|
||||
path = scriptInfo.path;
|
||||
// If this script info is not already a root add it
|
||||
if (!project.isRoot(scriptInfo)) {
|
||||
@ -1691,9 +1699,9 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
getOrCreateScriptInfoNotOpenedByClient(uncheckedFileName: string, hostToQueryFileExistsOn: DirectoryStructureHost) {
|
||||
getOrCreateScriptInfoNotOpenedByClient(uncheckedFileName: string, currentDirectory: string, hostToQueryFileExistsOn: DirectoryStructureHost) {
|
||||
return this.getOrCreateScriptInfoNotOpenedByClientForNormalizedPath(
|
||||
toNormalizedPath(uncheckedFileName), /*scriptKind*/ undefined,
|
||||
toNormalizedPath(uncheckedFileName), currentDirectory, /*scriptKind*/ undefined,
|
||||
/*hasMixedContent*/ undefined, hostToQueryFileExistsOn
|
||||
);
|
||||
}
|
||||
@ -1724,20 +1732,26 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
getOrCreateScriptInfoNotOpenedByClientForNormalizedPath(fileName: NormalizedPath, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: DirectoryStructureHost) {
|
||||
return this.getOrCreateScriptInfoForNormalizedPath(fileName, /*openedByClient*/ false, /*fileContent*/ undefined, scriptKind, hasMixedContent, hostToQueryFileExistsOn);
|
||||
getOrCreateScriptInfoNotOpenedByClientForNormalizedPath(fileName: NormalizedPath, currentDirectory: string, scriptKind: ScriptKind | undefined, hasMixedContent: boolean | undefined, hostToQueryFileExistsOn: DirectoryStructureHost | undefined) {
|
||||
return this.getOrCreateScriptInfoWorker(fileName, currentDirectory, /*openedByClient*/ false, /*fileContent*/ undefined, scriptKind, hasMixedContent, hostToQueryFileExistsOn);
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: DirectoryStructureHost) {
|
||||
return this.getOrCreateScriptInfoForNormalizedPath(fileName, /*openedByClient*/ true, fileContent, scriptKind, hasMixedContent, hostToQueryFileExistsOn);
|
||||
getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName: NormalizedPath, currentDirectory: string, fileContent: string | undefined, scriptKind: ScriptKind | undefined, hasMixedContent: boolean | undefined) {
|
||||
return this.getOrCreateScriptInfoWorker(fileName, currentDirectory, /*openedByClient*/ true, fileContent, scriptKind, hasMixedContent);
|
||||
}
|
||||
|
||||
getOrCreateScriptInfoForNormalizedPath(fileName: NormalizedPath, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: DirectoryStructureHost) {
|
||||
return this.getOrCreateScriptInfoWorker(fileName, this.currentDirectory, openedByClient, fileContent, scriptKind, hasMixedContent, hostToQueryFileExistsOn);
|
||||
}
|
||||
|
||||
private getOrCreateScriptInfoWorker(fileName: NormalizedPath, currentDirectory: string, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: DirectoryStructureHost) {
|
||||
Debug.assert(fileContent === undefined || openedByClient, "ScriptInfo needs to be opened by client to be able to set its user defined content");
|
||||
const path = normalizedPathToPath(fileName, this.currentDirectory, this.toCanonicalFileName);
|
||||
const path = normalizedPathToPath(fileName, currentDirectory, this.toCanonicalFileName);
|
||||
let info = this.getScriptInfoForPath(path);
|
||||
if (!info) {
|
||||
Debug.assert(isRootedDiskPath(fileName) || openedByClient, "Script info with relative file name can only be open script info");
|
||||
Debug.assert(!isRootedDiskPath(fileName) || this.currentDirectory === currentDirectory || !this.openFilesWithNonRootedDiskPath.has(this.toCanonicalFileName(fileName)), "Open script files with non rooted disk path opened with current directory context cannot have same canonical names");
|
||||
const isDynamic = isDynamicFileName(fileName);
|
||||
// If the file is not opened by client and the file doesnot exist on the disk, return
|
||||
if (!openedByClient && !isDynamic && !(hostToQueryFileExistsOn || this.host).fileExists(fileName)) {
|
||||
@ -1748,6 +1762,10 @@ namespace ts.server {
|
||||
if (!openedByClient) {
|
||||
this.watchClosedScriptInfo(info);
|
||||
}
|
||||
else if (!isRootedDiskPath(fileName) && currentDirectory !== this.currentDirectory) {
|
||||
// File that is opened by user but isn't rooted disk path
|
||||
this.openFilesWithNonRootedDiskPath.set(this.toCanonicalFileName(fileName), info);
|
||||
}
|
||||
}
|
||||
if (openedByClient && !info.isScriptOpen()) {
|
||||
// Opening closed script info
|
||||
@ -1764,8 +1782,12 @@ namespace ts.server {
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* This gets the script info for the normalized path. If the path is not rooted disk path then the open script info with project root context is preferred
|
||||
*/
|
||||
getScriptInfoForNormalizedPath(fileName: NormalizedPath) {
|
||||
return this.getScriptInfoForPath(normalizedPathToPath(fileName, this.currentDirectory, this.toCanonicalFileName));
|
||||
return !isRootedDiskPath(fileName) && this.openFilesWithNonRootedDiskPath.get(this.toCanonicalFileName(fileName)) ||
|
||||
this.getScriptInfoForPath(normalizedPathToPath(fileName, this.currentDirectory, this.toCanonicalFileName));
|
||||
}
|
||||
|
||||
getScriptInfoForPath(fileName: Path) {
|
||||
@ -1950,7 +1972,7 @@ namespace ts.server {
|
||||
let sendConfigFileDiagEvent = false;
|
||||
let configFileErrors: ReadonlyArray<Diagnostic>;
|
||||
|
||||
const info = this.getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName, fileContent, scriptKind, hasMixedContent);
|
||||
const info = this.getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName, projectRootPath ? this.getNormalizedAbsolutePath(projectRootPath) : this.currentDirectory, fileContent, scriptKind, hasMixedContent);
|
||||
let project: ConfiguredProject | ExternalProject = this.findContainingExternalProject(fileName);
|
||||
if (!project) {
|
||||
configFileName = this.getConfigFileNameForFile(info, projectRootPath);
|
||||
|
||||
@ -285,7 +285,7 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
private getOrCreateScriptInfoAndAttachToProject(fileName: string) {
|
||||
const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(fileName, this.directoryStructureHost);
|
||||
const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(fileName, this.currentDirectory, this.directoryStructureHost);
|
||||
if (scriptInfo) {
|
||||
const existingValue = this.rootFilesMap.get(scriptInfo.path);
|
||||
if (existingValue !== scriptInfo && existingValue !== undefined) {
|
||||
@ -365,7 +365,7 @@ namespace ts.server {
|
||||
|
||||
/*@internal*/
|
||||
toPath(fileName: string) {
|
||||
return this.projectService.toPath(fileName);
|
||||
return toPath(fileName, this.currentDirectory, this.projectService.toCanonicalFileName);
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
@ -658,7 +658,7 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
containsFile(filename: NormalizedPath, requireOpen?: boolean) {
|
||||
const info = this.projectService.getScriptInfoForNormalizedPath(filename);
|
||||
const info = this.projectService.getScriptInfoForPath(this.toPath(filename));
|
||||
if (info && (info.isScriptOpen() || !requireOpen)) {
|
||||
return this.containsScriptInfo(info);
|
||||
}
|
||||
@ -855,7 +855,7 @@ namespace ts.server {
|
||||
// by the LSHost for files in the program when the program is retrieved above but
|
||||
// the program doesn't contain external files so this must be done explicitly.
|
||||
inserted => {
|
||||
const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(inserted, this.directoryStructureHost);
|
||||
const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(inserted, this.currentDirectory, this.directoryStructureHost);
|
||||
scriptInfo.attachToProject(this);
|
||||
},
|
||||
removed => this.detachScriptInfoFromProject(removed)
|
||||
@ -901,7 +901,7 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
getScriptInfoForNormalizedPath(fileName: NormalizedPath) {
|
||||
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(fileName);
|
||||
const scriptInfo = this.projectService.getScriptInfoForPath(this.toPath(fileName));
|
||||
if (scriptInfo && !scriptInfo.isAttached(this)) {
|
||||
return Errors.ThrowProjectDoesNotContainDocument(fileName, this);
|
||||
}
|
||||
|
||||
@ -248,9 +248,9 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
|
||||
public close() {
|
||||
public close(fileExists = true) {
|
||||
this.textStorage.isOpen = false;
|
||||
if (this.isDynamicOrHasMixedContent()) {
|
||||
if (this.isDynamicOrHasMixedContent() || !fileExists) {
|
||||
if (this.textStorage.reload("")) {
|
||||
this.markContainingProjectsAsDirty();
|
||||
}
|
||||
|
||||
@ -7066,7 +7066,7 @@ declare namespace ts.server {
|
||||
constructor(host: ServerHost, fileName: NormalizedPath, scriptKind: ScriptKind, hasMixedContent: boolean, path: Path);
|
||||
isScriptOpen(): boolean;
|
||||
open(newText: string): void;
|
||||
close(): void;
|
||||
close(fileExists?: boolean): void;
|
||||
getSnapshot(): IScriptSnapshot;
|
||||
getFormatCodeSettings(): FormatCodeSettings;
|
||||
attachToProject(project: Project): boolean;
|
||||
@ -7490,6 +7490,10 @@ declare namespace ts.server {
|
||||
* Open files: with value being project root path, and key being Path of the file that is open
|
||||
*/
|
||||
readonly openFiles: Map<NormalizedPath>;
|
||||
/**
|
||||
* Map of open files that are opened without complete path but have projectRoot as current directory
|
||||
*/
|
||||
private readonly openFilesWithNonRootedDiskPath;
|
||||
private compilerOptionsForInferredProjects;
|
||||
private compilerOptionsForInferredProjectsPerProjectRoot;
|
||||
/**
|
||||
@ -7629,6 +7633,10 @@ declare namespace ts.server {
|
||||
private watchClosedScriptInfo(info);
|
||||
private stopWatchingScriptInfo(info);
|
||||
getOrCreateScriptInfoForNormalizedPath(fileName: NormalizedPath, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: DirectoryStructureHost): ScriptInfo;
|
||||
private getOrCreateScriptInfoWorker(fileName, currentDirectory, openedByClient, fileContent?, scriptKind?, hasMixedContent?, hostToQueryFileExistsOn?);
|
||||
/**
|
||||
* This gets the script info for the normalized path. If the path is not rooted disk path then the open script info with project root context is preferred
|
||||
*/
|
||||
getScriptInfoForNormalizedPath(fileName: NormalizedPath): ScriptInfo;
|
||||
getScriptInfoForPath(fileName: Path): ScriptInfo;
|
||||
setHostConfiguration(args: protocol.ConfigureRequestArguments): void;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user