pmd / pmd

An extensible multilanguage static code analyzer.

Home Page:https://pmd.github.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[java] CommentDefaultAccessModifier - false-positive for MethodSource in nested classes

Wolf2323 opened this issue · comments

Affects PMD Version: 7.1.0

Rule: CommentDefaultAccessModifier

Please provide the rule name and a link to the rule documentation:
https://pmd.github.io/pmd/pmd_rules_java_codestyle.html#commentdefaultaccessmodifier

Description:
The issue appeared with the update to PMD 7 previously in PMD 6 this was no issue. I think this is an false positive, but it could also be a new behavior, that i need to deal with.

When i have a nested class with a test, and the test use a @MethodSource the method for the source is violating CommentDefaultAccessModifier (it has no modifier) but previously it was fine in PMD 6. And i think this is actually a false positive, as it is no issue if you dont have a nested class

Code Sample demonstrating the issue:

class BoundPluralTests {
	@Nested
	class use {
		static @NotNull Stream<Arguments> plurals() { // <-- here is the issue
			return Stream.of(
					Arguments.of("0 branches"),
					Arguments.of("1 branch"),
					Arguments.of("2 branches"),
					Arguments.of("branches")
			);
		}

		@ParameterizedTest
		@MethodSource("plurals")
		void get_translation(@NotNull final String expected) {

Expected outcome:

everything should be fine, but i have this output:
[INFO] PMD Failure: works.reload.recore.intl.use:34 Rule:CommentDefaultAccessModifier Priority:3 Missing commented default access modifier on method 'plurals()'.

PMD reports a violation at line ..., but that's wrong. That's a false positive.

Running PMD through: Maven

And here is the rule configuration:

	<rule ref="category/java/codestyle.xml/CommentDefaultAccessModifier">
		<properties>
			<property name="ignoredAnnotations" value="com.google.common.annotations.VisibleForTesting,
			android.support.annotation.VisibleForTesting,
			org.junit.jupiter.api.Test,
			org.junit.jupiter.api.ParameterizedTest,
			org.junit.jupiter.api.RepeatedTest,
			org.junit.jupiter.api.TestFactory,
			org.junit.jupiter.api.TestTemplate,
			org.junit.jupiter.api.BeforeEach,
			org.junit.jupiter.api.BeforeAll,
			org.junit.jupiter.api.AfterEach,
			org.junit.jupiter.api.AfterAll,
			org.junit.jupiter.api.Nested,
			org.junit.jupiter.params.ParameterizedTest,
			org.jetbrains.annotations.VisibleForTesting
			"/>
		</properties>
	</rule>

Back in PMD 6.55.0 if, the container class had any of the ignored annotations, all methods were ignored (and therefore the @Nested implied plurals() was not flagged).

This behavior was removed in PMD 7.0.0. Based on the documentation for the rule and existing tests, this behavior was not intended, and actually a false-negative. Moreover, @MethodSource doesn't impose any requirements on method visibility that I am aware of, unlike @Test which under JUnit 5 expects package-private to be used prominently.

Test methods default to package-private because visibility isn't much of a concern with tests (there's little inheritance and as non-production code this isn't critical, anyway), so readability (i.e. no clutter, no /* default */ comment) trumps minimal visibility.
IMO that reasoning not just applies to test methods, but also nested test classes, methods that supply arguments to parameterized tests, and any other goodie that has been added (in JUnit 5).

If PMD is forcing users to tweak its default rules for test classes, I think that's unfortunate, especially because complex XPath expressions have to be used (targeting the (outer) test class name, but also including any nested test classes). Many projects adhere to Maven's file system structure (i.e. separation of test classes in src/test vs. src/main); it would be really great if PMD allowed exclusions based on that distinction.

@Wolf2323 you can make the method plurals() private. See also #4975, which has exactly this example. PMD 7.2.0 won't warn about such private methods anymore.