diff --git a/its/plugin/tests/src/test/java/com/sonar/it/java/suite/TestUtils.java b/its/plugin/tests/src/test/java/com/sonar/it/java/suite/TestUtils.java index 45255fbfdbc..a781cdb0026 100644 --- a/its/plugin/tests/src/test/java/com/sonar/it/java/suite/TestUtils.java +++ b/its/plugin/tests/src/test/java/com/sonar/it/java/suite/TestUtils.java @@ -23,7 +23,6 @@ import com.sonar.orchestrator.container.Server; import com.sonar.orchestrator.junit4.OrchestratorRule; import java.io.File; -import java.io.FilenameFilter; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -57,12 +56,9 @@ public static File homeDir() { } public static File pluginJar(String artifactId) { - return Iterables.getOnlyElement(Arrays.asList(new File(homeDir(), "plugins/" + artifactId + "/target/").listFiles(new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return name.endsWith(".jar") && !name.endsWith("-sources.jar"); - } - }))); + return Iterables.getOnlyElement(Arrays.asList(new File(homeDir(), "plugins/" + artifactId + "/target/").listFiles( + (dir, name) -> name.endsWith(".jar") && !name.endsWith("-sources.jar") + ))); } public static File projectDir(String projectName) { diff --git a/java-checks-aws/src/main/java/org/sonar/java/checks/security/HardCodedCredentialsShouldNotBeUsedCheck.java b/java-checks-aws/src/main/java/org/sonar/java/checks/security/HardCodedCredentialsShouldNotBeUsedCheck.java index 3a463607b95..8a13c5e2146 100644 --- a/java-checks-aws/src/main/java/org/sonar/java/checks/security/HardCodedCredentialsShouldNotBeUsedCheck.java +++ b/java-checks-aws/src/main/java/org/sonar/java/checks/security/HardCodedCredentialsShouldNotBeUsedCheck.java @@ -111,10 +111,9 @@ private void checkArguments(Arguments arguments, CredentialMethod method) { var secondaryLocations = new ArrayList(); if (isExpressionDerivedFromPlainText(argument, secondaryLocations, new HashSet<>())) { String value = ExpressionsHelper.getConstantValueAsString(argument).value(); - if (value != null && SecretClassifier.isKnownNonSecret(value)) { - continue; + if (value == null || !SecretClassifier.isKnownNonSecret(value)) { + reportIssue(argument, ISSUE_MESSAGE, secondaryLocations, null); } - reportIssue(argument, ISSUE_MESSAGE, secondaryLocations, null); } } } diff --git a/java-checks-testkit/src/main/java/org/sonar/java/checks/verifier/internal/Expectations.java b/java-checks-testkit/src/main/java/org/sonar/java/checks/verifier/internal/Expectations.java index 17fb7a0bd41..70e4170a634 100644 --- a/java-checks-testkit/src/main/java/org/sonar/java/checks/verifier/internal/Expectations.java +++ b/java-checks-testkit/src/main/java/org/sonar/java/checks/verifier/internal/Expectations.java @@ -448,26 +448,24 @@ void consolidateQuickFixes() { List quickFixesForIssue = new ArrayList<>(); for (String quickFixId : entry.getValue()) { - if (NO_QUICK_FIX_ID.equals(quickFixId)) { - // When the id corresponds to the "no quick fix id", it means that we expect no quick fix for this issue. - continue; + if (!NO_QUICK_FIX_ID.equals(quickFixId)) { + allQuickFixIds.add(quickFixId); + String message = quickfixesMessages.get(quickFixId); + if (message == null) { + throw new AssertionError("Missing message for quick fix: " + quickFixId); + } + List edits = quickfixesEdits.get(quickFixId); + if (edits == null) { + throw new AssertionError("Missing edits for quick fix: " + quickFixId); + } + + JavaQuickFix javaQuickFix = JavaQuickFix.newQuickFix(message).addTextEdits( + edits.stream() + .map(edit -> getEdit(edit, issueTextSpan, quickFixId)) + .toList() + ).build(); + quickFixesForIssue.add(javaQuickFix); } - allQuickFixIds.add(quickFixId); - String message = quickfixesMessages.get(quickFixId); - if (message == null) { - throw new AssertionError("Missing message for quick fix: " + quickFixId); - } - List edits = quickfixesEdits.get(quickFixId); - if (edits == null) { - throw new AssertionError("Missing edits for quick fix: " + quickFixId); - } - - JavaQuickFix javaQuickFix = JavaQuickFix.newQuickFix(message).addTextEdits( - edits.stream() - .map(edit -> getEdit(edit, issueTextSpan, quickFixId)) - .toList() - ).build(); - quickFixesForIssue.add(javaQuickFix); } quickFixes.put(issueTextSpan, quickFixesForIssue); } diff --git a/java-checks-testkit/src/main/java/org/sonar/java/checks/verifier/internal/InternalCheckVerifier.java b/java-checks-testkit/src/main/java/org/sonar/java/checks/verifier/internal/InternalCheckVerifier.java index c069b6c5631..ac3f8474c7d 100644 --- a/java-checks-testkit/src/main/java/org/sonar/java/checks/verifier/internal/InternalCheckVerifier.java +++ b/java-checks-testkit/src/main/java/org/sonar/java/checks/verifier/internal/InternalCheckVerifier.java @@ -659,18 +659,15 @@ public void accept(Set issues) { for (AnalyzerMessage issue : issues) { AnalyzerMessage.TextSpan primaryLocation = issue.primaryLocation(); List expected = expectedQuickFixes.get(primaryLocation); - if (expected == null) { - // We don't have to always test quick fixes, we do nothing if there is no expected quick fix. - continue; - } - List actual = actualQuickFixes.get(primaryLocation); - if (expected.isEmpty()) { - if (actual != null && !actual.isEmpty()) { - throw new AssertionError(String.format("[Quick Fix] Issue on line %d contains quick fixes while none where expected", primaryLocation.startLine)); + if (expected != null) { + List actual = actualQuickFixes.get(primaryLocation); + if (expected.isEmpty()) { + if (actual != null && !actual.isEmpty()) { + throw new AssertionError(String.format("[Quick Fix] Issue on line %d contains quick fixes while none where expected", primaryLocation.startLine)); + } + } else { + validateIfSameSize(expected, actual, issue); } - // Else: no issue in both expected and actual, nothing to do - } else { - validateIfSameSize(expected, actual, issue); } } } diff --git a/java-checks-testkit/src/test/java/org/sonar/java/checks/verifier/internal/JavaCheckVerifierTest.java b/java-checks-testkit/src/test/java/org/sonar/java/checks/verifier/internal/JavaCheckVerifierTest.java index 6b9ff77a6cc..d732eff40a2 100644 --- a/java-checks-testkit/src/test/java/org/sonar/java/checks/verifier/internal/JavaCheckVerifierTest.java +++ b/java-checks-testkit/src/test/java/org/sonar/java/checks/verifier/internal/JavaCheckVerifierTest.java @@ -44,7 +44,6 @@ import org.sonar.java.reporting.JavaQuickFix; import org.sonar.java.reporting.JavaTextEdit; import org.sonar.plugins.java.api.JavaFileScanner; -import org.sonar.plugins.java.api.JavaFileScannerContext; import org.sonar.plugins.java.api.caching.CacheContext; import org.sonar.plugins.java.api.caching.JavaReadCache; import org.sonar.plugins.java.api.caching.JavaWriteCache; @@ -245,12 +244,9 @@ void context_return_good_root_working_directory() { assertThatCode(() -> { JavaCheckVerifier.newInstance() .onFile(TEST_FILE) - .withCheck(new JavaFileScanner() { - @Override - public void scanFile(JavaFileScannerContext context) { - assertThat(context.getRootProjectWorkingDirectory().getPath()).isEqualTo(rootWorkDir); - } - }) + .withCheck((JavaFileScanner) context -> + assertThat(context.getRootProjectWorkingDirectory().getPath()).isEqualTo(rootWorkDir) + ) .withProjectLevelWorkDir(rootWorkDir) .verifyNoIssues(); }).doesNotThrowAnyException(); @@ -432,13 +428,10 @@ void compilationUnitModifier_modify_tree() { classTree.complete((ModifiersTreeImpl) classTree.modifiers(), classTree.declarationKeyword(), ident); }; - var check = new JavaFileScanner() { - @Override - public void scanFile(JavaFileScannerContext context) { - CompilationUnitTree tree = context.getTree(); - ClassTreeImpl classTree = (ClassTreeImpl) tree.types().get(0); - assertThat(classTree.simpleName().name()).isEqualTo("Modified"); - } + var check = (JavaFileScanner) context -> { + CompilationUnitTree tree = context.getTree(); + ClassTreeImpl classTree = (ClassTreeImpl) tree.types().get(0); + assertThat(classTree.simpleName().name()).isEqualTo("Modified"); }; JavaCheckVerifier.newInstance() diff --git a/java-frontend/src/main/java/org/sonar/java/cfg/LiveVariables.java b/java-frontend/src/main/java/org/sonar/java/cfg/LiveVariables.java index 478d80e2e33..f31923a333c 100644 --- a/java-frontend/src/main/java/org/sonar/java/cfg/LiveVariables.java +++ b/java-frontend/src/main/java/org/sonar/java/cfg/LiveVariables.java @@ -113,11 +113,10 @@ private void analyzeCFG(Map> in, Map newIn = new HashSet<>(gen.get(block)); newIn.addAll(SetUtils.difference(blockOut, kill.get(block))); - if (newIn.equals(in.get(block))) { - continue; + if (!newIn.equals(in.get(block))) { + in.put(block, newIn); + block.predecessors().forEach(workList::addLast); } - in.put(block, newIn); - block.predecessors().forEach(workList::addLast); } } diff --git a/java-frontend/src/main/java/org/sonar/java/classpath/JavaSdkUtil.java b/java-frontend/src/main/java/org/sonar/java/classpath/JavaSdkUtil.java index 03308f62300..51a72a8715c 100644 --- a/java-frontend/src/main/java/org/sonar/java/classpath/JavaSdkUtil.java +++ b/java-frontend/src/main/java/org/sonar/java/classpath/JavaSdkUtil.java @@ -66,20 +66,16 @@ private static List collectJars(Path home, boolean isMac) { List rootFiles = new ArrayList<>(); Set duplicatePathFilter = new HashSet<>(); for (Path jarDir : collectJarDirs(home, isMac)) { - if (!Files.isDirectory(jarDir)) { - continue; + if (Files.isDirectory(jarDir)) { + listFiles(jarDir, JavaSdkUtil::isJarFile).stream() + .filter(JavaSdkUtil::isNotAlternativeImplementation) + .map(JavaSdkUtil::toRealPath).filter(Optional::isPresent).map(Optional::get) + .forEach(jarFile -> { + if (duplicatePathFilter.add(jarFile)) { + rootFiles.add(jarFile.toFile()); + } + }); } - listFiles(jarDir, JavaSdkUtil::isJarFile).stream() - // filter out alternative implementations - .filter(JavaSdkUtil::isNotAlternativeImplementation) - // filter out duplicate (symbolically linked) .jar files commonly found in OS X JDK distributions - .map(JavaSdkUtil::toRealPath).filter(Optional::isPresent).map(Optional::get) - // make sure there is no duplicates - .forEach(jarFile -> { - if (duplicatePathFilter.add(jarFile)) { - rootFiles.add(jarFile.toFile()); - } - }); } return rootFiles; diff --git a/java-frontend/src/main/java/org/sonar/java/model/InternalSyntaxTrivia.java b/java-frontend/src/main/java/org/sonar/java/model/InternalSyntaxTrivia.java index e34d9442ad3..d7f341bc29c 100644 --- a/java-frontend/src/main/java/org/sonar/java/model/InternalSyntaxTrivia.java +++ b/java-frontend/src/main/java/org/sonar/java/model/InternalSyntaxTrivia.java @@ -24,7 +24,7 @@ import org.sonar.plugins.java.api.tree.Tree; import org.sonar.plugins.java.api.tree.TreeVisitor; -public class InternalSyntaxTrivia extends JavaTree implements SyntaxTrivia { +public final class InternalSyntaxTrivia extends JavaTree implements SyntaxTrivia { private final CommentKind commentKind; diff --git a/java-frontend/src/main/java/org/sonar/java/model/JMethodSymbol.java b/java-frontend/src/main/java/org/sonar/java/model/JMethodSymbol.java index 5ae3d502130..7a470516627 100644 --- a/java-frontend/src/main/java/org/sonar/java/model/JMethodSymbol.java +++ b/java-frontend/src/main/java/org/sonar/java/model/JMethodSymbol.java @@ -157,18 +157,14 @@ void findOverridesInParentTypes(Collection accumulator, Predicate< private void findOverridesInTypes(Collection accumulator, Predicate overridesCondition, ITypeBinding... types) { for (ITypeBinding type : types) { - if (type == null) { - // Can happen for unknown reason. - continue; + if (type != null) { + Stream.of(type.getDeclaredMethods()) + .filter(overridesCondition) + .findFirst() + .map(sema::methodSymbol) + .ifPresent(accumulator::add); + findOverridesInParentTypes(accumulator, overridesCondition, type); } - // check current type - Stream.of(type.getDeclaredMethods()) - .filter(overridesCondition) - .findFirst() - .map(sema::methodSymbol) - .ifPresent(accumulator::add); - // check other inheritance levels - findOverridesInParentTypes(accumulator, overridesCondition, type); } } diff --git a/java-frontend/src/main/java/org/sonar/java/model/JParser.java b/java-frontend/src/main/java/org/sonar/java/model/JParser.java index fbaf8af9307..7e80b322777 100644 --- a/java-frontend/src/main/java/org/sonar/java/model/JParser.java +++ b/java-frontend/src/main/java/org/sonar/java/model/JParser.java @@ -976,9 +976,10 @@ private EnumConstantTreeImpl processEnumConstantDeclaration(EnumConstantDeclarat final InternalSyntaxToken closeParToken; if (tokenManager.get(openParTokenIndex).tokenType == TerminalToken.TokenNameLPAREN) { openParToken = createSyntaxToken(openParTokenIndex); - closeParToken = e.arguments().isEmpty() - ? firstTokenAfter(e.getName(), TerminalToken.TokenNameRPAREN) - : firstTokenAfter((ASTNode) e.arguments().get(e.arguments().size() - 1), TerminalToken.TokenNameRPAREN); + ASTNode closeParAnchor = e.arguments().isEmpty() + ? e.getName() + : (ASTNode) e.arguments().get(e.arguments().size() - 1); + closeParToken = firstTokenAfter(closeParAnchor, TerminalToken.TokenNameRPAREN); } else { openParToken = null; closeParToken = null; @@ -2737,9 +2738,11 @@ private JavaTree.WildcardTreeImpl convertWildcardType(WildcardType e) { if (bound == null) { t = new JavaTree.WildcardTreeImpl(questionToken); } else { + Tree.Kind wildcardKind = e.isUpperBound() ? Tree.Kind.EXTENDS_WILDCARD : Tree.Kind.SUPER_WILDCARD; + TerminalToken boundTokenType = e.isUpperBound() ? TerminalToken.TokenNameextends : TerminalToken.TokenNamesuper; t = new JavaTree.WildcardTreeImpl( - e.isUpperBound() ? Tree.Kind.EXTENDS_WILDCARD : Tree.Kind.SUPER_WILDCARD, - e.isUpperBound() ? firstTokenBefore(bound, TerminalToken.TokenNameextends) : firstTokenBefore(bound, TerminalToken.TokenNamesuper), + wildcardKind, + firstTokenBefore(bound, boundTokenType), convertType(bound) ).complete(questionToken); } diff --git a/java-frontend/src/main/java/org/sonar/java/model/JSymbolMetadata.java b/java-frontend/src/main/java/org/sonar/java/model/JSymbolMetadata.java index 7c1bb897713..2b9c5b6b862 100644 --- a/java-frontend/src/main/java/org/sonar/java/model/JSymbolMetadata.java +++ b/java-frontend/src/main/java/org/sonar/java/model/JSymbolMetadata.java @@ -408,22 +408,19 @@ public List values() { } private Object convertAnnotationValue(Object value) { - if (value instanceof IVariableBinding iVariableBinding) { - return sema.variableSymbol(iVariableBinding); - } else if (value instanceof ITypeBinding iTypeBinding) { - return sema.typeSymbol(iTypeBinding); - } else if (value instanceof IAnnotationBinding iAnnotationBinding) { - return sema.annotation(iAnnotationBinding); - } else if (value instanceof Object[] a) { - // Godin: probably better to not modify original array - Object[] result = new Object[a.length]; - for (int i = 0; i < a.length; i++) { - result[i] = convertAnnotationValue(a[i]); + return switch (value) { + case IVariableBinding iVariableBinding -> sema.variableSymbol(iVariableBinding); + case ITypeBinding iTypeBinding -> sema.typeSymbol(iTypeBinding); + case IAnnotationBinding iAnnotationBinding -> sema.annotation(iAnnotationBinding); + case Object[] a -> { + Object[] result = new Object[a.length]; + for (int i = 0; i < a.length; i++) { + result[i] = convertAnnotationValue(a[i]); + } + yield result; } - return result; - } else { - return value; - } + case null, default -> value; + }; } } diff --git a/java-frontend/src/main/java/org/sonar/java/model/SmapFile.java b/java-frontend/src/main/java/org/sonar/java/model/SmapFile.java index 877fc90e4bf..d19e7b18335 100644 --- a/java-frontend/src/main/java/org/sonar/java/model/SmapFile.java +++ b/java-frontend/src/main/java/org/sonar/java/model/SmapFile.java @@ -43,7 +43,7 @@ *

* We expect only single JSP stratum, with single FileSection and LineSection. Moreover only single file is expected in FileSection */ -public class SmapFile { +public final class SmapFile { private static final Pattern LINE_INFO = Pattern.compile("(?\\d+)" + "(?:#(?\\d+))?" + diff --git a/java-frontend/src/test/java/org/sonar/java/ast/JavaAstScannerTest.java b/java-frontend/src/test/java/org/sonar/java/ast/JavaAstScannerTest.java index 00ff3723a2c..9c7d66bc68e 100644 --- a/java-frontend/src/test/java/org/sonar/java/ast/JavaAstScannerTest.java +++ b/java-frontend/src/test/java/org/sonar/java/ast/JavaAstScannerTest.java @@ -451,13 +451,10 @@ void scanWithoutParsing_filters_out_the_files_that_could_be_successfully_scanned @Test void test_modifyCompilationUnit_modify_ast() { - var check = new JavaFileScanner() { - @Override - public void scanFile(JavaFileScannerContext context) { - CompilationUnitTree tree = context.getTree(); - ClassTreeImpl classTree = (ClassTreeImpl) tree.types().get(0); - assertThat(classTree.simpleName().symbol().isUnknown()).isTrue(); - } + var check = (JavaFileScanner) scannerContext -> { + CompilationUnitTree tree = scannerContext.getTree(); + ClassTreeImpl classTree = (ClassTreeImpl) tree.types().get(0); + assertThat(classTree.simpleName().symbol().isUnknown()).isTrue(); }; VisitorsBridge visitorsBridge = new VisitorsBridge( diff --git a/java-jsp/src/main/java/org/sonar/java/jsp/Jasper.java b/java-jsp/src/main/java/org/sonar/java/jsp/Jasper.java index 42cf2bc1b24..54f3bfab15a 100644 --- a/java-jsp/src/main/java/org/sonar/java/jsp/Jasper.java +++ b/java-jsp/src/main/java/org/sonar/java/jsp/Jasper.java @@ -236,7 +236,7 @@ static Path outputDir(SensorContext sensorContext) { /** * Overloading log methods so messages are redirected to scanner log */ - static class ServletContext extends JspCServletContext { + static final class ServletContext extends JspCServletContext { public ServletContext(URL aResourceBaseURL, ClassLoader classLoader) throws JasperException { super(/* not used */ null, aResourceBaseURL, classLoader, false, true);