Skip to content

Commit 1eb7b91

Browse files
committed
Merge branch 'master' of https://github.com/Microsoft/TypeScript
2 parents e8a2173 + ae92437 commit 1eb7b91

File tree

126 files changed

+4161
-488
lines changed

Some content is hidden

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

126 files changed

+4161
-488
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
@@ -1513,7 +1513,7 @@ namespace ts {
15131513
errorOnFirstToken(node, Diagnostics.export_modifier_cannot_be_applied_to_ambient_modules_and_module_augmentations_since_they_are_always_visible);
15141514
}
15151515
if (isExternalModuleAugmentation(node)) {
1516-
declareSymbolAndAddToSymbolTable(node, SymbolFlags.NamespaceModule, SymbolFlags.NamespaceModuleExcludes);
1516+
declareModuleSymbol(node);
15171517
}
15181518
else {
15191519
let pattern: Pattern | undefined;
@@ -1535,12 +1535,8 @@ namespace ts {
15351535
}
15361536
}
15371537
else {
1538-
const state = getModuleInstanceState(node);
1539-
if (state === ModuleInstanceState.NonInstantiated) {
1540-
declareSymbolAndAddToSymbolTable(node, SymbolFlags.NamespaceModule, SymbolFlags.NamespaceModuleExcludes);
1541-
}
1542-
else {
1543-
declareSymbolAndAddToSymbolTable(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes);
1538+
const state = declareModuleSymbol(node);
1539+
if (state !== ModuleInstanceState.NonInstantiated) {
15441540
if (node.symbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.RegularEnum)) {
15451541
// if module was already merged with some function, class or non-const enum
15461542
// treat is a non-const-enum-only
@@ -1561,6 +1557,15 @@ namespace ts {
15611557
}
15621558
}
15631559

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

src/compiler/checker.ts

Lines changed: 126 additions & 34 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: 50 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,16 @@ namespace ts {
260260
return undefined;
261261
}
262262

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+
263273
/**
264274
* Returns the first truthy result of `callback`, or else fails.
265275
* This is like `forEach`, but never returns undefined.
@@ -1724,7 +1734,19 @@ namespace ts {
17241734
const singleAsteriskRegexFragmentFiles = "([^./]|(\\.(?!min\\.js$))?)*";
17251735
const singleAsteriskRegexFragmentOther = "[^/]*";
17261736

1727-
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 {
17281750
if (specs === undefined || specs.length === 0) {
17291751
return undefined;
17301752
}
@@ -1738,33 +1760,8 @@ namespace ts {
17381760
*/
17391761
const doubleAsteriskRegexFragment = usage === "exclude" ? "(/.+?)?" : "(/[^/.][^/]*)*?";
17401762

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

17701767
/**
@@ -1859,6 +1856,9 @@ namespace ts {
18591856
}
18601857

18611858
export interface FileMatcherPatterns {
1859+
/** One pattern for each "include" spec. */
1860+
includeFilePatterns: string[];
1861+
/** One pattern matching one of any of the "include" specs. */
18621862
includeFilePattern: string;
18631863
includeDirectoryPattern: string;
18641864
excludePattern: string;
@@ -1871,6 +1871,7 @@ namespace ts {
18711871
const absolutePath = combinePaths(currentDirectory, path);
18721872

18731873
return {
1874+
includeFilePatterns: map(getRegularExpressionsForWildcards(includes, absolutePath, "files"), pattern => `^${pattern}$`),
18741875
includeFilePattern: getRegularExpressionForWildcard(includes, absolutePath, "files"),
18751876
includeDirectoryPattern: getRegularExpressionForWildcard(includes, absolutePath, "directories"),
18761877
excludePattern: getRegularExpressionForWildcard(excludes, absolutePath, "exclude"),
@@ -1885,26 +1886,39 @@ namespace ts {
18851886
const patterns = getFileMatcherPatterns(path, excludes, includes, useCaseSensitiveFileNames, currentDirectory);
18861887

18871888
const regexFlag = useCaseSensitiveFileNames ? "" : "i";
1888-
const includeFileRegex = patterns.includeFilePattern && new RegExp(patterns.includeFilePattern, regexFlag);
1889+
const includeFileRegexes = patterns.includeFilePatterns && patterns.includeFilePatterns.map(pattern => new RegExp(pattern, regexFlag));
18891890
const includeDirectoryRegex = patterns.includeDirectoryPattern && new RegExp(patterns.includeDirectoryPattern, regexFlag);
18901891
const excludeRegex = patterns.excludePattern && new RegExp(patterns.excludePattern, regexFlag);
18911892

1892-
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;
18931898
for (const basePath of patterns.basePaths) {
18941899
visitDirectory(basePath, combinePaths(currentDirectory, basePath));
18951900
}
1896-
return result;
1901+
1902+
return flatten(results);
18971903

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

19011909
for (const current of files) {
19021910
const name = combinePaths(path, current);
19031911
const absoluteName = combinePaths(absolutePath, current);
1904-
if ((!extensions || fileExtensionIsAny(name, extensions)) &&
1905-
(!includeFileRegex || includeFileRegex.test(absoluteName)) &&
1906-
(!excludeRegex || !excludeRegex.test(absoluteName))) {
1907-
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+
}
19081922
}
19091923
}
19101924

src/compiler/diagnosticMessages.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1783,6 +1783,10 @@
17831783
"category": "Error",
17841784
"code": 2544
17851785
},
1786+
"A mixin class must have a constructor with a single rest parameter of type 'any[]'.": {
1787+
"category": "Error",
1788+
"code": 2545
1789+
},
17861790
"JSX element attributes type '{0}' may not be a union type.": {
17871791
"category": "Error",
17881792
"code": 2600
@@ -1823,6 +1827,10 @@
18231827
"category": "Error",
18241828
"code": 2609
18251829
},
1830+
"Cannot augment module '{0}' with value exports because it resolves to a non-module entity.": {
1831+
"category": "Error",
1832+
"code": 2649
1833+
},
18261834
"Cannot emit namespaced JSX elements in React": {
18271835
"category": "Error",
18281836
"code": 2650
@@ -2713,7 +2721,7 @@
27132721
"category": "Message",
27142722
"code": 6079
27152723
},
2716-
"Specify JSX code generation: 'preserve' or 'react'": {
2724+
"Specify JSX code generation: 'preserve', 'react-native', or 'react'": {
27172725
"category": "Message",
27182726
"code": 6080
27192727
},
@@ -3263,6 +3271,10 @@
32633271
"category": "Message",
32643272
"code": 90007
32653273
},
3274+
"Add 'this.' to unresolved variable.": {
3275+
"category": "Message",
3276+
"code": 90008
3277+
},
32663278
"Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig": {
32673279
"category": "Error",
32683280
"code": 90009

src/compiler/emitter.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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
@@ -6693,10 +6693,15 @@ namespace ts {
66936693
typedefTag.fullName = parseJSDocTypeNameWithNamespace(/*flags*/ 0);
66946694
if (typedefTag.fullName) {
66956695
let rightNode = typedefTag.fullName;
6696-
while (rightNode.kind !== SyntaxKind.Identifier) {
6696+
while (true) {
6697+
if (rightNode.kind === SyntaxKind.Identifier || !rightNode.body) {
6698+
// if node is identifier - use it as name
6699+
// otherwise use name of the rightmost part that we were able to parse
6700+
typedefTag.name = rightNode.kind === SyntaxKind.Identifier ? rightNode : rightNode.name;
6701+
break;
6702+
}
66976703
rightNode = rightNode.body;
66986704
}
6699-
typedefTag.name = rightNode;
67006705
}
67016706
typedefTag.typeExpression = typeExpression;
67026707
skipWhitespace();

src/compiler/transformers/es2015.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2316,7 +2316,7 @@ namespace ts {
23162316
addRange(statements, convertedLoopBodyStatements);
23172317
}
23182318
else {
2319-
const statement = visitNode(node.statement, visitor, isStatement);
2319+
const statement = visitNode(node.statement, visitor, isStatement, /*optional*/ false, liftToBlock);
23202320
if (isBlock(statement)) {
23212321
addRange(statements, statement.statements);
23222322
bodyLocation = statement;

src/compiler/transformers/es5.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ namespace ts {
1111
export function transformES5(context: TransformationContext) {
1212
const compilerOptions = context.getCompilerOptions();
1313

14-
// enable emit notification only if using --jsx preserve
14+
// enable emit notification only if using --jsx preserve or react-native
1515
let previousOnEmitNode: (emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) => void;
1616
let noSubstitution: boolean[];
17-
if (compilerOptions.jsx === JsxEmit.Preserve) {
17+
if (compilerOptions.jsx === JsxEmit.Preserve || compilerOptions.jsx === JsxEmit.ReactNative) {
1818
previousOnEmitNode = context.onEmitNode;
1919
context.onEmitNode = onEmitNode;
2020
context.enableEmitNotification(SyntaxKind.JsxOpeningElement);
@@ -116,4 +116,4 @@ namespace ts {
116116
return undefined;
117117
}
118118
}
119-
}
119+
}

0 commit comments

Comments
 (0)