@@ -17736,25 +17736,23 @@ namespace ts {
17736
17736
* Check whether the requested property access is valid.
17737
17737
* Returns true if node is a valid property access, and false otherwise.
17738
17738
* @param node The node to be checked.
17739
- * @param left The left hand side of the property access (e.g.: the super in `super.foo`) .
17740
- * @param type The type of left.
17741
- * @param prop The symbol for the right hand side of the property access .
17739
+ * @param isSuper True if the access is from `super.` .
17740
+ * @param type The type of the object whose property is being accessed. (Not the type of the property.)
17741
+ * @param prop The symbol for the property being accessed .
17742
17742
*/
17743
- function checkPropertyAccessibility(node: PropertyAccessExpression | QualifiedName | VariableLikeDeclaration | ImportTypeNode, left: Expression | QualifiedName | ImportTypeNode, type: Type, prop: Symbol): boolean {
17743
+ function checkPropertyAccessibility(
17744
+ node: PropertyAccessExpression | QualifiedName | PropertyAccessExpression | VariableDeclaration | ParameterDeclaration | ImportTypeNode | PropertyAssignment | ShorthandPropertyAssignment | BindingElement,
17745
+ isSuper: boolean, type: Type, prop: Symbol): boolean {
17744
17746
const flags = getDeclarationModifierFlagsFromSymbol(prop);
17745
- const errorNode = node.kind === SyntaxKind.PropertyAccessExpression || node.kind === SyntaxKind.VariableDeclaration ?
17746
- node.name :
17747
- node.kind === SyntaxKind.ImportType ?
17748
- node :
17749
- (<QualifiedName>node).right;
17747
+ const errorNode = node.kind === SyntaxKind.QualifiedName ? node.right : node.kind === SyntaxKind.ImportType ? node : node.name;
17750
17748
17751
17749
if (getCheckFlags(prop) & CheckFlags.ContainsPrivate) {
17752
17750
// Synthetic property with private constituent property
17753
17751
error(errorNode, Diagnostics.Property_0_has_conflicting_declarations_and_is_inaccessible_in_type_1, symbolToString(prop), typeToString(type));
17754
17752
return false;
17755
17753
}
17756
17754
17757
- if (left.kind === SyntaxKind.SuperKeyword ) {
17755
+ if (isSuper ) {
17758
17756
// TS 1.0 spec (April 2014): 4.8.2
17759
17757
// - In a constructor, instance member function, instance member accessor, or
17760
17758
// instance member variable initializer where this references a derived class instance,
@@ -17807,7 +17805,7 @@ namespace ts {
17807
17805
// Property is known to be protected at this point
17808
17806
17809
17807
// All protected properties of a supertype are accessible in a super access
17810
- if (left.kind === SyntaxKind.SuperKeyword ) {
17808
+ if (isSuper ) {
17811
17809
return true;
17812
17810
}
17813
17811
@@ -17940,7 +17938,7 @@ namespace ts {
17940
17938
checkPropertyNotUsedBeforeDeclaration(prop, node, right);
17941
17939
markPropertyAsReferenced(prop, node, left.kind === SyntaxKind.ThisKeyword);
17942
17940
getNodeLinks(node).resolvedSymbol = prop;
17943
- checkPropertyAccessibility(node, left, apparentType, prop);
17941
+ checkPropertyAccessibility(node, left.kind === SyntaxKind.SuperKeyword , apparentType, prop);
17944
17942
if (assignmentKind) {
17945
17943
if (isReferenceToReadonlyEntity(<Expression>node, prop) || isReferenceThroughNamespaceImport(<Expression>node)) {
17946
17944
error(right, Diagnostics.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, idText(right));
@@ -18174,16 +18172,16 @@ namespace ts {
18174
18172
function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName | ImportTypeNode, propertyName: __String): boolean {
18175
18173
switch (node.kind) {
18176
18174
case SyntaxKind.PropertyAccessExpression:
18177
- return isValidPropertyAccessWithType(node, node.expression, propertyName, getWidenedType(checkExpression(node.expression)));
18175
+ return isValidPropertyAccessWithType(node, node.expression.kind === SyntaxKind.SuperKeyword , propertyName, getWidenedType(checkExpression(node.expression)));
18178
18176
case SyntaxKind.QualifiedName:
18179
- return isValidPropertyAccessWithType(node, node.left , propertyName, getWidenedType(checkExpression(node.left)));
18177
+ return isValidPropertyAccessWithType(node, /*isSuper*/ false , propertyName, getWidenedType(checkExpression(node.left)));
18180
18178
case SyntaxKind.ImportType:
18181
- return isValidPropertyAccessWithType(node, node , propertyName, getTypeFromTypeNode(node));
18179
+ return isValidPropertyAccessWithType(node, /*isSuper*/ false , propertyName, getTypeFromTypeNode(node));
18182
18180
}
18183
18181
}
18184
18182
18185
18183
function isValidPropertyAccessForCompletions(node: PropertyAccessExpression | ImportTypeNode, type: Type, property: Symbol): boolean {
18186
- return isValidPropertyAccessWithType(node, node.kind === SyntaxKind.ImportType ? node : node.expression , property.escapedName, type)
18184
+ return isValidPropertyAccessWithType(node, node.kind !== SyntaxKind.ImportType && node.expression.kind === SyntaxKind.SuperKeyword , property.escapedName, type)
18187
18185
&& (!(property.flags & SymbolFlags.Method) || isValidMethodAccess(property, type));
18188
18186
}
18189
18187
function isValidMethodAccess(method: Symbol, actualThisType: Type): boolean {
@@ -18206,17 +18204,17 @@ namespace ts {
18206
18204
18207
18205
function isValidPropertyAccessWithType(
18208
18206
node: PropertyAccessExpression | QualifiedName | ImportTypeNode,
18209
- left: LeftHandSideExpression | QualifiedName | ImportTypeNode ,
18207
+ isSuper: boolean ,
18210
18208
propertyName: __String,
18211
18209
type: Type): boolean {
18212
18210
18213
18211
if (type === errorType || isTypeAny(type)) {
18214
18212
return true;
18215
18213
}
18216
18214
const prop = getPropertyOfType(type, propertyName);
18217
- return prop ? checkPropertyAccessibility(node, left , type, prop)
18215
+ return prop ? checkPropertyAccessibility(node, isSuper , type, prop)
18218
18216
// In js files properties of unions are allowed in completion
18219
- : isInJavaScriptFile(node) && (type.flags & TypeFlags.Union) !== 0 && (<UnionType>type).types.some(elementType => isValidPropertyAccessWithType(node, left , propertyName, elementType));
18217
+ : isInJavaScriptFile(node) && (type.flags & TypeFlags.Union) !== 0 && (<UnionType>type).types.some(elementType => isValidPropertyAccessWithType(node, isSuper , propertyName, elementType));
18220
18218
}
18221
18219
18222
18220
/**
@@ -21093,19 +21091,19 @@ namespace ts {
21093
21091
return booleanType;
21094
21092
}
21095
21093
21096
- function checkObjectLiteralAssignment(node: ObjectLiteralExpression, sourceType: Type): Type {
21094
+ function checkObjectLiteralAssignment(node: ObjectLiteralExpression, sourceType: Type, rightIsThis?: boolean ): Type {
21097
21095
const properties = node.properties;
21098
21096
if (strictNullChecks && properties.length === 0) {
21099
21097
return checkNonNullType(sourceType, node);
21100
21098
}
21101
21099
for (const p of properties) {
21102
- checkObjectLiteralDestructuringPropertyAssignment(sourceType, p, properties);
21100
+ checkObjectLiteralDestructuringPropertyAssignment(sourceType, p, properties, rightIsThis );
21103
21101
}
21104
21102
return sourceType;
21105
21103
}
21106
21104
21107
21105
/** Note: If property cannot be a SpreadAssignment, then allProperties does not need to be provided */
21108
- function checkObjectLiteralDestructuringPropertyAssignment(objectLiteralType: Type, property: ObjectLiteralElementLike, allProperties?: NodeArray<ObjectLiteralElementLike>) {
21106
+ function checkObjectLiteralDestructuringPropertyAssignment(objectLiteralType: Type, property: ObjectLiteralElementLike, allProperties?: NodeArray<ObjectLiteralElementLike>, rightIsThis = false ) {
21109
21107
if (property.kind === SyntaxKind.PropertyAssignment || property.kind === SyntaxKind.ShorthandPropertyAssignment) {
21110
21108
const name = property.name;
21111
21109
if (name.kind === SyntaxKind.ComputedPropertyName) {
@@ -21115,20 +21113,10 @@ namespace ts {
21115
21113
return undefined;
21116
21114
}
21117
21115
21118
- const text = getTextOfPropertyName(name);
21119
- const type = isTypeAny(objectLiteralType)
21120
- ? objectLiteralType
21121
- : getTypeOfPropertyOfType(objectLiteralType, text) ||
21122
- isNumericLiteralName(text) && getIndexTypeOfType(objectLiteralType, IndexKind.Number) ||
21123
- getIndexTypeOfType(objectLiteralType, IndexKind.String);
21116
+ const type = getTypeOfObjectLiteralDestructuringProperty(objectLiteralType, name, property, rightIsThis);
21124
21117
if (type) {
21125
- if (property.kind === SyntaxKind.ShorthandPropertyAssignment) {
21126
- return checkDestructuringAssignment(property, type);
21127
- }
21128
- else {
21129
- // non-shorthand property assignments should always have initializers
21130
- return checkDestructuringAssignment(property.initializer, type);
21131
- }
21118
+ // non-shorthand property assignments should always have initializers
21119
+ return checkDestructuringAssignment(property.kind === SyntaxKind.ShorthandPropertyAssignment ? property : property.initializer, type);
21132
21120
}
21133
21121
else {
21134
21122
error(name, Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(objectLiteralType), declarationNameToString(name));
@@ -21153,6 +21141,25 @@ namespace ts {
21153
21141
}
21154
21142
}
21155
21143
21144
+ function getTypeOfObjectLiteralDestructuringProperty(objectLiteralType: Type, name: PropertyName, property: PropertyAssignment | ShorthandPropertyAssignment, rightIsThis: boolean) {
21145
+ if (isTypeAny(objectLiteralType)) {
21146
+ return objectLiteralType;
21147
+ }
21148
+
21149
+ let type: Type | undefined;
21150
+ const text = getTextOfPropertyName(name);
21151
+ if (text) { // TODO: GH#26379
21152
+ const prop = getPropertyOfType(objectLiteralType, text);
21153
+ if (prop) {
21154
+ markPropertyAsReferenced(prop, property, rightIsThis);
21155
+ checkPropertyAccessibility(property, /*isSuper*/ false, objectLiteralType, prop);
21156
+ type = getTypeOfSymbol(prop);
21157
+ }
21158
+ type = type || (isNumericLiteralName(text) ? getIndexTypeOfType(objectLiteralType, IndexKind.Number) : undefined);
21159
+ }
21160
+ return type || getIndexTypeOfType(objectLiteralType, IndexKind.String);
21161
+ }
21162
+
21156
21163
function checkArrayLiteralAssignment(node: ArrayLiteralExpression, sourceType: Type, checkMode?: CheckMode): Type {
21157
21164
const elements = node.elements;
21158
21165
if (languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) {
@@ -21214,7 +21221,7 @@ namespace ts {
21214
21221
return undefined;
21215
21222
}
21216
21223
21217
- function checkDestructuringAssignment(exprOrAssignment: Expression | ShorthandPropertyAssignment, sourceType: Type, checkMode?: CheckMode): Type {
21224
+ function checkDestructuringAssignment(exprOrAssignment: Expression | ShorthandPropertyAssignment, sourceType: Type, checkMode?: CheckMode, rightIsThis?: boolean ): Type {
21218
21225
let target: Expression;
21219
21226
if (exprOrAssignment.kind === SyntaxKind.ShorthandPropertyAssignment) {
21220
21227
const prop = <ShorthandPropertyAssignment>exprOrAssignment;
@@ -21238,7 +21245,7 @@ namespace ts {
21238
21245
target = (<BinaryExpression>target).left;
21239
21246
}
21240
21247
if (target.kind === SyntaxKind.ObjectLiteralExpression) {
21241
- return checkObjectLiteralAssignment(<ObjectLiteralExpression>target, sourceType);
21248
+ return checkObjectLiteralAssignment(<ObjectLiteralExpression>target, sourceType, rightIsThis );
21242
21249
}
21243
21250
if (target.kind === SyntaxKind.ArrayLiteralExpression) {
21244
21251
return checkArrayLiteralAssignment(<ArrayLiteralExpression>target, sourceType, checkMode);
@@ -21337,7 +21344,7 @@ namespace ts {
21337
21344
function checkBinaryLikeExpression(left: Expression, operatorToken: Node, right: Expression, checkMode?: CheckMode, errorNode?: Node): Type {
21338
21345
const operator = operatorToken.kind;
21339
21346
if (operator === SyntaxKind.EqualsToken && (left.kind === SyntaxKind.ObjectLiteralExpression || left.kind === SyntaxKind.ArrayLiteralExpression)) {
21340
- return checkDestructuringAssignment(left, checkExpression(right, checkMode), checkMode);
21347
+ return checkDestructuringAssignment(left, checkExpression(right, checkMode), checkMode, right.kind === SyntaxKind.ThisKeyword );
21341
21348
}
21342
21349
let leftType: Type;
21343
21350
if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken) {
@@ -24400,7 +24407,7 @@ namespace ts {
24400
24407
const property = getPropertyOfType(parentType!, nameText)!; // TODO: GH#18217
24401
24408
markPropertyAsReferenced(property, /*nodeForCheckWriteOnly*/ undefined, /*isThisAccess*/ false); // A destructuring is never a write-only reference.
24402
24409
if (parent.initializer && property && !isComputedPropertyName(name)) {
24403
- checkPropertyAccessibility(parent, parent.initializer, parentType!, property);
24410
+ checkPropertyAccessibility(parent, parent.initializer.kind === SyntaxKind.SuperKeyword , parentType!, property);
24404
24411
}
24405
24412
}
24406
24413
}
0 commit comments