diff --git a/src/it/MPMD-266-typeresolution-aggregated/invoker.properties b/src/it/MPMD-266-typeresolution-aggregated/invoker.properties
index 2490429a..59e9a7b0 100644
--- a/src/it/MPMD-266-typeresolution-aggregated/invoker.properties
+++ b/src/it/MPMD-266-typeresolution-aggregated/invoker.properties
@@ -15,6 +15,6 @@
# specific language governing permissions and limitations
# under the License.
-invoker.goals = clean install
-invoker.goals.2 = site
+invoker.goals = clean verify
+invoker.goals.2 = verify site -DskipTests
invoker.maven.version = 3+
diff --git a/src/it/MPMD-266-typeresolution-aggregated/module-a/pom.xml b/src/it/MPMD-266-typeresolution-aggregated/module-a/pom.xml
index d60ab9e4..a71e17de 100644
--- a/src/it/MPMD-266-typeresolution-aggregated/module-a/pom.xml
+++ b/src/it/MPMD-266-typeresolution-aggregated/module-a/pom.xml
@@ -30,4 +30,17 @@ under the License.
MPMD-266-typeresolution-aggregated-module-a
+
+
+
+ @project.groupId@
+ @project.artifactId@
+
+
+ ../ruleset.xml
+
+
+
+
+
diff --git a/src/it/MPMD-266-typeresolution-aggregated/module-b/pom.xml b/src/it/MPMD-266-typeresolution-aggregated/module-b/pom.xml
index 3a67e1fc..e16304ac 100644
--- a/src/it/MPMD-266-typeresolution-aggregated/module-b/pom.xml
+++ b/src/it/MPMD-266-typeresolution-aggregated/module-b/pom.xml
@@ -30,6 +30,20 @@ under the License.
MPMD-266-typeresolution-aggregated-module-b
+
+
+
+ @project.groupId@
+ @project.artifactId@
+
+
+ ../ruleset.xml
+
+
+
+
+
+
${project.groupId}
diff --git a/src/it/MPMD-266-typeresolution-aggregated/pom.xml b/src/it/MPMD-266-typeresolution-aggregated/pom.xml
index 1cce966d..c56846bf 100644
--- a/src/it/MPMD-266-typeresolution-aggregated/pom.xml
+++ b/src/it/MPMD-266-typeresolution-aggregated/pom.xml
@@ -55,6 +55,11 @@ under the License.
@project.version@
true
+ false
+ 1
+
+ ruleset.xml
+
diff --git a/src/it/MPMD-266-typeresolution-aggregated/ruleset.xml b/src/it/MPMD-266-typeresolution-aggregated/ruleset.xml
index d0f3f04b..f6924eda 100644
--- a/src/it/MPMD-266-typeresolution-aggregated/ruleset.xml
+++ b/src/it/MPMD-266-typeresolution-aggregated/ruleset.xml
@@ -25,6 +25,8 @@ under the License.
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
Custom Ruleset for test case MPMD-266
-
+
+ 5
+
diff --git a/src/it/MPMD-277-multi-module-check/invoker.properties b/src/it/MPMD-277-multi-module-check/invoker.properties
new file mode 100644
index 00000000..abe0f0da
--- /dev/null
+++ b/src/it/MPMD-277-multi-module-check/invoker.properties
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+invoker.goals = clean package
+invoker.goals.2 = verify
+invoker.maven.version = 3+
diff --git a/src/it/MPMD-277-multi-module-check/module-a/pom.xml b/src/it/MPMD-277-multi-module-check/module-a/pom.xml
new file mode 100644
index 00000000..c972de6b
--- /dev/null
+++ b/src/it/MPMD-277-multi-module-check/module-a/pom.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+ 4.0.0
+
+
+ org.apache.maven.plugins.pmd.it
+ MPMD-277-multi-module-check-parent
+ 1.0-SNAPSHOT
+
+
+ MPMD-277-multi-module-check-module-a
+
+
diff --git a/src/it/MPMD-277-multi-module-check/module-a/src/main/java/module/a/IModuleA.java b/src/it/MPMD-277-multi-module-check/module-a/src/main/java/module/a/IModuleA.java
new file mode 100644
index 00000000..83cfecf9
--- /dev/null
+++ b/src/it/MPMD-277-multi-module-check/module-a/src/main/java/module/a/IModuleA.java
@@ -0,0 +1,24 @@
+package module.a;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+public interface IModuleA
+{
+}
\ No newline at end of file
diff --git a/src/it/MPMD-277-multi-module-check/module-a/src/main/java/module/a/ModuleA.java b/src/it/MPMD-277-multi-module-check/module-a/src/main/java/module/a/ModuleA.java
new file mode 100644
index 00000000..9d5d21dd
--- /dev/null
+++ b/src/it/MPMD-277-multi-module-check/module-a/src/main/java/module/a/ModuleA.java
@@ -0,0 +1,24 @@
+package module.a;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+public class ModuleA implements IModuleA
+{
+}
\ No newline at end of file
diff --git a/src/it/MPMD-277-multi-module-check/module-b/pom.xml b/src/it/MPMD-277-multi-module-check/module-b/pom.xml
new file mode 100644
index 00000000..8d76fcda
--- /dev/null
+++ b/src/it/MPMD-277-multi-module-check/module-b/pom.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+ 4.0.0
+
+
+ org.apache.maven.plugins.pmd.it
+ MPMD-277-multi-module-check-parent
+ 1.0-SNAPSHOT
+
+
+ MPMD-277-multi-module-check-module-b
+
+
+
+ ${project.groupId}
+ MPMD-277-multi-module-check-module-a
+ ${project.version}
+
+
+
+ org.apache.commons
+ commons-math
+ 2.2
+
+
+
diff --git a/src/it/MPMD-277-multi-module-check/module-b/src/main/java/module/b/ModuleB.java b/src/it/MPMD-277-multi-module-check/module-b/src/main/java/module/b/ModuleB.java
new file mode 100644
index 00000000..0689d93a
--- /dev/null
+++ b/src/it/MPMD-277-multi-module-check/module-b/src/main/java/module/b/ModuleB.java
@@ -0,0 +1,54 @@
+package module.b;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import module.a.IModuleA;
+import module.a.ModuleA;
+import org.apache.commons.math.complex.Complex;
+import org.apache.commons.math.FieldElement;
+
+public class ModuleB
+{
+ public static void main( String[] args )
+ {
+ ModuleA m = new ModuleA();
+ doSomething( m );
+ }
+
+ // this method will be detected as being unsued,
+ // if typeresolution is not setup correctly: module a needs
+ // to be on PMD's auxclasspath, so that PMD knows, that ModuleA
+ // implements IModuleA
+ private static void doSomething( IModuleA module )
+ {
+ System.out.println( module );
+ }
+
+ public static void aPublicMethod()
+ {
+ Complex u = new Complex(1, 1);
+ aPrivateMethod( u );
+ }
+
+ private static void aPrivateMethod( FieldElement u )
+ {
+ System.out.println( "aPrivateMethod: " + u );
+ }
+}
\ No newline at end of file
diff --git a/src/it/MPMD-277-multi-module-check/pom.xml b/src/it/MPMD-277-multi-module-check/pom.xml
new file mode 100644
index 00000000..5c7b8871
--- /dev/null
+++ b/src/it/MPMD-277-multi-module-check/pom.xml
@@ -0,0 +1,69 @@
+
+
+
+
+
+ 4.0.0
+
+ org.apache.maven.plugins.pmd.it
+ MPMD-277-multi-module-check-parent
+ 1.0-SNAPSHOT
+ pom
+
+
+ UTF-8
+ 1.8
+ 1.8
+
+
+
+ module-a
+ module-b
+
+
+
+
+
+
+ @project.groupId@
+ @project.artifactId@
+ @project.version@
+
+ true
+ true
+
+
+
+
+ check
+
+
+
+
+
+
+
+
+ @project.groupId@
+ @project.artifactId@
+
+
+
+
diff --git a/src/it/MPMD-277-multi-module-check/ruleset.xml b/src/it/MPMD-277-multi-module-check/ruleset.xml
new file mode 100644
index 00000000..004e68ad
--- /dev/null
+++ b/src/it/MPMD-277-multi-module-check/ruleset.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+ Custom Ruleset for test case MPMD-277
+
+
+
+
diff --git a/src/it/MPMD-277-multi-module-check/verify.groovy b/src/it/MPMD-277-multi-module-check/verify.groovy
new file mode 100644
index 00000000..ac95dd70
--- /dev/null
+++ b/src/it/MPMD-277-multi-module-check/verify.groovy
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+File pmdXml = new File( basedir, "target/pmd.xml" )
+assert pmdXml.exists()
+assert !pmdXml.text.contains( "Avoid unused private methods such as 'doSomething(IModuleA)'." )
+assert !pmdXml.text.contains( "Avoid unused private methods such as 'aPrivateMethod(FieldElement)'." )
diff --git a/src/main/java/org/apache/maven/plugins/pmd/PmdReport.java b/src/main/java/org/apache/maven/plugins/pmd/PmdReport.java
index 0e2fcd22..054af566 100644
--- a/src/main/java/org/apache/maven/plugins/pmd/PmdReport.java
+++ b/src/main/java/org/apache/maven/plugins/pmd/PmdReport.java
@@ -45,7 +45,10 @@
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuildingRequest;
import org.apache.maven.reporting.MavenReportException;
+import org.apache.maven.shared.artifact.filter.resolve.AndFilter;
+import org.apache.maven.shared.artifact.filter.resolve.ExclusionsFilter;
import org.apache.maven.shared.artifact.filter.resolve.ScopeFilter;
+import org.apache.maven.shared.artifact.filter.resolve.TransformableFilter;
import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResult;
import org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolver;
import org.codehaus.plexus.resource.ResourceManager;
@@ -721,24 +724,49 @@ private void configureTypeResolution( PMDConfiguration configuration ) throws Ma
{
List dependencies = new ArrayList<>();
+ // collect exclusions for projects within the reactor
+ // if module a depends on module b and both are in the reactor
+ // then we don't want to resolve the dependency as an artifact.
+ List exclusionPatterns = new ArrayList<>();
for ( MavenProject localProject : reactorProjects )
{
- // Add the project's target folder first
- classpath.addAll( includeTests ? localProject.getTestClasspathElements()
- : localProject.getCompileClasspathElements() );
+ exclusionPatterns.add( localProject.getGroupId() + ":" + localProject.getArtifactId() );
+ }
+ TransformableFilter filter = new AndFilter( Arrays.asList(
+ new ExclusionsFilter( exclusionPatterns ),
+ includeTests ? ScopeFilter.including( "test" ) : ScopeFilter.including( "compile" )
+ ) );
+ for ( MavenProject localProject : reactorProjects )
+ {
ProjectBuildingRequest buildingRequest = new DefaultProjectBuildingRequest(
session.getProjectBuildingRequest() );
Iterable resolvedDependencies = dependencyResolver.resolveDependencies(
- buildingRequest, localProject.getModel(),
- includeTests ? ScopeFilter.including( "test" ) : ScopeFilter.including( "compile" ) );
+ buildingRequest, localProject.getModel(), filter );
for ( ArtifactResult resolvedArtifact : resolvedDependencies )
{
dependencies.add( resolvedArtifact.getArtifact().getFile().toString() );
}
+ List projectCompileClasspath = includeTests ? localProject.getTestClasspathElements()
+ : localProject.getCompileClasspathElements();
+ // Add the project's target folder first
+ classpath.addAll( projectCompileClasspath );
+ if ( !localProject.isExecutionRoot() )
+ {
+ for ( String path : projectCompileClasspath )
+ {
+ File pathFile = new File( path );
+ if ( !pathFile.exists() || pathFile.list().length == 0 )
+ {
+ getLog().warn( "The project " + localProject.getArtifactId()
+ + " does not seem to be compiled. PMD results might be inaccurate." );
+ }
+ }
+ }
+
}
// Add the dependencies as last entries
diff --git a/src/site/fml/faq.fml b/src/site/fml/faq.fml
index e9f80c05..658a1544 100644
--- a/src/site/fml/faq.fml
+++ b/src/site/fml/faq.fml
@@ -99,5 +99,34 @@ under the License.
+
+
+ What does the warning "The project xyz does not seem to be compiled. PMD results might be inaccurate." mean?
+
+
+
+ In order to improve PMD's results, type resolution should be used. It is enabled by default
+ (property typeResolution) and helps to avoid false positive
+ findings by matching the exact types of method parameters or variables.
+
+
+ However, this requires that the project is built first, so that not only the project's dependencies
+ can be used for type resolution, but also the project's classes as well.
+
+
+ When using the property aggregate, this is problematic: With
+ aggregate=true, PMD is executed at the root of a multi-module project before the individual
+ modules are built. Then the types of the individual projects are not available, which might lead to
+ false positive findings e.g. for the rule "UnusedPrivateMethod".
+ If this might be the case, then the warning "The project xyz does not seem
+ to be compiled. PMD results might be inaccurate" is issued.
+
+
+ In order to use type resolution and aggregate together, maven needs to be execute in two passes:
+ First pass will compile the projects (e.g. mvn clean package
) and the second pass
+ will execute PMD without clean via the verify phase (e.g. mvn verify
).
+
+
+
\ No newline at end of file