Skip to content

Commit

Permalink
Merge branch 'master' into stricterGenericChecks
Browse files Browse the repository at this point in the history
  • Loading branch information
ahejlsberg committed Jun 7, 2017
2 parents 3154a6c + 5888804 commit 50b24ee
Show file tree
Hide file tree
Showing 248 changed files with 7,832 additions and 462 deletions.
7 changes: 4 additions & 3 deletions Jakefile.js
Original file line number Diff line number Diff line change
Expand Up @@ -802,7 +802,8 @@ function runConsoleTests(defaultReporter, runInParallel) {

var debug = process.env.debug || process.env.d;
var inspect = process.env.inspect;
tests = process.env.test || process.env.tests || process.env.t;
var testTimeout = process.env.timeout || defaultTestTimeout;
var tests = process.env.test || process.env.tests || process.env.t;
var light = process.env.light || false;
var stackTraceLimit = process.env.stackTraceLimit;
var testConfigFile = 'test.config';
Expand All @@ -820,7 +821,7 @@ function runConsoleTests(defaultReporter, runInParallel) {
} while (fs.existsSync(taskConfigsFolder));
fs.mkdirSync(taskConfigsFolder);

workerCount = process.env.workerCount || os.cpus().length;
workerCount = process.env.workerCount || process.env.p || os.cpus().length;
}

if (tests || light || taskConfigsFolder) {
Expand Down Expand Up @@ -925,7 +926,7 @@ function runConsoleTests(defaultReporter, runInParallel) {
}
}

var testTimeout = 20000;
var defaultTestTimeout = 22000;
desc("Runs all the tests in parallel using the built run.js file. Optional arguments are: t[ests]=category1|category2|... d[ebug]=true.");
task("runtests-parallel", ["build-rules", "tests", builtLocalDirectory], function () {
runConsoleTests('min', /*runInParallel*/ true);
Expand Down
4 changes: 2 additions & 2 deletions scripts/tslint/nextLineRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export class Rule extends Lint.Rules.AbstractRule {

function walk(ctx: Lint.WalkContext<void>, checkCatch: boolean, checkElse: boolean): void {
const { sourceFile } = ctx;
function recur(node: ts.Node): void {
ts.forEachChild(sourceFile, function recur(node) {
switch (node.kind) {
case ts.SyntaxKind.IfStatement:
checkIf(node as ts.IfStatement);
Expand All @@ -28,7 +28,7 @@ function walk(ctx: Lint.WalkContext<void>, checkCatch: boolean, checkElse: boole
break;
}
ts.forEachChild(node, recur);
}
});

function checkIf(node: ts.IfStatement): void {
const { thenStatement, elseStatement } = node;
Expand Down
6 changes: 5 additions & 1 deletion src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2333,7 +2333,7 @@ namespace ts {
// A common practice in node modules is to set 'export = module.exports = {}', this ensures that 'exports'
// is still pointing to 'module.exports'.
// We do not want to consider this as 'export=' since a module can have only one of these.
// Similarlly we do not want to treat 'module.exports = exports' as an 'export='.
// Similarly we do not want to treat 'module.exports = exports' as an 'export='.
const assignedExpression = getRightMostAssignedExpression(node.right);
if (isEmptyObjectLiteral(assignedExpression) || isExportsOrModuleExportsOrAlias(assignedExpression)) {
// Mark it as a module in case there are no other exports in the file
Expand Down Expand Up @@ -2741,6 +2741,10 @@ namespace ts {
transformFlags |= TransformFlags.AssertES2015;
}

if (expression.kind === SyntaxKind.ImportKeyword) {
transformFlags |= TransformFlags.ContainsDynamicImport;
}

node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
return transformFlags & ~TransformFlags.ArrayLiteralOrCallOrNewExcludes;
}
Expand Down
175 changes: 147 additions & 28 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,12 @@ namespace ts {
"umd": ModuleKind.UMD,
"es6": ModuleKind.ES2015,
"es2015": ModuleKind.ES2015,
"esnext": ModuleKind.ESNext
}),
paramType: Diagnostics.KIND,
showInSimplifiedHelpView: true,
category: Diagnostics.Basic_Options,
description: Diagnostics.Specify_module_code_generation_Colon_commonjs_amd_system_umd_or_es2015,
description: Diagnostics.Specify_module_code_generation_Colon_commonjs_amd_system_umd_es2015_or_ESNext,
},
{
name: "lib",
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ namespace ts {
* @param array The array to map.
* @param mapfn The callback used to map the result into one or more values.
*/
export function flatMap<T, U>(array: T[], mapfn: (x: T, i: number) => U | U[]): U[] {
export function flatMap<T, U>(array: T[] | undefined, mapfn: (x: T, i: number) => U | U[] | undefined): U[] | undefined {
let result: U[];
if (array) {
result = [];
Expand Down
50 changes: 42 additions & 8 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,23 @@
"category": "Error",
"code": 1322
},
"Dynamic import cannot be used when targeting ECMAScript 2015 modules.": {
"category": "Error",
"code": 1323
},
"Dynamic import must have one specifier as an argument.": {
"category": "Error",
"code": 1324
},
"Specifier of dynamic import cannot be spread element.": {
"category": "Error",
"code": 1325
},
"Dynamic import cannot have type arguments": {
"category": "Error",
"code": 1326
},

"Duplicate identifier '{0}'.": {
"category": "Error",
"code": 2300
Expand Down Expand Up @@ -1927,10 +1944,6 @@
"category": "Error",
"code": 2649
},
"Cannot emit namespaced JSX elements in React.": {
"category": "Error",
"code": 2650
},
"A member initializer in a enum declaration cannot reference members declared after it, including members defined in other enums.": {
"category": "Error",
"code": 2651
Expand Down Expand Up @@ -2163,6 +2176,14 @@
"category": "Error",
"code": 2710
},
"A dynamic import call returns a 'Promise'. Make sure you have a declaration for 'Promise' or include 'ES2015' in your `--lib` option.": {
"category": "Error",
"code": 2711
},
"A dynamic import call in ES5/ES3 requires the 'Promise' constructor. Make sure you have a declaration for the 'Promise' constructor or include 'ES2015' in your `--lib` option.": {
"category": "Error",
"code": 2712
},

"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
Expand Down Expand Up @@ -2629,7 +2650,7 @@
"category": "Message",
"code": 6015
},
"Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'.": {
"Specify module code generation: 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'.": {
"category": "Message",
"code": 6016
},
Expand Down Expand Up @@ -3365,6 +3386,11 @@
"category": "Error",
"code": 7035
},
"Dynamic import's specifier must be of type 'string', but here has type '{0}'.": {
"category": "Error",
"code": 7036
},

"You cannot rename this element.": {
"category": "Error",
"code": 8000
Expand Down Expand Up @@ -3559,11 +3585,11 @@
"category": "Message",
"code": 90015
},
"Add declaration for missing property '{0}'.": {
"Declare property '{0}'.": {
"category": "Message",
"code": 90016
},
"Add index signature for missing property '{0}'.": {
"Add index signature for property '{0}'.": {
"category": "Message",
"code": 90017
},
Expand All @@ -3587,7 +3613,15 @@
"category": "Message",
"code": 90022
},

"Declare method '{0}'.": {
"category": "Message",
"code": 90023
},
"Declare static method '{0}'.": {
"category": "Message",
"code": 90024
},

"Convert function to an ES2015 class": {
"category": "Message",
"code": 95001
Expand Down
1 change: 1 addition & 0 deletions src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,7 @@ namespace ts {
case SyntaxKind.SuperKeyword:
case SyntaxKind.TrueKeyword:
case SyntaxKind.ThisKeyword:
case SyntaxKind.ImportKeyword:
writeTokenNode(node);
return;

Expand Down
1 change: 1 addition & 0 deletions src/compiler/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2503,6 +2503,7 @@ namespace ts {
helpers
} = sourceEmitNode;
if (!destEmitNode) destEmitNode = {};
// We are using `.slice()` here in case `destEmitNode.leadingComments` is pushed to later.
if (leadingComments) destEmitNode.leadingComments = addRange(leadingComments.slice(), destEmitNode.leadingComments);
if (trailingComments) destEmitNode.trailingComments = addRange(trailingComments.slice(), destEmitNode.trailingComments);
if (flags) destEmitNode.flags = flags;
Expand Down
81 changes: 56 additions & 25 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,16 @@ namespace ts {
}
}

// Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes
// stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise,
// embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns
// a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned.
/**
* Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes
* stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise,
* embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns
* a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned.
*
* @param node a given node to visit its children
* @param cbNode a callback to be invoked for all child nodes
* @param cbNodeArray a callback to be invoked for embedded array
*/
export function forEachChild<T>(node: Node, cbNode: (node: Node) => T | undefined, cbNodeArray?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
if (!node) {
return;
Expand Down Expand Up @@ -2409,7 +2415,7 @@ namespace ts {
if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
return parseSignatureMember(SyntaxKind.CallSignature);
}
if (token() === SyntaxKind.NewKeyword && lookAhead(isStartOfConstructSignature)) {
if (token() === SyntaxKind.NewKeyword && lookAhead(nextTokenIsOpenParenOrLessThan)) {
return parseSignatureMember(SyntaxKind.ConstructSignature);
}
const fullStart = getNodePos();
Expand All @@ -2420,7 +2426,7 @@ namespace ts {
return parsePropertyOrMethodSignature(fullStart, modifiers);
}

function isStartOfConstructSignature() {
function nextTokenIsOpenParenOrLessThan() {
nextToken();
return token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken;
}
Expand Down Expand Up @@ -2777,6 +2783,8 @@ namespace ts {
case SyntaxKind.SlashEqualsToken:
case SyntaxKind.Identifier:
return true;
case SyntaxKind.ImportKeyword:
return lookAhead(nextTokenIsOpenParenOrLessThan);
default:
return isIdentifier();
}
Expand Down Expand Up @@ -3509,10 +3517,10 @@ namespace ts {
* 5) --UnaryExpression[?Yield]
*/
if (isUpdateExpression()) {
const incrementExpression = parseIncrementExpression();
const updateExpression = parseUpdateExpression();
return token() === SyntaxKind.AsteriskAsteriskToken ?
<BinaryExpression>parseBinaryExpressionRest(getBinaryOperatorPrecedence(), incrementExpression) :
incrementExpression;
<BinaryExpression>parseBinaryExpressionRest(getBinaryOperatorPrecedence(), updateExpression) :
updateExpression;
}

/**
Expand Down Expand Up @@ -3578,7 +3586,7 @@ namespace ts {
}
// falls through
default:
return parseIncrementExpression();
return parseUpdateExpression();
}
}

Expand All @@ -3594,7 +3602,7 @@ namespace ts {
*/
function isUpdateExpression(): boolean {
// This function is called inside parseUnaryExpression to decide
// whether to call parseSimpleUnaryExpression or call parseIncrementExpression directly
// whether to call parseSimpleUnaryExpression or call parseUpdateExpression directly
switch (token()) {
case SyntaxKind.PlusToken:
case SyntaxKind.MinusToken:
Expand All @@ -3618,17 +3626,17 @@ namespace ts {
}

/**
* Parse ES7 IncrementExpression. IncrementExpression is used instead of ES6's PostFixExpression.
* Parse ES7 UpdateExpression. UpdateExpression is used instead of ES6's PostFixExpression.
*
* ES7 IncrementExpression[yield]:
* ES7 UpdateExpression[yield]:
* 1) LeftHandSideExpression[?yield]
* 2) LeftHandSideExpression[?yield] [[no LineTerminator here]]++
* 3) LeftHandSideExpression[?yield] [[no LineTerminator here]]--
* 4) ++LeftHandSideExpression[?yield]
* 5) --LeftHandSideExpression[?yield]
* In TypeScript (2), (3) are parsed as PostfixUnaryExpression. (4), (5) are parsed as PrefixUnaryExpression
*/
function parseIncrementExpression(): IncrementExpression {
function parseUpdateExpression(): UpdateExpression {
if (token() === SyntaxKind.PlusPlusToken || token() === SyntaxKind.MinusMinusToken) {
const node = <PrefixUnaryExpression>createNode(SyntaxKind.PrefixUnaryExpression);
node.operator = <PrefixUnaryOperator>token();
Expand Down Expand Up @@ -3678,25 +3686,35 @@ namespace ts {
// CallExpression Arguments
// CallExpression[Expression]
// CallExpression.IdentifierName
// super ( ArgumentListopt )
// import (AssignmentExpression)
// super Arguments
// super.IdentifierName
//
// Because of the recursion in these calls, we need to bottom out first. There are two
// bottom out states we can run into. Either we see 'super' which must start either of
// the last two CallExpression productions. Or we have a MemberExpression which either
// completes the LeftHandSideExpression, or starts the beginning of the first four
// CallExpression productions.
const expression = token() === SyntaxKind.SuperKeyword
? parseSuperExpression()
: parseMemberExpressionOrHigher();
// Because of the recursion in these calls, we need to bottom out first. There are three
// bottom out states we can run into: 1) We see 'super' which must start either of
// the last two CallExpression productions. 2) We see 'import' which must start import call.
// 3)we have a MemberExpression which either completes the LeftHandSideExpression,
// or starts the beginning of the first four CallExpression productions.
let expression: MemberExpression;
if (token() === SyntaxKind.ImportKeyword) {
// We don't want to eagerly consume all import keyword as import call expression so we look a head to find "("
// For example:
// var foo3 = require("subfolder
// import * as foo1 from "module-from-node -> we want this import to be a statement rather than import call expression
sourceFile.flags |= NodeFlags.PossiblyContainDynamicImport;
expression = parseTokenNode<PrimaryExpression>();
}
else {
expression = token() === SyntaxKind.SuperKeyword ? parseSuperExpression() : parseMemberExpressionOrHigher();
}

// Now, we *may* be complete. However, we might have consumed the start of a
// CallExpression. As such, we need to consume the rest of it here to be complete.
return parseCallExpressionRest(expression);
}

function parseMemberExpressionOrHigher(): MemberExpression {
// Note: to make our lives simpler, we decompose the the NewExpression productions and
// Note: to make our lives simpler, we decompose the NewExpression productions and
// place ObjectCreationExpression and FunctionExpression into PrimaryExpression.
// like so:
//
Expand Down Expand Up @@ -4792,9 +4810,11 @@ namespace ts {
case SyntaxKind.FinallyKeyword:
return true;

case SyntaxKind.ImportKeyword:
return isStartOfDeclaration() || lookAhead(nextTokenIsOpenParenOrLessThan);

case SyntaxKind.ConstKeyword:
case SyntaxKind.ExportKeyword:
case SyntaxKind.ImportKeyword:
return isStartOfDeclaration();

case SyntaxKind.AsyncKeyword:
Expand Down Expand Up @@ -6513,6 +6533,10 @@ namespace ts {
case "augments":
tag = parseAugmentsTag(atToken, tagName);
break;
case "class":
case "constructor":
tag = parseClassTag(atToken, tagName);
break;
case "arg":
case "argument":
case "param":
Expand Down Expand Up @@ -6732,6 +6756,13 @@ namespace ts {
return finishNode(result);
}

function parseClassTag(atToken: AtToken, tagName: Identifier): JSDocClassTag {
const tag = <JSDocClassTag>createNode(SyntaxKind.JSDocClassTag, atToken.pos);
tag.atToken = atToken;
tag.tagName = tagName;
return finishNode(tag);
}

function parseTypedefTag(atToken: AtToken, tagName: Identifier): JSDocTypedefTag {
const typeExpression = tryParseTypeExpression();
skipWhitespace();
Expand Down
Loading

0 comments on commit 50b24ee

Please sign in to comment.