Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parser parity test #984

Merged
merged 36 commits into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
82e2f8b
Delete test
fabapp2 Oct 19, 2023
76ffa0a
Fix comment
fabapp2 Oct 19, 2023
915169c
Delete class
fabapp2 Oct 19, 2023
6f099e6
WIP test
fabapp2 Oct 19, 2023
7dfcc75
Always return MavenSettings
fabapp2 Oct 30, 2023
13a0e0f
Cleanup
fabapp2 Oct 30, 2023
3fff81f
Test parity of given and custom parser
fabapp2 Oct 30, 2023
5f6e5fd
Rename test and add javadoc
fabapp2 Oct 30, 2023
909b83d
Refactor test
fabapp2 Oct 31, 2023
79b8ddf
Set rewrite pom cache dir to user home
fabapp2 Oct 31, 2023
110f0a0
Refactor test
fabapp2 Oct 31, 2023
de647c5
Add missing import
fabapp2 Oct 31, 2023
6b240ba
WIP: hack to add parsed types to classpath
fabapp2 Oct 31, 2023
25785ef
Use version of parent pom when no version is set
fabapp2 Nov 1, 2023
f69a79a
Improve error message
fabapp2 Nov 1, 2023
adc5137
Formatting
fabapp2 Nov 1, 2023
5299623
Fix license header
fabapp2 Nov 1, 2023
0feeb87
Exception handling
fabapp2 Nov 1, 2023
cc20850
Introduce ParserParityTestHelper
fabapp2 Nov 1, 2023
a16b5e1
Introduce ParserParityTestHelper
fabapp2 Nov 1, 2023
a10a33e
Fix copyright
fabapp2 Nov 1, 2023
182789d
Remove duplicate test
fabapp2 Nov 1, 2023
e3b042f
Remove duplicate code
fabapp2 Nov 1, 2023
ff54f04
Only add non-existent elements to test classpath
fabapp2 Nov 1, 2023
416a2c9
Move ParserParityTestHelper to util package
fabapp2 Nov 1, 2023
5d06dae
Organize imports
fabapp2 Nov 1, 2023
a23f58e
Merge TestHelpers
fabapp2 Nov 1, 2023
03d72b6
Disable learning test
fabapp2 Nov 1, 2023
00eb002
Dynamically create path to local M2
fabapp2 Nov 1, 2023
5529f42
Remove printouts
fabapp2 Nov 1, 2023
e931aea
Use ParserParityTestHelper
fabapp2 Nov 1, 2023
db0f377
Remove license check action
fabapp2 Nov 1, 2023
bcb5b24
Change boot version in test
fabapp2 Nov 1, 2023
e453c33
Add comment
fabapp2 Nov 1, 2023
0abcb08
Extracted helper to parse in parallel
fabapp2 Nov 1, 2023
0d27f1b
Fix download error in build
fabapp2 Nov 1, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 0 additions & 14 deletions .github/workflows/check-license-headers.yml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,11 @@ public String getArtifactId() {
return pomModel.getArtifactId();
}

/**
* FIXME: when the version of parent pom is null (inherited by it's parent) the version will be null.
*/
public String getVersion() {
return pomModel.getVersion();
return pomModel.getVersion() == null ? pomModel.getParent().getVersion() : pomModel.getVersion();
}

@Override
Expand Down Expand Up @@ -223,4 +226,8 @@ public Path getModulePath() {
public ProjectId getProjectId() {
return projectId;
}

public Object getProjectEncoding() {
return getPomModel().getProperties().get("project.build.sourceEncoding");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,29 @@
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.openrewrite.ExecutionContext;
import org.openrewrite.FileAttributes;
import org.openrewrite.Parser;
import org.openrewrite.SourceFile;
import org.openrewrite.internal.lang.Nullable;
import org.openrewrite.java.JavaParser;
import org.openrewrite.java.internal.JavaTypeCache;
import org.openrewrite.java.marker.JavaSourceSet;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.JavaType;
import org.openrewrite.marker.Generated;
import org.openrewrite.marker.Marker;
import org.openrewrite.marker.Markers;
import org.openrewrite.xml.tree.Xml;
import org.springframework.core.io.Resource;
import org.springframework.sbm.utils.ResourceUtil;

import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.*;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Expand Down Expand Up @@ -73,7 +76,7 @@ public <T extends SourceFile> UnaryOperator<T> addProvenance(
/**
* Parse Java sources and resources under {@code src/main} of current module.
*/
public List<SourceFile> processMainSources(
public SourceSetParsingResult processMainSources(
Path baseDir,
List<Resource> resources,
Xml.Document moduleBuildFile,
Expand Down Expand Up @@ -116,20 +119,40 @@ public List<SourceFile> processMainSources(
javaParserBuilder.typeCache(typeCache);

Iterable<Parser.Input> inputs = mainJavaSources.stream()
.map(r -> new Parser.Input(ResourceUtil.getPath(r), () -> ResourceUtil.getInputStream(r)))
.map(r -> {
FileAttributes fileAttributes = null;
Path path = ResourceUtil.getPath(r);
boolean isSynthetic = Files.exists(path);
Supplier<InputStream> inputStreamSupplier = () -> ResourceUtil.getInputStream(r);
Parser.Input input = new Parser.Input(path, fileAttributes, inputStreamSupplier, isSynthetic);
return input;
})
.toList();

Stream<? extends SourceFile> cus = Stream.of(javaParserBuilder)
.map(JavaParser.Builder::build)
.flatMap(parser -> parser.parseInputs(inputs, baseDir, executionContext))
.peek(s -> alreadyParsed.add(baseDir.resolve(s.getSourcePath())));
Set<JavaType.FullyQualified> localClassesCp = new HashSet<>();
JavaSourceSet javaSourceSet = sourceSet("main", dependencies, typeCache);
List<? extends SourceFile> cus = javaParserBuilder.build()
.parseInputs(inputs, baseDir, executionContext)
.peek(s -> {
((J.CompilationUnit)s).getClasses()
.stream()
.map(J.ClassDeclaration::getType)
.forEach(localClassesCp::add);

alreadyParsed.add(baseDir.resolve(s.getSourcePath()));
})
.toList();

// TODO: This is a hack:
// Parsed java sources are not themselves on the classpath (here).
// The actual parsing happens when the stream is terminated (toList),
// therefore the toList() must be called before the parsed compilation units can be added to the classpath
List<Marker> mainProjectProvenance = new ArrayList<>(provenanceMarkers);
mainProjectProvenance.add(sourceSet("main", dependencies, typeCache));
javaSourceSet = appendToClasspath(localClassesCp, javaSourceSet);
mainProjectProvenance.add(javaSourceSet);

// FIXME: 945 Why target and not all main?
List<Path> parsedJavaPaths = javaSourcesInTarget.stream().map(ResourceUtil::getPath).toList();
Stream<SourceFile> parsedJava = cus.map(addProvenance(baseDir, mainProjectProvenance, parsedJavaPaths));
Stream<SourceFile> parsedJava = cus.stream().map(addProvenance(baseDir, mainProjectProvenance, parsedJavaPaths));
log.debug("[%s] Scanned %d java source files in main scope.".formatted(currentProject, mainJavaSources.size()));

//Filter out any generated source files from the returned list, as we do not want to apply the recipe to the
Expand All @@ -148,7 +171,22 @@ public List<SourceFile> processMainSources(
log.debug("[%s] Scanned %d resource files in main scope.".formatted(currentProject, (alreadyParsed.size() - sourcesParsedBefore)));
// Any resources parsed from "main/resources" should also have the main source set added to them.
sourceFiles.addAll(parsedResourceFiles);
return sourceFiles;
return new SourceSetParsingResult(sourceFiles, javaSourceSet.getClasspath());
}

/**
* Add entries that don't exist in the classpath of {@code javaSourceSet} from {@code appendingClasspath}.
*/
@NotNull
private static JavaSourceSet appendToClasspath(Set<JavaType.FullyQualified> appendingClasspath, JavaSourceSet javaSourceSet) {
List<JavaType.FullyQualified> curCp = javaSourceSet.getClasspath();
appendingClasspath.forEach(f -> {
if(!curCp.contains(f)) {
curCp.add(f);
}
});
javaSourceSet = javaSourceSet.withClasspath(new ArrayList<>(curCp));
return javaSourceSet;
}

@NotNull
Expand All @@ -160,7 +198,7 @@ private static JavaSourceSet sourceSet(String name, List<Path> dependencies, Jav
/**
* Parse Java sources and resource files under {@code src/test}.
*/
public List<SourceFile> processTestSources(
public SourceSetParsingResult processTestSources(
Path baseDir,
Xml.Document moduleBuildFile,
JavaParser.Builder<? extends JavaParser, ?> javaParserBuilder,
Expand All @@ -169,8 +207,8 @@ public List<SourceFile> processTestSources(
Set<Path> alreadyParsed,
ExecutionContext executionContext,
MavenProject currentProject,
List<Resource> resources
) {
List<Resource> resources,
List<JavaType.FullyQualified> classpath) {
log.info("Processing test sources in module '%s'".formatted(currentProject.getProjectId()));

List<Path> testDependencies = currentProject.getTestClasspathElements();
Expand All @@ -186,14 +224,25 @@ public List<SourceFile> processTestSources(
.map(r -> new Parser.Input(ResourceUtil.getPath(r), () -> ResourceUtil.getInputStream(r)))
.toList();

Stream<? extends SourceFile> cus = Stream.of(javaParserBuilder)
.map(JavaParser.Builder::build)
.flatMap(parser -> parser.parseInputs(inputs, baseDir, executionContext));
final List<JavaType.FullyQualified> localClassesCp = new ArrayList<>();
List<? extends SourceFile> cus = javaParserBuilder.build()
.parseInputs(inputs, baseDir, executionContext)
.peek(s -> {
((J.CompilationUnit) s).getClasses()
.stream()
.map(J.ClassDeclaration::getType)
.forEach(localClassesCp::add);
alreadyParsed.add(baseDir.resolve(s.getSourcePath()));
})
.toList();

List<Marker> markers = new ArrayList<>(provenanceMarkers);
markers.add(sourceSet("test", testDependencies, typeCache));

Stream<SourceFile> parsedJava = cus.map(addProvenance(baseDir, markers, null));
JavaSourceSet javaSourceSet = sourceSet("test", testDependencies, typeCache);
Set<JavaType.FullyQualified> curClasspath = Stream.concat(classpath.stream(), localClassesCp.stream()).collect(Collectors.toSet());
javaSourceSet = appendToClasspath(curClasspath, javaSourceSet);
markers.add(javaSourceSet);
Stream<SourceFile> parsedJava = cus.stream().map(addProvenance(baseDir, markers, null));

log.debug("[%s] Scanned %d java source files in test scope.".formatted(currentProject, testJavaSources.size()));
Stream<SourceFile> sourceFiles = parsedJava;
Expand All @@ -205,7 +254,7 @@ public List<SourceFile> processTestSources(
log.debug("[%s] Scanned %d resource files in test scope.".formatted(currentProject, (alreadyParsed.size() - sourcesParsedBefore)));
sourceFiles = Stream.concat(sourceFiles, parsedResourceFiles);
List<SourceFile> result = sourceFiles.toList();
return result;
return new SourceSetParsingResult(result, javaSourceSet.getClasspath());
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,5 @@ private void addSourceFileToModel(Path baseDir, List<MavenProject> sortedProject
.filter(p -> ResourceUtil.getPath(p.getPomFile()).toString().equals(baseDir.resolve(s.getSourcePath()).toString()))
.forEach(p -> p.setSourceFile(s));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.nio.file.Path;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
Expand Down Expand Up @@ -47,7 +48,7 @@ public class ParserProperties {
/**
* Directory used by RocksdbMavenPomCache when pomCacheEnabled is true
*/
private String pomCacheDirectory;
private String pomCacheDirectory = Path.of(System.getProperty("user.home")).resolve(".rewrite-cache").toAbsolutePath().normalize().toString();

/**
* Comma-separated list of patterns used to create PathMatcher
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ private List<Resource> filterIgnoredResources(Path baseDir, Resource[] resources
List<Resource> resultingResources = Stream.of(resources)
.filter(r -> isAccepted(baseDir, r, pathMatchers))
.toList();

if(resultingResources.isEmpty()) {
throw new IllegalArgumentException("No resources were scanned. Check directory and ignore patterns.");
}

return resultingResources;
}

Expand All @@ -101,7 +106,8 @@ private boolean isAccepted(Path baseDir, Resource r, List<PathMatcher> pathMatch
})
.findFirst();
if(isIgnored.isPresent() && log.isInfoEnabled()) {
log.info("Ignoring scanned resource '%s'.".formatted(baseDir.relativize(ResourceUtil.getPath(r))));
Set<String> ignoredPathPatterns = parserProperties.getIgnoredPathPatterns();
log.info("Ignoring scanned resource '%s' given these path matchers: %s.".formatted(baseDir.relativize(ResourceUtil.getPath(r)), ignoredPathPatterns));
}
return isIgnored.isEmpty();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import lombok.extern.slf4j.Slf4j;
import org.openrewrite.ExecutionContext;
import org.openrewrite.maven.MavenExecutionContextView;
import org.openrewrite.maven.cache.*;
import org.openrewrite.maven.utilities.MavenArtifactDownloader;
import org.openrewrite.tree.ParsingEventListener;
Expand Down Expand Up @@ -54,14 +55,6 @@
@Import({ScanScope.class, ScopeConfiguration.class})
public class RewriteParserConfiguration {

@Autowired
private ParserProperties parserProperties;

// @Bean
// ProvenanceMarkerFactory provenanceMarkerFactory(MavenMojoProjectParserFactory projectParserFactory) {
// return new ProvenanceMarkerFactory(projectParserFactory);
// }

@Bean
MavenPasswordDecrypter mavenPasswordDecrypter() {
return new MavenPasswordDecrypter();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import org.openrewrite.ExecutionContext;
import org.openrewrite.SourceFile;
import org.openrewrite.marker.Marker;
import org.openrewrite.maven.MavenExecutionContextView;
import org.openrewrite.maven.MavenSettings;
import org.openrewrite.style.NamedStyles;
import org.openrewrite.tree.ParsingEventListener;
import org.openrewrite.tree.ParsingExecutionContextView;
Expand All @@ -35,6 +37,8 @@
import org.springframework.sbm.parsers.maven.ProvenanceMarkerFactory;
import org.springframework.sbm.scopes.ScanScope;

import java.net.URI;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -117,7 +121,6 @@ public RewriteProjectParsingResult parse(Path givenBaseDir, List<Resource> resou
List<Xml.Document> parsedBuildFiles = buildFileParser.parseBuildFiles(baseDir, parserContext.getBuildFileResources(), parserContext.getActiveProfiles(), executionContext, parserProperties.isSkipMavenParsing(), provenanceMarkers);
parserContext.setParsedBuildFiles(parsedBuildFiles);


log.trace("Start to parse %d source files in %d modules".formatted(resources.size() + parsedBuildFiles.size(), parsedBuildFiles.size()));
List<SourceFile> otherSourceFiles = sourceFileParser.parseOtherSourceFiles(baseDir, parserContext, resources, provenanceMarkers, styles, executionContext);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.sbm.parsers.maven;
package org.springframework.sbm.parsers;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.openrewrite.maven.utilities.MavenArtifactDownloader;
import org.openrewrite.SourceFile;
import org.openrewrite.java.tree.JavaType;

import java.util.List;

/**
* @author Fabian Krüger
*/
@Slf4j
@RequiredArgsConstructor
class MavenMojoProjectParserPrivateMethods {

private final MavenMojoProjectParserFactory mavenMojoProjectParserFactory;
private final MavenArtifactDownloader artifactDownloader;



public record SourceSetParsingResult(List<SourceFile> sourceFiles, List<JavaType.FullyQualified> classpath) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
import org.openrewrite.Parser;
import org.openrewrite.SourceFile;
import org.openrewrite.marker.Marker;
import org.openrewrite.maven.MavenExecutionContextView;
import org.openrewrite.maven.MavenParser;
import org.openrewrite.maven.MavenSettings;
import org.openrewrite.xml.tree.Xml;
import org.springframework.core.io.Resource;
import org.springframework.sbm.utils.ResourceUtil;
Expand All @@ -46,14 +48,14 @@
public class BuildFileParser {

/**
* Parse a list of Maven Pom files to a Map of {@code Path} and their parsed {@link Xml.Document}s.
* The {@link Xml.Document}s are marked with {@link org.openrewrite.maven.tree.MavenResolutionResult} and the provided provenance markers.
* Parse a list of Maven Pom files to a {@code List} of {@link Xml.Document}s.
* The {@link Xml.Document}s get marked with {@link org.openrewrite.maven.tree.MavenResolutionResult} and the provided provenance markers.
*
* @param baseDir the {@link Path} to the root of the scanned project
* @param buildFiles the list of resources for relevant pom files.
* @param activeProfiles teh active Maven profiles
* @param activeProfiles the active Maven profiles
* @param executionContext the ExecutionContext to use
* * @param skipMavenParsing skip parsing Maven files
* @param skipMavenParsing skip parsing Maven files
* @param provenanceMarkers the map of markers to be added
*/
public List<Xml.Document> parseBuildFiles(
Expand Down Expand Up @@ -138,7 +140,10 @@ private Stream<Xml.Document> parsePoms(Path baseDir, List<Resource> pomFiles, Ma
}

private void initializeMavenSettings(ExecutionContext executionContext) {

// FIXME: https://github.com/spring-projects-experimental/spring-boot-migrator/issues/880
String repo = "file://" + Path.of(System.getProperty("user.home")).resolve(".m2/repository") + "/";
MavenSettings mavenSettings = new MavenSettings(repo, null, null, null, null);
MavenExecutionContextView.view(executionContext).setMavenSettings(mavenSettings);
}

public List<Resource> filterAndSortBuildFiles(List<Resource> resources) {
Expand Down
Loading
Loading