Skip to content

Commit c8e0b00

Browse files
committed
Make language service optional for a project
1 parent 225e3b4 commit c8e0b00

File tree

8 files changed

+250
-115
lines changed

8 files changed

+250
-115
lines changed

src/compiler/commandLineParser.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,15 @@ namespace ts {
637637
const supportedExtensions = getSupportedExtensions(options);
638638
Debug.assert(indexOf(supportedExtensions, ".ts") < indexOf(supportedExtensions, ".d.ts"), "Changed priority of extensions to pick");
639639

640-
const potentialFiles = host.readDirectory(basePath, supportedExtensions, exclude);
640+
const potentialFiles: string[] = [];
641+
if (host.readDirectoryWithMultipleExtensions) {
642+
addRange(potentialFiles, host.readDirectoryWithMultipleExtensions(basePath, supportedExtensions, exclude));
643+
}
644+
else {
645+
for (const extension of supportedExtensions) {
646+
addRange(potentialFiles, host.readDirectory(basePath, extension, exclude));
647+
}
648+
}
641649
// Get files of supported extensions in their order of resolution
642650
for (const extension of supportedExtensions) {
643651
for (const fileName of potentialFiles) {

src/compiler/program.ts

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ namespace ts {
77
/* @internal */ export let emitTime = 0;
88
/* @internal */ export let ioReadTime = 0;
99
/* @internal */ export let ioWriteTime = 0;
10+
/* @internal */ export const maxProgramSizeForNonTsFiles = 20 * 1024 * 1024;
1011

1112
/** The version of the TypeScript compiler release */
1213

@@ -696,6 +697,7 @@ namespace ts {
696697
let diagnosticsProducingTypeChecker: TypeChecker;
697698
let noDiagnosticsTypeChecker: TypeChecker;
698699
let classifiableNames: Map<string>;
700+
let programSizeLimitExceeded = false;
699701
let programSizeForNonTsFiles = 0;
700702

701703
let skipDefaultLib = options.noLib;
@@ -792,6 +794,11 @@ namespace ts {
792794

793795
return program;
794796

797+
function exceedProgramSizeLimit() {
798+
return !options.disableSizeLimit && programSizeLimitExceeded;
799+
}
800+
801+
795802
function getCommonSourceDirectory() {
796803
if (typeof commonSourceDirectory === "undefined") {
797804
if (options.rootDir && checkSourceFilesBelongToPath(files, options.rootDir)) {
@@ -1417,7 +1424,7 @@ namespace ts {
14171424
}
14181425
}
14191426

1420-
if (diagnostic) {
1427+
if (diagnostic && !exceedProgramSizeLimit()) {
14211428
if (refFile !== undefined && refEnd !== undefined && refPos !== undefined) {
14221429
fileProcessingDiagnostics.add(createFileDiagnostic(refFile, refPos, refEnd - refPos, diagnostic, ...diagnosticArgument));
14231430
}
@@ -1454,25 +1461,9 @@ namespace ts {
14541461
return file;
14551462
}
14561463

1457-
if (!options.disableSizeLimit) {
1458-
if (programSizeForNonTsFiles === -1) {
1459-
return;
1460-
}
1461-
if (programSizeForNonTsFiles > maxProgramSizeForNonTsFiles) {
1462-
// If the program size limit was reached when processing a file, this file is
1463-
// likely in the problematic folder than contains too many files.
1464-
// Normally the folder is one level down from the commonSourceDirectory, for example,
1465-
// if the commonSourceDirectory is "/src/", and the last processed path was "/src/node_modules/a/b.js",
1466-
// we should show in the error message "/src/node_modules/".
1467-
const commonSourceDirectory = getCommonSourceDirectory();
1468-
let rootLevelDirectory = path.substring(0, Math.max(commonSourceDirectory.length, path.indexOf(directorySeparator, commonSourceDirectory.length)));
1469-
if (rootLevelDirectory[rootLevelDirectory.length - 1] !== directorySeparator) {
1470-
rootLevelDirectory += directorySeparator;
1471-
}
1472-
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));
1473-
programSizeForNonTsFiles = -1;
1474-
return;
1475-
}
1464+
const isNonTsFile = !hasTypeScriptFileExtension(fileName);
1465+
if (isNonTsFile && exceedProgramSizeLimit()) {
1466+
return undefined;
14761467
}
14771468

14781469
// We haven't looked for this file, do so now and cache result
@@ -1488,6 +1479,21 @@ namespace ts {
14881479

14891480
if (!options.disableSizeLimit && file && file.text && !hasTypeScriptFileExtension(file.fileName)) {
14901481
programSizeForNonTsFiles += file.text.length;
1482+
if (programSizeForNonTsFiles > maxProgramSizeForNonTsFiles) {
1483+
// If the program size limit was reached when processing a file, this file is
1484+
// likely in the problematic folder than contains too many files.
1485+
// Normally the folder is one level down from the commonSourceDirectory, for example,
1486+
// if the commonSourceDirectory is "/src/", and the last processed path was "/src/node_modules/a/b.js",
1487+
// we should show in the error message "/src/node_modules/".
1488+
const commonSourceDirectory = getCommonSourceDirectory();
1489+
let rootLevelDirectory = path.substring(0, Math.max(commonSourceDirectory.length, path.indexOf(directorySeparator, commonSourceDirectory.length)));
1490+
if (rootLevelDirectory[rootLevelDirectory.length - 1] !== directorySeparator) {
1491+
rootLevelDirectory += directorySeparator;
1492+
}
1493+
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));
1494+
programSizeLimitExceeded = true;
1495+
return undefined;
1496+
}
14911497
}
14921498

14931499
filesByName.set(path, file);

src/compiler/sys.ts

Lines changed: 48 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ namespace ts {
1010
useCaseSensitiveFileNames: boolean;
1111
write(s: string): void;
1212
readFile(path: string, encoding?: string): string;
13+
getFileSize?(path: string): number;
1314
writeFile(path: string, data: string, writeByteOrderMark?: boolean): void;
1415
watchFile?(path: Path, callback: FileWatcherCallback): FileWatcher;
1516
watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
@@ -20,6 +21,7 @@ namespace ts {
2021
getExecutingFilePath(): string;
2122
getCurrentDirectory(): string;
2223
readDirectory(path: string, extension?: string, exclude?: string[]): string[];
24+
readDirectoryWithMultipleExtensions?(path: string, extensions: string[], exclude?: string[]): string[];
2325
getMemoryUsage?(): number;
2426
exit(exitCode?: number): void;
2527
}
@@ -489,10 +491,32 @@ namespace ts {
489491
return fileSystemEntryExists(path, FileSystemEntryKind.Directory);
490492
}
491493

492-
function readDirectory(path: string, extension?: string | string[], exclude?: string[]): string[] {
494+
function visitDirectory(path: string, extension: string | string[], exclude: string[]) {
493495
const result: string[] = [];
494-
exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s)));
495-
visitDirectory(path);
496+
const files = _fs.readdirSync(path || ".").sort();
497+
const directories: string[] = [];
498+
for (const current of files) {
499+
const name = combinePaths(path, current);
500+
if (!contains(exclude, getCanonicalPath(name))) {
501+
// fs.statSync would throw an exception if the file is a symlink
502+
// whose linked file doesn't exist.
503+
try {
504+
const stat = _fs.statSync(name);
505+
if (stat.isFile()) {
506+
if (checkExtension(name)) {
507+
result.push(name);
508+
}
509+
}
510+
else if (stat.isDirectory()) {
511+
directories.push(name);
512+
}
513+
}
514+
catch (e) { }
515+
}
516+
}
517+
for (const current of directories) {
518+
visitDirectory(current, extension, exclude);
519+
}
496520
return result;
497521

498522
function checkExtension(name: string) {
@@ -502,37 +526,20 @@ namespace ts {
502526
if (typeof extension === "string") {
503527
return fileExtensionIs(name, extension);
504528
}
505-
if (typeof extension === "string[]") {
529+
else {
506530
return forEach(extension, ext => fileExtensionIs(name, ext));
507531
}
508532
}
533+
}
509534

510-
function visitDirectory(path: string) {
511-
const files = _fs.readdirSync(path || ".").sort();
512-
const directories: string[] = [];
513-
for (const current of files) {
514-
const name = combinePaths(path, current);
515-
if (!contains(exclude, getCanonicalPath(name))) {
516-
// fs.statSync would throw an exception if the file is a symlink
517-
// whose linked file doesn't exist.
518-
try {
519-
const stat = _fs.statSync(name);
520-
if (stat.isFile()) {
521-
if (checkExtension(name)) {
522-
result.push(name);
523-
}
524-
}
525-
else if (stat.isDirectory()) {
526-
directories.push(name);
527-
}
528-
}
529-
catch (e) { }
530-
}
531-
}
532-
for (const current of directories) {
533-
visitDirectory(current);
534-
}
535-
}
535+
function readDirectoryWithMultipleExtensions(path: string, extensions: string[], exclude?: string[]): string[] {
536+
exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s)));
537+
return visitDirectory(path, extensions, exclude);
538+
}
539+
540+
function readDirectory(path: string, extension?: string, exclude?: string[]): string[] {
541+
exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s)));
542+
return visitDirectory(path, extension, exclude);
536543
}
537544

538545
return {
@@ -597,12 +604,23 @@ namespace ts {
597604
return process.cwd();
598605
},
599606
readDirectory,
607+
readDirectoryWithMultipleExtensions,
600608
getMemoryUsage() {
601609
if (global.gc) {
602610
global.gc();
603611
}
604612
return process.memoryUsage().heapUsed;
605613
},
614+
getFileSize(path) {
615+
try {
616+
const stat = _fs.statSync(path);
617+
if (stat.isFile()) {
618+
return stat.size;
619+
}
620+
}
621+
catch (e) { }
622+
return 0;
623+
},
606624
exit(exitCode?: number): void {
607625
process.exit(exitCode);
608626
}

src/compiler/types.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1580,7 +1580,8 @@ namespace ts {
15801580
}
15811581

15821582
export interface ParseConfigHost {
1583-
readDirectory(rootDir: string, extension: string | string[], exclude: string[]): string[];
1583+
readDirectory(rootDir: string, extension: string, exclude: string[]): string[];
1584+
readDirectoryWithMultipleExtensions?(rootDir: string, extensions: string[], exclude: string[]): string[];
15841585
}
15851586

15861587
export interface WriteFileCallback {
@@ -2440,7 +2441,7 @@ namespace ts {
24402441
allowJs?: boolean;
24412442
noImplicitUseStrict?: boolean;
24422443
disableSizeLimit?: boolean;
2443-
lib?: string[];
2444+
lib?: string[];
24442445
/* @internal */ stripInternal?: boolean;
24452446

24462447
// Skip checking lib.d.ts to help speed up tests.

src/compiler/utilities.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2870,6 +2870,4 @@ namespace ts {
28702870
export function isParameterPropertyDeclaration(node: ParameterDeclaration): boolean {
28712871
return node.flags & NodeFlags.AccessibilityModifier && node.parent.kind === SyntaxKind.Constructor && isClassLike(node.parent.parent);
28722872
}
2873-
2874-
export const maxProgramSizeForNonTsFiles = 20 * 1024 * 1024;
28752873
}

0 commit comments

Comments
 (0)