Added private and protected modifiers to constructors
This commit is contained in:
parent
6cc44d1a15
commit
f869b41f14
2 changed files with 101 additions and 16 deletions
|
@ -5889,16 +5889,20 @@ namespace ts {
|
|||
|
||||
const sourceSignatures = getSignaturesOfType(source, kind);
|
||||
const targetSignatures = getSignaturesOfType(target, kind);
|
||||
if (kind === SignatureKind.Construct && sourceSignatures.length && targetSignatures.length &&
|
||||
isAbstractConstructorType(source) && !isAbstractConstructorType(target)) {
|
||||
// An abstract constructor type is not assignable to a non-abstract constructor type
|
||||
// as it would otherwise be possible to new an abstract class. Note that the assignablity
|
||||
// check we perform for an extends clause excludes construct signatures from the target,
|
||||
// so this check never proceeds.
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type);
|
||||
if (kind === SignatureKind.Construct && sourceSignatures.length && targetSignatures.length) {
|
||||
if (isAbstractConstructorType(source) && !isAbstractConstructorType(target)) {
|
||||
// An abstract constructor type is not assignable to a non-abstract constructor type
|
||||
// as it would otherwise be possible to new an abstract class. Note that the assignablity
|
||||
// check we perform for an extends clause excludes construct signatures from the target,
|
||||
// so this check never proceeds.
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type);
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
if (!constructorRelatedTo(sourceSignatures[0], targetSignatures[0], reportErrors)) {
|
||||
return Ternary.False;
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
|
||||
let result = Ternary.True;
|
||||
|
@ -6052,6 +6056,32 @@ namespace ts {
|
|||
}
|
||||
return Ternary.True;
|
||||
}
|
||||
|
||||
function constructorRelatedTo(sourceSignature: Signature, targetSignature: Signature, reportErrors: boolean) {
|
||||
if (sourceSignature && targetSignature && sourceSignature.declaration && targetSignature.declaration) {
|
||||
const sourceAccessibility = sourceSignature.declaration.flags & (NodeFlags.Private | NodeFlags.Protected);
|
||||
const targetAccessibility = targetSignature.declaration.flags & (NodeFlags.Private | NodeFlags.Protected);
|
||||
|
||||
const isRelated = sourceAccessibility === targetAccessibility;
|
||||
if (!isRelated && reportErrors) {
|
||||
reportError(Diagnostics.Cannot_assign_a_0_constructor_type_to_a_1_constructor_type, flagsToString(sourceAccessibility), flagsToString(targetAccessibility));
|
||||
}
|
||||
|
||||
return isRelated;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
function flagsToString(flags: NodeFlags) {
|
||||
if (flags === NodeFlags.Private) {
|
||||
return "private";
|
||||
}
|
||||
if (flags === NodeFlags.Protected) {
|
||||
return "protected";
|
||||
}
|
||||
return "public";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return true if the given type is the constructor type for an abstract class
|
||||
|
@ -10103,6 +10133,9 @@ namespace ts {
|
|||
// that the user will not add any.
|
||||
const constructSignatures = getSignaturesOfType(expressionType, SignatureKind.Construct);
|
||||
if (constructSignatures.length) {
|
||||
if (!isConstructorAccessible(node, constructSignatures[0])) {
|
||||
return resolveErrorCall(node);
|
||||
}
|
||||
return resolveCall(node, constructSignatures, candidatesOutArray);
|
||||
}
|
||||
|
||||
|
@ -10123,6 +10156,37 @@ namespace ts {
|
|||
return resolveErrorCall(node);
|
||||
}
|
||||
|
||||
function isConstructorAccessible(node: NewExpression, signature: Signature) {
|
||||
if (!signature || !signature.declaration) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const declaration = signature.declaration;
|
||||
const flags = declaration.flags;
|
||||
|
||||
// Public constructor is accessible.
|
||||
if (!(flags & (NodeFlags.Private | NodeFlags.Protected))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const declaringClass = <InterfaceType>getDeclaredTypeOfSymbol(declaration.parent.symbol);
|
||||
const enclosingClassDeclaration = getContainingClass(node);
|
||||
const enclosingClass = enclosingClassDeclaration ? <InterfaceType>getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingClassDeclaration)) : undefined;
|
||||
|
||||
// A private or protected constructor can only be instantiated within it's own class
|
||||
if (declaringClass !== enclosingClass) {
|
||||
if (flags & NodeFlags.Private) {
|
||||
error(node, Diagnostics.Constructor_of_type_0_is_private_and_only_accessible_within_class_1, signatureToString(signature), typeToString(declaringClass));
|
||||
}
|
||||
if (flags & NodeFlags.Protected) {
|
||||
error(node, Diagnostics.Constructor_of_type_0_is_protected_and_only_accessible_within_class_1, signatureToString(signature), typeToString(declaringClass));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function resolveTaggedTemplateExpression(node: TaggedTemplateExpression, candidatesOutArray: Signature[]): Signature {
|
||||
const tagType = checkExpression(node.tag);
|
||||
const apparentType = getApparentType(tagType);
|
||||
|
@ -12059,7 +12123,7 @@ namespace ts {
|
|||
error(o.name, Diagnostics.Overload_signatures_must_all_be_ambient_or_non_ambient);
|
||||
}
|
||||
else if (deviation & (NodeFlags.Private | NodeFlags.Protected)) {
|
||||
error(o.name, Diagnostics.Overload_signatures_must_all_be_public_private_or_protected);
|
||||
error(o.name || o, Diagnostics.Overload_signatures_must_all_be_public_private_or_protected);
|
||||
}
|
||||
else if (deviation & NodeFlags.Abstract) {
|
||||
error(o.name, Diagnostics.Overload_signatures_must_all_be_abstract_or_not_abstract);
|
||||
|
@ -13928,6 +13992,7 @@ namespace ts {
|
|||
if (baseTypes.length && produceDiagnostics) {
|
||||
const baseType = baseTypes[0];
|
||||
const staticBaseType = getBaseConstructorTypeOfClass(type);
|
||||
checkBaseTypeAccessibility(staticBaseType, baseTypeNode);
|
||||
checkSourceElement(baseTypeNode.expression);
|
||||
if (baseTypeNode.typeArguments) {
|
||||
forEach(baseTypeNode.typeArguments, checkSourceElement);
|
||||
|
@ -13983,6 +14048,16 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
function checkBaseTypeAccessibility(type: ObjectType, node: ExpressionWithTypeArguments) {
|
||||
const signatures = getSignaturesOfType(type, SignatureKind.Construct);
|
||||
if (signatures.length) {
|
||||
const declaration = signatures[0].declaration;
|
||||
if (declaration && declaration.flags & NodeFlags.Private) {
|
||||
error(node, Diagnostics.Cannot_extend_private_class_0, (<Identifier>node.expression).text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getTargetSymbol(s: Symbol) {
|
||||
// if symbol is instantiated its flags are not copied from the 'target'
|
||||
// so we'll need to get back original 'target' symbol to work with correct set of flags
|
||||
|
@ -16348,12 +16423,6 @@ namespace ts {
|
|||
if (flags & NodeFlags.Abstract) {
|
||||
return grammarErrorOnNode(lastStatic, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "abstract");
|
||||
}
|
||||
else if (flags & NodeFlags.Protected) {
|
||||
return grammarErrorOnNode(lastProtected, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "protected");
|
||||
}
|
||||
else if (flags & NodeFlags.Private) {
|
||||
return grammarErrorOnNode(lastPrivate, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "private");
|
||||
}
|
||||
else if (flags & NodeFlags.Async) {
|
||||
return grammarErrorOnNode(lastAsync, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "async");
|
||||
}
|
||||
|
|
|
@ -1823,6 +1823,22 @@
|
|||
"category": "Error",
|
||||
"code": 2671
|
||||
},
|
||||
"Cannot assign a '{0}' constructor type to a '{1}' constructor type.": {
|
||||
"category": "Error",
|
||||
"code": 2672
|
||||
},
|
||||
"Constructor of type '{0}' is private and only accessible within class '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 2673
|
||||
},
|
||||
"Constructor of type '{0}' is protected and only accessible within class '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 2674
|
||||
},
|
||||
"Cannot extend private class '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 2675
|
||||
},
|
||||
"Import declaration '{0}' is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 4000
|
||||
|
|
Loading…
Reference in a new issue