diff --git a/src/main/java/spoon/support/compiler/SpoonPom.java b/src/main/java/spoon/support/compiler/SpoonPom.java index 15f9f7edfcb..1b7693c65a1 100644 --- a/src/main/java/spoon/support/compiler/SpoonPom.java +++ b/src/main/java/spoon/support/compiler/SpoonPom.java @@ -35,6 +35,7 @@ import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; @@ -165,9 +166,20 @@ public List getSourceDirectories() { sourcePath = build.getSourceDirectory(); } if (sourcePath == null) { - sourcePath = Paths.get("src/main/java").toString(); + sourcePath = getSourceDirectoryFromParent(getParentPom()); + if (sourcePath == null) { + sourcePath = Paths.get("src/main/java").toString(); + } + } + sourcePath = extractVariable(sourcePath); + Path path = Paths.get(sourcePath); + + String absoluteSourcePath; + if (path.isAbsolute()) { + absoluteSourcePath = path.toString(); + } else { + absoluteSourcePath = Paths.get(directory.getAbsolutePath(), sourcePath).toString(); } - String absoluteSourcePath = Paths.get(directory.getAbsolutePath(), sourcePath).toString(); File source = new File(absoluteSourcePath); if (source.exists()) { output.add(source); @@ -182,6 +194,28 @@ public List getSourceDirectories() { return output; } + /** + * Climbs the pom.xml hierarchy until a model is found in which + * a source directory is declared. + * @return the uninterpolated source directory declared in the nearest ancestor + */ + private String getSourceDirectoryFromParent(SpoonPom parent) { + if (parent == null) { + return null; + } + String sourcePath = null; + Build build = parent.model.getBuild(); + if (build != null) { + sourcePath = build.getSourceDirectory(); + if (sourcePath == null && parent.getParentPom() != null) { + return getSourceDirectoryFromParent(parent.getParentPom()); + } + } else if (parent.getParentPom() != null) { + return getSourceDirectoryFromParent(parent.getParentPom()); + } + return sourcePath; + } + /** * Get the list of test directories of the project * @return the list of test directories @@ -195,9 +229,20 @@ public List getTestDirectories() { sourcePath = build.getTestSourceDirectory(); } if (sourcePath == null) { - sourcePath = Paths.get("src/test/java").toString(); + sourcePath = getTestSourceDirectoryFromParent(getParentPom()); + if (sourcePath == null) { + sourcePath = Paths.get("src/test/java").toString(); + } + } + sourcePath = extractVariable(sourcePath); + Path path = Paths.get(sourcePath); + + String absoluteSourcePath; + if (path.isAbsolute()) { + absoluteSourcePath = path.toString(); + } else { + absoluteSourcePath = Paths.get(directory.getAbsolutePath(), sourcePath).toString(); } - String absoluteSourcePath = Paths.get(directory.getAbsolutePath(), sourcePath).toString(); File source = new File(absoluteSourcePath); if (source.exists()) { output.add(source); @@ -212,6 +257,28 @@ public List getTestDirectories() { return output; } + /** + * Climbs the pom.xml hierarchy until a model is found in which + * a test source directory is declared. + * @return the uninterpolated test source directory declared in the nearest ancestor + */ + private String getTestSourceDirectoryFromParent(SpoonPom parent) { + if (parent == null) { + return null; + } + String sourcePath = null; + Build build = parent.model.getBuild(); + if (build != null) { + sourcePath = build.getTestSourceDirectory(); + if (sourcePath == null && parent.getParentPom() != null) { + return getTestSourceDirectoryFromParent(parent.getParentPom()); + } + } else if (parent.getParentPom() != null) { + return getTestSourceDirectoryFromParent(parent.getParentPom()); + } + return sourcePath; + } + /** * Get the list of classpath files generated by maven * @return the list of classpath files @@ -247,29 +314,31 @@ private String extractVariable(String value) { } /** - * Get the value of a property + * Get the value of a property. Reference: https://maven.apache.org/ref/3.6.3/maven-model-builder/#Model_Interpolation * @param key the key of the property * @return the property value if key exists or null */ private String getProperty(String key) { - if ("project.version".equals(key) || "pom.version".equals(key)) { + if ("project.version".equals(key) || "pom.version".equals(key) || "version".equals(key)) { if (model.getVersion() != null) { return model.getVersion(); } else if (model.getParent() != null) { return model.getParent().getVersion(); } - } else if ("project.groupId".equals(key) || "pom.groupId".equals(key)) { + } else if ("project.groupId".equals(key) || "pom.groupId".equals(key) || "groupId".equals(key)) { if (model.getGroupId() != null) { return model.getGroupId(); } else if (model.getParent() != null) { return model.getParent().getGroupId(); } - } else if ("project.artifactId".equals(key) || "pom.artifactId".equals(key)) { + } else if ("project.artifactId".equals(key) || "pom.artifactId".equals(key) || "artifactId".equals(key)) { if (model.getArtifactId() != null) { return model.getArtifactId(); } else if (model.getParent() != null) { return model.getParent().getArtifactId(); } + } else if ("project.basedir".equals(key) || "pom.basedir".equals(key) || "basedir".equals(key)) { + return pomFile.getParent(); } String value = extractVariable(model.getProperties().getProperty(key)); if (value == null) { diff --git a/src/test/java/spoon/support/compiler/SpoonPomTest.java b/src/test/java/spoon/support/compiler/SpoonPomTest.java index 21bf4919910..b2b57ddb7b0 100644 --- a/src/test/java/spoon/support/compiler/SpoonPomTest.java +++ b/src/test/java/spoon/support/compiler/SpoonPomTest.java @@ -8,6 +8,7 @@ import java.io.IOException; import java.util.List; import java.util.regex.Pattern; +import java.nio.file.Paths; import static org.junit.Assert.*; @@ -51,4 +52,20 @@ public void checkProfilesModules(String path, String[] expected, Pattern profile assertEquals(expected[i], modules.get(i).getName()); } } + + public void getSourceDirectory() throws IOException, XmlPullParserException { + checkSourceDirectory( + "src/test/resources/maven-launcher/hierarchy", + Paths.get("src/test/resources/maven-launcher/hierarchy/child/src").toAbsolutePath().toString() + ); + } + + public void checkSourceDirectory(String path, String expected) throws IOException, XmlPullParserException { + SpoonPom pomModel = new SpoonPom(path, null, MavenLauncher.SOURCE_TYPE.APP_SOURCE, new StandardEnvironment()); + + SpoonPom childModel = pomModel.getModules().get(0); + //contract: source directory is derived from parent pom.xml if not declared in the current + // (childModel) SpoonPom + assertEquals(expected, childModel.getSourceDirectories().get(0).getAbsolutePath()); + } } \ No newline at end of file diff --git a/src/test/resources/maven-launcher/hierarchy/child/pom.xml b/src/test/resources/maven-launcher/hierarchy/child/pom.xml new file mode 100644 index 00000000000..7ca625d0612 --- /dev/null +++ b/src/test/resources/maven-launcher/hierarchy/child/pom.xml @@ -0,0 +1,16 @@ + + + 4.0.0 + + sample.text + parent + 0.0.1-SNAPSHOT + .. + + sample.text + child + 0.0.1-SNAPSHOT + + jar + \ No newline at end of file diff --git a/src/test/resources/maven-launcher/hierarchy/child/src/Test.java b/src/test/resources/maven-launcher/hierarchy/child/src/Test.java new file mode 100644 index 00000000000..6595d2962dd --- /dev/null +++ b/src/test/resources/maven-launcher/hierarchy/child/src/Test.java @@ -0,0 +1,5 @@ +package maven-launcher.hierarchy.child.src; + +public class Test { + +} \ No newline at end of file diff --git a/src/test/resources/maven-launcher/hierarchy/pom.xml b/src/test/resources/maven-launcher/hierarchy/pom.xml new file mode 100644 index 00000000000..26a04bff958 --- /dev/null +++ b/src/test/resources/maven-launcher/hierarchy/pom.xml @@ -0,0 +1,24 @@ + + + 4.0.0 + + sample.text + project + 2.2.2.RELEASE + + + sample.text + parent + 0.0.1-SNAPSHOT + + pom + + + child + + + + ${project.basedir}/src + + \ No newline at end of file