@@ -3736,9 +3736,9 @@ namespace ts {
3736
3736
return getObjectFlags(type) & ObjectFlags.Reference ? (<TypeReference>type).target : type;
3737
3737
}
3738
3738
3739
- function hasBaseType(type: BaseType , checkBase: BaseType ) {
3739
+ function hasBaseType(type: Type , checkBase: Type ) {
3740
3740
return check(type);
3741
- function check(type: BaseType ): boolean {
3741
+ function check(type: Type ): boolean {
3742
3742
if (getObjectFlags(type) & (ObjectFlags.ClassOrInterface | ObjectFlags.Reference)) {
3743
3743
const target = <InterfaceType>getTargetType(type);
3744
3744
return target === checkBase || forEach(getBaseTypes(target), check);
@@ -4939,29 +4939,33 @@ namespace ts {
4939
4939
}
4940
4940
4941
4941
function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: string): Symbol {
4942
- const types = containingType.types;
4943
- const excludeModifiers = containingType.flags & TypeFlags.Union ? ModifierFlags.Private | ModifierFlags.Protected : 0;
4944
4942
let props: Symbol[];
4943
+ const types = containingType.types;
4944
+ const isUnion = containingType.flags & TypeFlags.Union;
4945
+ const excludeModifiers = isUnion ? ModifierFlags.NonPublicAccessibilityModifier : 0;
4945
4946
// Flags we want to propagate to the result if they exist in all source symbols
4946
- let commonFlags = (containingType.flags & TypeFlags.Intersection) ? SymbolFlags.Optional : SymbolFlags.None ;
4947
+ let commonFlags = isUnion ? SymbolFlags.None : SymbolFlags.Optional ;
4947
4948
let checkFlags = CheckFlags.SyntheticProperty;
4948
4949
for (const current of types) {
4949
4950
const type = getApparentType(current);
4950
4951
if (type !== unknownType) {
4951
4952
const prop = getPropertyOfType(type, name);
4952
- if (prop && !(getDeclarationModifierFlagsFromSymbol(prop) & excludeModifiers)) {
4953
+ const modifiers = prop ? getDeclarationModifierFlagsFromSymbol(prop) : 0;
4954
+ if (prop && !(modifiers & excludeModifiers)) {
4953
4955
commonFlags &= prop.flags;
4954
4956
if (!props) {
4955
4957
props = [prop];
4956
4958
}
4957
4959
else if (!contains(props, prop)) {
4958
4960
props.push(prop);
4959
4961
}
4960
- if (isReadonlySymbol(prop)) {
4961
- checkFlags |= CheckFlags.Readonly;
4962
- }
4962
+ checkFlags |= (isReadonlySymbol(prop) ? CheckFlags.Readonly : 0) |
4963
+ (!(modifiers & ModifierFlags.NonPublicAccessibilityModifier) ? CheckFlags.ContainsPublic : 0) |
4964
+ (modifiers & ModifierFlags.Protected ? CheckFlags.ContainsProtected : 0) |
4965
+ (modifiers & ModifierFlags.Private ? CheckFlags.ContainsPrivate : 0) |
4966
+ (modifiers & ModifierFlags.Static ? CheckFlags.ContainsStatic : 0);
4963
4967
}
4964
- else if (containingType.flags & TypeFlags.Union ) {
4968
+ else if (isUnion ) {
4965
4969
checkFlags |= CheckFlags.Partial;
4966
4970
}
4967
4971
}
@@ -4992,7 +4996,7 @@ namespace ts {
4992
4996
result.checkFlags = checkFlags;
4993
4997
result.containingType = containingType;
4994
4998
result.declarations = declarations;
4995
- result.type = containingType.flags & TypeFlags.Union ? getUnionType(propTypes) : getIntersectionType(propTypes);
4999
+ result.type = isUnion ? getUnionType(propTypes) : getIntersectionType(propTypes);
4996
5000
return result;
4997
5001
}
4998
5002
@@ -6066,7 +6070,10 @@ namespace ts {
6066
6070
if (type.flags & TypeFlags.Union && typeSet.unionIndex === undefined) {
6067
6071
typeSet.unionIndex = typeSet.length;
6068
6072
}
6069
- typeSet.push(type);
6073
+ if (!(type.flags & TypeFlags.Object && (<ObjectType>type).objectFlags & ObjectFlags.Anonymous &&
6074
+ type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method) && containsIdenticalType(typeSet, type))) {
6075
+ typeSet.push(type);
6076
+ }
6070
6077
}
6071
6078
}
6072
6079
@@ -7950,6 +7957,12 @@ namespace ts {
7950
7957
const sourcePropFlags = getDeclarationModifierFlagsFromSymbol(sourceProp);
7951
7958
const targetPropFlags = getDeclarationModifierFlagsFromSymbol(targetProp);
7952
7959
if (sourcePropFlags & ModifierFlags.Private || targetPropFlags & ModifierFlags.Private) {
7960
+ if (getCheckFlags(sourceProp) & CheckFlags.ContainsPrivate) {
7961
+ if (reportErrors) {
7962
+ reportError(Diagnostics.Property_0_has_conflicting_declarations_and_is_inaccessible_in_type_1, symbolToString(sourceProp), typeToString(source));
7963
+ }
7964
+ return Ternary.False;
7965
+ }
7953
7966
if (sourceProp.valueDeclaration !== targetProp.valueDeclaration) {
7954
7967
if (reportErrors) {
7955
7968
if (sourcePropFlags & ModifierFlags.Private && targetPropFlags & ModifierFlags.Private) {
@@ -7965,13 +7978,10 @@ namespace ts {
7965
7978
}
7966
7979
}
7967
7980
else if (targetPropFlags & ModifierFlags.Protected) {
7968
- const sourceDeclaredInClass = sourceProp.parent && sourceProp.parent.flags & SymbolFlags.Class;
7969
- const sourceClass = sourceDeclaredInClass ? <InterfaceType>getDeclaredTypeOfSymbol(getParentOfSymbol(sourceProp)) : undefined;
7970
- const targetClass = <InterfaceType>getDeclaredTypeOfSymbol(getParentOfSymbol(targetProp));
7971
- if (!sourceClass || !hasBaseType(sourceClass, targetClass)) {
7981
+ if (!isValidOverrideOf(sourceProp, targetProp)) {
7972
7982
if (reportErrors) {
7973
- reportError(Diagnostics.Property_0_is_protected_but_type_1_is_not_a_class_derived_from_2,
7974
- symbolToString(targetProp), typeToString(sourceClass || source), typeToString(targetClass ));
7983
+ reportError(Diagnostics.Property_0_is_protected_but_type_1_is_not_a_class_derived_from_2, symbolToString(targetProp),
7984
+ typeToString(getDeclaringClass(sourceProp) || source), typeToString(getDeclaringClass(targetProp) || target ));
7975
7985
}
7976
7986
return Ternary.False;
7977
7987
}
@@ -8213,6 +8223,49 @@ namespace ts {
8213
8223
}
8214
8224
}
8215
8225
8226
+ // Invoke the callback for each underlying property symbol of the given symbol and return the first
8227
+ // value that isn't undefined.
8228
+ function forEachProperty<T>(prop: Symbol, callback: (p: Symbol) => T): T {
8229
+ if (getCheckFlags(prop) & CheckFlags.SyntheticProperty) {
8230
+ for (const t of (<TransientSymbol>prop).containingType.types) {
8231
+ const p = getPropertyOfType(t, prop.name);
8232
+ const result = p && forEachProperty(p, callback);
8233
+ if (result) {
8234
+ return result;
8235
+ }
8236
+ }
8237
+ return undefined;
8238
+ }
8239
+ return callback(prop);
8240
+ }
8241
+
8242
+ // Return the declaring class type of a property or undefined if property not declared in class
8243
+ function getDeclaringClass(prop: Symbol) {
8244
+ return prop.parent && prop.parent.flags & SymbolFlags.Class ? getDeclaredTypeOfSymbol(getParentOfSymbol(prop)) : undefined;
8245
+ }
8246
+
8247
+ // Return true if some underlying source property is declared in a class that derives
8248
+ // from the given base class.
8249
+ function isPropertyInClassDerivedFrom(prop: Symbol, baseClass: Type) {
8250
+ return forEachProperty(prop, sp => {
8251
+ const sourceClass = getDeclaringClass(sp);
8252
+ return sourceClass ? hasBaseType(sourceClass, baseClass) : false;
8253
+ });
8254
+ }
8255
+
8256
+ // Return true if source property is a valid override of protected parts of target property.
8257
+ function isValidOverrideOf(sourceProp: Symbol, targetProp: Symbol) {
8258
+ return !forEachProperty(targetProp, tp => getDeclarationModifierFlagsFromSymbol(tp) & ModifierFlags.Protected ?
8259
+ !isPropertyInClassDerivedFrom(sourceProp, getDeclaringClass(tp)) : false);
8260
+ }
8261
+
8262
+ // Return true if the given class derives from each of the declaring classes of the protected
8263
+ // constituents of the given property.
8264
+ function isClassDerivedFromDeclaringClasses(checkClass: Type, prop: Symbol) {
8265
+ return forEachProperty(prop, p => getDeclarationModifierFlagsFromSymbol(p) & ModifierFlags.Protected ?
8266
+ !hasBaseType(checkClass, getDeclaringClass(p)) : false) ? undefined : checkClass;
8267
+ }
8268
+
8216
8269
// Return true if the given type is the constructor type for an abstract class
8217
8270
function isAbstractConstructorType(type: Type) {
8218
8271
if (getObjectFlags(type) & ObjectFlags.Anonymous) {
@@ -12369,7 +12422,22 @@ namespace ts {
12369
12422
}
12370
12423
12371
12424
function getDeclarationModifierFlagsFromSymbol(s: Symbol): ModifierFlags {
12372
- return s.valueDeclaration ? getCombinedModifierFlags(s.valueDeclaration) : s.flags & SymbolFlags.Prototype ? ModifierFlags.Public | ModifierFlags.Static : 0;
12425
+ if (s.valueDeclaration) {
12426
+ const flags = getCombinedModifierFlags(s.valueDeclaration);
12427
+ return s.parent && s.parent.flags & SymbolFlags.Class ? flags : flags & ~ModifierFlags.AccessibilityModifier;
12428
+ }
12429
+ if (getCheckFlags(s) & CheckFlags.SyntheticProperty) {
12430
+ const checkFlags = (<TransientSymbol>s).checkFlags;
12431
+ const accessModifier = checkFlags & CheckFlags.ContainsPrivate ? ModifierFlags.Private :
12432
+ checkFlags & CheckFlags.ContainsPublic ? ModifierFlags.Public :
12433
+ ModifierFlags.Protected;
12434
+ const staticModifier = checkFlags & CheckFlags.ContainsStatic ? ModifierFlags.Static : 0;
12435
+ return accessModifier | staticModifier;
12436
+ }
12437
+ if (s.flags & SymbolFlags.Prototype) {
12438
+ return ModifierFlags.Public | ModifierFlags.Static;
12439
+ }
12440
+ return 0;
12373
12441
}
12374
12442
12375
12443
function getDeclarationNodeFlagsFromSymbol(s: Symbol): NodeFlags {
@@ -12384,12 +12452,18 @@ namespace ts {
12384
12452
* @param type The type of left.
12385
12453
* @param prop The symbol for the right hand side of the property access.
12386
12454
*/
12387
- function checkClassPropertyAccess (node: PropertyAccessExpression | QualifiedName | VariableLikeDeclaration, left: Expression | QualifiedName, type: Type, prop: Symbol): boolean {
12455
+ function checkPropertyAccessibility (node: PropertyAccessExpression | QualifiedName | VariableLikeDeclaration, left: Expression | QualifiedName, type: Type, prop: Symbol): boolean {
12388
12456
const flags = getDeclarationModifierFlagsFromSymbol(prop);
12389
- const declaringClass = <InterfaceType>getDeclaredTypeOfSymbol(getParentOfSymbol(prop));
12390
12457
const errorNode = node.kind === SyntaxKind.PropertyAccessExpression || node.kind === SyntaxKind.VariableDeclaration ?
12391
12458
(<PropertyAccessExpression | VariableDeclaration>node).name :
12392
12459
(<QualifiedName>node).right;
12460
+
12461
+ if (getCheckFlags(prop) & CheckFlags.ContainsPrivate) {
12462
+ // Synthetic property with private constituent property
12463
+ error(errorNode, Diagnostics.Property_0_has_conflicting_declarations_and_is_inaccessible_in_type_1, symbolToString(prop), typeToString(type));
12464
+ return false;
12465
+ }
12466
+
12393
12467
if (left.kind === SyntaxKind.SuperKeyword) {
12394
12468
// TS 1.0 spec (April 2014): 4.8.2
12395
12469
// - In a constructor, instance member function, instance member accessor, or
@@ -12408,14 +12482,12 @@ namespace ts {
12408
12482
return false;
12409
12483
}
12410
12484
}
12411
-
12412
12485
if (flags & ModifierFlags.Abstract) {
12413
12486
// A method cannot be accessed in a super property access if the method is abstract.
12414
12487
// This error could mask a private property access error. But, a member
12415
12488
// cannot simultaneously be private and abstract, so this will trigger an
12416
12489
// additional error elsewhere.
12417
-
12418
- error(errorNode, Diagnostics.Abstract_method_0_in_class_1_cannot_be_accessed_via_super_expression, symbolToString(prop), typeToString(declaringClass));
12490
+ error(errorNode, Diagnostics.Abstract_method_0_in_class_1_cannot_be_accessed_via_super_expression, symbolToString(prop), typeToString(getDeclaringClass(prop)));
12419
12491
return false;
12420
12492
}
12421
12493
}
@@ -12431,7 +12503,7 @@ namespace ts {
12431
12503
if (flags & ModifierFlags.Private) {
12432
12504
const declaringClassDeclaration = <ClassLikeDeclaration>getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop));
12433
12505
if (!isNodeWithinClass(node, declaringClassDeclaration)) {
12434
- error(errorNode, Diagnostics.Property_0_is_private_and_only_accessible_within_class_1, symbolToString(prop), typeToString(declaringClass ));
12506
+ error(errorNode, Diagnostics.Property_0_is_private_and_only_accessible_within_class_1, symbolToString(prop), typeToString(getDeclaringClass(prop) ));
12435
12507
return false;
12436
12508
}
12437
12509
return true;
@@ -12444,15 +12516,15 @@ namespace ts {
12444
12516
return true;
12445
12517
}
12446
12518
12447
- // Get the enclosing class that has the declaring class as its base type
12519
+ // Find the first enclosing class that has the declaring classes of the protected constituents
12520
+ // of the property as base classes
12448
12521
const enclosingClass = forEachEnclosingClass(node, enclosingDeclaration => {
12449
12522
const enclosingClass = <InterfaceType>getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingDeclaration));
12450
- return hasBaseType (enclosingClass, declaringClass ) ? enclosingClass : undefined;
12523
+ return isClassDerivedFromDeclaringClasses (enclosingClass, prop ) ? enclosingClass : undefined;
12451
12524
});
12452
-
12453
12525
// A protected property is accessible if the property is within the declaring class or classes derived from it
12454
12526
if (!enclosingClass) {
12455
- error(errorNode, Diagnostics.Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses, symbolToString(prop), typeToString(declaringClass ));
12527
+ error(errorNode, Diagnostics.Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses, symbolToString(prop), typeToString(getDeclaringClass(prop) || type ));
12456
12528
return false;
12457
12529
}
12458
12530
// No further restrictions for static properties
@@ -12464,9 +12536,7 @@ namespace ts {
12464
12536
// get the original type -- represented as the type constraint of the 'this' type
12465
12537
type = getConstraintOfTypeParameter(<TypeParameter>type);
12466
12538
}
12467
-
12468
- // TODO: why is the first part of this check here?
12469
- if (!(getObjectFlags(getTargetType(type)) & ObjectFlags.ClassOrInterface && hasBaseType(<InterfaceType>type, enclosingClass))) {
12539
+ if (!(getObjectFlags(getTargetType(type)) & ObjectFlags.ClassOrInterface && hasBaseType(type, enclosingClass))) {
12470
12540
error(errorNode, Diagnostics.Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1, symbolToString(prop), typeToString(enclosingClass));
12471
12541
return false;
12472
12542
}
@@ -12553,9 +12623,7 @@ namespace ts {
12553
12623
12554
12624
getNodeLinks(node).resolvedSymbol = prop;
12555
12625
12556
- if (prop.parent && prop.parent.flags & SymbolFlags.Class) {
12557
- checkClassPropertyAccess(node, left, apparentType, prop);
12558
- }
12626
+ checkPropertyAccessibility(node, left, apparentType, prop);
12559
12627
12560
12628
const propType = getTypeOfSymbol(prop);
12561
12629
const assignmentKind = getAssignmentTargetKind(node);
@@ -12587,8 +12655,8 @@ namespace ts {
12587
12655
const type = checkExpression(left);
12588
12656
if (type !== unknownType && !isTypeAny(type)) {
12589
12657
const prop = getPropertyOfType(getWidenedType(type), propertyName);
12590
- if (prop && prop.parent && prop.parent.flags & SymbolFlags.Class ) {
12591
- return checkClassPropertyAccess (node, left, type, prop);
12658
+ if (prop) {
12659
+ return checkPropertyAccessibility (node, left, type, prop);
12592
12660
}
12593
12661
}
12594
12662
return true;
@@ -17527,8 +17595,8 @@ namespace ts {
17527
17595
const name = node.propertyName || <Identifier>node.name;
17528
17596
const property = getPropertyOfType(parentType, getTextOfPropertyName(name));
17529
17597
markPropertyAsReferenced(property);
17530
- if (parent.initializer && property && getParentOfSymbol(property) ) {
17531
- checkClassPropertyAccess (parent, parent.initializer, parentType, property);
17598
+ if (parent.initializer && property) {
17599
+ checkPropertyAccessibility (parent, parent.initializer, parentType, property);
17532
17600
}
17533
17601
}
17534
17602
0 commit comments