Adds BindingFormatter, ExpressionFormatter, ValueClassGuesser, fixes constructor args matching, fixes factory methods

This commit is contained in:
Guillaume Tâche
2024-12-30 23:22:33 +01:00
parent b5c38bea54
commit c3d9e72e42
32 changed files with 1378 additions and 166 deletions

View File

@@ -22,7 +22,7 @@ import java.util.Set;
*/
public record CompilationInfo(Path inputFile, Path outputFile, String outputClass, Path controllerFile,
String controllerClass, Set<FieldInfo> injectedFields, Set<String> injectedMethods,
Map<String, Path> includes, boolean requiresResourceBundle) {
Map<String, Inclusion> includes, boolean requiresResourceBundle) {
/**
* Instantiates a new info
@@ -62,7 +62,7 @@ public record CompilationInfo(Path inputFile, Path outputFile, String outputClas
private boolean requiresResourceBundle;
private final Set<FieldInfo> injectedFields;
private final Set<String> injectedMethods;
private final Map<String, Path> includes;
private final Map<String, Inclusion> includes;
Builder() {
this.injectedFields = new HashSet<>();
@@ -110,7 +110,14 @@ public record CompilationInfo(Path inputFile, Path outputFile, String outputClas
}
Builder addInclude(final String key, final Path value) {
this.includes.put(key, value);
final var current = includes.get(key);
final Inclusion newInclusion;
if (current == null) {
newInclusion = new Inclusion(value, 1);
} else {
newInclusion = new Inclusion(value, current.count() + 1);
}
this.includes.put(key, newInclusion);
return this;
}

View File

@@ -48,11 +48,11 @@ final class ControllerInfoProvider {
final var name = fieldInfo.name();
final var type = fieldInfo.type();
if (fillFieldInfo(type, name, content, imports, propertyGenericTypes)) {
logger.debug("Found injected field {} of type {} with generic types {} in controller {}", name, type, propertyGenericTypes.get(name), info.controllerFile());
logger.debug("Found injected field {} of type {} with generic types {} in controller {}", name, type, propertyGenericTypes.get(name).genericTypes(), info.controllerFile());
} else if (type.contains(".")) {
final var simpleName = type.substring(type.lastIndexOf('.') + 1);
if (fillFieldInfo(simpleName, name, content, imports, propertyGenericTypes)) {
logger.debug("Found injected field {} of type {} with generic types {} in controller {}", name, simpleName, propertyGenericTypes.get(name), info.controllerFile());
logger.debug("Found injected field {} of type {} with generic types {} in controller {}", name, simpleName, propertyGenericTypes.get(name).genericTypes(), info.controllerFile());
}
} else {
logger.info("Field {}({}) not found in controller {}", name, type, info.controllerFile());

View File

@@ -0,0 +1,28 @@
package com.github.gtache.fxml.compiler.maven.internal;
import java.nio.file.Path;
import java.util.Objects;
/**
* Represents an fx:include info
*
* @param path The path to the included file
* @param count The number of times the file is included
*/
record Inclusion(Path path, int count) {
/**
* Instantiates a new Inclusion
*
* @param path The path to the included file
* @param count The number of times the file is included
* @throws NullPointerException if path is null
* @throws IllegalArgumentException if count < 1
*/
Inclusion {
Objects.requireNonNull(path);
if (count < 1) {
throw new IllegalArgumentException("count must be >= 1");
}
}
}

View File

@@ -5,8 +5,8 @@ import com.github.gtache.fxml.compiler.impl.SourceInfoImpl;
import com.github.gtache.fxml.compiler.maven.FXMLCompilerMojo;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
@@ -31,8 +31,13 @@ final class SourceInfoProvider {
final var includes = info.includes();
final var requiresResourceBundle = info.requiresResourceBundle();
final var includesMapping = new HashMap<String, SourceInfo>();
includes.forEach((k, v) -> includesMapping.put(k, getSourceInfo(mapping.get(v), mapping)));
//FIXME mutliple same includes
return new SourceInfoImpl(outputClass, controllerClass, inputFile, List.copyOf(includesMapping.values()), includesMapping, requiresResourceBundle);
includes.forEach((k, v) -> includesMapping.put(k, getSourceInfo(mapping.get(v.path()), mapping)));
final var includesSources = new ArrayList<SourceInfo>();
includes.forEach((key, value) -> {
for (var i = 0; i < value.count(); ++i) {
includesSources.add(includesMapping.get(key));
}
});
return new SourceInfoImpl(outputClass, controllerClass, inputFile, includesSources, includesMapping, requiresResourceBundle);
}
}

View File

@@ -24,11 +24,11 @@ class TestCompilationInfo {
private final String controllerClass;
private final Set<FieldInfo> injectedFields;
private final Set<String> injectedMethods;
private final Map<String, Path> includes;
private final Map<String, Inclusion> includes;
private final boolean requiresResourceBundle;
private final CompilationInfo info;
TestCompilationInfo(@Mock final Path inputFile, @Mock final Path outputFile, @Mock final Path controllerFile, @Mock final FieldInfo fieldInfo) {
TestCompilationInfo(@Mock final Path inputFile, @Mock final Path outputFile, @Mock final Path controllerFile, @Mock final Inclusion inclusion, @Mock final FieldInfo fieldInfo) {
this.inputFile = Objects.requireNonNull(inputFile);
this.outputFile = Objects.requireNonNull(outputFile);
this.outputClass = "outputClass";
@@ -36,7 +36,7 @@ class TestCompilationInfo {
this.controllerClass = "controllerClass";
this.injectedFields = new HashSet<>(Set.of(fieldInfo));
this.injectedMethods = new HashSet<>(Set.of("one", "two"));
this.includes = new HashMap<>(Map.of("one", Objects.requireNonNull(inputFile)));
this.includes = new HashMap<>(Map.of("one", Objects.requireNonNull(inclusion)));
this.requiresResourceBundle = true;
this.info = new CompilationInfo(inputFile, outputFile, outputClass, controllerFile, controllerClass, injectedFields, injectedMethods, includes, requiresResourceBundle);
}

View File

@@ -21,10 +21,10 @@ class TestCompilationInfoBuilder {
private final String controllerClass;
private final Set<FieldInfo> injectedFields;
private final Set<String> injectedMethods;
private final Map<String, Path> includes;
private final Map<String, Inclusion> includes;
private final CompilationInfo info;
TestCompilationInfoBuilder(@Mock final Path inputFile, @Mock final Path outputFile, @Mock final Path controllerFile, @Mock final FieldInfo fieldInfo) {
TestCompilationInfoBuilder(@Mock final Path inputFile, @Mock final Path outputFile, @Mock final Path controllerFile) {
this.inputFile = Objects.requireNonNull(inputFile);
this.outputFile = Objects.requireNonNull(outputFile);
this.outputClass = "outputClass";
@@ -32,7 +32,7 @@ class TestCompilationInfoBuilder {
this.controllerClass = "controllerClass";
this.injectedFields = Set.of(new FieldInfo("type", "name"));
this.injectedMethods = Set.of("one", "two");
this.includes = Map.of("one", Objects.requireNonNull(inputFile));
this.includes = Map.of("one", new Inclusion(inputFile, 1));
this.info = new CompilationInfo(inputFile, outputFile, outputClass, controllerFile, controllerClass, injectedFields, injectedMethods, includes, true);
}
@@ -47,9 +47,14 @@ class TestCompilationInfoBuilder {
builder.controllerClass(controllerClass);
injectedFields.forEach(f -> builder.addInjectedField(f.name(), f.type()));
injectedMethods.forEach(builder::addInjectedMethod);
includes.forEach(builder::addInclude);
builder.addInclude("one", inputFile);
builder.requiresResourceBundle();
final var actual = builder.build();
assertEquals(info, actual);
builder.addInclude("one", inputFile);
final var newIncludes = Map.of("one", new Inclusion(inputFile, 2));
final var newInfo = new CompilationInfo(inputFile, outputFile, outputClass, controllerFile, controllerClass, injectedFields, injectedMethods, newIncludes, true);
assertEquals(newInfo, builder.build());
}
}

View File

@@ -40,7 +40,7 @@ class TestCompilationInfoProvider {
"com.github.gtache.fxml.compiler.maven.internal.InfoView", controllerPath, controllerClass,
Set.of(new FieldInfo("javafx.event.EventHandler", "onContextMenuRequested"), new FieldInfo("Button", "button"),
new FieldInfo("com.github.gtache.fxml.compiler.maven.internal.IncludeController", "includeViewController")),
Set.of("onAction"), Map.of("includeView.fxml", path.getParent().resolve("includeView.fxml")), true);
Set.of("onAction"), Map.of("includeView.fxml", new Inclusion(path.getParent().resolve("includeView.fxml"), 1)), true);
final var compilationInfoProvider = new CompilationInfoProvider(project, tempDir);
final var actual = compilationInfoProvider.getCompilationInfo(tempDir, path, Map.of(includedPath, "com.github.gtache.fxml.compiler.maven.internal.IncludeController"));
assertEquals(expected, actual);
@@ -115,7 +115,7 @@ class TestCompilationInfoProvider {
"com.github.gtache.fxml.compiler.maven.internal.NoResourceBundle", controllerPath, controllerClass,
Set.of(new FieldInfo("javafx.event.EventHandler", "onContextMenuRequested"), new FieldInfo("Button", "button"),
new FieldInfo("com.github.gtache.fxml.compiler.maven.internal.IncludeController", "includeViewController")),
Set.of("onAction"), Map.of("includeView.fxml", path.getParent().resolve("includeView.fxml")), false);
Set.of("onAction"), Map.of("includeView.fxml", new Inclusion(path.getParent().resolve("includeView.fxml"), 1)), false);
final var compilationInfoProvider = new CompilationInfoProvider(project, tempDir);
final var actual = compilationInfoProvider.getCompilationInfo(tempDir, path, Map.of(includedPath, "com.github.gtache.fxml.compiler.maven.internal.IncludeController"));
assertEquals(expected, actual);

View File

@@ -0,0 +1,38 @@
package com.github.gtache.fxml.compiler.maven.internal;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.nio.file.Path;
import java.util.Objects;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
@ExtendWith(MockitoExtension.class)
class TestInclusion {
private final Path path;
private final int count;
private final Inclusion inclusion;
TestInclusion(@Mock final Path path) {
this.path = Objects.requireNonNull(path);
this.count = 1;
this.inclusion = new Inclusion(path, count);
}
@Test
void testGetters() {
assertEquals(path, inclusion.path());
assertEquals(count, inclusion.count());
}
@Test
void testIllegal() {
assertThrows(NullPointerException.class, () -> new Inclusion(null, count));
assertThrows(IllegalArgumentException.class, () -> new Inclusion(path, 0));
}
}

View File

@@ -23,7 +23,7 @@ class TestSourceInfoProvider {
final var controllerClass = "controllerClass";
final var inputFile = Path.of("inputFile");
final var includeFile = Path.of("includeFile");
final var includes = Map.of("one", includeFile);
final var includes = Map.of("one", new Inclusion(includeFile, 3));
when(compilationInfo.outputClass()).thenReturn(outputClass);
when(compilationInfo.controllerClass()).thenReturn(controllerClass);
when(compilationInfo.inputFile()).thenReturn(inputFile);
@@ -42,7 +42,7 @@ class TestSourceInfoProvider {
final var expectedIncludeSourceInfo = new SourceInfoImpl(includeOutputClass, includeControllerClass, includeInputFile, List.of(), Map.of(), false);
assertEquals(expectedIncludeSourceInfo, SourceInfoProvider.getSourceInfo(includeCompilationInfo, mapping));
final var expected = new SourceInfoImpl(outputClass, controllerClass, inputFile, List.of(expectedIncludeSourceInfo),
final var expected = new SourceInfoImpl(outputClass, controllerClass, inputFile, List.of(expectedIncludeSourceInfo, expectedIncludeSourceInfo, expectedIncludeSourceInfo),
Map.of("one", expectedIncludeSourceInfo), true);
assertEquals(expected, SourceInfoProvider.getSourceInfo(compilationInfo, mapping));
}