From e782c57d74000722f9db4c9426317410520670c6 Mon Sep 17 00:00:00 2001 From: Tor Norbye Date: Thu, 18 Sep 2014 11:43:07 -0700 Subject: Snapshot idea/138.2210 from git://git.jetbrains.org/idea/community.git Change-Id: I8f0204d7887ee78cf1fd8c09f936c5afff0edd2f --- .../struct/attr/StructAnnotationAttribute.java | 184 +++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/attr/StructAnnotationAttribute.java (limited to 'plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/attr/StructAnnotationAttribute.java') diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/attr/StructAnnotationAttribute.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/attr/StructAnnotationAttribute.java new file mode 100644 index 000000000000..d04cb04166d5 --- /dev/null +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/attr/StructAnnotationAttribute.java @@ -0,0 +1,184 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.java.decompiler.struct.attr; + +import org.jetbrains.java.decompiler.code.CodeConstants; +import org.jetbrains.java.decompiler.modules.decompiler.exps.*; +import org.jetbrains.java.decompiler.struct.consts.ConstantPool; +import org.jetbrains.java.decompiler.struct.consts.PrimitiveConstant; +import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor; +import org.jetbrains.java.decompiler.struct.gen.VarType; + +import java.io.DataInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class StructAnnotationAttribute extends StructGeneralAttribute { + + private List annotations; + + @Override + public void initContent(ConstantPool pool) throws IOException { + annotations = parseAnnotations(pool, stream()); + } + + public static List parseAnnotations(ConstantPool pool, DataInputStream data) throws IOException { + int len = data.readUnsignedShort(); + if (len > 0) { + List annotations = new ArrayList(len); + for (int i = 0; i < len; i++) { + annotations.add(parseAnnotation(data, pool)); + } + return annotations; + } + else { + return Collections.emptyList(); + } + } + + public static AnnotationExprent parseAnnotation(DataInputStream data, ConstantPool pool) throws IOException { + String className = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); + + List names; + List values; + int len = data.readUnsignedShort(); + if (len > 0) { + names = new ArrayList(len); + values = new ArrayList(len); + for (int i = 0; i < len; i++) { + names.add(pool.getPrimitiveConstant(data.readUnsignedShort()).getString()); + values.add(parseAnnotationElement(data, pool)); + } + } + else { + names = Collections.emptyList(); + values = Collections.emptyList(); + } + + return new AnnotationExprent(new VarType(className).value, names, values); + } + + public static Exprent parseAnnotationElement(DataInputStream data, ConstantPool pool) throws IOException { + int tag = data.readUnsignedByte(); + + switch (tag) { + case 'e': // enum constant + String className = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); + String constName = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); + FieldDescriptor descr = FieldDescriptor.parseDescriptor(className); + return new FieldExprent(constName, descr.type.value, true, null, descr); + + case 'c': // class + String descriptor = pool.getPrimitiveConstant(data.readUnsignedShort()).getString(); + VarType type = FieldDescriptor.parseDescriptor(descriptor).type; + + String value; + switch (type.type) { + case CodeConstants.TYPE_OBJECT: + value = type.value; + break; + case CodeConstants.TYPE_BYTE: + value = byte.class.getName(); + break; + case CodeConstants.TYPE_CHAR: + value = char.class.getName(); + break; + case CodeConstants.TYPE_DOUBLE: + value = double.class.getName(); + break; + case CodeConstants.TYPE_FLOAT: + value = float.class.getName(); + break; + case CodeConstants.TYPE_INT: + value = int.class.getName(); + break; + case CodeConstants.TYPE_LONG: + value = long.class.getName(); + break; + case CodeConstants.TYPE_SHORT: + value = short.class.getName(); + break; + case CodeConstants.TYPE_BOOLEAN: + value = boolean.class.getName(); + break; + case CodeConstants.TYPE_VOID: + value = void.class.getName(); + break; + default: + throw new RuntimeException("invalid class type: " + type.type); + } + return new ConstExprent(VarType.VARTYPE_CLASS, value); + + case '[': // array + List elements = Collections.emptyList(); + int len = data.readUnsignedShort(); + if (len > 0) { + elements = new ArrayList(len); + for (int i = 0; i < len; i++) { + elements.add(parseAnnotationElement(data, pool)); + } + } + + VarType newType; + if (elements.isEmpty()) { + newType = new VarType(CodeConstants.TYPE_OBJECT, 1, "java/lang/Object"); + } + else { + VarType elementType = elements.get(0).getExprType(); + newType = new VarType(elementType.type, 1, elementType.value); + } + + NewExprent newExpr = new NewExprent(newType, Collections.emptyList()); + newExpr.setDirectArrayInit(true); + newExpr.setLstArrayElements(elements); + return newExpr; + + case '@': // annotation + return parseAnnotation(data, pool); + + default: + PrimitiveConstant cn = pool.getPrimitiveConstant(data.readUnsignedShort()); + switch (tag) { + case 'B': + return new ConstExprent(VarType.VARTYPE_BYTE, cn.value); + case 'C': + return new ConstExprent(VarType.VARTYPE_CHAR, cn.value); + case 'D': + return new ConstExprent(VarType.VARTYPE_DOUBLE, cn.value); + case 'F': + return new ConstExprent(VarType.VARTYPE_FLOAT, cn.value); + case 'I': + return new ConstExprent(VarType.VARTYPE_INT, cn.value); + case 'J': + return new ConstExprent(VarType.VARTYPE_LONG, cn.value); + case 'S': + return new ConstExprent(VarType.VARTYPE_SHORT, cn.value); + case 'Z': + return new ConstExprent(VarType.VARTYPE_BOOLEAN, cn.value); + case 's': + return new ConstExprent(VarType.VARTYPE_STRING, cn.value); + default: + throw new RuntimeException("invalid element type!"); + } + } + } + + public List getAnnotations() { + return annotations; + } +} -- cgit v1.2.3