Skip to content

Commit

Permalink
Merge pull request #18 from GoodforGod/dev
Browse files Browse the repository at this point in the history
[1.2.0]
  • Loading branch information
GoodforGod authored Feb 25, 2024
2 parents d098c4d + e310a5b commit 01c7f1f
Show file tree
Hide file tree
Showing 32 changed files with 400 additions and 232 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,13 @@ public enum NativeImageOptions {
ENABLE_URL_PROTOCOLS("--enable-url-protocols"),
ALLOW_INCOMPLETE_CLASSPATH("--allow-incomplete-classpath"),
REPORT_UNSUPPORTED("--report-unsupported-elements-at-runtime"),
EXIT_HANDLERS("--install-exit-handlers"),
STATIC("--static"),
STATIC_WITH_DYNAMIC("-H:+StaticExecutableWithDynamicLibC"),
QUICK_BUILD("-Ob"),
MAX_COMPATIBILITY("-march=compatibility"),
MAX_PERFORMANCE("-march=native"),
UNLOCK_EXPERIMENTAL("-H:+UnlockExperimentalVMOptions"),
BUILD_REPORT("-H:+BuildReport"),
USE_LLVM("-H:CompilerBackend=llvm"),
INLINE_BEFORE_ANALYSIS("-H:+InlineBeforeAnalysis"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public int hashCode() {

protected abstract String getFileName();

protected abstract Collection<Access> getGraalAccessForAnnotatedElement(TypeElement element);
protected abstract List<Access> getAccessForElement(TypeElement element);

protected Set<TypeElement> getAnnotatedTypeElements(RoundEnvironment roundEnv) {
final Class[] classes = getSupportedAnnotations().toArray(Class[]::new);
Expand All @@ -77,16 +77,26 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment

try {
final Set<TypeElement> types = getAnnotatedTypeElements(roundEnv);
final List<Access> accesses = types.stream()
.flatMap(element -> getGraalAccessForAnnotatedElement(element).stream())
.distinct()
.sorted()
.collect(Collectors.toList());

final String configJson = getAccessConfigJson(accesses);
final HintOrigin origin = HintUtils.getHintOrigin(roundEnv, processingEnv);
final HintFile file = origin.getFileWithRelativePath(getFileName());
return HintUtils.writeConfigFile(file, configJson, processingEnv);

final Map<HintOrigin, Set<Access>> accessHints = new HashMap<>();
for (TypeElement type : types) {
final List<Access> typeAccesses = getAccessForElement(type);
if (!typeAccesses.isEmpty()) {
final HintOrigin origin = HintUtils.getHintOrigin(type, processingEnv);
final Set<Access> accesses = accessHints.computeIfAbsent(origin, k -> new LinkedHashSet<>());
accesses.addAll(typeAccesses);
}
}

for (var entry : accessHints.entrySet()) {
final String configJson = getAccessConfigJson(entry.getValue());
final HintFile file = entry.getKey().getFileWithRelativePath(getFileName());
if (!HintUtils.writeConfigFile(file, configJson, processingEnv)) {
return false;
}
}

return true;
} catch (Exception e) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, e.getMessage());
e.printStackTrace();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ public Set<String> getSupportedOptions() {
@Override
public SourceVersion getSupportedSourceVersion() {
SourceVersion sourceVersion = SourceVersion.latest();
if (sourceVersion.ordinal() <= 19) {
if (sourceVersion.ordinal() <= 22) {
if (sourceVersion.ordinal() >= 11) {
return sourceVersion;
} else {
return SourceVersion.RELEASE_11;
}
} else {
return SourceVersion.values()[19];
return SourceVersion.values()[22];
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
*
* @author Anton Kurako (GoodforGod)
* @see DynamicProxyHint
* @author Anton Kurako (GoodforGod)
* @since 07.04.2022
*/
final class DynamicProxyHintParser implements OptionParser {
Expand All @@ -34,59 +33,74 @@ public List<String> getInterfaces() {
}
}

private static final class DynamicProxy {

private final List<String> resources = new ArrayList<>();
private final List<String> files = new ArrayList<>();
private final List<Configuration> configurations = new ArrayList<>();
}

@Override
public List<Class<? extends Annotation>> getSupportedAnnotations() {
return List.of(DynamicProxyHint.class);
}

@Override
public List<String> getOptions(RoundEnvironment roundEnv, ProcessingEnvironment processingEnv) {
public List<Option> getOptions(RoundEnvironment roundEnv, ProcessingEnvironment processingEnv) {
final Set<? extends Element> annotated = roundEnv.getElementsAnnotatedWith(DynamicProxyHint.class);
final Set<TypeElement> elements = ElementFilter.typesIn(annotated);
if (elements.isEmpty()) {
return Collections.emptyList();
}

final List<String> resources = elements.stream()
.map(element -> element.getAnnotation(DynamicProxyHint.class))
.flatMap(hint -> Arrays.stream(hint.resources()))
.collect(Collectors.toList());

final List<String> files = elements.stream()
.map(element -> element.getAnnotation(DynamicProxyHint.class))
.flatMap(hint -> Arrays.stream(hint.files()))
.collect(Collectors.toList());

final List<Configuration> configurations = elements.stream()
.map(this::getDynamicProxyConfigurations)
.flatMap(Collection::stream)
.filter(c -> !c.getInterfaces().isEmpty())
.collect(Collectors.toList());

if (!configurations.isEmpty()) {
final String proxyConfigurationFile = configurations.stream()
.map(c -> c.getInterfaces().stream()
.collect(Collectors.joining("\", \"", " { \"interfaces\": [ \"", "\" ] }")))
.collect(Collectors.joining(",\n", "[\n", "\n]"));

final HintOrigin origin = HintUtils.getHintOrigin(roundEnv, processingEnv);
final HintFile file = origin.getFileWithRelativePath("dynamic-proxy-config.json");
HintUtils.writeConfigFile(file, proxyConfigurationFile, processingEnv);
resources.add(file.getPath());
final Map<HintOrigin, DynamicProxy> proxies = new HashMap<>();
for (TypeElement element : elements) {
final List<String> resources = List.of(element.getAnnotation(DynamicProxyHint.class).resources());
final List<String> files = List.of(element.getAnnotation(DynamicProxyHint.class).files());
final List<Configuration> configurations = getDynamicProxyConfigurations(element).stream()
.filter(c -> !c.getInterfaces().isEmpty())
.collect(Collectors.toList());

if (!configurations.isEmpty() || !files.isEmpty() || !resources.isEmpty()) {
final HintOrigin origin = HintUtils.getHintOrigin(element, processingEnv);
final DynamicProxy proxy = proxies.computeIfAbsent(origin, k -> new DynamicProxy());
proxy.files.addAll(files);
proxy.resources.addAll(resources);
proxy.configurations.addAll(configurations);
}
}

final List<String> options = new ArrayList<>();
if (!files.isEmpty()) {
final String proxyFileOption = files.stream()
.collect(Collectors.joining(",", "-H:DynamicProxyConfigurationFiles=", ""));
options.add(proxyFileOption);
}
proxies.forEach((o, p) -> {
if (!p.configurations.isEmpty()) {
final String proxyConfigurationFile = p.configurations.stream()
.map(c -> c.getInterfaces().stream()
.collect(Collectors.joining("\", \"", " { \"interfaces\": [ \"", "\" ] }")))
.collect(Collectors.joining(",\n", "[\n", "\n]"));

final HintOrigin origin = HintUtils.getHintOrigin(elements.iterator().next(), processingEnv);
final HintFile file = origin.getFileWithRelativePath("dynamic-proxy-config.json");
HintUtils.writeConfigFile(file, proxyConfigurationFile, processingEnv);
p.resources.add(file.getPath());
}
});

final List<Option> options = new ArrayList<>();
proxies.forEach((o, p) -> {
final List<String> originOptions = new ArrayList<>();
if (!p.files.isEmpty()) {
final String proxyFileOption = p.files.stream()
.collect(Collectors.joining(",", "-H:DynamicProxyConfigurationFiles=", ""));
originOptions.add(proxyFileOption);
}

if (!resources.isEmpty()) {
final String proxyResourceOption = resources.stream()
.collect(Collectors.joining(",", "-H:DynamicProxyConfigurationResources=", ""));
options.add(proxyResourceOption);
}
if (!p.resources.isEmpty()) {
final String proxyResourceOption = p.resources.stream()
.collect(Collectors.joining(",", "-H:DynamicProxyConfigurationResources=", ""));
originOptions.add(proxyResourceOption);
}

options.add(new Option(o, originOptions));
});

return options;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.goodforgod.graalvm.hint.processor;

import java.util.Objects;

/**
* Hint origin package and artifact where all configs will be generated
*
Expand All @@ -12,7 +14,6 @@ final class HintOrigin {
public static final String HINT_PROCESSING_ARTIFACT = "graalvm.hint.artifact";

static final String DEFAULT_PACKAGE = "io.graalvm.hint";
static final String DEFAULT_ARTIFACT = "hint";

/**
* Artifact group of project
Expand All @@ -30,11 +31,30 @@ final class HintOrigin {
}

public HintFile getFileWithRelativePath(String fileName) {
return new HintFile(fileName, "META-INF/native-image/" + group + "/" + artifact);
return (artifact == null)
? new HintFile(fileName, "META-INF/native-image/" + group)
: new HintFile(fileName, "META-INF/native-image/" + group + "/" + artifact);
}

@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
HintOrigin that = (HintOrigin) o;
return Objects.equals(group, that.group) && Objects.equals(artifact, that.artifact);
}

@Override
public int hashCode() {
return Objects.hash(group, artifact);
}

@Override
public String toString() {
return "[group=" + group + ", artifact=" + artifact + ']';
return (artifact == null)
? "[group=" + group + ']'
: "[group=" + group + ", artifact=" + artifact + ']';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,15 @@ final class HintUtils {

private HintUtils() {}

static HintOrigin getHintOrigin(RoundEnvironment roundEnv, ProcessingEnvironment processingEnv) {
static HintOrigin getHintOrigin(Element element, ProcessingEnvironment processingEnv) {
final Map<String, String> options = processingEnv.getOptions();
final Set<? extends Element> rootElements = roundEnv.getRootElements();
final Element anyElement = rootElements.iterator().next();

final String group = (options.containsKey(HintOrigin.HINT_PROCESSING_GROUP))
? options.get(HintOrigin.HINT_PROCESSING_GROUP)
: getPackage(processingEnv, anyElement);
: getPackage(processingEnv, element);

final String artifact = (options.containsKey(HintOrigin.HINT_PROCESSING_ARTIFACT))
? options.get(HintOrigin.HINT_PROCESSING_ARTIFACT)
: getArtifact(anyElement);
: getArtifact(element);

return new HintOrigin(group, artifact);
}
Expand Down Expand Up @@ -165,6 +162,6 @@ private static String getPackage(ProcessingEnvironment processingEnv, Element el
}

private static String getArtifact(Element element) {
return HintOrigin.DEFAULT_ARTIFACT;
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,37 +62,49 @@ public List<Class<? extends Annotation>> getSupportedAnnotations() {
}

@Override
public List<String> getOptions(RoundEnvironment roundEnv, ProcessingEnvironment processingEnv) {
final Set<TypeElement> elements = HintUtils.getAnnotatedElements(roundEnv, InitializationHint.class,
InitializationHints.class);
public List<Option> getOptions(RoundEnvironment roundEnv, ProcessingEnvironment processingEnv) {
final Set<TypeElement> elements = HintUtils.getAnnotatedElements(roundEnv,
InitializationHint.class, InitializationHints.class);
if (elements.isEmpty()) {
return Collections.emptyList();
}

final Map<InitPhase, List<Initialization>> groupedInitializationOptions = elements.stream()
.flatMap(e -> {
final InitializationHints hints = e.getAnnotation(InitializationHints.class);
if (hints == null) {
final InitializationHint hint = e.getAnnotation(InitializationHint.class);
return getAnnotationPhases(e, hint).stream();
} else {
return getParentAnnotationPhases(e, InitializationHint.class, InitializationHints.class).stream();
}
final Map<HintOrigin, List<Initialization>> inits = new HashMap<>();
for (TypeElement element : elements) {
final List<Initialization> initializations;

final InitializationHints hints = element.getAnnotation(InitializationHints.class);
if (hints == null) {
final InitializationHint hint = element.getAnnotation(InitializationHint.class);
initializations = getAnnotationPhases(element, hint);
} else {
initializations = getParentAnnotationPhases(element, InitializationHint.class, InitializationHints.class);
}

final HintOrigin origin = HintUtils.getHintOrigin(element, processingEnv);
final List<Initialization> value = inits.computeIfAbsent(origin, k -> new ArrayList<>());
value.addAll(initializations);
}

return inits.entrySet().stream()
.map(e -> {
final Map<InitPhase, List<Initialization>> grouped = e.getValue().stream()
.collect(Collectors.groupingBy(i -> i.phase));
final List<String> options = grouped.entrySet().stream()
.map(entry -> entry.getValue().stream()
.sorted()
.map(i -> i.className)
.collect(Collectors.joining(",", getInitializationArgumentName(entry.getKey()), "")))
.sorted()
.collect(Collectors.toList());

return new Option(e.getKey(), options);
})
.distinct()
.collect(Collectors.groupingBy(e -> e.phase));

return groupedInitializationOptions.entrySet().stream()
.map(e -> e.getValue().stream()
.sorted()
.map(i -> i.className)
.collect(Collectors.joining(",", getInitializationArgumentName(e.getKey()), "")))
.sorted()
.collect(Collectors.toList());
}

private static Collection<Initialization> getAnnotationPhases(TypeElement element,
InitializationHint hint) {
private static List<Initialization> getAnnotationPhases(TypeElement element,
InitializationHint hint) {
final InitializationHint.InitPhase phase = hint.value();
final List<String> typeNames = Arrays.asList(hint.typeNames());
final List<String> types = HintUtils.getAnnotationFieldClassNames(element, InitializationHint.class, "types");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ protected String getFileName() {
}

@Override
protected Collection<Access> getGraalAccessForAnnotatedElement(TypeElement element) {
protected List<Access> getAccessForElement(TypeElement element) {
final JniHints hints = element.getAnnotation(JniHints.class);
if (hints == null) {
final JniHint hint = element.getAnnotation(JniHint.class);
Expand All @@ -44,8 +44,8 @@ protected Collection<Access> getGraalAccessForAnnotatedElement(TypeElement eleme
}
}

private static Collection<Access> getAnnotationAccesses(TypeElement element,
JniHint hint) {
private static List<Access> getAnnotationAccesses(TypeElement element,
JniHint hint) {
final ReflectionHint.AccessType[] accessTypes = convert(hint.value());
final List<String> typeNames = Arrays.asList(hint.typeNames());
final List<String> types = HintUtils.getAnnotationFieldClassNames(element, JniHint.class, "types");
Expand Down
Loading

0 comments on commit 01c7f1f

Please sign in to comment.