Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
4d3cff1
Add upper limit for the program size, fix readDirectory for the symli…
Mar 11, 2016
b155fa8
Add comments
Mar 12, 2016
a3aa000
CR feedback / Change upper limit / Add disableSizeLimit compiler option
Mar 14, 2016
a6a466c
online and offline CR feedback
Mar 15, 2016
d4eb3b8
Don't count current opened client file if it's TS file
Mar 15, 2016
a839d93
Merge branch 'master' of https://github.com/Microsoft/TypeScript into…
Mar 17, 2016
225e3b4
Speed up file searching
Mar 17, 2016
c8e0b00
Make language service optional for a project
Mar 17, 2016
d7e1d34
Merge branch 'master' of https://github.com/Microsoft/TypeScript into…
Mar 18, 2016
cb46f16
Fix failed tests
Mar 18, 2016
74e3d7b
Fix project updateing issue after editing config file
Mar 18, 2016
1b76294
Merge branch 'master' of https://github.com/Microsoft/TypeScript into…
Mar 24, 2016
5c9ce9e
Merge branch 'master' of https://github.com/Microsoft/TypeScript into…
Mar 28, 2016
94d44ad
Merge branch 'master' of https://github.com/Microsoft/TypeScript into…
Jun 9, 2016
d387050
Fix merging issues and multiple project scenario
Jun 9, 2016
4383f1a
Refactoring
Jun 9, 2016
e41b10b
add test and spit commandLineParser changes to another PR
Jun 10, 2016
3354436
Merge branch 'master' of https://github.com/Microsoft/TypeScript into…
Jun 15, 2016
550d912
Refactor code to make if statements cheaper
Jun 15, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,10 @@ namespace ts {
name: "noImplicitUseStrict",
type: "boolean",
description: Diagnostics.Do_not_emit_use_strict_directives_in_module_output
},
{
name: "disableSizeLimit",
type: "boolean"
}
];

Expand Down Expand Up @@ -566,7 +570,7 @@ namespace ts {
}
else {
// by default exclude node_modules, and any specificied output directory
exclude = ["node_modules"];
exclude = ["node_modules", "bower_components"];
const outDir = json["compilerOptions"] && json["compilerOptions"]["outDir"];
if (outDir) {
exclude.push(outDir);
Expand Down
5 changes: 4 additions & 1 deletion src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -2620,7 +2620,6 @@
"category": "Message",
"code": 6112
},

"Variable '{0}' implicitly has an '{1}' type.": {
"category": "Error",
"code": 7005
Expand Down Expand Up @@ -2824,5 +2823,9 @@
"Unknown typing option '{0}'.": {
"category": "Error",
"code": 17010
},
"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'.": {
"category": "Error",
"code": 17012
}
}
29 changes: 28 additions & 1 deletion src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,7 @@ namespace ts {
let diagnosticsProducingTypeChecker: TypeChecker;
let noDiagnosticsTypeChecker: TypeChecker;
let classifiableNames: Map<string>;
let programSizeForNonTsFiles = 0;

let skipDefaultLib = options.noLib;
const supportedExtensions = getSupportedExtensions(options);
Expand Down Expand Up @@ -742,7 +743,8 @@ namespace ts {
(oldOptions.target !== options.target) ||
(oldOptions.noLib !== options.noLib) ||
(oldOptions.jsx !== options.jsx) ||
(oldOptions.allowJs !== options.allowJs)) {
(oldOptions.allowJs !== options.allowJs) ||
(oldOptions.disableSizeLimit !== options.disableSizeLimit)) {
oldProgram = undefined;
}
}
Expand Down Expand Up @@ -1452,6 +1454,27 @@ namespace ts {
return file;
}

if (!options.disableSizeLimit) {
if (programSizeForNonTsFiles === -1) {
return;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit. return undefined;

}
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;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and this too.

}
}

// We haven't looked for this file, do so now and cache result
const file = host.getSourceFile(fileName, options.target, hostErrorMessage => {
if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) {
Expand All @@ -1463,6 +1486,10 @@ namespace ts {
}
});

if (!options.disableSizeLimit && file && file.text && !hasTypeScriptFileExtension(file.fileName)) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like we do not need this in the program building, since we are doing it in the server.

programSizeForNonTsFiles += file.text.length;
}

filesByName.set(path, file);
if (file) {
file.wasReferenced = file.wasReferenced || isReference;
Expand Down
29 changes: 17 additions & 12 deletions src/compiler/sys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ namespace ts {
watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
};

export var sys: System = (function () {
export var sys: System = (function() {

function getWScriptSystem(): System {

Expand Down Expand Up @@ -404,8 +404,8 @@ namespace ts {
const watchedFileSet = createWatchedFileSet();

function isNode4OrLater(): boolean {
return parseInt(process.version.charAt(1)) >= 4;
}
return parseInt(process.version.charAt(1)) >= 4;
}

const platform: string = _os.platform();
// win32\win64 are case insensitive platforms, MacOS (darwin) by default is also case insensitive
Expand Down Expand Up @@ -500,15 +500,20 @@ namespace ts {
for (const current of files) {
const name = combinePaths(path, current);
if (!contains(exclude, getCanonicalPath(name))) {
const stat = _fs.statSync(name);
if (stat.isFile()) {
if (!extension || fileExtensionIs(name, extension)) {
result.push(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 (!extension || fileExtensionIs(name, extension)) {
result.push(name);
}
}
else if (stat.isDirectory()) {
directories.push(name);
}
}
else if (stat.isDirectory()) {
directories.push(name);
}
catch (e) { }
}
}
for (const current of directories) {
Expand All @@ -532,7 +537,7 @@ namespace ts {
// and https://github.com/Microsoft/TypeScript/issues/4643), therefore
// if the current node.js version is newer than 4, use `fs.watch` instead.
const watchSet = isNode4OrLater() ? watchedFileSet : pollingWatchedFileSet;
const watchedFile = watchSet.addFile(filePath, callback);
const watchedFile = watchSet.addFile(filePath, callback);
return {
close: () => watchSet.removeFile(watchedFile)
};
Expand Down Expand Up @@ -562,7 +567,7 @@ namespace ts {
}
);
},
resolvePath: function (path: string): string {
resolvePath: function(path: string): string {
return _path.resolve(path);
},
fileExists,
Expand Down
1 change: 1 addition & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2437,6 +2437,7 @@ namespace ts {
allowSyntheticDefaultImports?: boolean;
allowJs?: boolean;
noImplicitUseStrict?: boolean;
disableSizeLimit?: boolean;
/* @internal */ stripInternal?: boolean;

// Skip checking lib.d.ts to help speed up tests.
Expand Down
6 changes: 6 additions & 0 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2484,6 +2484,10 @@ namespace ts {
return forEach(supportedJavascriptExtensions, extension => fileExtensionIs(fileName, extension));
}

export function hasTypeScriptFileExtension(fileName: string) {
return forEach(supportedTypeScriptExtensions, extension => fileExtensionIs(fileName, extension));
}

/**
* Replace each instance of non-ascii characters by one, two, three, or four escape sequences
* representing the UTF-8 encoding of the character, and return the expanded char code list.
Expand Down Expand Up @@ -2866,4 +2870,6 @@ 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;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i would put this in program. and no need to export it. we only use it there.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now it is shared between the server and the program.ts though

}
42 changes: 39 additions & 3 deletions src/server/editorServices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1217,10 +1217,43 @@ namespace ts.server {
}
else {
const project = this.createProject(configFilename, projectOptions);
let programSizeForNonTsFiles = 0;

// 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) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i thought we said we did not need this anymore? is this not the case?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file reading here doesn't have an upper limit, therefore it could be much more than 20M. In the repro case it is around 100M, and in testing I noticed server crashes without the limit. So I kept the limit here as well.

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 (const rootFilename of projectOptions.files) {
if (rootFilename === clientFileName) {
continue;
}

if (this.host.fileExists(rootFilename)) {
const info = this.openFile(rootFilename, /*openedByClient*/ clientFileName == rootFilename);
project.addRoot(info);
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;
}
}
else {
return { errorMsg: "specified file " + rootFilename + " not found" };
Expand Down Expand Up @@ -1251,7 +1284,10 @@ namespace ts.server {
return error;
}
else {
const oldFileNames = project.compilerService.host.roots.map(info => info.fileName);
// 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.
const oldFileNames = project.projectOptions ? project.projectOptions.files : project.compilerService.host.roots.map(info => info.fileName);
const newFileNames = projectOptions.files;
const fileNamesToRemove = oldFileNames.filter(f => newFileNames.indexOf(f) < 0);
const fileNamesToAdd = newFileNames.filter(f => oldFileNames.indexOf(f) < 0);
Expand Down
3 changes: 2 additions & 1 deletion src/services/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2760,7 +2760,8 @@ namespace ts {
oldSettings.module !== newSettings.module ||
oldSettings.noResolve !== newSettings.noResolve ||
oldSettings.jsx !== newSettings.jsx ||
oldSettings.allowJs !== newSettings.allowJs);
oldSettings.allowJs !== newSettings.allowJs ||
oldSettings.disableSizeLimit !== oldSettings.disableSizeLimit);

// Now create a new compiler
const compilerHost: CompilerHost = {
Expand Down