Skip to content

Commit

Permalink
SONARJAVA-4700 Update API with methods from JUtils (#4559)
Browse files Browse the repository at this point in the history
  • Loading branch information
leonardo-pilastri-sonarsource authored Nov 22, 2023
1 parent ec579c8 commit f8601c3
Show file tree
Hide file tree
Showing 28 changed files with 228 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ private static boolean hasSingleAbstractMethodInHierarchy(Set<Type> superTypes)
// remove objects methods redefined in interfaces
.filter(symbol -> !isObjectMethod(symbol))
// remove generic methods, which can not be written as lambda (JLS-11 §15.27)
.filter(symbol -> !JUtils.isParametrizedMethod(symbol))
.filter(symbol -> !symbol.isParametrizedMethod())
// always take same symbol if method is redeclared over and over in hierarchy
.map(AnonymousClassShouldBeLambdaCheck::overridenSymbolIfAny)
.collect(Collectors.toSet())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

import org.sonar.check.Rule;
import org.sonar.java.model.ExpressionUtils;
import org.sonar.java.model.JUtils;
import org.sonar.java.model.LiteralUtils;
import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.semantic.Symbol;
Expand Down Expand Up @@ -98,7 +97,7 @@ private void reportIssueForSameType(Symbol.MethodSymbol methodSymbol, NewArrayTr
private static boolean isLastArgumentVarargs(Symbol.MethodSymbol methodSymbol, Arguments args) {
// If we have less arguments than parameter types, it means that no arguments was pass to the varargs.
// If we have more, the last argument can not be an array.
return !args.isEmpty() && JUtils.isVarArgsMethod(methodSymbol) && args.size() == methodSymbol.parameterTypes().size();
return !args.isEmpty() && methodSymbol.isVarArgsMethod() && args.size() == methodSymbol.parameterTypes().size();
}

private static Type getLastParameterType(List<? extends Type> list) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import javax.annotation.Nullable;
import org.sonar.check.Rule;
import org.sonar.java.model.ExpressionUtils;
import org.sonar.java.model.JUtils;
import org.sonar.java.model.JavaTree;
import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.JavaFileScannerContext;
Expand Down Expand Up @@ -96,7 +95,7 @@ public void visitMethodInvocation(MethodInvocationTree tree) {
String name = ExpressionUtils.methodName(tree).name();
unknownInvocations.computeIfAbsent(name, k -> new HashSet<>()).add(tree);
} else if (isPrivateMethodOfOuterClass(symbol) && isInvocationOnCurrentInstance(tree)) {
if (JUtils.isParametrizedMethod(symbol) && symbol.declaration() != null) {
if (symbol.isParametrizedMethod() && symbol.declaration() != null) {
// generic methods requires to use their declaration symbol rather than the parameterized one
symbol = symbol.declaration().symbol();
}
Expand Down Expand Up @@ -139,7 +138,7 @@ private boolean hasSameArity(Symbol.MethodSymbol methodUsed, MethodInvocationTre
int formalArity = methodUsed.parameterTypes().size();
int invokedArity = mit.arguments().size();
return formalArity == invokedArity ||
(JUtils.isVarArgsMethod(methodUsed) && invokedArity >= formalArity - 1);
(methodUsed.isVarArgsMethod() && invokedArity >= formalArity - 1);
}

private void reportIssueOnMethod(@Nullable MethodTree declaration, Symbol.TypeSymbol classSymbol) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ private static String typeNameWithParameters(Type type) {
private static boolean isCallToParametrizedOrUnknownMethod(ExpressionTree expressionTree) {
if (expressionTree.is(Tree.Kind.METHOD_INVOCATION)) {
Symbol.MethodSymbol symbol = ((MethodInvocationTree) expressionTree).methodSymbol();
return symbol.isUnknown() || JUtils.isParametrizedMethod(symbol);
return symbol.isUnknown() || symbol.isParametrizedMethod();
}
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public void visitNode(Tree tree) {
}

private void checkConfusingVararg(Symbol.MethodSymbol method, Arguments arguments) {
if (!JUtils.isVarArgsMethod(method)) {
if (!method.isVarArgsMethod()) {
return;
}
List<Type> parameterTypes = method.parameterTypes();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public void visitMethodInvocation(MethodInvocationTree tree) {
}
if (isInvocationOnSelf) {
Symbol symbol = methodIdentifier.symbol();
if (symbol.isMethodSymbol() && JUtils.isOverridable((Symbol.MethodSymbol) symbol) && isMethodDefinedOnConstructedType(symbol)) {
if (symbol.isMethodSymbol() && ((Symbol.MethodSymbol) symbol).isOverridable() && isMethodDefinedOnConstructedType(symbol)) {
reportIssue(methodIdentifier, "Remove this call from a constructor to the overridable \"" + methodIdentifier.name() + "\" method.");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import org.sonar.plugins.java.api.JavaVersionAwareVisitor;
import org.sonar.java.ast.visitors.SubscriptionVisitor;
import org.sonar.java.checks.helpers.QuickFixHelper;
import org.sonar.java.model.JUtils;
import org.sonar.java.model.JavaTree;
import org.sonar.java.reporting.JavaQuickFix;
import org.sonar.java.reporting.JavaTextEdit;
Expand Down Expand Up @@ -132,7 +131,7 @@ private static boolean usedAsArgumentWithoutDiamond(NewClassTree newClassTree) {
return false;
}

if (JUtils.isParametrizedMethod(methodSymbol)) {
if (methodSymbol.isParametrizedMethod()) {
// killing the noise - might be required for inference on nested method calls
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ private static boolean differentContract(Symbol.MethodSymbol method, Symbol.Meth
}

private static boolean removingParametrizedAspect(Symbol.MethodSymbol method, Symbol.MethodSymbol overridee) {
return !JUtils.isParametrizedMethod(method) && JUtils.isParametrizedMethod(overridee);
return !method.isParametrizedMethod() && overridee.isParametrizedMethod();
}

private static boolean differentThrows(Symbol.MethodSymbol method, Symbol.MethodSymbol overridee) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public void visitNode(Tree tree) {

private void checkMethodThrownList(MethodTree methodTree, ListTree<TypeTree> thrownList) {
Set<Type> thrownExceptions = thrownExceptionsFromBody(methodTree);
boolean isOverridableMethod = JUtils.isOverridable(methodTree.symbol());
boolean isOverridableMethod = methodTree.symbol().isOverridable();
Set<String> undocumentedExceptionNames = new Javadoc(methodTree).undocumentedThrownExceptions();
Set<String> reported = new HashSet<>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

import java.util.Collections;
import org.sonar.check.Rule;
import org.sonar.java.model.JUtils;
import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.JavaFileScannerContext;
import org.sonar.plugins.java.api.semantic.Symbol;
Expand Down Expand Up @@ -50,7 +49,7 @@ public void visitNode(Tree tree) {
return;
}
Symbol.MethodSymbol overriddenSymbol = overriddenSymbols.get(0);
if (JUtils.isSynchronizedMethod(overriddenSymbol) && !JUtils.isSynchronizedMethod(methodSymbol)) {
if (overriddenSymbol.isSynchronizedMethod() && !methodSymbol.isSynchronizedMethod()) {
List<JavaFileScannerContext.Location> secondaries = Collections.emptyList();
MethodTree overridenMethodTree = overriddenSymbol.declaration();
if (overridenMethodTree != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
package org.sonar.java.checks;

import org.sonar.check.Rule;
import org.sonar.java.model.JUtils;
import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.semantic.Symbol;
import org.sonar.plugins.java.api.semantic.Type;
Expand Down Expand Up @@ -67,7 +66,7 @@ private void checkArgumentsTypes(List<ExpressionTree> arguments, Symbol.MethodSy
for (int index = 0; index < arguments.size(); index++) {
ExpressionTree argument = arguments.get(index);
Type providedType = argument.symbolType();
if (!argument.is(Tree.Kind.NULL_LITERAL) && isThreadAsRunnable(providedType, parametersTypes, index, JUtils.isVarArgsMethod(methodSymbol))) {
if (!argument.is(Tree.Kind.NULL_LITERAL) && isThreadAsRunnable(providedType, parametersTypes, index, methodSymbol.isVarArgsMethod())) {
reportIssue(argument, getMessage(argument, providedType, index));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public void visitNode(Tree tree) {
private static boolean isExcludedInitializer(ExpressionTree initializer) {
if (initializer.is(Tree.Kind.METHOD_INVOCATION)) {
Symbol.MethodSymbol symbol = ((MethodInvocationTree) initializer).methodSymbol();
return !symbol.isUnknown() && JUtils.isParametrizedMethod(symbol);
return !symbol.isUnknown() && symbol.isParametrizedMethod();
}
return initializer.is(Tree.Kind.CONDITIONAL_EXPRESSION, Tree.Kind.METHOD_REFERENCE, Tree.Kind.LAMBDA_EXPRESSION);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import org.apache.commons.lang3.StringUtils;
import org.sonar.check.Rule;
import org.sonar.check.RuleProperty;
import org.sonar.java.model.JUtils;
import org.sonar.java.model.ModifiersUtils;
import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.semantic.Symbol;
Expand Down Expand Up @@ -226,7 +225,7 @@ private static Stream<Symbol> getAllMembers(Symbol.TypeSymbol symbol, boolean is
}
Stream<Symbol> defaultMethodsFromInterfaces = symbol.interfaces().stream()
.flatMap(i -> getAllMembers(i.symbol(), false, visitedSymbols))
.filter(m -> m.isMethodSymbol() && JUtils.isDefaultMethod((Symbol.MethodSymbol) m));
.filter(m -> m.isMethodSymbol() && ((Symbol.MethodSymbol) m).isDefaultMethod());
members = Stream.concat(members, defaultMethodsFromInterfaces);
for (Symbol s : symbol.memberSymbols()) {
if (isNested(s) || isPublicStaticConcrete(s)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import org.sonar.java.checks.helpers.MethodTreeUtils;
import org.sonar.java.checks.helpers.QuickFixHelper;
import org.sonar.java.checks.helpers.UnresolvedIdentifiersVisitor;
import org.sonar.java.model.JUtils;
import org.sonar.java.model.ModifiersUtils;
import org.sonar.java.reporting.AnalyzerMessage;
import org.sonar.java.reporting.JavaQuickFix;
Expand Down Expand Up @@ -89,7 +88,7 @@ public void visitNode(Tree tree) {
return;
}
Set<String> undocumentedParameters = new HashSet<>(new Javadoc(methodTree).undocumentedParameters());
boolean overridableMethod = JUtils.isOverridable(methodTree.symbol());
boolean overridableMethod = methodTree.symbol().isOverridable();
List<IdentifierTree> unused = new ArrayList<>();
for (VariableTree parameter : methodTree.parameters()) {
Symbol symbol = parameter.symbol();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,4 +185,29 @@ public String name() {
public String signature() {
return owner.name() + "." + name();
}

@Override
public boolean isOverridable() {
return false;
}

@Override
public boolean isParametrizedMethod() {
return false;
}

@Override
public boolean isDefaultMethod() {
return false;
}

@Override
public boolean isSynchronizedMethod() {
return false;
}

@Override
public boolean isVarArgsMethod() {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.eclipse.jdt.core.dom.ASTUtils;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.Modifier;
import org.sonar.java.annotations.VisibleForTesting;
import org.sonar.plugins.java.api.semantic.Symbol;
import org.sonar.plugins.java.api.semantic.Type;
Expand Down Expand Up @@ -176,6 +177,31 @@ public String signature() {
return signature;
}

@Override
public boolean isOverridable() {
return !isUnknown() && !(isPrivate() || isStatic() || isFinal() || owner().isFinal());
}

@Override
public boolean isParametrizedMethod() {
return !isUnknown() && (methodBinding().isParameterizedMethod() || methodBinding().isGenericMethod());
}

@Override
public boolean isDefaultMethod() {
return !isUnknown() && Modifier.isDefault(binding.getModifiers());
}

@Override
public boolean isSynchronizedMethod() {
return !isUnknown() && Modifier.isSynchronized(binding.getModifiers());
}

@Override
public boolean isVarArgsMethod() {
return !isUnknown() && methodBinding().isVarargs();
}

@Nullable
@Override
public MethodTree declaration() {
Expand Down
24 changes: 0 additions & 24 deletions java-frontend/src/main/java/org/sonar/java/model/JUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -146,22 +146,10 @@ public static Symbol getPackage(Symbol symbol) {
return symbol;
}

public static boolean isVarArgsMethod(Symbol.MethodSymbol method) {
return !method.isUnknown() && ((JMethodSymbol) method).methodBinding().isVarargs();
}

public static boolean isSynchronizedMethod(Symbol.MethodSymbol method) {
return !method.isUnknown() && Modifier.isSynchronized(((JMethodSymbol) method).binding.getModifiers());
}

public static boolean isNativeMethod(Symbol.MethodSymbol method) {
return !method.isUnknown() && Modifier.isNative(((JMethodSymbol) method).binding.getModifiers());
}

public static boolean isDefaultMethod(Symbol.MethodSymbol method) {
return !method.isUnknown() && Modifier.isDefault(((JMethodSymbol) method).binding.getModifiers());
}

@Nullable
public static Object defaultValue(Symbol.MethodSymbol method) {
if (method.isUnknown()) {
Expand All @@ -170,18 +158,6 @@ public static Object defaultValue(Symbol.MethodSymbol method) {
return ((JMethodSymbol) method).methodBinding().getDefaultValue();
}

public static boolean isOverridable(Symbol.MethodSymbol method) {
return !method.isUnknown() && !(method.isPrivate() || method.isStatic() || method.isFinal() || method.owner().isFinal());
}

public static boolean isParametrizedMethod(Symbol.MethodSymbol method) {
if (method.isUnknown()) {
return false;
}
return ((JMethodSymbol) method).methodBinding().isParameterizedMethod()
|| ((JMethodSymbol) method).methodBinding().isGenericMethod();
}

public static Set<Type> directSuperTypes(Type type) {
if (type.isUnknown()) {
return Collections.emptySet();
Expand Down
25 changes: 25 additions & 0 deletions java-frontend/src/main/java/org/sonar/java/model/Symbols.java
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,31 @@ public String name() {
public String signature() {
return "!unknownMethod!";
}

@Override
public boolean isOverridable() {
return false;
}

@Override
public boolean isParametrizedMethod() {
return false;
}

@Override
public boolean isDefaultMethod() {
return false;
}

@Override
public boolean isSynchronizedMethod() {
return false;
}

@Override
public boolean isVarArgsMethod() {
return false;
}
}

private static final class UnknownType implements Type {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,31 @@ interface MethodSymbol extends Symbol {
* @return the signature of the method, as String
*/
String signature();

/**
* @return true if the method symbol is overridable.
*/
boolean isOverridable();

/**
* @return true if the method has type parameters.
*/
boolean isParametrizedMethod();

/**
* @return true if the method has a default implementation.
*/
boolean isDefaultMethod();

/**
* @return true if the method is synchronized.
*/
boolean isSynchronizedMethod();

/**
* @return true if the method takes a vararg argument (e.g. `String... args`).
*/
boolean isVarArgsMethod();
}

/**
Expand Down
Loading

0 comments on commit f8601c3

Please sign in to comment.