Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Fixed

- Inaccurate type comparisons between class and interface types, where class-to-class upcasts were
not always preferred over class-to-interface upcasts.

## [1.18.0] - 2025-08-05

### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import org.sonar.plugins.communitydelphi.api.type.Type.PointerType;
import org.sonar.plugins.communitydelphi.api.type.Type.ProceduralType;
import org.sonar.plugins.communitydelphi.api.type.Type.StringType;
import org.sonar.plugins.communitydelphi.api.type.Type.StructType;
import org.sonar.plugins.communitydelphi.api.type.Type.SubrangeType;

final class TypeComparer {
Expand Down Expand Up @@ -780,7 +781,11 @@ private static EqualityType compareParameters(List<Parameter> from, List<Paramet

private static EqualityType compareObject(Type from, Type to) {
if (from.isStruct() && from.isDescendantOf(to)) {
return CONVERT_LEVEL_1;
if (((StructType) from).kind() == ((StructType) to).kind()) {
return CONVERT_LEVEL_1;
} else {
return CONVERT_LEVEL_2;
}
} else if (from.isPointer() && !to.isRecord()) {
PointerType fromPointer = (PointerType) from;
if (fromPointer.isUntypedPointer()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,21 @@ void testInheritedTypes() {
assertResolved(parent, grandparent, child);
}

@Test
void testClassToInterfaceTypes() {
Type grandparent = TypeMocker.struct("Grandparent", CLASS);
Type parent = TypeMocker.struct("Parent", CLASS, grandparent);
Type child = TypeMocker.struct("Child", CLASS, parent);
Type intf = TypeMocker.struct("Intf", INTERFACE);

when(child.ancestorList()).thenReturn(Set.of(parent, intf));
when(child.isDescendantOf(grandparent)).thenReturn(true);
when(child.isDescendantOf(parent)).thenReturn(true);
when(child.isDescendantOf(intf)).thenReturn(true);

assertResolved(child, grandparent, intf);
}

@Test
void testVarParameters() {
Type openArray =
Expand Down