mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
Add separate flag serverMode for server mode (#39735)
* Add separate flag serverMode for server mode to allow back compatibility * Addressed code review feedback. Co-authored-by: Daniel Rosenwasser <DanielRosenwasser@users.noreply.github.com>
This commit is contained in:
parent
86a87c493c
commit
aee78acedb
@ -396,7 +396,9 @@ namespace ts.server {
|
||||
pluginProbeLocations?: readonly string[];
|
||||
allowLocalPluginLoads?: boolean;
|
||||
typesMapLocation?: string;
|
||||
/** @deprecated use serverMode instead */
|
||||
syntaxOnly?: boolean;
|
||||
serverMode?: LanguageServiceMode;
|
||||
}
|
||||
|
||||
interface OriginalFileInfo { fileName: NormalizedPath; path: Path; }
|
||||
@ -683,7 +685,9 @@ namespace ts.server {
|
||||
|
||||
public readonly typesMapLocation: string | undefined;
|
||||
|
||||
public readonly syntaxOnly?: boolean;
|
||||
/** @deprecated use serverMode instead */
|
||||
public readonly syntaxOnly: boolean;
|
||||
public readonly serverMode: LanguageServiceMode;
|
||||
|
||||
/** Tracks projects that we have already sent telemetry for. */
|
||||
private readonly seenProjects = new Map<string, true>();
|
||||
@ -713,7 +717,18 @@ namespace ts.server {
|
||||
this.pluginProbeLocations = opts.pluginProbeLocations || emptyArray;
|
||||
this.allowLocalPluginLoads = !!opts.allowLocalPluginLoads;
|
||||
this.typesMapLocation = (opts.typesMapLocation === undefined) ? combinePaths(getDirectoryPath(this.getExecutingFilePath()), "typesMap.json") : opts.typesMapLocation;
|
||||
this.syntaxOnly = opts.syntaxOnly;
|
||||
if (opts.serverMode !== undefined) {
|
||||
this.serverMode = opts.serverMode;
|
||||
this.syntaxOnly = this.serverMode === LanguageServiceMode.SyntaxOnly;
|
||||
}
|
||||
else if (opts.syntaxOnly) {
|
||||
this.serverMode = LanguageServiceMode.SyntaxOnly;
|
||||
this.syntaxOnly = true;
|
||||
}
|
||||
else {
|
||||
this.serverMode = LanguageServiceMode.Semantic;
|
||||
this.syntaxOnly = false;
|
||||
}
|
||||
|
||||
Debug.assert(!!this.host.createHash, "'ServerHost.createHash' is required for ProjectService");
|
||||
if (this.host.realpath) {
|
||||
@ -749,7 +764,7 @@ namespace ts.server {
|
||||
this.logger.loggingEnabled() ? WatchLogLevel.TriggerOnly : WatchLogLevel.None;
|
||||
const log: (s: string) => void = watchLogLevel !== WatchLogLevel.None ? (s => this.logger.info(s)) : noop;
|
||||
this.packageJsonCache = createPackageJsonCache(this);
|
||||
this.watchFactory = this.syntaxOnly ?
|
||||
this.watchFactory = this.serverMode !== LanguageServiceMode.Semantic ?
|
||||
{
|
||||
watchFile: returnNoopFileWatcher,
|
||||
watchFilePath: returnNoopFileWatcher,
|
||||
@ -1727,7 +1742,7 @@ namespace ts.server {
|
||||
* the newly opened file.
|
||||
*/
|
||||
private forEachConfigFileLocation(info: OpenScriptInfoOrClosedOrConfigFileInfo, action: (configFileName: NormalizedPath, canonicalConfigFilePath: string) => boolean | void) {
|
||||
if (this.syntaxOnly) {
|
||||
if (this.serverMode !== LanguageServiceMode.Semantic) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@ -3014,7 +3029,7 @@ namespace ts.server {
|
||||
let retainProjects: ConfiguredProject[] | ConfiguredProject | undefined;
|
||||
let projectForConfigFileDiag: ConfiguredProject | undefined;
|
||||
let defaultConfigProjectIsCreated = false;
|
||||
if (this.syntaxOnly) {
|
||||
if (this.serverMode === LanguageServiceMode.ApproximateSemanticOnly) {
|
||||
// Invalidate resolutions in the file since this file is now open
|
||||
info.containingProjects.forEach(project => {
|
||||
if (project.resolutionCache.removeRelativeNoResolveResolutionsOfFile(info.path)) {
|
||||
@ -3022,7 +3037,7 @@ namespace ts.server {
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (!project) { // Checking syntaxOnly is an optimization
|
||||
else if (!project && this.serverMode === LanguageServiceMode.Semantic) { // Checking semantic mode is an optimization
|
||||
configFileName = this.getConfigFileNameForFile(info);
|
||||
if (configFileName) {
|
||||
project = this.findConfiguredProjectByProjectName(configFileName);
|
||||
@ -3109,7 +3124,7 @@ namespace ts.server {
|
||||
Debug.assert(this.openFiles.has(info.path));
|
||||
this.assignOrphanScriptInfoToInferredProject(info, this.openFiles.get(info.path));
|
||||
}
|
||||
else if (this.syntaxOnly && info.cacheSourceFile?.sourceFile.referencedFiles.length) {
|
||||
else if (this.serverMode === LanguageServiceMode.ApproximateSemanticOnly && info.cacheSourceFile?.sourceFile.referencedFiles.length) {
|
||||
// This file was just opened and references in this file will previously not been resolved so schedule update
|
||||
info.containingProjects.forEach(project => project.markAsDirty());
|
||||
}
|
||||
@ -3325,7 +3340,7 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
private telemetryOnOpenFile(scriptInfo: ScriptInfo): void {
|
||||
if (this.syntaxOnly || !this.eventHandler || !scriptInfo.isJavaScript() || !addToSeen(this.allJsFilesForOpenFileTelemetry, scriptInfo.path)) {
|
||||
if (this.serverMode !== LanguageServiceMode.Semantic || !this.eventHandler || !scriptInfo.isJavaScript() || !addToSeen(this.allJsFilesForOpenFileTelemetry, scriptInfo.path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3637,7 +3652,7 @@ namespace ts.server {
|
||||
for (const file of proj.rootFiles) {
|
||||
const normalized = toNormalizedPath(file.fileName);
|
||||
if (getBaseConfigFileName(normalized)) {
|
||||
if (!this.syntaxOnly && this.host.fileExists(normalized)) {
|
||||
if (this.serverMode === LanguageServiceMode.Semantic && this.host.fileExists(normalized)) {
|
||||
(tsConfigFiles || (tsConfigFiles = [])).push(normalized);
|
||||
}
|
||||
}
|
||||
|
||||
@ -279,9 +279,21 @@ namespace ts.server {
|
||||
this.compilerOptions.allowNonTsExtensions = true;
|
||||
}
|
||||
|
||||
this.languageServiceEnabled = true;
|
||||
if (projectService.syntaxOnly) {
|
||||
this.compilerOptions.types = [];
|
||||
switch (projectService.serverMode) {
|
||||
case LanguageServiceMode.Semantic:
|
||||
this.languageServiceEnabled = true;
|
||||
break;
|
||||
case LanguageServiceMode.ApproximateSemanticOnly:
|
||||
this.languageServiceEnabled = true;
|
||||
this.compilerOptions.types = [];
|
||||
break;
|
||||
case LanguageServiceMode.SyntaxOnly:
|
||||
this.languageServiceEnabled = false;
|
||||
this.compilerOptions.noResolve = true;
|
||||
this.compilerOptions.types = [];
|
||||
break;
|
||||
default:
|
||||
Debug.assertNever(projectService.serverMode);
|
||||
}
|
||||
|
||||
this.setInternalCompilerOptionsForEmittingJsFiles();
|
||||
@ -298,10 +310,10 @@ namespace ts.server {
|
||||
this.resolutionCache = createResolutionCache(
|
||||
this,
|
||||
currentDirectory && this.currentDirectory,
|
||||
projectService.syntaxOnly ? ResolutionKind.RelativeReferencesInOpenFileOnly : ResolutionKind.All,
|
||||
projectService.serverMode === LanguageServiceMode.Semantic ? ResolutionKind.All : ResolutionKind.RelativeReferencesInOpenFileOnly,
|
||||
/*logChangesWhenResolvingModule*/ true
|
||||
);
|
||||
this.languageService = createLanguageService(this, this.documentRegistry, this.projectService.syntaxOnly);
|
||||
this.languageService = createLanguageService(this, this.documentRegistry, this.projectService.serverMode);
|
||||
if (lastFileExceededProgramSize) {
|
||||
this.disableLanguageService(lastFileExceededProgramSize);
|
||||
}
|
||||
@ -456,7 +468,16 @@ namespace ts.server {
|
||||
|
||||
/*@internal*/
|
||||
includeTripleslashReferencesFrom(containingFile: string) {
|
||||
return !this.projectService.syntaxOnly || this.fileIsOpen(this.toPath(containingFile));
|
||||
switch (this.projectService.serverMode) {
|
||||
case LanguageServiceMode.Semantic:
|
||||
return true;
|
||||
case LanguageServiceMode.ApproximateSemanticOnly:
|
||||
return this.fileIsOpen(this.toPath(containingFile));
|
||||
case LanguageServiceMode.SyntaxOnly:
|
||||
return false;
|
||||
default:
|
||||
Debug.assertNever(this.projectService.serverMode);
|
||||
}
|
||||
}
|
||||
|
||||
directoryExists(path: string): boolean {
|
||||
@ -656,7 +677,7 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
enableLanguageService() {
|
||||
if (this.languageServiceEnabled) {
|
||||
if (this.languageServiceEnabled || this.projectService.serverMode === LanguageServiceMode.SyntaxOnly) {
|
||||
return;
|
||||
}
|
||||
this.languageServiceEnabled = true;
|
||||
@ -668,6 +689,7 @@ namespace ts.server {
|
||||
if (!this.languageServiceEnabled) {
|
||||
return;
|
||||
}
|
||||
Debug.assert(this.projectService.serverMode !== LanguageServiceMode.SyntaxOnly);
|
||||
this.languageService.cleanupSemanticCache();
|
||||
this.languageServiceEnabled = false;
|
||||
this.lastFileExceededProgramSize = lastFileExceededProgramSize;
|
||||
@ -997,7 +1019,7 @@ namespace ts.server {
|
||||
|
||||
// update builder only if language service is enabled
|
||||
// otherwise tell it to drop its internal state
|
||||
if (this.languageServiceEnabled && !this.projectService.syntaxOnly) {
|
||||
if (this.languageServiceEnabled && this.projectService.serverMode === LanguageServiceMode.Semantic) {
|
||||
// 1. no changes in structure, no changes in unresolved imports - do nothing
|
||||
// 2. no changes in structure, unresolved imports were changed - collect unresolved imports for all files
|
||||
// (can reuse cached imports for files that were not changed)
|
||||
@ -1128,7 +1150,7 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
// Watch the type locations that would be added to program as part of automatic type resolutions
|
||||
if (this.languageServiceEnabled && !this.projectService.syntaxOnly) {
|
||||
if (this.languageServiceEnabled && this.projectService.serverMode === LanguageServiceMode.Semantic) {
|
||||
this.resolutionCache.updateTypeRootsWatch();
|
||||
}
|
||||
}
|
||||
|
||||
@ -585,7 +585,7 @@ namespace ts.server {
|
||||
undefined;
|
||||
}
|
||||
|
||||
const invalidSyntaxOnlyCommands: readonly CommandNames[] = [
|
||||
const invalidApproximateSemanticOnlyCommands: readonly CommandNames[] = [
|
||||
CommandNames.OpenExternalProject,
|
||||
CommandNames.OpenExternalProjects,
|
||||
CommandNames.CloseExternalProject,
|
||||
@ -621,6 +621,36 @@ namespace ts.server {
|
||||
CommandNames.ProvideCallHierarchyOutgoingCalls,
|
||||
];
|
||||
|
||||
const invalidSyntaxOnlyCommands: readonly CommandNames[] = [
|
||||
...invalidApproximateSemanticOnlyCommands,
|
||||
CommandNames.Definition,
|
||||
CommandNames.DefinitionFull,
|
||||
CommandNames.DefinitionAndBoundSpan,
|
||||
CommandNames.DefinitionAndBoundSpanFull,
|
||||
CommandNames.TypeDefinition,
|
||||
CommandNames.Implementation,
|
||||
CommandNames.ImplementationFull,
|
||||
CommandNames.References,
|
||||
CommandNames.ReferencesFull,
|
||||
CommandNames.Rename,
|
||||
CommandNames.RenameLocationsFull,
|
||||
CommandNames.RenameInfoFull,
|
||||
CommandNames.Quickinfo,
|
||||
CommandNames.QuickinfoFull,
|
||||
CommandNames.CompletionInfo,
|
||||
CommandNames.Completions,
|
||||
CommandNames.CompletionsFull,
|
||||
CommandNames.CompletionDetails,
|
||||
CommandNames.CompletionDetailsFull,
|
||||
CommandNames.SignatureHelp,
|
||||
CommandNames.SignatureHelpFull,
|
||||
CommandNames.Navto,
|
||||
CommandNames.NavtoFull,
|
||||
CommandNames.Occurrences,
|
||||
CommandNames.DocumentHighlights,
|
||||
CommandNames.DocumentHighlightsFull,
|
||||
];
|
||||
|
||||
export interface SessionOptions {
|
||||
host: ServerHost;
|
||||
cancellationToken: ServerCancellationToken;
|
||||
@ -637,7 +667,9 @@ namespace ts.server {
|
||||
eventHandler?: ProjectServiceEventHandler;
|
||||
/** Has no effect if eventHandler is also specified. */
|
||||
suppressDiagnosticEvents?: boolean;
|
||||
/** @deprecated use serverMode instead */
|
||||
syntaxOnly?: boolean;
|
||||
serverMode?: LanguageServiceMode;
|
||||
throttleWaitMilliseconds?: number;
|
||||
noGetErrOnBackgroundUpdate?: boolean;
|
||||
|
||||
@ -709,18 +741,32 @@ namespace ts.server {
|
||||
allowLocalPluginLoads: opts.allowLocalPluginLoads,
|
||||
typesMapLocation: opts.typesMapLocation,
|
||||
syntaxOnly: opts.syntaxOnly,
|
||||
serverMode: opts.serverMode,
|
||||
};
|
||||
this.projectService = new ProjectService(settings);
|
||||
this.projectService.setPerformanceEventHandler(this.performanceEventHandler.bind(this));
|
||||
this.gcTimer = new GcTimer(this.host, /*delay*/ 7000, this.logger);
|
||||
|
||||
// Make sure to setup handlers to throw error for not allowed commands on syntax server;
|
||||
if (this.projectService.syntaxOnly) {
|
||||
invalidSyntaxOnlyCommands.forEach(commandName =>
|
||||
this.handlers.set(commandName, request => {
|
||||
throw new Error(`Request: ${request.command} not allowed on syntaxServer`);
|
||||
})
|
||||
);
|
||||
// Make sure to setup handlers to throw error for not allowed commands on syntax server
|
||||
switch (this.projectService.serverMode) {
|
||||
case LanguageServiceMode.Semantic:
|
||||
break;
|
||||
case LanguageServiceMode.ApproximateSemanticOnly:
|
||||
invalidApproximateSemanticOnlyCommands.forEach(commandName =>
|
||||
this.handlers.set(commandName, request => {
|
||||
throw new Error(`Request: ${request.command} not allowed on approximate semantic only server`);
|
||||
})
|
||||
);
|
||||
break;
|
||||
case LanguageServiceMode.SyntaxOnly:
|
||||
invalidSyntaxOnlyCommands.forEach(commandName =>
|
||||
this.handlers.set(commandName, request => {
|
||||
throw new Error(`Request: ${request.command} not allowed on syntax only server`);
|
||||
})
|
||||
);
|
||||
break;
|
||||
default:
|
||||
Debug.assertNever(this.projectService.serverMode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1171,7 +1171,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
const invalidOperationsOnSyntaxOnly: readonly (keyof LanguageService)[] = [
|
||||
const invalidOperationsOnApproximateSemanticOnly: readonly (keyof LanguageService)[] = [
|
||||
"getSyntacticDiagnostics",
|
||||
"getSemanticDiagnostics",
|
||||
"getSuggestionDiagnostics",
|
||||
@ -1191,10 +1191,42 @@ namespace ts {
|
||||
"provideCallHierarchyOutgoingCalls",
|
||||
];
|
||||
|
||||
const invalidOperationsOnSyntaxOnly: readonly (keyof LanguageService)[] = [
|
||||
...invalidOperationsOnApproximateSemanticOnly,
|
||||
"getCompletionsAtPosition",
|
||||
"getCompletionEntryDetails",
|
||||
"getCompletionEntrySymbol",
|
||||
"getSignatureHelpItems",
|
||||
"getQuickInfoAtPosition",
|
||||
"getDefinitionAtPosition",
|
||||
"getDefinitionAndBoundSpan",
|
||||
"getImplementationAtPosition",
|
||||
"getTypeDefinitionAtPosition",
|
||||
"getReferencesAtPosition",
|
||||
"findReferences",
|
||||
"getOccurrencesAtPosition",
|
||||
"getDocumentHighlights",
|
||||
"getNavigateToItems",
|
||||
"getRenameInfo",
|
||||
"findRenameLocations",
|
||||
"getApplicableRefactors",
|
||||
];
|
||||
export function createLanguageService(
|
||||
host: LanguageServiceHost,
|
||||
documentRegistry: DocumentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory()),
|
||||
syntaxOnly = false): LanguageService {
|
||||
syntaxOnlyOrLanguageServiceMode?: boolean | LanguageServiceMode,
|
||||
): LanguageService {
|
||||
let languageServiceMode: LanguageServiceMode;
|
||||
if (syntaxOnlyOrLanguageServiceMode === undefined) {
|
||||
languageServiceMode = LanguageServiceMode.Semantic;
|
||||
}
|
||||
else if (typeof syntaxOnlyOrLanguageServiceMode === "boolean") {
|
||||
// languageServiceMode = SyntaxOnly
|
||||
languageServiceMode = syntaxOnlyOrLanguageServiceMode ? LanguageServiceMode.SyntaxOnly : LanguageServiceMode.Semantic;
|
||||
}
|
||||
else {
|
||||
languageServiceMode = syntaxOnlyOrLanguageServiceMode;
|
||||
}
|
||||
|
||||
const syntaxTreeCache: SyntaxTreeCache = new SyntaxTreeCache(host);
|
||||
let program: Program;
|
||||
@ -1244,6 +1276,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function synchronizeHostData(): void {
|
||||
Debug.assert(languageServiceMode !== LanguageServiceMode.SyntaxOnly);
|
||||
// perform fast check if host supports it
|
||||
if (host.getProjectVersion) {
|
||||
const hostProjectVersion = host.getProjectVersion();
|
||||
@ -1429,6 +1462,11 @@ namespace ts {
|
||||
|
||||
// TODO: GH#18217 frequently asserted as defined
|
||||
function getProgram(): Program | undefined {
|
||||
if (languageServiceMode === LanguageServiceMode.SyntaxOnly) {
|
||||
Debug.assert(program === undefined);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
synchronizeHostData();
|
||||
|
||||
return program;
|
||||
@ -2504,14 +2542,26 @@ namespace ts {
|
||||
uncommentSelection,
|
||||
};
|
||||
|
||||
if (syntaxOnly) {
|
||||
invalidOperationsOnSyntaxOnly.forEach(key =>
|
||||
ls[key] = () => {
|
||||
throw new Error(`LanguageService Operation: ${key} not allowed on syntaxServer`);
|
||||
}
|
||||
);
|
||||
switch (languageServiceMode) {
|
||||
case LanguageServiceMode.Semantic:
|
||||
break;
|
||||
case LanguageServiceMode.ApproximateSemanticOnly:
|
||||
invalidOperationsOnApproximateSemanticOnly.forEach(key =>
|
||||
ls[key] = () => {
|
||||
throw new Error(`LanguageService Operation: ${key} not allowed on approximate semantic only server`);
|
||||
}
|
||||
);
|
||||
break;
|
||||
case LanguageServiceMode.SyntaxOnly:
|
||||
invalidOperationsOnSyntaxOnly.forEach(key =>
|
||||
ls[key] = () => {
|
||||
throw new Error(`LanguageService Operation: ${key} not allowed on syntax only server`);
|
||||
}
|
||||
);
|
||||
break;
|
||||
default:
|
||||
Debug.assertNever(languageServiceMode);
|
||||
}
|
||||
|
||||
return ls;
|
||||
}
|
||||
|
||||
|
||||
@ -221,6 +221,12 @@ namespace ts {
|
||||
durationMs: number;
|
||||
}
|
||||
|
||||
export enum LanguageServiceMode {
|
||||
Semantic,
|
||||
ApproximateSemanticOnly,
|
||||
SyntaxOnly,
|
||||
}
|
||||
|
||||
//
|
||||
// Public interface of the host of a language service instance.
|
||||
//
|
||||
|
||||
@ -145,6 +145,7 @@
|
||||
"unittests/tscWatch/watchApi.ts",
|
||||
"unittests/tscWatch/watchEnvironment.ts",
|
||||
"unittests/tsserver/applyChangesToOpenFiles.ts",
|
||||
"unittests/tsserver/approximateSemanticOnlyServer.ts",
|
||||
"unittests/tsserver/autoImportProvider.ts",
|
||||
"unittests/tsserver/cachingFileSystemInformation.ts",
|
||||
"unittests/tsserver/cancellationToken.ts",
|
||||
|
||||
@ -0,0 +1,217 @@
|
||||
namespace ts.projectSystem {
|
||||
describe("unittests:: tsserver:: Semantic operations on Approximate Semantic only server", () => {
|
||||
function setup() {
|
||||
const file1: File = {
|
||||
path: `${tscWatch.projectRoot}/a.ts`,
|
||||
content: `import { y, cc } from "./b";
|
||||
import { something } from "something";
|
||||
class c { prop = "hello"; foo() { return this.prop; } }`
|
||||
};
|
||||
const file2: File = {
|
||||
path: `${tscWatch.projectRoot}/b.ts`,
|
||||
content: `export { cc } from "./c";
|
||||
import { something } from "something";
|
||||
export const y = 10;`
|
||||
};
|
||||
const file3: File = {
|
||||
path: `${tscWatch.projectRoot}/c.ts`,
|
||||
content: `export const cc = 10;`
|
||||
};
|
||||
const something: File = {
|
||||
path: `${tscWatch.projectRoot}/node_modules/something/index.d.ts`,
|
||||
content: "export const something = 10;"
|
||||
};
|
||||
const configFile: File = {
|
||||
path: `${tscWatch.projectRoot}/tsconfig.json`,
|
||||
content: "{}"
|
||||
};
|
||||
const host = createServerHost([file1, file2, file3, something, libFile, configFile]);
|
||||
const session = createSession(host, { serverMode: LanguageServiceMode.ApproximateSemanticOnly, useSingleInferredProject: true });
|
||||
return { host, session, file1, file2, file3, something, configFile };
|
||||
}
|
||||
|
||||
it("open files are added to inferred project even if config file is present and semantic operations succeed", () => {
|
||||
const { host, session, file1, file2, file3, something } = setup();
|
||||
const service = session.getProjectService();
|
||||
openFilesForSession([file1], session);
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
const project = service.inferredProjects[0];
|
||||
checkProjectActualFiles(project, [libFile.path, file1.path, file2.path]); // Relative import from open file is resolves but not non relative
|
||||
verifyCompletions();
|
||||
verifyGoToDefToB();
|
||||
|
||||
openFilesForSession([file2], session);
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
checkProjectActualFiles(project, [libFile.path, file1.path, file2.path, file3.path]);
|
||||
verifyCompletions();
|
||||
verifyGoToDefToB();
|
||||
verifyGoToDefToC();
|
||||
|
||||
openFilesForSession([file3], session);
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
checkProjectActualFiles(project, [libFile.path, file1.path, file2.path, file3.path]);
|
||||
|
||||
openFilesForSession([something], session);
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
checkProjectActualFiles(project, [libFile.path, file1.path, file2.path, file3.path, something.path]);
|
||||
|
||||
// Close open files and verify resolutions
|
||||
closeFilesForSession([file3], session);
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
checkProjectActualFiles(project, [libFile.path, file1.path, file2.path, file3.path, something.path]);
|
||||
|
||||
closeFilesForSession([file2], session);
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
checkProjectActualFiles(project, [libFile.path, file1.path, file2.path, file3.path, something.path]);
|
||||
|
||||
function verifyCompletions() {
|
||||
assert.isTrue(project.languageServiceEnabled);
|
||||
checkWatchedFiles(host, emptyArray);
|
||||
checkWatchedDirectories(host, emptyArray, /*recursive*/ true);
|
||||
checkWatchedDirectories(host, emptyArray, /*recursive*/ false);
|
||||
const response = session.executeCommandSeq<protocol.CompletionsRequest>({
|
||||
command: protocol.CommandTypes.Completions,
|
||||
arguments: protocolFileLocationFromSubstring(file1, "prop", { index: 1 })
|
||||
}).response as protocol.CompletionEntry[];
|
||||
assert.deepEqual(response, [
|
||||
completionEntry("foo", ScriptElementKind.memberFunctionElement),
|
||||
completionEntry("prop", ScriptElementKind.memberVariableElement),
|
||||
]);
|
||||
}
|
||||
|
||||
function completionEntry(name: string, kind: ScriptElementKind): protocol.CompletionEntry {
|
||||
return {
|
||||
name,
|
||||
kind,
|
||||
kindModifiers: "",
|
||||
sortText: Completions.SortText.LocationPriority,
|
||||
hasAction: undefined,
|
||||
insertText: undefined,
|
||||
isPackageJsonImport: undefined,
|
||||
isRecommended: undefined,
|
||||
replacementSpan: undefined,
|
||||
source: undefined
|
||||
};
|
||||
}
|
||||
|
||||
function verifyGoToDefToB() {
|
||||
const response = session.executeCommandSeq<protocol.DefinitionAndBoundSpanRequest>({
|
||||
command: protocol.CommandTypes.DefinitionAndBoundSpan,
|
||||
arguments: protocolFileLocationFromSubstring(file1, "y")
|
||||
}).response as protocol.DefinitionInfoAndBoundSpan;
|
||||
assert.deepEqual(response, {
|
||||
definitions: [{
|
||||
file: file2.path,
|
||||
...protocolTextSpanWithContextFromSubstring({ fileText: file2.content, text: "y", contextText: "export const y = 10;" })
|
||||
}],
|
||||
textSpan: protocolTextSpanWithContextFromSubstring({ fileText: file1.content, text: "y" })
|
||||
});
|
||||
}
|
||||
|
||||
function verifyGoToDefToC() {
|
||||
const response = session.executeCommandSeq<protocol.DefinitionAndBoundSpanRequest>({
|
||||
command: protocol.CommandTypes.DefinitionAndBoundSpan,
|
||||
arguments: protocolFileLocationFromSubstring(file1, "cc")
|
||||
}).response as protocol.DefinitionInfoAndBoundSpan;
|
||||
assert.deepEqual(response, {
|
||||
definitions: [{
|
||||
file: file3.path,
|
||||
...protocolTextSpanWithContextFromSubstring({ fileText: file3.content, text: "cc", contextText: "export const cc = 10;" })
|
||||
}],
|
||||
textSpan: protocolTextSpanWithContextFromSubstring({ fileText: file1.content, text: "cc" })
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it("throws on unsupported commands", () => {
|
||||
const { session, file1 } = setup();
|
||||
const service = session.getProjectService();
|
||||
openFilesForSession([file1], session);
|
||||
let hasException = false;
|
||||
const request: protocol.SemanticDiagnosticsSyncRequest = {
|
||||
type: "request",
|
||||
seq: 1,
|
||||
command: protocol.CommandTypes.SemanticDiagnosticsSync,
|
||||
arguments: { file: file1.path }
|
||||
};
|
||||
try {
|
||||
session.executeCommand(request);
|
||||
}
|
||||
catch (e) {
|
||||
assert.equal(e.message, `Request: semanticDiagnosticsSync not allowed on approximate semantic only server`);
|
||||
hasException = true;
|
||||
}
|
||||
assert.isTrue(hasException);
|
||||
|
||||
hasException = false;
|
||||
const project = service.inferredProjects[0];
|
||||
try {
|
||||
project.getLanguageService().getSemanticDiagnostics(file1.path);
|
||||
}
|
||||
catch (e) {
|
||||
assert.equal(e.message, `LanguageService Operation: getSemanticDiagnostics not allowed on approximate semantic only server`);
|
||||
hasException = true;
|
||||
}
|
||||
assert.isTrue(hasException);
|
||||
});
|
||||
|
||||
it("should not include auto type reference directives", () => {
|
||||
const { host, session, file1, file2 } = setup();
|
||||
const atTypes: File = {
|
||||
path: `/node_modules/@types/somemodule/index.d.ts`,
|
||||
content: "export const something = 10;"
|
||||
};
|
||||
host.ensureFileOrFolder(atTypes);
|
||||
const service = session.getProjectService();
|
||||
openFilesForSession([file1], session);
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
const project = service.inferredProjects[0];
|
||||
checkProjectActualFiles(project, [libFile.path, file1.path, file2.path]); // Should not contain atTypes
|
||||
});
|
||||
|
||||
it("should not include referenced files from unopened files", () => {
|
||||
const file1: File = {
|
||||
path: `${tscWatch.projectRoot}/a.ts`,
|
||||
content: `///<reference path="b.ts"/>
|
||||
///<reference path="${tscWatch.projectRoot}/node_modules/something/index.d.ts"/>
|
||||
function fooA() { }`
|
||||
};
|
||||
const file2: File = {
|
||||
path: `${tscWatch.projectRoot}/b.ts`,
|
||||
content: `///<reference path="./c.ts"/>
|
||||
///<reference path="${tscWatch.projectRoot}/node_modules/something/index.d.ts"/>
|
||||
function fooB() { }`
|
||||
};
|
||||
const file3: File = {
|
||||
path: `${tscWatch.projectRoot}/c.ts`,
|
||||
content: `function fooC() { }`
|
||||
};
|
||||
const something: File = {
|
||||
path: `${tscWatch.projectRoot}/node_modules/something/index.d.ts`,
|
||||
content: "function something() {}"
|
||||
};
|
||||
const configFile: File = {
|
||||
path: `${tscWatch.projectRoot}/tsconfig.json`,
|
||||
content: "{}"
|
||||
};
|
||||
const host = createServerHost([file1, file2, file3, something, libFile, configFile]);
|
||||
const session = createSession(host, { serverMode: LanguageServiceMode.ApproximateSemanticOnly, useSingleInferredProject: true });
|
||||
const service = session.getProjectService();
|
||||
openFilesForSession([file1], session);
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
const project = service.inferredProjects[0];
|
||||
checkProjectActualFiles(project, [libFile.path, file1.path, file2.path, something.path]); // Should not contains c
|
||||
|
||||
openFilesForSession([file2], session);
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
assert.isTrue(project.dirty);
|
||||
project.updateGraph();
|
||||
checkProjectActualFiles(project, [libFile.path, file1.path, file2.path, file3.path, something.path]);
|
||||
|
||||
closeFilesForSession([file2], session);
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
assert.isFalse(project.dirty);
|
||||
checkProjectActualFiles(project, [libFile.path, file1.path, file2.path, file3.path, something.path]);
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -86,7 +86,7 @@ namespace ts.projectSystem {
|
||||
const proj = projectService.inferredProjects[0];
|
||||
assert.isDefined(proj);
|
||||
|
||||
assert.isTrue(proj.languageServiceEnabled);
|
||||
assert.isFalse(proj.languageServiceEnabled);
|
||||
});
|
||||
|
||||
it("project settings for inferred projects", () => {
|
||||
|
||||
@ -30,95 +30,74 @@ import { something } from "something";
|
||||
return { host, session, file1, file2, file3, something, configFile };
|
||||
}
|
||||
|
||||
it("open files are added to inferred project even if config file is present and semantic operations succeed", () => {
|
||||
function verifySessionException<T extends server.protocol.Request>(session: TestSession, request: Partial<T>) {
|
||||
let hasException = false;
|
||||
try {
|
||||
session.executeCommandSeq(request);
|
||||
}
|
||||
catch (e) {
|
||||
assert.equal(e.message, `Request: ${request.command} not allowed on syntax only server`);
|
||||
hasException = true;
|
||||
}
|
||||
assert.isTrue(hasException);
|
||||
}
|
||||
|
||||
it("open files are added to inferred project even if config file is present and semantic operations fail", () => {
|
||||
const { host, session, file1, file2, file3, something } = setup();
|
||||
const service = session.getProjectService();
|
||||
openFilesForSession([file1], session);
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
const project = service.inferredProjects[0];
|
||||
checkProjectActualFiles(project, [libFile.path, file1.path, file2.path]); // Relative import from open file is resolves but not non relative
|
||||
checkProjectActualFiles(project, emptyArray);
|
||||
verifyCompletions();
|
||||
verifyGoToDefToB();
|
||||
|
||||
openFilesForSession([file2], session);
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
checkProjectActualFiles(project, [libFile.path, file1.path, file2.path, file3.path]);
|
||||
checkProjectActualFiles(project, emptyArray);
|
||||
verifyCompletions();
|
||||
verifyGoToDefToB();
|
||||
verifyGoToDefToC();
|
||||
|
||||
openFilesForSession([file3], session);
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
checkProjectActualFiles(project, [libFile.path, file1.path, file2.path, file3.path]);
|
||||
checkProjectActualFiles(project, emptyArray);
|
||||
|
||||
openFilesForSession([something], session);
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
checkProjectActualFiles(project, [libFile.path, file1.path, file2.path, file3.path, something.path]);
|
||||
checkProjectActualFiles(project, emptyArray);
|
||||
|
||||
// Close open files and verify resolutions
|
||||
closeFilesForSession([file3], session);
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
checkProjectActualFiles(project, [libFile.path, file1.path, file2.path, file3.path, something.path]);
|
||||
checkProjectActualFiles(project, emptyArray);
|
||||
|
||||
closeFilesForSession([file2], session);
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
checkProjectActualFiles(project, [libFile.path, file1.path, file2.path, file3.path, something.path]);
|
||||
checkProjectActualFiles(project, emptyArray);
|
||||
|
||||
function verifyCompletions() {
|
||||
assert.isTrue(project.languageServiceEnabled);
|
||||
assert.isFalse(project.languageServiceEnabled);
|
||||
checkWatchedFiles(host, emptyArray);
|
||||
checkWatchedDirectories(host, emptyArray, /*recursive*/ true);
|
||||
checkWatchedDirectories(host, emptyArray, /*recursive*/ false);
|
||||
const response = session.executeCommandSeq<protocol.CompletionsRequest>({
|
||||
verifySessionException<protocol.CompletionsRequest>(session, {
|
||||
command: protocol.CommandTypes.Completions,
|
||||
arguments: protocolFileLocationFromSubstring(file1, "prop", { index: 1 })
|
||||
}).response as protocol.CompletionEntry[];
|
||||
assert.deepEqual(response, [
|
||||
completionEntry("foo", ScriptElementKind.memberFunctionElement),
|
||||
completionEntry("prop", ScriptElementKind.memberVariableElement),
|
||||
]);
|
||||
}
|
||||
|
||||
function completionEntry(name: string, kind: ScriptElementKind): protocol.CompletionEntry {
|
||||
return {
|
||||
name,
|
||||
kind,
|
||||
kindModifiers: "",
|
||||
sortText: Completions.SortText.LocationPriority,
|
||||
hasAction: undefined,
|
||||
insertText: undefined,
|
||||
isPackageJsonImport: undefined,
|
||||
isRecommended: undefined,
|
||||
replacementSpan: undefined,
|
||||
source: undefined
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function verifyGoToDefToB() {
|
||||
const response = session.executeCommandSeq<protocol.DefinitionAndBoundSpanRequest>({
|
||||
verifySessionException<protocol.DefinitionAndBoundSpanRequest>(session, {
|
||||
command: protocol.CommandTypes.DefinitionAndBoundSpan,
|
||||
arguments: protocolFileLocationFromSubstring(file1, "y")
|
||||
}).response as protocol.DefinitionInfoAndBoundSpan;
|
||||
assert.deepEqual(response, {
|
||||
definitions: [{
|
||||
file: file2.path,
|
||||
...protocolTextSpanWithContextFromSubstring({ fileText: file2.content, text: "y", contextText: "export const y = 10;" })
|
||||
}],
|
||||
textSpan: protocolTextSpanWithContextFromSubstring({ fileText: file1.content, text: "y" })
|
||||
});
|
||||
}
|
||||
|
||||
function verifyGoToDefToC() {
|
||||
const response = session.executeCommandSeq<protocol.DefinitionAndBoundSpanRequest>({
|
||||
verifySessionException<protocol.DefinitionAndBoundSpanRequest>(session, {
|
||||
command: protocol.CommandTypes.DefinitionAndBoundSpan,
|
||||
arguments: protocolFileLocationFromSubstring(file1, "cc")
|
||||
}).response as protocol.DefinitionInfoAndBoundSpan;
|
||||
assert.deepEqual(response, {
|
||||
definitions: [{
|
||||
file: file3.path,
|
||||
...protocolTextSpanWithContextFromSubstring({ fileText: file3.content, text: "cc", contextText: "export const cc = 10;" })
|
||||
}],
|
||||
textSpan: protocolTextSpanWithContextFromSubstring({ fileText: file1.content, text: "cc" })
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -127,36 +106,27 @@ import { something } from "something";
|
||||
const { session, file1 } = setup();
|
||||
const service = session.getProjectService();
|
||||
openFilesForSession([file1], session);
|
||||
let hasException = false;
|
||||
const request: protocol.SemanticDiagnosticsSyncRequest = {
|
||||
verifySessionException<protocol.SemanticDiagnosticsSyncRequest>(session, {
|
||||
type: "request",
|
||||
seq: 1,
|
||||
command: protocol.CommandTypes.SemanticDiagnosticsSync,
|
||||
arguments: { file: file1.path }
|
||||
};
|
||||
try {
|
||||
session.executeCommand(request);
|
||||
}
|
||||
catch (e) {
|
||||
assert.equal(e.message, `Request: semanticDiagnosticsSync not allowed on syntaxServer`);
|
||||
hasException = true;
|
||||
}
|
||||
assert.isTrue(hasException);
|
||||
});
|
||||
|
||||
hasException = false;
|
||||
let hasException = false;
|
||||
const project = service.inferredProjects[0];
|
||||
try {
|
||||
project.getLanguageService().getSemanticDiagnostics(file1.path);
|
||||
}
|
||||
catch (e) {
|
||||
assert.equal(e.message, `LanguageService Operation: getSemanticDiagnostics not allowed on syntaxServer`);
|
||||
assert.equal(e.message, `LanguageService Operation: getSemanticDiagnostics not allowed on syntax only server`);
|
||||
hasException = true;
|
||||
}
|
||||
assert.isTrue(hasException);
|
||||
});
|
||||
|
||||
it("should not include auto type reference directives", () => {
|
||||
const { host, session, file1, file2 } = setup();
|
||||
const { host, session, file1 } = setup();
|
||||
const atTypes: File = {
|
||||
path: `/node_modules/@types/somemodule/index.d.ts`,
|
||||
content: "export const something = 10;"
|
||||
@ -166,7 +136,7 @@ import { something } from "something";
|
||||
openFilesForSession([file1], session);
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
const project = service.inferredProjects[0];
|
||||
checkProjectActualFiles(project, [libFile.path, file1.path, file2.path]); // Should not contain atTypes
|
||||
checkProjectActualFiles(project, emptyArray); // Should not contain atTypes
|
||||
});
|
||||
|
||||
it("should not include referenced files from unopened files", () => {
|
||||
@ -200,18 +170,18 @@ function fooB() { }`
|
||||
openFilesForSession([file1], session);
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
const project = service.inferredProjects[0];
|
||||
checkProjectActualFiles(project, [libFile.path, file1.path, file2.path, something.path]); // Should not contains c
|
||||
checkProjectActualFiles(project, emptyArray);
|
||||
|
||||
openFilesForSession([file2], session);
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
assert.isTrue(project.dirty);
|
||||
assert.isFalse(project.dirty);
|
||||
project.updateGraph();
|
||||
checkProjectActualFiles(project, [libFile.path, file1.path, file2.path, file3.path, something.path]);
|
||||
checkProjectActualFiles(project, emptyArray);
|
||||
|
||||
closeFilesForSession([file2], session);
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
assert.isFalse(project.dirty);
|
||||
checkProjectActualFiles(project, [libFile.path, file1.path, file2.path, file3.path, something.path]);
|
||||
assert.isTrue(project.dirty);
|
||||
checkProjectActualFiles(project, emptyArray);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -516,6 +516,7 @@ namespace ts.server {
|
||||
canUseEvents: true,
|
||||
suppressDiagnosticEvents,
|
||||
syntaxOnly,
|
||||
serverMode,
|
||||
noGetErrOnBackgroundUpdate,
|
||||
globalPlugins,
|
||||
pluginProbeLocations,
|
||||
@ -948,6 +949,26 @@ namespace ts.server {
|
||||
return arg.split(",").filter(name => name !== "");
|
||||
}
|
||||
|
||||
let unknownServerMode: string | undefined;
|
||||
function parseServerMode(): LanguageServiceMode | undefined {
|
||||
const mode = findArgument("--serverMode");
|
||||
if (mode === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
switch (mode.toLowerCase()) {
|
||||
case "semantic":
|
||||
return LanguageServiceMode.Semantic;
|
||||
case "approximatesemanticonly":
|
||||
return LanguageServiceMode.ApproximateSemanticOnly;
|
||||
case "syntaxonly":
|
||||
return LanguageServiceMode.SyntaxOnly;
|
||||
default:
|
||||
unknownServerMode = mode;
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
const globalPlugins = parseStringArray("--globalPlugins");
|
||||
const pluginProbeLocations = parseStringArray("--pluginProbeLocations");
|
||||
const allowLocalPluginLoads = hasArgument("--allowLocalPluginLoads");
|
||||
@ -957,6 +978,7 @@ namespace ts.server {
|
||||
const disableAutomaticTypingAcquisition = hasArgument("--disableAutomaticTypingAcquisition");
|
||||
const suppressDiagnosticEvents = hasArgument("--suppressDiagnosticEvents");
|
||||
const syntaxOnly = hasArgument("--syntaxOnly");
|
||||
const serverMode = parseServerMode();
|
||||
const telemetryEnabled = hasArgument(Arguments.EnableTelemetry);
|
||||
const noGetErrOnBackgroundUpdate = hasArgument("--noGetErrOnBackgroundUpdate");
|
||||
|
||||
@ -964,6 +986,7 @@ namespace ts.server {
|
||||
logger.info(`Version: ${version}`);
|
||||
logger.info(`Arguments: ${process.argv.join(" ")}`);
|
||||
logger.info(`Platform: ${os.platform()} NodeVersion: ${nodeVersion} CaseSensitive: ${sys.useCaseSensitiveFileNames}`);
|
||||
logger.info(`ServerMode: ${serverMode} syntaxOnly: ${syntaxOnly} hasUnknownServerMode: ${unknownServerMode}`);
|
||||
|
||||
const ioSession = new IOSession();
|
||||
process.on("uncaughtException", err => {
|
||||
|
||||
@ -5314,6 +5314,11 @@ declare namespace ts {
|
||||
kind: "UpdateGraph" | "CreatePackageJsonAutoImportProvider";
|
||||
durationMs: number;
|
||||
}
|
||||
enum LanguageServiceMode {
|
||||
Semantic = 0,
|
||||
ApproximateSemanticOnly = 1,
|
||||
SyntaxOnly = 2
|
||||
}
|
||||
interface LanguageServiceHost extends GetEffectiveTypeRootsHost {
|
||||
getCompilationSettings(): CompilerOptions;
|
||||
getNewLine?(): string;
|
||||
@ -6325,7 +6330,7 @@ declare namespace ts {
|
||||
function getSupportedCodeFixes(): string[];
|
||||
function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTarget: ScriptTarget, version: string, setNodeParents: boolean, scriptKind?: ScriptKind): SourceFile;
|
||||
function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange | undefined, aggressiveChecks?: boolean): SourceFile;
|
||||
function createLanguageService(host: LanguageServiceHost, documentRegistry?: DocumentRegistry, syntaxOnly?: boolean): LanguageService;
|
||||
function createLanguageService(host: LanguageServiceHost, documentRegistry?: DocumentRegistry, syntaxOnlyOrLanguageServiceMode?: boolean | LanguageServiceMode): LanguageService;
|
||||
/**
|
||||
* Get the path of the default library files (lib.d.ts) as distributed with the typescript
|
||||
* node package.
|
||||
@ -9483,7 +9488,9 @@ declare namespace ts.server {
|
||||
pluginProbeLocations?: readonly string[];
|
||||
allowLocalPluginLoads?: boolean;
|
||||
typesMapLocation?: string;
|
||||
/** @deprecated use serverMode instead */
|
||||
syntaxOnly?: boolean;
|
||||
serverMode?: LanguageServiceMode;
|
||||
}
|
||||
export class ProjectService {
|
||||
private readonly scriptInfoInNodeModulesWatchers;
|
||||
@ -9555,7 +9562,9 @@ declare namespace ts.server {
|
||||
readonly allowLocalPluginLoads: boolean;
|
||||
private currentPluginConfigOverrides;
|
||||
readonly typesMapLocation: string | undefined;
|
||||
readonly syntaxOnly?: boolean;
|
||||
/** @deprecated use serverMode instead */
|
||||
readonly syntaxOnly: boolean;
|
||||
readonly serverMode: LanguageServiceMode;
|
||||
/** Tracks projects that we have already sent telemetry for. */
|
||||
private readonly seenProjects;
|
||||
private performanceEventHandler?;
|
||||
@ -9773,7 +9782,9 @@ declare namespace ts.server {
|
||||
eventHandler?: ProjectServiceEventHandler;
|
||||
/** Has no effect if eventHandler is also specified. */
|
||||
suppressDiagnosticEvents?: boolean;
|
||||
/** @deprecated use serverMode instead */
|
||||
syntaxOnly?: boolean;
|
||||
serverMode?: LanguageServiceMode;
|
||||
throttleWaitMilliseconds?: number;
|
||||
noGetErrOnBackgroundUpdate?: boolean;
|
||||
globalPlugins?: readonly string[];
|
||||
|
||||
@ -5314,6 +5314,11 @@ declare namespace ts {
|
||||
kind: "UpdateGraph" | "CreatePackageJsonAutoImportProvider";
|
||||
durationMs: number;
|
||||
}
|
||||
enum LanguageServiceMode {
|
||||
Semantic = 0,
|
||||
ApproximateSemanticOnly = 1,
|
||||
SyntaxOnly = 2
|
||||
}
|
||||
interface LanguageServiceHost extends GetEffectiveTypeRootsHost {
|
||||
getCompilationSettings(): CompilerOptions;
|
||||
getNewLine?(): string;
|
||||
@ -6325,7 +6330,7 @@ declare namespace ts {
|
||||
function getSupportedCodeFixes(): string[];
|
||||
function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTarget: ScriptTarget, version: string, setNodeParents: boolean, scriptKind?: ScriptKind): SourceFile;
|
||||
function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange | undefined, aggressiveChecks?: boolean): SourceFile;
|
||||
function createLanguageService(host: LanguageServiceHost, documentRegistry?: DocumentRegistry, syntaxOnly?: boolean): LanguageService;
|
||||
function createLanguageService(host: LanguageServiceHost, documentRegistry?: DocumentRegistry, syntaxOnlyOrLanguageServiceMode?: boolean | LanguageServiceMode): LanguageService;
|
||||
/**
|
||||
* Get the path of the default library files (lib.d.ts) as distributed with the typescript
|
||||
* node package.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user