-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
issues/133: part 3 - introduction of ClassFileSelector (#192)
issues/133: part 3 - introduction of ClassFileSelector
- Loading branch information
Showing
36 changed files
with
677 additions
and
430 deletions.
There are no files selected for viewing
136 changes: 136 additions & 0 deletions
136
skippy-core/src/main/java/io/skippy/core/ClassFileSelector.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
/* | ||
* Copyright 2023-2024 the original author or authors. | ||
* | ||
* Licensed 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 | ||
* | ||
* https://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. | ||
*/ | ||
|
||
package io.skippy.core; | ||
|
||
import java.util.List; | ||
|
||
/** | ||
* Strategy to select {@link ClassFile}s from a {@link ClassFileContainer} based on | ||
* | ||
* <ul> | ||
* <li>class name and </li> | ||
* <li>class path.</li> | ||
* </ul> | ||
* | ||
* Why is this needed? The same class name can occur multiple times within a project: | ||
* | ||
* <pre> | ||
* src/main/java/com.example.Foo | ||
* src/test/java/com.example.Foo | ||
* </pre> | ||
* | ||
* The above example will result in multiple entries for the same class name in test-impact-analysis.java: | ||
* | ||
* <pre> | ||
* { | ||
* "classes": { | ||
* "1": { | ||
* "name": "com.example.Foo", | ||
* "path": "com/example/Foo.class", | ||
* "outputFolder": "build/classes/java/integrationTest", | ||
* ... | ||
* } | ||
* "1": { | ||
* "name": "com.example.Foo", | ||
* "path": "com/example/Foo.class", | ||
* "outputFolder": "build/classes/java/test", | ||
* ... | ||
* } | ||
* ] | ||
* } | ||
* </pre> | ||
* | ||
* A {@link ClassFileSelector} can try to map a class name to a single {@link ClassFile} by taking | ||
* the class path into account. | ||
* | ||
* <br /><br /> | ||
* | ||
* Let's consider the classpath to be as follows: | ||
* | ||
* <pre> | ||
* build/classes/java/test | ||
* build/classes/java/main | ||
* build/resources/main | ||
* </pre> | ||
* | ||
* In the above classpath, com.example.Foo can be mapped to | ||
* | ||
* <pre> | ||
* { | ||
* "name": "com.example.Foo", | ||
* "path": "com/example/Foo.class", | ||
* "outputFolder": "build/classes/java/test", | ||
* ... | ||
* } | ||
* </pre> | ||
* | ||
* Now, let's consider the following classpath: | ||
* | ||
* <pre> | ||
* build/classes/java/integrationTest | ||
* build/classes/java/main | ||
* build/resources/main | ||
* </pre> | ||
* | ||
* In this example, com.example.Foo can be mapped to | ||
* | ||
* <pre> | ||
* { | ||
* "name": "com.example.Foo", | ||
* "path": "com/example/Foo.class", | ||
* "outputFolder": "build/classes/java/integrationTest", | ||
* ... | ||
* } | ||
* </pre> | ||
* | ||
* If no exact match is possible, then multiple {@link ClassFile}s can be returned. This is safe, but it might result in | ||
* unnecessary {@link Prediction#EXECUTE} predictions. | ||
* | ||
* <br /><br /> | ||
* | ||
* Custom implementations must have a public no-args constructor. | ||
* They can be registered using Skippy's build plugins. | ||
* | ||
* <br /><br /> | ||
* | ||
* Gradle example: | ||
* <pre> | ||
* skippy { | ||
* ... | ||
* classFileSelector = 'com.example.CustomClassFileSelector' | ||
* } | ||
* </pre> | ||
* | ||
* @author Florian McKee | ||
*/ | ||
public interface ClassFileSelector { | ||
|
||
/** | ||
* Select {@link ClassFile}s from the {@code classFileContainer} based on | ||
* | ||
* <ul> | ||
* <li>{@code className} and </li> | ||
* <li>{@code classPath}.</li> | ||
* </ul> | ||
* @param className a class name (e.g., com.example.Foo) | ||
* @param classFileContainer a {@link ClassFileContainer} | ||
* @param classPath a list of folders within the project's output folders that contribute to the classpath (e.g. build/classes/java/main). | ||
* | ||
* @return all matching {@link ClassFile}s | ||
*/ | ||
List<ClassFile> select(String className, ClassFileContainer classFileContainer, List<String> classPath); | ||
} |
51 changes: 51 additions & 0 deletions
51
skippy-core/src/main/java/io/skippy/core/DefaultClassFileSelector.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package io.skippy.core; | ||
|
||
import java.nio.file.Path; | ||
import java.util.List; | ||
|
||
import static java.util.Collections.emptyList; | ||
|
||
/** | ||
* Default {@link ClassFileSelector} implementation. | ||
* | ||
* @author Florian McKee | ||
*/ | ||
public final class DefaultClassFileSelector implements ClassFileSelector { | ||
|
||
/** | ||
* Comment to make the JavaDoc task happy. | ||
*/ | ||
public DefaultClassFileSelector() { | ||
} | ||
|
||
@Override | ||
public List<ClassFile> select(String className, ClassFileContainer classFileContainer, List<String> classPath) { | ||
|
||
// try to match by class name only | ||
var classFiles = classFileContainer.getIdsByClassName(className).stream().map(classFileContainer::getById).toList(); | ||
|
||
// no match? return nothing | ||
if (classFiles.size() == 0) { | ||
return emptyList(); | ||
} | ||
|
||
// exactly one match? return the match | ||
if (classFiles.size() == 1) { | ||
return List.of(classFiles.get(0)); | ||
} | ||
|
||
// iterate through the classpath folders | ||
for (var classPathEntry : classPath) { | ||
|
||
// check for a match for the given folder | ||
var matchingClassFiles = classFiles.stream().filter(classFile -> classFile.getOutputFolder().equals(Path.of(classPathEntry))).toList(); | ||
|
||
if (matchingClassFiles.size() == 1) { | ||
return List.of(matchingClassFiles.get(0)); | ||
} | ||
} | ||
|
||
// no exact match found: return all candidates (this is safe, but it will result in unnecessary execute predictions) | ||
return classFiles; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
93 changes: 0 additions & 93 deletions
93
skippy-core/src/main/java/io/skippy/core/ParametersFromBuildPlugin.java
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.