Skip to content

Commit 2c9aa39

Browse files
committed
SONARJAVA-1432 Resolution of default constructor
1 parent b617afc commit 2c9aa39

5 files changed

Lines changed: 46 additions & 8 deletions

File tree

java-checks/src/main/java/org/sonar/java/checks/AbstractClassWithoutAbstractMethodCheck.java

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,34 @@ public void visitNode(Tree tree) {
5454
ClassTree classTree = (ClassTree) tree;
5555
Symbol.TypeSymbol typeSymbol = classTree.symbol();
5656
if (typeSymbol.isAbstract()) {
57-
Collection<Symbol> symbols = typeSymbol.memberSymbols();
58-
int abstractMethod = countAbstractMethods(symbols);
59-
if (isExtendingObject(classTree) && abstractMethod == symbols.size() - 2) {
57+
Collection<Symbol> members = typeSymbol.memberSymbols();
58+
int nbAbstractMethod = countAbstractMethods(members);
59+
// don't count this and super as members
60+
int nbOfMembers = members.size() - 2;
61+
if (hasDefaultConstructor(members)) {
62+
//remove default constructor from members
63+
nbOfMembers -=1;
64+
}
65+
if (isExtendingObject(classTree) && nbAbstractMethod == nbOfMembers) {
6066
// emtpy abstract class or only abstract method
6167
context.addIssue(tree, this, "Convert this \"" + typeSymbol + "\" class to an interface");
6268
}
63-
if (symbols.size() > 2 && abstractMethod == 0 && !isPartialImplementation(classTree)) {
69+
if (nbOfMembers > 0 && nbAbstractMethod == 0 && !isPartialImplementation(classTree)) {
6470
// Not empty abstract class with no abstract method
6571
context.addIssue(tree, this, "Convert this \"" + typeSymbol + "\" class to a concrete class with a private constructor");
6672
}
6773
}
6874
}
6975

76+
private boolean hasDefaultConstructor(Collection<Symbol> members) {
77+
for (Symbol member : members) {
78+
if ("<init>".equals(member.name()) && member.declaration() == null) {
79+
return true;
80+
}
81+
}
82+
return false;
83+
}
84+
7085
private static boolean isExtendingObject(ClassTree tree) {
7186
TypeTree superClass = tree.superClass();
7287
return superClass == null || superClass.symbolType().is("java.lang.Object");

java-checks/src/main/java/org/sonar/java/checks/NoTestInTestClassCheck.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ private void checkClass(ClassTree classTree) {
9595

9696
private void checkTestNGmembers(IdentifierTree className, Iterable<Symbol> members) {
9797
for (Symbol member : members) {
98-
if (member.isMethodSymbol() && member.isPublic() && !member.isStatic()) {
98+
if (member.isMethodSymbol() && member.isPublic() && !member.isStatic() && ((Symbol.MethodSymbol) member).returnType() != null) {
9999
return;
100100
}
101101
}

java-squid/src/main/java/org/sonar/java/resolve/FirstPass.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
package org.sonar.java.resolve;
2121

2222
import com.google.common.base.Preconditions;
23+
import com.google.common.collect.ImmutableList;
2324
import com.google.common.collect.Lists;
2425
import org.sonar.java.ast.api.JavaPunctuator;
2526
import org.sonar.java.model.declaration.ClassTreeImpl;
@@ -255,6 +256,13 @@ public void visitClass(ClassTree tree) {
255256
scan(tree.superClass());
256257
scan(tree.superInterfaces());
257258
scan(tree.members());
259+
//Register default constructor
260+
if(tree.is(Tree.Kind.CLASS) && classEnv.scope.lookup("<init>").isEmpty()) {
261+
JavaSymbol.MethodJavaSymbol defaultConstructor = new JavaSymbol.MethodJavaSymbol(symbol.flags & Flags.ACCESS_FLAGS, "<init>", symbol);
262+
JavaType.MethodJavaType defaultConstructorType = new JavaType.MethodJavaType(ImmutableList.<JavaType>of(), null, ImmutableList.<JavaType>of(), symbol);
263+
defaultConstructor.setMethodType(defaultConstructorType);
264+
classEnv.scope.enter(defaultConstructor);
265+
}
258266
restoreEnvironment(tree);
259267
restoreEnvironment(tree);
260268
}

java-squid/src/test/files/sym/declarations/ConstructorDeclaration.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,13 @@ class ParameterType {
1919
}
2020

2121
ConstructorDeclaration cd = new ConstructorDeclaration(null);
22+
23+
ParameterType pt = new ParameterType();
24+
25+
abstract class Foo {}
26+
class Bar extends Foo {
27+
Bar(int i) {
28+
super();
29+
}
30+
}
2231
}

java-squid/src/test/java/org/sonar/java/resolve/SymbolTableTest.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -404,16 +404,22 @@ public void MethodDeclaration() {
404404
public void ConstructorDeclaration() {
405405
Result result = Result.createFor("declarations/ConstructorDeclaration");
406406

407-
JavaSymbol.MethodJavaSymbol methodSymbol = (JavaSymbol.MethodJavaSymbol) result.symbol("<init>");
407+
JavaSymbol.MethodJavaSymbol methodSymbol = (JavaSymbol.MethodJavaSymbol) result.symbol("<init>", 18);
408408
assertThat(methodSymbol.owner()).isSameAs(result.symbol("ConstructorDeclaration"));
409409
assertThat(methodSymbol.flags()).isEqualTo(0);
410-
assertThat(methodSymbol.getReturnType()).isNull(); // TODO should it be result.symbol("ConstructorDeclaration")?
410+
assertThat(methodSymbol.getReturnType()).isNull();
411411
assertThat(methodSymbol.parameterTypes()).hasSize(1);
412412
assertThat(methodSymbol.thrownTypes()).containsExactly(
413413
result.symbol("FirstExceptionType").type(),
414414
result.symbol("SecondExceptionType").type());
415-
416415
assertThat(result.reference(21, 35)).isEqualTo(methodSymbol);
416+
assertThat(((JavaSymbol.TypeJavaSymbol) methodSymbol.owner()).lookupSymbols("<init>")).as("Constructor with a declared constructor should not have a default one").hasSize(1);
417+
//Default constructor
418+
JavaSymbol defaultConstructor = result.reference(23, 26);
419+
assertThat(defaultConstructor.owner).isSameAs(result.symbol("ParameterType"));
420+
defaultConstructor = result.reference(28, 7);
421+
assertThat(defaultConstructor.isAbstract()).isFalse();
422+
417423
}
418424

419425
@Test

0 commit comments

Comments
 (0)