Skip to content

Commit 23b340e

Browse files
authored
feat: info if overriding member is not needed (#759)
Closes #25 ### Summary of Changes Show an info if an overriding member is identical to the overridden one. In this case, it can be removed.
1 parent a698a6a commit 23b340e

File tree

4 files changed

+97
-55
lines changed

4 files changed

+97
-55
lines changed

packages/safe-ds-lang/src/language/validation/inheritance.ts

+10-3
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ import { ClassType, UnknownType } from '../typing/model.js';
77

88
export const CODE_INHERITANCE_CYCLE = 'inheritance/cycle';
99
export const CODE_INHERITANCE_MULTIPLE_INHERITANCE = 'inheritance/multiple-inheritance';
10-
export const CODE_INHERITANCE_MUST_MATCH_OVERRIDDEN_MEMBER = 'inheritance/must-match-overridden-member';
10+
export const CODE_INHERITANCE_IDENTICAL_TO_OVERRIDDEN_MEMBER = 'inheritance/identical-to-overridden-member';
11+
export const CODE_INHERITANCE_INCOMPATIBLE_TO_OVERRIDDEN_MEMBER = 'inheritance/incompatible-to-overridden-member';
1112
export const CODE_INHERITANCE_NOT_A_CLASS = 'inheritance/not-a-class';
1213

13-
export const classMemberMustMatchOverriddenMember = (services: SafeDsServices) => {
14+
export const classMemberMustMatchOverriddenMemberAndShouldBeNeeded = (services: SafeDsServices) => {
1415
const classHierarchy = services.types.ClassHierarchy;
1516
const typeChecker = services.types.TypeChecker;
1617
const typeComputer = services.types.TypeComputer;
@@ -35,9 +36,15 @@ export const classMemberMustMatchOverriddenMember = (services: SafeDsServices) =
3536
{
3637
node,
3738
property: 'name',
38-
code: CODE_INHERITANCE_MUST_MATCH_OVERRIDDEN_MEMBER,
39+
code: CODE_INHERITANCE_INCOMPATIBLE_TO_OVERRIDDEN_MEMBER,
3940
},
4041
);
42+
} else if (typeChecker.isAssignableTo(overriddenMemberType, ownMemberType)) {
43+
accept('info', 'Overriding member is identical to overridden member and can be removed.', {
44+
node,
45+
property: 'name',
46+
code: CODE_INHERITANCE_IDENTICAL_TO_OVERRIDDEN_MEMBER,
47+
});
4148
}
4249
};
4350
};

packages/safe-ds-lang/src/language/validation/safe-ds-validator.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import {
3636
unionTypesShouldBeUsedWithCaution,
3737
} from './experimentalLanguageFeatures.js';
3838
import {
39-
classMemberMustMatchOverriddenMember,
39+
classMemberMustMatchOverriddenMemberAndShouldBeNeeded,
4040
classMustNotInheritItself,
4141
classMustOnlyInheritASingleClass,
4242
} from './inheritance.js';
@@ -228,7 +228,7 @@ export const registerValidationChecks = function (services: SafeDsServices) {
228228
classMustNotInheritItself(services),
229229
],
230230
SdsClassBody: [classBodyShouldNotBeEmpty],
231-
SdsClassMember: [classMemberMustMatchOverriddenMember(services)],
231+
SdsClassMember: [classMemberMustMatchOverriddenMemberAndShouldBeNeeded(services)],
232232
SdsConstraintList: [constraintListsShouldBeUsedWithCaution, constraintListShouldNotBeEmpty],
233233
SdsDeclaration: [
234234
nameMustNotStartWithCodegenPrefix,
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,55 @@
11
package tests.validation.inheritance.overridingMethodMustMatchOverriddenMethod
22

33
class MySuperClass {
4-
attr myInstanceAttribute: Int
5-
static attr myStaticAttribute: Int
4+
attr myInstanceAttribute: Number
5+
static attr myStaticAttribute: Number
66

7-
fun myInstanceMethod(a: Int = 0) -> r: Int
8-
static fun myStaticMethod(a: Int = 0) -> r: Int
7+
fun myInstanceMethod(a: Number = 0) -> r: Number
8+
static fun myStaticMethod(a: Number = 0) -> r: Number
99
}
1010

1111
class MyClass1 sub MySuperClass {
12-
// $TEST$ no error r"Overriding member does not match the overridden member:[\s\S]*"
12+
// $TEST$ no error r"Overriding member does not match the overridden member:.*"
1313
attr »myInstanceAttribute«: Int
14-
// $TEST$ no error r"Overriding member does not match the overridden member:[\s\S]*"
14+
// $TEST$ no error r"Overriding member does not match the overridden member:.*"
1515
static attr »myStaticAttribute«: Int
1616

17-
// $TEST$ no error r"Overriding member does not match the overridden member:[\s\S]*"
18-
attr »myInstanceAttribute«: String
19-
// $TEST$ no error r"Overriding member does not match the overridden member:[\s\S]*"
20-
static attr »myStaticAttribute«: String
17+
// $TEST$ no error r"Overriding member does not match the overridden member:.*"
18+
attr »myInstanceAttribute«: Any
19+
// $TEST$ no error r"Overriding member does not match the overridden member:.*"
20+
static attr »myStaticAttribute«: Any
2121

22-
// $TEST$ no error r"Overriding member does not match the overridden member:[\s\S]*"
22+
// $TEST$ no error r"Overriding member does not match the overridden member:.*"
2323
attr »myOwnInstanceAttribute«: Int
24-
// $TEST$ no error r"Overriding member does not match the overridden member:[\s\S]*"
24+
// $TEST$ no error r"Overriding member does not match the overridden member:.*"
2525
static attr »myOwnStaticAttribute«: Int
2626

2727

28-
// $TEST$ no error r"Overriding member does not match the overridden member:[\s\S]*"
29-
fun »myInstanceMethod«(a: Int = 0) -> r: Int
30-
// $TEST$ no error r"Overriding member does not match the overridden member:[\s\S]*"
31-
static fun »myStaticMethod«(a: Int = 0) -> r: Int
28+
// $TEST$ no error r"Overriding member does not match the overridden member:.*"
29+
fun »myInstanceMethod«(a: Any = 0) -> r: Int
30+
// $TEST$ no error r"Overriding member does not match the overridden member:.*"
31+
static fun »myStaticMethod«(a: Any = 0) -> r: Int
3232

33-
// $TEST$ no error r"Overriding member does not match the overridden member:[\s\S]*"
33+
// $TEST$ no error r"Overriding member does not match the overridden member:.*"
3434
fun »myInstanceMethod«() -> r: Int
35-
// $TEST$ no error r"Overriding member does not match the overridden member:[\s\S]*"
35+
// $TEST$ no error r"Overriding member does not match the overridden member:.*"
3636
static fun »myStaticMethod«() -> r: Int
3737

38-
// $TEST$ no error r"Overriding member does not match the overridden member:[\s\S]*"
39-
fun »myOwnInstanceMethod«(a: Int = 0) -> r: Int
40-
// $TEST$ no error r"Overriding member does not match the overridden member:[\s\S]*"
41-
static fun »myOwnStaticMethod«(a: Int = 0) -> r: Int
38+
// $TEST$ no error r"Overriding member does not match the overridden member:.*"
39+
fun »myOwnInstanceMethod«(a: Any = 0) -> r: Int
40+
// $TEST$ no error r"Overriding member does not match the overridden member:.*"
41+
static fun »myOwnStaticMethod«(a: Any = 0) -> r: Int
4242
}
4343

4444
class MyClass2 sub MySuperClass {
45-
// $TEST$ error r"Overriding member does not match the overridden member:[\s\S]*"
46-
attr »myInstanceAttribute«: String
47-
// $TEST$ no error r"Overriding member does not match the overridden member:[\s\S]*"
48-
static attr »myStaticAttribute«: String
45+
// $TEST$ error r"Overriding member does not match the overridden member:.*"
46+
attr »myInstanceAttribute«: Any
47+
// $TEST$ no error r"Overriding member does not match the overridden member:.*"
48+
static attr »myStaticAttribute«: Any
4949

50-
// $TEST$ no error r"Overriding member does not match the overridden member:[\s\S]*"
51-
attr »myInstanceAttribute«: Int
52-
// $TEST$ no error r"Overriding member does not match the overridden member:[\s\S]*"
53-
static attr »myStaticAttribute«: Int
54-
55-
// $TEST$ no error r"Overriding member does not match the overridden member:[\s\S]*"
56-
attr »myOwnInstanceAttribute«: Int
57-
// $TEST$ no error r"Overriding member does not match the overridden member:[\s\S]*"
58-
static attr »myOwnStaticAttribute«: Int
59-
60-
61-
// $TEST$ error r"Overriding member does not match the overridden member:[\s\S]*"
62-
fun »myInstanceMethod«() -> r: Int
63-
// $TEST$ no error r"Overriding member does not match the overridden member:[\s\S]*"
64-
static fun »myStaticMethod«() -> r: Int
65-
66-
// $TEST$ no error r"Overriding member does not match the overridden member:[\s\S]*"
67-
fun »myInstanceMethod«(a: Int = 0) -> r: Int
68-
// $TEST$ no error r"Overriding member does not match the overridden member:[\s\S]*"
69-
static fun »myStaticMethod«(a: Int = 0) -> r: Int
7050

71-
// $TEST$ no error r"Overriding member does not match the overridden member:[\s\S]*"
72-
fun »myOwnInstanceMethod«(a: Int = 0) -> r: Int
73-
// $TEST$ no error r"Overriding member does not match the overridden member:[\s\S]*"
74-
static fun »myOwnStaticMethod«(a: Int = 0) -> r: Int
51+
// $TEST$ error r"Overriding member does not match the overridden member:.*"
52+
fun »myInstanceMethod«(a: Number = 0) -> r: Any
53+
// $TEST$ no error r"Overriding member does not match the overridden member:.*"
54+
static fun »myStaticMethod«(a: Number = 0) -> r: Any
7555
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package tests.validation.inheritance.overridingMethodShouldDifferFromOverriddenMethod
2+
3+
class MySuperClass {
4+
attr myInstanceAttribute: Number
5+
static attr myStaticAttribute: Number
6+
7+
fun myInstanceMethod(a: Number = 0) -> r: Number
8+
static fun myStaticMethod(a: Number = 0) -> r: Number
9+
}
10+
11+
class MyClass1 sub MySuperClass {
12+
// $TEST$ info "Overriding member is identical to overridden member and can be removed."
13+
attr »myInstanceAttribute«: Number
14+
// $TEST$ no info "Overriding member is identical to overridden member and can be removed."
15+
static attr »myStaticAttribute«: Number
16+
17+
// $TEST$ no info "Overriding member is identical to overridden member and can be removed."
18+
attr »myInstanceAttribute«: Number
19+
// $TEST$ no info "Overriding member is identical to overridden member and can be removed."
20+
static attr »myStaticAttribute«: Number
21+
22+
// $TEST$ no info "Overriding member is identical to overridden member and can be removed."
23+
attr »myOwnInstanceAttribute«: Number
24+
// $TEST$ no info "Overriding member is identical to overridden member and can be removed."
25+
static attr »myOwnStaticAttribute«: Number
26+
27+
28+
// $TEST$ info "Overriding member is identical to overridden member and can be removed."
29+
fun »myInstanceMethod«(a: Number = 0) -> r: Number
30+
// $TEST$ no info "Overriding member is identical to overridden member and can be removed."
31+
static fun »myStaticMethod«(a: Number = 0) -> r: Number
32+
33+
// $TEST$ no info "Overriding member is identical to overridden member and can be removed."
34+
fun »myInstanceMethod«() -> r: Number
35+
// $TEST$ no info "Overriding member is identical to overridden member and can be removed."
36+
static fun »myStaticMethod«() -> r: Number
37+
38+
// $TEST$ no info "Overriding member is identical to overridden member and can be removed."
39+
fun »myOwnInstanceMethod«(a: Number = 0) -> r: Number
40+
// $TEST$ no info "Overriding member is identical to overridden member and can be removed."
41+
static fun »myOwnStaticMethod«(a: Number = 0) -> r: Number
42+
}
43+
44+
class MyClass2 sub MySuperClass {
45+
// $TEST$ no info "Overriding member is identical to overridden member and can be removed."
46+
attr »myInstanceAttribute«: Int
47+
// $TEST$ no info "Overriding member is identical to overridden member and can be removed."
48+
static attr »myStaticAttribute«: Int
49+
50+
51+
// $TEST$ no info "Overriding member is identical to overridden member and can be removed."
52+
fun »myInstanceMethod«(a: Number = 0) -> r: Int
53+
// $TEST$ no info "Overriding member is identical to overridden member and can be removed."
54+
static fun »myStaticMethod«(a: Number = 0) -> r: Int
55+
}

0 commit comments

Comments
 (0)