From 8fe0d2d6df3e3e15be7aa7ecf617bf2b3aede192 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Tue, 23 Aug 2016 16:18:48 -0700 Subject: [PATCH] remove merge artefacts --- src/server/editorServices.ts.orig | 1203 ----------------------- src/server/project.ts.orig | 681 ------------- src/server/protocol.d.ts.orig | 1488 ----------------------------- 3 files changed, 3372 deletions(-) delete mode 100644 src/server/editorServices.ts.orig delete mode 100644 src/server/project.ts.orig delete mode 100644 src/server/protocol.d.ts.orig diff --git a/src/server/editorServices.ts.orig b/src/server/editorServices.ts.orig deleted file mode 100644 index b100cf21261..00000000000 --- a/src/server/editorServices.ts.orig +++ /dev/null @@ -1,1203 +0,0 @@ -/// -/// -/// -/// -/// -/// -/// -/// -/// - -namespace ts.server { - export const maxProgramSizeForNonTsFiles = 20 * 1024 * 1024; - - /** - * This helper function processes a list of projects and return the concatenated, sortd and deduplicated output of processing each project. - */ - export function combineProjectOutput(projects: Project[], action: (project: Project) => T[], comparer?: (a: T, b: T) => number, areEqual?: (a: T, b: T) => boolean) { - const result = projects.reduce((previous, current) => concatenate(previous, action(current)), []).sort(comparer); - return projects.length > 1 ? deduplicate(result, areEqual) : result; - } - - export interface ProjectServiceEventHandler { - (eventName: string, project: Project, fileName: NormalizedPath): void; - } - - export interface HostConfiguration { - formatCodeOptions: FormatCodeSettings; - hostInfo: string; - } - - interface ConfigFileConversionResult { - success: boolean; - errors?: Diagnostic[]; - - projectOptions?: ProjectOptions; - } - - interface OpenConfigFileResult { - success: boolean; - errors?: Diagnostic[]; - - project?: ConfiguredProject; - } - - export interface OpenConfiguredProjectResult { - configFileName?: string; - configFileErrors?: Diagnostic[]; - } - - interface FilePropertyReader { - getFileName(f: T): string; - getScriptKind(f: T): ScriptKind; - hasMixedContent(f: T): boolean; - } - - const fileNamePropertyReader: FilePropertyReader = { - getFileName: x => x, - getScriptKind: _ => undefined, - hasMixedContent: _ => false - }; - - const externalFilePropertyReader: FilePropertyReader = { - getFileName: x => x.fileName, - getScriptKind: x => x.scriptKind, - hasMixedContent: x => x.hasMixedContent - }; - - function findProjectByName(projectName: string, projects: T[]): T { - for (const proj of projects) { - if (proj.getProjectName() === projectName) { - return proj; - } - } - } - - /** - * TODO: enforce invariants: - * - script info can be never migrate to state - root file in inferred project, this is only a starting point - * - if script info has more that one containing projects - it is not a root file in inferred project because: - * - references in inferred project supercede the root part - * - root/reference in non-inferred project beats root in inferred project - */ - function isRootFileInInferredProject(info: ScriptInfo): boolean { - if (info.containingProjects.length === 0) { - return false; - } - return info.containingProjects[0].projectKind === ProjectKind.Inferred && info.containingProjects[0].isRoot(info); - } - - class DirectoryWatchers { - /** - * a path to directory watcher map that detects added tsconfig files - **/ - private readonly directoryWatchersForTsconfig: Map = createMap(); - /** - * count of how many projects are using the directory watcher. - * If the number becomes 0 for a watcher, then we should close it. - **/ - private readonly directoryWatchersRefCount: Map = createMap(); - - constructor(private readonly projectService: ProjectService) { - } - - stopWatchingDirectory(directory: string) { - // if the ref count for this directory watcher drops to 0, it's time to close it - this.directoryWatchersRefCount[directory]--; - if (this.directoryWatchersRefCount[directory] === 0) { - this.projectService.logger.info(`Close directory watcher for: ${directory}`); - this.directoryWatchersForTsconfig[directory].close(); - delete this.directoryWatchersForTsconfig[directory]; - } - } - - startWatchingContainingDirectoriesForFile(fileName: string, project: InferredProject, callback: (fileName: string) => void) { - let currentPath = getDirectoryPath(fileName); - let parentPath = getDirectoryPath(currentPath); - while (currentPath != parentPath) { - if (!this.directoryWatchersForTsconfig[currentPath]) { - this.projectService.logger.info(`Add watcher for: ${currentPath}`); - this.directoryWatchersForTsconfig[currentPath] = this.projectService.host.watchDirectory(currentPath, callback); - this.directoryWatchersRefCount[currentPath] = 1; - } - else { - this.directoryWatchersRefCount[currentPath] += 1; - } - project.directoriesWatchedForTsconfig.push(currentPath); - currentPath = parentPath; - parentPath = getDirectoryPath(parentPath); - } - } - } - - export class ProjectService { - - public readonly typingsCache: TypingsCache; - - private readonly documentRegistry: DocumentRegistry; - - /** - * Container of all known scripts - */ - private readonly filenameToScriptInfo = createFileMap(); - /** - * maps external project file name to list of config files that were the part of this project - */ - private readonly externalProjectToConfiguredProjectMap: Map = createMap(); - - /** - * external projects (configuration and list of root files is not controlled by tsserver) - */ - readonly externalProjects: ExternalProject[] = []; - /** - * projects built from openFileRoots - **/ - readonly inferredProjects: InferredProject[] = []; - /** - * projects specified by a tsconfig.json file - **/ - readonly configuredProjects: ConfiguredProject[] = []; - /** - * list of open files - */ - readonly openFiles: ScriptInfo[] = []; - - private compilerOptionsForInferredProjects: CompilerOptions; - private readonly directoryWatchers: DirectoryWatchers; - private readonly throttledOperations: ThrottledOperations; - - private readonly hostConfiguration: HostConfiguration; - - private changedFiles: ScriptInfo[]; - - private toCanonicalFileName: (f: string) => string; - - constructor(public readonly host: ServerHost, - public readonly logger: Logger, - public readonly cancellationToken: HostCancellationToken, - private readonly useSingleInferredProject: boolean, - private typingsInstaller: ITypingsInstaller, - private readonly eventHandler?: ProjectServiceEventHandler) { - - this.toCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames); - this.directoryWatchers = new DirectoryWatchers(this); - this.throttledOperations = new ThrottledOperations(host); - - const installer = typingsInstaller || nullTypingsInstaller; - installer.attach(this); - - this.typingsCache = new TypingsCache(installer); - - // ts.disableIncrementalParsing = true; - - this.hostConfiguration = { - formatCodeOptions: getDefaultFormatCodeSettings(this.host), - hostInfo: "Unknown host" - }; - - this.documentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames, host.getCurrentDirectory()); - } - - getChangedFiles_TestOnly() { - return this.changedFiles; - } - - ensureInferredProjectsUpToDate_TestOnly() { - this.ensureInferredProjectsUpToDate(); - } - - updateTypingsForProject(response: SetTypings | InvalidateCachedTypings): void { - const project = this.findProject(response.projectName); - if (!project) { - return; - } - switch (response.kind) { - case "set": - this.typingsCache.updateTypingsForProject(response.projectName, response.compilerOptions, response.typingOptions, response.typings); - project.updateGraph(); - break; - case "invalidate": - this.typingsCache.invalidateCachedTypingsForProject(project); - break; - } - } - - setCompilerOptionsForInferredProjects(compilerOptions: CompilerOptions): void { - this.compilerOptionsForInferredProjects = compilerOptions; - for (const proj of this.inferredProjects) { - proj.setCompilerOptions(compilerOptions); - } - this.updateProjectGraphs(this.inferredProjects); - } - - stopWatchingDirectory(directory: string) { - this.directoryWatchers.stopWatchingDirectory(directory); - } - - findProject(projectName: string): Project { - if (projectName === undefined) { - return undefined; - } - if (isInferredProjectName(projectName)) { - this.ensureInferredProjectsUpToDate(); - return findProjectByName(projectName, this.inferredProjects); - } - return this.findExternalProjectByProjectName(projectName) || this.findConfiguredProjectByProjectName(toNormalizedPath(projectName)); - } - - getDefaultProjectForFile(fileName: NormalizedPath, refreshInferredProjects: boolean) { - if (refreshInferredProjects) { - this.ensureInferredProjectsUpToDate(); - } - const scriptInfo = this.getScriptInfoForNormalizedPath(fileName); - return scriptInfo && scriptInfo.getDefaultProject(); - } - - private ensureInferredProjectsUpToDate() { - if (this.changedFiles) { - let projectsToUpdate: Project[]; - if (this.changedFiles.length === 1) { - // simpliest case - no allocations - projectsToUpdate = this.changedFiles[0].containingProjects; - } - else { - projectsToUpdate = []; - for (const f of this.changedFiles) { - projectsToUpdate = projectsToUpdate.concat(f.containingProjects); - } - } - this.updateProjectGraphs(projectsToUpdate); - this.changedFiles = undefined; - } - } - - private findContainingExternalProject(fileName: NormalizedPath): ExternalProject { - for (const proj of this.externalProjects) { - if (proj.containsFile(fileName)) { - return proj; - } - } - return undefined; - } - - getFormatCodeOptions(file?: NormalizedPath) { - if (file) { - const info = this.getScriptInfoForNormalizedPath(file); - if (info) { - return info.formatCodeSettings; - } - } - return this.hostConfiguration.formatCodeOptions; - } - - private updateProjectGraphs(projects: Project[]) { - let shouldRefreshInferredProjects = false; - for (const p of projects) { - if (!p.updateGraph()) { - shouldRefreshInferredProjects = true; - } - } - if (shouldRefreshInferredProjects) { - this.refreshInferredProjects(); - } - } - - private onSourceFileChanged(fileName: NormalizedPath) { - const info = this.getScriptInfoForNormalizedPath(fileName); - if (!info) { - this.logger.info(`Error: got watch notification for unknown file: ${fileName}`); - } - - if (!this.host.fileExists(fileName)) { - // File was deleted - this.handleDeletedFile(info); - } - else { - if (info && (!info.isOpen)) { - // file has been changed which might affect the set of referenced files in projects that include - // this file and set of inferred projects - info.reloadFromFile(); - this.updateProjectGraphs(info.containingProjects); - } - } - } - - private handleDeletedFile(info: ScriptInfo) { - this.logger.info(`${info.fileName} deleted`); - - info.stopWatcher(); - - // TODO: handle isOpen = true case - - if (!info.isOpen) { - this.filenameToScriptInfo.remove(info.path); - - // capture list of projects since detachAllProjects will wipe out original list - const containingProjects = info.containingProjects.slice(); - info.detachAllProjects(); - - // update projects to make sure that set of referenced files is correct - this.updateProjectGraphs(containingProjects); - - if (!this.eventHandler) { - return; - } - - for (const openFile of this.openFiles) { - this.eventHandler("context", openFile.getDefaultProject(), openFile.fileName); - } - } - - this.printProjects(); - } - - /** - * This is the callback function when a watched directory has added or removed source code files. - * @param project the project that associates with this directory watcher - * @param fileName the absolute file name that changed in watched directory - */ - private onSourceFileInDirectoryChangedForConfiguredProject(project: ConfiguredProject, fileName: string) { - // If a change was made inside "folder/file", node will trigger the callback twice: - // one with the fileName being "folder/file", and the other one with "folder". - // We don't respond to the second one. - if (fileName && !ts.isSupportedSourceFileName(fileName, project.getCompilerOptions())) { - return; - } - - this.logger.info(`Detected source file changes: ${fileName}`); - this.throttledOperations.schedule( - project.configFileName, - /*delay*/250, - () => this.handleChangeInSourceFileForConfiguredProject(project)); - } - - private handleChangeInSourceFileForConfiguredProject(project: ConfiguredProject) { - const { projectOptions } = this.convertConfigFileContentToProjectOptions(project.configFileName); - - const newRootFiles = projectOptions.files.map((f => this.getCanonicalFileName(f))); - const currentRootFiles = project.getRootFiles().map((f => this.getCanonicalFileName(f))); - - // We check if the project file list has changed. If so, we update the project. - if (!arrayIsEqualTo(currentRootFiles.sort(), newRootFiles.sort())) { - // For configured projects, the change is made outside the tsconfig file, and - // it is not likely to affect the project for other files opened by the client. We can - // just update the current project. - this.updateConfiguredProject(project); - - // Call refreshInferredProjects to clean up inferred projects we may have - // created for the new files - this.refreshInferredProjects(); - } - } - - private onConfigChangedForConfiguredProject(project: ConfiguredProject) { - this.logger.info(`Config file changed: ${project.configFileName}`); - this.updateConfiguredProject(project); - this.refreshInferredProjects(); - } - - /** - * This is the callback function when a watched directory has an added tsconfig file. - */ - private onConfigFileAddedForInferredProject(fileName: string) { - // TODO: check directory separators - if (getBaseFileName(fileName) != "tsconfig.json") { - this.logger.info(`${fileName} is not tsconfig.json`); - return; - } - - this.logger.info(`Detected newly added tsconfig file: ${fileName}`); - this.reloadProjects(); - } - - private getCanonicalFileName(fileName: string) { - const name = this.host.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); - return normalizePath(name); - } - - private removeProject(project: Project) { - this.logger.info(`remove project: ${project.getRootFiles().toString()}`); - - project.close(); - - switch (project.projectKind) { - case ProjectKind.External: - removeItemFromSet(this.externalProjects, project); - break; - case ProjectKind.Configured: - removeItemFromSet(this.configuredProjects, project); - break; - case ProjectKind.Inferred: - removeItemFromSet(this.inferredProjects, project); - break; - } - } - - private assignScriptInfoToInferredProjectIfNecessary(info: ScriptInfo, addToListOfOpenFiles: boolean): void { - const externalProject = this.findContainingExternalProject(info.fileName); - if (externalProject) { - // file is already included in some external project - do nothing - if (addToListOfOpenFiles) { - this.openFiles.push(info); - } - return; - } - - let foundConfiguredProject = false; - for (const p of info.containingProjects) { - // file is the part of configured project - if (p.projectKind === ProjectKind.Configured) { - foundConfiguredProject = true; - if (addToListOfOpenFiles) { - ((p)).addOpenRef(); - } - } - } - if (foundConfiguredProject) { - if (addToListOfOpenFiles) { - this.openFiles.push(info); - } - return; - } - - if (info.containingProjects.length === 0) { - // create new inferred project p with the newly opened file as root - // or add root to existing inferred project if 'useOneInferredProject' is true - const inferredProject = this.createInferredProjectWithRootFileIfNecessary(info); - if (!this.useSingleInferredProject) { - // if useOneInferredProject is not set then try to fixup ownership of open files - // check 'defaultProject !== inferredProject' is necessary to handle cases - // when creation inferred project for some file has added other open files into this project (i.e. as referenced files) - // we definitely don't want to delete the project that was just created - for (const f of this.openFiles) { - if (f.containingProjects.length === 0) { - // this is orphaned file that we have not processed yet - skip it - continue; - } - const defaultProject = f.getDefaultProject(); - if (isRootFileInInferredProject(info) && defaultProject !== inferredProject && inferredProject.containsScriptInfo(f)) { - // open file used to be root in inferred project, - // this inferred project is different from the one we've just created for current file - // and new inferred project references this open file. - // We should delete old inferred project and attach open file to the new one - this.removeProject(defaultProject); - f.attachToProject(inferredProject); - } - } - } - } - - if (addToListOfOpenFiles) { - this.openFiles.push(info); - } - } - - /** - * Remove this file from the set of open, non-configured files. - * @param info The file that has been closed or newly configured - */ - private closeOpenFile(info: ScriptInfo): void { - // 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.reloadFromFile(); - - removeItemFromSet(this.openFiles, info); - info.isOpen = false; - - // collect all projects that should be removed - let projectsToRemove: Project[]; - for (const p of info.containingProjects) { - if (p.projectKind === ProjectKind.Configured) { - // last open file in configured project - close it - if ((p).deleteOpenRef() === 0) { - (projectsToRemove || (projectsToRemove = [])).push(p); - } - } - else if (p.projectKind === ProjectKind.Inferred && p.isRoot(info)) { - // open file in inferred project - (projectsToRemove || (projectsToRemove = [])).push(p); - } - } - if (projectsToRemove) { - for (const project of projectsToRemove) { - this.removeProject(project); - } - - let orphanFiles: ScriptInfo[]; - // for all open files - for (const f of this.openFiles) { - // collect orphanted files and try to re-add them as newly opened - if (f.containingProjects.length === 0) { - (orphanFiles || (orphanFiles = [])).push(f); - } - } - - // treat orphaned files as newly opened - if (orphanFiles) { - for (const f of orphanFiles) { - this.assignScriptInfoToInferredProjectIfNecessary(f, /*addToListOfOpenFiles*/ false); - } - } - } - if (info.containingProjects.length === 0) { - // if there are not projects that include this script info - delete it - this.filenameToScriptInfo.remove(info.path); - } - } - - /** - * This function tries to search for a tsconfig.json for the given file. If we found it, - * we first detect if there is already a configured project created for it: if so, we re-read - * the tsconfig file content and update the project; otherwise we create a new one. - */ - private openOrUpdateConfiguredProjectForFile(fileName: NormalizedPath): OpenConfiguredProjectResult { - const searchPath = getDirectoryPath(fileName); - this.logger.info(`Search path: ${searchPath}`); - - // check if this file is already included in one of external projects - const configFileName = this.findConfigFile(asNormalizedPath(searchPath)); - if (!configFileName) { - this.logger.info("No config files found."); - return {}; - } - - this.logger.info(`Config file name: ${configFileName}`); - - const project = this.findConfiguredProjectByProjectName(configFileName); - if (!project) { - const { success, errors } = this.openConfigFile(configFileName, fileName); - if (!success) { - return { configFileName, configFileErrors: errors }; - } - - // even if opening config file was successful, it could still - // contain errors that were tolerated. - this.logger.info(`Opened configuration file ${configFileName}`); - if (errors && errors.length > 0) { - return { configFileName, configFileErrors: errors }; - } - } - else { - this.updateConfiguredProject(project); - } - - return { configFileName }; - } - - // This is different from the method the compiler uses because - // the compiler can assume it will always start searching in the - // current directory (the directory in which tsc was invoked). - // The server must start searching from the directory containing - // the newly opened file. - private findConfigFile(searchPath: NormalizedPath): NormalizedPath { - while (true) { - const tsconfigFileName = asNormalizedPath(combinePaths(searchPath, "tsconfig.json")); - if (this.host.fileExists(tsconfigFileName)) { - return tsconfigFileName; - } - - const jsconfigFileName = asNormalizedPath(combinePaths(searchPath, "jsconfig.json")); - if (this.host.fileExists(jsconfigFileName)) { - return jsconfigFileName; - } - - const parentPath = asNormalizedPath(getDirectoryPath(searchPath)); - if (parentPath === searchPath) { - break; - } - searchPath = parentPath; - } - return undefined; - } - - private printProjects() { - if (!this.logger.hasLevel(LogLevel.verbose)) { - return; - } - - this.logger.startGroup(); - - let counter = 0; - counter = printProjects(this.logger, this.externalProjects, counter); - counter = printProjects(this.logger, this.configuredProjects, counter); - counter = printProjects(this.logger, this.inferredProjects, counter); - - this.logger.info("Open files: "); - for (const rootFile of this.openFiles) { - this.logger.info(rootFile.fileName); - } - - this.logger.endGroup(); - - function printProjects(logger: Logger, projects: Project[], counter: number) { - for (const project of projects) { - project.updateGraph(); - logger.info(`Project '${project.getProjectName()}' (${ProjectKind[project.projectKind]}) ${counter}`); - logger.info(project.filesToString()); - logger.info("-----------------------------------------------"); - counter++; - } - return counter; - } - } - - private findConfiguredProjectByProjectName(configFileName: NormalizedPath) { - return findProjectByName(configFileName, this.configuredProjects); - } - - private findExternalProjectByProjectName(projectFileName: string) { - return findProjectByName(projectFileName, this.externalProjects); - } - - private convertConfigFileContentToProjectOptions(configFilename: string): ConfigFileConversionResult { - configFilename = normalizePath(configFilename); - - const configObj = parseConfigFileTextToJson(configFilename, this.host.readFile(configFilename)); - if (configObj.error) { - return { success: false, errors: [configObj.error] }; - } - - const parsedCommandLine = parseJsonConfigFileContent( - configObj.config, - this.host, - getDirectoryPath(configFilename), - /*existingOptions*/ {}, - configFilename); - - Debug.assert(!!parsedCommandLine.fileNames); - - if (parsedCommandLine.errors && (parsedCommandLine.errors.length > 0)) { - return { success: false, errors: parsedCommandLine.errors }; - } - - if (parsedCommandLine.fileNames.length === 0) { - const error = createCompilerDiagnostic(Diagnostics.The_config_file_0_found_doesn_t_contain_any_source_files, configFilename); - return { success: false, errors: [error] }; - } - - const projectOptions: ProjectOptions = { - files: parsedCommandLine.fileNames, - compilerOptions: parsedCommandLine.options, - configHasFilesProperty: configObj.config["files"] !== undefined, - wildcardDirectories: createMap(parsedCommandLine.wildcardDirectories), - typingOptions: parsedCommandLine.typingOptions, - compileOnSave: parsedCommandLine.compileOnSave - }; - return { success: true, projectOptions }; - } - - private exceededTotalSizeLimitForNonTsFiles(options: CompilerOptions, fileNames: T[], propertyReader: FilePropertyReader) { - if (options && options.disableSizeLimit || !this.host.getFileSize) { - return false; - } - let totalNonTsFileSize = 0; - for (const f of fileNames) { - const fileName = propertyReader.getFileName(f); - if (hasTypeScriptFileExtension(fileName)) { - continue; - } - totalNonTsFileSize += this.host.getFileSize(fileName); - if (totalNonTsFileSize > maxProgramSizeForNonTsFiles) { - return true; - } - } - return false; - } - -<<<<<<< HEAD - private createAndAddExternalProject(projectFileName: string, files: protocol.ExternalFile[], options: protocol.ExternalProjectCompilerOptions, typingOptions: TypingOptions) { -======= - private createAndAddExternalProject(projectFileName: string, files: protocol.ExternalFile[], compilerOptions: CompilerOptions, typingOptions: TypingOptions) { ->>>>>>> d736db3b01a5f4f4215c17845deb3ae09cf28787 - const project = new ExternalProject( - projectFileName, - this, - this.documentRegistry, -<<<<<<< HEAD - options, - typingOptions, - /*languageServiceEnabled*/ !this.exceededTotalSizeLimitForNonTsFiles(options, files, externalFilePropertyReader), - !!options.compileOnSave); -======= - compilerOptions, - typingOptions, - /*languageServiceEnabled*/ !this.exceededTotalSizeLimitForNonTsFiles(compilerOptions, files, externalFilePropertyReader)); ->>>>>>> d736db3b01a5f4f4215c17845deb3ae09cf28787 - - const errors = this.addFilesToProjectAndUpdateGraph(project, files, externalFilePropertyReader, /*clientFileName*/ undefined); - this.externalProjects.push(project); - return { project, errors }; - } - - private createAndAddConfiguredProject(configFileName: NormalizedPath, projectOptions: ProjectOptions, clientFileName?: string) { - const sizeLimitExceeded = this.exceededTotalSizeLimitForNonTsFiles(projectOptions.compilerOptions, projectOptions.files, fileNamePropertyReader); - const project = new ConfiguredProject( - configFileName, - this, - this.documentRegistry, - projectOptions.configHasFilesProperty, - projectOptions.compilerOptions, - projectOptions.typingOptions, - projectOptions.wildcardDirectories, - /*languageServiceEnabled*/ !sizeLimitExceeded, - /*compileOnSaveEnabled*/ !!projectOptions.compileOnSave); - - const errors = this.addFilesToProjectAndUpdateGraph(project, projectOptions.files, fileNamePropertyReader, clientFileName); - - project.watchConfigFile(project => this.onConfigChangedForConfiguredProject(project)); - if (!sizeLimitExceeded) { - this.watchConfigDirectoryForProject(project, projectOptions); - } - project.watchWildcards((project, path) => this.onSourceFileInDirectoryChangedForConfiguredProject(project, path)); - - this.configuredProjects.push(project); - return { project, errors }; - } - - private watchConfigDirectoryForProject(project: ConfiguredProject, options: ProjectOptions): void { - if (!options.configHasFilesProperty) { - project.watchConfigDirectory((project, path) => this.onSourceFileInDirectoryChangedForConfiguredProject(project, path)); - } - } - - private addFilesToProjectAndUpdateGraph(project: ConfiguredProject | ExternalProject, files: T[], propertyReader: FilePropertyReader, clientFileName: string): Diagnostic[] { - let errors: Diagnostic[]; - for (const f of files) { - const rootFilename = propertyReader.getFileName(f); - const scriptKind = propertyReader.getScriptKind(f); - const hasMixedContent = propertyReader.hasMixedContent(f); - if (this.host.fileExists(rootFilename)) { - const info = this.getOrCreateScriptInfoForNormalizedPath(toNormalizedPath(rootFilename), /*openedByClient*/ clientFileName == rootFilename, /*fileContent*/ undefined, scriptKind, hasMixedContent); - project.addRoot(info); - } - else { - (errors || (errors = [])).push(createCompilerDiagnostic(Diagnostics.File_0_not_found, rootFilename)); - } - } - project.updateGraph(); - return errors; - } - - private openConfigFile(configFileName: NormalizedPath, clientFileName?: string): OpenConfigFileResult { - const conversionResult = this.convertConfigFileContentToProjectOptions(configFileName); - if (!conversionResult.success) { - return { success: false, errors: conversionResult.errors }; - } - const { project, errors } = this.createAndAddConfiguredProject(configFileName, conversionResult.projectOptions, clientFileName); - return { success: true, project, errors }; - } - -<<<<<<< HEAD - private updateNonInferredProject(project: ExternalProject | ConfiguredProject, newUncheckedFiles: T[], propertyReader: FilePropertyReader, newOptions: CompilerOptions, newTypingOptions: TypingOptions, compileOnSave: boolean) { -======= - private updateNonInferredProject(project: ExternalProject | ConfiguredProject, newUncheckedFiles: T[], propertyReader: FilePropertyReader, newOptions: CompilerOptions, newTypingOptions: TypingOptions) { ->>>>>>> d736db3b01a5f4f4215c17845deb3ae09cf28787 - const oldRootScriptInfos = project.getRootScriptInfos(); - const newRootScriptInfos: ScriptInfo[] = []; - const newRootScriptInfoMap: NormalizedPathMap = createNormalizedPathMap(); - - let rootFilesChanged = false; - for (const f of newUncheckedFiles) { - const newRootFile = propertyReader.getFileName(f); - if (!this.host.fileExists(newRootFile)) { - continue; - } - const normalizedPath = toNormalizedPath(newRootFile); - let scriptInfo = this.getScriptInfoForNormalizedPath(normalizedPath); - if (!scriptInfo || !project.isRoot(scriptInfo)) { - rootFilesChanged = true; - if (!scriptInfo) { - const scriptKind = propertyReader.getScriptKind(f); - const hasMixedContent = propertyReader.hasMixedContent(f); - scriptInfo = this.getOrCreateScriptInfoForNormalizedPath(normalizedPath, /*openedByClient*/ false, /*fileContent*/ undefined, scriptKind, hasMixedContent); - } - } - newRootScriptInfos.push(scriptInfo); - newRootScriptInfoMap.set(scriptInfo.fileName, scriptInfo); - } - - if (rootFilesChanged || newRootScriptInfos.length !== oldRootScriptInfos.length) { - let toAdd: ScriptInfo[]; - let toRemove: ScriptInfo[]; - for (const oldFile of oldRootScriptInfos) { - if (!newRootScriptInfoMap.contains(oldFile.fileName)) { - (toRemove || (toRemove = [])).push(oldFile); - } - } - for (const newFile of newRootScriptInfos) { - if (!project.isRoot(newFile)) { - (toAdd || (toAdd = [])).push(newFile); - } - } - if (toRemove) { - for (const f of toRemove) { - project.removeFile(f); - } - } - if (toAdd) { - for (const f of toAdd) { - if (f.isOpen && isRootFileInInferredProject(f)) { - // if file is already root in some inferred project - // - remove the file from that project and delete the project if necessary - const inferredProject = f.containingProjects[0]; - inferredProject.removeFile(f); - if (!inferredProject.hasRoots()) { - this.removeProject(inferredProject); - } - } - project.addRoot(f); - } - } - } - - project.setCompilerOptions(newOptions); - (project).setTypingOptions(newTypingOptions); -<<<<<<< HEAD - project.compileOnSaveEnabled = !!compileOnSave; -======= ->>>>>>> d736db3b01a5f4f4215c17845deb3ae09cf28787 - project.updateGraph(); - } - - private updateConfiguredProject(project: ConfiguredProject) { - if (!this.host.fileExists(project.configFileName)) { - this.logger.info("Config file deleted"); - this.removeProject(project); - return; - } - - const { success, projectOptions, errors } = this.convertConfigFileContentToProjectOptions(project.configFileName); - if (!success) { - return errors; - } - - if (this.exceededTotalSizeLimitForNonTsFiles(projectOptions.compilerOptions, projectOptions.files, fileNamePropertyReader)) { - project.setCompilerOptions(projectOptions.compilerOptions); - if (!project.languageServiceEnabled) { - // language service is already disabled - return; - } - project.disableLanguageService(); - project.stopWatchingDirectory(); - } - else { - if (!project.languageServiceEnabled) { - project.enableLanguageService(); - } - this.watchConfigDirectoryForProject(project, projectOptions); -<<<<<<< HEAD - this.updateNonInferredProject(project, projectOptions.files, fileNamePropertyReader, projectOptions.compilerOptions, projectOptions.typingOptions, projectOptions.compileOnSave); -======= - this.updateNonInferredProject(project, projectOptions.files, fileNamePropertyReader, projectOptions.compilerOptions, projectOptions.typingOptions); ->>>>>>> d736db3b01a5f4f4215c17845deb3ae09cf28787 - } - } - - createInferredProjectWithRootFileIfNecessary(root: ScriptInfo) { - const useExistingProject = this.useSingleInferredProject && this.inferredProjects.length; - const project = useExistingProject - ? this.inferredProjects[0] - : new InferredProject(this, this.documentRegistry, /*languageServiceEnabled*/ true, this.compilerOptionsForInferredProjects); - - project.addRoot(root); - - this.directoryWatchers.startWatchingContainingDirectoriesForFile( - root.fileName, - project, - fileName => this.onConfigFileAddedForInferredProject(fileName)); - - project.updateGraph(); - - if (!useExistingProject) { - this.inferredProjects.push(project); - } - return project; - } - - /** - * @param uncheckedFileName is absolute pathname - * @param fileContent is a known version of the file content that is more up to date than the one on disk - */ - - getOrCreateScriptInfo(uncheckedFileName: string, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind) { - return this.getOrCreateScriptInfoForNormalizedPath(toNormalizedPath(uncheckedFileName), openedByClient, fileContent, scriptKind); - } - - getScriptInfo(uncheckedFileName: string) { - return this.getScriptInfoForNormalizedPath(toNormalizedPath(uncheckedFileName)); - } - - getOrCreateScriptInfoForNormalizedPath(fileName: NormalizedPath, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean) { - let info = this.getScriptInfoForNormalizedPath(fileName); - if (!info) { - let content: string; - if (this.host.fileExists(fileName)) { - // by default pick whatever content was supplied as the argument - // if argument was not given - then for mixed content files assume that its content is empty string - content = fileContent || (hasMixedContent ? "" : this.host.readFile(fileName)); - } - if (!content) { - if (openedByClient) { - content = ""; - } - } - if (content !== undefined) { - info = new ScriptInfo(this.host, fileName, content, scriptKind, openedByClient, hasMixedContent); - info.setFormatOptions(toEditorSettings(this.getFormatCodeOptions())); - // do not watch files with mixed content - server doesn't know how to interpret it - this.filenameToScriptInfo.set(info.path, info); - if (!info.isOpen && !hasMixedContent) { - info.setWatcher(this.host.watchFile(fileName, _ => this.onSourceFileChanged(fileName))); - } - } - } - if (info) { - if (fileContent) { - info.reload(fileContent); - } - if (openedByClient) { - info.isOpen = true; - } - } - return info; - } - - getScriptInfoForNormalizedPath(fileName: NormalizedPath) { - return this.filenameToScriptInfo.get(normalizedPathToPath(fileName, this.host.getCurrentDirectory(), this.toCanonicalFileName)); - } - - setHostConfiguration(args: protocol.ConfigureRequestArguments) { - if (args.file) { - const info = this.getScriptInfoForNormalizedPath(toNormalizedPath(args.file)); - if (info) { - info.setFormatOptions(args.formatOptions); - this.logger.info(`Host configuration update for file ${args.file}`); - } - } - else { - if (args.hostInfo !== undefined) { - this.hostConfiguration.hostInfo = args.hostInfo; - this.logger.info(`Host information ${args.hostInfo}`); - } - if (args.formatOptions) { - mergeMaps(this.hostConfiguration.formatCodeOptions, args.formatOptions); - this.logger.info("Format host information updated"); - } - } - } - - closeLog() { - this.logger.close(); - } - - /** - * This function rebuilds the project for every file opened by the client - */ - reloadProjects() { - this.logger.info("reload projects."); - // try to reload config file for all open files - for (const info of this.openFiles) { - this.openOrUpdateConfiguredProjectForFile(info.fileName); - } - this.refreshInferredProjects(); - } - - /** - * This function is to update the project structure for every projects. - * It is called on the premise that all the configured projects are - * up to date. - */ - refreshInferredProjects() { - this.logger.info("updating project structure from ..."); - this.printProjects(); - - const orphantedFiles: ScriptInfo[] = []; - // collect all orphanted script infos from open files - for (const info of this.openFiles) { - if (info.containingProjects.length === 0) { - orphantedFiles.push(info); - } - else { - if (isRootFileInInferredProject(info) && info.containingProjects.length > 1) { - const inferredProject = info.containingProjects[0]; - Debug.assert(inferredProject.projectKind === ProjectKind.Inferred); - inferredProject.removeFile(info); - if (!inferredProject.hasRoots()) { - this.removeProject(inferredProject); - } - } - } - } - for (const f of orphantedFiles) { - this.assignScriptInfoToInferredProjectIfNecessary(f, /*addToListOfOpenFiles*/ false); - } - - for (const p of this.inferredProjects) { - p.updateGraph(); - } - this.printProjects(); - } - - /** - * Open file whose contents is managed by the client - * @param filename is absolute pathname - * @param fileContent is a known version of the file content that is more up to date than the one on disk - */ - openClientFile(fileName: string, fileContent?: string, scriptKind?: ScriptKind): OpenConfiguredProjectResult { - return this.openClientFileWithNormalizedPath(toNormalizedPath(fileName), fileContent, scriptKind); - } - - openClientFileWithNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean): OpenConfiguredProjectResult { - const { configFileName = undefined, configFileErrors = undefined }: OpenConfiguredProjectResult = this.findContainingExternalProject(fileName) - ? {} - : this.openOrUpdateConfiguredProjectForFile(fileName); - - // at this point if file is the part of some configured/external project then this project should be created - const info = this.getOrCreateScriptInfoForNormalizedPath(fileName, /*openedByClient*/ true, fileContent, scriptKind, hasMixedContent); - this.assignScriptInfoToInferredProjectIfNecessary(info, /*addToListOfOpenFiles*/ true); - this.printProjects(); - return { configFileName, configFileErrors }; - } - - /** - * Close file whose contents is managed by the client - * @param filename is absolute pathname - */ - closeClientFile(uncheckedFileName: string) { - const info = this.getScriptInfoForNormalizedPath(toNormalizedPath(uncheckedFileName)); - if (info) { - this.closeOpenFile(info); - info.isOpen = false; - } - this.printProjects(); - } - - private collectChanges(lastKnownProjectVersions: protocol.ProjectVersionInfo[], currentProjects: Project[], result: protocol.ProjectFiles[]): void { - for (const proj of currentProjects) { - const knownProject = forEach(lastKnownProjectVersions, p => p.projectName === proj.getProjectName() && p); - result.push(proj.getChangesSinceVersion(knownProject && knownProject.version)); - } - } - - synchronizeProjectList(knownProjects: protocol.ProjectVersionInfo[]): protocol.ProjectFiles[] { - const files: protocol.ProjectFiles[] = []; - this.collectChanges(knownProjects, this.externalProjects, files); - this.collectChanges(knownProjects, this.configuredProjects, files); - this.collectChanges(knownProjects, this.inferredProjects, files); - return files; - } - - applyChangesInOpenFiles(openFiles: protocol.ExternalFile[], changedFiles: protocol.ChangedOpenFile[], closedFiles: string[]): void { - const recordChangedFiles = changedFiles && !openFiles && !closedFiles; - if (openFiles) { - for (const file of openFiles) { - const scriptInfo = this.getScriptInfo(file.fileName); - Debug.assert(!scriptInfo || !scriptInfo.isOpen); - const normalizedPath = scriptInfo ? scriptInfo.fileName : toNormalizedPath(file.fileName); - this.openClientFileWithNormalizedPath(normalizedPath, file.content, file.scriptKind, file.hasMixedContent); - } - } - - if (changedFiles) { - for (const file of changedFiles) { - const scriptInfo = this.getScriptInfo(file.fileName); - Debug.assert(!!scriptInfo); - // apply changes in reverse order - for (let i = file.changes.length - 1; i >= 0; i--) { - const change = file.changes[i]; - scriptInfo.editContent(change.span.start, change.span.start + change.span.length, change.newText); - } - if (recordChangedFiles) { - if (!this.changedFiles) { - this.changedFiles = [scriptInfo]; - } - else if (this.changedFiles.indexOf(scriptInfo) < 0) { - this.changedFiles.push(scriptInfo); - } - } - } - } - - if (closedFiles) { - for (const file of closedFiles) { - this.closeClientFile(file); - } - } - // if files were open or closed then explicitly refresh list of inferred projects - // otherwise if there were only changes in files - record changed files in `changedFiles` and defer the update - if (openFiles || closedFiles) { - this.refreshInferredProjects(); - } - } - - closeExternalProject(uncheckedFileName: string): void { - const fileName = toNormalizedPath(uncheckedFileName); - const configFiles = this.externalProjectToConfiguredProjectMap[fileName]; - if (configFiles) { - let shouldRefreshInferredProjects = false; - for (const configFile of configFiles) { - const configuredProject = this.findConfiguredProjectByProjectName(configFile); - if (configuredProject && configuredProject.deleteOpenRef() === 0) { - this.removeProject(configuredProject); - shouldRefreshInferredProjects = true; - } - } - if (shouldRefreshInferredProjects) { - this.refreshInferredProjects(); - } - } - else { - // close external project - const externalProject = this.findExternalProjectByProjectName(uncheckedFileName); - if (externalProject) { - this.removeProject(externalProject); - this.refreshInferredProjects(); - } - } - } - - openExternalProject(proj: protocol.ExternalProject): void { - const externalProject = this.findExternalProjectByProjectName(proj.projectFileName); - if (externalProject) { -<<<<<<< HEAD - this.updateNonInferredProject(externalProject, proj.rootFiles, externalFilePropertyReader, proj.options, proj.typingOptions, proj.options.compileOnSave); -======= - this.updateNonInferredProject(externalProject, proj.rootFiles, externalFilePropertyReader, proj.options, proj.typingOptions); ->>>>>>> d736db3b01a5f4f4215c17845deb3ae09cf28787 - return; - } - - let tsConfigFiles: NormalizedPath[]; - const rootFiles: protocol.ExternalFile[] = []; - for (const file of proj.rootFiles) { - const normalized = toNormalizedPath(file.fileName); - if (getBaseFileName(normalized) === "tsconfig.json") { - (tsConfigFiles || (tsConfigFiles = [])).push(normalized); - } - else { - rootFiles.push(file); - } - } - if (tsConfigFiles) { - // store the list of tsconfig files that belong to the external project - this.externalProjectToConfiguredProjectMap[proj.projectFileName] = tsConfigFiles; - for (const tsconfigFile of tsConfigFiles) { - let project = this.findConfiguredProjectByProjectName(tsconfigFile); - if (!project) { - const result = this.openConfigFile(tsconfigFile); - // TODO: save errors - project = result.success && result.project; - } - if (project) { - // keep project alive even if no documents are opened - its lifetime is bound to the lifetime of containing external project - project.addOpenRef(); - } - } - } - else { - this.createAndAddExternalProject(proj.projectFileName, rootFiles, proj.options, proj.typingOptions); - } - } - } -} diff --git a/src/server/project.ts.orig b/src/server/project.ts.orig deleted file mode 100644 index 6fef06dfa7e..00000000000 --- a/src/server/project.ts.orig +++ /dev/null @@ -1,681 +0,0 @@ -/// -/// -/// -/// -/// -/// - -namespace ts.server { - - export enum ProjectKind { - Inferred, - Configured, - External - } - - function remove(items: T[], item: T) { - const index = items.indexOf(item); - if (index >= 0) { - items.splice(index, 1); - } - } - - const jsOrDts = [".js", ".d.ts"]; - - export function allFilesAreJsOrDts(project: Project): boolean { - return project.getFileNames().every(f => fileExtensionIsAny(f, jsOrDts)); - } - - export abstract class Project { - private rootFiles: ScriptInfo[] = []; - private rootFilesMap: FileMap = createFileMap(); - private lsHost: ServerLanguageServiceHost; - private program: ts.Program; - - private languageService: LanguageService; - builder: Builder; - /** - * Set of files that was returned from the last call to getChangesSinceVersion. - */ - private lastReportedFileNames: Map; - /** - * Last version that was reported. - */ - private lastReportedVersion = 0; - /** - * Current project structure version. - * This property is changed in 'updateGraph' based on the set of files in program - */ - private projectStructureVersion = 0; - /** - * Current version of the project state. It is changed when: - * - new root file was added/removed - * - edit happen in some file that is currently included in the project. - * This property is different from projectStructureVersion since in most cases edits don't affect set of files in the project - */ - private projectStateVersion = 0; - - private typingFiles: TypingsArray; - - constructor( - readonly projectKind: ProjectKind, - readonly projectService: ProjectService, - private documentRegistry: ts.DocumentRegistry, - hasExplicitListOfFiles: boolean, - public languageServiceEnabled: boolean, - private compilerOptions: CompilerOptions, - public compileOnSaveEnabled: boolean) { - - if (!this.compilerOptions) { - this.compilerOptions = ts.getDefaultCompilerOptions(); - this.compilerOptions.allowNonTsExtensions = true; - this.compilerOptions.allowJs = true; - } - else if (hasExplicitListOfFiles) { - // If files are listed explicitly, allow all extensions - this.compilerOptions.allowNonTsExtensions = true; - } - - if (languageServiceEnabled) { - this.enableLanguageService(); - } - else { - this.disableLanguageService(); - } - - this.builder = createBuilder(this); - this.markAsDirty(); - } - - getLanguageService(ensureSynchronized = true): LanguageService { - if (ensureSynchronized) { - this.updateGraph(); - } - return this.languageService; - } - - getCompileOnSaveAffectedFileList(scriptInfo: ScriptInfo): string[] { - if (!this.languageServiceEnabled) { - return []; - } - this.updateGraph(); - return this.builder.getFilesAffectedBy(scriptInfo); - } - - getProjectVersion() { - return this.projectStateVersion.toString(); - } - - enableLanguageService() { - const lsHost = new LSHost(this.projectService.host, this, this.projectService.cancellationToken); - lsHost.setCompilationSettings(this.compilerOptions); - this.languageService = ts.createLanguageService(lsHost, this.documentRegistry); - - this.lsHost = lsHost; - this.languageServiceEnabled = true; - } - - disableLanguageService() { - this.languageService = nullLanguageService; - this.lsHost = nullLanguageServiceHost; - this.languageServiceEnabled = false; - } - - abstract getProjectName(): string; - abstract getTypingOptions(): TypingOptions; -<<<<<<< HEAD - - getSourceFile(path: Path) { - if (!this.program) { - return undefined; - } - return this.program.getSourceFileByPath(path); - } -======= ->>>>>>> d736db3b01a5f4f4215c17845deb3ae09cf28787 - - close() { - if (this.program) { - // if we have a program - release all files that are enlisted in program - for (const f of this.program.getSourceFiles()) { - const info = this.projectService.getScriptInfo(f.fileName); - info.detachFromProject(this); - } - } - else { - // release all root files - for (const root of this.rootFiles) { - root.detachFromProject(this); - } - } - this.rootFiles = undefined; - this.rootFilesMap = undefined; - this.program = undefined; - - // signal language service to release source files acquired from document registry - this.languageService.dispose(); - } - - getCompilerOptions() { - return this.compilerOptions; - } - - hasRoots() { - return this.rootFiles && this.rootFiles.length > 0; - } - - getRootFiles() { - return this.rootFiles && this.rootFiles.map(info => info.fileName); - } - - getRootFilesLSHost() { - const result: string[] = []; - if (this.rootFiles) { - for (const f of this.rootFiles) { - result.push(f.fileName); - } - if (this.typingFiles) { - for (const f of this.typingFiles) { - result.push(f); - } - } - } - return result; - } - - getRootScriptInfos() { - return this.rootFiles; - } - - getScriptInfos() { - return map(this.program.getSourceFiles(), sourceFile => this.getScriptInfoLSHost(sourceFile.path)); - } - - getFileEmitOutput(info: ScriptInfo, emitOnlyDtsFiles: boolean) { - if (!this.languageServiceEnabled) { - return undefined; - } - return this.getLanguageService().getEmitOutput(info.fileName, emitOnlyDtsFiles); - } - - getFileNames() { - if (!this.program) { - return []; - } - - if (!this.languageServiceEnabled) { - // if language service is disabled assume that all files in program are root files + default library - let rootFiles = this.getRootFiles(); - if (this.compilerOptions) { - const defaultLibrary = getDefaultLibFilePath(this.compilerOptions); - if (defaultLibrary) { - (rootFiles || (rootFiles = [])).push(asNormalizedPath(defaultLibrary)); - } - } - return rootFiles; - } - const sourceFiles = this.program.getSourceFiles(); - return sourceFiles.map(sourceFile => asNormalizedPath(sourceFile.fileName)); - } - - getFileNamesWithoutDefaultLib() { - if (!this.languageServiceEnabled) { - return this.getRootFiles(); - } - const defaultLibraryFileName = getDefaultLibFileName(this.compilerOptions); - return filter(this.getFileNames(), file => getBaseFileName(file) !== defaultLibraryFileName); - } - - containsScriptInfo(info: ScriptInfo): boolean { - return this.isRoot(info) || (this.program && this.program.getSourceFileByPath(info.path) !== undefined); - } - - containsFile(filename: NormalizedPath, requireOpen?: boolean) { - const info = this.projectService.getScriptInfoForNormalizedPath(filename); - if (info && (info.isOpen || !requireOpen)) { - return this.containsScriptInfo(info); - } - } - - isRoot(info: ScriptInfo) { - return this.rootFilesMap && this.rootFilesMap.contains(info.path); - } - - // add a root file to project - addRoot(info: ScriptInfo) { - if (!this.isRoot(info)) { - this.rootFiles.push(info); - this.rootFilesMap.set(info.path, info); - info.attachToProject(this); - - this.markAsDirty(); - } - } - - removeFile(info: ScriptInfo, detachFromProject = true) { - this.removeRootFileIfNecessary(info); - this.lsHost.notifyFileRemoved(info); - - if (detachFromProject) { - info.detachFromProject(this); - } - - this.markAsDirty(); - } - - markAsDirty() { - this.projectStateVersion++; - } - - /** - * Updates set of files that contribute to this project - * @returns: true if set of files in the project stays the same and false - otherwise. - */ - updateGraph(): boolean { - if (!this.languageServiceEnabled) { - return true; - } - let hasChanges = this.updateGraphWorker(); - const cachedTypings = this.projectService.typingsCache.getTypingsForProject(this); - if (this.setTypings(cachedTypings)) { - hasChanges = this.updateGraphWorker() || hasChanges; - } - if (hasChanges) { - this.projectStructureVersion++; - } - return !hasChanges; - } - - private setTypings(typings: TypingsArray): boolean { - if (arrayIsEqualTo(this.typingFiles, typings)) { - return false; - } - this.typingFiles = typings; - this.markAsDirty(); - return true; - } - - private updateGraphWorker() { - const oldProgram = this.program; - this.program = this.languageService.getProgram(); - - let hasChanges = false; - // bump up the version if - // - oldProgram is not set - this is a first time updateGraph is called - // - newProgram is different from the old program and structure of the old program was not reused. - if (!oldProgram || (this.program !== oldProgram && !oldProgram.structureIsReused)) { - hasChanges = true; - if (oldProgram) { - for (const f of oldProgram.getSourceFiles()) { - if (this.program.getSourceFileByPath(f.path)) { - continue; - } - // new program does not contain this file - detach it from the project - const scriptInfoToDetach = this.projectService.getScriptInfo(f.fileName); - if (scriptInfoToDetach) { - scriptInfoToDetach.detachFromProject(this); - } - } - } - } - this.builder.onProjectUpdateGraph(); - return hasChanges; - } - - getScriptInfoLSHost(fileName: string) { - const scriptInfo = this.projectService.getOrCreateScriptInfo(fileName, /*openedByClient*/ false); - if (scriptInfo) { - scriptInfo.attachToProject(this); - } - return scriptInfo; - } - - getScriptInfoForNormalizedPath(fileName: NormalizedPath) { - const scriptInfo = this.projectService.getOrCreateScriptInfoForNormalizedPath(fileName, /*openedByClient*/ false); - Debug.assert(!scriptInfo || scriptInfo.isAttached(this)); - return scriptInfo; - } - - getScriptInfo(uncheckedFileName: string) { - return this.getScriptInfoForNormalizedPath(toNormalizedPath(uncheckedFileName)); - } - - filesToString() { - if (!this.program) { - return ""; - } - let strBuilder = ""; - for (const file of this.program.getSourceFiles()) { - strBuilder += `${file.fileName}\n`; - } - return strBuilder; - } - - setCompilerOptions(compilerOptions: CompilerOptions) { - if (compilerOptions) { - if (this.projectKind === ProjectKind.Inferred) { - compilerOptions.allowJs = true; - } - compilerOptions.allowNonTsExtensions = true; - this.compilerOptions = compilerOptions; - this.lsHost.setCompilationSettings(compilerOptions); - - this.markAsDirty(); - } - } - - reloadScript(filename: NormalizedPath): boolean { - const script = this.projectService.getScriptInfoForNormalizedPath(filename); - if (script) { - Debug.assert(script.isAttached(this)); - script.reloadFromFile(); - return true; - } - return false; - } - - getChangesSinceVersion(lastKnownVersion?: number): protocol.ProjectFiles { - this.updateGraph(); - - const info = { - projectName: this.getProjectName(), - version: this.projectStructureVersion, - isInferred: this.projectKind === ProjectKind.Inferred, - options: this.getCompilerOptions() - }; - // check if requested version is the same that we have reported last time - if (this.lastReportedFileNames && lastKnownVersion === this.lastReportedVersion) { - // if current structure version is the same - return info witout any changes - if (this.projectStructureVersion == this.lastReportedVersion) { - return { info }; - } - // compute and return the difference - const lastReportedFileNames = this.lastReportedFileNames; - const currentFiles = arrayToMap(this.getFileNames(), x => x); - - const added: string[] = []; - const removed: string[] = []; - for (const id in currentFiles) { - if (hasProperty(currentFiles, id) && !hasProperty(lastReportedFileNames, id)) { - added.push(id); - } - } - for (const id in lastReportedFileNames) { - if (hasProperty(lastReportedFileNames, id) && !hasProperty(currentFiles, id)) { - removed.push(id); - } - } - this.lastReportedFileNames = currentFiles; - - this.lastReportedFileNames = currentFiles; - this.lastReportedVersion = this.projectStructureVersion; - return { info, changes: { added, removed } }; - } - else { - // unknown version - return everything - const projectFileNames = this.getFileNames(); - this.lastReportedFileNames = arrayToMap(projectFileNames, x => x); - this.lastReportedVersion = this.projectStructureVersion; - return { info, files: projectFileNames }; - } - } - - getReferencedFiles(path: Path): Path[] { - if (!this.languageServiceEnabled) { - return []; - } - - const sourceFile = this.getSourceFile(path); - if (!sourceFile) { - return []; - } - // We need to use a set here since the code can contain the same import twice, - // but that will only be one dependency. - // To avoid invernal conversion, the key of the referencedFiles map must be of type Path - const referencedFiles = createMap(); - if (sourceFile.imports) { - const checker: TypeChecker = this.program.getTypeChecker(); - for (const importName of sourceFile.imports) { - const symbol = checker.getSymbolAtLocation(importName); - if (symbol && symbol.declarations && symbol.declarations[0]) { - const declarationSourceFile = symbol.declarations[0].getSourceFile(); - if (declarationSourceFile) { - referencedFiles[declarationSourceFile.path] = true; - } - } - } - } - - const currentDirectory = getDirectoryPath(path); - const getCanonicalFileName = createGetCanonicalFileName(this.projectService.host.useCaseSensitiveFileNames); - // Handle triple slash references - if (sourceFile.referencedFiles) { - for (const referencedFile of sourceFile.referencedFiles) { - const referencedPath = toPath(referencedFile.fileName, currentDirectory, getCanonicalFileName); - referencedFiles[referencedPath] = true; - } - } - - // Handle type reference directives - if (sourceFile.resolvedTypeReferenceDirectiveNames) { - for (const typeName in sourceFile.resolvedTypeReferenceDirectiveNames) { - const resolvedTypeReferenceDirective = sourceFile.resolvedTypeReferenceDirectiveNames[typeName]; - if (!resolvedTypeReferenceDirective) { - continue; - } - - const fileName = resolvedTypeReferenceDirective.resolvedFileName; - const typeFilePath = toPath(fileName, currentDirectory, getCanonicalFileName); - referencedFiles[typeFilePath] = true; - } - } - - return map(Object.keys(referencedFiles), key => key); - } - - // remove a root file from project - private removeRootFileIfNecessary(info: ScriptInfo): void { - if (this.isRoot(info)) { - remove(this.rootFiles, info); - this.rootFilesMap.remove(info.path); - } - } - } - - export class InferredProject extends Project { - - private static NextId = 1; - - /** - * Unique name that identifies this particular inferred project - */ - private readonly inferredProjectName: string; - - // Used to keep track of what directories are watched for this project - directoriesWatchedForTsconfig: string[] = []; - - constructor(projectService: ProjectService, documentRegistry: ts.DocumentRegistry, languageServiceEnabled: boolean, compilerOptions: CompilerOptions) { - super(ProjectKind.Inferred, - projectService, - documentRegistry, - /*files*/ undefined, - languageServiceEnabled, - compilerOptions, - /*compileOnSaveEnabled*/ false); - - this.inferredProjectName = makeInferredProjectName(InferredProject.NextId); - InferredProject.NextId++; - } - - getProjectName() { - return this.inferredProjectName; - } - - close() { - super.close(); - - for (const directory of this.directoriesWatchedForTsconfig) { - this.projectService.stopWatchingDirectory(directory); - } - } - - getTypingOptions(): TypingOptions { - return { - enableAutoDiscovery: allFilesAreJsOrDts(this), - include: [], - exclude: [] - }; - } - } - - export class ConfiguredProject extends Project { - private projectFileWatcher: FileWatcher; - private directoryWatcher: FileWatcher; - private directoriesWatchedForWildcards: Map; - /** Used for configured projects which may have multiple open roots */ - openRefCount = 0; - - constructor(readonly configFileName: NormalizedPath, - projectService: ProjectService, - documentRegistry: ts.DocumentRegistry, - hasExplicitListOfFiles: boolean, - compilerOptions: CompilerOptions, - private typingOptions: TypingOptions, - private wildcardDirectories: Map, - languageServiceEnabled: boolean, - public compileOnSaveEnabled = false) { - super(ProjectKind.Configured, projectService, documentRegistry, hasExplicitListOfFiles, languageServiceEnabled, compilerOptions, compileOnSaveEnabled); - } - - setTypingOptions(newTypingOptions: TypingOptions): void { - this.typingOptions = newTypingOptions; - } - - setTypingOptions(newTypingOptions: TypingOptions): void { - this.typingOptions = newTypingOptions; - } - - getTypingOptions() { - return this.typingOptions; - } - - getProjectName() { - return this.configFileName; - } - - watchConfigFile(callback: (project: ConfiguredProject) => void) { - this.projectFileWatcher = this.projectService.host.watchFile(this.configFileName, _ => callback(this)); - } - - watchConfigDirectory(callback: (project: ConfiguredProject, path: string) => void) { - if (this.directoryWatcher) { - return; - } - - const directoryToWatch = getDirectoryPath(this.configFileName); - this.projectService.logger.info(`Add recursive watcher for: ${directoryToWatch}`); - this.directoryWatcher = this.projectService.host.watchDirectory(directoryToWatch, path => callback(this, path), /*recursive*/ true); - } - - watchWildcards(callback: (project: ConfiguredProject, path: string) => void) { - if (!this.wildcardDirectories) { - return; - } - const configDirectoryPath = getDirectoryPath(this.configFileName); - this.directoriesWatchedForWildcards = reduceProperties(this.wildcardDirectories, (watchers, flag, directory) => { - if (comparePaths(configDirectoryPath, directory, ".", !this.projectService.host.useCaseSensitiveFileNames) !== Comparison.EqualTo) { - const recursive = (flag & WatchDirectoryFlags.Recursive) !== 0; - this.projectService.logger.info(`Add ${recursive ? "recursive " : ""}watcher for: ${directory}`); - watchers[directory] = this.projectService.host.watchDirectory( - directory, - path => callback(this, path), - recursive - ); - } - return watchers; - }, >{}); - } - - stopWatchingDirectory() { - if (this.directoryWatcher) { - this.directoryWatcher.close(); - this.directoryWatcher = undefined; - } - } - - close() { - super.close(); - - if (this.projectFileWatcher) { - this.projectFileWatcher.close(); - } - - for (const id in this.directoriesWatchedForWildcards) { - this.directoriesWatchedForWildcards[id].close(); - } - this.directoriesWatchedForWildcards = undefined; - - this.stopWatchingDirectory(); - } - - addOpenRef() { - this.openRefCount++; - } - - deleteOpenRef() { - this.openRefCount--; - return this.openRefCount; - } - } - - export class ExternalProject extends Project { - private typingOptions: TypingOptions; - constructor(readonly externalProjectName: string, - projectService: ProjectService, - documentRegistry: ts.DocumentRegistry, - compilerOptions: CompilerOptions, - typingOptions: TypingOptions, -<<<<<<< HEAD - languageServiceEnabled: boolean, - public compileOnSaveEnabled = true) { - super(ProjectKind.External, projectService, documentRegistry, /*hasExplicitListOfFiles*/ true, languageServiceEnabled, compilerOptions, compileOnSaveEnabled); -======= - languageServiceEnabled: boolean) { - super(ProjectKind.External, projectService, documentRegistry, /*hasExplicitListOfFiles*/ true, languageServiceEnabled, compilerOptions); ->>>>>>> d736db3b01a5f4f4215c17845deb3ae09cf28787 - this.setTypingOptions(typingOptions); - } - - getTypingOptions() { - return this.typingOptions; - } - - setTypingOptions(newTypingOptions: TypingOptions): void { - if (!newTypingOptions) { - // set default typings options - newTypingOptions = { - enableAutoDiscovery: allFilesAreJsOrDts(this), - include: [], - exclude: [] - }; - } - else { - if (newTypingOptions.enableAutoDiscovery === undefined) { - // if autoDiscovery was not specified by the caller - set it based on the content of the project - newTypingOptions.enableAutoDiscovery = allFilesAreJsOrDts(this); - } - if (!newTypingOptions.include) { - newTypingOptions.include = []; - } - if (!newTypingOptions.exclude) { - newTypingOptions.exclude = []; - } - } - this.typingOptions = newTypingOptions; - } - - getProjectName() { - return this.externalProjectName; - } - } -} \ No newline at end of file diff --git a/src/server/protocol.d.ts.orig b/src/server/protocol.d.ts.orig deleted file mode 100644 index 0fd9a916be7..00000000000 --- a/src/server/protocol.d.ts.orig +++ /dev/null @@ -1,1488 +0,0 @@ -/** - * Declaration module describing the TypeScript Server protocol - */ -declare namespace ts.server.protocol { - /** - * A TypeScript Server message - */ - export interface Message { - /** - * Sequence number of the message - */ - seq: number; - - /** - * One of "request", "response", or "event" - */ - type: string; - } - - /** - * Client-initiated request message - */ - export interface Request extends Message { - /** - * The command to execute - */ - command: string; - - /** - * Object containing arguments for the command - */ - arguments?: any; - } - - /** - * Request to reload the project structure for all the opened files - */ - export interface ReloadProjectsRequest extends Message { - } - - /** - * Server-initiated event message - */ - export interface Event extends Message { - /** - * Name of event - */ - event: string; - - /** - * Event-specific information - */ - body?: any; - } - - /** - * Response by server to client request message. - */ - export interface Response extends Message { - /** - * Sequence number of the request message. - */ - request_seq: number; - - /** - * Outcome of the request. - */ - success: boolean; - - /** - * The command requested. - */ - command: string; - - /** - * Contains error message if success === false. - */ - message?: string; - - /** - * Contains message body if success === true. - */ - body?: any; - } - - /** - * Arguments for FileRequest messages. - */ - export interface FileRequestArgs { - /** - * The file for the request (absolute pathname required). - */ - file: string; - - /* - * Optional name of project that contains file - */ - projectFileName?: string; - } - - export interface TodoCommentRequest extends FileRequest { - arguments: TodoCommentRequestArgs; - } - - export interface TodoCommentRequestArgs extends FileRequestArgs { - descriptors: TodoCommentDescriptor[]; - } - - export interface IndentationRequest extends FileLocationRequest { - arguments: IndentationRequestArgs; - } - - export interface IndentationRequestArgs extends FileLocationRequestArgs { - options?: EditorSettings; - } - - /** - * Arguments for ProjectInfoRequest request. - */ - export interface ProjectInfoRequestArgs extends FileRequestArgs { - /** - * Indicate if the file name list of the project is needed - */ - needFileNameList: boolean; - } - - /** - * A request to get the project information of the current file - */ - export interface ProjectInfoRequest extends Request { - arguments: ProjectInfoRequestArgs; - } - - export interface ProjectRequest extends Request { - arguments: ProjectRequestArgs; - } - - export interface ProjectRequestArgs { - projectFileName: string; - } - - /** - * Response message body for "projectInfo" request - */ - export interface ProjectInfo { - /** - * For configured project, this is the normalized path of the 'tsconfig.json' file - * For inferred project, this is undefined - */ - configFileName: string; - /** - * The list of normalized file name in the project, including 'lib.d.ts' - */ - fileNames?: string[]; - /** - * Indicates if the project has a active language service instance - */ - languageServiceDisabled?: boolean; - } - - export interface DiagnosticWithLinePosition { - message: string; - start: number; - length: number; - startLocation: Location; - endLocation: Location; - category: string; - code: number; - } - - /** - * Response message for "projectInfo" request - */ - export interface ProjectInfoResponse extends Response { - body?: ProjectInfo; - } - - /** - * Request whose sole parameter is a file name. - */ - export interface FileRequest extends Request { - arguments: FileRequestArgs; - } - - /** - * Instances of this interface specify a location in a source file: - * (file, line, character offset), where line and character offset are 1-based. - */ - export interface FileLocationRequestArgs extends FileRequestArgs { - /** - * The line number for the request (1-based). - */ - line?: number; - - /** - * The character offset (on the line) for the request (1-based). - */ - offset?: number; - - /** - * Position (can be specified instead of line/offset pair) - */ - position?: number; - } - - /** - * A request whose arguments specify a file location (file, line, col). - */ - export interface FileLocationRequest extends FileRequest { - arguments: FileLocationRequestArgs; - } - - export interface FileSpanRequestArgs extends FileRequestArgs { - start: number; - length: number; - } - - export interface FileSpanRequest extends FileRequest { - arguments: FileSpanRequestArgs; - } - - /** - * Arguments in document highlight request; include: filesToSearch, file, - * line, offset. - */ - export interface DocumentHighlightsRequestArgs extends FileLocationRequestArgs { - /** - * List of files to search for document highlights. - */ - filesToSearch: string[]; - } - - /** - * Go to definition request; value of command field is - * "definition". Return response giving the file locations that - * define the symbol found in file at location line, col. - */ - export interface DefinitionRequest extends FileLocationRequest { - } - - /** - * Go to type request; value of command field is - * "typeDefinition". Return response giving the file locations that - * define the type for the symbol found in file at location line, col. - */ - export interface TypeDefinitionRequest extends FileLocationRequest { - } - - /** - * Location in source code expressed as (one-based) line and character offset. - */ - export interface Location { - line: number; - offset: number; - } - - /** - * Object found in response messages defining a span of text in source code. - */ - export interface TextSpan { - /** - * First character of the definition. - */ - start: Location; - - /** - * One character past last character of the definition. - */ - end: Location; - } - - /** - * Object found in response messages defining a span of text in a specific source file. - */ - export interface FileSpan extends TextSpan { - /** - * File containing text span. - */ - file: string; - } - - /** - * Definition response message. Gives text range for definition. - */ - export interface DefinitionResponse extends Response { - body?: FileSpan[]; - } - - /** - * Definition response message. Gives text range for definition. - */ - export interface TypeDefinitionResponse extends Response { - body?: FileSpan[]; - } - - export interface BraceCompletionRequest extends FileLocationRequest { - arguments: BraceCompletionRequestArgs; - } - - export interface BraceCompletionRequestArgs extends FileLocationRequestArgs { - openingBrace: string; - } - - /** - * Get occurrences request; value of command field is - * "occurrences". Return response giving spans that are relevant - * in the file at a given line and column. - */ - export interface OccurrencesRequest extends FileLocationRequest { - } - - export interface OccurrencesResponseItem extends FileSpan { - /** - * True if the occurrence is a write location, false otherwise. - */ - isWriteAccess: boolean; - } - - export interface OccurrencesResponse extends Response { - body?: OccurrencesResponseItem[]; - } - - /** - * Get document highlights request; value of command field is - * "documentHighlights". Return response giving spans that are relevant - * in the file at a given line and column. - */ - export interface DocumentHighlightsRequest extends FileLocationRequest { - arguments: DocumentHighlightsRequestArgs; - } - - export interface HighlightSpan extends TextSpan { - kind: string; - } - - export interface DocumentHighlightsItem { - /** - * File containing highlight spans. - */ - file: string; - - /** - * Spans to highlight in file. - */ - highlightSpans: HighlightSpan[]; - } - - export interface DocumentHighlightsResponse extends Response { - body?: DocumentHighlightsItem[]; - } - - /** - * Find references request; value of command field is - * "references". Return response giving the file locations that - * reference the symbol found in file at location line, col. - */ - export interface ReferencesRequest extends FileLocationRequest { - } - - export interface ReferencesResponseItem extends FileSpan { - /** Text of line containing the reference. Including this - * with the response avoids latency of editor loading files - * to show text of reference line (the server already has - * loaded the referencing files). - */ - lineText: string; - - /** - * True if reference is a write location, false otherwise. - */ - isWriteAccess: boolean; - - /** - * True if reference is a definition, false otherwise. - */ - isDefinition: boolean; - } - - /** - * The body of a "references" response message. - */ - export interface ReferencesResponseBody { - /** - * The file locations referencing the symbol. - */ - refs: ReferencesResponseItem[]; - - /** - * The name of the symbol. - */ - symbolName: string; - - /** - * The start character offset of the symbol (on the line provided by the references request). - */ - symbolStartOffset: number; - - /** - * The full display name of the symbol. - */ - symbolDisplayString: string; - } - - /** - * Response to "references" request. - */ - export interface ReferencesResponse extends Response { - body?: ReferencesResponseBody; - } - - export interface RenameRequestArgs extends FileLocationRequestArgs { - findInComments?: boolean; - findInStrings?: boolean; - } - - - /** - * Rename request; value of command field is "rename". Return - * response giving the file locations that reference the symbol - * found in file at location line, col. Also return full display - * name of the symbol so that client can print it unambiguously. - */ - export interface RenameRequest extends FileLocationRequest { - arguments: RenameRequestArgs; - } - - /** - * Information about the item to be renamed. - */ - export interface RenameInfo { - /** - * True if item can be renamed. - */ - canRename: boolean; - - /** - * Error message if item can not be renamed. - */ - localizedErrorMessage?: string; - - /** - * Display name of the item to be renamed. - */ - displayName: string; - - /** - * Full display name of item to be renamed. - */ - fullDisplayName: string; - - /** - * The items's kind (such as 'className' or 'parameterName' or plain 'text'). - */ - kind: string; - - /** - * Optional modifiers for the kind (such as 'public'). - */ - kindModifiers: string; - } - - /** - * A group of text spans, all in 'file'. - */ - export interface SpanGroup { - /** The file to which the spans apply */ - file: string; - /** The text spans in this group */ - locs: TextSpan[]; - } - - export interface RenameResponseBody { - /** - * Information about the item to be renamed. - */ - info: RenameInfo; - - /** - * An array of span groups (one per file) that refer to the item to be renamed. - */ - locs: SpanGroup[]; - } - - /** - * Rename response message. - */ - export interface RenameResponse extends Response { - body?: RenameResponseBody; - } - - export interface ExternalFile { - fileName: string; - scriptKind?: ScriptKind; - hasMixedContent?: boolean; - content?: string; - } - - export interface ExternalProject { - projectFileName: string; - rootFiles: ExternalFile[]; -<<<<<<< HEAD - options: ExternalProjectCompilerOptions; - typingOptions?: TypingOptions; - } - - /** - * For external projects, some of the project settings are sent together with - * compiler settings. - */ - export interface ExternalProjectCompilerOptions extends CompilerOptions { - compileOnSave?: boolean; -======= - options: CompilerOptions; - typingOptions?: TypingOptions; ->>>>>>> d736db3b01a5f4f4215c17845deb3ae09cf28787 - } - - export interface ProjectVersionInfo { - projectName: string; - isInferred: boolean; - version: number; - options: CompilerOptions; - } - - export interface ProjectChanges { - added: string[]; - removed: string[]; - } - - /** - * Describes set of files in the project. - * info might be omitted in case of inferred projects - * if files is set - then this is the entire set of files in the project - * if changes is set - then this is the set of changes that should be applied to existing project - * otherwise - assume that nothing is changed - */ - export interface ProjectFiles { - info?: ProjectVersionInfo; - files?: string[]; - changes?: ProjectChanges; - } - - export interface ChangedOpenFile { - fileName: string; - changes: ts.TextChange[]; - } - - /** - * Editor options - */ - export interface EditorOptions { - - /** Number of spaces for each tab. Default value is 4. */ - tabSize?: number; - - /** Number of spaces to indent during formatting. Default value is 4. */ - indentSize?: number; - - /** Number of additional spaces to indent during formatting to preserve base indentation (ex. script block indentation). Default value is 0. */ - baseIndentSize?: number; - - /** The new line character to be used. Default value is the OS line delimiter. */ - newLineCharacter?: string; - - /** Whether tabs should be converted to spaces. Default value is true. */ - convertTabsToSpaces?: boolean; - } - - /** - * Format options - */ - export interface FormatOptions extends EditorOptions { - - /** Defines space handling after a comma delimiter. Default value is true. */ - insertSpaceAfterCommaDelimiter?: boolean; - - /** Defines space handling after a semicolon in a for statement. Default value is true */ - insertSpaceAfterSemicolonInForStatements?: boolean; - - /** Defines space handling after a binary operator. Default value is true. */ - insertSpaceBeforeAndAfterBinaryOperators?: boolean; - - /** Defines space handling after keywords in control flow statement. Default value is true. */ - insertSpaceAfterKeywordsInControlFlowStatements?: boolean; - - /** Defines space handling after function keyword for anonymous functions. Default value is false. */ - insertSpaceAfterFunctionKeywordForAnonymousFunctions?: boolean; - - /** Defines space handling after opening and before closing non empty parenthesis. Default value is false. */ - insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis?: boolean; - - /** Defines space handling after opening and before closing non empty brackets. Default value is false. */ - insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets?: boolean; - - /** Defines whether an open brace is put onto a new line for functions or not. Default value is false. */ - placeOpenBraceOnNewLineForFunctions?: boolean; - - /** Defines whether an open brace is put onto a new line for control blocks or not. Default value is false. */ - placeOpenBraceOnNewLineForControlBlocks?: boolean; - } - - /** - * Information found in a configure request. - */ - export interface ConfigureRequestArguments { - - /** - * Information about the host, for example 'Emacs 24.4' or - * 'Sublime Text version 3075' - */ - hostInfo?: string; - - /** - * If present, tab settings apply only to this file. - */ - file?: string; - - /** - * The format options to use during formatting and other code editing features. - */ - formatOptions?: FormatOptions; - - /** - * If set to true - then all loose files will land into one inferred project - */ - useOneInferredProject?: boolean; - } - - /** - * Configure request; value of command field is "configure". Specifies - * host information, such as host type, tab size, and indent size. - */ - export interface ConfigureRequest extends Request { - arguments: ConfigureRequestArguments; - } - - /** - * Response to "configure" request. This is just an acknowledgement, so - * no body field is required. - */ - export interface ConfigureResponse extends Response { - } - - /** - * Information found in an "open" request. - */ - export interface OpenRequestArgs extends FileRequestArgs { - /** - * Used when a version of the file content is known to be more up to date than the one on disk. - * Then the known content will be used upon opening instead of the disk copy - */ - fileContent?: string; - /** - * Used to specify the script kind of the file explicitly. It could be one of the following: - * "TS", "JS", "TSX", "JSX" - */ - scriptKindName?: "TS" | "JS" | "TSX" | "JSX"; - } - - /** - * Open request; value of command field is "open". Notify the - * server that the client has file open. The server will not - * monitor the filesystem for changes in this file and will assume - * that the client is updating the server (using the change and/or - * reload messages) when the file changes. Server does not currently - * send a response to an open request. - */ - export interface OpenRequest extends Request { - arguments: OpenRequestArgs; - } - - type OpenExternalProjectArgs = ExternalProject; - - export interface OpenExternalProjectRequest extends Request { - arguments: OpenExternalProjectArgs; - } - - export interface CloseExternalProjectRequestArgs { - projectFileName: string; - } - - export interface OpenExternalProjectsRequest extends Request { - arguments: OpenExternalProjectsArgs; - } - - export interface OpenExternalProjectsArgs { - projects: ExternalProject[]; - } - - export interface CloseExternalProjectRequest extends Request { - arguments: CloseExternalProjectRequestArgs; - } - - export interface SynchronizeProjectListRequest extends Request { - arguments: SynchronizeProjectListRequestArgs; - } - - export interface SynchronizeProjectListRequestArgs { - knownProjects: protocol.ProjectVersionInfo[]; - } - - export interface ApplyChangedToOpenFilesRequest extends Request { - arguments: ApplyChangedToOpenFilesRequestArgs; - } - - export interface ApplyChangedToOpenFilesRequestArgs { - openFiles?: ExternalFile[]; - changedFiles?: ChangedOpenFile[]; - closedFiles?: string[]; - } - - export interface SetCompilerOptionsForInferredProjectsArgs { - options: CompilerOptions; - } - - export interface SetCompilerOptionsForInferredProjectsRequest extends Request { - arguments: SetCompilerOptionsForInferredProjectsArgs; - } - - /** - * Exit request; value of command field is "exit". Ask the server process - * to exit. - */ - export interface ExitRequest extends Request { - } - - /** - * Close request; value of command field is "close". Notify the - * server that the client has closed a previously open file. If - * file is still referenced by open files, the server will resume - * monitoring the filesystem for changes to file. Server does not - * currently send a response to a close request. - */ - export interface CloseRequest extends FileRequest { - } - - export interface CompileOnSaveAffectedFileListRequest extends FileRequest { - } - - export interface CompileOnSaveEmitFileRequest extends FileRequest { - args: CompileOnSaveEmitFileRequestArgs; - } - - export interface CompileOnSaveEmitFileRequestArgs extends FileRequestArgs { - forced?: boolean; - } - - /** - * Quickinfo request; value of command field is - * "quickinfo". Return response giving a quick type and - * documentation string for the symbol found in file at location - * line, col. - */ - export interface QuickInfoRequest extends FileLocationRequest { - } - - /** - * Body of QuickInfoResponse. - */ - export interface QuickInfoResponseBody { - /** - * The symbol's kind (such as 'className' or 'parameterName' or plain 'text'). - */ - kind: string; - - /** - * Optional modifiers for the kind (such as 'public'). - */ - kindModifiers: string; - - /** - * Starting file location of symbol. - */ - start: Location; - - /** - * One past last character of symbol. - */ - end: Location; - - /** - * Type and kind of symbol. - */ - displayString: string; - - /** - * Documentation associated with symbol. - */ - documentation: string; - } - - /** - * Quickinfo response message. - */ - export interface QuickInfoResponse extends Response { - body?: QuickInfoResponseBody; - } - - /** - * Arguments for format messages. - */ - export interface FormatRequestArgs extends FileLocationRequestArgs { - /** - * Last line of range for which to format text in file. - */ - endLine: number; - - /** - * Character offset on last line of range for which to format text in file. - */ - endOffset: number; - - endPosition?: number; - options?: ts.FormatCodeOptions; - } - - /** - * Format request; value of command field is "format". Return - * response giving zero or more edit instructions. The edit - * instructions will be sorted in file order. Applying the edit - * instructions in reverse to file will result in correctly - * reformatted text. - */ - export interface FormatRequest extends FileLocationRequest { - arguments: FormatRequestArgs; - } - - /** - * Object found in response messages defining an editing - * instruction for a span of text in source code. The effect of - * this instruction is to replace the text starting at start and - * ending one character before end with newText. For an insertion, - * the text span is empty. For a deletion, newText is empty. - */ - export interface CodeEdit { - /** - * First character of the text span to edit. - */ - start: Location; - - /** - * One character past last character of the text span to edit. - */ - end: Location; - - /** - * Replace the span defined above with this string (may be - * the empty string). - */ - newText: string; - } - - /** - * Format and format on key response message. - */ - export interface FormatResponse extends Response { - body?: CodeEdit[]; - } - - /** - * Arguments for format on key messages. - */ - export interface FormatOnKeyRequestArgs extends FileLocationRequestArgs { - /** - * Key pressed (';', '\n', or '}'). - */ - key: string; - - options?: ts.FormatCodeOptions; - } - - /** - * Format on key request; value of command field is - * "formatonkey". Given file location and key typed (as string), - * return response giving zero or more edit instructions. The - * edit instructions will be sorted in file order. Applying the - * edit instructions in reverse to file will result in correctly - * reformatted text. - */ - export interface FormatOnKeyRequest extends FileLocationRequest { - arguments: FormatOnKeyRequestArgs; - } - - /** - * Arguments for completions messages. - */ - export interface CompletionsRequestArgs extends FileLocationRequestArgs { - /** - * Optional prefix to apply to possible completions. - */ - prefix?: string; - } - - /** - * Completions request; value of command field is "completions". - * Given a file location (file, line, col) and a prefix (which may - * be the empty string), return the possible completions that - * begin with prefix. - */ - export interface CompletionsRequest extends FileLocationRequest { - arguments: CompletionsRequestArgs; - } - - /** - * Arguments for completion details request. - */ - export interface CompletionDetailsRequestArgs extends FileLocationRequestArgs { - /** - * Names of one or more entries for which to obtain details. - */ - entryNames: string[]; - } - - /** - * Completion entry details request; value of command field is - * "completionEntryDetails". Given a file location (file, line, - * col) and an array of completion entry names return more - * detailed information for each completion entry. - */ - export interface CompletionDetailsRequest extends FileLocationRequest { - arguments: CompletionDetailsRequestArgs; - } - - /** - * Part of a symbol description. - */ - export interface SymbolDisplayPart { - /** - * Text of an item describing the symbol. - */ - text: string; - - /** - * The symbol's kind (such as 'className' or 'parameterName' or plain 'text'). - */ - kind: string; - } - - /** - * An item found in a completion response. - */ - export interface CompletionEntry { - /** - * The symbol's name. - */ - name: string; - /** - * The symbol's kind (such as 'className' or 'parameterName'). - */ - kind: string; - /** - * Optional modifiers for the kind (such as 'public'). - */ - kindModifiers: string; - /** - * A string that is used for comparing completion items so that they can be ordered. This - * is often the same as the name but may be different in certain circumstances. - */ - sortText: string; - } - - /** - * Additional completion entry details, available on demand - */ - export interface CompletionEntryDetails { - /** - * The symbol's name. - */ - name: string; - /** - * The symbol's kind (such as 'className' or 'parameterName'). - */ - kind: string; - /** - * Optional modifiers for the kind (such as 'public'). - */ - kindModifiers: string; - /** - * Display parts of the symbol (similar to quick info). - */ - displayParts: SymbolDisplayPart[]; - - /** - * Documentation strings for the symbol. - */ - documentation: SymbolDisplayPart[]; - } - - export interface CompletionsResponse extends Response { - body?: CompletionEntry[]; - } - - export interface CompletionDetailsResponse extends Response { - body?: CompletionEntryDetails[]; - } - - /** - * Signature help information for a single parameter - */ - export interface SignatureHelpParameter { - - /** - * The parameter's name - */ - name: string; - - /** - * Documentation of the parameter. - */ - documentation: SymbolDisplayPart[]; - - /** - * Display parts of the parameter. - */ - displayParts: SymbolDisplayPart[]; - - /** - * Whether the parameter is optional or not. - */ - isOptional: boolean; - } - - /** - * Represents a single signature to show in signature help. - */ - export interface SignatureHelpItem { - - /** - * Whether the signature accepts a variable number of arguments. - */ - isVariadic: boolean; - - /** - * The prefix display parts. - */ - prefixDisplayParts: SymbolDisplayPart[]; - - /** - * The suffix display parts. - */ - suffixDisplayParts: SymbolDisplayPart[]; - - /** - * The separator display parts. - */ - separatorDisplayParts: SymbolDisplayPart[]; - - /** - * The signature helps items for the parameters. - */ - parameters: SignatureHelpParameter[]; - - /** - * The signature's documentation - */ - documentation: SymbolDisplayPart[]; - } - - /** - * Signature help items found in the response of a signature help request. - */ - export interface SignatureHelpItems { - - /** - * The signature help items. - */ - items: SignatureHelpItem[]; - - /** - * The span for which signature help should appear on a signature - */ - applicableSpan: TextSpan; - - /** - * The item selected in the set of available help items. - */ - selectedItemIndex: number; - - /** - * The argument selected in the set of parameters. - */ - argumentIndex: number; - - /** - * The argument count - */ - argumentCount: number; - } - - /** - * Arguments of a signature help request. - */ - export interface SignatureHelpRequestArgs extends FileLocationRequestArgs { - } - - /** - * Signature help request; value of command field is "signatureHelp". - * Given a file location (file, line, col), return the signature - * help. - */ - export interface SignatureHelpRequest extends FileLocationRequest { - arguments: SignatureHelpRequestArgs; - } - - /** - * Response object for a SignatureHelpRequest. - */ - export interface SignatureHelpResponse extends Response { - body?: SignatureHelpItems; - } - - /** - * Synchronous request for semantic diagnostics of one file. - */ - export interface SemanticDiagnosticsSyncRequest extends FileRequest { - arguments: SemanticDiagnosticsSyncRequestArgs; - } - - export interface SemanticDiagnosticsSyncRequestArgs extends FileRequestArgs { - includeLinePosition?: boolean; - } - - /** - * Response object for synchronous sematic diagnostics request. - */ - export interface SemanticDiagnosticsSyncResponse extends Response { - body?: Diagnostic[] | DiagnosticWithLinePosition[]; - } - - /** - * Synchronous request for syntactic diagnostics of one file. - */ - export interface SyntacticDiagnosticsSyncRequest extends FileRequest { - arguments: SyntacticDiagnosticsSyncRequestArgs; - } - - export interface SyntacticDiagnosticsSyncRequestArgs extends FileRequestArgs { - includeLinePosition?: boolean; - } - - /** - * Response object for synchronous syntactic diagnostics request. - */ - export interface SyntacticDiagnosticsSyncResponse extends Response { - body?: Diagnostic[] | DiagnosticWithLinePosition[]; - } - - /** - * Arguments for GeterrForProject request. - */ - export interface GeterrForProjectRequestArgs { - /** - * the file requesting project error list - */ - file: string; - - /** - * Delay in milliseconds to wait before starting to compute - * errors for the files in the file list - */ - delay: number; - } - - /** - * GeterrForProjectRequest request; value of command field is - * "geterrForProject". It works similarly with 'Geterr', only - * it request for every file in this project. - */ - export interface GeterrForProjectRequest extends Request { - arguments: GeterrForProjectRequestArgs; - } - - /** - * Arguments for geterr messages. - */ - export interface GeterrRequestArgs { - /** - * List of file names for which to compute compiler errors. - * The files will be checked in list order. - */ - files: string[]; - - /** - * Delay in milliseconds to wait before starting to compute - * errors for the files in the file list - */ - delay: number; - } - - /** - * Geterr request; value of command field is "geterr". Wait for - * delay milliseconds and then, if during the wait no change or - * reload messages have arrived for the first file in the files - * list, get the syntactic errors for the file, field requests, - * and then get the semantic errors for the file. Repeat with a - * smaller delay for each subsequent file on the files list. Best - * practice for an editor is to send a file list containing each - * file that is currently visible, in most-recently-used order. - */ - export interface GeterrRequest extends Request { - arguments: GeterrRequestArgs; - } - - /** - * Item of diagnostic information found in a DiagnosticEvent message. - */ - export interface Diagnostic { - /** - * Starting file location at which text applies. - */ - start: Location; - - /** - * The last file location at which the text applies. - */ - end: Location; - - /** - * Text of diagnostic message. - */ - text: string; - } - - export interface DiagnosticEventBody { - /** - * The file for which diagnostic information is reported. - */ - file: string; - - /** - * An array of diagnostic information items. - */ - diagnostics: Diagnostic[]; - } - - /** - * Event message for "syntaxDiag" and "semanticDiag" event types. - * These events provide syntactic and semantic errors for a file. - */ - export interface DiagnosticEvent extends Event { - body?: DiagnosticEventBody; - } - - export interface ConfigFileDiagnosticEventBody { - /** - * The file which trigged the searching and error-checking of the config file - */ - triggerFile: string; - - /** - * The name of the found config file. - */ - configFile: string; - - /** - * An arry of diagnostic information items for the found config file. - */ - diagnostics: Diagnostic[]; - } - - /** - * Event message for "configFileDiag" event type. - * This event provides errors for a found config file. - */ - export interface ConfigFileDiagnosticEvent extends Event { - body?: ConfigFileDiagnosticEventBody; - event: "configFileDiag"; - } - - /** - * Arguments for reload request. - */ - export interface ReloadRequestArgs extends FileRequestArgs { - /** - * Name of temporary file from which to reload file - * contents. May be same as file. - */ - tmpfile: string; - } - - /** - * Reload request message; value of command field is "reload". - * Reload contents of file with name given by the 'file' argument - * from temporary file with name given by the 'tmpfile' argument. - * The two names can be identical. - */ - export interface ReloadRequest extends FileRequest { - arguments: ReloadRequestArgs; - } - - /** - * Response to "reload" request. This is just an acknowledgement, so - * no body field is required. - */ - export interface ReloadResponse extends Response { - } - - /** - * Arguments for saveto request. - */ - export interface SavetoRequestArgs extends FileRequestArgs { - /** - * Name of temporary file into which to save server's view of - * file contents. - */ - tmpfile: string; - } - - /** - * Saveto request message; value of command field is "saveto". - * For debugging purposes, save to a temporaryfile (named by - * argument 'tmpfile') the contents of file named by argument - * 'file'. The server does not currently send a response to a - * "saveto" request. - */ - export interface SavetoRequest extends FileRequest { - arguments: SavetoRequestArgs; - } - - /** - * Arguments for navto request message. - */ - export interface NavtoRequestArgs extends FileRequestArgs { - /** - * Search term to navigate to from current location; term can - * be '.*' or an identifier prefix. - */ - searchValue: string; - /** - * Optional limit on the number of items to return. - */ - maxResultCount?: number; - - projectFileName?: string; - } - - /** - * Navto request message; value of command field is "navto". - * Return list of objects giving file locations and symbols that - * match the search term given in argument 'searchTerm'. The - * context for the search is given by the named file. - */ - export interface NavtoRequest extends FileRequest { - arguments: NavtoRequestArgs; - } - - /** - * An item found in a navto response. - */ - export interface NavtoItem { - /** - * The symbol's name. - */ - name: string; - - /** - * The symbol's kind (such as 'className' or 'parameterName'). - */ - kind: string; - - /** - * exact, substring, or prefix. - */ - matchKind?: string; - - /** - * If this was a case sensitive or insensitive match. - */ - isCaseSensitive?: boolean; - - /** - * Optional modifiers for the kind (such as 'public'). - */ - kindModifiers?: string; - - /** - * The file in which the symbol is found. - */ - file: string; - - /** - * The location within file at which the symbol is found. - */ - start: Location; - - /** - * One past the last character of the symbol. - */ - end: Location; - - /** - * Name of symbol's container symbol (if any); for example, - * the class name if symbol is a class member. - */ - containerName?: string; - - /** - * Kind of symbol's container symbol (if any). - */ - containerKind?: string; - } - - /** - * Navto response message. Body is an array of navto items. Each - * item gives a symbol that matched the search term. - */ - export interface NavtoResponse extends Response { - body?: NavtoItem[]; - } - - /** - * Arguments for change request message. - */ - export interface ChangeRequestArgs extends FormatRequestArgs { - /** - * Optional string to insert at location (file, line, offset). - */ - insertString?: string; - } - - /** - * Change request message; value of command field is "change". - * Update the server's view of the file named by argument 'file'. - * Server does not currently send a response to a change request. - */ - export interface ChangeRequest extends FileLocationRequest { - arguments: ChangeRequestArgs; - } - - /** - * Response to "brace" request. - */ - export interface BraceResponse extends Response { - body?: TextSpan[]; - } - - /** - * Brace matching request; value of command field is "brace". - * Return response giving the file locations of matching braces - * found in file at location line, offset. - */ - export interface BraceRequest extends FileLocationRequest { - } - - /** - * NavBar items request; value of command field is "navbar". - * Return response giving the list of navigation bar entries - * extracted from the requested file. - */ - export interface NavBarRequest extends FileRequest { - } - - export interface NavigationBarItem { - /** - * The item's display text. - */ - text: string; - - /** - * The symbol's kind (such as 'className' or 'parameterName'). - */ - kind: string; - - /** - * Optional modifiers for the kind (such as 'public'). - */ - kindModifiers?: string; - - /** - * The definition locations of the item. - */ - spans: TextSpan[]; - - /** - * Optional children. - */ - childItems?: NavigationBarItem[]; - - /** - * Number of levels deep this item should appear. - */ - indent: number; - } - - export interface NavBarResponse extends Response { - body?: NavigationBarItem[]; - } -}