Skip to content

Commit f1c84b3

Browse files
Remove compiler-specific casts from semantic helpers
1 parent c1c6b74 commit f1c84b3

9 files changed

Lines changed: 77 additions & 27 deletions

File tree

‎java-frontend/src/main/java/org/sonar/java/model/JMethodSymbol.java‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,12 @@ IMethodBinding methodBinding() {
7070
return (IMethodBinding) binding;
7171
}
7272

73+
@Override
74+
@Nullable
75+
public Object defaultValue() {
76+
return EcjSymbolMetadata.convertAnnotationValue(sema, methodBinding().getDefaultValue());
77+
}
78+
7379
public boolean isLambda() {
7480
return methodBinding().getDeclaringMember() != null;
7581
}

‎java-frontend/src/main/java/org/sonar/java/model/JType.java‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717
package org.sonar.java.model;
1818

1919
import java.util.Arrays;
20+
import java.util.HashSet;
2021
import java.util.List;
2122
import java.util.Locale;
2223
import java.util.Objects;
24+
import java.util.Set;
2325
import java.util.TreeSet;
2426
import javax.annotation.Nullable;
2527
import org.eclipse.jdt.core.dom.ITypeBinding;
@@ -63,6 +65,19 @@ final class JType implements Type, Type.ArrayType {
6365
this.fullyQualifiedName = fullyQualifiedName(typeBinding);
6466
}
6567

68+
@Override
69+
public Set<Type> directSuperTypes() {
70+
Set<Type> result = new HashSet<>();
71+
ITypeBinding superclass = typeBinding.getSuperclass();
72+
if (superclass != null) {
73+
result.add(sema.type(superclass));
74+
}
75+
Arrays.stream(typeBinding.getInterfaces())
76+
.map(sema::type)
77+
.forEach(result::add);
78+
return result;
79+
}
80+
6681
@Override
6782
public boolean is(String fullyQualifiedName) {
6883
return fullyQualifiedName.equals(this.fullyQualifiedName());

‎java-frontend/src/main/java/org/sonar/java/model/JTypeSymbol.java‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,12 +162,24 @@ public Set<Type> superTypes() {
162162
superTypes = Collections.emptySet();
163163
} else {
164164
superTypes = new HashSet<>();
165-
JUtils.collectSuperTypes(superTypes, sema, typeBinding());
165+
collectSuperTypes(superTypes, sema, typeBinding());
166166
}
167167
}
168168
return superTypes;
169169
}
170170

171+
private void collectSuperTypes(Set<Type> result, JSema sema, ITypeBinding typeBinding) {
172+
ITypeBinding s = typeBinding.getSuperclass();
173+
if (s != null) {
174+
result.add(sema.type(s));
175+
collectSuperTypes(result, sema, s);
176+
}
177+
Arrays.stream(typeBinding.getInterfaces()).forEach(i -> {
178+
result.add(sema.type(i));
179+
collectSuperTypes(result, sema, i);
180+
});
181+
}
182+
171183
@Override
172184
@Nullable
173185
public TypeSymbol outermostClass() {

‎java-frontend/src/main/java/org/sonar/java/model/JUtils.java‎

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
*/
1717
package org.sonar.java.model;
1818

19-
import java.util.Arrays;
2019
import java.util.Collections;
2120
import java.util.HashSet;
2221
import java.util.LinkedHashSet;
@@ -26,7 +25,6 @@
2625
import java.util.Set;
2726
import java.util.stream.Collectors;
2827
import javax.annotation.Nullable;
29-
import org.eclipse.jdt.core.dom.ITypeBinding;
3028
import org.sonar.plugins.java.api.semantic.Symbol;
3129
import org.sonar.plugins.java.api.semantic.SymbolMetadata;
3230
import org.sonar.plugins.java.api.semantic.Type;
@@ -67,19 +65,7 @@ public static Type wrapTypeIfPrimitive(Type type) {
6765
}
6866

6967
public static boolean isIntersectionType(Type type) {
70-
return !type.isUnknown() && ((JType) type).typeBinding.isIntersectionType();
71-
}
72-
73-
public static void collectSuperTypes(Set<Type> result, JSema sema, ITypeBinding typeBinding) {
74-
ITypeBinding s = typeBinding.getSuperclass();
75-
if (s != null) {
76-
result.add(sema.type(s));
77-
collectSuperTypes(result, sema, s);
78-
}
79-
Arrays.stream(typeBinding.getInterfaces()).forEach(i -> {
80-
result.add(sema.type(i));
81-
collectSuperTypes(result, sema, i);
82-
});
68+
return !type.isUnknown() && type.isIntersectionType();
8369
}
8470

8571
public static Symbol getPackage(Symbol symbol) {
@@ -94,7 +80,7 @@ public static Object defaultValue(Symbol.MethodSymbol method) {
9480
if (method.isUnknown()) {
9581
return null;
9682
}
97-
return ((JMethodSymbol) method).methodBinding().getDefaultValue();
83+
return method.defaultValue();
9884
}
9985

10086
/**
@@ -161,16 +147,7 @@ public static Set<Type> directSuperTypes(Type type) {
161147
if (type.isUnknown()) {
162148
return Collections.emptySet();
163149
}
164-
Set<Type> result = new HashSet<>();
165-
JType t = (JType) type;
166-
ITypeBinding superclass = t.typeBinding.getSuperclass();
167-
if (superclass != null) {
168-
result.add(t.sema.type(superclass));
169-
}
170-
Arrays.stream(t.typeBinding.getInterfaces())
171-
.map(t.sema::type)
172-
.forEach(result::add);
173-
return result;
150+
return type.directSuperTypes();
174151
}
175152

176153
@Nullable

‎java-frontend/src/main/java/org/sonar/java/model/Symbols.java‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,11 @@ public boolean isMethodSymbol() {
348348
}
349349

350350
public static final class UnknownType implements Type {
351+
@Override
352+
public Set<Type> directSuperTypes() {
353+
return Collections.emptySet();
354+
}
355+
351356
@Override
352357
public boolean is(String fullyQualifiedName) {
353358
return false;

‎java-frontend/src/main/java/org/sonar/plugins/java/api/semantic/Symbol.java‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,15 @@ interface MethodSymbol extends Symbol {
227227
*/
228228
MethodSymbol UNKNOWN_METHOD = new Symbols.UnknownMethodSymbol();
229229

230+
/**
231+
* Returns the annotation member's default value, or {@code null} when none is available. Values use the
232+
* same representation as {@link SymbolMetadata.AnnotationValue#value()}.
233+
*/
234+
@Nullable
235+
default Object defaultValue() {
236+
return null;
237+
}
238+
230239
/**
231240
* Type of parameters declared by this method.
232241
* In case of generic types of method invocations, this list of types is more specialized than declarationParameters().stream().map(Symbol::type).

‎java-frontend/src/main/java/org/sonar/plugins/java/api/semantic/Type.java‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.sonar.plugins.java.api.semantic;
1818

1919
import java.util.List;
20+
import java.util.Set;
2021
import javax.annotation.Nullable;
2122
import org.sonar.java.model.Symbols;
2223

@@ -30,6 +31,14 @@ public interface Type {
3031
*/
3132
Type UNKNOWN = new Symbols.UnknownType();
3233

34+
/**
35+
* Returns the immediate superclass and interfaces, preserving generic substitutions. Unknown types have
36+
* no direct supertypes. Interfaces do not acquire an implicit {@code java.lang.Object} superclass.
37+
*/
38+
default Set<Type> directSuperTypes() {
39+
return java.util.Collections.emptySet();
40+
}
41+
3342
/**
3443
* Primitive java types.
3544
*/

‎java-frontend/src/test/java/org/sonar/java/model/JUtilsTest.java‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,28 @@
3737
import org.sonar.plugins.java.api.tree.TypeParameterTree;
3838

3939
import static org.assertj.core.api.Assertions.assertThat;
40+
import static org.mockito.Mockito.mock;
41+
import static org.mockito.Mockito.when;
4042

4143
class JUtilsTest {
4244

4345
static final JSema SEMA = test("").sema;
4446
private static final Type OBJECT_TYPE = SEMA.type(SEMA.resolveType("java.lang.Object"));
4547

48+
@Test
49+
void semantic_helpers_use_the_existing_api_interfaces() {
50+
Type type = mock(Type.class);
51+
Type parent = mock(Type.class);
52+
when(type.directSuperTypes()).thenReturn(Set.of(parent));
53+
assertThat(JUtils.directSuperTypes(type)).containsExactly(parent);
54+
Symbol.MethodSymbol method = mock(Symbol.MethodSymbol.class);
55+
when(method.defaultValue()).thenReturn(42);
56+
assertThat(JUtils.defaultValue(method)).isEqualTo(42);
57+
assertThat(Type.UNKNOWN.directSuperTypes()).isEmpty();
58+
assertThat(Symbol.MethodSymbol.UNKNOWN_METHOD.defaultValue()).isNull();
59+
assertThat(new JInitializerBlockSymbol(Symbol.TypeSymbol.UNKNOWN_TYPE, false).defaultValue()).isNull();
60+
}
61+
4662
@Nested
4763
class PrimitiveType {
4864
@Test

‎java-frontend/src/test/java/org/sonar/java/model/SymbolsTest.java‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ void unknown_type() {
4343
Type unknownType = Type.UNKNOWN;
4444

4545
assertThat(unknownType.isUnknown()).isTrue();
46+
assertThat(unknownType.directSuperTypes()).isEmpty();
4647
assertThat(unknownType).isEqualTo(Type.UNKNOWN);
4748

4849
assertThat(unknownType.is("!Unknown!")).isFalse();

0 commit comments

Comments
 (0)