JS: add support for Class.getModifiers

This commit is contained in:
Alexey Andreev 2016-10-20 20:02:08 +03:00
parent 4171d468d4
commit 12dded73f6
10 changed files with 65 additions and 35 deletions

View File

@ -89,6 +89,10 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
Set<String> accessibleFields = reflection.getAccessibleFields(className);
ClassReader cls = context.getClassSource().get(className);
if (cls == null) {
return;
}
writer.appendClass(className).append(".$meta.fields").ws().append('=').ws().append('[').indent();
generateCreateMembers(writer, cls.getFields(), field -> {
@ -120,6 +124,10 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
Set<MethodDescriptor> accessibleMethods = reflection.getAccessibleMethods(className);
ClassReader cls = context.getClassSource().get(className);
if (cls == null) {
return;
}
writer.appendClass(className).append(".$meta.methods").ws().append('=').ws().append('[').indent();
generateCreateMembers(writer, cls.getMethods(), method -> {
@ -160,7 +168,8 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
appendProperty(writer, "name", true, () -> writer.append('"')
.append(RenderingUtil.escapeString(member.getName())).append('"'));
appendProperty(writer, "modifiers", false, () -> writer.append(packModifiers(member.readModifiers())));
appendProperty(writer, "modifiers", false, () -> writer.append(
ElementModifier.pack(member.readModifiers())));
appendProperty(writer, "accessLevel", false, () -> writer.append(member.getLevel().ordinal()));
renderer.render(member);
writer.outdent().softNewLine().append("}");
@ -323,18 +332,4 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
private interface MemberRenderer<T extends MemberReader> {
void render(T member) throws IOException;
}
private int packModifiers(Set<ElementModifier> elementModifiers) {
ElementModifier[] knownModifiers = ElementModifier.values();
int value = 0;
int bit = 1;
for (int i = 0; i < knownModifiers.length; ++i) {
ElementModifier modifier = knownModifiers[i];
if (elementModifiers.contains(modifier)) {
value |= bit;
}
bit <<= 1;
}
return value;
}
}

View File

@ -325,6 +325,12 @@ public class TClass<T> extends TObject implements TAnnotatedElement {
}
}
public int getModifiers() {
int flags = platformClass.getMetadata().getFlags();
int accessLevel = platformClass.getMetadata().getAccessLevel();
return Flags.getModifiers(flags, accessLevel);
}
public boolean desiredAssertionStatus() {
return true;
}

View File

@ -19,12 +19,14 @@ import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import org.teavm.model.AccessLevel;
import org.teavm.model.ElementModifier;
public class ClassNode {
private String name;
private String parentName;
private Set<ElementModifier> modifiers = EnumSet.noneOf(ElementModifier.class);
private AccessLevel accessLevel = AccessLevel.PUBLIC;
private List<FieldNode> fields = new ArrayList<>();
private List<MethodNode> methods = new ArrayList<>();
private List<String> interfaces = new ArrayList<>();
@ -57,4 +59,12 @@ public class ClassNode {
public Set<ElementModifier> getModifiers() {
return modifiers;
}
public AccessLevel getAccessLevel() {
return accessLevel;
}
public void setAccessLevel(AccessLevel accessLevel) {
this.accessLevel = accessLevel;
}
}

View File

@ -209,6 +209,7 @@ public class Decompiler {
}
clsNode.getInterfaces().addAll(cls.getInterfaces());
clsNode.getModifiers().addAll(cls.getModifiers());
clsNode.setAccessLevel(cls.getLevel());
return clsNode;
}

View File

@ -467,11 +467,10 @@ public class Renderer implements RenderingManager {
writer.appendClass(iface);
}
writer.append("],").ws();
int flags = 0;
if (cls.getModifiers().contains(ElementModifier.ENUM)) {
flags |= 1;
}
writer.append(flags).append(',').ws();
writer.append(ElementModifier.pack(cls.getModifiers())).append(',').ws();
writer.append(cls.getAccessLevel().ordinal()).append(',').ws();
MethodReader clinit = classSource.get(cls.getName()).getMethod(
new MethodDescriptor("<clinit>", ValueType.VOID));
if (clinit != null) {

View File

@ -92,7 +92,7 @@ public class AstIO {
}
public void write(DataOutput output, RegularMethodNode method) throws IOException {
output.writeInt(packModifiers(method.getModifiers()));
output.writeInt(ElementModifier.pack(method.getModifiers()));
output.writeShort(method.getVariables().size());
for (VariableNode var : method.getVariables()) {
write(output, var);
@ -136,7 +136,7 @@ public class AstIO {
}
public void writeAsync(DataOutput output, AsyncMethodNode method) throws IOException {
output.writeInt(packModifiers(method.getModifiers()));
output.writeInt(ElementModifier.pack(method.getModifiers()));
output.writeShort(method.getVariables().size());
for (VariableNode var : method.getVariables()) {
write(output, var);
@ -167,14 +167,6 @@ public class AstIO {
return node;
}
private int packModifiers(Set<ElementModifier> modifiers) {
int packed = 0;
for (ElementModifier modifier : modifiers) {
packed |= 1 << modifier.ordinal();
}
return packed;
}
private Set<ElementModifier> unpackModifiers(int packed) {
EnumSet<ElementModifier> modifiers = EnumSet.noneOf(ElementModifier.class);
while (packed != 0) {

View File

@ -15,6 +15,8 @@
*/
package org.teavm.model;
import java.util.Set;
/**
* Represents flags for classes and class members.
* @see ElementHolder
@ -37,5 +39,19 @@ public enum ElementModifier {
SYNTHETIC,
TRANSIENT,
VARARGS,
VOLATILE
VOLATILE;
public static int pack(Set<ElementModifier> elementModifiers) {
ElementModifier[] knownModifiers = ElementModifier.values();
int value = 0;
int bit = 1;
for (int i = 0; i < knownModifiers.length; ++i) {
ElementModifier modifier = knownModifiers[i];
if (elementModifiers.contains(modifier)) {
value |= bit;
}
bit <<= 1;
}
return value;
}
}

View File

@ -418,7 +418,7 @@ function $rt_putStderr(ch) {
}
}
function $rt_metadata(data) {
for (var i = 0; i < data.length; i += 7) {
for (var i = 0; i < data.length; i += 8) {
var cls = data[i];
cls.$meta = {};
var m = cls.$meta;
@ -434,15 +434,19 @@ function $rt_metadata(data) {
cls.prototype = {};
}
var flags = data[i + 4];
m.enum = (flags & 1) != 0;
m.enum = (flags & 16) != 0;
m.flags = flags;
m.primitive = false;
m.item = null;
cls.prototype.constructor = cls;
cls.classObject = null;
var clinit = data[i + 5];
m.accessLevel = data[i + 5];
var clinit = data[i + 6];
cls.$clinit = clinit !== 0 ? clinit : function() {};
var virtualMethods = data[i + 6];
var virtualMethods = data[i + 7];
for (var j = 0; j < virtualMethods.length; j += 2) {
var name = virtualMethods[j];
var func = virtualMethods[j + 1];

View File

@ -39,4 +39,7 @@ public interface PlatformClassMetadata extends JSObject {
@JSProperty
int getFlags();
@JSProperty
int getAccessLevel();
}

View File

@ -10,6 +10,10 @@
<root url="file://$MODULE_DIR$/target/generated/js" relative="/" />
<root url="file://$MODULE_DIR$/src/main/webapp" relative="/" />
</webroots>
<sourceRoots>
<root url="file://$MODULE_DIR$/src/main/kotlin" />
<root url="file://$MODULE_DIR$/src/main/resources" />
</sourceRoots>
</configuration>
</facet>
</component>