Fixes generics, only creates one constructor, adds some tests, adds java compatibility options, rework some classes, fixes some problems
This commit is contained in:
@@ -1,20 +0,0 @@
|
||||
package com.github.gtache.fxml.compiler;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Factory for creating controllers
|
||||
*
|
||||
* @param <T> The type of the controller
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ControllerFactory<T> {
|
||||
|
||||
/**
|
||||
* Creates a controller
|
||||
*
|
||||
* @param fieldMap The assignment of field name to value
|
||||
* @return The created controller
|
||||
*/
|
||||
T create(final Map<String, Object> fieldMap);
|
||||
}
|
||||
@@ -28,5 +28,5 @@ public interface ControllerFieldInfo {
|
||||
*
|
||||
* @return The generic types as a list, empty if not generic or raw
|
||||
*/
|
||||
List<String> genericTypes();
|
||||
List<GenericTypes> genericTypes();
|
||||
}
|
||||
|
||||
@@ -7,10 +7,17 @@ import java.util.Map;
|
||||
*/
|
||||
public interface ControllerInfo {
|
||||
|
||||
/**
|
||||
* Returns the controller class name
|
||||
*
|
||||
* @return The name
|
||||
*/
|
||||
String className();
|
||||
|
||||
/**
|
||||
* Returns a mapping of event handler method name -> boolean
|
||||
*
|
||||
* @return A mapping of method name to true if the method has an argument
|
||||
* @return A mapping of method name to true if the method has an argument (event handler may not have an argument)
|
||||
*/
|
||||
Map<String, Boolean> handlerHasArgument();
|
||||
|
||||
@@ -18,7 +25,7 @@ public interface ControllerInfo {
|
||||
* Returns whether the given event handler method has an argument
|
||||
*
|
||||
* @param methodName The method name
|
||||
* @return A mapping of method name to true if the method has an event
|
||||
* @return True if the method has an argument
|
||||
*/
|
||||
default boolean handlerHasArgument(final String methodName) {
|
||||
return handlerHasArgument().getOrDefault(methodName, true);
|
||||
@@ -40,4 +47,11 @@ public interface ControllerInfo {
|
||||
default ControllerFieldInfo fieldInfo(final String property) {
|
||||
return fieldInfo().get(property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the controller has an initialize method
|
||||
*
|
||||
* @return True if the controller has an initialize method
|
||||
*/
|
||||
boolean hasInitialize();
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
package com.github.gtache.fxml.compiler;
|
||||
|
||||
/**
|
||||
* Represents a controller injection to use for generated code
|
||||
*/
|
||||
public interface ControllerInjection {
|
||||
|
||||
/**
|
||||
* Returns the injection type of class fields
|
||||
*
|
||||
* @return The injection type for fields
|
||||
*/
|
||||
InjectionType fieldInjectionType();
|
||||
|
||||
/**
|
||||
* Returns the injection type for event handlers methods
|
||||
*
|
||||
* @return The injection type for event handlers
|
||||
*/
|
||||
InjectionType methodInjectionType();
|
||||
|
||||
/**
|
||||
* The name of the controller class
|
||||
*
|
||||
* @return The class
|
||||
*/
|
||||
String injectionClass();
|
||||
}
|
||||
@@ -6,7 +6,7 @@ package com.github.gtache.fxml.compiler;
|
||||
public class GenerationException extends Exception {
|
||||
|
||||
/**
|
||||
* Instantiates a new GenerationException
|
||||
* Instantiates a new exception
|
||||
*
|
||||
* @param message The message
|
||||
*/
|
||||
@@ -15,7 +15,7 @@ public class GenerationException extends Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new GenerationException
|
||||
* Instantiates a new exception
|
||||
*
|
||||
* @param message The message
|
||||
* @param cause The cause
|
||||
@@ -25,7 +25,7 @@ public class GenerationException extends Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new GenerationException
|
||||
* Instantiates a new exception
|
||||
*
|
||||
* @param cause The cause
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.github.gtache.fxml.compiler;
|
||||
|
||||
import com.github.gtache.fxml.compiler.compatibility.GenerationCompatibility;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -8,31 +10,52 @@ import java.util.Map;
|
||||
public interface GenerationParameters {
|
||||
|
||||
/**
|
||||
* Returns the mapping of controller class name to controller injection
|
||||
* Returns the compatibility information
|
||||
*
|
||||
* @return The mapping
|
||||
* @return The compatibility
|
||||
*/
|
||||
Map<String, ControllerInjection> controllerInjections();
|
||||
GenerationCompatibility compatibility();
|
||||
|
||||
/**
|
||||
* Returns the mapping of fx:include source to generated class name
|
||||
* Returns whether to use Image InputStream constructor instead of the String (url) one.
|
||||
* This allows avoiding opening some packages with JPMS
|
||||
*
|
||||
* @return The mapping
|
||||
* @return True if the constructor should be used
|
||||
*/
|
||||
Map<String, String> sourceToGeneratedClassName();
|
||||
|
||||
boolean useImageInputStreamConstructor();
|
||||
|
||||
/**
|
||||
* Returns the mapping of fx:include source to controller class name
|
||||
* Returns the mapping of controller class to resource bundle path (in case of GET-BUNDLE injection)
|
||||
*
|
||||
* @return The mapping
|
||||
* @return The map
|
||||
*/
|
||||
Map<String, String> sourceToControllerName();
|
||||
Map<String, String> bundleMap();
|
||||
|
||||
/**
|
||||
* Returns the resource bundle injection to use
|
||||
* Returns the controller injection to use
|
||||
*
|
||||
* @return The injection
|
||||
*/
|
||||
ResourceBundleInjection resourceBundleInjection();
|
||||
InjectionType controllerInjectionType();
|
||||
|
||||
/**
|
||||
* Returns the field injection to use
|
||||
*
|
||||
* @return The injection
|
||||
*/
|
||||
InjectionType fieldInjectionType();
|
||||
|
||||
/**
|
||||
* Returns the method injection to use
|
||||
*
|
||||
* @return The injection
|
||||
*/
|
||||
InjectionType methodInjectionType();
|
||||
|
||||
/**
|
||||
* Returns the resource injection to use
|
||||
*
|
||||
* @return The injection
|
||||
*/
|
||||
InjectionType resourceInjectionType();
|
||||
}
|
||||
|
||||
@@ -21,6 +21,13 @@ public interface GenerationRequest {
|
||||
*/
|
||||
GenerationParameters parameters();
|
||||
|
||||
/**
|
||||
* Returns the info about the main source file
|
||||
*
|
||||
* @return The info
|
||||
*/
|
||||
SourceInfo sourceInfo();
|
||||
|
||||
/**
|
||||
* Returns the object to generate code for
|
||||
*
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.github.gtache.fxml.compiler;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents generic types for a field
|
||||
*/
|
||||
public interface GenericTypes {
|
||||
|
||||
/**
|
||||
* Returns the name of the type
|
||||
*
|
||||
* @return The name
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* Returns the possible subtypes of the type
|
||||
*
|
||||
* @return The list of subtypes, empty if no subtypes
|
||||
*/
|
||||
List<GenericTypes> subTypes();
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package com.github.gtache.fxml.compiler;
|
||||
|
||||
/**
|
||||
* Represents a controller injection to use for generated code
|
||||
*/
|
||||
public interface ResourceBundleInjection {
|
||||
|
||||
/**
|
||||
* Returns the injection type for the resource bundle
|
||||
*
|
||||
* @return The injection type
|
||||
*/
|
||||
InjectionType injectionType();
|
||||
|
||||
/**
|
||||
* Returns the resource bundle name
|
||||
*
|
||||
* @return The path
|
||||
*/
|
||||
String bundleName();
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.github.gtache.fxml.compiler;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Info about a source file
|
||||
*/
|
||||
public interface SourceInfo {
|
||||
|
||||
/**
|
||||
* Returns the generated view class name
|
||||
*
|
||||
* @return The class name
|
||||
*/
|
||||
String generatedClassName();
|
||||
|
||||
/**
|
||||
* Returns the controller class name
|
||||
*
|
||||
* @return The class name
|
||||
*/
|
||||
String controllerClassName();
|
||||
|
||||
/**
|
||||
* Returns the source file
|
||||
*
|
||||
* @return The file
|
||||
*/
|
||||
Path sourceFile();
|
||||
|
||||
/**
|
||||
* Returns the included sources.
|
||||
* Note that there can be multiple times the same source.
|
||||
*
|
||||
* @return The sources
|
||||
*/
|
||||
List<SourceInfo> includedSources();
|
||||
|
||||
/**
|
||||
* Returns the mapping of source value to source info
|
||||
*
|
||||
* @return The mapping
|
||||
*/
|
||||
Map<String, SourceInfo> sourceToSourceInfo();
|
||||
|
||||
/**
|
||||
* Returns whether the source or its children requires a resource bundle
|
||||
*
|
||||
* @return True if the subtree requires a resource bundle
|
||||
*/
|
||||
boolean requiresResourceBundle();
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.github.gtache.fxml.compiler.compatibility;
|
||||
|
||||
/**
|
||||
* Compatibility information for generated code
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface GenerationCompatibility {
|
||||
|
||||
/**
|
||||
* Returns the minimum supported Java version
|
||||
*
|
||||
* @return The version
|
||||
*/
|
||||
int javaVersion();
|
||||
|
||||
/**
|
||||
* Returns whether to use var for object declaration
|
||||
*
|
||||
* @return True if var should be used
|
||||
*/
|
||||
default boolean useVar() {
|
||||
return javaVersion() >= 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of list collector to use
|
||||
*
|
||||
* @return The collector
|
||||
*/
|
||||
default ListCollector listCollector() {
|
||||
if (javaVersion() >= 16) {
|
||||
return ListCollector.TO_LIST;
|
||||
} else if (javaVersion() >= 10) {
|
||||
return ListCollector.COLLECT_TO_UNMODIFIABLE_LIST;
|
||||
} else {
|
||||
return ListCollector.COLLECT_TO_LIST;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether to use List.of() (or Set.of() etc.) instead of Arrays.asList()
|
||||
*
|
||||
* @return True if List.of() should be used
|
||||
*/
|
||||
default boolean useCollectionsOf() {
|
||||
return javaVersion() >= 9;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether to use getFirst() or get(0)
|
||||
*
|
||||
* @return True if getFirst() should be used
|
||||
*/
|
||||
default boolean useGetFirst() {
|
||||
return javaVersion() >= 21;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.github.gtache.fxml.compiler.compatibility;
|
||||
|
||||
/**
|
||||
* Type of list collector to use for generated code
|
||||
*/
|
||||
public enum ListCollector {
|
||||
|
||||
/**
|
||||
* Use .toList()
|
||||
*/
|
||||
TO_LIST,
|
||||
|
||||
/**
|
||||
* Use .collect(Collectors.toUnmodifiableList())
|
||||
*/
|
||||
COLLECT_TO_UNMODIFIABLE_LIST,
|
||||
|
||||
/**
|
||||
* Use .collect(Collectors.toList())
|
||||
*/
|
||||
COLLECT_TO_LIST
|
||||
}
|
||||
@@ -6,7 +6,7 @@ package com.github.gtache.fxml.compiler.parsing;
|
||||
public class ParseException extends Exception {
|
||||
|
||||
/**
|
||||
* Instantiates a new ParseException
|
||||
* Instantiates a new exception
|
||||
*
|
||||
* @param message The message
|
||||
*/
|
||||
@@ -15,7 +15,7 @@ public class ParseException extends Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new ParseException
|
||||
* Instantiates a new exception
|
||||
*
|
||||
* @param message The message
|
||||
* @param cause The cause
|
||||
@@ -25,7 +25,7 @@ public class ParseException extends Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new ParseException
|
||||
* Instantiates a new exception
|
||||
*
|
||||
* @param cause The cause
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.github.gtache.fxml.compiler.parsing;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.SequencedCollection;
|
||||
import java.util.SequencedMap;
|
||||
@@ -10,30 +11,18 @@ import java.util.SequencedMap;
|
||||
@FunctionalInterface
|
||||
public interface ParsedDefine extends ParsedObject {
|
||||
|
||||
/**
|
||||
* Returns the object defined by this fx:define
|
||||
*
|
||||
* @return The object
|
||||
*/
|
||||
ParsedObject object();
|
||||
|
||||
@Override
|
||||
default String className() {
|
||||
return object().className();
|
||||
return ParsedDefine.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
default Map<String, ParsedProperty> attributes() {
|
||||
return object().attributes();
|
||||
return Map.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
default SequencedMap<ParsedProperty, SequencedCollection<ParsedObject>> properties() {
|
||||
return object().properties();
|
||||
}
|
||||
|
||||
@Override
|
||||
default SequencedCollection<ParsedObject> children() {
|
||||
return object().children();
|
||||
return new LinkedHashMap<>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,8 @@ public interface ParsedFactory extends ParsedObject {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the arguments for the factory
|
||||
* Returns the arguments for the factory.
|
||||
* Different from {@link ParsedObject#children()} (in practice, children should only contain fx:define)
|
||||
*
|
||||
* @return The arguments
|
||||
*/
|
||||
|
||||
@@ -10,7 +10,7 @@ import java.util.SequencedMap;
|
||||
public interface ParsedObject {
|
||||
|
||||
/**
|
||||
* The type of the object
|
||||
* Returns the type of the object
|
||||
*
|
||||
* @return The class name
|
||||
*/
|
||||
|
||||
@@ -21,7 +21,7 @@ public interface ParsedText extends ParsedObject {
|
||||
|
||||
@Override
|
||||
default String className() {
|
||||
return "java.lang.String";
|
||||
return String.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
*/
|
||||
module com.github.gtache.fxml.compiler.api {
|
||||
exports com.github.gtache.fxml.compiler;
|
||||
exports com.github.gtache.fxml.compiler.compatibility;
|
||||
exports com.github.gtache.fxml.compiler.parsing;
|
||||
}
|
||||
@@ -6,8 +6,7 @@ import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
class TestControllerFieldInfo {
|
||||
|
||||
@@ -25,7 +24,7 @@ class TestControllerFieldInfo {
|
||||
|
||||
@Test
|
||||
void testIsGenericTrue() {
|
||||
when(info.genericTypes()).thenReturn(List.of("A", "B", "C"));
|
||||
when(info.genericTypes()).thenReturn(List.of(mock(GenericTypes.class)));
|
||||
assertTrue(info.isGeneric());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.github.gtache.fxml.compiler.compatibility;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class TestGenerationCompatibility {
|
||||
|
||||
private final GenerationCompatibility compatibility;
|
||||
|
||||
TestGenerationCompatibility() {
|
||||
this.compatibility = spy(GenerationCompatibility.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUseVar() {
|
||||
when(compatibility.javaVersion()).thenReturn(10);
|
||||
assertTrue(compatibility.useVar());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDontUseVar() {
|
||||
when(compatibility.javaVersion()).thenReturn(9);
|
||||
assertFalse(compatibility.useVar());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testToListCollector() {
|
||||
when(compatibility.javaVersion()).thenReturn(16);
|
||||
assertEquals(ListCollector.TO_LIST, compatibility.listCollector());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCollectToUnmodifiableListCollector() {
|
||||
when(compatibility.javaVersion()).thenReturn(15);
|
||||
assertEquals(ListCollector.COLLECT_TO_UNMODIFIABLE_LIST, compatibility.listCollector());
|
||||
when(compatibility.javaVersion()).thenReturn(10);
|
||||
assertEquals(ListCollector.COLLECT_TO_UNMODIFIABLE_LIST, compatibility.listCollector());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCollectToListCollector() {
|
||||
when(compatibility.javaVersion()).thenReturn(9);
|
||||
assertEquals(ListCollector.COLLECT_TO_LIST, compatibility.listCollector());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUseCollectionsOf() {
|
||||
when(compatibility.javaVersion()).thenReturn(9);
|
||||
assertTrue(compatibility.useCollectionsOf());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDontUseCollectionsOf() {
|
||||
when(compatibility.javaVersion()).thenReturn(8);
|
||||
assertFalse(compatibility.useCollectionsOf());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUseGetFirst() {
|
||||
when(compatibility.javaVersion()).thenReturn(21);
|
||||
assertTrue(compatibility.useGetFirst());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDontUseGetFirst() {
|
||||
when(compatibility.javaVersion()).thenReturn(20);
|
||||
assertFalse(compatibility.useGetFirst());
|
||||
}
|
||||
}
|
||||
@@ -1,80 +1,34 @@
|
||||
package com.github.gtache.fxml.compiler.parsing;
|
||||
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
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.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.SequencedCollection;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class TestParsedDefine {
|
||||
|
||||
private final ParsedProperty property;
|
||||
private final ParsedObject object;
|
||||
private final String string;
|
||||
private final ParsedDefine define;
|
||||
|
||||
TestParsedDefine(@Mock final ParsedProperty property, @Mock final ParsedObject object) {
|
||||
this.property = requireNonNull(property);
|
||||
this.object = requireNonNull(object);
|
||||
this.string = "str/ing";
|
||||
TestParsedDefine() {
|
||||
this.define = spy(ParsedDefine.class);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
when(property.value()).thenReturn(string);
|
||||
when(define.object()).thenReturn(object);
|
||||
when(object.className()).thenReturn(string);
|
||||
when(object.children()).thenReturn(List.of(define));
|
||||
final var map = new LinkedHashMap<ParsedProperty, SequencedCollection<ParsedObject>>();
|
||||
map.put(property, List.of(object));
|
||||
when(object.properties()).thenReturn(map);
|
||||
when(object.attributes()).thenReturn(Map.of(string, property));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testObject() {
|
||||
assertEquals(object, define.object());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testClassName() {
|
||||
assertEquals(string, define.className());
|
||||
verify(define).object();
|
||||
verify(object).className();
|
||||
assertEquals(ParsedDefine.class.getName(), define.className());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAttributes() {
|
||||
assertEquals(Map.of(string, property), define.attributes());
|
||||
verify(define).object();
|
||||
verify(object).attributes();
|
||||
assertEquals(Map.of(), define.attributes());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testProperties() {
|
||||
final var map = new LinkedHashMap<ParsedProperty, SequencedCollection<ParsedObject>>();
|
||||
map.put(property, List.of(object));
|
||||
assertEquals(map, define.properties());
|
||||
verify(define).object();
|
||||
verify(object).properties();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testChildren() {
|
||||
assertEquals(List.of(define), define.children());
|
||||
verify(define).object();
|
||||
verify(object).children();
|
||||
assertEquals(new LinkedHashMap<>(), define.properties());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user