Refactored GroowtAntlrPlugin to be much simpler.
This commit is contained in:
parent
b66ecd89b7
commit
f573f1cec4
@ -1,5 +0,0 @@
|
|||||||
package groowt.gradle.antlr;
|
|
||||||
|
|
||||||
import org.gradle.api.plugins.antlr.AntlrTask;
|
|
||||||
|
|
||||||
public class GroowtAntlrAllTask extends AntlrTask {}
|
|
@ -0,0 +1,95 @@
|
|||||||
|
package groowt.gradle.antlr;
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask;
|
||||||
|
import org.gradle.api.artifacts.Configuration;
|
||||||
|
import org.gradle.api.file.DirectoryProperty;
|
||||||
|
import org.gradle.api.file.RegularFileProperty;
|
||||||
|
import org.gradle.api.model.ObjectFactory;
|
||||||
|
import org.gradle.api.provider.Property;
|
||||||
|
import org.gradle.api.provider.Provider;
|
||||||
|
import org.gradle.api.tasks.Input;
|
||||||
|
import org.gradle.api.tasks.InputFile;
|
||||||
|
import org.gradle.api.tasks.OutputDirectory;
|
||||||
|
import org.gradle.api.tasks.TaskAction;
|
||||||
|
import org.gradle.api.tasks.options.Option;
|
||||||
|
import org.gradle.process.ExecOperations;
|
||||||
|
import org.gradle.process.ExecResult;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public class GroowtAntlrExecTask extends DefaultTask {
|
||||||
|
|
||||||
|
private final ExecOperations execOperations;
|
||||||
|
private final Provider<Configuration> configurationProvider;
|
||||||
|
private final RegularFileProperty antlrSourceFile;
|
||||||
|
private final DirectoryProperty outputDirectory;
|
||||||
|
private final Property<String> packageName;
|
||||||
|
private final Property<Boolean> visitor;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public GroowtAntlrExecTask(
|
||||||
|
ObjectFactory objectFactory,
|
||||||
|
ExecOperations execOperations,
|
||||||
|
Provider<Configuration> configurationProvider
|
||||||
|
) {
|
||||||
|
this.execOperations = execOperations;
|
||||||
|
this.configurationProvider = configurationProvider;
|
||||||
|
this.antlrSourceFile = objectFactory.fileProperty();
|
||||||
|
this.outputDirectory = objectFactory.directoryProperty();
|
||||||
|
this.packageName = objectFactory.property(String.class);
|
||||||
|
this.visitor = objectFactory.property(Boolean.class);
|
||||||
|
this.visitor.convention(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@InputFile
|
||||||
|
public RegularFileProperty getAntlrSourceFile() {
|
||||||
|
return this.antlrSourceFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
@OutputDirectory
|
||||||
|
public DirectoryProperty getOutputDirectory() {
|
||||||
|
return this.outputDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Option(option = "packageName", description = "The packageName argument for Antlr.")
|
||||||
|
@Input
|
||||||
|
public Property<String> getPackageName() {
|
||||||
|
return this.packageName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Option(option = "visitor", description = "Whether Antlr should generate visitor classes or not.")
|
||||||
|
@Input
|
||||||
|
public Property<Boolean> getVisitor() {
|
||||||
|
return this.visitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File resolveOutputFile(String name) {
|
||||||
|
return new File(this.outputDirectory.get().getAsFile(), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
public void doGenerate() {
|
||||||
|
final Configuration antlrConfiguration = configurationProvider.get();
|
||||||
|
|
||||||
|
final ExecResult result = this.execOperations.javaexec(javaExecSpec -> {
|
||||||
|
javaExecSpec.classpath(antlrConfiguration);
|
||||||
|
javaExecSpec.getMainClass().set("org.antlr.v4.Tool");
|
||||||
|
|
||||||
|
final String visitorArg = this.visitor.map(isVisitor -> isVisitor ? "-visitor" : "").get();
|
||||||
|
if (!visitorArg.isEmpty()) {
|
||||||
|
javaExecSpec.args(visitorArg);
|
||||||
|
}
|
||||||
|
final String packageNameArg = this.packageName.getOrElse("");
|
||||||
|
if (!packageNameArg.isEmpty()) {
|
||||||
|
javaExecSpec.args("-package", packageNameArg);
|
||||||
|
}
|
||||||
|
javaExecSpec.args("-o", this.outputDirectory.get().getAsFile().toString());
|
||||||
|
|
||||||
|
javaExecSpec.args(this.antlrSourceFile.getAsFile().get().toString());
|
||||||
|
});
|
||||||
|
|
||||||
|
result.assertNormalExitValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,34 +0,0 @@
|
|||||||
package groowt.gradle.antlr;
|
|
||||||
|
|
||||||
import org.gradle.api.Action;
|
|
||||||
import org.gradle.api.model.ObjectFactory;
|
|
||||||
import org.gradle.api.provider.Property;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
public abstract class GroowtAntlrExtension {
|
|
||||||
|
|
||||||
private final SourceSpecContainer sourceSpecs;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public GroowtAntlrExtension(ObjectFactory objectFactory) {
|
|
||||||
this.sourceSpecs = objectFactory.newInstance(SourceSpecContainer.class, (Action<SourceSpec>) sourceSpec -> {
|
|
||||||
sourceSpec.getPackageName().convention(this.getPackageName());
|
|
||||||
sourceSpec.getVisitor().convention(this.getVisitor());
|
|
||||||
sourceSpec.getIsCompileDependency().convention(true);
|
|
||||||
sourceSpec.getDebug().convention(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract Property<String> getPackageName();
|
|
||||||
public abstract Property<Boolean> getVisitor();
|
|
||||||
|
|
||||||
public SourceSpecContainer getSourceSpecs() {
|
|
||||||
return this.sourceSpecs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sourceSpecs(Action<SourceSpecContainer> configure) {
|
|
||||||
configure.execute(this.getSourceSpecs());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,215 +1,75 @@
|
|||||||
package groowt.gradle.antlr;
|
package groowt.gradle.antlr;
|
||||||
|
|
||||||
import org.gradle.api.Action;
|
|
||||||
import org.gradle.api.Plugin;
|
import org.gradle.api.Plugin;
|
||||||
import org.gradle.api.Project;
|
import org.gradle.api.Project;
|
||||||
import org.gradle.api.file.FileTree;
|
|
||||||
import org.gradle.api.model.ObjectFactory;
|
|
||||||
import org.gradle.api.plugins.JavaPluginExtension;
|
import org.gradle.api.plugins.JavaPluginExtension;
|
||||||
import org.gradle.api.plugins.antlr.AntlrPlugin;
|
|
||||||
import org.gradle.api.plugins.antlr.AntlrSourceDirectorySet;
|
|
||||||
import org.gradle.api.plugins.antlr.AntlrTask;
|
|
||||||
import org.gradle.api.provider.Provider;
|
|
||||||
import org.gradle.api.tasks.SourceSet;
|
|
||||||
import org.gradle.api.tasks.TaskContainer;
|
|
||||||
import org.gradle.api.tasks.compile.JavaCompile;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.*;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import static groowt.gradle.antlr.GroowtAntlrUtil.*;
|
|
||||||
|
|
||||||
public final class GroowtAntlrPlugin implements Plugin<Project> {
|
public final class GroowtAntlrPlugin implements Plugin<Project> {
|
||||||
|
|
||||||
public static final String taskGroup = "groowtAntlr";
|
public static final String GROOWT_ANTLR = "groowtAntlr";
|
||||||
|
|
||||||
private static final String packageArg = "-package";
|
|
||||||
private static final String traceArg = "-trace";
|
|
||||||
private static final String visitorArg = "-visitor";
|
|
||||||
|
|
||||||
private final ObjectFactory objectFactory;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public GroowtAntlrPlugin(ObjectFactory objectFactory) {
|
|
||||||
this.objectFactory = objectFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static NullableProviderList<String> getArguments(SourceSpec sourceSpec) {
|
|
||||||
final NullableProviderList<String> arguments = new NullableProviderList<>();
|
|
||||||
arguments.addCollectionProvider(sourceSpec.getPackageName().map(packageName -> List.of(packageArg, packageName)));
|
|
||||||
arguments.addProvider(sourceSpec.getVisitor().map(isVisitor -> isVisitor ? visitorArg : null));
|
|
||||||
arguments.addProvider(sourceSpec.getDebug().map(isDebug -> isDebug ? traceArg : null));
|
|
||||||
return arguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For afterEvaluate!
|
|
||||||
private static List<GroowtAntlrTask> createAndRegister(Project project, GroowtAntlrExtension extension) {
|
|
||||||
final TaskContainer taskContainer = project.getTasks();
|
|
||||||
return extension.getSourceSpecs().stream().map(sourceSpec -> {
|
|
||||||
return taskContainer.create(
|
|
||||||
getGenerateTaskName(sourceSpec),
|
|
||||||
GroowtAntlrTask.class,
|
|
||||||
sourceSpec,
|
|
||||||
(Action<GroowtAntlrTask>) task -> {
|
|
||||||
task.setGroup(taskGroup);
|
|
||||||
task.setArguments(getArguments(sourceSpec));
|
|
||||||
task.setSource(sourceSpec.getResolvedSource().getSourceFile());
|
|
||||||
task.setOutputDirectory(
|
|
||||||
getOutputDirectory(
|
|
||||||
project,
|
|
||||||
sourceSpec.getResolvedSource().getSourceSet(),
|
|
||||||
sourceSpec.getPackageName()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
// For afterEvaluate!
|
|
||||||
private static void addCompileDependencies(Project project, List<GroowtAntlrTask> tasks) {
|
|
||||||
tasks.forEach(task -> {
|
|
||||||
// if it is a compile dependency, add it as input to java source set
|
|
||||||
final var isCompileDependency = task.getSourceSpec().getIsCompileDependency().get();
|
|
||||||
if (isCompileDependency) {
|
|
||||||
project.getTasks().withType(JavaCompile.class).configureEach(javaCompile -> {
|
|
||||||
javaCompile.dependsOn(task);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private record GenerateAllSpec(
|
|
||||||
@Nullable FileTree source,
|
|
||||||
@NotNull List<String> args,
|
|
||||||
@NotNull Provider<String> packageName
|
|
||||||
) {}
|
|
||||||
|
|
||||||
private GenerateAllSpec getBlankGenerateAllSpec() {
|
|
||||||
return new GenerateAllSpec(null, List.of(), this.objectFactory.property(String.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static GenerateAllSpec getGenerateAllSpecFromTask(GroowtAntlrTask task) {
|
|
||||||
return new GenerateAllSpec(task.getSource(), task.getArguments(), task.getSourceSpec().getPackageName());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static @Nullable FileTree combineFileTrees(@Nullable FileTree f0, @Nullable FileTree f1) {
|
|
||||||
if (f0 != null && f1 != null) {
|
|
||||||
return f0.plus(f1);
|
|
||||||
} else if (f0 != null) {
|
|
||||||
return f0;
|
|
||||||
} else {
|
|
||||||
return f1; // null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<String> combineArguments(List<String> a0, List<String> a1) {
|
|
||||||
final List<String> result = new ArrayList<>(a0);
|
|
||||||
final Iterator<String> a1Iter = a1.iterator();
|
|
||||||
while (a1Iter.hasNext()) {
|
|
||||||
final String arg = a1Iter.next();
|
|
||||||
if (arg.equals(packageArg) && result.contains(packageArg)) {
|
|
||||||
if (!a1Iter.hasNext()) {
|
|
||||||
throw new IllegalStateException("shouldn't get here");
|
|
||||||
}
|
|
||||||
final String a0PackageName = result.get(result.indexOf(arg) + 1);
|
|
||||||
final String a1PackageName = a1Iter.next();
|
|
||||||
if (!a0PackageName.equals(a1PackageName)) {
|
|
||||||
throw new IllegalArgumentException("Cannot have separate package arguments for two files from the same source set.");
|
|
||||||
}
|
|
||||||
} else if (!result.contains(arg)) {
|
|
||||||
result.add(arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Provider<String> combinePackageNames(Provider<String> p0, Provider<String> p1) {
|
|
||||||
return p0.zip(p1, (pn0, pn1) -> {
|
|
||||||
if (!pn0.equals(pn1)) {
|
|
||||||
throw new IllegalArgumentException("Cannot have separate package names for two files from the same source set.");
|
|
||||||
}
|
|
||||||
return pn0;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static GenerateAllSpec combineGenerateAllSpecs(GenerateAllSpec s0, GenerateAllSpec s1) {
|
|
||||||
return new GenerateAllSpec(
|
|
||||||
combineFileTrees(s0.source(), s1.source()),
|
|
||||||
combineArguments(s0.args(), s1.args()),
|
|
||||||
combinePackageNames(s0.packageName(), s1.packageName())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// For afterEvaluate!
|
|
||||||
private static void addGenerateAllTasks(Project project, List<GroowtAntlrTask> tasks) {
|
|
||||||
final Map<SourceSet, List<GroowtAntlrTask>> sourceSetToTasks = tasks.stream().collect(Collectors.groupingBy(
|
|
||||||
task -> task.getSourceSpec().getResolvedSource().getSourceSet()
|
|
||||||
));
|
|
||||||
|
|
||||||
final Map<SourceSet, GenerateAllSpec> sourceSetToSpec = new HashMap<>();
|
|
||||||
sourceSetToTasks.forEach((sourceSet, sourceSetTasks) -> {
|
|
||||||
List<GenerateAllSpec> specs = sourceSetTasks.stream().map(task ->
|
|
||||||
new GenerateAllSpec(task.getSource(), task.getArguments(), task.getSourceSpec().getPackageName())
|
|
||||||
).toList();
|
|
||||||
specs.stream().reduce(GroowtAntlrPlugin::combineGenerateAllSpecs).ifPresent(allSpec -> {
|
|
||||||
sourceSetToSpec.put(sourceSet, allSpec);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
sourceSetToSpec.forEach((sourceSet, spec) -> {
|
|
||||||
project.getTasks().register(
|
|
||||||
getGenerateAllTaskName(sourceSet),
|
|
||||||
GroowtAntlrAllTask.class,
|
|
||||||
task -> {
|
|
||||||
task.setGroup(taskGroup);
|
|
||||||
if (spec.source() != null) {
|
|
||||||
task.setSource(spec.source());
|
|
||||||
}
|
|
||||||
task.setArguments(spec.args());
|
|
||||||
task.setOutputDirectory(
|
|
||||||
getOutputDirectory(project, sourceSet, spec.packageName()).get().getAsFile()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void apply(Project project) {
|
public void apply(Project project) {
|
||||||
project.getPluginManager().apply(AntlrPlugin.class);
|
// register configuration
|
||||||
|
final var configurationProvider = project.getConfigurations().register(GROOWT_ANTLR, configuration -> {
|
||||||
// undo the antlr plugin creating its own tasks
|
configuration.setCanBeConsumed(false);
|
||||||
project.getTasks().withType(AntlrTask.class, antlrTask -> {
|
configuration.setCanBeResolved(true);
|
||||||
if (!(antlrTask instanceof GroowtAntlrTask || antlrTask instanceof GroowtAntlrAllTask)) {
|
|
||||||
antlrTask.setEnabled(false);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// create extension
|
// register extension
|
||||||
final GroowtAntlrExtension extension = project.getExtensions().create("groowtAntlr", GroowtAntlrExtension.class);
|
final var extension = project.getExtensions().create(GROOWT_ANTLR, GroowtAntlrSimpleExtension.class);
|
||||||
extension.getPackageName().convention("");
|
|
||||||
extension.getVisitor().convention(false);
|
|
||||||
|
|
||||||
// find all antlr files first and add them to extension
|
// register tasks for each source file
|
||||||
project.getExtensions().getByType(JavaPluginExtension.class).getSourceSets().forEach(sourceSet -> {
|
project.getExtensions().getByType(JavaPluginExtension.class).getSourceSets().forEach(sourceSet -> {
|
||||||
final Set<File> antlrFiles = sourceSet.getExtensions().getByType(AntlrSourceDirectorySet.class).getFiles();
|
// register sourceDirectorySet
|
||||||
for (final File antlrFile : antlrFiles) {
|
final var antlrSourceDirectorySet = project.getObjects().sourceDirectorySet(GROOWT_ANTLR, GROOWT_ANTLR);
|
||||||
if (isAntlrSourceFile(antlrFile)) {
|
antlrSourceDirectorySet.srcDir(
|
||||||
extension.getSourceSpecs().register(sourceSet, antlrFile);
|
String.join(File.separator, "src", sourceSet.getName(), "antlr")
|
||||||
}
|
);
|
||||||
}
|
sourceSet.getAllSource().source(antlrSourceDirectorySet);
|
||||||
});
|
|
||||||
|
|
||||||
// after evaluate, generate tasks for each registered sourceSpec
|
final var baseOutputDir = project.getLayout().getBuildDirectory().dir(String.join(
|
||||||
project.afterEvaluate(postEvaluateProject -> {
|
File.separator,
|
||||||
final List<GroowtAntlrTask> tasks = createAndRegister(postEvaluateProject, extension);
|
"generated-src",
|
||||||
addCompileDependencies(project, tasks);
|
"antlr",
|
||||||
addGenerateAllTasks(project, tasks);
|
sourceSet.getName()
|
||||||
|
));
|
||||||
|
|
||||||
|
sourceSet.getJava().srcDir(baseOutputDir);
|
||||||
|
|
||||||
|
final var sourceSetTasks = antlrSourceDirectorySet.getFiles().stream()
|
||||||
|
.filter(GroowtAntlrUtil::isAntlrFile)
|
||||||
|
.map(file -> {
|
||||||
|
final var taskProvider = project.getTasks().register(
|
||||||
|
GroowtAntlrUtil.getGenerateTaskName(sourceSet, file),
|
||||||
|
GroowtAntlrExecTask.class,
|
||||||
|
configurationProvider
|
||||||
|
);
|
||||||
|
taskProvider.configure(task -> {
|
||||||
|
task.setGroup(GROOWT_ANTLR);
|
||||||
|
task.getAntlrSourceFile().set(file);
|
||||||
|
task.getOutputDirectory().convention(
|
||||||
|
baseOutputDir.flatMap(base -> base.dir(
|
||||||
|
task.getPackageName().map(packageName ->
|
||||||
|
packageName.replace(".", File.separator)
|
||||||
|
)
|
||||||
|
))
|
||||||
|
);
|
||||||
|
task.getVisitor().convention(extension.getVisitor());
|
||||||
|
task.getPackageName().convention(extension.getPackageName());
|
||||||
|
});
|
||||||
|
return taskProvider;
|
||||||
|
})
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
if (!sourceSetTasks.isEmpty()) {
|
||||||
|
project.getTasks().register(sourceSet.getTaskName("generate", "AllAntlr"), task -> {
|
||||||
|
task.dependsOn(sourceSetTasks);
|
||||||
|
task.setGroup(GROOWT_ANTLR);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
package groowt.gradle.antlr;
|
||||||
|
|
||||||
|
import org.gradle.api.provider.Property;
|
||||||
|
|
||||||
|
public interface GroowtAntlrSimpleExtension {
|
||||||
|
Property<String> getPackageName();
|
||||||
|
Property<Boolean> getVisitor();
|
||||||
|
}
|
@ -1,70 +0,0 @@
|
|||||||
package groowt.gradle.antlr;
|
|
||||||
|
|
||||||
import org.gradle.api.Action;
|
|
||||||
import org.gradle.api.file.Directory;
|
|
||||||
import org.gradle.api.file.DirectoryProperty;
|
|
||||||
import org.gradle.api.model.ObjectFactory;
|
|
||||||
import org.gradle.api.plugins.antlr.AntlrTask;
|
|
||||||
import org.gradle.api.provider.Provider;
|
|
||||||
import org.gradle.api.tasks.Internal;
|
|
||||||
import org.gradle.api.tasks.Nested;
|
|
||||||
import org.gradle.api.tasks.OutputDirectory;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class GroowtAntlrTask extends AntlrTask {
|
|
||||||
|
|
||||||
private final ObjectFactory objectFactory;
|
|
||||||
private final SourceSpec sourceSpec;
|
|
||||||
|
|
||||||
private Provider<Directory> outputDirectory;
|
|
||||||
private NullableProviderList<String> arguments;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public GroowtAntlrTask(ObjectFactory objectFactory, SourceSpec sourceSpec, Action<? super GroowtAntlrTask> configure) {
|
|
||||||
this.objectFactory = objectFactory;
|
|
||||||
this.sourceSpec = sourceSpec;
|
|
||||||
configure.execute(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nested
|
|
||||||
public SourceSpec getSourceSpec() {
|
|
||||||
return this.sourceSpec;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull File getOutputDirectory() {
|
|
||||||
return this.outputDirectory.get().getAsFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setOutputDirectory(@NotNull File outputDirectory) {
|
|
||||||
final DirectoryProperty directoryProperty = this.objectFactory.directoryProperty();
|
|
||||||
directoryProperty.set(outputDirectory);
|
|
||||||
this.outputDirectory = directoryProperty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOutputDirectory(Provider<Directory> outputDirectoryProvider) {
|
|
||||||
this.outputDirectory = outputDirectoryProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Internal
|
|
||||||
public @NotNull List<String> getArguments() {
|
|
||||||
return this.arguments.getElements();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setArguments(@NotNull List<String> arguments) {
|
|
||||||
this.arguments = new NullableProviderList<>();
|
|
||||||
this.arguments.addAllElements(arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setArguments(@NotNull NullableProviderList<String> arguments) {
|
|
||||||
this.arguments = arguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,147 +1,35 @@
|
|||||||
package groowt.gradle.antlr;
|
package groowt.gradle.antlr;
|
||||||
|
|
||||||
import org.gradle.api.Project;
|
|
||||||
import org.gradle.api.file.Directory;
|
|
||||||
import org.gradle.api.file.SourceDirectorySet;
|
|
||||||
import org.gradle.api.provider.Provider;
|
|
||||||
import org.gradle.api.tasks.SourceSet;
|
import org.gradle.api.tasks.SourceSet;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public final class GroowtAntlrUtil {
|
public final class GroowtAntlrUtil {
|
||||||
|
|
||||||
public static final List<String> antlrFileExtensions = List.of("g4", "g");
|
public static final List<String> antlrExtensions = List.of("g4", "g");
|
||||||
|
|
||||||
private static final Pattern extensionPattern = Pattern.compile("(?<name>.*)\\.(?<ext>.*)$");
|
private static final Pattern nameAndExtension = Pattern.compile("(?<name>.*)\\.(?<ext>.*)$");
|
||||||
|
|
||||||
public static File resolve(File from, File to) {
|
public static boolean isAntlrFile(File file) {
|
||||||
return from.toPath().resolve(to.toPath()).toFile();
|
for (final var antlrExtension : antlrExtensions) {
|
||||||
|
if (file.getName().endsWith(antlrExtension)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static File relativize(File from, File to) {
|
public static String getGenerateTaskName(SourceSet sourceSet, File sourceFile) {
|
||||||
return from.toPath().relativize(to.toPath()).toFile();
|
final var matcher = nameAndExtension.matcher(sourceFile.getName());
|
||||||
}
|
if (matcher.matches()) {
|
||||||
|
return sourceSet.getTaskName("generate", matcher.group("name"));
|
||||||
public static boolean isAntlrSourceFile(File file) {
|
|
||||||
final var m = extensionPattern.matcher(file.getName());
|
|
||||||
if (m.matches()) {
|
|
||||||
return antlrFileExtensions.contains(m.group("ext"));
|
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Cannot determine extension of file: " + file);
|
throw new IllegalArgumentException("Cannot determine source name for " + sourceFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<String> sourceFileToIdentifierParts(File sourceDir, File sourceFile) {
|
|
||||||
final var relative = getRelativePathToSourceFile(sourceDir, sourceFile);
|
|
||||||
final List<String> result = new ArrayList<>();
|
|
||||||
for (int i = 0; i < relative.getNameCount(); i++) {
|
|
||||||
final var name = relative.getName(i);
|
|
||||||
final var m = extensionPattern.matcher(name.toString());
|
|
||||||
if (m.matches()) {
|
|
||||||
result.add(m.group("name"));
|
|
||||||
} else {
|
|
||||||
result.add(name.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Path getRelativePathToSourceFile(File sourceDir, File sourceFile) {
|
|
||||||
if (!sourceDir.isAbsolute()) {
|
|
||||||
throw new IllegalArgumentException("sourceDir must be absolute, given: " + sourceDir);
|
|
||||||
}
|
|
||||||
if (sourceFile.isAbsolute()) {
|
|
||||||
final var sourceDirPath = sourceDir.toPath();
|
|
||||||
final var sourceFilePath = sourceFile.toPath();
|
|
||||||
return sourceDirPath.relativize(sourceFilePath);
|
|
||||||
} else {
|
|
||||||
return sourceFile.toPath();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getSourceIdentifier(ResolvedSource resolvedSource) {
|
|
||||||
final List<String> parts = new ArrayList<>();
|
|
||||||
if (!resolvedSource.getSourceSet().getName().equals("main")) {
|
|
||||||
parts.add(resolvedSource.getSourceSet().getName());
|
|
||||||
}
|
|
||||||
parts.addAll(sourceFileToIdentifierParts(resolvedSource.getSourceDir(), resolvedSource.getSourceFile()));
|
|
||||||
final List<String> capitalizedParts = parts.stream()
|
|
||||||
.map(part -> {
|
|
||||||
final var first = part.substring(0, 1);
|
|
||||||
final var rest = part.substring(1);
|
|
||||||
return first.toUpperCase() + rest;
|
|
||||||
})
|
|
||||||
.toList();
|
|
||||||
return String.join("", capitalizedParts);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Provider<Directory> getOutputDirectory(
|
|
||||||
Project project,
|
|
||||||
SourceSet sourceSet,
|
|
||||||
Provider<String> packageNameProvider
|
|
||||||
) {
|
|
||||||
return project.getLayout().getBuildDirectory().flatMap(buildDir -> {
|
|
||||||
return buildDir.dir(packageNameProvider.map(packageName -> {
|
|
||||||
return String.join(File.separator, List.of(
|
|
||||||
"generated-src",
|
|
||||||
"antlr",
|
|
||||||
sourceSet.getName(),
|
|
||||||
packageName.replace(".", File.separator)
|
|
||||||
));
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getGenerateTaskName(SourceSpec sourceSpec) {
|
|
||||||
return sourceSpec.getResolvedSource().getSourceSet().getTaskName("generate", sourceSpec.getIdentifier());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getGenerateAllTaskName(SourceSet sourceSet) {
|
|
||||||
return sourceSet.getTaskName("generate", "AllAntlr");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ResolvedSource resolveSource(
|
|
||||||
Project project,
|
|
||||||
SourceSet sourceSet,
|
|
||||||
SourceDirectorySet sourceDirectorySet,
|
|
||||||
File sourceFile
|
|
||||||
) {
|
|
||||||
if (!isAntlrSourceFile(sourceFile)) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"The given source file " + sourceFile + " is not a recognized antlr file (bad extension)."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<File> potentialSrcDirs = new ArrayList<>();
|
|
||||||
|
|
||||||
if (sourceFile.isAbsolute()) {
|
|
||||||
for (final File srcDir : sourceDirectorySet.getSrcDirs()) {
|
|
||||||
if (sourceFile.getPath().startsWith(srcDir.getPath())) {
|
|
||||||
potentialSrcDirs.add(srcDir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (final File srcDir : sourceDirectorySet.getSrcDirs()) {
|
|
||||||
if (resolve(srcDir, sourceFile).exists()) {
|
|
||||||
potentialSrcDirs.add(srcDir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (potentialSrcDirs.size() > 1) {
|
|
||||||
throw new IllegalArgumentException("Multiple source directories in " + sourceDirectorySet.getName() + " contain a source file " + sourceFile);
|
|
||||||
} else if (potentialSrcDirs.isEmpty()) {
|
|
||||||
throw new IllegalArgumentException("No directories in " + sourceDirectorySet.getName() + " contain a source file " + sourceFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
final File srcDir = potentialSrcDirs.getFirst();
|
|
||||||
return new ResolvedSource(project, sourceSet, srcDir, resolve(srcDir, sourceFile));
|
|
||||||
}
|
|
||||||
|
|
||||||
private GroowtAntlrUtil() {}
|
private GroowtAntlrUtil() {}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,160 +0,0 @@
|
|||||||
package groowt.gradle.antlr;
|
|
||||||
|
|
||||||
import org.gradle.api.provider.Provider;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
public final class NullableProviderList<T> {
|
|
||||||
|
|
||||||
private sealed interface Element<T> extends Iterable<T> permits BareElement, ElementProvider, CollectionProvider {
|
|
||||||
boolean isPresent();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class BareElement<T> implements Element<T> {
|
|
||||||
|
|
||||||
private final T element;
|
|
||||||
|
|
||||||
public BareElement(T element) {
|
|
||||||
this.element = element;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isPresent() {
|
|
||||||
return this.element != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Iterator<T> iterator() {
|
|
||||||
return new Iterator<>() {
|
|
||||||
private boolean hasNext = true;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasNext() {
|
|
||||||
return this.hasNext;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T next() {
|
|
||||||
if (!this.hasNext) throw new IllegalStateException();
|
|
||||||
this.hasNext = false;
|
|
||||||
return BareElement.this.element;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class ElementProvider<T> implements Element<T> {
|
|
||||||
|
|
||||||
private final Provider<T> provider;
|
|
||||||
|
|
||||||
public ElementProvider(Provider<T> provider) {
|
|
||||||
this.provider = provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isPresent() {
|
|
||||||
return this.provider.isPresent();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Iterator<T> iterator() {
|
|
||||||
return new Iterator<T>() {
|
|
||||||
private boolean hasNext = true;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasNext() {
|
|
||||||
return this.hasNext;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T next() {
|
|
||||||
if (!this.hasNext) throw new IllegalStateException();
|
|
||||||
this.hasNext = false;
|
|
||||||
return ElementProvider.this.provider.get();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class CollectionProvider<T> implements Element<T> {
|
|
||||||
|
|
||||||
private final Provider<Collection<T>> collectionProvider;
|
|
||||||
|
|
||||||
public CollectionProvider(Provider<Collection<T>> collectionProvider) {
|
|
||||||
this.collectionProvider = collectionProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isPresent() {
|
|
||||||
return this.collectionProvider.isPresent();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Iterator<T> iterator() {
|
|
||||||
return this.collectionProvider.get().iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private final List<Element<T>> elements = new ArrayList<>();
|
|
||||||
|
|
||||||
public void addElement(@Nullable T element) {
|
|
||||||
this.elements.add(new BareElement<>(element));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addProvider(Provider<T> elementProvider) {
|
|
||||||
this.elements.add(new ElementProvider<>(elementProvider));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addCollectionProvider(Provider<Collection<T>> collectionProvider) {
|
|
||||||
this.elements.add(new CollectionProvider<>(collectionProvider));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addAllElements(Collection<T> elements) {
|
|
||||||
for (final T element : elements) {
|
|
||||||
this.elements.add(new BareElement<>(element));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addAllProviders(Collection<Provider<T>> providers) {
|
|
||||||
for (final Provider<T> provider : providers) {
|
|
||||||
this.elements.add(new ElementProvider<>(provider));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addAllCollectionProviders(Collection<Provider<Collection<T>>> collectionProviders) {
|
|
||||||
for (final Provider<Collection<T>> collectionProvider : collectionProviders) {
|
|
||||||
this.elements.add(new CollectionProvider<>(collectionProvider));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<T> getElements() {
|
|
||||||
return this.getElements(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<T> getElements(@Nullable Supplier<T> onNullElement) {
|
|
||||||
final List<T> result = new ArrayList<>();
|
|
||||||
for (final Element<T> element : this.elements) {
|
|
||||||
if (element.isPresent()) {
|
|
||||||
for (final T t : element) {
|
|
||||||
result.add(t);
|
|
||||||
}
|
|
||||||
} else if (onNullElement != null) {
|
|
||||||
result.add(onNullElement.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,90 +0,0 @@
|
|||||||
package groowt.gradle.antlr;
|
|
||||||
|
|
||||||
import org.gradle.api.Project;
|
|
||||||
import org.gradle.api.tasks.InputDirectory;
|
|
||||||
import org.gradle.api.tasks.InputFile;
|
|
||||||
import org.gradle.api.tasks.Internal;
|
|
||||||
import org.gradle.api.tasks.SourceSet;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static groowt.gradle.antlr.GroowtAntlrUtil.relativize;
|
|
||||||
|
|
||||||
public final class ResolvedSource {
|
|
||||||
|
|
||||||
private final Project project;
|
|
||||||
private final SourceSet sourceSet;
|
|
||||||
private final File sourceDir;
|
|
||||||
private final File sourceFile;
|
|
||||||
|
|
||||||
public ResolvedSource(Project project, SourceSet sourceSet, File sourceDir, File sourceFile) {
|
|
||||||
this.project = project;
|
|
||||||
this.sourceSet = sourceSet;
|
|
||||||
this.sourceDir = sourceDir;
|
|
||||||
this.sourceFile = sourceFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Internal
|
|
||||||
public Project getProject() {
|
|
||||||
return this.project;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Internal
|
|
||||||
public SourceSet getSourceSet() {
|
|
||||||
return this.sourceSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
@InputDirectory
|
|
||||||
public File getSourceDir() {
|
|
||||||
return this.sourceDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
@InputFile
|
|
||||||
public File getSourceFile() {
|
|
||||||
return this.sourceFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String relativizeSourceDir() {
|
|
||||||
return relativize(this.project.getProjectDir(), this.sourceDir).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String relativeSourceFile() {
|
|
||||||
return relativize(this.sourceDir, this.sourceFile).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (obj == this) {
|
|
||||||
return true;
|
|
||||||
} else if (obj instanceof ResolvedSource other) {
|
|
||||||
return this.project.equals(other.project)
|
|
||||||
&& this.sourceSet.equals(other.sourceSet)
|
|
||||||
&& this.sourceDir.equals(other.sourceDir)
|
|
||||||
&& this.sourceFile.equals(other.sourceFile);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int result = this.project.hashCode();
|
|
||||||
result = 31 * result + this.sourceSet.hashCode();
|
|
||||||
result = 31 * result + this.sourceDir.hashCode();
|
|
||||||
result = 31 * result + this.sourceFile.hashCode();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "ResolvedSource("
|
|
||||||
+ String.join(", ", List.of(
|
|
||||||
"sourceSet: " + this.sourceSet.getName(),
|
|
||||||
"sourceDir: " + this.relativizeSourceDir(),
|
|
||||||
"sourceFile: " + this.relativeSourceFile()
|
|
||||||
))
|
|
||||||
+ ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
package groowt.gradle.antlr;
|
|
||||||
|
|
||||||
import org.gradle.api.provider.Property;
|
|
||||||
import org.gradle.api.tasks.Input;
|
|
||||||
import org.gradle.api.tasks.Internal;
|
|
||||||
import org.gradle.api.tasks.Nested;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
public abstract class SourceSpec {
|
|
||||||
|
|
||||||
private final String identifier;
|
|
||||||
private final ResolvedSource resolvedSource;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public SourceSpec(String identifier, ResolvedSource resolvedSource) {
|
|
||||||
this.identifier = identifier;
|
|
||||||
this.resolvedSource = resolvedSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Internal
|
|
||||||
public String getIdentifier() {
|
|
||||||
return this.identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nested
|
|
||||||
public ResolvedSource getResolvedSource() {
|
|
||||||
return this.resolvedSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Input
|
|
||||||
public abstract Property<Boolean> getIsCompileDependency();
|
|
||||||
|
|
||||||
@Input
|
|
||||||
public abstract Property<Boolean> getDebug();
|
|
||||||
|
|
||||||
@Input
|
|
||||||
public abstract Property<String> getPackageName();
|
|
||||||
|
|
||||||
@Input
|
|
||||||
public abstract Property<Boolean> getVisitor();
|
|
||||||
|
|
||||||
}
|
|
@ -1,89 +0,0 @@
|
|||||||
package groowt.gradle.antlr;
|
|
||||||
|
|
||||||
import org.gradle.api.Action;
|
|
||||||
import org.gradle.api.Project;
|
|
||||||
import org.gradle.api.internal.CollectionCallbackActionDecorator;
|
|
||||||
import org.gradle.api.internal.DefaultDomainObjectSet;
|
|
||||||
import org.gradle.api.model.ObjectFactory;
|
|
||||||
import org.gradle.api.plugins.antlr.AntlrSourceDirectorySet;
|
|
||||||
import org.gradle.api.tasks.SourceSet;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
import static groowt.gradle.antlr.GroowtAntlrUtil.getSourceIdentifier;
|
|
||||||
import static groowt.gradle.antlr.GroowtAntlrUtil.resolveSource;
|
|
||||||
|
|
||||||
public class SourceSpecContainer extends DefaultDomainObjectSet<SourceSpec> {
|
|
||||||
|
|
||||||
private final Project project;
|
|
||||||
private final ObjectFactory objectFactory;
|
|
||||||
private final Action<SourceSpec> applyConventions;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public SourceSpecContainer(Project project, ObjectFactory objectFactory, Action<SourceSpec> applyConventions) {
|
|
||||||
super(SourceSpec.class, CollectionCallbackActionDecorator.NOOP);
|
|
||||||
this.project = project;
|
|
||||||
this.objectFactory = objectFactory;
|
|
||||||
this.applyConventions = applyConventions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param sourceFilePaths instances of File or String
|
|
||||||
*/
|
|
||||||
public void ignore(SourceSet sourceSet, Object... sourceFilePaths) {
|
|
||||||
for (final Object sourceFilePath : sourceFilePaths) {
|
|
||||||
switch (sourceFilePath) {
|
|
||||||
case File f -> this.ignoreFile(sourceSet, f);
|
|
||||||
case String s -> this.ignoreFile(sourceSet, new File(s));
|
|
||||||
default -> throw new IllegalArgumentException("Can only ignore Files or Strings, given: " + sourceFilePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ignoreFile(SourceSet sourceSet, File target) {
|
|
||||||
this.removeIf(potentialSourceSpec -> {
|
|
||||||
final SourceSet potentialSourceSet = potentialSourceSpec.getResolvedSource().getSourceSet();
|
|
||||||
if (!sourceSet.equals(potentialSourceSet)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
final var antlrSourceDirectorySet = sourceSet.getExtensions().getByType(AntlrSourceDirectorySet.class);
|
|
||||||
final ResolvedSource toIgnore = resolveSource(this.project, sourceSet, antlrSourceDirectorySet, target);
|
|
||||||
final File potentialSourceFile = potentialSourceSpec.getResolvedSource().getSourceFile();
|
|
||||||
return toIgnore.getSourceFile().equals(potentialSourceFile);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void register(SourceSet sourceSet, String sourceFilePath) {
|
|
||||||
this.register(sourceSet, new File(sourceFilePath), sourceSpec -> {}); // no-op action
|
|
||||||
}
|
|
||||||
|
|
||||||
public void register(SourceSet sourceSet, File sourceFile) {
|
|
||||||
this.register(sourceSet, sourceFile, sourceSpec -> {});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void register(SourceSet sourceSet, String sourceFilePath, Action<? super SourceSpec> action) {
|
|
||||||
this.register(sourceSet, new File(sourceFilePath), action);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void register(SourceSet sourceSet, File sourceFile, Action<? super SourceSpec> action) {
|
|
||||||
final var antlrSourceDirectorySet = sourceSet.getExtensions().getByType(AntlrSourceDirectorySet.class);
|
|
||||||
final var resolvedSource = resolveSource(this.project, sourceSet, antlrSourceDirectorySet, sourceFile);
|
|
||||||
|
|
||||||
final String identifier = getSourceIdentifier(resolvedSource);
|
|
||||||
final var specOptional = this.stream().filter(sourceSpec -> sourceSpec.getIdentifier().equals(identifier)).findFirst();
|
|
||||||
|
|
||||||
if (specOptional.isPresent()) {
|
|
||||||
// we already have one, so find and run the action against it
|
|
||||||
final var spec = specOptional.get();
|
|
||||||
action.execute(spec);
|
|
||||||
} else {
|
|
||||||
// create a new one
|
|
||||||
final var spec = this.objectFactory.newInstance(SourceSpec.class, identifier, resolvedSource);
|
|
||||||
this.applyConventions.execute(spec);
|
|
||||||
action.execute(spec);
|
|
||||||
this.add(spec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
//file:noinspection ConfigurationAvoidance
|
|
||||||
package groowt.gradle.antlr
|
|
||||||
|
|
||||||
import org.gradle.api.plugins.JavaPlugin
|
|
||||||
import org.gradle.api.plugins.JavaPluginExtension
|
|
||||||
import org.gradle.api.plugins.antlr.AntlrPlugin
|
|
||||||
import org.gradle.testfixtures.ProjectBuilder
|
|
||||||
import org.junit.jupiter.api.Disabled
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
import org.junit.jupiter.api.function.Executable
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow
|
|
||||||
|
|
||||||
class GroowtAntlrPluginTests {
|
|
||||||
|
|
||||||
@Disabled('TODO: figure out why register(SourceSet, String) is not working.')
|
|
||||||
@Test
|
|
||||||
void smokeScreen() {
|
|
||||||
def projectDir = File.createTempDir()
|
|
||||||
new FileTreeBuilder(projectDir).tap {
|
|
||||||
dir(['src', 'main', 'antlr'].join(File.separator)) {
|
|
||||||
file('MyGrammar.g4') {
|
|
||||||
write("parser grammar MyGrammar;")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
def project = ProjectBuilder.builder().with {
|
|
||||||
withProjectDir(projectDir)
|
|
||||||
build()
|
|
||||||
}
|
|
||||||
|
|
||||||
project.pluginManager.with {
|
|
||||||
apply(JavaPlugin)
|
|
||||||
apply(AntlrPlugin)
|
|
||||||
apply(GroowtAntlrPlugin)
|
|
||||||
}
|
|
||||||
|
|
||||||
def mainSourceSet = project.extensions.getByType(JavaPluginExtension).sourceSets.findByName('main')
|
|
||||||
|
|
||||||
project.extensions.getByType(GroowtAntlrExtension).sourceSpecs.with {
|
|
||||||
register(mainSourceSet, 'MyGrammar.g4')
|
|
||||||
}
|
|
||||||
|
|
||||||
def findTask = {
|
|
||||||
project.tasks.named('generateMyGrammar', GroowtAntlrTask)
|
|
||||||
} as Executable
|
|
||||||
|
|
||||||
assertDoesNotThrow(findTask) {
|
|
||||||
"Could not find task 'generateMyGrammar' (all tasks: ${project.tasks*.name.join(', ')})"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,132 +0,0 @@
|
|||||||
//file:noinspection ConfigurationAvoidance
|
|
||||||
package groowt.gradle.antlr
|
|
||||||
|
|
||||||
import groovy.transform.TupleConstructor
|
|
||||||
import org.gradle.api.plugins.JavaPlugin
|
|
||||||
import org.gradle.api.plugins.JavaPluginExtension
|
|
||||||
import org.gradle.api.plugins.antlr.AntlrPlugin
|
|
||||||
import org.gradle.api.provider.Provider
|
|
||||||
import org.gradle.api.tasks.SourceSet
|
|
||||||
import org.gradle.testfixtures.ProjectBuilder
|
|
||||||
import org.junit.jupiter.api.DynamicTest
|
|
||||||
import org.junit.jupiter.api.TestFactory
|
|
||||||
|
|
||||||
import java.nio.file.Path
|
|
||||||
|
|
||||||
import static groowt.gradle.antlr.GroowtAntlrUtil.*
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertIterableEquals
|
|
||||||
import static org.junit.jupiter.api.DynamicTest.dynamicTest
|
|
||||||
|
|
||||||
class GroowtAntlrUtilTests {
|
|
||||||
|
|
||||||
@TupleConstructor
|
|
||||||
private static class SourceFileToIdentifierTestSpec {
|
|
||||||
File srcDir
|
|
||||||
File srcFile
|
|
||||||
List<String> expected
|
|
||||||
}
|
|
||||||
|
|
||||||
@TestFactory
|
|
||||||
Collection<DynamicTest> sourceFileToIdentifierPartsTests() {
|
|
||||||
def srcDir = File.createTempDir()
|
|
||||||
def getSpec = { String path, List<String> expected ->
|
|
||||||
new SourceFileToIdentifierTestSpec(srcDir, new File(path), expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
def specs = [
|
|
||||||
getSpec('MyGrammar.g4', ['MyGrammar']),
|
|
||||||
getSpec('subDir/MyGrammar.g4', ['subDir', 'MyGrammar']),
|
|
||||||
getSpec('subDir/subSubDir/MyGrammar.g4', ['subDir', 'subSubDir', 'MyGrammar']),
|
|
||||||
getSpec('My.grammar.g4', ['My.grammar'])
|
|
||||||
]
|
|
||||||
|
|
||||||
return specs.collect { spec ->
|
|
||||||
dynamicTest(spec.srcFile.toString()) {
|
|
||||||
def actual = sourceFileToIdentifierParts(spec.srcDir, spec.srcFile)
|
|
||||||
assertIterableEquals(spec.expected, actual) {
|
|
||||||
"Unexpected result: ${actual}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@TestFactory
|
|
||||||
Collection<DynamicTest> getSourceIdentifierTests() {
|
|
||||||
def projectDir = File.createTempDir()
|
|
||||||
File srcDir
|
|
||||||
new FileTreeBuilder(projectDir).with {
|
|
||||||
srcDir = dir(['src', 'main', 'antlr'].join(File.separator))
|
|
||||||
}
|
|
||||||
|
|
||||||
def project = ProjectBuilder.builder()
|
|
||||||
.withProjectDir(projectDir)
|
|
||||||
.build()
|
|
||||||
project.pluginManager.with {
|
|
||||||
apply(JavaPlugin)
|
|
||||||
apply(AntlrPlugin)
|
|
||||||
}
|
|
||||||
def mainSourceSet = project.extensions.getByType(JavaPluginExtension)
|
|
||||||
.sourceSets.getByName('main')
|
|
||||||
|
|
||||||
def getResolvedSource = { String path ->
|
|
||||||
new ResolvedSource(project, mainSourceSet, srcDir, new File(path))
|
|
||||||
}
|
|
||||||
|
|
||||||
Closure<Tuple2<String, ResolvedSource>> getSpec = { String expected, String path ->
|
|
||||||
new Tuple2(expected, getResolvedSource(path))
|
|
||||||
}
|
|
||||||
|
|
||||||
def specs = [
|
|
||||||
getSpec('MyGrammar', 'MyGrammar.g4'),
|
|
||||||
getSpec('SubDirMyGrammar', 'subDir/MyGrammar.g4')
|
|
||||||
]
|
|
||||||
|
|
||||||
return specs.collect { spec ->
|
|
||||||
dynamicTest(spec.v2.sourceFile.toString()) {
|
|
||||||
def actual = getSourceIdentifier(spec.v2)
|
|
||||||
assertEquals(spec.v1, actual)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@TestFactory
|
|
||||||
Collection<DynamicTest> getOutputDirTests() {
|
|
||||||
def project = ProjectBuilder.builder().build()
|
|
||||||
project.pluginManager.tap {
|
|
||||||
apply(JavaPlugin)
|
|
||||||
apply(AntlrPlugin)
|
|
||||||
}
|
|
||||||
project.layout.buildDirectory.set(new File('build'))
|
|
||||||
|
|
||||||
def mainSourceSet = project.extensions.getByType(JavaPluginExtension)
|
|
||||||
.sourceSets.getByName('main')
|
|
||||||
|
|
||||||
Closure<Tuple3<Path, SourceSet, Provider<String>>> getSpec = { String givenPackageName ->
|
|
||||||
def expectedPackagePath = givenPackageName.replace('.', File.separator)
|
|
||||||
def expected = Path.of('build', ['generated-src', 'antlr', mainSourceSet.name, expectedPackagePath] as String[])
|
|
||||||
def packageProperty = project.objects.property(String).tap { set(givenPackageName) }
|
|
||||||
new Tuple3(expected, mainSourceSet, packageProperty)
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Tuple3<Path, SourceSet, Provider<String>>> specs = [
|
|
||||||
getSpec('antlr.one.two.three'), // build/generated-src/antlr/main/antlr/one/two/three
|
|
||||||
getSpec('test.antlr'), // build/generated-src/antlr/main/test/antlr
|
|
||||||
getSpec('antlr'), // build/generated-src/antlr/main/antlr
|
|
||||||
getSpec('') // build/generated-src/antlr/main
|
|
||||||
]
|
|
||||||
|
|
||||||
def projectPath = project.layout.projectDirectory.asFile.toPath()
|
|
||||||
|
|
||||||
return specs.collect { spec ->
|
|
||||||
def givenPackageName = spec.v3.get()
|
|
||||||
dynamicTest(givenPackageName.empty ? '<empty>' : givenPackageName) {
|
|
||||||
def actualPath = getOutputDirectory(project, spec.v2, spec.v3)
|
|
||||||
.get().asFile.toPath()
|
|
||||||
def result = projectPath.relativize(actualPath)
|
|
||||||
assertEquals(spec.v1, result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,11 +1,10 @@
|
|||||||
import groovy.transform.NullCheck
|
import groovy.transform.NullCheck
|
||||||
import groowt.gradle.antlr.GroowtAntlrTask
|
import groowt.gradle.antlr.GroowtAntlrExecTask
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id 'java'
|
id 'java'
|
||||||
id 'java-library'
|
id 'java-library'
|
||||||
id 'groovy'
|
id 'groovy'
|
||||||
id 'antlr'
|
|
||||||
id 'GroowtAntlrPlugin'
|
id 'GroowtAntlrPlugin'
|
||||||
id 'org.jetbrains.kotlin.jvm'
|
id 'org.jetbrains.kotlin.jvm'
|
||||||
id 'java-test-fixtures'
|
id 'java-test-fixtures'
|
||||||
@ -49,7 +48,7 @@ dependencies {
|
|||||||
project(':di'),
|
project(':di'),
|
||||||
project(':extensible')
|
project(':extensible')
|
||||||
)
|
)
|
||||||
antlr libs.antlr
|
groowtAntlr libs.antlr
|
||||||
runtimeOnly libs.log4j.slf4jBinding
|
runtimeOnly libs.log4j.slf4jBinding
|
||||||
|
|
||||||
def testLibs = [
|
def testLibs = [
|
||||||
@ -82,13 +81,10 @@ groowtAntlr {
|
|||||||
visitor = true
|
visitor = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Must be temporarily afterEvaluate unless we switch the GroowtAntlr plugin
|
tasks.named('generateWebViewComponentsLexerBase', GroowtAntlrExecTask) { task ->
|
||||||
// to eagerly create the tasks upon plugin application
|
|
||||||
afterEvaluate {
|
|
||||||
tasks.named('generateWebViewComponentsLexerBase', GroowtAntlrTask) { task ->
|
|
||||||
doLast {
|
doLast {
|
||||||
def pattern = ~/public class WebViewComponentsLexerBase(.*)/
|
def pattern = ~/public class WebViewComponentsLexerBase(.*)/
|
||||||
def lexerSource = new File(task.outputDirectory, 'WebViewComponentsLexerBase.java')
|
def lexerSource = task.resolveOutputFile 'WebViewComponentsLexerBase.java'
|
||||||
def outLines = lexerSource.readLines().collect {
|
def outLines = lexerSource.readLines().collect {
|
||||||
def matcher = pattern.matcher(it)
|
def matcher = pattern.matcher(it)
|
||||||
if (matcher.matches()) {
|
if (matcher.matches()) {
|
||||||
@ -99,7 +95,6 @@ afterEvaluate {
|
|||||||
}
|
}
|
||||||
lexerSource.write(outLines.join('\n'))
|
lexerSource.write(outLines.join('\n'))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register('groovyConsole', JavaExec) {
|
tasks.register('groovyConsole', JavaExec) {
|
||||||
@ -178,11 +173,6 @@ tasks.register('cleanBin', Delete) {
|
|||||||
delete file('bin')
|
delete file('bin')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hacky
|
|
||||||
tasks.named('compileKotlin').configure {
|
|
||||||
dependsOn 'generateLexerFragments', 'generateWebViewComponentsLexerBase', 'generateWebViewComponentsParser'
|
|
||||||
}
|
|
||||||
|
|
||||||
test {
|
test {
|
||||||
jvmArgs '-XX:+EnableDynamicAgentLoading' // for mockito/bytebuddy
|
jvmArgs '-XX:+EnableDynamicAgentLoading' // for mockito/bytebuddy
|
||||||
testLogging.showStandardStreams = true
|
testLogging.showStandardStreams = true
|
||||||
|
Loading…
Reference in New Issue
Block a user