Skip to content

Commit

Permalink
Merge branch 'master' into completionsRecommended
Browse files Browse the repository at this point in the history
  • Loading branch information
Andy Hanson committed Nov 30, 2017
2 parents 8918891 + 8f1cdc9 commit 52a0b4b
Show file tree
Hide file tree
Showing 281 changed files with 22,470 additions and 2,524 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,4 @@ tests/cases/user/*/**/*.d.ts
!tests/cases/user/zone.js/
!tests/cases/user/bignumber.js/
!tests/cases/user/discord.js/
tests/baselines/reference/dt
4 changes: 2 additions & 2 deletions lib/typescript.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4487,9 +4487,9 @@ declare namespace ts {
* @param compilationSettings Some compilation settings like target affects the
* shape of a the resulting SourceFile. This allows the DocumentRegistry to store
* multiple copies of the same file for different compilation settings.
* @parm scriptSnapshot Text of the file. Only used if the file was not found
* @param scriptSnapshot Text of the file. Only used if the file was not found
* in the registry and a new one was created.
* @parm version Current version of the file. Only used if the file was not found
* @param version Current version of the file. Only used if the file was not found
* in the registry and a new one was created.
*/
acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile;
Expand Down
4 changes: 2 additions & 2 deletions lib/typescriptServices.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4487,9 +4487,9 @@ declare namespace ts {
* @param compilationSettings Some compilation settings like target affects the
* shape of a the resulting SourceFile. This allows the DocumentRegistry to store
* multiple copies of the same file for different compilation settings.
* @parm scriptSnapshot Text of the file. Only used if the file was not found
* @param scriptSnapshot Text of the file. Only used if the file was not found
* in the registry and a new one was created.
* @parm version Current version of the file. Only used if the file was not found
* @param version Current version of the file. Only used if the file was not found
* in the registry and a new one was created.
*/
acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile;
Expand Down
95 changes: 69 additions & 26 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -517,16 +517,15 @@ namespace ts {
const isIIFE = containerFlags & ContainerFlags.IsFunctionExpression && !hasModifier(node, ModifierFlags.Async) && !!getImmediatelyInvokedFunctionExpression(node);
// A non-async IIFE is considered part of the containing control flow. Return statements behave
// similarly to break statements that exit to a label just past the statement body.
if (isIIFE) {
currentReturnTarget = createBranchLabel();
}
else {
if (!isIIFE) {
currentFlow = { flags: FlowFlags.Start };
if (containerFlags & (ContainerFlags.IsFunctionExpression | ContainerFlags.IsObjectLiteralOrClassExpressionMethod)) {
(<FlowStart>currentFlow).container = <FunctionExpression | ArrowFunction | MethodDeclaration>node;
}
currentReturnTarget = undefined;
}
// We create a return control flow graph for IIFEs and constructors. For constructors
// we use the return control flow graph in strict property intialization checks.
currentReturnTarget = isIIFE || node.kind === SyntaxKind.Constructor ? createBranchLabel() : undefined;
currentBreakTarget = undefined;
currentContinueTarget = undefined;
activeLabels = undefined;
Expand All @@ -541,11 +540,14 @@ namespace ts {
if (node.kind === SyntaxKind.SourceFile) {
node.flags |= emitFlags;
}
if (isIIFE) {
if (currentReturnTarget) {
addAntecedent(currentReturnTarget, currentFlow);
currentFlow = finishFlowLabel(currentReturnTarget);
if (node.kind === SyntaxKind.Constructor) {
(<ConstructorDeclaration>node).returnFlowNode = currentFlow;
}
}
else {
if (!isIIFE) {
currentFlow = saveCurrentFlow;
}
currentBreakTarget = saveBreakTarget;
Expand Down Expand Up @@ -2004,6 +2006,9 @@ namespace ts {
if (currentFlow && isNarrowableReference(<Expression>node)) {
node.flowNode = currentFlow;
}
if (isSpecialPropertyDeclaration(node as PropertyAccessExpression)) {
bindSpecialPropertyDeclaration(node as PropertyAccessExpression);
}
break;
case SyntaxKind.BinaryExpression:
const specialKind = getSpecialPropertyAssignmentKind(node as BinaryExpression);
Expand Down Expand Up @@ -2312,7 +2317,7 @@ namespace ts {
declareSymbol(file.symbol.exports, file.symbol, node, SymbolFlags.Property | SymbolFlags.ExportValue | SymbolFlags.ValueModule, SymbolFlags.None);
}

function bindThisPropertyAssignment(node: BinaryExpression) {
function bindThisPropertyAssignment(node: BinaryExpression | PropertyAccessExpression) {
Debug.assert(isInJavaScriptFile(node));
const container = getThisContainer(node, /*includeArrowFunctions*/ false);
switch (container.kind) {
Expand All @@ -2338,8 +2343,19 @@ namespace ts {
}
}

function bindSpecialPropertyDeclaration(node: PropertyAccessExpression) {
Debug.assert(isInJavaScriptFile(node));
if (node.expression.kind === SyntaxKind.ThisKeyword) {
bindThisPropertyAssignment(node);
}
else if ((node.expression.kind === SyntaxKind.Identifier || node.expression.kind === SyntaxKind.PropertyAccessExpression) &&
node.parent.parent.kind === SyntaxKind.SourceFile) {
bindStaticPropertyAssignment(node);
}
}

function bindPrototypePropertyAssignment(node: BinaryExpression) {
// We saw a node of the form 'x.prototype.y = z'. Declare a 'member' y on x if x was a function.
// We saw a node of the form 'x.prototype.y = z'. Declare a 'member' y on x if x is a function or class, or not declared.

// Look up the function in the local scope, since prototype assignments should
// follow the function declaration
Expand All @@ -2355,24 +2371,27 @@ namespace ts {
bindPropertyAssignment(constructorFunction.escapedText, leftSideOfAssignment, /*isPrototypeProperty*/ true);
}

function bindStaticPropertyAssignment(node: BinaryExpression) {
// We saw a node of the form 'x.y = z'. Declare a 'member' y on x if x was a function.

// Look up the function in the local scope, since prototype assignments should
/**
* For nodes like `x.y = z`, declare a member 'y' on 'x' if x is a function or class, or not declared.
* Also works for expression statements preceded by JSDoc, like / ** @type number * / x.y;
*/
function bindStaticPropertyAssignment(node: BinaryExpression | PropertyAccessExpression) {
// Look up the function in the local scope, since static assignments should
// follow the function declaration
const leftSideOfAssignment = node.left as PropertyAccessExpression;
const leftSideOfAssignment = node.kind === SyntaxKind.PropertyAccessExpression ? node : node.left as PropertyAccessExpression;
const target = leftSideOfAssignment.expression;

if (isIdentifier(target)) {
// Fix up parent pointers since we're going to use these nodes before we bind into them
leftSideOfAssignment.parent = node;
target.parent = leftSideOfAssignment;

if (node.kind === SyntaxKind.BinaryExpression) {
leftSideOfAssignment.parent = node;
}
if (isNameOfExportsOrModuleExportsAliasDeclaration(target)) {
// This can be an alias for the 'exports' or 'module.exports' names, e.g.
// var util = module.exports;
// util.property = function ...
bindExportsPropertyAssignment(node);
bindExportsPropertyAssignment(node as BinaryExpression);
}
else {
bindPropertyAssignment(target.escapedText, leftSideOfAssignment, /*isPrototypeProperty*/ false);
Expand All @@ -2381,17 +2400,41 @@ namespace ts {
}

function lookupSymbolForName(name: __String) {
return (container.symbol && container.symbol.exports && container.symbol.exports.get(name)) || (container.locals && container.locals.get(name));
const local = container.locals && container.locals.get(name);
if (local) {
return local.exportSymbol || local;
}
return container.symbol && container.symbol.exports && container.symbol.exports.get(name);
}

function bindPropertyAssignment(functionName: __String, propertyAccessExpression: PropertyAccessExpression, isPrototypeProperty: boolean) {
let targetSymbol = lookupSymbolForName(functionName);

if (targetSymbol && isDeclarationOfFunctionOrClassExpression(targetSymbol)) {
targetSymbol = (targetSymbol.valueDeclaration as VariableDeclaration).initializer.symbol;
function bindPropertyAssignment(functionName: __String, propertyAccess: PropertyAccessExpression, isPrototypeProperty: boolean) {
const symbol = lookupSymbolForName(functionName);
let targetSymbol = symbol && isDeclarationOfFunctionOrClassExpression(symbol) ?
(symbol.valueDeclaration as VariableDeclaration).initializer.symbol :
symbol;
Debug.assert(propertyAccess.parent.kind === SyntaxKind.BinaryExpression || propertyAccess.parent.kind === SyntaxKind.ExpressionStatement);
let isLegalPosition: boolean;
if (propertyAccess.parent.kind === SyntaxKind.BinaryExpression) {
const initializerKind = (propertyAccess.parent as BinaryExpression).right.kind;
isLegalPosition = (initializerKind === SyntaxKind.ClassExpression || initializerKind === SyntaxKind.FunctionExpression) &&
propertyAccess.parent.parent.parent.kind === SyntaxKind.SourceFile;
}

if (!targetSymbol || !(targetSymbol.flags & (SymbolFlags.Function | SymbolFlags.Class))) {
else {
isLegalPosition = propertyAccess.parent.parent.kind === SyntaxKind.SourceFile;
}
if (!isPrototypeProperty && (!targetSymbol || !(targetSymbol.flags & SymbolFlags.Namespace)) && isLegalPosition) {
Debug.assert(isIdentifier(propertyAccess.expression));
const identifier = propertyAccess.expression as Identifier;
const flags = SymbolFlags.Module | SymbolFlags.JSContainer;
const excludeFlags = SymbolFlags.ValueModuleExcludes & ~SymbolFlags.JSContainer;
if (targetSymbol) {
addDeclarationToSymbol(symbol, identifier, flags);
}
else {
targetSymbol = declareSymbol(container.locals, /*parent*/ undefined, identifier, flags, excludeFlags);
}
}
if (!targetSymbol || !(targetSymbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.NamespaceModule))) {
return;
}

Expand All @@ -2401,7 +2444,7 @@ namespace ts {
(targetSymbol.exports || (targetSymbol.exports = createSymbolTable()));

// Declare the method/property
declareSymbol(symbolTable, targetSymbol, propertyAccessExpression, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
declareSymbol(symbolTable, targetSymbol, propertyAccess, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
}

function bindCallExpression(node: CallExpression) {
Expand Down
Loading

0 comments on commit 52a0b4b

Please sign in to comment.