Merge branch 'release-1.8' into checksuperbeforethislexically

This commit is contained in:
Kanchalai Tanglertsampan
2016-02-08 10:43:41 -08:00
154 changed files with 3632 additions and 160 deletions
+14 -5
View File
@@ -1384,7 +1384,7 @@ namespace ts {
// Export assignment in some sort of block construct
bindAnonymousDeclaration(node, SymbolFlags.Alias, getDeclarationName(node));
}
else if (boundExpression.kind === SyntaxKind.Identifier) {
else if (boundExpression.kind === SyntaxKind.Identifier && node.kind === SyntaxKind.ExportAssignment) {
// An export default clause with an identifier exports all meanings of that identifier
declareSymbol(container.symbol.exports, container.symbol, node, SymbolFlags.Alias, SymbolFlags.PropertyExcludes | SymbolFlags.AliasExcludes);
}
@@ -1435,7 +1435,8 @@ namespace ts {
// Declare a 'member' in case it turns out the container was an ES5 class
if (container.kind === SyntaxKind.FunctionExpression || container.kind === SyntaxKind.FunctionDeclaration) {
container.symbol.members = container.symbol.members || {};
declareSymbol(container.symbol.members, container.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
// It's acceptable for multiple 'this' assignments of the same identifier to occur
declareSymbol(container.symbol.members, container.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property);
}
}
@@ -1444,8 +1445,16 @@ namespace ts {
// Look up the function in the local scope, since prototype assignments should
// follow the function declaration
const classId = <Identifier>(<PropertyAccessExpression>(<PropertyAccessExpression>node.left).expression).expression;
const funcSymbol = container.locals[classId.text];
const leftSideOfAssignment = node.left as PropertyAccessExpression;
const classPrototype = leftSideOfAssignment.expression as PropertyAccessExpression;
const constructorFunction = classPrototype.expression as Identifier;
// Fix up parent pointers since we're going to use these nodes before we bind into them
leftSideOfAssignment.parent = node;
constructorFunction.parent = classPrototype;
classPrototype.parent = leftSideOfAssignment;
const funcSymbol = container.locals[constructorFunction.text];
if (!funcSymbol || !(funcSymbol.flags & SymbolFlags.Function)) {
return;
}
@@ -1456,7 +1465,7 @@ namespace ts {
}
// Declare the method/property
declareSymbol(funcSymbol.members, funcSymbol, <PropertyAccessExpression>node.left, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
declareSymbol(funcSymbol.members, funcSymbol, leftSideOfAssignment, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
}
function bindCallExpression(node: CallExpression) {
+64 -3
View File
@@ -2845,7 +2845,7 @@ namespace ts {
}
// Handle module.exports = expr
if (declaration.kind === SyntaxKind.BinaryExpression) {
return links.type = checkExpression((<BinaryExpression>declaration).right);
return links.type = getUnionType(map(symbol.declarations, (decl: BinaryExpression) => checkExpressionCached(decl.right)));
}
if (declaration.kind === SyntaxKind.PropertyAccessExpression) {
// Declarations only exist for property access expressions for certain
@@ -7242,6 +7242,15 @@ namespace ts {
// mark iteration statement as containing block-scoped binding captured in some function
getNodeLinks(current).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding;
}
// mark variables that are declared in loop initializer and reassigned inside the body of ForStatement.
// if body of ForStatement will be converted to function then we'll need a extra machinery to propagate reassigned values back.
if (container.kind === SyntaxKind.ForStatement &&
getAncestor(symbol.valueDeclaration, SyntaxKind.VariableDeclarationList).parent === container &&
isAssignedInBodyOfForStatement(node, <ForStatement>container)) {
getNodeLinks(symbol.valueDeclaration).flags |= NodeCheckFlags.NeedsLoopOutParameter;
}
// set 'declared inside loop' bit on the block-scoped binding
getNodeLinks(symbol.valueDeclaration).flags |= NodeCheckFlags.BlockScopedBindingInLoop;
}
@@ -7251,6 +7260,41 @@ namespace ts {
}
}
function isAssignedInBodyOfForStatement(node: Identifier, container: ForStatement): boolean {
let current: Node = node;
// skip parenthesized nodes
while (current.parent.kind === SyntaxKind.ParenthesizedExpression) {
current = current.parent;
}
// check if node is used as LHS in some assignment expression
let isAssigned = false;
if (current.parent.kind === SyntaxKind.BinaryExpression) {
isAssigned = (<BinaryExpression>current.parent).left === current && isAssignmentOperator((<BinaryExpression>current.parent).operatorToken.kind);
}
if ((current.parent.kind === SyntaxKind.PrefixUnaryExpression || current.parent.kind === SyntaxKind.PostfixUnaryExpression)) {
const expr = <PrefixUnaryExpression | PostfixUnaryExpression>current.parent;
isAssigned = expr.operator === SyntaxKind.PlusPlusToken || expr.operator === SyntaxKind.MinusMinusToken;
}
if (!isAssigned) {
return false;
}
// at this point we know that node is the target of assignment
// now check that modification happens inside the statement part of the ForStatement
while (current !== container) {
if (current === container.statement) {
return true;
}
else {
current = current.parent;
}
}
return false;
}
function captureLexicalThis(node: Node, container: Node): void {
getNodeLinks(node).flags |= NodeCheckFlags.LexicalThis;
if (container.kind === SyntaxKind.PropertyDeclaration || container.kind === SyntaxKind.Constructor) {
@@ -10412,9 +10456,11 @@ namespace ts {
function getReturnTypeFromJSDocComment(func: SignatureDeclaration | FunctionDeclaration): Type {
const returnTag = getJSDocReturnTag(func);
if (returnTag) {
if (returnTag && returnTag.typeExpression) {
return getTypeFromTypeNode(returnTag.typeExpression.type);
}
return undefined;
}
function createPromiseType(promisedType: Type): Type {
@@ -10489,7 +10535,8 @@ namespace ts {
}
else {
error(func, Diagnostics.No_best_common_type_exists_among_return_expressions);
return unknownType;
// Defer to unioning the return types so we get a) downstream errors earlier and b) better Salsa experience
return getUnionType(types);
}
}
@@ -15400,6 +15447,20 @@ namespace ts {
return getSymbolOfNode(entityName.parent);
}
if (isInJavaScriptFile(entityName) && entityName.parent.kind === SyntaxKind.PropertyAccessExpression) {
const specialPropertyAssignmentKind = getSpecialPropertyAssignmentKind(entityName.parent.parent);
switch (specialPropertyAssignmentKind) {
case SpecialPropertyAssignmentKind.ExportsProperty:
case SpecialPropertyAssignmentKind.PrototypeProperty:
return getSymbolOfNode(entityName.parent);
case SpecialPropertyAssignmentKind.ThisProperty:
case SpecialPropertyAssignmentKind.ModuleExports:
return getSymbolOfNode(entityName.parent.parent);
default:
// Fall through if it is not a special property assignment
}
}
if (entityName.parent.kind === SyntaxKind.ExportAssignment) {
return resolveEntityName(<Identifier>entityName,
/*all meanings*/ SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias);
+5
View File
@@ -294,6 +294,11 @@ namespace ts {
name: "allowJs",
type: "boolean",
description: Diagnostics.Allow_javascript_files_to_be_compiled
},
{
name: "noImplicitUseStrict",
type: "boolean",
description: Diagnostics.Do_not_emit_use_strict_directives_in_module_output
}
];
-4
View File
@@ -695,10 +695,6 @@ namespace ts {
}
function writeImportDeclaration(node: ImportDeclaration) {
if (!node.importClause && !(node.flags & NodeFlags.Export)) {
// do not write non-exported import declarations that don't have import clauses
return;
}
emitJsDocComments(node);
if (node.flags & NodeFlags.Export) {
write("export ");
+21 -16
View File
@@ -1,4 +1,4 @@
{
{
"Unterminated string literal.": {
"category": "Error",
"code": 1002
@@ -2171,6 +2171,7 @@
"category": "Error",
"code": 5059
},
"Concatenate and emit output to single file.": {
"category": "Message",
@@ -2216,10 +2217,10 @@
"category": "Message",
"code": 6011
},
"Specify ECMAScript target version: 'ES3' (default), 'ES5', or 'ES2015' (experimental)": {
"category": "Message",
"code": 6015
},
"Specify ECMAScript target version: 'ES3' (default), 'ES5', or 'ES2015' (experimental)": {
"category": "Message",
"code": 6015
},
"Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'": {
"category": "Message",
"code": 6016
@@ -2445,6 +2446,10 @@
"category": "Message",
"code": 6084
},
"Do not emit 'use strict' directives in module output.": {
"category": "Message",
"code": 6112
},
"Variable '{0}' implicitly has an '{1}' type.": {
"category": "Error",
@@ -2632,23 +2637,23 @@
"code": 17004
},
"A constructor cannot contain a 'super' call when its class extends 'null'": {
"category": "Error",
"code": 17005
"category": "Error",
"code": 17005
},
"An unary expression with the '{0}' operator is not allowed in the left-hand side of an exponentiation expression. Consider enclosing the expression in parentheses.": {
"category": "Error",
"code": 17006
"category": "Error",
"code": 17006
},
"A type assertion expression is not allowed in the left-hand side of an exponentiation expression. Consider enclosing the expression in parentheses.": {
"category": "Error",
"code": 17007
"category": "Error",
"code": 17007
},
"JSX element '{0}' has no corresponding closing tag.": {
"category": "Error",
"code": 17008
"category": "Error",
"code": 17008
},
"'super' must be called before accessing 'this' in the constructor of a derived class.": {
"category": "Error",
"code": 17009
"category": "Error",
"code": 17009
}
}
}
+151 -38
View File
@@ -287,6 +287,54 @@ namespace ts {
_i = 0x10000000, // Use/preference flag for '_i'
}
const enum CopyDirection {
ToOriginal,
ToOutParameter
}
/**
* If loop contains block scoped binding captured in some function then loop body is converted to a function.
* Lexical bindings declared in loop initializer will be passed into the loop body function as parameters,
* however if this binding is modified inside the body - this new value should be propagated back to the original binding.
* This is done by declaring new variable (out parameter holder) outside of the loop for every binding that is reassigned inside the body.
* On every iteration this variable is initialized with value of corresponding binding.
* At every point where control flow leaves the loop either explicitly (break/continue) or implicitly (at the end of loop body)
* we copy the value inside the loop to the out parameter holder.
*
* for (let x;;) {
* let a = 1;
* let b = () => a;
* x++
* if (...) break;
* ...
* }
*
* will be converted to
*
* var out_x;
* var loop = function(x) {
* var a = 1;
* var b = function() { return a; }
* x++;
* if (...) return out_x = x, "break";
* ...
* out_x = x;
* }
* for (var x;;) {
* out_x = x;
* var state = loop(x);
* x = out_x;
* if (state === "break") break;
* }
*
* NOTE: values to out parameters are not copies if loop is abrupted with 'return' - in this case this will end the entire enclosing function
* so nobody can observe this new value.
*/
interface LoopOutParameter {
originalName: Identifier;
outParamName: string;
}
// targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile): EmitResult {
// emit output for the __extends helper function
@@ -419,6 +467,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
* for (var x;;) loop(x);
*/
hoistedLocalVariables?: Identifier[];
/**
* List of loop out parameters - detailed descripion can be found in the comment to LoopOutParameter
*/
loopOutParameters?: LoopOutParameter[];
}
function setLabeledJump(state: ConvertedLoopState, isBreak: boolean, labelText: string, labelMarker: string): void {
@@ -2944,11 +2997,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
}
let loopParameters: string[];
let loopOutParameters: LoopOutParameter[];
if (loopInitializer && (getCombinedNodeFlags(loopInitializer) & NodeFlags.BlockScoped)) {
// if loop initializer contains block scoped variables - they should be passed to converted loop body as parameters
loopParameters = [];
for (const varDeclaration of loopInitializer.declarations) {
collectNames(varDeclaration.name);
processVariableDeclaration(varDeclaration.name);
}
}
@@ -2958,14 +3012,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
writeLine();
write(`var ${functionName} = function(${paramList})`);
if (!bodyIsBlock) {
write(" {");
writeLine();
increaseIndent();
}
const convertedOuterLoopState = convertedLoopState;
convertedLoopState = {};
convertedLoopState = { loopOutParameters };
if (convertedOuterLoopState) {
// convertedOuterLoopState !== undefined means that this converted loop is nested in another converted loop.
@@ -2989,16 +3037,38 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
}
}
emitEmbeddedStatement(node.statement);
write(" {");
writeLine();
increaseIndent();
if (!bodyIsBlock) {
decreaseIndent();
writeLine();
write("}");
if (bodyIsBlock) {
emitLines((<Block>node.statement).statements);
}
write(";");
else {
emit(node.statement);
}
writeLine();
// end of loop body -> copy out parameter
copyLoopOutParameters(convertedLoopState, CopyDirection.ToOutParameter, /*emitAsStatements*/true);
decreaseIndent();
writeLine();
write("};");
writeLine();
if (loopOutParameters) {
// declare variables to hold out params for loop body
write(`var `);
for (let i = 0; i < loopOutParameters.length; i++) {
if (i !== 0) {
write(", ");
}
write(loopOutParameters[i].outParamName);
}
write(";");
writeLine();
}
if (convertedLoopState.argumentsName) {
// if alias for arguments is set
if (convertedOuterLoopState) {
@@ -3062,14 +3132,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
return { functionName, paramList, state: currentLoopState };
function collectNames(name: Identifier | BindingPattern): void {
function processVariableDeclaration(name: Identifier | BindingPattern): void {
if (name.kind === SyntaxKind.Identifier) {
const nameText = isNameOfNestedBlockScopedRedeclarationOrCapturedBinding(<Identifier>name) ? getGeneratedNameForNode(name) : (<Identifier>name).text;
const nameText = isNameOfNestedBlockScopedRedeclarationOrCapturedBinding(<Identifier>name)
? getGeneratedNameForNode(name)
: (<Identifier>name).text;
loopParameters.push(nameText);
if (resolver.getNodeCheckFlags(name.parent) & NodeCheckFlags.NeedsLoopOutParameter) {
const reassignedVariable = { originalName: <Identifier>name, outParamName: makeUniqueName(`out_${nameText}`) };
(loopOutParameters || (loopOutParameters = [])).push(reassignedVariable);
}
}
else {
for (const element of (<BindingPattern>name).elements) {
collectNames(element.name);
processVariableDeclaration(element.name);
}
}
}
@@ -3100,6 +3177,28 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
}
}
function copyLoopOutParameters(state: ConvertedLoopState, copyDirection: CopyDirection, emitAsStatements: boolean) {
if (state.loopOutParameters) {
for (const outParam of state.loopOutParameters) {
if (copyDirection === CopyDirection.ToOriginal) {
emitIdentifier(outParam.originalName);
write(` = ${outParam.outParamName}`);
}
else {
write(`${outParam.outParamName} = `);
emitIdentifier(outParam.originalName);
}
if (emitAsStatements) {
write(";");
writeLine();
}
else {
write(", ");
}
}
}
}
function emitConvertedLoopCall(loop: ConvertedLoop, emitAsBlock: boolean): void {
if (emitAsBlock) {
write(" {");
@@ -3120,6 +3219,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
}
write(`${loop.functionName}(${loop.paramList});`);
writeLine();
copyLoopOutParameters(loop.state, CopyDirection.ToOriginal, /*emitAsStatements*/ true);
if (!isSimpleLoop) {
// for non simple loops we need to store result returned from converted loop function and use it to do dispatching
@@ -3138,7 +3240,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
}
else {
// top level converted loop - return unwrapped value
write(`return ${loopResult}.value`);
write(`return ${loopResult}.value;`);
}
writeLine();
}
@@ -3439,14 +3541,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
(!node.label && (convertedLoopState.allowedNonLabeledJumps & jump));
if (!canUseBreakOrContinue) {
write ("return ");
// explicit exit from loop -> copy out parameters
copyLoopOutParameters(convertedLoopState, CopyDirection.ToOutParameter, /*emitAsStatements*/ false);
if (!node.label) {
if (node.kind === SyntaxKind.BreakStatement) {
convertedLoopState.nonLocalJumps |= Jump.Break;
write(`return "break";`);
write(`"break";`);
}
else {
convertedLoopState.nonLocalJumps |= Jump.Continue;
write(`return "continue";`);
write(`"continue";`);
}
}
else {
@@ -3459,7 +3564,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
labelMarker = `continue-${node.label.text}`;
setLabeledJump(convertedLoopState, /*isBreak*/ false, node.label.text, labelMarker);
}
write(`return "${labelMarker}";`);
write(`"${labelMarker}";`);
}
return;
@@ -4766,18 +4871,24 @@ const _super = (function (geti, seti) {
emitToken(SyntaxKind.CloseBraceToken, body.statements.end);
}
function findInitialSuperCall(ctor: ConstructorDeclaration): ExpressionStatement {
if (ctor.body) {
const statement = (<Block>ctor.body).statements[0];
if (statement && statement.kind === SyntaxKind.ExpressionStatement) {
const expr = (<ExpressionStatement>statement).expression;
if (expr && expr.kind === SyntaxKind.CallExpression) {
const func = (<CallExpression>expr).expression;
if (func && func.kind === SyntaxKind.SuperKeyword) {
return <ExpressionStatement>statement;
}
}
}
/**
* Return the statement at a given index if it is a super-call statement
* @param ctor a constructor declaration
* @param index an index to constructor's body to check
*/
function getSuperCallAtGivenIndex(ctor: ConstructorDeclaration, index: number): ExpressionStatement {
if (!ctor.body) {
return undefined;
}
const statements = ctor.body.statements;
if (!statements || index >= statements.length) {
return undefined;
}
const statement = statements[index];
if (statement.kind === SyntaxKind.ExpressionStatement) {
return isSuperCallExpression((<ExpressionStatement>statement).expression) ? <ExpressionStatement>statement : undefined;
}
}
@@ -5061,13 +5172,15 @@ const _super = (function (geti, seti) {
if (ctor) {
emitDefaultValueAssignments(ctor);
emitRestParameter(ctor);
if (baseTypeElement) {
superCall = findInitialSuperCall(ctor);
superCall = getSuperCallAtGivenIndex(ctor, startIndex);
if (superCall) {
writeLine();
emit(superCall);
}
}
emitParameterPropertyAssignments(ctor);
}
else {
@@ -7155,7 +7268,7 @@ const _super = (function (geti, seti) {
write(`], function(${exportFunctionForFile}, ${contextObjectForFile}) {`);
writeLine();
increaseIndent();
const startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ true, /*ensureUseStrict*/ true);
const startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ true, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict);
writeLine();
write(`var __moduleName = ${contextObjectForFile} && ${contextObjectForFile}.id;`);
writeLine();
@@ -7261,7 +7374,7 @@ const _super = (function (geti, seti) {
writeModuleName(node, emitRelativePathAsModuleName);
emitAMDDependencies(node, /*includeNonAmdDependencies*/ true, emitRelativePathAsModuleName);
increaseIndent();
const startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ true, /*ensureUseStrict*/ true);
const startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ true, /*ensureUseStrict*/!compilerOptions.noImplicitUseStrict);
emitExportStarHelper();
emitCaptureThisForNodeIfNecessary(node);
emitLinesStartingAt(node.statements, startIndex);
@@ -7273,7 +7386,7 @@ const _super = (function (geti, seti) {
}
function emitCommonJSModule(node: SourceFile) {
const startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ false, /*ensureUseStrict*/ true);
const startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ false, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict);
emitEmitHelpers(node);
collectExternalModuleInfo(node);
emitExportStarHelper();
@@ -7302,7 +7415,7 @@ const _super = (function (geti, seti) {
})(`);
emitAMDFactoryHeader(dependencyNames);
increaseIndent();
const startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ true, /*ensureUseStrict*/ true);
const startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ true, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict);
emitExportStarHelper();
emitCaptureThisForNodeIfNecessary(node);
emitLinesStartingAt(node.statements, startIndex);
+23 -14
View File
@@ -3995,7 +3995,7 @@ namespace ts {
shorthandDeclaration.equalsToken = equalsToken;
shorthandDeclaration.objectAssignmentInitializer = allowInAnd(parseAssignmentExpressionOrHigher);
}
return finishNode(shorthandDeclaration);
return addJSDocComment(finishNode(shorthandDeclaration));
}
else {
const propertyAssignment = <PropertyAssignment>createNode(SyntaxKind.PropertyAssignment, fullStart);
@@ -4004,7 +4004,7 @@ namespace ts {
propertyAssignment.questionToken = questionToken;
parseExpected(SyntaxKind.ColonToken);
propertyAssignment.initializer = allowInAnd(parseAssignmentExpressionOrHigher);
return finishNode(propertyAssignment);
return addJSDocComment(finishNode(propertyAssignment));
}
}
@@ -4051,7 +4051,7 @@ namespace ts {
setDecoratorContext(/*val*/ true);
}
return finishNode(node);
return addJSDocComment(finishNode(node));
}
function parseOptionalIdentifier() {
@@ -4335,13 +4335,13 @@ namespace ts {
const labeledStatement = <LabeledStatement>createNode(SyntaxKind.LabeledStatement, fullStart);
labeledStatement.label = <Identifier>expression;
labeledStatement.statement = parseStatement();
return finishNode(labeledStatement);
return addJSDocComment(finishNode(labeledStatement));
}
else {
const expressionStatement = <ExpressionStatement>createNode(SyntaxKind.ExpressionStatement, fullStart);
expressionStatement.expression = expression;
parseSemicolon();
return finishNode(expressionStatement);
return addJSDocComment(finishNode(expressionStatement));
}
}
@@ -4778,7 +4778,7 @@ namespace ts {
parseExpected(SyntaxKind.ConstructorKeyword);
fillSignature(SyntaxKind.ColonToken, /*yieldContext*/ false, /*awaitContext*/ false, /*requireCompleteParameterList*/ false, node);
node.body = parseFunctionBlockOrSemicolon(/*isGenerator*/ false, /*isAsync*/ false, Diagnostics.or_expected);
return finishNode(node);
return addJSDocComment(finishNode(node));
}
function parseMethodDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray, asteriskToken: Node, name: PropertyName, questionToken: Node, diagnosticMessage?: DiagnosticMessage): MethodDeclaration {
@@ -4792,7 +4792,7 @@ namespace ts {
const isAsync = !!(method.flags & NodeFlags.Async);
fillSignature(SyntaxKind.ColonToken, /*yieldContext*/ isGenerator, /*awaitContext*/ isAsync, /*requireCompleteParameterList*/ false, method);
method.body = parseFunctionBlockOrSemicolon(isGenerator, isAsync, diagnosticMessage);
return finishNode(method);
return addJSDocComment(finishNode(method));
}
function parsePropertyDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray, name: PropertyName, questionToken: Node): ClassElement {
@@ -5758,6 +5758,9 @@ namespace ts {
function parseJSDocParameter(): ParameterDeclaration {
const parameter = <ParameterDeclaration>createNode(SyntaxKind.Parameter);
parameter.type = parseJSDocType();
if (parseOptional(SyntaxKind.EqualsToken)) {
parameter.questionToken = createNode(SyntaxKind.EqualsToken);
}
return finishNode(parameter);
}
@@ -5765,16 +5768,22 @@ namespace ts {
const result = <JSDocTypeReference>createNode(SyntaxKind.JSDocTypeReference);
result.name = parseSimplePropertyName();
while (parseOptional(SyntaxKind.DotToken)) {
if (token === SyntaxKind.LessThanToken) {
result.typeArguments = parseTypeArguments();
break;
}
else {
result.name = parseQualifiedName(result.name);
if (token === SyntaxKind.LessThanToken) {
result.typeArguments = parseTypeArguments();
}
else {
while (parseOptional(SyntaxKind.DotToken)) {
if (token === SyntaxKind.LessThanToken) {
result.typeArguments = parseTypeArguments();
break;
}
else {
result.name = parseQualifiedName(result.name);
}
}
}
return finishNode(result);
}
+3 -1
View File
@@ -2068,7 +2068,8 @@ namespace ts {
CapturedBlockScopedBinding = 0x00020000, // Block-scoped binding that is captured in some function
BlockScopedBindingInLoop = 0x00040000, // Block-scoped binding with declaration nested inside iteration statement
ClassWithBodyScopedClassBinding = 0x0080000, // Decorated class that contains a binding to itself inside of the class body.
BodyScopedClassBinding = 0x00100000, // Binding to a decorated class inside of the class's body.
BodyScopedClassBinding = 0x00100000, // Binding to a decorated class inside of the class's body.
NeedsLoopOutParameter = 0x00200000, // Block scoped binding whose value should be explicitly copied outside of the converted loop
}
/* @internal */
@@ -2434,6 +2435,7 @@ namespace ts {
forceConsistentCasingInFileNames?: boolean;
allowSyntheticDefaultImports?: boolean;
allowJs?: boolean;
noImplicitUseStrict?: boolean;
/* @internal */ stripInternal?: boolean;
// Skip checking lib.d.ts to help speed up tests.
+39 -3
View File
@@ -464,6 +464,10 @@ namespace ts {
return !!(getCombinedNodeFlags(node) & NodeFlags.Let);
}
export function isSuperCallExpression(n: Node): boolean {
return n.kind === SyntaxKind.CallExpression && (<CallExpression>n).expression.kind === SyntaxKind.SuperKeyword;
}
export function isPrologueDirective(node: Node): boolean {
return node.kind === SyntaxKind.ExpressionStatement && (<ExpressionStatement>node).expression.kind === SyntaxKind.StringLiteral;
}
@@ -1207,7 +1211,25 @@ namespace ts {
node.parent.parent.parent.kind === SyntaxKind.VariableStatement;
const variableStatementNode = isInitializerOfVariableDeclarationInStatement ? node.parent.parent.parent : undefined;
return variableStatementNode && variableStatementNode.jsDocComment;
if (variableStatementNode) {
return variableStatementNode.jsDocComment;
}
// Also recognize when the node is the RHS of an assignment expression
const parent = node.parent;
const isSourceOfAssignmentExpressionStatement =
parent && parent.parent &&
parent.kind === SyntaxKind.BinaryExpression &&
(parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken &&
parent.parent.kind === SyntaxKind.ExpressionStatement;
if (isSourceOfAssignmentExpressionStatement) {
return parent.parent.jsDocComment;
}
const isPropertyAssignmentExpression = parent && parent.kind === SyntaxKind.PropertyAssignment;
if (isPropertyAssignmentExpression) {
return parent.jsDocComment;
}
}
return undefined;
@@ -2018,8 +2040,22 @@ namespace ts {
}
function onSingleFileEmit(host: EmitHost, sourceFile: SourceFile) {
const jsFilePath = getOwnEmitOutputFilePath(sourceFile, host,
sourceFile.languageVariant === LanguageVariant.JSX && options.jsx === JsxEmit.Preserve ? ".jsx" : ".js");
// JavaScript files are always LanguageVariant.JSX, as JSX syntax is allowed in .js files also.
// So for JavaScript files, '.jsx' is only emitted if the input was '.jsx', and JsxEmit.Preserve.
// For TypeScript, the only time to emit with a '.jsx' extension, is on JSX input, and JsxEmit.Preserve
let extension = ".js";
if (options.jsx === JsxEmit.Preserve) {
if (isSourceFileJavaScript(sourceFile)) {
if (fileExtensionIs(sourceFile.fileName, ".jsx")) {
extension = ".jsx";
}
}
else if (sourceFile.languageVariant === LanguageVariant.JSX) {
// TypeScript source file preserving JSX syntax
extension = ".jsx";
}
}
const jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, extension);
const emitFileNames: EmitFileNames = {
jsFilePath,
sourceMapFilePath: getSourceMapFilePath(jsFilePath, options),
+16 -13
View File
@@ -62,7 +62,7 @@ namespace ts {
export interface SourceFile {
/* @internal */ version: string;
/* @internal */ scriptSnapshot: IScriptSnapshot;
/* @internal */ nameTable: Map<string>;
/* @internal */ nameTable: Map<number>;
/* @internal */ getNamedDeclarations(): Map<Declaration[]>;
@@ -808,7 +808,7 @@ namespace ts {
public languageVersion: ScriptTarget;
public languageVariant: LanguageVariant;
public identifiers: Map<string>;
public nameTable: Map<string>;
public nameTable: Map<number>;
public resolvedModules: Map<ResolvedModule>;
public imports: LiteralExpression[];
public moduleAugmentations: LiteralExpression[];
@@ -1957,8 +1957,6 @@ namespace ts {
const text = scriptSnapshot.getText(0, scriptSnapshot.getLength());
const sourceFile = createSourceFile(fileName, text, scriptTarget, setNodeParents);
setSourceFileFields(sourceFile, scriptSnapshot, version);
// after full parsing we can use table with interned strings as name table
sourceFile.nameTable = sourceFile.identifiers;
return sourceFile;
}
@@ -3821,7 +3819,7 @@ namespace ts {
return undefined;
}
const { symbols, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot, isJsDocTagName } = completionData;
const { symbols, isMemberCompletion, isNewIdentifierLocation, location, isJsDocTagName } = completionData;
if (isJsDocTagName) {
// If the current position is a jsDoc tag name, only tag names should be provided for completion
@@ -3832,9 +3830,9 @@ namespace ts {
const entries: CompletionEntry[] = [];
if (isRightOfDot && isSourceFileJavaScript(sourceFile)) {
if (isSourceFileJavaScript(sourceFile)) {
const uniqueNames = getCompletionEntriesFromSymbols(symbols, entries);
addRange(entries, getJavaScriptCompletionEntries(sourceFile, uniqueNames));
addRange(entries, getJavaScriptCompletionEntries(sourceFile, location.pos, uniqueNames));
}
else {
if (!symbols || symbols.length === 0) {
@@ -3867,12 +3865,17 @@ namespace ts {
return { isMemberCompletion, isNewIdentifierLocation, entries };
function getJavaScriptCompletionEntries(sourceFile: SourceFile, uniqueNames: Map<string>): CompletionEntry[] {
function getJavaScriptCompletionEntries(sourceFile: SourceFile, position: number, uniqueNames: Map<string>): CompletionEntry[] {
const entries: CompletionEntry[] = [];
const target = program.getCompilerOptions().target;
const nameTable = getNameTable(sourceFile);
for (const name in nameTable) {
// Skip identifiers produced only from the current location
if (nameTable[name] === position) {
continue;
}
if (!uniqueNames[name]) {
uniqueNames[name] = name;
const displayName = getCompletionEntryDisplayName(name, target, /*performCharacterChecks*/ true);
@@ -5487,7 +5490,7 @@ namespace ts {
const nameTable = getNameTable(sourceFile);
if (lookUp(nameTable, internedName)) {
if (lookUp(nameTable, internedName) !== undefined) {
result = result || [];
getReferencesInNode(sourceFile, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex);
}
@@ -7525,7 +7528,7 @@ namespace ts {
}
/* @internal */
export function getNameTable(sourceFile: SourceFile): Map<string> {
export function getNameTable(sourceFile: SourceFile): Map<number> {
if (!sourceFile.nameTable) {
initializeNameTable(sourceFile);
}
@@ -7534,7 +7537,7 @@ namespace ts {
}
function initializeNameTable(sourceFile: SourceFile): void {
const nameTable: Map<string> = {};
const nameTable: Map<number> = {};
walk(sourceFile);
sourceFile.nameTable = nameTable;
@@ -7542,7 +7545,7 @@ namespace ts {
function walk(node: Node) {
switch (node.kind) {
case SyntaxKind.Identifier:
nameTable[(<Identifier>node).text] = (<Identifier>node).text;
nameTable[(<Identifier>node).text] = nameTable[(<Identifier>node).text] === undefined ? node.pos : -1;
break;
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
@@ -7554,7 +7557,7 @@ namespace ts {
node.parent.kind === SyntaxKind.ExternalModuleReference ||
isArgumentOfElementAccessExpression(node)) {
nameTable[(<LiteralExpression>node).text] = (<LiteralExpression>node).text;
nameTable[(<LiteralExpression>node).text] = nameTable[(<LiteralExpression>node).text] === undefined ? node.pos : -1;
}
break;
default: