@@ -1577,8 +1577,8 @@ namespace ts {
1577
1577
}
1578
1578
}
1579
1579
1580
- function diagnosticName(nameArg: __String | Identifier) {
1581
- return isString(nameArg) ? unescapeLeadingUnderscores(nameArg as __String) : declarationNameToString(nameArg as Identifier);
1580
+ function diagnosticName(nameArg: __String | Identifier | PrivateName ) {
1581
+ return isString(nameArg) ? unescapeLeadingUnderscores(nameArg as __String) : declarationNameToString(nameArg as Identifier | PrivateName );
1582
1582
}
1583
1583
1584
1584
function isTypeParameterSymbolDeclaredInContainer(symbol: Symbol, container: Node) {
@@ -2676,15 +2676,16 @@ namespace ts {
2676
2676
return getUnionType(arrayFrom(typeofEQFacts.keys(), getLiteralType));
2677
2677
}
2678
2678
2679
- // A reserved member name starts with two underscores, but the third character cannot be an underscore
2680
- // or the @ symbol . A third underscore indicates an escaped form of an identifer that started
2679
+ // A reserved member name starts with two underscores, but the third character cannot be an underscore,
2680
+ // @ or # . A third underscore indicates an escaped form of an identifer that started
2681
2681
// with at least two underscores. The @ character indicates that the name is denoted by a well known ES
2682
- // Symbol instance.
2682
+ // Symbol instance and the # indicates that the name is a PrivateName .
2683
2683
function isReservedMemberName(name: __String) {
2684
2684
return (name as string).charCodeAt(0) === CharacterCodes._ &&
2685
2685
(name as string).charCodeAt(1) === CharacterCodes._ &&
2686
2686
(name as string).charCodeAt(2) !== CharacterCodes._ &&
2687
- (name as string).charCodeAt(2) !== CharacterCodes.at;
2687
+ (name as string).charCodeAt(2) !== CharacterCodes.at &&
2688
+ (name as string).charCodeAt(2) !== CharacterCodes.hash;
2688
2689
}
2689
2690
2690
2691
function getNamedMembers(members: SymbolTable): Symbol[] {
@@ -9211,7 +9212,9 @@ namespace ts {
9211
9212
}
9212
9213
9213
9214
function getLiteralTypeFromPropertyName(prop: Symbol, include: TypeFlags) {
9214
- if (!(getDeclarationModifierFlagsFromSymbol(prop) & ModifierFlags.NonPublicAccessibilityModifier)) {
9215
+ const hasNonPublicModifier = !!(getDeclarationModifierFlagsFromSymbol(prop) & ModifierFlags.NonPublicAccessibilityModifier);
9216
+ const hasPrivateName = prop.valueDeclaration && isNamedDeclaration(prop.valueDeclaration) && isPrivateName(prop.valueDeclaration.name);
9217
+ if (!hasNonPublicModifier && !hasPrivateName) {
9215
9218
let type = getLateBoundSymbol(prop).nameType;
9216
9219
if (!type && !isKnownSymbol(prop)) {
9217
9220
const name = prop.valueDeclaration && getNameOfDeclaration(prop.valueDeclaration);
@@ -12132,7 +12135,28 @@ namespace ts {
12132
12135
const unmatchedProperty = getUnmatchedProperty(source, target, requireOptionalProperties);
12133
12136
if (unmatchedProperty) {
12134
12137
if (reportErrors) {
12135
- reportError(Diagnostics.Property_0_is_missing_in_type_1, symbolToString(unmatchedProperty), typeToString(source));
12138
+ let hasReported = false;
12139
+ // give specific error in case where private names have the same description
12140
+ if (
12141
+ unmatchedProperty.valueDeclaration
12142
+ && isNamedDeclaration(unmatchedProperty.valueDeclaration)
12143
+ && isPrivateName(unmatchedProperty.valueDeclaration.name)
12144
+ && isClassDeclaration(source.symbol.valueDeclaration)
12145
+ ) {
12146
+ const privateNameDescription = unmatchedProperty.valueDeclaration.name.escapedText;
12147
+ const symbolTableKey = getPropertyNameForPrivateNameDescription(source.symbol, privateNameDescription);
12148
+ if (symbolTableKey && !!getPropertyOfType(source, symbolTableKey)) {
12149
+ reportError(
12150
+ Diagnostics.Property_0_is_missing_in_type_1_While_type_1_has_a_private_member_with_the_same_spelling_its_declaration_and_accessibility_are_distinct,
12151
+ diagnosticName(privateNameDescription),
12152
+ diagnosticName(source.symbol.valueDeclaration.name || ("anonymous" as __String))
12153
+ );
12154
+ hasReported = true;
12155
+ }
12156
+ }
12157
+ if (!hasReported) {
12158
+ reportError(Diagnostics.Property_0_is_missing_in_type_1, symbolToString(unmatchedProperty), typeToString(source));
12159
+ }
12136
12160
}
12137
12161
return Ternary.False;
12138
12162
}
@@ -18621,6 +18645,46 @@ namespace ts {
18621
18645
return checkPropertyAccessExpressionOrQualifiedName(node, node.left, node.right);
18622
18646
}
18623
18647
18648
+ function getPropertyByPrivateName(apparentType: Type, leftType: Type, right: PrivateName): Symbol | undefined {
18649
+ let classWithShadowedPrivateName;
18650
+ let klass = getContainingClass(right);
18651
+ while (klass) {
18652
+ const symbolTableKey = getPropertyNameForPrivateNameDescription(klass.symbol, right.escapedText);
18653
+ if (symbolTableKey) {
18654
+ const prop = getPropertyOfType(apparentType, symbolTableKey);
18655
+ if (prop) {
18656
+ if (classWithShadowedPrivateName) {
18657
+ error(
18658
+ right,
18659
+ Diagnostics.This_usage_of_0_refers_to_the_private_member_declared_in_its_enclosing_class_While_type_1_has_a_private_member_with_the_same_spelling_its_declaration_and_accessibility_are_distinct,
18660
+ diagnosticName(right),
18661
+ diagnosticName(classWithShadowedPrivateName.name || ("anonymous" as __String))
18662
+ );
18663
+ return undefined;
18664
+ }
18665
+ return prop;
18666
+ }
18667
+ else {
18668
+ classWithShadowedPrivateName = klass;
18669
+ }
18670
+ }
18671
+ klass = getContainingClass(klass);
18672
+ }
18673
+ // If this isn't a case of shadowing, and the lhs has a property with the same
18674
+ // private name description, then there is a privacy violation
18675
+ if (leftType.symbol.members) {
18676
+ const symbolTableKey = getPropertyNameForPrivateNameDescription(leftType.symbol, right.escapedText);
18677
+ if (symbolTableKey) {
18678
+ const prop = getPropertyOfType(apparentType, symbolTableKey);
18679
+ if (prop) {
18680
+ error(right, Diagnostics.Property_0_is_not_accessible_outside_class_1_because_it_has_a_private_name, symbolToString(prop), typeToString(getDeclaringClass(prop)!));
18681
+ }
18682
+ }
18683
+ }
18684
+ // not found
18685
+ return undefined;
18686
+ }
18687
+
18624
18688
function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier | PrivateName) {
18625
18689
let propType: Type;
18626
18690
const leftType = checkNonNullExpression(left);
@@ -18633,7 +18697,7 @@ namespace ts {
18633
18697
return apparentType;
18634
18698
}
18635
18699
const assignmentKind = getAssignmentTargetKind(node);
18636
- const prop = getPropertyOfType(apparentType, right.escapedText);
18700
+ const prop = isPrivateName(right) ? getPropertyByPrivateName(apparentType, leftType, right) : getPropertyOfType(apparentType, right.escapedText);
18637
18701
if (isIdentifier(left) && parentSymbol && !(prop && isConstEnumOrConstEnumOnlyModule(prop))) {
18638
18702
markAliasReferenced(parentSymbol, node);
18639
18703
}
@@ -21489,10 +21553,16 @@ namespace ts {
21489
21553
error(expr, Diagnostics.The_operand_of_a_delete_operator_must_be_a_property_reference);
21490
21554
return booleanType;
21491
21555
}
21556
+ if (expr.kind === SyntaxKind.PropertyAccessExpression && isPrivateName((expr as PropertyAccessExpression).name)) {
21557
+ error(expr, Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_private_name);
21558
+
21559
+ }
21492
21560
const links = getNodeLinks(expr);
21493
21561
const symbol = getExportSymbolOfValueSymbolIfExported(links.resolvedSymbol);
21494
- if (symbol && isReadonlySymbol(symbol)) {
21495
- error(expr, Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_read_only_property);
21562
+ if (symbol) {
21563
+ if (isReadonlySymbol(symbol)) {
21564
+ error(expr, Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_read_only_property);
21565
+ }
21496
21566
}
21497
21567
return booleanType;
21498
21568
}
@@ -22642,9 +22712,6 @@ namespace ts {
22642
22712
checkGrammarDecoratorsAndModifiers(node);
22643
22713
22644
22714
checkVariableLikeDeclaration(node);
22645
- if (node.name && isIdentifier(node.name) && node.name.originalKeywordKind === SyntaxKind.PrivateName) {
22646
- error(node, Diagnostics.Private_names_cannot_be_used_as_parameters);
22647
- }
22648
22715
const func = getContainingFunction(node)!;
22649
22716
if (hasModifier(node, ModifierFlags.ParameterPropertyModifier)) {
22650
22717
if (!(func.kind === SyntaxKind.Constructor && nodeIsPresent(func.body))) {
@@ -29321,6 +29388,9 @@ namespace ts {
29321
29388
else if (node.kind === SyntaxKind.Parameter && (flags & ModifierFlags.ParameterPropertyModifier) && (<ParameterDeclaration>node).dotDotDotToken) {
29322
29389
return grammarErrorOnNode(node, Diagnostics.A_parameter_property_cannot_be_declared_using_a_rest_parameter);
29323
29390
}
29391
+ else if (isNamedDeclaration(node) && (flags & ModifierFlags.AccessibilityModifier) && node.name.kind === SyntaxKind.PrivateName) {
29392
+ return grammarErrorOnNode(node, Diagnostics.Accessibility_modifiers_cannot_be_used_with_private_names);
29393
+ }
29324
29394
if (flags & ModifierFlags.Async) {
29325
29395
return checkGrammarAsyncModifier(node, lastAsync!);
29326
29396
}
@@ -30146,10 +30216,6 @@ namespace ts {
30146
30216
checkESModuleMarker(node.name);
30147
30217
}
30148
30218
30149
- if (isIdentifier(node.name) && node.name.originalKeywordKind === SyntaxKind.PrivateName) {
30150
- return grammarErrorOnNode(node.name, Diagnostics.Private_names_are_not_allowed_in_variable_declarations);
30151
- }
30152
-
30153
30219
const checkLetConstNames = (isLet(node) || isVarConst(node));
30154
30220
30155
30221
// 1. LexicalDeclaration : LetOrConst BindingList ;
0 commit comments