mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-04 16:13:38 -05:00
Make language service optional for a project
This commit is contained in:
@@ -637,7 +637,15 @@ namespace ts {
|
||||
const supportedExtensions = getSupportedExtensions(options);
|
||||
Debug.assert(indexOf(supportedExtensions, ".ts") < indexOf(supportedExtensions, ".d.ts"), "Changed priority of extensions to pick");
|
||||
|
||||
const potentialFiles = host.readDirectory(basePath, supportedExtensions, exclude);
|
||||
const potentialFiles: string[] = [];
|
||||
if (host.readDirectoryWithMultipleExtensions) {
|
||||
addRange(potentialFiles, host.readDirectoryWithMultipleExtensions(basePath, supportedExtensions, exclude));
|
||||
}
|
||||
else {
|
||||
for (const extension of supportedExtensions) {
|
||||
addRange(potentialFiles, host.readDirectory(basePath, extension, exclude));
|
||||
}
|
||||
}
|
||||
// Get files of supported extensions in their order of resolution
|
||||
for (const extension of supportedExtensions) {
|
||||
for (const fileName of potentialFiles) {
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace ts {
|
||||
/* @internal */ export let emitTime = 0;
|
||||
/* @internal */ export let ioReadTime = 0;
|
||||
/* @internal */ export let ioWriteTime = 0;
|
||||
/* @internal */ export const maxProgramSizeForNonTsFiles = 20 * 1024 * 1024;
|
||||
|
||||
/** The version of the TypeScript compiler release */
|
||||
|
||||
@@ -696,6 +697,7 @@ namespace ts {
|
||||
let diagnosticsProducingTypeChecker: TypeChecker;
|
||||
let noDiagnosticsTypeChecker: TypeChecker;
|
||||
let classifiableNames: Map<string>;
|
||||
let programSizeLimitExceeded = false;
|
||||
let programSizeForNonTsFiles = 0;
|
||||
|
||||
let skipDefaultLib = options.noLib;
|
||||
@@ -792,6 +794,11 @@ namespace ts {
|
||||
|
||||
return program;
|
||||
|
||||
function exceedProgramSizeLimit() {
|
||||
return !options.disableSizeLimit && programSizeLimitExceeded;
|
||||
}
|
||||
|
||||
|
||||
function getCommonSourceDirectory() {
|
||||
if (typeof commonSourceDirectory === "undefined") {
|
||||
if (options.rootDir && checkSourceFilesBelongToPath(files, options.rootDir)) {
|
||||
@@ -1417,7 +1424,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
if (diagnostic) {
|
||||
if (diagnostic && !exceedProgramSizeLimit()) {
|
||||
if (refFile !== undefined && refEnd !== undefined && refPos !== undefined) {
|
||||
fileProcessingDiagnostics.add(createFileDiagnostic(refFile, refPos, refEnd - refPos, diagnostic, ...diagnosticArgument));
|
||||
}
|
||||
@@ -1454,25 +1461,9 @@ namespace ts {
|
||||
return file;
|
||||
}
|
||||
|
||||
if (!options.disableSizeLimit) {
|
||||
if (programSizeForNonTsFiles === -1) {
|
||||
return;
|
||||
}
|
||||
if (programSizeForNonTsFiles > maxProgramSizeForNonTsFiles) {
|
||||
// If the program size limit was reached when processing a file, this file is
|
||||
// likely in the problematic folder than contains too many files.
|
||||
// Normally the folder is one level down from the commonSourceDirectory, for example,
|
||||
// if the commonSourceDirectory is "/src/", and the last processed path was "/src/node_modules/a/b.js",
|
||||
// we should show in the error message "/src/node_modules/".
|
||||
const commonSourceDirectory = getCommonSourceDirectory();
|
||||
let rootLevelDirectory = path.substring(0, Math.max(commonSourceDirectory.length, path.indexOf(directorySeparator, commonSourceDirectory.length)));
|
||||
if (rootLevelDirectory[rootLevelDirectory.length - 1] !== directorySeparator) {
|
||||
rootLevelDirectory += directorySeparator;
|
||||
}
|
||||
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Too_many_JavaScript_files_in_the_project_Consider_specifying_the_exclude_setting_in_project_configuration_to_limit_included_source_folders_The_likely_folder_to_exclude_is_0_To_disable_the_project_size_limit_set_the_disableSizeLimit_compiler_option_to_true, rootLevelDirectory));
|
||||
programSizeForNonTsFiles = -1;
|
||||
return;
|
||||
}
|
||||
const isNonTsFile = !hasTypeScriptFileExtension(fileName);
|
||||
if (isNonTsFile && exceedProgramSizeLimit()) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// We haven't looked for this file, do so now and cache result
|
||||
@@ -1488,6 +1479,21 @@ namespace ts {
|
||||
|
||||
if (!options.disableSizeLimit && file && file.text && !hasTypeScriptFileExtension(file.fileName)) {
|
||||
programSizeForNonTsFiles += file.text.length;
|
||||
if (programSizeForNonTsFiles > maxProgramSizeForNonTsFiles) {
|
||||
// If the program size limit was reached when processing a file, this file is
|
||||
// likely in the problematic folder than contains too many files.
|
||||
// Normally the folder is one level down from the commonSourceDirectory, for example,
|
||||
// if the commonSourceDirectory is "/src/", and the last processed path was "/src/node_modules/a/b.js",
|
||||
// we should show in the error message "/src/node_modules/".
|
||||
const commonSourceDirectory = getCommonSourceDirectory();
|
||||
let rootLevelDirectory = path.substring(0, Math.max(commonSourceDirectory.length, path.indexOf(directorySeparator, commonSourceDirectory.length)));
|
||||
if (rootLevelDirectory[rootLevelDirectory.length - 1] !== directorySeparator) {
|
||||
rootLevelDirectory += directorySeparator;
|
||||
}
|
||||
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Too_many_JavaScript_files_in_the_project_Consider_specifying_the_exclude_setting_in_project_configuration_to_limit_included_source_folders_The_likely_folder_to_exclude_is_0_To_disable_the_project_size_limit_set_the_disableSizeLimit_compiler_option_to_true, rootLevelDirectory));
|
||||
programSizeLimitExceeded = true;
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
filesByName.set(path, file);
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace ts {
|
||||
useCaseSensitiveFileNames: boolean;
|
||||
write(s: string): void;
|
||||
readFile(path: string, encoding?: string): string;
|
||||
getFileSize?(path: string): number;
|
||||
writeFile(path: string, data: string, writeByteOrderMark?: boolean): void;
|
||||
watchFile?(path: Path, callback: FileWatcherCallback): FileWatcher;
|
||||
watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
|
||||
@@ -20,6 +21,7 @@ namespace ts {
|
||||
getExecutingFilePath(): string;
|
||||
getCurrentDirectory(): string;
|
||||
readDirectory(path: string, extension?: string, exclude?: string[]): string[];
|
||||
readDirectoryWithMultipleExtensions?(path: string, extensions: string[], exclude?: string[]): string[];
|
||||
getMemoryUsage?(): number;
|
||||
exit(exitCode?: number): void;
|
||||
}
|
||||
@@ -489,10 +491,32 @@ namespace ts {
|
||||
return fileSystemEntryExists(path, FileSystemEntryKind.Directory);
|
||||
}
|
||||
|
||||
function readDirectory(path: string, extension?: string | string[], exclude?: string[]): string[] {
|
||||
function visitDirectory(path: string, extension: string | string[], exclude: string[]) {
|
||||
const result: string[] = [];
|
||||
exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s)));
|
||||
visitDirectory(path);
|
||||
const files = _fs.readdirSync(path || ".").sort();
|
||||
const directories: string[] = [];
|
||||
for (const current of files) {
|
||||
const name = combinePaths(path, current);
|
||||
if (!contains(exclude, getCanonicalPath(name))) {
|
||||
// fs.statSync would throw an exception if the file is a symlink
|
||||
// whose linked file doesn't exist.
|
||||
try {
|
||||
const stat = _fs.statSync(name);
|
||||
if (stat.isFile()) {
|
||||
if (checkExtension(name)) {
|
||||
result.push(name);
|
||||
}
|
||||
}
|
||||
else if (stat.isDirectory()) {
|
||||
directories.push(name);
|
||||
}
|
||||
}
|
||||
catch (e) { }
|
||||
}
|
||||
}
|
||||
for (const current of directories) {
|
||||
visitDirectory(current, extension, exclude);
|
||||
}
|
||||
return result;
|
||||
|
||||
function checkExtension(name: string) {
|
||||
@@ -502,37 +526,20 @@ namespace ts {
|
||||
if (typeof extension === "string") {
|
||||
return fileExtensionIs(name, extension);
|
||||
}
|
||||
if (typeof extension === "string[]") {
|
||||
else {
|
||||
return forEach(extension, ext => fileExtensionIs(name, ext));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function visitDirectory(path: string) {
|
||||
const files = _fs.readdirSync(path || ".").sort();
|
||||
const directories: string[] = [];
|
||||
for (const current of files) {
|
||||
const name = combinePaths(path, current);
|
||||
if (!contains(exclude, getCanonicalPath(name))) {
|
||||
// fs.statSync would throw an exception if the file is a symlink
|
||||
// whose linked file doesn't exist.
|
||||
try {
|
||||
const stat = _fs.statSync(name);
|
||||
if (stat.isFile()) {
|
||||
if (checkExtension(name)) {
|
||||
result.push(name);
|
||||
}
|
||||
}
|
||||
else if (stat.isDirectory()) {
|
||||
directories.push(name);
|
||||
}
|
||||
}
|
||||
catch (e) { }
|
||||
}
|
||||
}
|
||||
for (const current of directories) {
|
||||
visitDirectory(current);
|
||||
}
|
||||
}
|
||||
function readDirectoryWithMultipleExtensions(path: string, extensions: string[], exclude?: string[]): string[] {
|
||||
exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s)));
|
||||
return visitDirectory(path, extensions, exclude);
|
||||
}
|
||||
|
||||
function readDirectory(path: string, extension?: string, exclude?: string[]): string[] {
|
||||
exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s)));
|
||||
return visitDirectory(path, extension, exclude);
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -597,12 +604,23 @@ namespace ts {
|
||||
return process.cwd();
|
||||
},
|
||||
readDirectory,
|
||||
readDirectoryWithMultipleExtensions,
|
||||
getMemoryUsage() {
|
||||
if (global.gc) {
|
||||
global.gc();
|
||||
}
|
||||
return process.memoryUsage().heapUsed;
|
||||
},
|
||||
getFileSize(path) {
|
||||
try {
|
||||
const stat = _fs.statSync(path);
|
||||
if (stat.isFile()) {
|
||||
return stat.size;
|
||||
}
|
||||
}
|
||||
catch (e) { }
|
||||
return 0;
|
||||
},
|
||||
exit(exitCode?: number): void {
|
||||
process.exit(exitCode);
|
||||
}
|
||||
|
||||
@@ -1580,7 +1580,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
export interface ParseConfigHost {
|
||||
readDirectory(rootDir: string, extension: string | string[], exclude: string[]): string[];
|
||||
readDirectory(rootDir: string, extension: string, exclude: string[]): string[];
|
||||
readDirectoryWithMultipleExtensions?(rootDir: string, extensions: string[], exclude: string[]): string[];
|
||||
}
|
||||
|
||||
export interface WriteFileCallback {
|
||||
@@ -2440,7 +2441,7 @@ namespace ts {
|
||||
allowJs?: boolean;
|
||||
noImplicitUseStrict?: boolean;
|
||||
disableSizeLimit?: boolean;
|
||||
lib?: string[];
|
||||
lib?: string[];
|
||||
/* @internal */ stripInternal?: boolean;
|
||||
|
||||
// Skip checking lib.d.ts to help speed up tests.
|
||||
|
||||
@@ -2870,6 +2870,4 @@ namespace ts {
|
||||
export function isParameterPropertyDeclaration(node: ParameterDeclaration): boolean {
|
||||
return node.flags & NodeFlags.AccessibilityModifier && node.parent.kind === SyntaxKind.Constructor && isClassLike(node.parent.parent);
|
||||
}
|
||||
|
||||
export const maxProgramSizeForNonTsFiles = 20 * 1024 * 1024;
|
||||
}
|
||||
|
||||
@@ -347,12 +347,29 @@ namespace ts.server {
|
||||
/** Used for configured projects which may have multiple open roots */
|
||||
openRefCount = 0;
|
||||
|
||||
constructor(public projectService: ProjectService, public projectOptions?: ProjectOptions) {
|
||||
constructor(
|
||||
public projectService: ProjectService,
|
||||
public projectOptions?: ProjectOptions,
|
||||
public languageServiceDiabled?: boolean) {
|
||||
if (projectOptions && projectOptions.files) {
|
||||
// If files are listed explicitly, allow all extensions
|
||||
projectOptions.compilerOptions.allowNonTsExtensions = true;
|
||||
}
|
||||
this.compilerService = new CompilerService(this, projectOptions && projectOptions.compilerOptions);
|
||||
if (!languageServiceDiabled) {
|
||||
this.compilerService = new CompilerService(this, projectOptions && projectOptions.compilerOptions);
|
||||
}
|
||||
}
|
||||
|
||||
enableLanguageService() {
|
||||
// if the language service was disabled, we should re-initiate the compiler service
|
||||
if (this.languageServiceDiabled) {
|
||||
this.compilerService = new CompilerService(this, this.projectOptions && this.projectOptions.compilerOptions);
|
||||
}
|
||||
this.languageServiceDiabled = false;
|
||||
}
|
||||
|
||||
disableLanguageService() {
|
||||
this.languageServiceDiabled = true;
|
||||
}
|
||||
|
||||
addOpenRef() {
|
||||
@@ -369,19 +386,36 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
getRootFiles() {
|
||||
if (this.languageServiceDiabled) {
|
||||
// When the languageService was disabled, only return file list if it is a configured project
|
||||
return this.projectOptions ? this.projectOptions.files : undefined;
|
||||
}
|
||||
|
||||
return this.compilerService.host.roots.map(info => info.fileName);
|
||||
}
|
||||
|
||||
getFileNames() {
|
||||
if (this.languageServiceDiabled) {
|
||||
return this.projectOptions ? this.projectOptions.files : undefined;
|
||||
}
|
||||
|
||||
const sourceFiles = this.program.getSourceFiles();
|
||||
return sourceFiles.map(sourceFile => sourceFile.fileName);
|
||||
}
|
||||
|
||||
getSourceFile(info: ScriptInfo) {
|
||||
if (this.languageServiceDiabled) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return this.filenameToSourceFile[info.fileName];
|
||||
}
|
||||
|
||||
getSourceFileFromName(filename: string, requireOpen?: boolean) {
|
||||
if (this.languageServiceDiabled) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const info = this.projectService.getScriptInfo(filename);
|
||||
if (info) {
|
||||
if ((!requireOpen) || info.isOpen) {
|
||||
@@ -391,15 +425,30 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
isRoot(info: ScriptInfo) {
|
||||
if (this.languageServiceDiabled) {
|
||||
if (!this.projectOptions) {
|
||||
return undefined;
|
||||
}
|
||||
return forEach(this.projectOptions.files, file => toPath(file, file, createGetCanonicalFileName(this.projectService.host.useCaseSensitiveFileNames)) === info.path);
|
||||
}
|
||||
|
||||
return this.compilerService.host.roots.some(root => root === info);
|
||||
}
|
||||
|
||||
removeReferencedFile(info: ScriptInfo) {
|
||||
if (this.languageServiceDiabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.compilerService.host.removeReferencedFile(info);
|
||||
this.updateGraph();
|
||||
}
|
||||
|
||||
updateFileMap() {
|
||||
if (this.languageServiceDiabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.filenameToSourceFile = {};
|
||||
const sourceFiles = this.program.getSourceFiles();
|
||||
for (let i = 0, len = sourceFiles.length; i < len; i++) {
|
||||
@@ -409,11 +458,19 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
finishGraph() {
|
||||
if (this.languageServiceDiabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateGraph();
|
||||
this.compilerService.languageService.getNavigateToItems(".*");
|
||||
}
|
||||
|
||||
updateGraph() {
|
||||
if (this.languageServiceDiabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.program = this.compilerService.languageService.getProgram();
|
||||
this.updateFileMap();
|
||||
}
|
||||
@@ -424,15 +481,32 @@ namespace ts.server {
|
||||
|
||||
// add a root file to project
|
||||
addRoot(info: ScriptInfo) {
|
||||
if (this.languageServiceDiabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.compilerService.host.addRoot(info);
|
||||
}
|
||||
|
||||
// remove a root file from project
|
||||
removeRoot(info: ScriptInfo) {
|
||||
if (this.languageServiceDiabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.compilerService.host.removeRoot(info);
|
||||
}
|
||||
|
||||
filesToString() {
|
||||
if (this.languageServiceDiabled) {
|
||||
if (this.projectOptions) {
|
||||
let strBuilder = "";
|
||||
ts.forEach(this.projectOptions.files,
|
||||
file => { strBuilder += file + "\n"; });
|
||||
return strBuilder;
|
||||
}
|
||||
}
|
||||
|
||||
let strBuilder = "";
|
||||
ts.forEachValue(this.filenameToSourceFile,
|
||||
sourceFile => { strBuilder += sourceFile.fileName + "\n"; });
|
||||
@@ -443,7 +517,9 @@ namespace ts.server {
|
||||
this.projectOptions = projectOptions;
|
||||
if (projectOptions.compilerOptions) {
|
||||
projectOptions.compilerOptions.allowNonTsExtensions = true;
|
||||
this.compilerService.setCompilerOptions(projectOptions.compilerOptions);
|
||||
if (!this.languageServiceDiabled) {
|
||||
this.compilerService.setCompilerOptions(projectOptions.compilerOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1055,10 +1131,12 @@ namespace ts.server {
|
||||
* @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) {
|
||||
this.log("start openClientFile: " + new Date().getTime());
|
||||
this.openOrUpdateConfiguredProjectForFile(fileName);
|
||||
const info = this.openFile(fileName, /*openedByClient*/ true, fileContent);
|
||||
this.addOpenFile(info);
|
||||
this.printProjects();
|
||||
this.log("end openClientFile: " + new Date().getTime());
|
||||
return info;
|
||||
}
|
||||
|
||||
@@ -1068,6 +1146,7 @@ namespace ts.server {
|
||||
* the tsconfig file content and update the project; otherwise we create a new one.
|
||||
*/
|
||||
openOrUpdateConfiguredProjectForFile(fileName: string) {
|
||||
this.log("start openOrUpdateConfiguredProjectForFile: " + new Date().getTime());
|
||||
const searchPath = ts.normalizePath(getDirectoryPath(fileName));
|
||||
this.log("Search path: " + searchPath, "Info");
|
||||
const configFileName = this.findConfigFile(searchPath);
|
||||
@@ -1091,6 +1170,7 @@ namespace ts.server {
|
||||
else {
|
||||
this.log("No config files found.");
|
||||
}
|
||||
this.log("end openOrUpdateConfiguredProjectForFile: " + new Date().getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1207,53 +1287,49 @@ namespace ts.server {
|
||||
return { succeeded: true, projectOptions };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private exceedTotalNonTsFileSizeLimit(fileNames: string[]) {
|
||||
let totalNonTsFileSize = 0;
|
||||
for (const fileName of fileNames) {
|
||||
if (hasTypeScriptFileExtension(fileName)) {
|
||||
continue;
|
||||
}
|
||||
totalNonTsFileSize += this.host.getFileSize(fileName);
|
||||
if (totalNonTsFileSize > maxProgramSizeForNonTsFiles) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
openConfigFile(configFilename: string, clientFileName?: string): ProjectOpenResult {
|
||||
this.log("start openConfigFile: " + new Date().getTime());
|
||||
const { succeeded, projectOptions, error } = this.configFileToProjectOptions(configFilename);
|
||||
this.log("finish reading config file: " + new Date().getTime());
|
||||
if (!succeeded) {
|
||||
this.log("finish openConfigFile: " + new Date().getTime());
|
||||
return error;
|
||||
}
|
||||
else {
|
||||
const project = this.createProject(configFilename, projectOptions);
|
||||
let programSizeForNonTsFiles = 0;
|
||||
if (!projectOptions.compilerOptions.disableSizeLimit && projectOptions.compilerOptions.allowJs) {
|
||||
if (this.exceedTotalNonTsFileSizeLimit(projectOptions.files)) {
|
||||
const project = this.createProject(configFilename, projectOptions, /*languageServiceDisabled*/ true);
|
||||
|
||||
// As the project openning might not be complete if there are too many files,
|
||||
// therefore to surface the diagnostics we need to make sure the given client file is opened.
|
||||
if (clientFileName) {
|
||||
if (this.host.fileExists(clientFileName)) {
|
||||
const currentClientFileInfo = this.openFile(clientFileName, /*openedByClient*/ true);
|
||||
project.addRoot(currentClientFileInfo);
|
||||
if (!hasTypeScriptFileExtension(currentClientFileInfo.fileName) && currentClientFileInfo.content) {
|
||||
programSizeForNonTsFiles += currentClientFileInfo.content.length;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return { errorMsg: "specified file " + clientFileName + " not found" };
|
||||
// for configured projects with languageService disabled, we only watch its config file,
|
||||
// do not care about the directory changes in the folder.
|
||||
project.projectFileWatcher = this.host.watchFile(
|
||||
toPath(configFilename, configFilename, createGetCanonicalFileName(sys.useCaseSensitiveFileNames)),
|
||||
_ => this.watchedProjectConfigFileChanged(project));
|
||||
return { success: true, project };
|
||||
}
|
||||
}
|
||||
|
||||
const project = this.createProject(configFilename, projectOptions);
|
||||
for (const rootFilename of projectOptions.files) {
|
||||
if (rootFilename === clientFileName) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this.host.fileExists(rootFilename)) {
|
||||
if (projectOptions.compilerOptions.disableSizeLimit) {
|
||||
const info = this.openFile(rootFilename, /*openedByClient*/ false);
|
||||
project.addRoot(info);
|
||||
}
|
||||
else if (programSizeForNonTsFiles <= maxProgramSizeForNonTsFiles) {
|
||||
const info = this.openFile(rootFilename, /*openedByClient*/ false);
|
||||
project.addRoot(info);
|
||||
if (!hasTypeScriptFileExtension(rootFilename)) {
|
||||
programSizeForNonTsFiles += info.content.length;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
const info = this.openFile(rootFilename, /*openedByClient*/ clientFileName == rootFilename);
|
||||
project.addRoot(info);
|
||||
}
|
||||
else {
|
||||
return { errorMsg: "specified file " + rootFilename + " not found" };
|
||||
@@ -1269,6 +1345,7 @@ namespace ts.server {
|
||||
path => this.directoryWatchedForSourceFilesChanged(project, path),
|
||||
/*recursive*/ true
|
||||
);
|
||||
this.log("finish openConfigFile: " + new Date().getTime());
|
||||
return { success: true, project: project };
|
||||
}
|
||||
}
|
||||
@@ -1284,6 +1361,23 @@ namespace ts.server {
|
||||
return error;
|
||||
}
|
||||
else {
|
||||
if (this.exceedTotalNonTsFileSizeLimit(projectOptions.files)) {
|
||||
project.disableLanguageService();
|
||||
project.directoryWatcher.close();
|
||||
project.directoryWatcher = undefined;
|
||||
project.setProjectOptions(projectOptions);
|
||||
return;
|
||||
}
|
||||
|
||||
project.enableLanguageService();
|
||||
if (!project.directoryWatcher) {
|
||||
project.directoryWatcher = this.host.watchDirectory(
|
||||
ts.getDirectoryPath(project.projectFilename),
|
||||
path => this.directoryWatchedForSourceFilesChanged(project, path),
|
||||
/*recursive*/ true
|
||||
);
|
||||
}
|
||||
|
||||
// if the project is too large, the root files might not have been all loaded if the total
|
||||
// program size reached the upper limit. In that case project.projectOptions.files should
|
||||
// be more precise. However this would only happen for configured project.
|
||||
@@ -1330,8 +1424,8 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
|
||||
createProject(projectFilename: string, projectOptions?: ProjectOptions) {
|
||||
const project = new Project(this, projectOptions);
|
||||
createProject(projectFilename: string, projectOptions?: ProjectOptions, languageServiceDisabled?: boolean) {
|
||||
const project = new Project(this, projectOptions, languageServiceDisabled);
|
||||
project.projectFilename = projectFilename;
|
||||
return project;
|
||||
}
|
||||
|
||||
1
src/server/protocol.d.ts
vendored
1
src/server/protocol.d.ts
vendored
@@ -123,6 +123,7 @@ declare namespace ts.server.protocol {
|
||||
* The list of normalized file name in the project, including 'lib.d.ts'
|
||||
*/
|
||||
fileNames?: string[];
|
||||
languageServiceDisabled?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -288,7 +288,7 @@ namespace ts.server {
|
||||
private getDefinition(line: number, offset: number, fileName: string): protocol.FileSpan[] {
|
||||
const file = ts.normalizePath(fileName);
|
||||
const project = this.projectService.getProjectForFile(file);
|
||||
if (!project) {
|
||||
if (!project || project.languageServiceDiabled) {
|
||||
throw Errors.NoProject;
|
||||
}
|
||||
|
||||
@@ -310,7 +310,7 @@ namespace ts.server {
|
||||
private getTypeDefinition(line: number, offset: number, fileName: string): protocol.FileSpan[] {
|
||||
const file = ts.normalizePath(fileName);
|
||||
const project = this.projectService.getProjectForFile(file);
|
||||
if (!project) {
|
||||
if (!project || project.languageServiceDiabled) {
|
||||
throw Errors.NoProject;
|
||||
}
|
||||
|
||||
@@ -333,7 +333,7 @@ namespace ts.server {
|
||||
fileName = ts.normalizePath(fileName);
|
||||
const project = this.projectService.getProjectForFile(fileName);
|
||||
|
||||
if (!project) {
|
||||
if (!project || project.languageServiceDiabled) {
|
||||
throw Errors.NoProject;
|
||||
}
|
||||
|
||||
@@ -363,7 +363,7 @@ namespace ts.server {
|
||||
fileName = ts.normalizePath(fileName);
|
||||
const project = this.projectService.getProjectForFile(fileName);
|
||||
|
||||
if (!project) {
|
||||
if (!project || project.languageServiceDiabled) {
|
||||
throw Errors.NoProject;
|
||||
}
|
||||
|
||||
@@ -396,24 +396,29 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
private getProjectInfo(fileName: string, needFileNameList: boolean): protocol.ProjectInfo {
|
||||
this.logger.info("start getProjectInfo:" + new Date().getTime());
|
||||
fileName = ts.normalizePath(fileName);
|
||||
const project = this.projectService.getProjectForFile(fileName);
|
||||
if (!project) {
|
||||
throw Errors.NoProject;
|
||||
}
|
||||
|
||||
const projectInfo: protocol.ProjectInfo = {
|
||||
configFileName: project.projectFilename
|
||||
configFileName: project.projectFilename,
|
||||
languageServiceDisabled: project.languageServiceDiabled
|
||||
};
|
||||
|
||||
if (needFileNameList) {
|
||||
projectInfo.fileNames = project.getFileNames();
|
||||
}
|
||||
|
||||
this.logger.info("end getProjectInfo:" + new Date().getTime());
|
||||
return projectInfo;
|
||||
}
|
||||
|
||||
private getRenameLocations(line: number, offset: number, fileName: string, findInComments: boolean, findInStrings: boolean): protocol.RenameResponseBody {
|
||||
const file = ts.normalizePath(fileName);
|
||||
const project = this.projectService.getProjectForFile(file);
|
||||
if (!project) {
|
||||
if (!project || project.languageServiceDiabled) {
|
||||
throw Errors.NoProject;
|
||||
}
|
||||
|
||||
@@ -483,7 +488,7 @@ namespace ts.server {
|
||||
// can avoid duplicates by eliminating same ref file from subsequent projects
|
||||
const file = ts.normalizePath(fileName);
|
||||
const project = this.projectService.getProjectForFile(file);
|
||||
if (!project) {
|
||||
if (!project || project.languageServiceDiabled) {
|
||||
throw Errors.NoProject;
|
||||
}
|
||||
|
||||
@@ -537,7 +542,7 @@ namespace ts.server {
|
||||
private getQuickInfo(line: number, offset: number, fileName: string): protocol.QuickInfoResponseBody {
|
||||
const file = ts.normalizePath(fileName);
|
||||
const project = this.projectService.getProjectForFile(file);
|
||||
if (!project) {
|
||||
if (!project || project.languageServiceDiabled) {
|
||||
throw Errors.NoProject;
|
||||
}
|
||||
|
||||
@@ -563,7 +568,7 @@ namespace ts.server {
|
||||
private getFormattingEditsForRange(line: number, offset: number, endLine: number, endOffset: number, fileName: string): protocol.CodeEdit[] {
|
||||
const file = ts.normalizePath(fileName);
|
||||
const project = this.projectService.getProjectForFile(file);
|
||||
if (!project) {
|
||||
if (!project || project.languageServiceDiabled) {
|
||||
throw Errors.NoProject;
|
||||
}
|
||||
|
||||
@@ -591,7 +596,7 @@ namespace ts.server {
|
||||
const file = ts.normalizePath(fileName);
|
||||
|
||||
const project = this.projectService.getProjectForFile(file);
|
||||
if (!project) {
|
||||
if (!project || project.languageServiceDiabled) {
|
||||
throw Errors.NoProject;
|
||||
}
|
||||
|
||||
@@ -669,7 +674,7 @@ namespace ts.server {
|
||||
}
|
||||
const file = ts.normalizePath(fileName);
|
||||
const project = this.projectService.getProjectForFile(file);
|
||||
if (!project) {
|
||||
if (!project || project.languageServiceDiabled) {
|
||||
throw Errors.NoProject;
|
||||
}
|
||||
|
||||
@@ -693,7 +698,7 @@ namespace ts.server {
|
||||
entryNames: string[], fileName: string): protocol.CompletionEntryDetails[] {
|
||||
const file = ts.normalizePath(fileName);
|
||||
const project = this.projectService.getProjectForFile(file);
|
||||
if (!project) {
|
||||
if (!project || project.languageServiceDiabled) {
|
||||
throw Errors.NoProject;
|
||||
}
|
||||
|
||||
@@ -712,7 +717,7 @@ namespace ts.server {
|
||||
private getSignatureHelpItems(line: number, offset: number, fileName: string): protocol.SignatureHelpItems {
|
||||
const file = ts.normalizePath(fileName);
|
||||
const project = this.projectService.getProjectForFile(file);
|
||||
if (!project) {
|
||||
if (!project || project.languageServiceDiabled) {
|
||||
throw Errors.NoProject;
|
||||
}
|
||||
|
||||
@@ -742,7 +747,7 @@ namespace ts.server {
|
||||
const checkList = fileNames.reduce((accum: PendingErrorCheck[], fileName: string) => {
|
||||
fileName = ts.normalizePath(fileName);
|
||||
const project = this.projectService.getProjectForFile(fileName);
|
||||
if (project) {
|
||||
if (project && !project.languageServiceDiabled) {
|
||||
accum.push({ fileName, project });
|
||||
}
|
||||
return accum;
|
||||
@@ -756,7 +761,7 @@ namespace ts.server {
|
||||
private change(line: number, offset: number, endLine: number, endOffset: number, insertString: string, fileName: string) {
|
||||
const file = ts.normalizePath(fileName);
|
||||
const project = this.projectService.getProjectForFile(file);
|
||||
if (project) {
|
||||
if (project && !project.languageServiceDiabled) {
|
||||
const compilerService = project.compilerService;
|
||||
const start = compilerService.host.lineOffsetToPosition(file, line, offset);
|
||||
const end = compilerService.host.lineOffsetToPosition(file, endLine, endOffset);
|
||||
@@ -772,7 +777,7 @@ namespace ts.server {
|
||||
const file = ts.normalizePath(fileName);
|
||||
const tmpfile = ts.normalizePath(tempFileName);
|
||||
const project = this.projectService.getProjectForFile(file);
|
||||
if (project) {
|
||||
if (project && !project.languageServiceDiabled) {
|
||||
this.changeSeq++;
|
||||
// make sure no changes happen before this one is finished
|
||||
project.compilerService.host.reloadScript(file, tmpfile, () => {
|
||||
@@ -786,7 +791,7 @@ namespace ts.server {
|
||||
const tmpfile = ts.normalizePath(tempFileName);
|
||||
|
||||
const project = this.projectService.getProjectForFile(file);
|
||||
if (project) {
|
||||
if (project && !project.languageServiceDiabled) {
|
||||
project.compilerService.host.saveTo(file, tmpfile);
|
||||
}
|
||||
}
|
||||
@@ -821,7 +826,7 @@ namespace ts.server {
|
||||
private getNavigationBarItems(fileName: string): protocol.NavigationBarItem[] {
|
||||
const file = ts.normalizePath(fileName);
|
||||
const project = this.projectService.getProjectForFile(file);
|
||||
if (!project) {
|
||||
if (!project || project.languageServiceDiabled) {
|
||||
throw Errors.NoProject;
|
||||
}
|
||||
|
||||
@@ -837,7 +842,7 @@ namespace ts.server {
|
||||
private getNavigateToItems(searchValue: string, fileName: string, maxResultCount?: number): protocol.NavtoItem[] {
|
||||
const file = ts.normalizePath(fileName);
|
||||
const project = this.projectService.getProjectForFile(file);
|
||||
if (!project) {
|
||||
if (!project || project.languageServiceDiabled) {
|
||||
throw Errors.NoProject;
|
||||
}
|
||||
|
||||
@@ -877,7 +882,7 @@ namespace ts.server {
|
||||
const file = ts.normalizePath(fileName);
|
||||
|
||||
const project = this.projectService.getProjectForFile(file);
|
||||
if (!project) {
|
||||
if (!project || project.languageServiceDiabled) {
|
||||
throw Errors.NoProject;
|
||||
}
|
||||
|
||||
@@ -896,7 +901,11 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
getDiagnosticsForProject(delay: number, fileName: string) {
|
||||
const { fileNames } = this.getProjectInfo(fileName, /*needFileNameList*/ true);
|
||||
const { fileNames, languageServiceDisabled } = this.getProjectInfo(fileName, /*needFileNameList*/ true);
|
||||
if (languageServiceDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// No need to analyze lib.d.ts
|
||||
let fileNamesInProject = fileNames.filter((value, index, array) => value.indexOf("lib.d.ts") < 0);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user