Skip to content

Commit

Permalink
SONARJAVA-4702 Update API with methods from JUtils (#4569)
Browse files Browse the repository at this point in the history
  • Loading branch information
leonardo-pilastri-sonarsource authored Nov 27, 2023
1 parent 2d4042b commit e13d168
Show file tree
Hide file tree
Showing 52 changed files with 546 additions and 246 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.sonar.java.model.JUtils;
import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.semantic.MethodMatchers;
import org.sonar.plugins.java.api.semantic.Symbol;
Expand Down Expand Up @@ -67,7 +66,7 @@ public void visitNode(Tree tree) {
// If the call to build is made on a builder variable, we look into initialization and usages for a call to the method
getIdentifier(invocation).ifPresentOrElse(identifier -> {
Symbol symbol = identifier.symbol();
if (!JUtils.isLocalVariable(symbol) || JUtils.isParameter(symbol)) {
if (!symbol.isLocalVariable() || symbol.isParameter()) {
return;
}
VariableTree declaration = (VariableTree) symbol.declaration();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import org.sonar.java.checks.helpers.ExpressionsHelper;
import org.sonar.java.checks.methods.AbstractMethodDetection;
import org.sonar.java.model.ExpressionUtils;
import org.sonar.java.model.JUtils;
import org.sonar.java.model.Symbols;
import org.sonar.plugins.java.api.semantic.MethodMatchers;
import org.sonar.plugins.java.api.semantic.Symbol;
Expand Down Expand Up @@ -118,7 +117,7 @@ private static boolean isVariableContainingABuilderResult(ExpressionTree express
return false;
}
Symbol variable = ((IdentifierTree) expression).symbol();
return JUtils.isLocalVariable(variable) &&
return variable.isLocalVariable() &&
ExpressionsHelper.initializedAndAssignedExpressionStream(variable)
.anyMatch(AwsConsumerBuilderUsageCheck::isBuilder);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import org.sonar.check.Rule;
import org.sonar.java.checks.helpers.ExpressionsHelper;
import org.sonar.java.model.ExpressionUtils;
Expand All @@ -39,9 +38,6 @@
import org.sonar.plugins.java.api.tree.Tree;
import org.sonar.plugins.java.api.tree.VariableTree;

import static org.sonar.java.model.JUtils.isLocalVariable;
import static org.sonar.java.model.JUtils.isParameter;

@Rule(key = "S6246")
public class AwsLambdaSyncCallCheck extends AbstractAwsMethodVisitor {

Expand Down Expand Up @@ -89,10 +85,10 @@ private static Optional<String> getSyncCalls(MethodInvocationTree tree) {

// We know there is at least one usage, i.e. the one we just got above.
List<IdentifierTree> localUsages = invokeRequest.symbol().usages().stream()
.filter(u -> isLocalVariable(u.symbol()) && !u.equals(invokeRequest))
.filter(u -> u.symbol().isLocalVariable() && !u.equals(invokeRequest))
.collect(Collectors.toList());

if (isParameter(invokeRequest.symbol())
if (invokeRequest.symbol().isParameter()
|| localUsages.stream().anyMatch(lu -> isArgumentToACall(lu) || statementSetsAsyncCall(lu))
|| declarationSetsAsyncCall(invokeRequest)) {
return Optional.empty();
Expand All @@ -113,7 +109,7 @@ private static boolean isArgumentToACall(IdentifierTree invokeRequest) {

private static boolean hasLocalVarDeclaration(IdentifierTree invokeRequest) {
Tree declaration = invokeRequest.symbol().declaration();
return (declaration != null && declaration.is(Tree.Kind.VARIABLE) && isLocalVariable(((VariableTree) declaration).symbol()));
return (declaration != null && declaration.is(Tree.Kind.VARIABLE) && ((VariableTree) declaration).symbol().isLocalVariable());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.java.model.ExpressionUtils;
import org.sonar.java.model.JUtils;
import org.sonar.plugins.java.api.JavaFileScannerContext;
import org.sonar.plugins.java.api.semantic.Symbol;
import org.sonar.plugins.java.api.semantic.Type;
Expand Down Expand Up @@ -255,7 +254,7 @@ public static Optional<Symbol> getInvokedSymbol(MethodInvocationTree mit) {
}

public static boolean isNotReassigned(Symbol symbol) {
return symbol.isFinal() || (symbol.isVariableSymbol() && JUtils.isEffectivelyFinal(((Symbol.VariableSymbol) symbol)));
return symbol.isFinal() || (symbol.isVariableSymbol() && ((Symbol.VariableSymbol) symbol).isEffectivelyFinal());
}

public static List<ExpressionTree> getIdentifierAssignments(IdentifierTree identifier) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import java.util.List;
import java.util.Set;
import org.sonar.java.model.ExpressionUtils;
import org.sonar.java.model.JUtils;
import org.sonar.java.model.LiteralUtils;
import org.sonar.plugins.java.api.JavaFileScannerContext;
import org.sonar.plugins.java.api.semantic.MethodMatchers;
Expand Down Expand Up @@ -158,12 +157,12 @@ private static boolean isDerivedFromPlainText(IdentifierTree identifier, List<Ja
Set<Symbol> visited) {
Symbol symbol = identifier.symbol();
boolean firstVisit = visited.add(symbol);
if (!firstVisit || !symbol.isVariableSymbol() || JUtils.isParameter(symbol) || isNonFinalField(symbol)) {
if (!firstVisit || !symbol.isVariableSymbol() || symbol.isParameter() || isNonFinalField(symbol)) {
return false;
}
VariableTree variable = (VariableTree) symbol.declaration();
if (variable == null) {
return JUtils.constantValue((Symbol.VariableSymbol) symbol).isPresent();
return ((Symbol.VariableSymbol) symbol).constantValue().isPresent();
}

List<ExpressionTree> assignments = getIdentifierAssignments(identifier);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@

import java.lang.reflect.Constructor;
import javax.annotation.Nullable;

import org.junit.jupiter.api.Test;
import org.sonar.plugins.java.api.semantic.Symbol;
import org.sonar.plugins.java.api.tree.IdentifierTree;
import org.sonar.plugins.java.api.tree.MethodTree;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

class ExpressionsHelperTest extends JParserTestUtils {

Expand Down Expand Up @@ -127,6 +129,23 @@ void variableSwapSOE() {
assertValueResolution(code, null);
}

@Test
void isNotReassignedTest(){
Symbol.VariableSymbol symbol = mock(Symbol.VariableSymbol.class);

when(symbol.isFinal()).thenReturn(true);
assertThat(ExpressionsHelper.isNotReassigned(symbol)).isTrue();

when(symbol.isFinal()).thenReturn(false);
assertThat(ExpressionsHelper.isNotReassigned(symbol)).isFalse();

when(symbol.isVariableSymbol()).thenReturn(true);
assertThat(ExpressionsHelper.isNotReassigned(symbol)).isFalse();

when(symbol.isEffectivelyFinal()).thenReturn(true);
assertThat(ExpressionsHelper.isNotReassigned(symbol)).isTrue();
}

private <T> void assertValueResolution(String code, @Nullable T target) {
MethodTree method = methodTree(code);
IdentifierTree a = variableFromLastReturnStatement(method.block().body());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* SonarQube Java
* Copyright (C) 2012-2023 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.java.checks.helpers;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.sonar.plugins.java.api.semantic.Symbol;
import org.sonar.plugins.java.api.tree.IdentifierTree;
import org.sonar.plugins.java.api.tree.Tree;
import org.sonar.plugins.java.api.tree.VariableTree;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonar.java.checks.helpers.HardcodedStringExpressionChecker.isExpressionDerivedFromPlainText;

class HardcodedStringExpressionCheckerTest {

@Test
void isExpressionDerivedFromPlainTextTest() {
IdentifierTree expression = mock(IdentifierTree.class);
when(expression.kind()).thenReturn(Tree.Kind.IDENTIFIER);
Symbol.VariableSymbol symbol = mockSymbol(true, false, true);
Symbol owner = mockOwner(true);
when(symbol.owner()).thenReturn(owner);
VariableTree declaration = mock(VariableTree.class);
when(symbol.declaration()).thenReturn(declaration);
when(expression.symbol()).thenReturn(symbol);

assertThat(isExpressionDerivedFromPlainText(expression, new ArrayList<>(), new HashSet<>())).isFalse();

when(symbol.declaration()).thenReturn(null);
when(symbol.constantValue()).thenReturn(Optional.of("SOME VALUE"));
assertThat(isExpressionDerivedFromPlainText(expression, new ArrayList<>(), new HashSet<>())).isTrue();

when(symbol.isVariableSymbol()).thenReturn(false);
assertThat(isExpressionDerivedFromPlainText(expression, new ArrayList<>(), new HashSet<>())).isFalse();

when(symbol.isVariableSymbol()).thenReturn(true);
when(symbol.isParameter()).thenReturn(true);
assertThat(isExpressionDerivedFromPlainText(expression, new ArrayList<>(), new HashSet<>())).isFalse();

}

private Symbol mockOwner(boolean isTypeSymbol){
Symbol owner = mock(Symbol.class);
when(owner.isTypeSymbol()).thenReturn(isTypeSymbol);
return owner;
}

private Symbol.VariableSymbol mockSymbol(boolean isVariableSymbol, boolean isParameter, boolean isFinal){
Symbol.VariableSymbol symbol = mock(Symbol.VariableSymbol.class);
when(symbol.isVariableSymbol()).thenReturn(isVariableSymbol);
when(symbol.isParameter()).thenReturn(isParameter);
when(symbol.isFinal()).thenReturn(isFinal);
return symbol;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@

import static org.sonar.java.checks.helpers.DeprecatedCheckerHelper.deprecatedAnnotation;
import static org.sonar.java.checks.helpers.DeprecatedCheckerHelper.hasJavadocDeprecatedTag;
import static org.sonar.java.model.JUtils.isLocalVariable;

public abstract class AbstractMissingDeprecatedChecker extends IssuableSubscriptionVisitor {

Expand All @@ -48,7 +47,7 @@ public List<Kind> nodesToVisit() {

@Override
public void visitNode(Tree tree) {
boolean isLocalVar = tree.is(Tree.Kind.VARIABLE) && isLocalVariable(((VariableTree) tree).symbol());
boolean isLocalVar = tree.is(Tree.Kind.VARIABLE) && ((VariableTree) tree).symbol().isLocalVariable();
AnnotationTree deprecatedAnnotation = deprecatedAnnotation(tree);
boolean hasDeprecatedAnnotation = deprecatedAnnotation != null;
boolean hasJavadocDeprecatedTag = hasJavadocDeprecatedTag(tree);
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.java.checks.helpers.ExpressionsHelper;
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 @@ -62,7 +61,7 @@ private void visitClassTree(ClassTree classTree) {
}

private static boolean isInnerClass(Symbol.TypeSymbol typeSymbol) {
return !typeSymbol.equals(JUtils.outermostClass(typeSymbol));
return !typeSymbol.equals(typeSymbol.outermostClass());
}

protected boolean isSerializable(Type type) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,10 @@
import java.util.Set;
import java.util.stream.Collectors;
import org.sonar.check.Rule;
import org.sonar.plugins.java.api.JavaVersionAwareVisitor;
import org.sonar.java.model.JUtils;
import org.sonar.plugins.java.api.JavaFileScanner;
import org.sonar.plugins.java.api.JavaFileScannerContext;
import org.sonar.plugins.java.api.JavaVersion;
import org.sonar.plugins.java.api.JavaVersionAwareVisitor;
import org.sonar.plugins.java.api.semantic.Symbol;
import org.sonar.plugins.java.api.semantic.Symbol.MethodSymbol;
import org.sonar.plugins.java.api.semantic.Type;
Expand Down Expand Up @@ -89,7 +88,7 @@ private static boolean isSAM(ClassTree classBody) {
// should be anonymous class of interface and not abstract class
return symbol.interfaces().size() == 1
&& symbol.superClass().is(JAVA_LANG_OBJECT)
&& hasSingleAbstractMethodInHierarchy(JUtils.superTypes(symbol));
&& hasSingleAbstractMethodInHierarchy(symbol.superTypes());
}
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import java.util.stream.Collectors;
import org.sonar.check.Rule;
import org.sonar.java.model.ExpressionUtils;
import org.sonar.java.model.JUtils;
import org.sonar.java.model.Symbols;
import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.semantic.MethodMatchers;
Expand Down Expand Up @@ -155,7 +154,7 @@ private static Type findSuperTypeMatching(Type type, String genericTypeName) {
if (type.is(genericTypeName)) {
return type;
}
return JUtils.superTypes(type.symbol())
return type.symbol().superTypes()
.stream()
.filter(superType -> superType.is(genericTypeName))
.findFirst()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import java.util.Collections;
import java.util.List;
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.tree.MethodTree;
Expand All @@ -41,7 +40,7 @@ public void visitNode(Tree tree) {
MethodTree methodTree = (MethodTree) tree;
if (isCompareToMethod(methodTree) && Boolean.FALSE.equals(methodTree.isOverriding())) {
Symbol.TypeSymbol ownerType = (Symbol.TypeSymbol) methodTree.symbol().owner();
JUtils.superTypes(ownerType).stream().filter(supertype -> supertype.is("java.lang.Comparable")).findFirst().ifPresent(
ownerType.superTypes().stream().filter(supertype -> supertype.is("java.lang.Comparable")).findFirst().ifPresent(
comparableType -> {
String name = "Object";
if (comparableType.isParameterized()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import java.util.Collections;
import java.util.List;
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 @@ -112,7 +111,7 @@ private boolean isThisOrSuper(ExpressionTree expression) {

private boolean isMethodDefinedOnConstructedType(Symbol symbol) {
Type typeDefiningMethod = symbol.enclosingClass().type().erasure();
for (Type superType : JUtils.superTypes(constructorType)) {
for (Type superType : constructorType.superTypes()) {
if (superType.erasure().equals(typeDefiningMethod)) {
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@
import org.sonar.plugins.java.api.tree.UnaryExpressionTree;
import org.sonar.plugins.java.api.tree.VariableTree;

import static org.sonar.java.model.JUtils.isLocalVariable;

@Rule(key = "S1854")
public class DeadStoreCheck extends IssuableSubscriptionVisitor {

Expand Down Expand Up @@ -156,7 +154,7 @@ private void handleAssignment(Set<Symbol> out, Set<Tree> assignmentLHS, Assignme
ExpressionTree lhs = ExpressionUtils.skipParentheses(element.variable());
if (lhs.is(Tree.Kind.IDENTIFIER)) {
Symbol symbol = ((IdentifierTree) lhs).symbol();
if (isLocalVariable(symbol)
if (symbol.isLocalVariable()
&& !out.contains(symbol)
&& (element.is(Tree.Kind.ASSIGNMENT) || isParentExpressionStatement(element))
&& !UNRESOLVED_IDENTIFIERS_VISITOR.isUnresolved(symbol.name())) {
Expand All @@ -177,7 +175,7 @@ private static boolean isParentExpressionStatement(Tree element) {

private static void handleIdentifier(Set<Symbol> out, Set<Tree> assignmentLHS, IdentifierTree element) {
Symbol symbol = element.symbol();
if (!assignmentLHS.contains(element) && isLocalVariable(symbol)) {
if (!assignmentLHS.contains(element) && symbol.isLocalVariable()) {
out.add(symbol);
}
}
Expand Down Expand Up @@ -234,7 +232,7 @@ private void handlePrefixExpression(Set<Symbol> out, UnaryExpressionTree element
ExpressionTree expression = element.expression();
if (isParentExpressionStatement(element) && expression.is(Tree.Kind.IDENTIFIER)) {
Symbol symbol = ((IdentifierTree) expression).symbol();
if (isLocalVariable(symbol) && !out.contains(symbol)) {
if (symbol.isLocalVariable() && !out.contains(symbol)) {
createIssue(element, symbol);
}
}
Expand All @@ -244,7 +242,7 @@ private void handlePostfixExpression(Set<Symbol> out, UnaryExpressionTree elemen
ExpressionTree expression = ExpressionUtils.skipParentheses(element.expression());
if (expression.is(Tree.Kind.IDENTIFIER)) {
Symbol symbol = ((IdentifierTree) expression).symbol();
if (isLocalVariable(symbol) && !out.contains(symbol)) {
if (symbol.isLocalVariable() && !out.contains(symbol)) {
createIssue(element, symbol);
}
}
Expand Down Expand Up @@ -306,7 +304,7 @@ public void visitAssignmentExpression(AssignmentExpressionTree tree) {
ExpressionTree lhs = ExpressionUtils.skipParentheses(tree.variable());
if (lhs.is(Tree.Kind.IDENTIFIER)) {
Symbol symbol = ((IdentifierTree) lhs).symbol();
if (isLocalVariable(symbol)) {
if (symbol.isLocalVariable()) {
assignedLocalVars.add(symbol);
}
super.visitAssignmentExpression(tree);
Expand Down
Loading

0 comments on commit e13d168

Please sign in to comment.