diff --git a/packages/jsii/lib/validator.ts b/packages/jsii/lib/validator.ts index 6f5aebcc1a..aedaa7d771 100644 --- a/packages/jsii/lib/validator.ts +++ b/packages/jsii/lib/validator.ts @@ -392,6 +392,14 @@ function _defaultValidations(): ValidationFunction[] { label: string, action: string, ) { + if (!!expected.protected !== !!actual.protected) { + const expVisibility = expected.protected ? 'protected' : 'public'; + const actVisibility = actual.protected ? 'protected' : 'public'; + diagnostic( + ts.DiagnosticCategory.Error, + `${label} changes visibility when ${action} (expected ${expVisibility}, found ${actVisibility})`, + ); + } if (!deepEqual(actual.returns, expected.returns)) { const expType = spec.describeTypeReference(expected.returns?.type); const actType = spec.describeTypeReference(actual.returns?.type); @@ -446,6 +454,14 @@ function _defaultValidations(): ValidationFunction[] { label: string, action: string, ) { + if (!!expected.protected !== !!actual.protected) { + const expVisibility = expected.protected ? 'protected' : 'public'; + const actVisibility = actual.protected ? 'protected' : 'public'; + diagnostic( + ts.DiagnosticCategory.Error, + `${label} changes visibility when ${action} (expected ${expVisibility}, found ${actVisibility})`, + ); + } if (!deepEqual(expected.type, actual.type)) { const expType = spec.describeTypeReference(expected.type); const actType = spec.describeTypeReference(actual.type); diff --git a/packages/jsii/test/__snapshots__/negatives.test.js.snap b/packages/jsii/test/__snapshots__/negatives.test.js.snap index d42c6919fc..d9b1f709a2 100644 --- a/packages/jsii/test/__snapshots__/negatives.test.js.snap +++ b/packages/jsii/test/__snapshots__/negatives.test.js.snap @@ -436,6 +436,12 @@ exports[`omit.4 1`] = ` " `; +exports[`override-changes-visibility 1`] = ` +"error TS0: jsii.ChildClass#method changes visibility when overriding jsii.BaseClass (expected protected, found public) +error TS0: jsii.ChildClass#property changes visibility when overriding jsii.BaseClass (expected protected, found public) +" +`; + exports[`prohibited-member-name 1`] = ` "neg.prohibited-member-name.ts:4:3 - error TS9999: JSII: Prohibited member name: equals diff --git a/packages/jsii/test/negatives/neg.override-changes-visibility.ts b/packages/jsii/test/negatives/neg.override-changes-visibility.ts new file mode 100644 index 0000000000..92f096defd --- /dev/null +++ b/packages/jsii/test/negatives/neg.override-changes-visibility.ts @@ -0,0 +1,20 @@ +// Note: not testing "public -> protected" because this is invalid TypeScript, +// so the type checker will already have caught it for us. + +export class BaseClass { + protected readonly property?: string; + + protected method() { + return; + } +} + +export class ChildClass extends BaseClass { + // This property cannot be public as it overrides the one on BaseClass which is protected + public readonly property?: string; + + // This method cannot be public as it overrides the one on BaseClass which is protected + public method() { + throw new Error('Not Implemented'); + } +}