mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Allow special element access assignments to create declarations (#33537)
* Start enabling element access special assignment * Treat element access assignment as special assignment in JS * Make declarations for bindable element access expressions * Fix navigationBar crash * Add multi-level test for JS * Propagate element access expressions to more code paths * Fix property access on `this` * Add quick info test * Uhhh I guess this is fine * Fix module["exports"] and property access chained off element access * Add test for this property assignment * Add test for and fix prototype property assignment * Fix teeeest??? * Update APIs * Fix element access declarations on `this` * Fix go-to-definition * Add declaration emit to tests * Reconcile with late-bound symbol element access assignment * Fix baselines * Add JS declaration back to tests * Fix JS declaration emit of non-late-bound string literal property names * Revert accidental auto-format * Use `isAccessExpression` * Add underscore escaping member to test * Fix and test navBar changes
This commit is contained in:
+42
-44
@@ -2333,17 +2333,18 @@ namespace ts {
|
||||
return checkStrictModeIdentifier(<Identifier>node);
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
case SyntaxKind.ElementAccessExpression:
|
||||
if (currentFlow && isNarrowableReference(<Expression>node)) {
|
||||
node.flowNode = currentFlow;
|
||||
const expr = node as PropertyAccessExpression | ElementAccessExpression;
|
||||
if (currentFlow && isNarrowableReference(expr)) {
|
||||
expr.flowNode = currentFlow;
|
||||
}
|
||||
if (isSpecialPropertyDeclaration(node as PropertyAccessExpression)) {
|
||||
bindSpecialPropertyDeclaration(node as PropertyAccessExpression);
|
||||
if (isSpecialPropertyDeclaration(expr)) {
|
||||
bindSpecialPropertyDeclaration(expr);
|
||||
}
|
||||
if (isInJSFile(node) &&
|
||||
if (isInJSFile(expr) &&
|
||||
file.commonJsModuleIndicator &&
|
||||
isModuleExportsPropertyAccessExpression(node as PropertyAccessExpression) &&
|
||||
isModuleExportsAccessExpression(expr) &&
|
||||
!lookupSymbolForNameWorker(blockScopeContainer, "module" as __String)) {
|
||||
declareSymbol(file.locals!, /*parent*/ undefined, (node as PropertyAccessExpression).expression as Identifier,
|
||||
declareSymbol(file.locals!, /*parent*/ undefined, expr.expression,
|
||||
SymbolFlags.FunctionScopedVariable | SymbolFlags.ModuleExports, SymbolFlags.FunctionScopedVariableExcludes);
|
||||
}
|
||||
break;
|
||||
@@ -2351,22 +2352,22 @@ namespace ts {
|
||||
const specialKind = getAssignmentDeclarationKind(node as BinaryExpression);
|
||||
switch (specialKind) {
|
||||
case AssignmentDeclarationKind.ExportsProperty:
|
||||
bindExportsPropertyAssignment(node as BinaryExpression);
|
||||
bindExportsPropertyAssignment(node as BindableStaticPropertyAssignmentExpression);
|
||||
break;
|
||||
case AssignmentDeclarationKind.ModuleExports:
|
||||
bindModuleExportsAssignment(node as BinaryExpression);
|
||||
bindModuleExportsAssignment(node as BindablePropertyAssignmentExpression);
|
||||
break;
|
||||
case AssignmentDeclarationKind.PrototypeProperty:
|
||||
bindPrototypePropertyAssignment((node as BinaryExpression).left as PropertyAccessEntityNameExpression, node);
|
||||
bindPrototypePropertyAssignment((node as BindableStaticPropertyAssignmentExpression).left, node);
|
||||
break;
|
||||
case AssignmentDeclarationKind.Prototype:
|
||||
bindPrototypeAssignment(node as BinaryExpression);
|
||||
bindPrototypeAssignment(node as BindableStaticPropertyAssignmentExpression);
|
||||
break;
|
||||
case AssignmentDeclarationKind.ThisProperty:
|
||||
bindThisPropertyAssignment(node as BinaryExpression);
|
||||
bindThisPropertyAssignment(node as BindablePropertyAssignmentExpression);
|
||||
break;
|
||||
case AssignmentDeclarationKind.Property:
|
||||
bindSpecialPropertyAssignment(node as BinaryExpression);
|
||||
bindSpecialPropertyAssignment(node as BindablePropertyAssignmentExpression);
|
||||
break;
|
||||
case AssignmentDeclarationKind.None:
|
||||
// Nothing to do
|
||||
@@ -2641,14 +2642,13 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function bindExportsPropertyAssignment(node: BinaryExpression) {
|
||||
function bindExportsPropertyAssignment(node: BindableStaticPropertyAssignmentExpression) {
|
||||
// When we create a property via 'exports.foo = bar', the 'exports.foo' property access
|
||||
// expression is the declaration
|
||||
if (!setCommonJsModuleIndicator(node)) {
|
||||
return;
|
||||
}
|
||||
const lhs = node.left as PropertyAccessEntityNameExpression;
|
||||
const symbol = forEachIdentifierInEntityName(lhs.expression, /*parent*/ undefined, (id, symbol) => {
|
||||
const symbol = forEachIdentifierInEntityName(node.left.expression, /*parent*/ undefined, (id, symbol) => {
|
||||
if (symbol) {
|
||||
addDeclarationToSymbol(symbol, id, SymbolFlags.Module | SymbolFlags.Assignment);
|
||||
}
|
||||
@@ -2658,11 +2658,11 @@ namespace ts {
|
||||
const flags = isClassExpression(node.right) ?
|
||||
SymbolFlags.Property | SymbolFlags.ExportValue | SymbolFlags.Class :
|
||||
SymbolFlags.Property | SymbolFlags.ExportValue;
|
||||
declareSymbol(symbol.exports!, symbol, lhs, flags, SymbolFlags.None);
|
||||
declareSymbol(symbol.exports!, symbol, node.left, flags, SymbolFlags.None);
|
||||
}
|
||||
}
|
||||
|
||||
function bindModuleExportsAssignment(node: BinaryExpression) {
|
||||
function bindModuleExportsAssignment(node: BindablePropertyAssignmentExpression) {
|
||||
// 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.
|
||||
@@ -2682,7 +2682,7 @@ namespace ts {
|
||||
declareSymbol(file.symbol.exports!, file.symbol, node, flags | SymbolFlags.Assignment, SymbolFlags.None);
|
||||
}
|
||||
|
||||
function bindThisPropertyAssignment(node: BinaryExpression | PropertyAccessExpression) {
|
||||
function bindThisPropertyAssignment(node: BindablePropertyAssignmentExpression | PropertyAccessExpression | LiteralLikeElementAccessExpression) {
|
||||
Debug.assert(isInJSFile(node));
|
||||
const thisContainer = getThisContainer(node, /*includeArrowFunctions*/ false);
|
||||
switch (thisContainer.kind) {
|
||||
@@ -2692,7 +2692,7 @@ namespace ts {
|
||||
// For `f.prototype.m = function() { this.x = 0; }`, `this.x = 0` should modify `f`'s members, not the function expression.
|
||||
if (isBinaryExpression(thisContainer.parent) && thisContainer.parent.operatorToken.kind === SyntaxKind.EqualsToken) {
|
||||
const l = thisContainer.parent.left;
|
||||
if (isPropertyAccessEntityNameExpression(l) && isPrototypeAccess(l.expression)) {
|
||||
if (isBindableStaticAccessExpression(l) && isPrototypeAccess(l.expression)) {
|
||||
constructorSymbol = lookupSymbolForPropertyAccess(l.expression.expression, thisParentContainer);
|
||||
}
|
||||
}
|
||||
@@ -2754,11 +2754,11 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function bindSpecialPropertyDeclaration(node: PropertyAccessExpression) {
|
||||
function bindSpecialPropertyDeclaration(node: PropertyAccessExpression | LiteralLikeElementAccessExpression) {
|
||||
if (node.expression.kind === SyntaxKind.ThisKeyword) {
|
||||
bindThisPropertyAssignment(node);
|
||||
}
|
||||
else if (isPropertyAccessEntityNameExpression(node) && node.parent.parent.kind === SyntaxKind.SourceFile) {
|
||||
else if (isBindableStaticAccessExpression(node) && node.parent.parent.kind === SyntaxKind.SourceFile) {
|
||||
if (isPrototypeAccess(node.expression)) {
|
||||
bindPrototypePropertyAssignment(node, node.parent);
|
||||
}
|
||||
@@ -2769,11 +2769,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
/** For `x.prototype = { p, ... }`, declare members p,... if `x` is function/class/{}, or not declared. */
|
||||
function bindPrototypeAssignment(node: BinaryExpression) {
|
||||
function bindPrototypeAssignment(node: BindableStaticPropertyAssignmentExpression) {
|
||||
node.left.parent = node;
|
||||
node.right.parent = node;
|
||||
const lhs = node.left as PropertyAccessEntityNameExpression;
|
||||
bindPropertyAssignment(lhs.expression, lhs, /*isPrototypeProperty*/ false, /*containerIsClass*/ true);
|
||||
bindPropertyAssignment(node.left.expression, node.left, /*isPrototypeProperty*/ false, /*containerIsClass*/ true);
|
||||
}
|
||||
|
||||
function bindObjectDefinePrototypeProperty(node: BindableObjectDefinePropertyCall) {
|
||||
@@ -2785,10 +2784,10 @@ namespace ts {
|
||||
* For `x.prototype.y = z`, declare a member `y` on `x` if `x` is a function or class, or not declared.
|
||||
* Note that jsdoc preceding an ExpressionStatement like `x.prototype.y;` is also treated as a declaration.
|
||||
*/
|
||||
function bindPrototypePropertyAssignment(lhs: PropertyAccessEntityNameExpression, parent: Node) {
|
||||
function bindPrototypePropertyAssignment(lhs: BindableStaticAccessExpression, parent: Node) {
|
||||
// Look up the function in the local scope, since prototype assignments should
|
||||
// follow the function declaration
|
||||
const classPrototype = lhs.expression as PropertyAccessEntityNameExpression;
|
||||
const classPrototype = lhs.expression as BindableStaticAccessExpression;
|
||||
const constructorFunction = classPrototype.expression;
|
||||
|
||||
// Fix up parent pointers since we're going to use these nodes before we bind into them
|
||||
@@ -2806,30 +2805,29 @@ namespace ts {
|
||||
bindPotentiallyNewExpandoMemberToNamespace(node, namespaceSymbol, /*isPrototypeProperty*/ false);
|
||||
}
|
||||
|
||||
function bindSpecialPropertyAssignment(node: BinaryExpression) {
|
||||
const lhs = node.left as PropertyAccessEntityNameExpression;
|
||||
function bindSpecialPropertyAssignment(node: BindablePropertyAssignmentExpression) {
|
||||
// Class declarations in Typescript do not allow property declarations
|
||||
const parentSymbol = lookupSymbolForPropertyAccess(lhs.expression);
|
||||
const parentSymbol = lookupSymbolForPropertyAccess(node.left.expression);
|
||||
if (!isInJSFile(node) && !isFunctionSymbol(parentSymbol)) {
|
||||
return;
|
||||
}
|
||||
// Fix up parent pointers since we're going to use these nodes before we bind into them
|
||||
node.left.parent = node;
|
||||
node.right.parent = node;
|
||||
if (isIdentifier(lhs.expression) && container === file && isExportsOrModuleExportsOrAlias(file, lhs.expression)) {
|
||||
if (isIdentifier(node.left.expression) && container === file && isExportsOrModuleExportsOrAlias(file, node.left.expression)) {
|
||||
// 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 BindableStaticPropertyAssignmentExpression);
|
||||
}
|
||||
else {
|
||||
if (hasDynamicName(node)) {
|
||||
bindAnonymousDeclaration(node, SymbolFlags.Property | SymbolFlags.Assignment, InternalSymbolName.Computed);
|
||||
const sym = bindPotentiallyMissingNamespaces(parentSymbol, lhs.expression, isTopLevelNamespaceAssignment(lhs), /*isPrototype*/ false, /*containerIsClass*/ false);
|
||||
const sym = bindPotentiallyMissingNamespaces(parentSymbol, node.left.expression, isTopLevelNamespaceAssignment(node.left), /*isPrototype*/ false, /*containerIsClass*/ false);
|
||||
addLateBoundAssignmentDeclarationToSymbol(node, sym);
|
||||
}
|
||||
else {
|
||||
bindStaticPropertyAssignment(lhs);
|
||||
bindStaticPropertyAssignment(cast(node.left, isBindableStaticAccessExpression));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2838,12 +2836,12 @@ namespace ts {
|
||||
* For nodes like `x.y = z`, declare a member 'y' on 'x' if x is a function (or IIFE) or class or {}, or not declared.
|
||||
* Also works for expression statements preceded by JSDoc, like / ** @type number * / x.y;
|
||||
*/
|
||||
function bindStaticPropertyAssignment(node: PropertyAccessEntityNameExpression) {
|
||||
function bindStaticPropertyAssignment(node: BindableStaticAccessExpression) {
|
||||
node.expression.parent = node;
|
||||
bindPropertyAssignment(node.expression, node, /*isPrototypeProperty*/ false, /*containerIsClass*/ false);
|
||||
}
|
||||
|
||||
function bindPotentiallyMissingNamespaces(namespaceSymbol: Symbol | undefined, entityName: EntityNameExpression, isToplevel: boolean, isPrototypeProperty: boolean, containerIsClass: boolean) {
|
||||
function bindPotentiallyMissingNamespaces(namespaceSymbol: Symbol | undefined, entityName: BindableStaticNameExpression, isToplevel: boolean, isPrototypeProperty: boolean, containerIsClass: boolean) {
|
||||
if (isToplevel && !isPrototypeProperty) {
|
||||
// make symbols or add declarations for intermediate containers
|
||||
const flags = SymbolFlags.Module | SymbolFlags.Assignment;
|
||||
@@ -2866,7 +2864,7 @@ namespace ts {
|
||||
return namespaceSymbol;
|
||||
}
|
||||
|
||||
function bindPotentiallyNewExpandoMemberToNamespace(declaration: PropertyAccessEntityNameExpression | CallExpression, namespaceSymbol: Symbol | undefined, isPrototypeProperty: boolean) {
|
||||
function bindPotentiallyNewExpandoMemberToNamespace(declaration: BindableStaticAccessExpression | CallExpression, namespaceSymbol: Symbol | undefined, isPrototypeProperty: boolean) {
|
||||
if (!namespaceSymbol || !isExpandoSymbol(namespaceSymbol)) {
|
||||
return;
|
||||
}
|
||||
@@ -2911,13 +2909,13 @@ namespace ts {
|
||||
declareSymbol(symbolTable, namespaceSymbol, declaration, includes | SymbolFlags.Assignment, excludes & ~SymbolFlags.Assignment);
|
||||
}
|
||||
|
||||
function isTopLevelNamespaceAssignment(propertyAccess: PropertyAccessEntityNameExpression) {
|
||||
function isTopLevelNamespaceAssignment(propertyAccess: BindableAccessExpression) {
|
||||
return isBinaryExpression(propertyAccess.parent)
|
||||
? getParentOfBinaryExpression(propertyAccess.parent).parent.kind === SyntaxKind.SourceFile
|
||||
: propertyAccess.parent.parent.kind === SyntaxKind.SourceFile;
|
||||
}
|
||||
|
||||
function bindPropertyAssignment(name: EntityNameExpression, propertyAccess: PropertyAccessEntityNameExpression, isPrototypeProperty: boolean, containerIsClass: boolean) {
|
||||
function bindPropertyAssignment(name: BindableStaticNameExpression, propertyAccess: BindableStaticAccessExpression, isPrototypeProperty: boolean, containerIsClass: boolean) {
|
||||
let namespaceSymbol = lookupSymbolForPropertyAccess(name);
|
||||
const isToplevel = isTopLevelNamespaceAssignment(propertyAccess);
|
||||
namespaceSymbol = bindPotentiallyMissingNamespaces(namespaceSymbol, propertyAccess.expression, isToplevel, isPrototypeProperty, containerIsClass);
|
||||
@@ -2962,17 +2960,17 @@ namespace ts {
|
||||
return expr.parent;
|
||||
}
|
||||
|
||||
function lookupSymbolForPropertyAccess(node: EntityNameExpression, lookupContainer: Node = container): Symbol | undefined {
|
||||
function lookupSymbolForPropertyAccess(node: BindableStaticNameExpression, lookupContainer: Node = container): Symbol | undefined {
|
||||
if (isIdentifier(node)) {
|
||||
return lookupSymbolForNameWorker(lookupContainer, node.escapedText);
|
||||
}
|
||||
else {
|
||||
const symbol = lookupSymbolForPropertyAccess(node.expression);
|
||||
return symbol && symbol.exports && symbol.exports.get(node.name.escapedText);
|
||||
return symbol && symbol.exports && symbol.exports.get(escapeLeadingUnderscores(getElementOrPropertyAccessName(node)));
|
||||
}
|
||||
}
|
||||
|
||||
function forEachIdentifierInEntityName(e: EntityNameExpression, parent: Symbol | undefined, action: (e: Identifier, symbol: Symbol | undefined, parent: Symbol | undefined) => Symbol | undefined): Symbol | undefined {
|
||||
function forEachIdentifierInEntityName(e: BindableStaticNameExpression, parent: Symbol | undefined, action: (e: Declaration, symbol: Symbol | undefined, parent: Symbol | undefined) => Symbol | undefined): Symbol | undefined {
|
||||
if (isExportsOrModuleExportsOrAlias(file, e)) {
|
||||
return file.symbol;
|
||||
}
|
||||
@@ -2981,7 +2979,7 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
const s = forEachIdentifierInEntityName(e.expression, parent, action);
|
||||
return action(e.name, s && s.exports && s.exports.get(e.name.escapedText), s);
|
||||
return action(getNameOrArgument(e), s && s.exports && s.exports.get(escapeLeadingUnderscores(getElementOrPropertyAccessName(e))), s);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3255,7 +3253,7 @@ namespace ts {
|
||||
while (q.length && i < 100) {
|
||||
i++;
|
||||
node = q.shift()!;
|
||||
if (isExportsIdentifier(node) || isModuleExportsPropertyAccessExpression(node)) {
|
||||
if (isExportsIdentifier(node) || isModuleExportsAccessExpression(node)) {
|
||||
return true;
|
||||
}
|
||||
else if (isIdentifier(node)) {
|
||||
|
||||
+27
-9
@@ -3041,7 +3041,7 @@ namespace ts {
|
||||
return getSymbolOfNode(d.parent);
|
||||
}
|
||||
if (isClassExpression(d) && isBinaryExpression(d.parent) && d.parent.operatorToken.kind === SyntaxKind.EqualsToken && isAccessExpression(d.parent.left) && isEntityNameExpression(d.parent.left.expression)) {
|
||||
if (isModuleExportsPropertyAccessExpression(d.parent.left) || isExportsIdentifier(d.parent.left.expression)) {
|
||||
if (isModuleExportsAccessExpression(d.parent.left) || isExportsIdentifier(d.parent.left.expression)) {
|
||||
return getSymbolOfNode(getSourceFileOfNode(d));
|
||||
}
|
||||
checkExpressionCached(d.parent.left.expression);
|
||||
@@ -4877,6 +4877,15 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getPropertyNameNodeForSymbol(symbol: Symbol, context: NodeBuilderContext) {
|
||||
const fromNameType = getPropertyNameNodeForSymbolFromNameType(symbol, context);
|
||||
if (fromNameType) {
|
||||
return fromNameType;
|
||||
}
|
||||
const rawName = unescapeLeadingUnderscores(symbol.escapedName);
|
||||
return createPropertyNameNodeForIdentifierOrLiteral(rawName);
|
||||
}
|
||||
|
||||
// See getNameForSymbolFromNameType for a stringy equivalent
|
||||
function getPropertyNameNodeForSymbolFromNameType(symbol: Symbol, context: NodeBuilderContext) {
|
||||
const nameType = symbol.nameType;
|
||||
@@ -4889,7 +4898,7 @@ namespace ts {
|
||||
if (isNumericLiteralName(name) && startsWith(name, "-")) {
|
||||
return createComputedPropertyName(createLiteral(+name));
|
||||
}
|
||||
return isIdentifierText(name, compilerOptions.target) ? createIdentifier(name) : createLiteral(isNumericLiteralName(name) ? +name : name) as StringLiteral | NumericLiteral;
|
||||
return createPropertyNameNodeForIdentifierOrLiteral(name);
|
||||
}
|
||||
if (nameType.flags & TypeFlags.UniqueESSymbol) {
|
||||
return createComputedPropertyName(symbolToExpression((<UniqueESSymbolType>nameType).symbol, context, SymbolFlags.Value));
|
||||
@@ -4897,6 +4906,10 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function createPropertyNameNodeForIdentifierOrLiteral(name: string) {
|
||||
return isIdentifierText(name, compilerOptions.target) ? createIdentifier(name) : createLiteral(isNumericLiteralName(name) ? +name : name) as StringLiteral | NumericLiteral;
|
||||
}
|
||||
|
||||
function cloneNodeBuilderContext(context: NodeBuilderContext): NodeBuilderContext {
|
||||
const initial: NodeBuilderContext = { ...context };
|
||||
// Make type parameters created within this context not consume the name outside this context
|
||||
@@ -5772,8 +5785,7 @@ namespace ts {
|
||||
return [];
|
||||
}
|
||||
const staticFlag = isStatic ? ModifierFlags.Static : 0;
|
||||
const rawName = unescapeLeadingUnderscores(p.escapedName);
|
||||
const name = getPropertyNameNodeForSymbolFromNameType(p, context) || createIdentifier(rawName);
|
||||
const name = getPropertyNameNodeForSymbol(p, context);
|
||||
const firstPropertyLikeDecl = find(p.declarations, or(isPropertyDeclaration, isAccessor, isVariableDeclaration, isPropertySignature, isBinaryExpression, isPropertyAccessExpression));
|
||||
if (p.flags & SymbolFlags.Accessor && useAccessors) {
|
||||
const result: AccessorDeclaration[] = [];
|
||||
@@ -6869,13 +6881,15 @@ namespace ts {
|
||||
let types: Type[] | undefined;
|
||||
for (const declaration of symbol.declarations) {
|
||||
const expression = (isBinaryExpression(declaration) || isCallExpression(declaration)) ? declaration :
|
||||
isPropertyAccessExpression(declaration) ? isBinaryExpression(declaration.parent) ? declaration.parent : declaration :
|
||||
isAccessExpression(declaration) ? isBinaryExpression(declaration.parent) ? declaration.parent : declaration :
|
||||
undefined;
|
||||
if (!expression) {
|
||||
continue; // Non-assignment declaration merged in (eg, an Identifier to mark the thing as a namespace) - skip over it and pull type info from elsewhere
|
||||
}
|
||||
|
||||
const kind = isPropertyAccessExpression(expression) ? getAssignmentDeclarationPropertyAccessKind(expression) : getAssignmentDeclarationKind(expression);
|
||||
const kind = isAccessExpression(expression)
|
||||
? getAssignmentDeclarationPropertyAccessKind(expression)
|
||||
: getAssignmentDeclarationKind(expression);
|
||||
if (kind === AssignmentDeclarationKind.ThisProperty) {
|
||||
if (isDeclarationInConstructor(expression)) {
|
||||
definedInConstructor = true;
|
||||
@@ -7250,12 +7264,15 @@ namespace ts {
|
||||
else if (
|
||||
isBinaryExpression(declaration) ||
|
||||
(isInJSFile(declaration) &&
|
||||
(isCallExpression(declaration) || isPropertyAccessExpression(declaration) && isBinaryExpression(declaration.parent)))) {
|
||||
(isCallExpression(declaration) || (isPropertyAccessExpression(declaration) || isBindableStaticElementAccessExpression(declaration)) && isBinaryExpression(declaration.parent)))) {
|
||||
type = getWidenedTypeForAssignmentDeclaration(symbol);
|
||||
}
|
||||
else if (isJSDocPropertyLikeTag(declaration)
|
||||
|| isPropertyAccessExpression(declaration)
|
||||
|| isElementAccessExpression(declaration)
|
||||
|| isIdentifier(declaration)
|
||||
|| isStringLiteralLike(declaration)
|
||||
|| isNumericLiteral(declaration)
|
||||
|| isClassDeclaration(declaration)
|
||||
|| isFunctionDeclaration(declaration)
|
||||
|| (isMethodDeclaration(declaration) && !isObjectLiteralMethod(declaration))
|
||||
@@ -7436,7 +7453,8 @@ namespace ts {
|
||||
return anyType;
|
||||
}
|
||||
else if (declaration.kind === SyntaxKind.BinaryExpression ||
|
||||
declaration.kind === SyntaxKind.PropertyAccessExpression && declaration.parent.kind === SyntaxKind.BinaryExpression) {
|
||||
(declaration.kind === SyntaxKind.PropertyAccessExpression || declaration.kind === SyntaxKind.ElementAccessExpression) &&
|
||||
declaration.parent.kind === SyntaxKind.BinaryExpression) {
|
||||
return getWidenedTypeForAssignmentDeclaration(symbol);
|
||||
}
|
||||
else if (symbol.flags & SymbolFlags.ValueModule && declaration && isSourceFile(declaration) && declaration.commonJsModuleIndicator) {
|
||||
@@ -32134,7 +32152,7 @@ namespace ts {
|
||||
return node;
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
do {
|
||||
if (isModuleExportsPropertyAccessExpression(node.expression)) {
|
||||
if (isModuleExportsAccessExpression(node.expression)) {
|
||||
return node.name;
|
||||
}
|
||||
node = node.expression;
|
||||
|
||||
@@ -2280,7 +2280,7 @@ namespace ts {
|
||||
// if the expression doesn't have any comments that will be emitted.
|
||||
return !expression.numericLiteralFlags && !stringContains(text, tokenToString(SyntaxKind.DotToken)!);
|
||||
}
|
||||
else if (isPropertyAccessExpression(expression) || isElementAccessExpression(expression)) {
|
||||
else if (isAccessExpression(expression)) {
|
||||
// check if constant enum value is integer
|
||||
const constantValue = getConstantValue(expression);
|
||||
// isFinite handles cases when constantValue is undefined
|
||||
|
||||
+30
-4
@@ -1306,7 +1306,7 @@ namespace ts {
|
||||
literal: BooleanLiteral | LiteralExpression | PrefixUnaryExpression;
|
||||
}
|
||||
|
||||
export interface StringLiteral extends LiteralExpression {
|
||||
export interface StringLiteral extends LiteralExpression, Declaration {
|
||||
kind: SyntaxKind.StringLiteral;
|
||||
/* @internal */ textSourceNode?: Identifier | StringLiteralLike | NumericLiteral; // Allows a StringLiteral to get its text from another node (used by transforms).
|
||||
/** Note: this is only set when synthesizing a node, not during parsing. */
|
||||
@@ -1693,7 +1693,7 @@ namespace ts {
|
||||
kind: SyntaxKind.RegularExpressionLiteral;
|
||||
}
|
||||
|
||||
export interface NoSubstitutionTemplateLiteral extends LiteralExpression, TemplateLiteralLikeNode {
|
||||
export interface NoSubstitutionTemplateLiteral extends LiteralExpression, TemplateLiteralLikeNode, Declaration {
|
||||
kind: SyntaxKind.NoSubstitutionTemplateLiteral;
|
||||
}
|
||||
|
||||
@@ -1722,7 +1722,7 @@ namespace ts {
|
||||
NumericLiteralFlags = Scientific | Octal | HexSpecifier | BinaryOrOctalSpecifier | ContainsSeparator
|
||||
}
|
||||
|
||||
export interface NumericLiteral extends LiteralExpression {
|
||||
export interface NumericLiteral extends LiteralExpression, Declaration {
|
||||
kind: SyntaxKind.NumericLiteral;
|
||||
/* @internal */
|
||||
numericLiteralFlags: TokenFlags;
|
||||
@@ -1885,7 +1885,33 @@ namespace ts {
|
||||
;
|
||||
|
||||
/** @internal */
|
||||
export type BindableObjectDefinePropertyCall = CallExpression & { arguments: { 0: EntityNameExpression, 1: StringLiteralLike | NumericLiteral, 2: ObjectLiteralExpression } };
|
||||
export type BindableObjectDefinePropertyCall = CallExpression & { arguments: { 0: BindableStaticNameExpression, 1: StringLiteralLike | NumericLiteral, 2: ObjectLiteralExpression } };
|
||||
/** @internal */
|
||||
export type BindableStaticNameExpression = EntityNameExpression | BindableStaticElementAccessExpression;
|
||||
/** @internal */
|
||||
export type LiteralLikeElementAccessExpression = ElementAccessExpression & Declaration & {
|
||||
argumentExpression: StringLiteralLike | NumericLiteral;
|
||||
};
|
||||
/** @internal */
|
||||
export type BindableStaticElementAccessExpression = LiteralLikeElementAccessExpression & {
|
||||
expression: BindableStaticNameExpression;
|
||||
};
|
||||
/** @internal */
|
||||
export type BindableElementAccessExpression = ElementAccessExpression & {
|
||||
expression: BindableStaticNameExpression;
|
||||
};
|
||||
/** @internal */
|
||||
export type BindableStaticAccessExpression = PropertyAccessEntityNameExpression | BindableStaticElementAccessExpression;
|
||||
/** @internal */
|
||||
export type BindableAccessExpression = PropertyAccessEntityNameExpression | BindableElementAccessExpression;
|
||||
/** @internal */
|
||||
export interface BindableStaticPropertyAssignmentExpression extends BinaryExpression {
|
||||
left: BindableStaticAccessExpression;
|
||||
}
|
||||
/** @internal */
|
||||
export interface BindablePropertyAssignmentExpression extends BinaryExpression {
|
||||
left: BindableAccessExpression;
|
||||
}
|
||||
|
||||
// see: https://tc39.github.io/ecma262/#prod-SuperCall
|
||||
export interface SuperCall extends CallExpression {
|
||||
|
||||
+85
-42
@@ -1875,7 +1875,7 @@ namespace ts {
|
||||
decl = name;
|
||||
}
|
||||
|
||||
if (!name || !isEntityNameExpression(name) || !isSameEntityName(name, node.parent.left)) {
|
||||
if (!name || !isBindableStaticNameExpression(name) || !isSameEntityName(name, node.parent.left)) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@@ -1887,7 +1887,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function isAssignmentDeclaration(decl: Declaration) {
|
||||
return isBinaryExpression(decl) || isPropertyAccessExpression(decl) || isIdentifier(decl) || isCallExpression(decl);
|
||||
return isBinaryExpression(decl) || isAccessExpression(decl) || isIdentifier(decl) || isCallExpression(decl);
|
||||
}
|
||||
|
||||
/** Get the initializer, taking into account defaulted Javascript initializers */
|
||||
@@ -1907,18 +1907,23 @@ namespace ts {
|
||||
}
|
||||
|
||||
function hasExpandoValueProperty(node: ObjectLiteralExpression, isPrototypeAssignment: boolean) {
|
||||
return forEach(node.properties, p => isPropertyAssignment(p) && isIdentifier(p.name) && p.name.escapedText === "value" && p.initializer && getExpandoInitializer(p.initializer, isPrototypeAssignment));
|
||||
return forEach(node.properties, p =>
|
||||
isPropertyAssignment(p) &&
|
||||
isIdentifier(p.name) &&
|
||||
p.name.escapedText === "value" &&
|
||||
p.initializer &&
|
||||
getExpandoInitializer(p.initializer, isPrototypeAssignment));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the assignment 'initializer' -- the righthand side-- when the initializer is container-like (See getExpandoInitializer).
|
||||
* We treat the right hand side of assignments with container-like initalizers as declarations.
|
||||
*/
|
||||
export function getAssignedExpandoInitializer(node: Node | undefined) {
|
||||
export function getAssignedExpandoInitializer(node: Node | undefined): Expression | undefined {
|
||||
if (node && node.parent && isBinaryExpression(node.parent) && node.parent.operatorToken.kind === SyntaxKind.EqualsToken) {
|
||||
const isPrototypeAssignment = isPrototypeAccess(node.parent.left);
|
||||
return getExpandoInitializer(node.parent.right, isPrototypeAssignment) ||
|
||||
getDefaultedExpandoInitializer(node.parent.left as EntityNameExpression, node.parent.right, isPrototypeAssignment);
|
||||
getDefaultedExpandoInitializer(node.parent.left, node.parent.right, isPrototypeAssignment);
|
||||
}
|
||||
if (node && isCallExpression(node) && isBindableObjectDefinePropertyCall(node)) {
|
||||
const result = hasExpandoValueProperty(node.arguments[2], node.arguments[1].text === "prototype");
|
||||
@@ -1961,9 +1966,9 @@ namespace ts {
|
||||
* The second Lhs is required to be the same as the first except that it may be prefixed with
|
||||
* 'window.', 'global.' or 'self.' The second Lhs is otherwise ignored by the binder and checker.
|
||||
*/
|
||||
function getDefaultedExpandoInitializer(name: EntityNameExpression, initializer: Expression, isPrototypeAssignment: boolean) {
|
||||
function getDefaultedExpandoInitializer(name: Expression, initializer: Expression, isPrototypeAssignment: boolean) {
|
||||
const e = isBinaryExpression(initializer) && initializer.operatorToken.kind === SyntaxKind.BarBarToken && getExpandoInitializer(initializer.right, isPrototypeAssignment);
|
||||
if (e && isSameEntityName(name, (initializer as BinaryExpression).left as EntityNameExpression)) {
|
||||
if (e && isSameEntityName(name, (initializer as BinaryExpression).left)) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
@@ -1998,19 +2003,20 @@ namespace ts {
|
||||
* my.app = self.my.app || class { }
|
||||
*/
|
||||
function isSameEntityName(name: Expression, initializer: Expression): boolean {
|
||||
if (isIdentifier(name) && isIdentifier(initializer)) {
|
||||
return name.escapedText === initializer.escapedText;
|
||||
if (isPropertyNameLiteral(name) && isPropertyNameLiteral(initializer)) {
|
||||
return getTextOfIdentifierOrLiteral(name) === getTextOfIdentifierOrLiteral(name);
|
||||
}
|
||||
if (isIdentifier(name) && isPropertyAccessExpression(initializer)) {
|
||||
return (initializer.expression.kind as SyntaxKind.ThisKeyword === SyntaxKind.ThisKeyword ||
|
||||
if (isIdentifier(name) && (isLiteralLikeAccess(initializer))) {
|
||||
return (initializer.expression.kind === SyntaxKind.ThisKeyword ||
|
||||
isIdentifier(initializer.expression) &&
|
||||
(initializer.expression.escapedText === "window" as __String ||
|
||||
initializer.expression.escapedText === "self" as __String ||
|
||||
initializer.expression.escapedText === "global" as __String)) &&
|
||||
isSameEntityName(name, initializer.name);
|
||||
(initializer.expression.escapedText === "window" ||
|
||||
initializer.expression.escapedText === "self" ||
|
||||
initializer.expression.escapedText === "global")) &&
|
||||
isSameEntityName(name, getNameOrArgument(initializer));
|
||||
}
|
||||
if (isPropertyAccessExpression(name) && isPropertyAccessExpression(initializer)) {
|
||||
return name.name.escapedText === initializer.name.escapedText && isSameEntityName(name.expression, initializer.expression);
|
||||
if (isLiteralLikeAccess(name) && isLiteralLikeAccess(initializer)) {
|
||||
return getElementOrPropertyAccessName(name) === getElementOrPropertyAccessName(initializer)
|
||||
&& isSameEntityName(name.expression, initializer.expression);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -2026,8 +2032,11 @@ namespace ts {
|
||||
return isIdentifier(node) && node.escapedText === "exports";
|
||||
}
|
||||
|
||||
export function isModuleExportsPropertyAccessExpression(node: Node) {
|
||||
return isPropertyAccessExpression(node) && isIdentifier(node.expression) && node.expression.escapedText === "module" && node.name.escapedText === "exports";
|
||||
export function isModuleExportsAccessExpression(node: Node): node is LiteralLikeElementAccessExpression & { expression: Identifier } {
|
||||
return (isPropertyAccessExpression(node) || isLiteralLikeElementAccess(node))
|
||||
&& isIdentifier(node.expression)
|
||||
&& node.expression.escapedText === "module"
|
||||
&& getElementOrPropertyAccessName(node) === "exports";
|
||||
}
|
||||
|
||||
/// Given a BinaryExpression, returns SpecialPropertyAssignmentKind for the various kinds of property
|
||||
@@ -2044,7 +2053,38 @@ namespace ts {
|
||||
idText(expr.expression.expression) === "Object" &&
|
||||
idText(expr.expression.name) === "defineProperty" &&
|
||||
isStringOrNumericLiteralLike(expr.arguments[1]) &&
|
||||
isEntityNameExpression(expr.arguments[0]);
|
||||
isBindableStaticNameExpression(expr.arguments[0]);
|
||||
}
|
||||
|
||||
export function isBindableStaticElementAccessExpression(node: Node, excludeThisKeyword?: boolean): node is BindableStaticElementAccessExpression {
|
||||
return isLiteralLikeElementAccess(node)
|
||||
&& ((!excludeThisKeyword && node.expression.kind === SyntaxKind.ThisKeyword) ||
|
||||
isEntityNameExpression(node.expression) ||
|
||||
isBindableStaticElementAccessExpression(node.expression, /*excludeThisKeyword*/ true));
|
||||
}
|
||||
|
||||
export function isLiteralLikeAccess(node: Node): node is LiteralLikeElementAccessExpression | PropertyAccessExpression {
|
||||
return isPropertyAccessExpression(node) || isLiteralLikeElementAccess(node);
|
||||
}
|
||||
|
||||
export function isLiteralLikeElementAccess(node: Node): node is LiteralLikeElementAccessExpression {
|
||||
return isElementAccessExpression(node) && isStringOrNumericLiteralLike(node.argumentExpression);
|
||||
}
|
||||
|
||||
export function isBindableStaticAccessExpression(node: Node, excludeThisKeyword?: boolean): node is BindableStaticAccessExpression {
|
||||
return isPropertyAccessExpression(node) && (!excludeThisKeyword && node.expression.kind === SyntaxKind.ThisKeyword || isBindableStaticNameExpression(node.expression, /*excludeThisKeyword*/ true))
|
||||
|| isBindableStaticElementAccessExpression(node, excludeThisKeyword);
|
||||
}
|
||||
|
||||
export function isBindableStaticNameExpression(node: Node, excludeThisKeyword?: boolean): node is BindableStaticNameExpression {
|
||||
return isEntityNameExpression(node) || isBindableStaticAccessExpression(node, excludeThisKeyword);
|
||||
}
|
||||
|
||||
export function getNameOrArgument(expr: PropertyAccessExpression | LiteralLikeElementAccessExpression) {
|
||||
if (isPropertyAccessExpression(expr)) {
|
||||
return expr.name;
|
||||
}
|
||||
return expr.argumentExpression;
|
||||
}
|
||||
|
||||
function getAssignmentDeclarationKindWorker(expr: BinaryExpression | CallExpression): AssignmentDeclarationKind {
|
||||
@@ -2053,26 +2093,22 @@ namespace ts {
|
||||
return AssignmentDeclarationKind.None;
|
||||
}
|
||||
const entityName = expr.arguments[0];
|
||||
if (isExportsIdentifier(entityName) || isModuleExportsPropertyAccessExpression(entityName)) {
|
||||
if (isExportsIdentifier(entityName) || isModuleExportsAccessExpression(entityName)) {
|
||||
return AssignmentDeclarationKind.ObjectDefinePropertyExports;
|
||||
}
|
||||
if (isPropertyAccessExpression(entityName) && entityName.name.escapedText === "prototype" && isEntityNameExpression(entityName.expression)) {
|
||||
if (isBindableStaticAccessExpression(entityName) && getElementOrPropertyAccessName(entityName) === "prototype") {
|
||||
return AssignmentDeclarationKind.ObjectDefinePrototypeProperty;
|
||||
}
|
||||
return AssignmentDeclarationKind.ObjectDefinePropertyValue;
|
||||
}
|
||||
if (expr.operatorToken.kind !== SyntaxKind.EqualsToken) {
|
||||
if (expr.operatorToken.kind !== SyntaxKind.EqualsToken || !isAccessExpression(expr.left)) {
|
||||
return AssignmentDeclarationKind.None;
|
||||
}
|
||||
const lhs = expr.left;
|
||||
if (isAccessExpression(lhs)) {
|
||||
if (isEntityNameExpression(lhs.expression) && getElementOrPropertyAccessName(lhs) === "prototype" && isObjectLiteralExpression(getInitializerOfBinaryExpression(expr))) {
|
||||
// F.prototype = { ... }
|
||||
return AssignmentDeclarationKind.Prototype;
|
||||
}
|
||||
return getAssignmentDeclarationPropertyAccessKind(lhs);
|
||||
if (isBindableStaticNameExpression(expr.left.expression) && getElementOrPropertyAccessName(expr.left) === "prototype" && isObjectLiteralExpression(getInitializerOfBinaryExpression(expr))) {
|
||||
// F.prototype = { ... }
|
||||
return AssignmentDeclarationKind.Prototype;
|
||||
}
|
||||
return AssignmentDeclarationKind.None;
|
||||
return getAssignmentDeclarationPropertyAccessKind(expr.left);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2092,6 +2128,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function getElementOrPropertyAccessName(node: LiteralLikeElementAccessExpression | PropertyAccessExpression): string;
|
||||
export function getElementOrPropertyAccessName(node: AccessExpression): string | undefined;
|
||||
export function getElementOrPropertyAccessName(node: AccessExpression): string | undefined {
|
||||
const name = getElementOrPropertyAccessArgumentExpressionOrName(node);
|
||||
if (name) {
|
||||
@@ -2109,22 +2147,21 @@ namespace ts {
|
||||
if (lhs.expression.kind === SyntaxKind.ThisKeyword) {
|
||||
return AssignmentDeclarationKind.ThisProperty;
|
||||
}
|
||||
else if (isModuleExportsPropertyAccessExpression(lhs)) {
|
||||
else if (isModuleExportsAccessExpression(lhs)) {
|
||||
// module.exports = expr
|
||||
return AssignmentDeclarationKind.ModuleExports;
|
||||
}
|
||||
else if (isEntityNameExpression(lhs.expression)) {
|
||||
else if (isBindableStaticNameExpression(lhs.expression, /*excludeThisKeyword*/ true)) {
|
||||
if (isPrototypeAccess(lhs.expression)) {
|
||||
// F.G....prototype.x = expr
|
||||
return AssignmentDeclarationKind.PrototypeProperty;
|
||||
}
|
||||
|
||||
let nextToLast = lhs;
|
||||
while (isAccessExpression(nextToLast.expression)) {
|
||||
nextToLast = nextToLast.expression;
|
||||
while (!isIdentifier(nextToLast.expression)) {
|
||||
nextToLast = nextToLast.expression as Exclude<BindableStaticNameExpression, Identifier>;
|
||||
}
|
||||
Debug.assert(isIdentifier(nextToLast.expression));
|
||||
const id = nextToLast.expression as Identifier;
|
||||
const id = nextToLast.expression;
|
||||
if (id.escapedText === "exports" ||
|
||||
id.escapedText === "module" && getElementOrPropertyAccessName(nextToLast) === "exports") {
|
||||
// exports.name = expr OR module.exports.name = expr
|
||||
@@ -2148,9 +2185,10 @@ namespace ts {
|
||||
return isBinaryExpression(node) && getAssignmentDeclarationKind(node) === AssignmentDeclarationKind.PrototypeProperty;
|
||||
}
|
||||
|
||||
export function isSpecialPropertyDeclaration(expr: PropertyAccessExpression): boolean {
|
||||
export function isSpecialPropertyDeclaration(expr: PropertyAccessExpression | ElementAccessExpression): expr is PropertyAccessExpression | LiteralLikeElementAccessExpression {
|
||||
return isInJSFile(expr) &&
|
||||
expr.parent && expr.parent.kind === SyntaxKind.ExpressionStatement &&
|
||||
(!isElementAccessExpression(expr) || isLiteralLikeElementAccess(expr)) &&
|
||||
!!getJSDocTypeTag(expr.parent);
|
||||
}
|
||||
|
||||
@@ -4147,8 +4185,8 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function isPrototypeAccess(node: Node): node is PropertyAccessExpression {
|
||||
return isPropertyAccessExpression(node) && node.name.escapedText === "prototype";
|
||||
export function isPrototypeAccess(node: Node): node is BindableStaticAccessExpression {
|
||||
return isBindableStaticAccessExpression(node) && getElementOrPropertyAccessName(node) === "prototype";
|
||||
}
|
||||
|
||||
export function isRightSideOfQualifiedNameOrPropertyAccess(node: Node) {
|
||||
@@ -5378,6 +5416,11 @@ namespace ts {
|
||||
const { expression } = declaration as ExportAssignment;
|
||||
return isIdentifier(expression) ? expression : undefined;
|
||||
}
|
||||
case SyntaxKind.ElementAccessExpression:
|
||||
const expr = declaration as ElementAccessExpression;
|
||||
if (isBindableStaticElementAccessExpression(expr)) {
|
||||
return expr.argumentExpression;
|
||||
}
|
||||
}
|
||||
return (declaration as NamedDeclaration).name;
|
||||
}
|
||||
@@ -5399,8 +5442,8 @@ namespace ts {
|
||||
if (isIdentifier(node.parent.left)) {
|
||||
return node.parent.left;
|
||||
}
|
||||
else if (isPropertyAccessExpression(node.parent.left)) {
|
||||
return node.parent.left.name;
|
||||
else if (isAccessExpression(node.parent.left)) {
|
||||
return getElementOrPropertyAccessArgumentExpressionOrName(node.parent.left);
|
||||
}
|
||||
}
|
||||
else if (isVariableDeclaration(node.parent) && isIdentifier(node.parent.name)) {
|
||||
|
||||
@@ -135,12 +135,13 @@ namespace ts.NavigationBar {
|
||||
function endNestedNodes(depth: number): void {
|
||||
for (let i = 0; i < depth; i++) endNode();
|
||||
}
|
||||
function startNestedNodes(targetNode: Node, entityName: EntityNameExpression) {
|
||||
const names: Identifier[] = [];
|
||||
while (!isIdentifier(entityName)) {
|
||||
const name = entityName.name;
|
||||
function startNestedNodes(targetNode: Node, entityName: BindableStaticNameExpression) {
|
||||
const names: PropertyNameLiteral[] = [];
|
||||
while (!isPropertyNameLiteral(entityName)) {
|
||||
const name = getNameOrArgument(entityName);
|
||||
const nameText = getElementOrPropertyAccessName(entityName);
|
||||
entityName = entityName.expression;
|
||||
if (name.escapedText === "prototype") continue;
|
||||
if (nameText === "prototype") continue;
|
||||
names.push(name);
|
||||
}
|
||||
names.push(entityName);
|
||||
@@ -333,7 +334,7 @@ namespace ts.NavigationBar {
|
||||
assignmentTarget;
|
||||
|
||||
let depth = 0;
|
||||
let className: Identifier;
|
||||
let className: PropertyNameLiteral;
|
||||
// If we see a prototype assignment, start tracking the target as a class
|
||||
// This is only done for simple classes not nested assignments.
|
||||
if (isIdentifier(prototypeAccess.expression)) {
|
||||
@@ -384,16 +385,16 @@ namespace ts.NavigationBar {
|
||||
}
|
||||
case AssignmentDeclarationKind.Property: {
|
||||
const binaryExpression = (node as BinaryExpression);
|
||||
const assignmentTarget = binaryExpression.left as PropertyAccessExpression;
|
||||
const assignmentTarget = binaryExpression.left as PropertyAccessExpression | BindableElementAccessExpression;
|
||||
const targetFunction = assignmentTarget.expression;
|
||||
if (isIdentifier(targetFunction) && assignmentTarget.name.escapedText !== "prototype" &&
|
||||
if (isIdentifier(targetFunction) && getElementOrPropertyAccessName(assignmentTarget) !== "prototype" &&
|
||||
trackedEs5Classes && trackedEs5Classes.has(targetFunction.text)) {
|
||||
if (isFunctionExpression(binaryExpression.right) || isArrowFunction(binaryExpression.right)) {
|
||||
addNodeWithRecursiveChild(node, binaryExpression.right, targetFunction);
|
||||
}
|
||||
else {
|
||||
else if (isBindableStaticAccessExpression(assignmentTarget)) {
|
||||
startNode(binaryExpression, targetFunction);
|
||||
addNodeWithRecursiveChild(binaryExpression.left, binaryExpression.right, assignmentTarget.name);
|
||||
addNodeWithRecursiveChild(binaryExpression.left, binaryExpression.right, getNameOrArgument(assignmentTarget));
|
||||
endNode();
|
||||
}
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user