From 9c83d63c862b173b87e56ed8ee1cec782f2c865e Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Wed, 6 Nov 2013 17:31:08 +0400 Subject: [PATCH] Class components renamer --- .../java/org/teavm/javascript/Renderer.java | 2 +- .../org/teavm/model/AnnotationContainer.java | 6 +- .../model/resource/ClassRefsRenamer.java | 225 ++++++++++++++++++ .../resource/ClasspathResourceMapper.java | 18 ++ 4 files changed, 249 insertions(+), 2 deletions(-) create mode 100644 teavm-core/src/main/java/org/teavm/model/resource/ClassRefsRenamer.java diff --git a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java index 56e8eb843..1bd8fd3b5 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java @@ -230,7 +230,7 @@ public class Renderer implements ExprVisitor, StatementVisitor { public String getParameterName(int index) { return variableName(index); } - }; + } @Override public void visit(AssignmentStatement statement) { diff --git a/teavm-core/src/main/java/org/teavm/model/AnnotationContainer.java b/teavm-core/src/main/java/org/teavm/model/AnnotationContainer.java index fe6bcdba6..fc17e5769 100644 --- a/teavm-core/src/main/java/org/teavm/model/AnnotationContainer.java +++ b/teavm-core/src/main/java/org/teavm/model/AnnotationContainer.java @@ -1,7 +1,7 @@ package org.teavm.model; -import java.util.Map; import java.util.HashMap; +import java.util.Map; /** * @@ -32,4 +32,8 @@ public class AnnotationContainer { public void remove(String type) { annotations.remove(type); } + + public Iterable all() { + return annotations.values(); + } } diff --git a/teavm-core/src/main/java/org/teavm/model/resource/ClassRefsRenamer.java b/teavm-core/src/main/java/org/teavm/model/resource/ClassRefsRenamer.java new file mode 100644 index 000000000..1c78c19ee --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/model/resource/ClassRefsRenamer.java @@ -0,0 +1,225 @@ +package org.teavm.model.resource; + +import java.util.Map; +import org.teavm.codegen.Mapper; +import org.teavm.javascript.ni.Rename; +import org.teavm.model.*; +import org.teavm.model.instructions.*; + +/** + * + * @author Alexey Andreev + */ +class ClassRefsRenamer implements InstructionVisitor { + private Mapper classNameMapper; + + public ClassRefsRenamer(Mapper classNameMapper) { + this.classNameMapper = classNameMapper; + } + + public ClassHolder rename(ClassHolder cls) { + ClassHolder renamedCls = new ClassHolder(classNameMapper.map(cls.getName())); + renamedCls.getModifiers().addAll(cls.getModifiers()); + renamedCls.setLevel(cls.getLevel()); + if (cls != null) { + renamedCls.setParent(classNameMapper.map(cls.getParent())); + } + for (MethodHolder method : cls.getMethods()) { + renamedCls.addMethod(rename(method)); + } + for (FieldHolder field : cls.getFields().toArray(new FieldHolder[0])) { + field.getOwner().removeField(field); + renamedCls.addField(field); + } + rename(cls.getAnnotations(), renamedCls.getAnnotations()); + for (String iface : cls.getInterfaces()) { + renamedCls.getInterfaces().add(classNameMapper.map(iface)); + } + return renamedCls; + } + + public MethodHolder rename(MethodHolder method) { + String methodName = method.getName(); + AnnotationHolder renameAnnot = method.getAnnotations().get(Rename.class.getName()); + if (renameAnnot != null) { + methodName = renameAnnot.getValues().get("value").getString(); + } + ValueType[] signature = method.getSignature(); + for (int i = 0; i < signature.length; ++i) { + signature[i] = rename(signature[i]); + } + MethodHolder renamedMethod = new MethodHolder(methodName, signature); + renamedMethod.getModifiers().addAll(method.getModifiers()); + renamedMethod.setLevel(method.getLevel()); + renamedMethod.setProgram(method.getProgram()); + rename(method.getAnnotations(), renamedMethod.getAnnotations()); + rename(renamedMethod.getProgram()); + return renamedMethod; + } + + private ValueType rename(ValueType type) { + if (type instanceof ValueType.Array) { + ValueType itemType = ((ValueType.Array)type).getItemType(); + return ValueType.arrayOf(rename(itemType)); + } else if (type instanceof ValueType.Object) { + String className = ((ValueType.Object)type).getClassName(); + return ValueType.object(classNameMapper.map(className)); + } else { + return type; + } + } + + private void rename(AnnotationContainer source, AnnotationContainer target) { + for (AnnotationHolder annot : source.all()) { + if (!annot.getType().equals(Rename.class.getName())) { + target.add(rename(annot)); + } + } + } + + private AnnotationHolder rename(AnnotationHolder annot) { + AnnotationHolder renamedAnnot = new AnnotationHolder(classNameMapper.map(annot.getType())); + for (Map.Entry entry : renamedAnnot.getValues().entrySet()) { + renamedAnnot.getValues().put(entry.getKey(), entry.getValue()); + } + return renamedAnnot; + } + + public void rename(Program program) { + for (int i = 0; i < program.basicBlockCount(); ++i) { + BasicBlock basicBlock = program.basicBlockAt(i); + for (Instruction insn : basicBlock.getInstructions()) { + insn.acceptVisitor(this); + } + } + } + + @Override + public void visit(EmptyInstruction insn) { + } + + @Override + public void visit(ClassConstantInstruction insn) { + insn.setConstant(rename(insn.getConstant())); + } + + @Override + public void visit(NullConstantInstruction insn) { + } + + @Override + public void visit(IntegerConstantInstruction insn) { + } + + @Override + public void visit(LongConstantInstruction insn) { + } + + @Override + public void visit(FloatConstantInstruction insn) { + } + + @Override + public void visit(DoubleConstantInstruction insn) { + } + + @Override + public void visit(StringConstantInstruction insn) { + } + + @Override + public void visit(BinaryInstruction insn) { + } + + @Override + public void visit(NegateInstruction insn) { + } + + @Override + public void visit(AssignInstruction insn) { + } + + @Override + public void visit(CastInstruction insn) { + insn.setTargetType(rename(insn.getTargetType())); + } + + @Override + public void visit(CastNumberInstruction insn) { + } + + @Override + public void visit(BranchingInstruction insn) { + } + + @Override + public void visit(BinaryBranchingInstruction insn) { + } + + @Override + public void visit(JumpInstruction insn) { + } + + @Override + public void visit(SwitchInstruction insn) { + } + + @Override + public void visit(ExitInstruction insn) { + } + + @Override + public void visit(RaiseInstruction insn) { + } + + @Override + public void visit(ConstructArrayInstruction insn) { + insn.setItemType(rename(insn.getItemType())); + } + + @Override + public void visit(ConstructInstruction insn) { + insn.setType(classNameMapper.map(insn.getType())); + } + + @Override + public void visit(ConstructMultiArrayInstruction insn) { + insn.setItemType(rename(insn.getItemType())); + } + + @Override + public void visit(GetFieldInstruction insn) { + insn.setClassName(classNameMapper.map(insn.getClassName())); + } + + @Override + public void visit(PutFieldInstruction insn) { + insn.setClassName(classNameMapper.map(insn.getClassName())); + } + + @Override + public void visit(ArrayLengthInstruction insn) { + } + + @Override + public void visit(CloneArrayInstruction insn) { + } + + @Override + public void visit(GetElementInstruction insn) { + } + + @Override + public void visit(PutElementInstruction insn) { + } + + @Override + public void visit(InvokeInstruction insn) { + insn.setClassName(classNameMapper.map(insn.getClassName())); + } + + @Override + public void visit(IsInstanceInstruction insn) { + insn.setType(rename(insn.getType())); + } +} diff --git a/teavm-core/src/main/java/org/teavm/model/resource/ClasspathResourceMapper.java b/teavm-core/src/main/java/org/teavm/model/resource/ClasspathResourceMapper.java index 6efe96e84..a97a19dff 100644 --- a/teavm-core/src/main/java/org/teavm/model/resource/ClasspathResourceMapper.java +++ b/teavm-core/src/main/java/org/teavm/model/resource/ClasspathResourceMapper.java @@ -20,6 +20,7 @@ public class ClasspathResourceMapper implements Mapper { private static class Transformation { String packageName; String packagePrefix = ""; + String fullPrefix = ""; String classPrefix = ""; } @@ -48,6 +49,7 @@ public class ClasspathResourceMapper implements Mapper { String packageName = propertyName.substring(PACKAGE_PREFIX.length()); Transformation transformation = getTransformation(cache, packageName); transformation.packagePrefix = properties.getProperty(propertyName) + "."; + transformation.fullPrefix = transformation.packagePrefix + transformation.packageName + "."; } else if (propertyName.startsWith(CLASS_PREFIX)) { String packageName = propertyName.substring(CLASS_PREFIX.length()); Transformation transformation = getTransformation(cache, packageName); @@ -61,6 +63,7 @@ public class ClasspathResourceMapper implements Mapper { if (transformation == null) { transformation = new Transformation(); transformation.packageName = packageName; + transformation.fullPrefix = packageName + "."; cache.put(packageName, transformation); } return transformation; @@ -80,4 +83,19 @@ public class ClasspathResourceMapper implements Mapper { } return innerMapper.map(name); } + + String renameClass(String name) { + for (Transformation transformation : transformations) { + if (name.startsWith(transformation.fullPrefix)) { + int index = name.lastIndexOf('.'); + String className = name.substring(index + 1); + String packageName = name.substring(0, index); + if (className.startsWith(transformation.classPrefix)) { + return packageName.substring(transformation.fullPrefix.length()) + "." + + className.substring(transformation.classPrefix.length()); + } + } + } + return name; + } }