Skip to content

Commit b58ef9e

Browse files
committed
Merge branch 'master' into genericDefaults
2 parents febde3f + 9b6f930 commit b58ef9e

File tree

137 files changed

+3700
-683
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

137 files changed

+3700
-683
lines changed

Gulpfile.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ const cmdLineOptions = minimist(process.argv.slice(2), {
5050
r: "reporter",
5151
color: "colors",
5252
f: "files",
53-
file: "files"
53+
file: "files",
54+
w: "workers",
5455
},
5556
default: {
5657
soft: false,
@@ -63,6 +64,7 @@ const cmdLineOptions = minimist(process.argv.slice(2), {
6364
reporter: process.env.reporter || process.env.r,
6465
lint: process.env.lint || true,
6566
files: process.env.f || process.env.file || process.env.files || "",
67+
workers: process.env.workerCount || os.cpus().length,
6668
}
6769
});
6870

@@ -604,7 +606,7 @@ function runConsoleTests(defaultReporter: string, runInParallel: boolean, done:
604606
} while (fs.existsSync(taskConfigsFolder));
605607
fs.mkdirSync(taskConfigsFolder);
606608

607-
workerCount = process.env.workerCount || os.cpus().length;
609+
workerCount = cmdLineOptions["workers"];
608610
}
609611

610612
if (tests || light || taskConfigsFolder) {
@@ -1017,7 +1019,7 @@ gulp.task("lint", "Runs tslint on the compiler sources. Optional arguments are:
10171019
cb();
10181020
}, (cb) => {
10191021
files = files.filter(file => fileMatcher.test(file.path)).sort((filea, fileb) => filea.stat.size - fileb.stat.size);
1020-
const workerCount = (process.env.workerCount && +process.env.workerCount) || os.cpus().length;
1022+
const workerCount = cmdLineOptions["workers"];
10211023
for (let i = 0; i < workerCount; i++) {
10221024
spawnLintWorker(files, finished);
10231025
}

src/compiler/binder.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1512,7 +1512,7 @@ namespace ts {
15121512
errorOnFirstToken(node, Diagnostics.export_modifier_cannot_be_applied_to_ambient_modules_and_module_augmentations_since_they_are_always_visible);
15131513
}
15141514
if (isExternalModuleAugmentation(node)) {
1515-
declareSymbolAndAddToSymbolTable(node, SymbolFlags.NamespaceModule, SymbolFlags.NamespaceModuleExcludes);
1515+
declareModuleSymbol(node);
15161516
}
15171517
else {
15181518
let pattern: Pattern | undefined;
@@ -1534,12 +1534,8 @@ namespace ts {
15341534
}
15351535
}
15361536
else {
1537-
const state = getModuleInstanceState(node);
1538-
if (state === ModuleInstanceState.NonInstantiated) {
1539-
declareSymbolAndAddToSymbolTable(node, SymbolFlags.NamespaceModule, SymbolFlags.NamespaceModuleExcludes);
1540-
}
1541-
else {
1542-
declareSymbolAndAddToSymbolTable(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes);
1537+
const state = declareModuleSymbol(node);
1538+
if (state !== ModuleInstanceState.NonInstantiated) {
15431539
if (node.symbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.RegularEnum)) {
15441540
// if module was already merged with some function, class or non-const enum
15451541
// treat is a non-const-enum-only
@@ -1560,6 +1556,15 @@ namespace ts {
15601556
}
15611557
}
15621558

1559+
function declareModuleSymbol(node: ModuleDeclaration): ModuleInstanceState {
1560+
const state = getModuleInstanceState(node);
1561+
const instantiated = state !== ModuleInstanceState.NonInstantiated;
1562+
declareSymbolAndAddToSymbolTable(node,
1563+
instantiated ? SymbolFlags.ValueModule : SymbolFlags.NamespaceModule,
1564+
instantiated ? SymbolFlags.ValueModuleExcludes : SymbolFlags.NamespaceModuleExcludes);
1565+
return state;
1566+
}
1567+
15631568
function bindFunctionOrConstructorType(node: SignatureDeclaration): void {
15641569
// For a given function symbol "<...>(...) => T" we want to generate a symbol identical
15651570
// to the one we would get for: { <...>(...): T }

src/compiler/checker.ts

Lines changed: 115 additions & 70 deletions
Large diffs are not rendered by default.

src/compiler/commandLineParser.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,11 @@ namespace ts {
6767
name: "jsx",
6868
type: createMapFromTemplate({
6969
"preserve": JsxEmit.Preserve,
70+
"react-native": JsxEmit.ReactNative,
7071
"react": JsxEmit.React
7172
}),
7273
paramType: Diagnostics.KIND,
73-
description: Diagnostics.Specify_JSX_code_generation_Colon_preserve_or_react,
74+
description: Diagnostics.Specify_JSX_code_generation_Colon_preserve_react_native_or_react,
7475
},
7576
{
7677
name: "reactNamespace",
@@ -1257,7 +1258,6 @@ namespace ts {
12571258

12581259
const literalFiles = arrayFrom(literalFileMap.values());
12591260
const wildcardFiles = arrayFrom(wildcardFileMap.values());
1260-
wildcardFiles.sort(host.useCaseSensitiveFileNames ? compareStrings : compareStringsCaseInsensitive);
12611261
return {
12621262
fileNames: literalFiles.concat(wildcardFiles),
12631263
wildcardDirectories

src/compiler/core.ts

Lines changed: 54 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,10 @@ namespace ts {
204204
GreaterThan = 1
205205
}
206206

207+
export function length(array: any[]) {
208+
return array ? array.length : 0;
209+
}
210+
207211
/**
208212
* Iterates through 'array' by index and performs the callback on each element of array until the callback
209213
* returns a truthy value, then returns that value.
@@ -256,6 +260,16 @@ namespace ts {
256260
return undefined;
257261
}
258262

263+
/** Works like Array.prototype.findIndex, returning `-1` if no element satisfying the predicate is found. */
264+
export function findIndex<T>(array: T[], predicate: (element: T, index: number) => boolean): number {
265+
for (let i = 0; i < array.length; i++) {
266+
if (predicate(array[i], i)) {
267+
return i;
268+
}
269+
}
270+
return -1;
271+
}
272+
259273
/**
260274
* Returns the first truthy result of `callback`, or else fails.
261275
* This is like `forEach`, but never returns undefined.
@@ -1720,7 +1734,19 @@ namespace ts {
17201734
const singleAsteriskRegexFragmentFiles = "([^./]|(\\.(?!min\\.js$))?)*";
17211735
const singleAsteriskRegexFragmentOther = "[^/]*";
17221736

1723-
export function getRegularExpressionForWildcard(specs: string[], basePath: string, usage: "files" | "directories" | "exclude") {
1737+
export function getRegularExpressionForWildcard(specs: string[], basePath: string, usage: "files" | "directories" | "exclude"): string | undefined {
1738+
const patterns = getRegularExpressionsForWildcards(specs, basePath, usage);
1739+
if (!patterns || !patterns.length) {
1740+
return undefined;
1741+
}
1742+
1743+
const pattern = patterns.map(pattern => `(${pattern})`).join("|");
1744+
// If excluding, match "foo/bar/baz...", but if including, only allow "foo".
1745+
const terminator = usage === "exclude" ? "($|/)" : "$";
1746+
return `^(${pattern})${terminator}`;
1747+
}
1748+
1749+
function getRegularExpressionsForWildcards(specs: string[], basePath: string, usage: "files" | "directories" | "exclude"): string[] | undefined {
17241750
if (specs === undefined || specs.length === 0) {
17251751
return undefined;
17261752
}
@@ -1734,33 +1760,8 @@ namespace ts {
17341760
*/
17351761
const doubleAsteriskRegexFragment = usage === "exclude" ? "(/.+?)?" : "(/[^/.][^/]*)*?";
17361762

1737-
let pattern = "";
1738-
let hasWrittenSubpattern = false;
1739-
for (const spec of specs) {
1740-
if (!spec) {
1741-
continue;
1742-
}
1743-
1744-
const subPattern = getSubPatternFromSpec(spec, basePath, usage, singleAsteriskRegexFragment, doubleAsteriskRegexFragment, replaceWildcardCharacter);
1745-
if (subPattern === undefined) {
1746-
continue;
1747-
}
1748-
1749-
if (hasWrittenSubpattern) {
1750-
pattern += "|";
1751-
}
1752-
1753-
pattern += "(" + subPattern + ")";
1754-
hasWrittenSubpattern = true;
1755-
}
1756-
1757-
if (!pattern) {
1758-
return undefined;
1759-
}
1760-
1761-
// If excluding, match "foo/bar/baz...", but if including, only allow "foo".
1762-
const terminator = usage === "exclude" ? "($|/)" : "$";
1763-
return `^(${pattern})${terminator}`;
1763+
return flatMap(specs, spec =>
1764+
spec && getSubPatternFromSpec(spec, basePath, usage, singleAsteriskRegexFragment, doubleAsteriskRegexFragment, replaceWildcardCharacter));
17641765
}
17651766

17661767
/**
@@ -1855,6 +1856,9 @@ namespace ts {
18551856
}
18561857

18571858
export interface FileMatcherPatterns {
1859+
/** One pattern for each "include" spec. */
1860+
includeFilePatterns: string[];
1861+
/** One pattern matching one of any of the "include" specs. */
18581862
includeFilePattern: string;
18591863
includeDirectoryPattern: string;
18601864
excludePattern: string;
@@ -1867,6 +1871,7 @@ namespace ts {
18671871
const absolutePath = combinePaths(currentDirectory, path);
18681872

18691873
return {
1874+
includeFilePatterns: map(getRegularExpressionsForWildcards(includes, absolutePath, "files"), pattern => `^${pattern}$`),
18701875
includeFilePattern: getRegularExpressionForWildcard(includes, absolutePath, "files"),
18711876
includeDirectoryPattern: getRegularExpressionForWildcard(includes, absolutePath, "directories"),
18721877
excludePattern: getRegularExpressionForWildcard(excludes, absolutePath, "exclude"),
@@ -1881,26 +1886,39 @@ namespace ts {
18811886
const patterns = getFileMatcherPatterns(path, excludes, includes, useCaseSensitiveFileNames, currentDirectory);
18821887

18831888
const regexFlag = useCaseSensitiveFileNames ? "" : "i";
1884-
const includeFileRegex = patterns.includeFilePattern && new RegExp(patterns.includeFilePattern, regexFlag);
1889+
const includeFileRegexes = patterns.includeFilePatterns && patterns.includeFilePatterns.map(pattern => new RegExp(pattern, regexFlag));
18851890
const includeDirectoryRegex = patterns.includeDirectoryPattern && new RegExp(patterns.includeDirectoryPattern, regexFlag);
18861891
const excludeRegex = patterns.excludePattern && new RegExp(patterns.excludePattern, regexFlag);
18871892

1888-
const result: string[] = [];
1893+
// Associate an array of results with each include regex. This keeps results in order of the "include" order.
1894+
// If there are no "includes", then just put everything in results[0].
1895+
const results: string[][] = includeFileRegexes ? includeFileRegexes.map(() => []) : [[]];
1896+
1897+
const comparer = useCaseSensitiveFileNames ? compareStrings : compareStringsCaseInsensitive;
18891898
for (const basePath of patterns.basePaths) {
18901899
visitDirectory(basePath, combinePaths(currentDirectory, basePath));
18911900
}
1892-
return result;
1901+
1902+
return flatten(results);
18931903

18941904
function visitDirectory(path: string, absolutePath: string) {
1895-
const { files, directories } = getFileSystemEntries(path);
1905+
let { files, directories } = getFileSystemEntries(path);
1906+
files = files.slice().sort(comparer);
1907+
directories = directories.slice().sort(comparer);
18961908

18971909
for (const current of files) {
18981910
const name = combinePaths(path, current);
18991911
const absoluteName = combinePaths(absolutePath, current);
1900-
if ((!extensions || fileExtensionIsAny(name, extensions)) &&
1901-
(!includeFileRegex || includeFileRegex.test(absoluteName)) &&
1902-
(!excludeRegex || !excludeRegex.test(absoluteName))) {
1903-
result.push(name);
1912+
if (extensions && !fileExtensionIsAny(name, extensions)) continue;
1913+
if (excludeRegex && excludeRegex.test(absoluteName)) continue;
1914+
if (!includeFileRegexes) {
1915+
results[0].push(name);
1916+
}
1917+
else {
1918+
const includeIndex = findIndex(includeFileRegexes, re => re.test(absoluteName));
1919+
if (includeIndex !== -1) {
1920+
results[includeIndex].push(name);
1921+
}
19041922
}
19051923
}
19061924

src/compiler/declarationEmitter.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ namespace ts {
3232

3333
export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, targetSourceFile: SourceFile): Diagnostic[] {
3434
const declarationDiagnostics = createDiagnosticCollection();
35-
forEachExpectedEmitFile(host, getDeclarationDiagnosticsFromFile, targetSourceFile);
35+
forEachEmittedFile(host, getDeclarationDiagnosticsFromFile, targetSourceFile);
3636
return declarationDiagnostics.getDiagnostics(targetSourceFile ? targetSourceFile.fileName : undefined);
3737

3838
function getDeclarationDiagnosticsFromFile({ declarationFilePath }: EmitFileNames, sources: SourceFile[], isBundledEmit: boolean) {
@@ -1805,7 +1805,7 @@ namespace ts {
18051805
}
18061806
else {
18071807
// Get the declaration file path
1808-
forEachExpectedEmitFile(host, getDeclFileName, referencedFile, emitOnlyDtsFiles);
1808+
forEachEmittedFile(host, getDeclFileName, referencedFile, emitOnlyDtsFiles);
18091809
}
18101810

18111811
if (declFileName) {

src/compiler/diagnosticMessages.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1827,6 +1827,10 @@
18271827
"category": "Error",
18281828
"code": 2609
18291829
},
1830+
"Cannot augment module '{0}' with value exports because it resolves to a non-module entity.": {
1831+
"category": "Error",
1832+
"code": 2649
1833+
},
18301834
"Cannot emit namespaced JSX elements in React": {
18311835
"category": "Error",
18321836
"code": 2650
@@ -2725,7 +2729,7 @@
27252729
"category": "Message",
27262730
"code": 6079
27272731
},
2728-
"Specify JSX code generation: 'preserve' or 'react'": {
2732+
"Specify JSX code generation: 'preserve', 'react-native', or 'react'": {
27292733
"category": "Message",
27302734
"code": 6080
27312735
},
@@ -3275,6 +3279,10 @@
32753279
"category": "Message",
32763280
"code": 90007
32773281
},
3282+
"Add 'this.' to unresolved variable.": {
3283+
"category": "Message",
3284+
"code": 90008
3285+
},
32783286
"Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig": {
32793287
"category": "Error",
32803288
"code": 90009

src/compiler/emitter.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ namespace ts {
7373

7474
// Emit each output file
7575
performance.mark("beforePrint");
76-
forEachTransformedEmitFile(host, transformed, emitFile, emitOnlyDtsFiles);
76+
forEachEmittedFile(host, emitFile, transformed, emitOnlyDtsFiles);
7777
performance.measure("printTime", "beforePrint");
7878

7979
// Clean up emit nodes on parse tree
@@ -88,7 +88,7 @@ namespace ts {
8888
sourceMaps: sourceMapDataList
8989
};
9090

91-
function emitFile(jsFilePath: string, sourceMapFilePath: string, declarationFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) {
91+
function emitFile({ jsFilePath, sourceMapFilePath, declarationFilePath }: EmitFileNames, sourceFiles: SourceFile[], isBundledEmit: boolean) {
9292
// Make sure not to write js file and source map file if any of them cannot be written
9393
if (!host.isEmitBlocked(jsFilePath) && !compilerOptions.noEmit) {
9494
if (!emitOnlyDtsFiles) {
@@ -1054,9 +1054,11 @@ namespace ts {
10541054
// Also emit a dot if expression is a integer const enum value - it will appear in generated code as numeric literal
10551055
function needsDotDotForPropertyAccess(expression: Expression) {
10561056
if (expression.kind === SyntaxKind.NumericLiteral) {
1057-
// check if numeric literal was originally written with a dot
1057+
// check if numeric literal is a decimal literal that was originally written with a dot
10581058
const text = getLiteralTextOfNode(<LiteralExpression>expression);
1059-
return text.indexOf(tokenToString(SyntaxKind.DotToken)) < 0;
1059+
return getNumericLiteralFlags(text, /*hint*/ NumericLiteralFlags.All) === NumericLiteralFlags.None
1060+
&& !(<LiteralExpression>expression).isOctalLiteral
1061+
&& text.indexOf(tokenToString(SyntaxKind.DotToken)) < 0;
10601062
}
10611063
else if (isPropertyAccessExpression(expression) || isElementAccessExpression(expression)) {
10621064
// check if constant enum value is integer

src/compiler/parser.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6698,10 +6698,15 @@ namespace ts {
66986698
typedefTag.fullName = parseJSDocTypeNameWithNamespace(/*flags*/ 0);
66996699
if (typedefTag.fullName) {
67006700
let rightNode = typedefTag.fullName;
6701-
while (rightNode.kind !== SyntaxKind.Identifier) {
6701+
while (true) {
6702+
if (rightNode.kind === SyntaxKind.Identifier || !rightNode.body) {
6703+
// if node is identifier - use it as name
6704+
// otherwise use name of the rightmost part that we were able to parse
6705+
typedefTag.name = rightNode.kind === SyntaxKind.Identifier ? rightNode : rightNode.name;
6706+
break;
6707+
}
67026708
rightNode = rightNode.body;
67036709
}
6704-
typedefTag.name = rightNode;
67056710
}
67066711
typedefTag.typeExpression = typeExpression;
67076712
skipWhitespace();

src/compiler/program.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ namespace ts {
439439

440440
function getCommonSourceDirectory() {
441441
if (commonSourceDirectory === undefined) {
442-
const emittedFiles = filterSourceFilesInDirectory(files, isSourceFileFromExternalLibrary);
442+
const emittedFiles = filter(files, file => sourceFileMayBeEmitted(file, options, isSourceFileFromExternalLibrary));
443443
if (options.rootDir && checkSourceFilesBelongToPath(emittedFiles, options.rootDir)) {
444444
// If a rootDir is specified and is valid use it as the commonSourceDirectory
445445
commonSourceDirectory = getNormalizedAbsolutePath(options.rootDir, currentDirectory);
@@ -1707,7 +1707,7 @@ namespace ts {
17071707
if (!options.noEmit && !options.suppressOutputPathCheck) {
17081708
const emitHost = getEmitHost();
17091709
const emitFilesSeen = createFileMap<boolean>(!host.useCaseSensitiveFileNames() ? key => key.toLocaleLowerCase() : undefined);
1710-
forEachExpectedEmitFile(emitHost, (emitFileNames) => {
1710+
forEachEmittedFile(emitHost, (emitFileNames) => {
17111711
verifyEmitFilePath(emitFileNames.jsFilePath, emitFilesSeen);
17121712
verifyEmitFilePath(emitFileNames.declarationFilePath, emitFilesSeen);
17131713
});

0 commit comments

Comments
 (0)