diff --git a/common/changes/@itwin/ecschema-editing/remove-ecrule-102_2023-04-05-12-44.json b/common/changes/@itwin/ecschema-editing/remove-ecrule-102_2023-04-05-12-44.json new file mode 100644 index 000000000000..e85ccb56ec5b --- /dev/null +++ b/common/changes/@itwin/ecschema-editing/remove-ecrule-102_2023-04-05-12-44.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/ecschema-editing", + "comment": "Removed obsolete EC rule 102 - Abstract class must have abstract base class.", + "type": "none" + } + ], + "packageName": "@itwin/ecschema-editing" +} \ No newline at end of file diff --git a/core/ecschema-editing/src/Validation/ECRules.ts b/core/ecschema-editing/src/Validation/ECRules.ts index f7c7e0ac2a3f..1194a2057128 100644 --- a/core/ecschema-editing/src/Validation/ECRules.ts +++ b/core/ecschema-editing/src/Validation/ECRules.ts @@ -58,6 +58,7 @@ export const DiagnosticCodes = { // Class Rule Codes (100-199) BaseClassIsSealed: getCode(100), BaseClassOfDifferentType: getCode(101), + // EC-102 has been deprecated. Leaving the code here to prevent re-use. AbstractClassWithNonAbstractBase: getCode(102), // CA Container Rule Codes (500-599) @@ -111,7 +112,7 @@ export const Diagnostics = { BaseClassIsOfDifferentType: createClassDiagnosticClass<[string, string, string]>(DiagnosticCodes.BaseClassOfDifferentType, "Class '{0}' cannot derive from base class '{1}' of type '{2}'."), - /** EC-102: Required message parameters: childClass.FullName, baseClass.FullName */ + /** **DEPRECATED** EC-102: Required message parameters: childClass.FullName, baseClass.FullName */ AbstractClassWithNonAbstractBase: createClassDiagnosticClass<[string, string]>(DiagnosticCodes.AbstractClassWithNonAbstractBase, "Abstract Class '{0}' cannot derive from base class '{1}' because it is not an abstract class."), @@ -197,7 +198,6 @@ export const ECRuleSet: IRuleSet = { classRules: [ baseClassIsSealed, baseClassIsOfDifferentType, - abstractClassWithNonAbstractBase, ], propertyRules: [ incompatibleValueTypePropertyOverride, @@ -298,22 +298,6 @@ export async function* baseClassIsOfDifferentType(ecClass: AnyClass): AsyncItera yield new Diagnostics.BaseClassIsOfDifferentType(ecClass, [ecClass.fullName, baseClass.fullName, itemType]); } -/** - * EC Rule: Abstract class cannot derive from a non-abstract base class. - * @internal - */ -export async function* abstractClassWithNonAbstractBase(ecClass: AnyClass): AsyncIterable> { - if (ecClass.modifier !== ECClassModifier.Abstract || !ecClass.baseClass) - return; - - const baseClass = await ecClass.baseClass; - // return if rule passed - if (baseClass.modifier === ECClassModifier.Abstract) - return; - - yield new Diagnostics.AbstractClassWithNonAbstractBase(ecClass, [ecClass.fullName, baseClass.fullName]); -} - /** * EC Rule: When overriding a class primitive property, the child and base property must be of the same type (string, number, etc...). * @internal diff --git a/core/ecschema-editing/src/test/Validation/ECRules/ClassRules.test.ts b/core/ecschema-editing/src/test/Validation/ECRules/ClassRules.test.ts index b436988147dd..8fdeacc5ad9b 100644 --- a/core/ecschema-editing/src/test/Validation/ECRules/ClassRules.test.ts +++ b/core/ecschema-editing/src/test/Validation/ECRules/ClassRules.test.ts @@ -98,73 +98,4 @@ describe("ClassRule tests", () => { expect(false, "Rule should have passed").to.be.true; } }); - - it("AbstractClassWithNonAbstractBase, base class is sealed, rule violated.", async () => { - const baseClass = new EntityClass(schema, "TestBase", ECClassModifier.Sealed); - const entityClass = new EntityClass(schema, "TestClass", ECClassModifier.Abstract); - entityClass.baseClass = new DelayedPromiseWithProps(baseClass.key, async () => baseClass); - - const result = Rules.abstractClassWithNonAbstractBase(entityClass); - expect(result).not.undefined; - let resultHasEntries = false; - for await (const diagnostic of result) { - resultHasEntries = true; - expect(diagnostic.ecDefinition).to.equal(entityClass); - expect(diagnostic.messageArgs).to.eql([entityClass.fullName, baseClass.fullName]); - expect(diagnostic.category).to.equal(DiagnosticCategory.Error); - expect(diagnostic.code).to.equal(Rules.DiagnosticCodes.AbstractClassWithNonAbstractBase); - expect(diagnostic.diagnosticType).to.equal(DiagnosticType.SchemaItem); - } - expect(resultHasEntries, "expected rule to return an AsyncIterable with entries.").to.be.true; - }); - - it("AbstractClassWithNonAbstractBase, base class modifier is `none`, rule violated.", async () => { - const baseClass = new EntityClass(schema, "TestBase", ECClassModifier.None); - const entityClass = new EntityClass(schema, "TestClass", ECClassModifier.Abstract); - entityClass.baseClass = new DelayedPromiseWithProps(baseClass.key, async () => baseClass); - - const result = Rules.abstractClassWithNonAbstractBase(entityClass); - expect(result).not.undefined; - let resultHasEntries = false; - for await (const diagnostic of result) { - resultHasEntries = true; - expect(diagnostic.ecDefinition).to.equal(entityClass); - expect(diagnostic.messageArgs).to.eql([entityClass.fullName, baseClass.fullName]); - expect(diagnostic.category).to.equal(DiagnosticCategory.Error); - expect(diagnostic.code).to.equal(Rules.DiagnosticCodes.AbstractClassWithNonAbstractBase); - expect(diagnostic.diagnosticType).to.equal(DiagnosticType.SchemaItem); - } - expect(resultHasEntries, "expected rule to return an AsyncIterable with entries.").to.be.true; - }); - - it("AbstractClassWithNonAbstractBase, no base class, rule passes.", async () => { - const entityClass = new EntityClass(schema, "TestClass", ECClassModifier.Abstract); - - const result = Rules.abstractClassWithNonAbstractBase(entityClass); - for await (const _diagnostic of result) { - expect(false, "Rule should have passed").to.be.true; - } - }); - - it("AbstractClassWithNonAbstractBase, base class is abstract, rule passes.", async () => { - const baseClass = new EntityClass(schema, "TestBase", ECClassModifier.Abstract); - const entityClass = new EntityClass(schema, "TestClass", ECClassModifier.Abstract); - entityClass.baseClass = new DelayedPromiseWithProps(baseClass.key, async () => baseClass); - - const result = Rules.abstractClassWithNonAbstractBase(entityClass); - for await (const _diagnostic of result) { - expect(false, "Rule should have passed").to.be.true; - } - }); - - it("AbstractClassWithNonAbstractBase, class is not abstract, rule passes.", async () => { - const baseClass = new EntityClass(schema, "TestBase", ECClassModifier.Sealed); - const entityClass = new EntityClass(schema, "TestClass", ECClassModifier.None); - entityClass.baseClass = new DelayedPromiseWithProps(baseClass.key, async () => baseClass); - - const result = Rules.abstractClassWithNonAbstractBase(entityClass); - for await (const _diagnostic of result) { - expect(false, "Rule should have passed").to.be.true; - } - }); });