Skip to content

Commit a3b0810

Browse files
committed
Merge branch 'release-2.0' into Fix9636
2 parents 290caad + 2b8c1f9 commit a3b0810

36 files changed

+616
-90
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,4 @@ internal/
5050
!**/.vscode/tasks.json
5151
!tests/cases/projects/projectOption/**/node_modules
5252
!tests/cases/projects/NodeModulesSearch/**/*
53+
!tests/baselines/reference/project/nodeModules*/**/*

src/compiler/checker.ts

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3160,23 +3160,26 @@ namespace ts {
31603160
if (declaration.kind === SyntaxKind.ExportAssignment) {
31613161
return links.type = checkExpression((<ExportAssignment>declaration).expression);
31623162
}
3163+
if (declaration.flags & NodeFlags.JavaScriptFile && declaration.kind === SyntaxKind.JSDocPropertyTag && (<JSDocPropertyTag>declaration).typeExpression) {
3164+
return links.type = getTypeFromTypeNode((<JSDocPropertyTag>declaration).typeExpression.type);
3165+
}
31633166
// Handle variable, parameter or property
31643167
if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
31653168
return unknownType;
31663169
}
31673170

31683171
let type: Type = undefined;
3169-
// Handle module.exports = expr or this.p = expr
3170-
if (declaration.kind === SyntaxKind.BinaryExpression) {
3171-
type = getUnionType(map(symbol.declarations, (decl: BinaryExpression) => checkExpressionCached(decl.right)));
3172-
}
3173-
else if (declaration.kind === SyntaxKind.PropertyAccessExpression) {
3174-
// Declarations only exist for property access expressions for certain
3175-
// special assignment kinds
3176-
if (declaration.parent.kind === SyntaxKind.BinaryExpression) {
3177-
// Handle exports.p = expr or className.prototype.method = expr
3178-
type = checkExpressionCached((<BinaryExpression>declaration.parent).right);
3179-
}
3172+
// Handle certain special assignment kinds, which happen to union across multiple declarations:
3173+
// * module.exports = expr
3174+
// * exports.p = expr
3175+
// * this.p = expr
3176+
// * className.prototype.method = expr
3177+
if (declaration.kind === SyntaxKind.BinaryExpression ||
3178+
declaration.kind === SyntaxKind.PropertyAccessExpression && declaration.parent.kind === SyntaxKind.BinaryExpression) {
3179+
type = getUnionType(map(symbol.declarations,
3180+
decl => decl.kind === SyntaxKind.BinaryExpression ?
3181+
checkExpressionCached((<BinaryExpression>decl).right) :
3182+
checkExpressionCached((<BinaryExpression>decl.parent).right)));
31803183
}
31813184

31823185
if (type === undefined) {
@@ -11673,7 +11676,7 @@ namespace ts {
1167311676
function getInferredClassType(symbol: Symbol) {
1167411677
const links = getSymbolLinks(symbol);
1167511678
if (!links.inferredClassType) {
11676-
links.inferredClassType = createAnonymousType(undefined, symbol.members, emptyArray, emptyArray, /*stringIndexType*/ undefined, /*numberIndexType*/ undefined);
11679+
links.inferredClassType = createAnonymousType(symbol, symbol.members, emptyArray, emptyArray, /*stringIndexType*/ undefined, /*numberIndexType*/ undefined);
1167711680
}
1167811681
return links.inferredClassType;
1167911682
}

src/compiler/program.ts

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,29 @@ namespace ts {
997997
return sortAndDeduplicateDiagnostics(diagnostics);
998998
}
999999

1000+
export interface FormatDiagnosticsHost {
1001+
getCurrentDirectory(): string;
1002+
getCanonicalFileName(fileName: string): string;
1003+
getNewLine(): string;
1004+
}
1005+
1006+
export function formatDiagnostics(diagnostics: Diagnostic[], host: FormatDiagnosticsHost): string {
1007+
let output = "";
1008+
1009+
for (const diagnostic of diagnostics) {
1010+
if (diagnostic.file) {
1011+
const { line, character } = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
1012+
const fileName = diagnostic.file.fileName;
1013+
const relativeFileName = convertToRelativePath(fileName, host.getCurrentDirectory(), fileName => host.getCanonicalFileName(fileName));
1014+
output += `${ relativeFileName }(${ line + 1 },${ character + 1 }): `;
1015+
}
1016+
1017+
const category = DiagnosticCategory[diagnostic.category].toLowerCase();
1018+
output += `${ category } TS${ diagnostic.code }: ${ flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine()) }${ host.getNewLine() }`;
1019+
}
1020+
return output;
1021+
}
1022+
10001023
export function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain, newLine: string): string {
10011024
if (typeof messageText === "string") {
10021025
return messageText;
@@ -1095,13 +1118,13 @@ namespace ts {
10951118
// As all these operations happen - and are nested - within the createProgram call, they close over the below variables.
10961119
// The current resolution depth is tracked by incrementing/decrementing as the depth first search progresses.
10971120
const maxNodeModulesJsDepth = typeof options.maxNodeModuleJsDepth === "number" ? options.maxNodeModuleJsDepth : 2;
1098-
let currentNodeModulesJsDepth = 0;
1121+
let currentNodeModulesDepth = 0;
10991122

11001123
// If a module has some of its imports skipped due to being at the depth limit under node_modules, then track
11011124
// this, as it may be imported at a shallower depth later, and then it will need its skipped imports processed.
11021125
const modulesWithElidedImports: Map<boolean> = {};
11031126

1104-
// Track source files that are JavaScript files found by searching under node_modules, as these shouldn't be compiled.
1127+
// Track source files that are source files found by searching under node_modules, as these shouldn't be compiled.
11051128
const sourceFilesFoundSearchingNodeModules: Map<boolean> = {};
11061129

11071130
const start = new Date().getTime();
@@ -1918,9 +1941,21 @@ namespace ts {
19181941
reportFileNamesDifferOnlyInCasingError(fileName, file.fileName, refFile, refPos, refEnd);
19191942
}
19201943

1944+
// If the file was previously found via a node_modules search, but is now being processed as a root file,
1945+
// then everything it sucks in may also be marked incorrectly, and needs to be checked again.
1946+
if (file && lookUp(sourceFilesFoundSearchingNodeModules, file.path) && currentNodeModulesDepth == 0) {
1947+
sourceFilesFoundSearchingNodeModules[file.path] = false;
1948+
if (!options.noResolve) {
1949+
processReferencedFiles(file, getDirectoryPath(fileName), isDefaultLib);
1950+
processTypeReferenceDirectives(file);
1951+
}
1952+
1953+
modulesWithElidedImports[file.path] = false;
1954+
processImportedModules(file, getDirectoryPath(fileName));
1955+
}
19211956
// See if we need to reprocess the imports due to prior skipped imports
1922-
if (file && lookUp(modulesWithElidedImports, file.path)) {
1923-
if (currentNodeModulesJsDepth < maxNodeModulesJsDepth) {
1957+
else if (file && lookUp(modulesWithElidedImports, file.path)) {
1958+
if (currentNodeModulesDepth < maxNodeModulesJsDepth) {
19241959
modulesWithElidedImports[file.path] = false;
19251960
processImportedModules(file, getDirectoryPath(fileName));
19261961
}
@@ -1942,6 +1977,7 @@ namespace ts {
19421977

19431978
filesByName.set(path, file);
19441979
if (file) {
1980+
sourceFilesFoundSearchingNodeModules[path] = (currentNodeModulesDepth > 0);
19451981
file.path = path;
19461982

19471983
if (host.useCaseSensitiveFileNames()) {
@@ -2075,13 +2111,10 @@ namespace ts {
20752111
const isJsFileFromNodeModules = isFromNodeModulesSearch && hasJavaScriptFileExtension(resolution.resolvedFileName);
20762112

20772113
if (isFromNodeModulesSearch) {
2078-
sourceFilesFoundSearchingNodeModules[resolvedPath] = true;
2079-
}
2080-
if (isJsFileFromNodeModules) {
2081-
currentNodeModulesJsDepth++;
2114+
currentNodeModulesDepth++;
20822115
}
20832116

2084-
const elideImport = isJsFileFromNodeModules && currentNodeModulesJsDepth > maxNodeModulesJsDepth;
2117+
const elideImport = isJsFileFromNodeModules && currentNodeModulesDepth > maxNodeModulesJsDepth;
20852118
const shouldAddFile = resolution && !options.noResolve && i < file.imports.length && !elideImport;
20862119

20872120
if (elideImport) {
@@ -2096,8 +2129,8 @@ namespace ts {
20962129
file.imports[i].end);
20972130
}
20982131

2099-
if (isJsFileFromNodeModules) {
2100-
currentNodeModulesJsDepth--;
2132+
if (isFromNodeModulesSearch) {
2133+
currentNodeModulesDepth--;
21012134
}
21022135
}
21032136
}

src/compiler/tsc.ts

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,19 @@ namespace ts {
66
fileWatcher?: FileWatcher;
77
}
88

9-
let reportDiagnostic = reportDiagnosticSimply;
9+
const defaultFormatDiagnosticsHost: FormatDiagnosticsHost = {
10+
getCurrentDirectory: () => sys.getCurrentDirectory(),
11+
getNewLine: () => sys.newLine,
12+
getCanonicalFileName: createGetCanonicalFileName(sys.useCaseSensitiveFileNames)
13+
};
14+
15+
let reportDiagnosticWorker = reportDiagnosticSimply;
16+
17+
function reportDiagnostic(diagnostic: Diagnostic, host: FormatDiagnosticsHost) {
18+
reportDiagnosticWorker(diagnostic, host || defaultFormatDiagnosticsHost);
19+
}
1020

11-
function reportDiagnostics(diagnostics: Diagnostic[], host: CompilerHost): void {
21+
function reportDiagnostics(diagnostics: Diagnostic[], host: FormatDiagnosticsHost): void {
1222
for (const diagnostic of diagnostics) {
1323
reportDiagnostic(diagnostic, host);
1424
}
@@ -101,23 +111,8 @@ namespace ts {
101111
return <string>diagnostic.messageText;
102112
}
103113

104-
function getRelativeFileName(fileName: string, host: CompilerHost): string {
105-
return host ? convertToRelativePath(fileName, host.getCurrentDirectory(), fileName => host.getCanonicalFileName(fileName)) : fileName;
106-
}
107-
108-
function reportDiagnosticSimply(diagnostic: Diagnostic, host: CompilerHost): void {
109-
let output = "";
110-
111-
if (diagnostic.file) {
112-
const { line, character } = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
113-
const relativeFileName = getRelativeFileName(diagnostic.file.fileName, host);
114-
output += `${ relativeFileName }(${ line + 1 },${ character + 1 }): `;
115-
}
116-
117-
const category = DiagnosticCategory[diagnostic.category].toLowerCase();
118-
output += `${ category } TS${ diagnostic.code }: ${ flattenDiagnosticMessageText(diagnostic.messageText, sys.newLine) }${ sys.newLine }`;
119-
120-
sys.write(output);
114+
function reportDiagnosticSimply(diagnostic: Diagnostic, host: FormatDiagnosticsHost): void {
115+
sys.write(ts.formatDiagnostics([diagnostic], host));
121116
}
122117

123118
const redForegroundEscapeSequence = "\u001b[91m";
@@ -137,15 +132,15 @@ namespace ts {
137132
return formatStyle + text + resetEscapeSequence;
138133
}
139134

140-
function reportDiagnosticWithColorAndContext(diagnostic: Diagnostic, host: CompilerHost): void {
135+
function reportDiagnosticWithColorAndContext(diagnostic: Diagnostic, host: FormatDiagnosticsHost): void {
141136
let output = "";
142137

143138
if (diagnostic.file) {
144139
const { start, length, file } = diagnostic;
145140
const { line: firstLine, character: firstLineChar } = getLineAndCharacterOfPosition(file, start);
146141
const { line: lastLine, character: lastLineChar } = getLineAndCharacterOfPosition(file, start + length);
147142
const lastLineInFile = getLineAndCharacterOfPosition(file, file.text.length).line;
148-
const relativeFileName = getRelativeFileName(file.fileName, host);
143+
const relativeFileName = host ? convertToRelativePath(file.fileName, host.getCurrentDirectory(), fileName => host.getCanonicalFileName(fileName)) : file.fileName;
149144

150145
const hasMoreThanFiveLines = (lastLine - firstLine) >= 4;
151146
let gutterWidth = (lastLine + 1 + "").length;
@@ -272,7 +267,7 @@ namespace ts {
272267

273268
if (commandLine.options.locale) {
274269
if (!isJSONSupported()) {
275-
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--locale"), /* compilerHost */ undefined);
270+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--locale"), /* host */ undefined);
276271
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
277272
}
278273
validateLocaleAndSetLanguage(commandLine.options.locale, commandLine.errors);
@@ -303,26 +298,26 @@ namespace ts {
303298

304299
if (commandLine.options.project) {
305300
if (!isJSONSupported()) {
306-
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--project"), /* compilerHost */ undefined);
301+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--project"), /* host */ undefined);
307302
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
308303
}
309304
if (commandLine.fileNames.length !== 0) {
310-
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line), /* compilerHost */ undefined);
305+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line), /* host */ undefined);
311306
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
312307
}
313308

314309
const fileOrDirectory = normalizePath(commandLine.options.project);
315310
if (!fileOrDirectory /* current directory "." */ || sys.directoryExists(fileOrDirectory)) {
316311
configFileName = combinePaths(fileOrDirectory, "tsconfig.json");
317312
if (!sys.fileExists(configFileName)) {
318-
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Cannot_find_a_tsconfig_json_file_at_the_specified_directory_Colon_0, commandLine.options.project), /* compilerHost */ undefined);
313+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Cannot_find_a_tsconfig_json_file_at_the_specified_directory_Colon_0, commandLine.options.project), /* host */ undefined);
319314
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
320315
}
321316
}
322317
else {
323318
configFileName = fileOrDirectory;
324319
if (!sys.fileExists(configFileName)) {
325-
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_specified_path_does_not_exist_Colon_0, commandLine.options.project), /* compilerHost */ undefined);
320+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_specified_path_does_not_exist_Colon_0, commandLine.options.project), /* host */ undefined);
326321
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
327322
}
328323
}
@@ -340,7 +335,7 @@ namespace ts {
340335

341336
if (isWatchSet(commandLine.options)) {
342337
if (!sys.watchFile) {
343-
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"), /* compilerHost */ undefined);
338+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"), /* host */ undefined);
344339
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
345340
}
346341
if (configFileName) {
@@ -393,7 +388,7 @@ namespace ts {
393388
}
394389
if (isWatchSet(configParseResult.options)) {
395390
if (!sys.watchFile) {
396-
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"), /* compilerHost */ undefined);
391+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"), /* host */ undefined);
397392
sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
398393
}
399394

@@ -432,7 +427,7 @@ namespace ts {
432427
}
433428

434429
if (compilerOptions.pretty) {
435-
reportDiagnostic = reportDiagnosticWithColorAndContext;
430+
reportDiagnosticWorker = reportDiagnosticWithColorAndContext;
436431
}
437432

438433
// reset the cache of existing files
@@ -757,7 +752,7 @@ namespace ts {
757752
const currentDirectory = sys.getCurrentDirectory();
758753
const file = normalizePath(combinePaths(currentDirectory, "tsconfig.json"));
759754
if (sys.fileExists(file)) {
760-
reportDiagnostic(createCompilerDiagnostic(Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file), /* compilerHost */ undefined);
755+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file), /* host */ undefined);
761756
}
762757
else {
763758
const compilerOptions = extend(options, defaultInitCompilerOptions);
@@ -777,7 +772,7 @@ namespace ts {
777772
}
778773

779774
sys.writeFile(file, JSON.stringify(configurations, undefined, 4));
780-
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Successfully_created_a_tsconfig_json_file), /* compilerHost */ undefined);
775+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Successfully_created_a_tsconfig_json_file), /* host */ undefined);
781776
}
782777

783778
return;

0 commit comments

Comments
 (0)