Skip to content

Commit 42c0816

Browse files
author
Kanchalai Tanglertsampan
committed
Merge branch 'master' into wip-master-statelessOverload
2 parents ceb7720 + 445421b commit 42c0816

File tree

79 files changed

+3463
-391
lines changed

Some content is hidden

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

79 files changed

+3463
-391
lines changed

src/compiler/checker.ts

Lines changed: 106 additions & 22 deletions
Large diffs are not rendered by default.

src/compiler/commandLineParser.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1258,7 +1258,6 @@ namespace ts {
12581258

12591259
const literalFiles = arrayFrom(literalFileMap.values());
12601260
const wildcardFiles = arrayFrom(wildcardFileMap.values());
1261-
wildcardFiles.sort(host.useCaseSensitiveFileNames ? compareStrings : compareStringsCaseInsensitive);
12621261
return {
12631262
fileNames: literalFiles.concat(wildcardFiles),
12641263
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: 8 additions & 0 deletions
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
@@ -3267,6 +3271,10 @@
32673271
"category": "Message",
32683272
"code": 90007
32693273
},
3274+
"Add 'this.' to unresolved variable.": {
3275+
"category": "Message",
3276+
"code": 90008
3277+
},
32703278
"Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig": {
32713279
"category": "Error",
32723280
"code": 90009

src/compiler/emitter.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,9 +1056,11 @@ namespace ts {
10561056
// Also emit a dot if expression is a integer const enum value - it will appear in generated code as numeric literal
10571057
function needsDotDotForPropertyAccess(expression: Expression) {
10581058
if (expression.kind === SyntaxKind.NumericLiteral) {
1059-
// check if numeric literal was originally written with a dot
1059+
// check if numeric literal is a decimal literal that was originally written with a dot
10601060
const text = getLiteralTextOfNode(<LiteralExpression>expression);
1061-
return text.indexOf(tokenToString(SyntaxKind.DotToken)) < 0;
1061+
return getNumericLiteralFlags(text, /*hint*/ NumericLiteralFlags.All) === NumericLiteralFlags.None
1062+
&& !(<LiteralExpression>expression).isOctalLiteral
1063+
&& text.indexOf(tokenToString(SyntaxKind.DotToken)) < 0;
10621064
}
10631065
else if (isPropertyAccessExpression(expression) || isElementAccessExpression(expression)) {
10641066
// 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
@@ -6701,10 +6701,15 @@ namespace ts {
67016701
typedefTag.fullName = parseJSDocTypeNameWithNamespace(/*flags*/ 0);
67026702
if (typedefTag.fullName) {
67036703
let rightNode = typedefTag.fullName;
6704-
while (rightNode.kind !== SyntaxKind.Identifier) {
6704+
while (true) {
6705+
if (rightNode.kind === SyntaxKind.Identifier || !rightNode.body) {
6706+
// if node is identifier - use it as name
6707+
// otherwise use name of the rightmost part that we were able to parse
6708+
typedefTag.name = rightNode.kind === SyntaxKind.Identifier ? rightNode : rightNode.name;
6709+
break;
6710+
}
67056711
rightNode = rightNode.body;
67066712
}
6707-
typedefTag.name = rightNode;
67086713
}
67096714
typedefTag.typeExpression = typeExpression;
67106715
skipWhitespace();

src/compiler/transformers/esnext.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,11 @@ namespace ts {
402402
};
403403

404404
export function createAssignHelper(context: TransformationContext, attributesSegments: Expression[]) {
405+
if (context.getCompilerOptions().target >= ScriptTarget.ES2015) {
406+
return createCall(createPropertyAccess(createIdentifier("Object"), "assign"),
407+
/*typeArguments*/ undefined,
408+
attributesSegments);
409+
}
405410
context.requestEmitHelper(assignHelper);
406411
return createCall(
407412
getHelperName("__assign"),

src/compiler/utilities.ts

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -341,16 +341,52 @@ namespace ts {
341341
}
342342

343343
export function isBinaryOrOctalIntegerLiteral(node: LiteralLikeNode, text: string) {
344-
if (node.kind === SyntaxKind.NumericLiteral && text.length > 1) {
344+
return node.kind === SyntaxKind.NumericLiteral
345+
&& (getNumericLiteralFlags(text, /*hint*/ NumericLiteralFlags.BinaryOrOctal) & NumericLiteralFlags.BinaryOrOctal) !== 0;
346+
}
347+
348+
export const enum NumericLiteralFlags {
349+
None = 0,
350+
Hexadecimal = 1 << 0,
351+
Binary = 1 << 1,
352+
Octal = 1 << 2,
353+
Scientific = 1 << 3,
354+
355+
BinaryOrOctal = Binary | Octal,
356+
BinaryOrOctalOrHexadecimal = BinaryOrOctal | Hexadecimal,
357+
All = Hexadecimal | Binary | Octal | Scientific,
358+
}
359+
360+
/**
361+
* Scans a numeric literal string to determine the form of the number.
362+
* @param text Numeric literal text
363+
* @param hint If `Scientific` or `All` is specified, performs a more expensive check to scan for scientific notation.
364+
*/
365+
export function getNumericLiteralFlags(text: string, hint?: NumericLiteralFlags) {
366+
if (text.length > 1) {
345367
switch (text.charCodeAt(1)) {
346368
case CharacterCodes.b:
347369
case CharacterCodes.B:
370+
return NumericLiteralFlags.Binary;
348371
case CharacterCodes.o:
349372
case CharacterCodes.O:
350-
return true;
373+
return NumericLiteralFlags.Octal;
374+
case CharacterCodes.x:
375+
case CharacterCodes.X:
376+
return NumericLiteralFlags.Hexadecimal;
377+
}
378+
379+
if (hint & NumericLiteralFlags.Scientific) {
380+
for (let i = text.length - 1; i >= 0; i--) {
381+
switch (text.charCodeAt(i)) {
382+
case CharacterCodes.e:
383+
case CharacterCodes.E:
384+
return NumericLiteralFlags.Scientific;
385+
}
386+
}
351387
}
352388
}
353-
return false;
389+
return NumericLiteralFlags.None;
354390
}
355391

356392
function getQuotedEscapedLiteralText(leftQuote: string, text: string, rightQuote: string) {
@@ -395,7 +431,7 @@ namespace ts {
395431

396432
function isShorthandAmbientModule(node: Node): boolean {
397433
// The only kind of module that can be missing a body is a shorthand ambient module.
398-
return node.kind === SyntaxKind.ModuleDeclaration && (!(<ModuleDeclaration>node).body);
434+
return node && node.kind === SyntaxKind.ModuleDeclaration && (!(<ModuleDeclaration>node).body);
399435
}
400436

401437
export function isBlockScopedContainerTopLevel(node: Node): boolean {
@@ -1667,11 +1703,15 @@ namespace ts {
16671703
node = parent;
16681704
break;
16691705
case SyntaxKind.ShorthandPropertyAssignment:
1670-
if ((<ShorthandPropertyAssignment>parent).name !== node) {
1706+
if ((parent as ShorthandPropertyAssignment).name !== node) {
16711707
return AssignmentKind.None;
16721708
}
1673-
// Fall through
1709+
node = parent.parent;
1710+
break;
16741711
case SyntaxKind.PropertyAssignment:
1712+
if ((parent as ShorthandPropertyAssignment).name === node) {
1713+
return AssignmentKind.None;
1714+
}
16751715
node = parent.parent;
16761716
break;
16771717
default:
@@ -1683,7 +1723,8 @@ namespace ts {
16831723

16841724
// A node is an assignment target if it is on the left hand side of an '=' token, if it is parented by a property
16851725
// assignment in an object literal that is an assignment target, or if it is parented by an array literal that is
1686-
// an assignment target. Examples include 'a = xxx', '{ p: a } = xxx', '[{ p: a}] = xxx'.
1726+
// an assignment target. Examples include 'a = xxx', '{ p: a } = xxx', '[{ a }] = xxx'.
1727+
// (Note that `p` is not a target in the above examples, only `a`.)
16871728
export function isAssignmentTarget(node: Node): boolean {
16881729
return getAssignmentTargetKind(node) !== AssignmentKind.None;
16891730
}
@@ -3109,7 +3150,11 @@ namespace ts {
31093150
}
31103151

31113152
export function getLocalSymbolForExportDefault(symbol: Symbol) {
3112-
return symbol && symbol.valueDeclaration && hasModifier(symbol.valueDeclaration, ModifierFlags.Default) ? symbol.valueDeclaration.localSymbol : undefined;
3153+
return isExportDefaultSymbol(symbol) ? symbol.valueDeclaration.localSymbol : undefined;
3154+
}
3155+
3156+
export function isExportDefaultSymbol(symbol: Symbol): boolean {
3157+
return symbol && symbol.valueDeclaration && hasModifier(symbol.valueDeclaration, ModifierFlags.Default);
31133158
}
31143159

31153160
/** Return ".ts", ".d.ts", or ".tsx", if that is the extension. */

0 commit comments

Comments
 (0)