auphong2707/dl4se-code-review-dataset huggingface dataset:
Source:
START public void done() throws CommitException { END commit(); close(); } nice maybe try finally?

Target:
public void done() throws CommitException { try { commit(); } finally { close(); } }
Source:
public boolean checkExists(Long transactorId) { // once a transactor has timed out, act like it does not exist even if still in zookeeper START if (timeoutCache.getIfPresent(transactorId) != null) END return false; return cache.getCurrentData(TransactorID.getNodePath(config, transactorId)) != null; } It might make sense to modify the usage of this cache. Transactors that have timed out should only "not exist" for all transactions before the startTime of the timeout. For any newer transactions, the timeout needs to occur again before the timeout cache is updated with a newer time. This will prevent rollbacks from continuing to occur on transactors that were slow but started to function correctly again.

Target:
public boolean checkExists(Long transactorId) { return cache.getCurrentData(TransactorID.getNodePath(config, transactorId)) != null; }
Source:
START public void stop() throws Exception { END if (started) { server.stop(); serverThread.join(); started = false; currentLeader = null; if (curatorFramework.getState().equals(CuratorFrameworkState.STARTED)) { pathChildrenCache.getListenable().removeListener(this); pathChildrenCache.close(); leaderSelector.close(); curatorFramework.getConnectionStateListenable().removeListener(this); curatorFramework.close(); } log.info("Oracle server has been stopped."); } } this is unrelated to this issue, but this stop method should probably be synchronized.

Target:
public synchronized void stop() throws Exception { if (started) { server.stop(); serverThread.join(); started = false; currentLeader = null; if (curatorFramework.getState().equals(CuratorFrameworkState.STARTED)) { pathChildrenCache.getListenable().removeListener(this); pathChildrenCache.close(); leaderSelector.close(); curatorFramework.getConnectionStateListenable().removeListener(this); curatorFramework.close(); } log.info("Oracle server has been stopped."); } }
Source:
public static String setupTestPath(final ConfigContext config, final MantaClient client, final String testName, final String testType) { if ("buckets".equals(testType)) { if (BooleanUtils.isTrue(verifyBucketsSupport(config, client))) { return setupBucketsPath(config, testName); } else { throw new SkipException("Bucket operations not supported by the server"); } } START return IntegrationTestConfigContext.generateBasePath(config, testName); END } We want to make sure that the bucket name doesn't start with an upper case character, since it's one of the naming restrictions as mentioned [here](https://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html).

Target:
public static String setupTestPath(final ConfigContext config, final MantaClient client, final String testName, final String testType) throws IOException { if ("buckets".equals(testType)) { if (BooleanUtils.isTrue(verifyBucketsSupport(config, client))) { return setupBucketsPath(config, testName); } else { throw new SkipException("Bucket operations not supported by the server"); } } return IntegrationTestConfigContext.generateBasePath(config, testName); }
Source:
public void valueOfCodeCanFindByMatchingCode() { START final MantaErrorCode expectedLimitError = MantaErrorCode.INVALID_LIMIT_ERROR; END final MantaErrorCode expectedNoApiError = MantaErrorCode.NO_API_SERVERS_AVAILABLE; final MantaErrorCode expectedObjectNotFoundError = MantaErrorCode.OBJECT_NOT_FOUND_ERROR; final MantaErrorCode actualLimitError = MantaErrorCode.valueOfCode("InvalidLimit"); final MantaErrorCode actualNoApiError = MantaErrorCode.valueOfCode("NoApiServersAvailable"); final MantaErrorCode actualObjectNotFoundError = MantaErrorCode.valueOfCode("ObjectNotFoundError"); Assert.assertEquals(actualLimitError, expectedLimitError); Assert.assertEquals(actualNoApiError, expectedNoApiError); Assert.assertEquals(actualObjectNotFoundError, expectedObjectNotFoundError); } I would just use the raw enum because that is simpler.

Target:
public void valueOfCodeCanFindByMatchingCode() { final MantaErrorCode actualLimitError = MantaErrorCode.valueOfCode("InvalidLimit"); final MantaErrorCode actualNoApiError = MantaErrorCode.valueOfCode("NoApiServersAvailable"); final MantaErrorCode actualObjectNotFoundError = MantaErrorCode.valueOfCode("ObjectNotFoundError"); Assert.assertEquals(actualLimitError, INVALID_LIMIT_ERROR); Assert.assertEquals(actualNoApiError, NO_API_SERVERS_AVAILABLE); Assert.assertEquals(actualObjectNotFoundError, OBJECT_NOT_FOUND_ERROR); }
Source:
public void validateAllSupportedCiphers() throws IOException, DecoderException { /* Loop through each Supported Cipher for All Supported Providers*/ final Iterator<SupportedCipherDetails> i = CIPHERS_TO_TEST.iterator(); START while (i.hasNext()) { END final SupportedCipherDetails cipherDetails = i.next(); validateEncryptedFileWithHeaderValues(cipherDetails); } } Use `for :` and not an iterator directly.

Target:
public void validateAllSupportedCiphers() throws IOException, DecoderException { /* Loop through each Supported Cipher for All Supported Providers*/ for (final SupportedCipherDetails cipherDetails : CIPHERS_TO_TEST) { validateEncryptedFileWithHeaderValues(cipherDetails); } }
Source:
void delete(final String rawPath, final MantaHttpHeaders requestHeaders, final Integer pruneDepth) throws IOException { Validate.notBlank(rawPath, "rawPath must not be blank"); String path = formatPath(rawPath); START if (pruneDepth == null) { END LOG.debug("DELETE {}", path); httpHelper.httpDelete(path, requestHeaders); } else { PruneEmpytParentDirectoryStrategy.pruneParentDirectories(this, requestHeaders, path, pruneDepth); } } It's good that you can handle the 0 case in `PruneEmpytParentDirectoryStrategy` but it's easier on the next maintainer if you make this check `pruneDepth == null || pruneDepth == 0` (since the fact that it isn't null means the unboxing will be safe)

Target:
void delete(final String rawPath, final MantaHttpHeaders requestHeaders, final Integer pruneDepth) throws IOException { Validate.notBlank(rawPath, "rawPath must not be blank"); String path = formatPath(rawPath); if (pruneDepth == null || pruneDepth == 0) { LOG.debug("DELETE {}", path); httpHelper.httpDelete(path, requestHeaders); } else { PruneEmpytParentDirectoryStrategy.pruneParentDirectories(this, requestHeaders, path, pruneDepth); } }
Source:
START private static long[] byteRangeAsNullSafe(final Long[] ranges, END final SupportedCipherDetails cipherDetails) { final long plaintextMax = cipherDetails.getMaximumPlaintextSizeInBytes(); final long startPos; final long endPos; if (ranges[0] == null) { startPos = 0L; } else { startPos = ranges[0]; } if (ranges[1] == null) { endPos = plaintextMax; } else { endPos = ranges[1]; } return new long[] {startPos, endPos}; } Can this be `@VisibleForTesting` (even if we are not using guava or whatever has the actual formal annotation)?

Target:
static long[] byteRangeAsNullSafe(final Long[] ranges, final SupportedCipherDetails cipherDetails) { final long plaintextMax = cipherDetails.getMaximumPlaintextSizeInBytes(); final long startPos; final long endPos; if (ranges[0] == null) { startPos = 0L; } else { startPos = ranges[0]; } if (ranges[1] == null) { endPos = plaintextMax; } else { endPos = ranges[1]; } return new long[] {startPos, endPos}; }
Source:
private void shuffleDataset() { Random random = new Random(); int iterator, shufflePosition; START Object temp; END for(iterator = dataset.length - 1; iterator > 0; iterator--) { shufflePosition = random.nextInt(iterator); temp = dataset[iterator]; dataset[iterator] = dataset[shufflePosition]; dataset[shufflePosition] = temp; } } This could be declared inside his scope, the for loop.

Target:
private void shuffleDataset() { Random random = new Random(); for(int shufflePosition = 0, iterator = dataset.length - 1; iterator > 0; iterator--) { shufflePosition = random.nextInt(iterator); Object temp = dataset[iterator]; dataset[iterator] = dataset[shufflePosition]; dataset[shufflePosition] = temp; } }
Source:
public void randomBigDecimalUsingRange() { RandomFunction random = new RandomFunction(BigDecimal.class, new Range(1, 1000)); BigDecimal bigDecimal = random.generateValue(); assertNotNull("Generated BigDecimal must not be null", bigDecimal); assertTrue("Generated value must be a BigDecimal", bigDecimal instanceof BigDecimal); START assertTrue(new BigDecimal("1").compareTo(bigDecimal) != 1); END assertTrue(new BigDecimal("1000").compareTo(bigDecimal) != -1); } Maybe here should be better to check if the generated value is in the range instead of checking if it's not the `limit values`. Something like: ``` assertTrue(new BigDecimal("1").compareTo(bigDecimal) >= 1); assertTrue(new BigDecimal("1000").compareTo(bigDecimal) <= 1000); ``` What do you think?

Target:
public void randomBigDecimalUsingRange() { RandomFunction random = new RandomFunction(BigDecimal.class, new Range(1, 1000)); BigDecimal bigDecimal = random.generateValue(); assertNotNull("Generated BigDecimal must not be null", bigDecimal); assertTrue("Generated value must be a BigDecimal", bigDecimal instanceof BigDecimal); assertTrue(bigDecimal.compareTo(new BigDecimal("1")) >= 0); assertTrue(bigDecimal.compareTo(new BigDecimal("1000")) <= 0); }
Source:
public void testItValidatesMaxSizeOfPhotoShareByMessage() throws MalformedURLException { SharePhotoContent sharePhotoContent = START new SharePhotoContent.Builder().addPhoto(buildSharePhoto("https://facebook.com/awesome-1.gif")) END .addPhoto(buildSharePhoto("https://facebook.com/awesome-2.gif")) .addPhoto(buildSharePhoto("https://facebook.com/awesome-3.gif")) .addPhoto(buildSharePhoto("https://facebook.com/awesome-4.gif")) .addPhoto(buildSharePhoto("https://facebook.com/awesome-5.gif")) .addPhoto(buildSharePhoto("https://facebook.com/awesome-6.gif")) .addPhoto(buildSharePhoto("https://facebook.com/awesome-7.gif")) .build(); ShareContentValidation.validateForMessage(sharePhotoContent); } nit put addPhoto on next line

Target:
public void testItValidatesMaxSizeOfPhotoShareByMessage() { SharePhotoContent sharePhotoContent = new SharePhotoContent.Builder() .addPhoto(buildSharePhoto("https://facebook.com/awesome-1.gif")) .addPhoto(buildSharePhoto("https://facebook.com/awesome-2.gif")) .addPhoto(buildSharePhoto("https://facebook.com/awesome-3.gif")) .addPhoto(buildSharePhoto("https://facebook.com/awesome-4.gif")) .addPhoto(buildSharePhoto("https://facebook.com/awesome-5.gif")) .addPhoto(buildSharePhoto("https://facebook.com/awesome-6.gif")) .addPhoto(buildSharePhoto("https://facebook.com/awesome-7.gif")) .build(); ShareContentValidation.validateForMessage(sharePhotoContent); }
Source:
public boolean canBePloted(World world, int x, int y, int z) { for (GhostGroupElement element : elementList) { START if (!Eln.ghostManager.canCreateGhostAt(world, new BlockPos( + element.x, y + element.y, z + element.z))) END return false; } return true; } This is obviously a syntax error.

Target:
public boolean canBePloted(World world, int x, int y, int z) { for (GhostGroupElement element : elementList) { if (!Eln.ghostManager.canCreateGhostAt(world, new BlockPos( x + element.x, y + element.y, z + element.z))) return false; } return true; }
Source:
private void replaceFile(Path from, Path to) throws IOException { try { START Files.move(from, to, StandardCopyOption.ATOMIC_MOVE); END } catch (AtomicMoveNotSupportedException e) { Files.move(from, to, StandardCopyOption.REPLACE_EXISTING); } } Files.move(from, to, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE); I would pass both parameters for the first try.

Target:
private void replaceFile(Path from, Path to) throws IOException { try { Files.move(from, to, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING); } catch (AtomicMoveNotSupportedException e) { Files.move(from, to, StandardCopyOption.REPLACE_EXISTING); } }
Source:
public boolean textboxKeyTyped(char par1, int par2) { if (getEnabled() && this.isFocused() && par1 == '\r') { return true; START setFocused(false); END } return super.textboxKeyTyped(par1, par2); } Should be inverted

Target:
public boolean textboxKeyTyped(char par1, int par2) { if (getEnabled() && this.isFocused() && par1 == '\r') { setFocused(false); return true; } return super.textboxKeyTyped(par1, par2); }
Source:
public void visitNode(Tree tree) { START if (!hasSemantic()) { return; } END String qualifiedName = ((AnnotationTree) tree).annotationType().symbolType().fullyQualifiedName(); if (OLD_NEW_ANNOTATIONS_MAP.containsKey(qualifiedName)) { reportIssue(tree, String.format("Change this JUnit4 %s to the equivalent JUnit5 %s annotation.", qualifiedName, OLD_NEW_ANNOTATIONS_MAP.get(qualifiedName))); } } It needs to be clearly discussed and clarified at one point, but the case where the semantic is missing should never happen, we already removed this check for many rules. I believe you can also remove this one (and the corresponding test).

Target:
public void visitNode(Tree tree) { String qualifiedName = ((AnnotationTree) tree).annotationType().symbolType().fullyQualifiedName(); if (OLD_NEW_ANNOTATIONS_MAP.containsKey(qualifiedName)) { reportIssue(tree, String.format("Change this JUnit4 %s to the equivalent JUnit5 %s annotation.", qualifiedName, OLD_NEW_ANNOTATIONS_MAP.get(qualifiedName))); } }
Source:
public void visitMethodInvocation(MethodInvocationTree mit) { START if (isInvocationOnVariable(mit, variable) && SET_SSL_CHECK_SERVER_ID.matches(mit) && isNotFalse(mit.arguments().get(0))) { END this.isSecured = true; } super.visitMethodInvocation(mit); } This test condition leads to FP if we are bad at resolving the variable symbol. I would prefer to replace `isInvocationOnVariable` by something like `isInvocationOnTheGivenVariableButReturnTrueIfYourAreUnsureAboutOnWhatThisMethodIsInvoked` :wink:

Target:
public void visitMethodInvocation(MethodInvocationTree mit) { if (isInvocationOnVariable(mit, variable, true) && SET_SSL_CHECK_SERVER_ID.matches(mit) && isNotFalse(mit.arguments().get(0))) { this.isSecured = true; } super.visitMethodInvocation(mit); }
Source:
protected List<MethodMatcher> getMethodInvocationMatchers() { return Collections.singletonList( MethodMatcher.create() START .typeDefinition(TypeCriteria.is("javax.crypto.Cipher")) END .name("getInstance") .withAnyParameters()); } You can directly use the string is you are using `TypeCriteria.is()`

Target:
protected List<MethodMatcher> getMethodInvocationMatchers() { return Collections.singletonList( MethodMatcher.create() .typeDefinition("javax.crypto.Cipher") .name("getInstance") .withAnyParameters()); }
Source:
private void addIssueIfNotCaught(Type thrown, Tree node) { if (isNotCaught(thrown)) { START String message = "Handle the " + "\"" + thrown + "\"" + " thrown here in a \"try/catch\" block."; END reportIssue(node, message); } } Never rely on the ToString() method of a type. What if it change in implementation class for debugging purpose? Use `thrown.name()` instead.

Target:
private void addIssueIfNotCaught(Type thrown, Tree node) { if (isNotCaught(thrown)) { String message = "Handle the " + "\"" + thrown.name() + "\"" + " thrown here in a \"try/catch\" block."; reportIssue(node, message); } }
Source:
START private void usageLabel(@Nullable IdentifierTreeImpl node) { END if (node == null) { return; } labels.stream() .filter(couple -> couple.label.equals(node.name())) .map(couple -> couple.symbol) .findFirst() .ifPresent(labelSymbol -> { labelSymbol.usages.add(node); node.labelSymbol = labelSymbol; }); } Do not break the group of methods working with tokens, i.e. should be above `firstTokenIndexAfter`.

Target:
private void usageLabel(@Nullable IdentifierTreeImpl node) { if (node == null) { return; } labels.stream() .filter(symbol -> symbol.name().equals(node.name())) .findFirst() .ifPresent(labelSymbol -> { labelSymbol.usages.add(node); node.labelSymbol = labelSymbol; }); }
Source:
private void declaration(@Nullable IBinding binding, Tree node) { if (binding == null) { return; } START sema.declarations.put(sema.declarationBinding(binding), node); END } IMO for declarations `binding == sema.declarationBinding(binding)` already.

Target:
private void declaration(@Nullable IBinding binding, Tree node) { if (binding == null) { return; } sema.declarations.put(binding, node); }
Source:
START public List<String> getStrings() { END if (null == strings) { synchronized (this) { if (null == this.strings) { strings = new ArrayList<>(); // Noncompliant [[sc=11;ec=38;secondary=25,27]] {{Fully initialize "strings" before assigning it.}} strings.add("Hello"); System.out.println(); strings.add("World"); } } } return strings; } please use a different name for the method here, this should not compile...

Target:
public List<String> getStrings() { if (strings == null) { synchronized (this) { if (strings == null) { strings = new ArrayList<>(); // Noncompliant [[sc=11;ec=38;secondary=15,16]] {{Fully initialize "strings" before assigning it.}} strings.add("Hello"); strings.add("World"); } } } return strings; }
Source:
private static Symbol symbol(ExpressionTree tree) { START return Optional.ofNullable(tree).filter(t -> t.is(Kind.IDENTIFIER)).map(t -> ((IdentifierTree) t).symbol()).orElse(null); END } You should annotate parameter with `@Nullable` , or if you don't need to handle `null` argument, you don't need `ofNullable`

Target:
private static Symbol symbol(ExpressionTree tree) { if (tree.is(Kind.IDENTIFIER)) { return ((IdentifierTree) tree).symbol(); } return null; }
Source:
private static StatementTree getBody(StatementTree tree, int expectedSize) { START StatementTree statement = tree; END if (statement.is(Kind.BLOCK)) { BlockTree block = (BlockTree) statement; List<StatementTree> body = block.body(); statement = body.size() == expectedSize ? body.get(0) : null; } return statement; } Do we need this variable?

Target:
private static StatementTree getBody(StatementTree tree, int expectedSize) { if (tree.is(Kind.BLOCK)) { BlockTree block = (BlockTree) tree; List<StatementTree> body = block.body(); tree = body.size() == expectedSize ? body.get(0) : null; } return tree; }
Source:
public List<Tree.Kind> nodesToVisit() { START return ImmutableList.of(Tree.Kind.CLASS, Tree.Kind.METHOD); END } I'm not sure why you need to have both Classes and Methods here Why not only registering to CLASS, and iterate over its members (Trees)? You will then have only 2 cases to handle: * It's a VariableTree, so it's necessarily a field, you already have the declaration... And in such cases you absolutely don't need to rely on the `isField()` method. * It's a MethodTree, so it's a method... and you have everything you need to check the parameters already. * It's something else (inner class for instance), do nothing

Target:
public List<Tree.Kind> nodesToVisit() { return ImmutableList.of(Tree.Kind.CLASS); }
Source:
private boolean isMessageLoggedWithAdditionalContext() { START if (loggingMethodInvocations.isEmpty()) { END return false; } return loggingMethodInvocations.stream().anyMatch(mit -> hasGetMessageInvocation(mit) && hasDynamicExceptionMessageUsage(mit)); } unecessray with the anymatch afterwards.

Target:
private boolean isMessageLoggedWithAdditionalContext() { return loggingMethodInvocations.stream().anyMatch(mit -> hasGetMessageInvocation(mit) && hasDynamicExceptionMessageUsage(mit)); }
Source:
public void scanFile(final JavaFileScannerContext context) { this.context = context; assertionInMethod.clear(); visitedMethods.clear(); inUnitTest.push(false); methodContainsAssertion.push(false); scan(context.getTree()); methodContainsAssertion.pop(); inUnitTest.pop(); assertionInMethod.clear(); START visitedMethods.clear(); END } As discussed, you can probably rely on the keySet of assertionInMethod map rather than using an other set.

Target:
public void scanFile(final JavaFileScannerContext context) { this.context = context; assertionInMethod.clear(); inUnitTest.push(false); methodContainsAssertion.push(false); scan(context.getTree()); methodContainsAssertion.pop(); inUnitTest.pop(); assertionInMethod.clear(); }
Source:
protected void onMethodInvocationFound(MethodInvocationTree mit) { ExpressionTree arg = mit.arguments().get(0); String domain = ConstantUtils.resolveAsStringConstant(arg); START if (domain != null && !domain.substring(1).contains(".")) { END reportIssue(arg, "Specify at least a second-level cookie domain."); } } Check will crash if code contains a call to `setDomain` method with empty string `myCookie.setDomain("");`

Target:
protected void onMethodInvocationFound(MethodInvocationTree mit) { ExpressionTree arg = mit.arguments().get(0); String domain = ConstantUtils.resolveAsStringConstant(arg); if (domain != null && !domain.isEmpty() && !domain.substring(1).contains(".")) { reportIssue(arg, "Specify at least a second-level cookie domain."); } }
Source:
void HttpCookie(String domain) { START HttpCookie myCookie = new Cookie("name", "val"); END myCookie.setDomain(".com"); // Noncompliant myCookie.setDomain(".myDomain.com"); // Compliant myCookie.setDomain(domain); // Compliant } Should it not be `new HttpCookie` instead?

Target:
void HttpCookie(String domain) { HttpCookie myCookie = new HttpCookie("name", "val"); myCookie.setDomain(".com"); // Noncompliant myCookie.setDomain(".myDomain.com"); // Compliant myCookie.setDomain(domain); // Compliant }
Source:
START public void visitMethod(MethodTree tree) { END if (!isEquals(tree)) { super.visitMethod(tree); } } make it final. You don't want classes extending it to override this, as it's driving the analysis.

Target:
public final void visitMethod(MethodTree tree) { if (!isEquals(tree)) { super.visitMethod(tree); } }
Source:
START protected static boolean isBot(Type type) { END return ((JavaType) type).isTagged(JavaType.BOT); } why not private?

Target:
private static boolean isBot(Type type) { return ((JavaType) type).isTagged(JavaType.BOT); }
Source:
public void visitNewClass(NewClassTree tree) { START if (tree.is(Tree.Kind.NEW_CLASS)) { END checkMethodInvocationArgument(tree.arguments(), tree.constructorSymbol()); } super.visitNewClass(tree); } the `tree` is necessarily a `NewClassTree` here, so you already know it's going to be of the good kind. You can drop the `if`.

Target:
public void visitNewClass(NewClassTree tree) { checkMethodInvocationArgument(tree.arguments(), tree.constructorSymbol()); super.visitNewClass(tree); }
Source:
private boolean hasNoSecurityConstraint(XmlFile file) { NodeList nodeList = evaluate(securityConstraintExpression, file.getNamespaceUnawareDocument()); START return (nodeList.getLength() == 0); END } no need for the parenthesis

Target:
private boolean hasNoSecurityConstraint(XmlFile file) { NodeList nodeList = evaluate(securityConstraintExpression, file.getNamespaceUnawareDocument()); return nodeList.getLength() == 0; }
Source:
public void visitIdentifier(IdentifierTree tree) { START if (tree.name().equals(exceptionIdentifier.name())) { END isExceptionIdentifierUsed = true; } } There is no need to recheck equality if `isExceptionIdentifierUsed` is already true

Target:
public void visitIdentifier(IdentifierTree tree) { if (!isExceptionIdentifierUsed && tree.name().equals(exceptionIdentifier.name())) { isExceptionIdentifierUsed = true; } }
Source:
protected List<MethodMatcher> getMethodInvocationMatchers() { return ImmutableList.of( MethodMatcher.create() START .typeDefinition(TypeCriteria.is("javax.crypto.Cipher")) END .name("getInstance") .withAnyParameters(), MethodMatcher.create() .typeDefinition(TypeCriteria.is("org.apache.commons.crypto.utils.Utils")) .name("getCipherInstance") .withAnyParameters()); } You can use the string overload when TypeCriteria is exact match.

Target:
protected List<MethodMatcher> getMethodInvocationMatchers() { return ImmutableList.of( MethodMatcher.create() .typeDefinition("javax.crypto.Cipher") .name("getInstance") .withAnyParameters(), MethodMatcher.create() .typeDefinition("org.apache.commons.crypto.utils.Utils") .name("getCipherInstance") .withAnyParameters()); }
Source:
private static Tree firstStatementParent(Tree node) { Tree current = node; START while (true) { END if (current instanceof StatementTree) { return current; } current = current.parent(); } } probably safer to have a current != null

Target:
private static Tree firstStatementParent(Tree node) { Tree current = node.parent(); while (current != null) { if (current instanceof StatementTree) { break; } current = current.parent(); } return current; }
Source:
private static void addSecurityStandards(NewRule rule, SecurityStandards securityStandards) { for (String s : securityStandards.OWASP) { rule.addOwaspTop10(OwaspTop10.valueOf(s)); } START int[] cweNumbers = Arrays.stream(securityStandards.CWE).map(cwe -> cwe.substring(4)).mapToInt(Integer::valueOf).toArray(); END rule.addCwe(cweNumbers); } hm... do we want change API? to accept full names?

Target:
private static void addSecurityStandards(NewRule rule, SecurityStandards securityStandards) { for (String s : securityStandards.OWASP) { rule.addOwaspTop10(OwaspTop10.valueOf(s)); } rule.addCwe(securityStandards.CWE); }
Source:
private boolean methodOpeningResource(MethodInvocationTree mit) { return !excludedByRuleOption(mit.symbolType()) START && !isWithinTryHeader(mit) END && !handledByFramework(mit) && (JDBC_RESOURCE_CREATIONS.anyMatch(mit) || STREAMS_BACKED_BY_RESOURCE.anyMatch(mit) || (needsClosing(mit.symbolType()) && !CLOSEABLE_EXCEPTIONS.anyMatch(mit) && mitHeuristics(mit))); } Why switching the order of the short circuit ?

Target:
private boolean methodOpeningResource(MethodInvocationTree mit) { return !isWithinTryHeader(mit) && !excludedByRuleOption(mit.symbolType()) && !handledByFramework(mit) && (JDBC_RESOURCE_CREATIONS.anyMatch(mit) || STREAMS_BACKED_BY_RESOURCE.anyMatch(mit) || (needsClosing(mit.symbolType()) && !CLOSEABLE_EXCEPTIONS.anyMatch(mit) && mitHeuristics(mit))); }
Source:
private static List<StringConstant> antMatchersPatterns(MethodInvocationTree mit) { List<StringConstant> argumentsAsString = mit.arguments().stream() .map(StringConstant::of) .collect(Collectors.toList()); START return argumentsAsString.stream().allMatch(Objects::nonNull) ? argumentsAsString : Collections.emptyList(); END } Why only considering the cases having only literals? I think we should also consider the following cases, as we already know they are wrong, even without considering `myVar`: ```java http.authorizeRequests().antMatchers("/admin/**", myVar, "/admin/login"); // Noncompliant ``` Therefore, I would simply skip the null values.

Target:
private static List<StringConstant> antMatchersPatterns(MethodInvocationTree mit) { return mit.arguments().stream() .map(StringConstant::of) .filter(Objects::nonNull) .collect(Collectors.toList()); }
Source:
public void reportIssue(JavaCheck javaCheck, Tree syntaxNode, String message, List<Location> secondary, @Nullable Integer cost) { START throwIfCrossFileScanner(javaCheck); END List<List<Location>> flows = secondary.stream().map(Collections::singletonList).collect(Collectors.toList()); reportIssueWithFlow(javaCheck, syntaxNode, message, flows, cost); } I wonder about throwing everywhere, as most of the `reportIssue` message are calling the same on line 123/127.

Target:
public void reportIssue(JavaCheck javaCheck, Tree syntaxNode, String message, List<Location> secondary, @Nullable Integer cost) { List<List<Location>> flows = secondary.stream().map(Collections::singletonList).collect(Collectors.toList()); reportIssueWithFlow(javaCheck, syntaxNode, message, flows, cost); }
Source:
public void reportIssue(JavaCheck javaCheck, Tree tree, String message) { START throwIfEndOfAnalysisCheck(javaCheck); END reportIssue(javaCheck, tree, message, ImmutableList.of(), null); } Let's use this method on overloading.

Target:
public void reportIssue(JavaCheck javaCheck, Tree tree, String message) { reportIssue(javaCheck, tree, message, ImmutableList.of(), null); }
Source:
public void test() { JavaCheckVerifier.verify("src/test/files/checks/spring/SpringSecurityDisableCSRFCheck.java", new SpringSecurityDisableCSRFCheck()); START JavaCheckVerifier.verifyNoIssueWithoutSemantic("src/test/files/checks/spring/SpringSecurityDisableCSRFCheck.java", new SpringSecurityDisableCSRFCheck()); END } To me this line is useless, the `AbstractMethodDetection` checks won't work without semantic, and it won't change coverage.

Target:
public void test() { JavaCheckVerifier.verify("src/test/files/checks/spring/SpringSecurityDisableCSRFCheck.java", new SpringSecurityDisableCSRFCheck()); }
Source:
public void junit_assert_that() { START assertThat("aaa", org.junit.matchers.JUnitMatchers.containsString("a")); END } Do not change that. Keep it explicit to show that it's a junit assert.

Target:
public void junit_assert_that() { org.junit.Assert.assertThat("aaa", org.junit.matchers.JUnitMatchers.containsString("a")); }
Source:
void testRecursion() { Math f = new Math() { // Compliant, recursion @Override START public String powerOfTwo(int n) { END return n == 0 ? 1 : 2 * powerOfTwo(n -1); } }; } int powerOfTwo(int n);

Target:
void testRecursion() { Math f = new Math() { // Compliant, recursion @Override public int powerOfTwo(int n) { return n == 0 ? 1 : 2 * powerOfTwo(n -1); } }; }
Source:
START private static MethodTree findEnclosingMethod(Tree tree) { END while (!tree.is(Tree.Kind.CLASS, Tree.Kind.METHOD)) { tree = tree.parent(); } if (tree.is(Tree.Kind.CLASS)) { return null; } return (MethodTree) tree; } this duplicates `findEnclosingMethod` on `CipherBlockChainingCheck` - should move to `ExpressionsHelper` or something similar

Target:
public static MethodTree findEnclosingMethod(Tree tree) { while (!tree.is(Tree.Kind.CLASS, Tree.Kind.METHOD)) { tree = tree.parent(); } if (tree.is(Tree.Kind.CLASS)) { return null; } return (MethodTree) tree; }
Source:
public void visitNode(Tree tree) { if (!hasSemantic()) { return; } MethodTree methodTree = (MethodTree) tree; BlockTree blockTree = methodTree.block(); if (blockTree == null) { return; } START if (!CHECK_CLIENT_TRUSTED_MATCHER.matches(methodTree) && !CHECK_SERVER_TRUSTED_MATCHER.matches(methodTree)) { END return; } if (!ThrowExceptionVisitor.throwsException(blockTree)) { reportIssue(methodTree.simpleName(), "Change this method so it throws exceptions."); } } Think it would be easier to read without negations and return. ``` if (CHECK_CLIENT_TRUSTED_MATCHER.matches(methodTree) || CHECK_SERVER_TRUSTED_MATCHER.matches(methodTree)) { if (!ThrowExceptionVisitor.throwsException(blockTree)) { //... } } ```

Target:
public void visitNode(Tree tree) { if (!hasSemantic()) { return; } MethodTree methodTree = (MethodTree) tree; BlockTree blockTree = methodTree.block(); if (blockTree == null) { return; } if ((CHECK_CLIENT_TRUSTED_MATCHER.matches(methodTree) || CHECK_SERVER_TRUSTED_MATCHER.matches(methodTree)) && !ThrowExceptionVisitor.throwsException(blockTree)) { reportIssue(methodTree.simpleName(), "Change this method so it throws exceptions."); } }
Source:
public void method_with_unknown_symbol_should_not_produce_ucfg() { CompilationUnitTree cut = getCompilationUnitTreeWithSemantics("class A {void foo(UnkownType t) {return t;}}"); UCFGJavaVisitor UCFGJavaVisitor = new UCFGJavaVisitor(tmp.getRoot()) { @Override protected void serializeUCFG(MethodTree tree, CFG cfg) { fail("should not serialize a UCFG of a method with unknown parameters"); } }; UCFGJavaVisitor.fileKey = FILE_KEY; UCFGJavaVisitor.visitCompilationUnit(cut); cut = getCompilationUnitTreeWithSemantics("class A {UnkownType foo(String t) {return t;}}"); UCFGJavaVisitor.visitCompilationUnit(cut); START END } useless empty lines

Target:
public void method_with_unknown_symbol_should_not_produce_ucfg() { UCFGJavaVisitor UCFGJavaVisitor = new UCFGJavaVisitor(tmp.getRoot()) { @Override protected void serializeUCFG(MethodTree tree, CFG cfg) { fail("should not serialize a UCFG of a method with unknown parameters"); } }; UCFGJavaVisitor.fileKey = FILE_KEY; // method with unknown arg CompilationUnitTree cut = getCompilationUnitTreeWithSemantics("class A {void foo(UnkownType t) {return t;}}"); UCFGJavaVisitor.visitCompilationUnit(cut); // method with unkown return type cut = getCompilationUnitTreeWithSemantics("class A {UnkownType foo(String t) {return t;}}"); UCFGJavaVisitor.visitCompilationUnit(cut); }
Source:
public void scanFile(JavaFileScannerContext context) { this.context = context; statementSet.clear(); START scan(context.getTree()); END } You should clear the set after the scan to, to be sure that references to the `IfStatementTree` are not kept for the whole scanning process. Actually, I think I'd prefer to avoid using a set altogether by using the parent to retrieve the `else` keyword (i.e. if the parent is a `IfStatementTree` and current if is the else statement of the parent). What do you think?

Target:
public void scanFile(JavaFileScannerContext context) { this.context = context; scan(context.getTree()); }
Source:
private static String getSuggestedType(boolean springInjectionAnnotated, Type leastSpecificType) { if (springInjectionAnnotated && leastSpecificType.is("java.lang.Iterable")) { return "java.util.Collection"; START } else { END return leastSpecificType.fullyQualifiedName().replace('$', '.'); } } minor : no need for the else with the returns...

Target:
private static String getSuggestedType(boolean springInjectionAnnotated, Type leastSpecificType) { if (springInjectionAnnotated && leastSpecificType.is("java.lang.Iterable")) { return "java.util.Collection"; } return leastSpecificType.fullyQualifiedName().replace('$', '.'); }
Source:
private void handleParameter(Symbol parameter, boolean springInjectionAnnotated) { Type leastSpecificType = findLeastSpecificType(parameter); if (parameter.type() != leastSpecificType && !leastSpecificType.is("java.lang.Object") START && !(springInjectionAnnotated && parameter.type().is("java.util.Collection"))) { END String suggestedType = getSuggestedType(springInjectionAnnotated, leastSpecificType); reportIssue(parameter.declaration(), String.format("Use '%s' here; it is a more general type than '%s'.", suggestedType, parameter.type().name())); } } matter of style and choices but I tend to think that this last part of the && should be implemented as a filter of stream on the parameters stream.

Target:
private void handleParameter(Symbol parameter, boolean springInjectionAnnotated) { Type leastSpecificType = findLeastSpecificType(parameter); if (parameter.type() != leastSpecificType && !leastSpecificType.is("java.lang.Object")) { String suggestedType = getSuggestedType(springInjectionAnnotated, leastSpecificType); reportIssue(parameter.declaration(), String.format("Use '%s' here; it is a more general type than '%s'.", suggestedType, parameter.type().name())); } }
Source:
private static boolean noSpacingBetween(SyntaxToken firstToken, SyntaxToken secondToken) { START return firstToken.column() + firstToken.text().length() == secondToken.column(); END } I just realized that this could generate FPs when placed on different lines: ```java target = +num; ``` We should check that both token are sharing the same line.

Target:
private static boolean noSpacingBetween(SyntaxToken firstToken, SyntaxToken secondToken) { return firstToken.line() == secondToken.line() && firstToken.column() + firstToken.text().length() == secondToken.column(); }
Source:
private void checkMethodDefinition(MethodTree tree) { BlockTree blockTree = tree.block(); START if (tree.symbol() != null && VERIFY_METHOD_MATCHER.matches(tree) && blockTree != null) { END checkBlock(blockTree); } } symbol cannot be null for a method tree.

Target:
private void checkMethodDefinition(MethodTree tree) { BlockTree blockTree = tree.block(); if (VERIFY_METHOD_MATCHER.matches(tree) && blockTree != null) { checkBlock(blockTree); } }
Source:
private static boolean isHostnameVerifierSignature(LambdaExpressionTree lambdaExpressionTree) { List<VariableTree> parameters = lambdaExpressionTree.parameters(); START return lambdaExpressionTree.symbolType().isSubtypeOf("javax.net.ssl.HostnameVerifier") END && parameters.size() == 2 && TYPE_CRITERIA_STRING.test(parameters.get(0).type().symbolType()) && TYPE_CRITERIA_SSL_SESSION.test(parameters.get(1).type().symbolType()); } if you have a lambda as a subtype of HostnameVerifier I don't think you need all the elements of the condition. (in other words, there is no way if this first part is true that any of the following might be false, and it is therefore uncoverable by unit test and useless) : so all the following && can be safely removed I think. (please prove me wrong if I am ;) )

Target:
private static boolean isHostnameVerifierSignature(LambdaExpressionTree lambdaExpressionTree) { return lambdaExpressionTree.symbolType().isSubtypeOf("javax.net.ssl.HostnameVerifier"); }
Source:
private static ExpressionTree instanceofFound(ExpressionTree expressionTree, Tree.Kind kind) { START if (Tree.Kind.CONDITIONAL_OR.equals(kind)) { END /* if CONDITIONAL_OR we want LOGICAL COMPLEMENT before instanceof */ if (expressionTree.is(Tree.Kind.LOGICAL_COMPLEMENT)) { return instanceofLHS(ExpressionUtils.skipParentheses(((UnaryExpressionTree) expressionTree).expression())); } else { return null; } } else { return instanceofLHS(expressionTree); } } ``` kind == Tree.Kind.CONDITIONAL_OR ```

Target:
private static ExpressionTree instanceofFound(ExpressionTree expressionTree, Tree.Kind kind) { if (kind == Tree.Kind.CONDITIONAL_OR) { /* if CONDITIONAL_OR we want LOGICAL COMPLEMENT before instanceof */ if (expressionTree.is(Tree.Kind.LOGICAL_COMPLEMENT)) { return instanceofLHS(ExpressionUtils.skipParentheses(((UnaryExpressionTree) expressionTree).expression())); } else { return null; } } else { return instanceofLHS(expressionTree); } }
Source:
private void checkUsage(IdentifierTree parameterUsage, MethodTree methodTree) { START Tree parameterParent = parameterUsage.identifierToken().parent(); END while (!parameterParent.equals(methodTree) && !assertReported.contains(parameterParent)) { if (parameterParent.is(Tree.Kind.ASSERT_STATEMENT)) { assertReported.add((AssertStatementTree) parameterParent); reportIssue(parameterParent, "Replace this assert with a proper check."); return; } parameterParent = parameterParent.parent(); } } why starting from the `identifierToken()` and not directly from `parameterUsage` ? You can directly strart from the parameter parent.

Target:
private void checkUsage(IdentifierTree parameterUsage, MethodTree methodTree) { Tree parameterParent = parameterUsage.parent(); while (!parameterParent.equals(methodTree) && !assertReported.contains(parameterParent)) { if (parameterParent.is(Tree.Kind.ASSERT_STATEMENT)) { assertReported.add((AssertStatementTree) parameterParent); reportIssue(parameterParent, "Replace this assert with a proper check."); return; } parameterParent = parameterParent.parent(); } }
Source:
private static void logNoMatchClasses(Collection<IClassCoverage> noMatchClasses) { START if (!noMatchClasses.isEmpty()) { END LOG.warn("The following class(es) did not match with execution data:"); for (IClassCoverage iClassCoverage : noMatchClasses) { LOG.warn(String.format("> '%s'", iClassCoverage.getName())); } LOG.warn("In order to have accurate coverage measures, the same class files must be used as at runtime for report generation."); } } @m-g-sonar use early return to improve readability?

Target:
private static void logNoMatchClasses(Collection<IClassCoverage> noMatchClasses) { if (noMatchClasses.isEmpty()) { return; } LOG.warn("The following class(es) did not match with execution data:"); for (IClassCoverage iClassCoverage : noMatchClasses) { LOG.warn(String.format("> '%s'", iClassCoverage.getName())); } LOG.warn("In order to have accurate coverage measures, the same class files must be used as at runtime for report generation."); }
Source:
public void visitNewClass(NewClassTree tree) { super.visitNewClass(tree); ClassTree classBody = tree.classBody(); if (classBody != null) { TypeTree identifier = tree.identifier(); START if (!useThisIdentifier(classBody) && !enumConstants.contains(identifier) && isSAM(classBody, identifier)) { END context.reportIssue(this, identifier, "Make this anonymous inner class a lambda" + context.getJavaVersion().java8CompatibilityMessage()); } } } You don't need the identifier here. You can extract the equivalent symbol from the classBody directly in the method `isSAM`.

Target:
public void visitNewClass(NewClassTree tree) { super.visitNewClass(tree); ClassTree classBody = tree.classBody(); if (classBody != null) { TypeTree identifier = tree.identifier(); if (!useThisIdentifier(classBody) && !enumConstants.contains(identifier) && isSAM(classBody)) { context.reportIssue(this, identifier, "Make this anonymous inner class a lambda" + context.getJavaVersion().java8CompatibilityMessage()); } } }
Source:
public void visitNode(Tree tree) { IfStatementTree treeIfStmt = (IfStatementTree) tree; StatementTree elseStmt = treeIfStmt.elseStatement(); IfStatementTree ifStmt = null; if (elseStmt != null && elseStmt.is(Tree.Kind.IF_STATEMENT)) { START ifStmt = (IfStatementTree) elseStmt; END } if (ifStmt != null && ifStmt.elseStatement() == null) { reportIssue(treeIfStmt.elseKeyword(), ifStmt.ifKeyword(), "\"if ... else if\" constructs should end with \"else\" clauses."); } } I think you are over-complicating things here. Try to keep it simple and "logical" to read, introducing the variable you need and minimizing the number of validation you need to do. In this case, simply nest the 2 `if` statements, and put the definition of the `ifStmt` variable within the body of the first `if`. you can then remove the `ifStmt != null` test.

Target:
public void visitNode(Tree tree) { IfStatementTree treeIfStmt = (IfStatementTree) tree; StatementTree elseStmt = treeIfStmt.elseStatement(); if (elseStmt != null && elseStmt.is(Tree.Kind.IF_STATEMENT)) { IfStatementTree ifStmt = (IfStatementTree) elseStmt; if (ifStmt.elseStatement() == null) { reportIssue(treeIfStmt.elseKeyword(), ifStmt.ifKeyword(), "\"if ... else if\" constructs should end with \"else\" clauses."); } } }
Source:
public List<Tree.Kind> nodesToVisit() { START return Collections.singletonList((Tree.Kind.CONSTRUCTOR)); END } Unecessary parentheses.

Target:
public List<Tree.Kind> nodesToVisit() { return Collections.singletonList(Tree.Kind.CONSTRUCTOR); }
Source:
START public List<Kind> nodesToVisit() { END return ImmutableList.of(Tree.Kind.SWITCH_STATEMENT); } Use `Tree.Kind` instead, to remove the import.

Target:
public List<Tree.Kind> nodesToVisit() { return ImmutableList.of(Tree.Kind.SWITCH_STATEMENT); }
Source:
public void visitSwitchStatement(SwitchStatementTree tree) { START reportIssue((tree).switchKeyword(), END "Refactor the code to eliminate this nested \"switch\"."); } remove the useless parentheses, and no need for 2 different lines.

Target:
public void visitSwitchStatement(SwitchStatementTree tree) { reportIssue(tree.switchKeyword(), "Refactor the code to eliminate this nested \"switch\"."); }
Source:
private static boolean isNullableThroughNonNull(Symbol symbol) { List<SymbolMetadata.AnnotationValue> valuesForAnnotation = symbol.metadata().valuesForAnnotation("javax.annotation.Nonnull"); if (valuesForAnnotation == null) { return false; } START if (valuesForAnnotation.isEmpty()) { END return false; } return checkAnnotationParameter(valuesForAnnotation, "when", "MAYBE") || checkAnnotationParameter(valuesForAnnotation, "when", "UNKNOWN"); } I would factorize this in the condition of the previous if.

Target:
private static boolean isNullableThroughNonNull(Symbol symbol) { List<SymbolMetadata.AnnotationValue> valuesForAnnotation = symbol.metadata().valuesForAnnotation("javax.annotation.Nonnull"); if (valuesForAnnotation == null || valuesForAnnotation.isEmpty()) { return false; } return checkAnnotationParameter(valuesForAnnotation, "when", "MAYBE") || checkAnnotationParameter(valuesForAnnotation, "when", "UNKNOWN"); }
Source:
START public static Optional<String> parameterNonNullGlobalAnnotation(Symbol.MethodSymbol method) { END if (isGloballyAnnotatedWith(method, JAVAX_ANNOTATION_PARAMETERS_ARE_NONNULL_BY_DEFAULT)) { return Optional.of(JAVAX_ANNOTATION_PARAMETERS_ARE_NONNULL_BY_DEFAULT); } if (isGloballyAnnotatedWith(method, ORG_ECLIPSE_JDT_ANNOTATION_NON_NULL_BY_DEFAULT, "PARAMETER")) { return Optional.of(ORG_ECLIPSE_JDT_ANNOTATION_NON_NULL_BY_DEFAULT); } return Optional.empty(); } as far as I understand the usage of this method it seems you don't get anything out of Optional: this method should just return null

Target:
public static String parameterNonNullGlobalAnnotation(Symbol.MethodSymbol method) { if (isGloballyAnnotatedWith(method, JAVAX_ANNOTATION_PARAMETERS_ARE_NONNULL_BY_DEFAULT)) { return JAVAX_ANNOTATION_PARAMETERS_ARE_NONNULL_BY_DEFAULT; } if (isGloballyAnnotatedWith(method, ORG_ECLIPSE_JDT_ANNOTATION_NON_NULL_BY_DEFAULT, "PARAMETER")) { return ORG_ECLIPSE_JDT_ANNOTATION_NON_NULL_BY_DEFAULT; } return null; }
Source:
START public void setUp() { END semanticModel = SETestUtils.getSemanticModel("src/test/files/se/annotations/NullableAnnotationUtils.java"); } This change implies parsing and semantic computation for every test of this class. This seems quite some overhead.

Target:
public static void setUp() { semanticModel = SETestUtils.getSemanticModel("src/test/files/se/annotations/NullableAnnotationUtils.java"); }
Source:
private ProgramState handleSpecialMethods(ProgramState ps, MethodInvocationTree mit) { START if (AnnotationUtils.isAnnotatedNonNull(mit.symbol())) { END return ps.addConstraint(ps.peekValue(), ObjectConstraint.NOT_NULL); } else if (OBJECT_WAIT_MATCHER.matches(mit)) { return ps.resetFieldValues(constraintManager, false); } return ps; } Wondering about having a static import for AnnotationUtils method.

Target:
private ProgramState handleSpecialMethods(ProgramState ps, MethodInvocationTree mit) { if (isAnnotatedNonNull(mit.symbol())) { return ps.addConstraint(ps.peekValue(), ObjectConstraint.NOT_NULL); } else if (OBJECT_WAIT_MATCHER.matches(mit)) { return ps.resetFieldValues(constraintManager, false); } return ps; }
Source:
static boolean enqueueExitBlock4() { try { throwSpecificException(); } catch (Throwable e) { START return true; END } return true; } wonder if it would not be more interesting to have `false` here to see that we are correctly jumping into the catch.

Target:
static boolean enqueueExitBlock4() { try { throwSpecificException(); } catch (Throwable e) { return true; } return false; }
Source:
public String toString() { START return "[" + stream().map(Constraint::toString).sorted().collect(Collectors.joining(",")) + "]"; END } 👍 Minor: you can provide suffix and prefix args to `Collectors.joining` and avoid adding brackets with `+`

Target:
public String toString() { return stream().map(Constraint::toString).sorted().collect(Collectors.joining(",", "[", "]")); }
Source:
public boolean equals(Object o) { START if (this == o) END return true; if (o == null || getClass() != o.getClass()) return false; FieldOrMethod that = (FieldOrMethod) o; return ownerIsInterface == that.ownerIsInterface && Objects.equals(owner, that.owner) && Objects.equals(name, that.name) && Objects.equals(desc, that.desc); } please fix this one

Target:
public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } FieldOrMethod that = (FieldOrMethod) o; return ownerIsInterface == that.ownerIsInterface && Objects.equals(owner, that.owner) && Objects.equals(name, that.name) && Objects.equals(desc, that.desc); }
Source:
public void visitMethodInvocation(MethodInvocationTree tree) { if (SUPER_THREAD.matches(tree) && ThreadOverridesRunCheck.hasRunnableArgument(tree.arguments())) { START callSuperWithRunnable = true; END } super.visitMethodInvocation(tree); } micro optimisation but : no need to visit further...

Target:
public void visitMethodInvocation(MethodInvocationTree tree) { if (SUPER_THREAD.matches(tree) && ThreadOverridesRunCheck.hasRunnableArgument(tree.arguments())) { callSuperWithRunnable = true; // no need to visit further return; } super.visitMethodInvocation(tree); }