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); Set<String> accessibleFields = reflection.getAccessibleFields(className);
ClassReader cls = context.getClassSource().get(className); ClassReader cls = context.getClassSource().get(className);
if (cls == null) {
return;
}
writer.appendClass(className).append(".$meta.fields").ws().append('=').ws().append('[').indent(); writer.appendClass(className).append(".$meta.fields").ws().append('=').ws().append('[').indent();
generateCreateMembers(writer, cls.getFields(), field -> { generateCreateMembers(writer, cls.getFields(), field -> {
@ -120,6 +124,10 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
Set<MethodDescriptor> accessibleMethods = reflection.getAccessibleMethods(className); Set<MethodDescriptor> accessibleMethods = reflection.getAccessibleMethods(className);
ClassReader cls = context.getClassSource().get(className); ClassReader cls = context.getClassSource().get(className);
if (cls == null) {
return;
}
writer.appendClass(className).append(".$meta.methods").ws().append('=').ws().append('[').indent(); writer.appendClass(className).append(".$meta.methods").ws().append('=').ws().append('[').indent();
generateCreateMembers(writer, cls.getMethods(), method -> { generateCreateMembers(writer, cls.getMethods(), method -> {
@ -160,7 +168,8 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
appendProperty(writer, "name", true, () -> writer.append('"') appendProperty(writer, "name", true, () -> writer.append('"')
.append(RenderingUtil.escapeString(member.getName())).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())); appendProperty(writer, "accessLevel", false, () -> writer.append(member.getLevel().ordinal()));
renderer.render(member); renderer.render(member);
writer.outdent().softNewLine().append("}"); writer.outdent().softNewLine().append("}");
@ -323,18 +332,4 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
private interface MemberRenderer<T extends MemberReader> { private interface MemberRenderer<T extends MemberReader> {
void render(T member) throws IOException; 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() { public boolean desiredAssertionStatus() {
return true; return true;
} }

View File

@ -19,12 +19,14 @@ import java.util.ArrayList;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import org.teavm.model.AccessLevel;
import org.teavm.model.ElementModifier; import org.teavm.model.ElementModifier;
public class ClassNode { public class ClassNode {
private String name; private String name;
private String parentName; private String parentName;
private Set<ElementModifier> modifiers = EnumSet.noneOf(ElementModifier.class); private Set<ElementModifier> modifiers = EnumSet.noneOf(ElementModifier.class);
private AccessLevel accessLevel = AccessLevel.PUBLIC;
private List<FieldNode> fields = new ArrayList<>(); private List<FieldNode> fields = new ArrayList<>();
private List<MethodNode> methods = new ArrayList<>(); private List<MethodNode> methods = new ArrayList<>();
private List<String> interfaces = new ArrayList<>(); private List<String> interfaces = new ArrayList<>();
@ -57,4 +59,12 @@ public class ClassNode {
public Set<ElementModifier> getModifiers() { public Set<ElementModifier> getModifiers() {
return modifiers; 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.getInterfaces().addAll(cls.getInterfaces());
clsNode.getModifiers().addAll(cls.getModifiers()); clsNode.getModifiers().addAll(cls.getModifiers());
clsNode.setAccessLevel(cls.getLevel());
return clsNode; return clsNode;
} }

View File

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

View File

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

View File

@ -15,6 +15,8 @@
*/ */
package org.teavm.model; package org.teavm.model;
import java.util.Set;
/** /**
* Represents flags for classes and class members. * Represents flags for classes and class members.
* @see ElementHolder * @see ElementHolder
@ -37,5 +39,19 @@ public enum ElementModifier {
SYNTHETIC, SYNTHETIC,
TRANSIENT, TRANSIENT,
VARARGS, 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) { 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]; var cls = data[i];
cls.$meta = {}; cls.$meta = {};
var m = cls.$meta; var m = cls.$meta;
@ -434,15 +434,19 @@ function $rt_metadata(data) {
cls.prototype = {}; cls.prototype = {};
} }
var flags = data[i + 4]; var flags = data[i + 4];
m.enum = (flags & 1) != 0; m.enum = (flags & 16) != 0;
m.flags = flags;
m.primitive = false; m.primitive = false;
m.item = null; m.item = null;
cls.prototype.constructor = cls; cls.prototype.constructor = cls;
cls.classObject = null; cls.classObject = null;
var clinit = data[i + 5];
m.accessLevel = data[i + 5];
var clinit = data[i + 6];
cls.$clinit = clinit !== 0 ? clinit : function() {}; 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) { for (var j = 0; j < virtualMethods.length; j += 2) {
var name = virtualMethods[j]; var name = virtualMethods[j];
var func = virtualMethods[j + 1]; var func = virtualMethods[j + 1];

View File

@ -39,4 +39,7 @@ public interface PlatformClassMetadata extends JSObject {
@JSProperty @JSProperty
int getFlags(); 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$/target/generated/js" relative="/" />
<root url="file://$MODULE_DIR$/src/main/webapp" relative="/" /> <root url="file://$MODULE_DIR$/src/main/webapp" relative="/" />
</webroots> </webroots>
<sourceRoots>
<root url="file://$MODULE_DIR$/src/main/kotlin" />
<root url="file://$MODULE_DIR$/src/main/resources" />
</sourceRoots>
</configuration> </configuration>
</facet> </facet>
</component> </component>