mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
parent
6788642ea9
commit
c1b3deedff
|
@ -34,6 +34,7 @@ public final class Flags {
|
|||
public static final int TRANSIENT = 4096;
|
||||
public static final int VARARGS = 8192;
|
||||
public static final int VOLATILE = 16384;
|
||||
public static final int INHERITED_ANNOTATION = 32768;
|
||||
|
||||
public static final int PACKAGE_PRIVATE = 0;
|
||||
public static final int PRIVATE = 1;
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
@ -58,6 +59,7 @@ public class TClass<T> extends TObject implements TAnnotatedElement, TType {
|
|||
String canonicalName;
|
||||
private PlatformClass platformClass;
|
||||
private TAnnotation[] annotationsCache;
|
||||
private TAnnotation[] declaredAnnotationsCache;
|
||||
private Map<TClass<?>, TAnnotation> annotationsByType;
|
||||
private TField[] declaredFields;
|
||||
private TField[] fields;
|
||||
|
@ -744,14 +746,33 @@ public class TClass<T> extends TObject implements TAnnotatedElement, TType {
|
|||
@Override
|
||||
public TAnnotation[] getAnnotations() {
|
||||
if (annotationsCache == null) {
|
||||
annotationsCache = (TAnnotation[]) Platform.getAnnotations(getPlatformClass());
|
||||
TClass<?> cls = this;
|
||||
var initial = true;
|
||||
var map = new LinkedHashMap<Class<?>, TAnnotation>();
|
||||
while (cls != null) {
|
||||
for (var annot : cls.getDeclaredAnnotations()) {
|
||||
var platformClass = ((TClass<?>) (Object) annot.annotationType()).platformClass;
|
||||
if (initial || (platformClass.getMetadata().getFlags() & Flags.INHERITED_ANNOTATION) != 0) {
|
||||
map.putIfAbsent(annot.annotationType(), annot);
|
||||
}
|
||||
}
|
||||
cls = cls.getSuperclass();
|
||||
initial = false;
|
||||
}
|
||||
annotationsCache = map.values().toArray(new TAnnotation[0]);
|
||||
}
|
||||
return annotationsCache.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TAnnotation[] getDeclaredAnnotations() {
|
||||
return getAnnotations();
|
||||
if (declaredAnnotationsCache == null) {
|
||||
declaredAnnotationsCache = (TAnnotation[]) Platform.getAnnotations(getPlatformClass());
|
||||
if (declaredAnnotationsCache == null) {
|
||||
declaredAnnotationsCache = new TAnnotation[0];
|
||||
}
|
||||
}
|
||||
return declaredAnnotationsCache.clone();
|
||||
}
|
||||
|
||||
private void ensureAnnotationsByType() {
|
||||
|
|
|
@ -17,6 +17,8 @@ package org.teavm.backend.javascript.rendering;
|
|||
|
||||
import com.carrotsearch.hppc.ObjectIntHashMap;
|
||||
import com.carrotsearch.hppc.ObjectIntMap;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
@ -517,7 +519,16 @@ public class Renderer implements RenderingManager {
|
|||
}
|
||||
writer.append("],").ws();
|
||||
|
||||
writer.append(ElementModifier.pack(cls.readModifiers())).append(',').ws();
|
||||
var flags = ElementModifier.pack(cls.readModifiers());
|
||||
if (cls.hasModifier(ElementModifier.ANNOTATION)) {
|
||||
var retention = cls.getAnnotations().get(Retention.class.getName());
|
||||
if (retention != null && retention.getValue("value").getEnumValue().getFieldName().equals("RUNTIME")) {
|
||||
if (cls.getAnnotations().get(Inherited.class.getName()) != null) {
|
||||
flags |= 32768;
|
||||
}
|
||||
}
|
||||
}
|
||||
writer.append(flags).append(',').ws();
|
||||
writer.append(cls.getLevel().ordinal()).append(',').ws();
|
||||
|
||||
if (!requiredMetadata.enclosingClass() && !requiredMetadata.declaringClass()
|
||||
|
|
|
@ -20,11 +20,12 @@ import static org.junit.Assert.assertEquals;
|
|||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.teavm.junit.SkipPlatform;
|
||||
|
@ -182,9 +183,8 @@ public class ClassTest {
|
|||
@Test
|
||||
@SkipPlatform({TestPlatform.C, TestPlatform.WEBASSEMBLY, TestPlatform.WASI})
|
||||
public void annotationsExposed() {
|
||||
Annotation[] annotations = A.class.getAnnotations();
|
||||
assertEquals(1, annotations.length);
|
||||
assertTrue(TestAnnot.class.isAssignableFrom(annotations[0].getClass()));
|
||||
var annotations = A.class.getAnnotations();
|
||||
assertTrue(Stream.of(annotations).anyMatch(a -> a instanceof TestAnnot));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -225,6 +225,23 @@ public class ClassTest {
|
|||
Set.of(ClassWithInterfaces.class.getInterfaces()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SkipPlatform({TestPlatform.C, TestPlatform.WEBASSEMBLY, TestPlatform.WASI})
|
||||
public void inheritedAnnotation() {
|
||||
assertTrue(A.class.isAnnotationPresent(InheritedAnnot.class));
|
||||
assertTrue(A.class.isAnnotationPresent(TestAnnot.class));
|
||||
assertTrue(ASub.class.isAnnotationPresent(InheritedAnnot.class));
|
||||
assertFalse(ASub.class.isAnnotationPresent(TestAnnot.class));
|
||||
assertTrue(TestInterface1.class.isAnnotationPresent(InheritedAnnot.class));
|
||||
assertFalse(ClassWithInterfaces.class.isAnnotationPresent(InheritedAnnot.class));
|
||||
|
||||
var annotationSet = Set.of(ASub.class.getAnnotations());
|
||||
assertTrue(annotationSet.stream().anyMatch(a -> a instanceof InheritedAnnot));
|
||||
assertFalse(annotationSet.stream().anyMatch(a -> a instanceof TestAnnot));
|
||||
|
||||
assertEquals(0, ASub.class.getDeclaredAnnotations().length);
|
||||
}
|
||||
|
||||
private static class SuperclassWithoutInterfaces {
|
||||
}
|
||||
|
||||
|
@ -232,6 +249,7 @@ public class ClassTest {
|
|||
implements TestInterface1, TestInterface2 {
|
||||
}
|
||||
|
||||
@InheritedAnnot
|
||||
private interface TestInterface1 {
|
||||
}
|
||||
|
||||
|
@ -239,9 +257,13 @@ public class ClassTest {
|
|||
}
|
||||
|
||||
@TestAnnot
|
||||
@InheritedAnnot
|
||||
private static class A {
|
||||
}
|
||||
|
||||
private static class ASub extends A {
|
||||
}
|
||||
|
||||
@AnnotWithDefaultField
|
||||
private static class B {
|
||||
}
|
||||
|
@ -265,6 +287,11 @@ public class ClassTest {
|
|||
int x() default 2;
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@interface InheritedAnnot {
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface AnnotWithVariousFields {
|
||||
boolean a();
|
||||
|
|
Loading…
Reference in New Issue
Block a user