Skip to content

Allow special element access assignments to create declarations #33537

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7f5ce60
Start enabling element access special assignment
andrewbranch Jul 25, 2019
d784e57
Treat element access assignment as special assignment in JS
andrewbranch Jul 25, 2019
7a925b9
Make declarations for bindable element access expressions
andrewbranch Sep 17, 2019
3e206c4
Fix navigationBar crash
andrewbranch Sep 18, 2019
6218fe0
Add multi-level test for JS
andrewbranch Sep 18, 2019
7b57aca
Propagate element access expressions to more code paths
andrewbranch Sep 18, 2019
020508b
Fix property access on `this`
andrewbranch Sep 18, 2019
cba5fba
Add quick info test
andrewbranch Sep 19, 2019
e148c60
Uhhh I guess this is fine
andrewbranch Sep 20, 2019
6589523
Fix module["exports"] and property access chained off element access
andrewbranch Sep 20, 2019
bd6602c
Add test for this property assignment
andrewbranch Sep 20, 2019
c04e30a
Add test for and fix prototype property assignment
andrewbranch Sep 20, 2019
a357d31
Fix teeeest???
andrewbranch Sep 20, 2019
3146066
Update APIs
andrewbranch Sep 20, 2019
862b822
Fix element access declarations on `this`
andrewbranch Sep 25, 2019
7436c2d
Fix go-to-definition
andrewbranch Sep 25, 2019
82283fc
Merge branch 'master' into feature/element-access-assignment
andrewbranch Sep 26, 2019
f25848a
Add declaration emit to tests
andrewbranch Sep 27, 2019
e2c6049
Merge branch 'master' into feature/element-access-assignment
andrewbranch Sep 27, 2019
fe3a574
Reconcile with late-bound symbol element access assignment
andrewbranch Sep 27, 2019
34967b8
Fix baselines
andrewbranch Sep 27, 2019
72272d9
Add JS declaration back to tests
andrewbranch Sep 27, 2019
23d7946
Merge branch 'master' into feature/element-access-assignment
andrewbranch Sep 30, 2019
98baa61
Fix JS declaration emit of non-late-bound string literal property names
andrewbranch Sep 30, 2019
389902f
Revert accidental auto-format
andrewbranch Sep 30, 2019
ef30b11
Use `isAccessExpression`
andrewbranch Sep 30, 2019
96575df
Add underscore escaping member to test
andrewbranch Sep 30, 2019
d8fa7d6
Fix and test navBar changes
andrewbranch Sep 30, 2019
81819ed
Merge branch 'master' into feature/element-access-assignment
andrewbranch Sep 30, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 42 additions & 44 deletions src/compiler/binder.ts

Large diffs are not rendered by default.

36 changes: 27 additions & 9 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3033,7 +3033,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);
Expand Down Expand Up @@ -4869,6 +4869,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;
Expand All @@ -4881,14 +4890,18 @@ 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));
}
}
}

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
Expand Down Expand Up @@ -5764,8 +5777,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[] = [];
Expand Down Expand Up @@ -6861,13 +6873,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;
Expand Down Expand Up @@ -7242,12 +7256,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))
Expand Down Expand Up @@ -7428,7 +7445,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) {
Expand Down Expand Up @@ -32028,7 +32046,7 @@ namespace ts {
return node;
case SyntaxKind.PropertyAccessExpression:
do {
if (isModuleExportsPropertyAccessExpression(node.expression)) {
if (isModuleExportsAccessExpression(node.expression)) {
return node.name;
}
node = node.expression;
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2260,7 +2260,7 @@ namespace ts {
return !expression.numericLiteralFlags && !stringContains(text, tokenToString(SyntaxKind.DotToken)!) &&
(!dotHasTrivia || printerOptions.removeComments);
}
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
Expand Down
34 changes: 30 additions & 4 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1301,7 +1301,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. */
Expand Down Expand Up @@ -1688,7 +1688,7 @@ namespace ts {
kind: SyntaxKind.RegularExpressionLiteral;
}

export interface NoSubstitutionTemplateLiteral extends LiteralExpression, TemplateLiteralLikeNode {
export interface NoSubstitutionTemplateLiteral extends LiteralExpression, TemplateLiteralLikeNode, Declaration {
kind: SyntaxKind.NoSubstitutionTemplateLiteral;
}

Expand Down Expand Up @@ -1717,7 +1717,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;
Expand Down Expand Up @@ -1837,7 +1837,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 {
Expand Down
Loading