Step 1: add top-level field/method/parameter annotations to stubs; include them in decompiled text.master
parent
a8403429ef
commit
52b31bf325
@ -0,0 +1,67 @@ |
||||
/* |
||||
* Copyright 2000-2016 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.modules.decompiler.exps; |
||||
|
||||
public class TypeAnnotation { |
||||
public static final int CLASS_TYPE_PARAMETER = 0x00; |
||||
public static final int METHOD_TYPE_PARAMETER = 0x01; |
||||
public static final int SUPER_TYPE_REFERENCE = 0x10; |
||||
public static final int CLASS_TYPE_PARAMETER_BOUND = 0x11; |
||||
public static final int METHOD_TYPE_PARAMETER_BOUND = 0x12; |
||||
public static final int FIELD = 0x13; |
||||
public static final int METHOD_RETURN_TYPE = 0x14; |
||||
public static final int METHOD_RECEIVER = 0x15; |
||||
public static final int METHOD_PARAMETER = 0x16; |
||||
public static final int THROWS_REFERENCE = 0x17; |
||||
public static final int LOCAL_VARIABLE = 0x40; |
||||
public static final int RESOURCE_VARIABLE = 0x41; |
||||
public static final int CATCH_CLAUSE = 0x42; |
||||
public static final int EXPR_INSTANCEOF = 0x43; |
||||
public static final int EXPR_NEW = 0x44; |
||||
public static final int EXPR_CONSTRUCTOR_REF = 0x45; |
||||
public static final int EXPR_METHOD_REF = 0x46; |
||||
public static final int TYPE_ARG_CAST = 0x47; |
||||
public static final int TYPE_ARG_CONSTRUCTOR_CALL = 0x48; |
||||
public static final int TYPE_ARG_METHOD_CALL = 0x49; |
||||
public static final int TYPE_ARG_CONSTRUCTOR_REF = 0x4A; |
||||
public static final int TYPE_ARG_METHOD_REF = 0x4B; |
||||
|
||||
private final int target; |
||||
private final byte[] path; |
||||
private final AnnotationExprent annotation; |
||||
|
||||
public TypeAnnotation(int target, byte[] path, AnnotationExprent annotation) { |
||||
this.target = target; |
||||
this.path = path; |
||||
this.annotation = annotation; |
||||
} |
||||
|
||||
public int getTargetType() { |
||||
return target >> 24; |
||||
} |
||||
|
||||
public int getIndex() { |
||||
return target & 0x0FFFF; |
||||
} |
||||
|
||||
public boolean isTopLevel() { |
||||
return path == null; |
||||
} |
||||
|
||||
public AnnotationExprent getAnnotation() { |
||||
return annotation; |
||||
} |
||||
} |
@ -1,194 +0,0 @@ |
||||
/* |
||||
* 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.modules.decompiler.exps.AnnotationExprent; |
||||
import org.jetbrains.java.decompiler.struct.consts.ConstantPool; |
||||
|
||||
import java.io.DataInputStream; |
||||
import java.io.IOException; |
||||
import java.util.ArrayList; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
|
||||
public class StructAnnotationTypeAttribute extends StructGeneralAttribute { |
||||
|
||||
private static final int ANNOTATION_TARGET_TYPE_GENERIC_CLASS = 0x00; |
||||
private static final int ANNOTATION_TARGET_TYPE_GENERIC_METHOD = 0x01; |
||||
private static final int ANNOTATION_TARGET_TYPE_EXTENDS_IMPLEMENTS = 0x10; |
||||
private static final int ANNOTATION_TARGET_TYPE_GENERIC_CLASS_BOUND = 0x11; |
||||
private static final int ANNOTATION_TARGET_TYPE_GENERIC_METHOD_BOUND = 0x12; |
||||
private static final int ANNOTATION_TARGET_TYPE_FIELD = 0x13; |
||||
private static final int ANNOTATION_TARGET_TYPE_RETURN = 0x14; |
||||
private static final int ANNOTATION_TARGET_TYPE_RECEIVER = 0x15; |
||||
private static final int ANNOTATION_TARGET_TYPE_FORMAL = 0x16; |
||||
private static final int ANNOTATION_TARGET_TYPE_THROWS = 0x17; |
||||
private static final int ANNOTATION_TARGET_TYPE_LOCAL_VARIABLE = 0x40; |
||||
private static final int ANNOTATION_TARGET_TYPE_RESOURCE_VARIABLE = 0x41; |
||||
private static final int ANNOTATION_TARGET_TYPE_EXCEPTION = 0x42; |
||||
private static final int ANNOTATION_TARGET_TYPE_INSTANCEOF = 0x43; |
||||
private static final int ANNOTATION_TARGET_TYPE_NEW = 0x44; |
||||
private static final int ANNOTATION_TARGET_TYPE_DOUBLE_COLON_NEW = 0x45; |
||||
private static final int ANNOTATION_TARGET_TYPE_DOUBLE_COLON_ID = 0x46; |
||||
private static final int ANNOTATION_TARGET_TYPE_CAST = 0x47; |
||||
private static final int ANNOTATION_TARGET_TYPE_INVOCATION_CONSTRUCTOR = 0x48; |
||||
private static final int ANNOTATION_TARGET_TYPE_INVOCATION_METHOD = 0x49; |
||||
private static final int ANNOTATION_TARGET_TYPE_GENERIC_DOUBLE_COLON_NEW = 0x4A; |
||||
private static final int ANNOTATION_TARGET_TYPE_GENERIC_DOUBLE_COLON_ID = 0x4B; |
||||
|
||||
private static final int ANNOTATION_TARGET_UNION_TYPE_PARAMETER = 1; |
||||
private static final int ANNOTATION_TARGET_UNION_SUPERTYPE = 2; |
||||
private static final int ANNOTATION_TARGET_UNION_TYPE_PARAMETER_BOUND = 3; |
||||
private static final int ANNOTATION_TARGET_UNION_EMPTY = 4; |
||||
private static final int ANNOTATION_TARGET_UNION_FORMAL_PARAMETER = 5; |
||||
private static final int ANNOTATION_TARGET_UNION_THROWS = 6; |
||||
private static final int ANNOTATION_TARGET_UNION_LOCAL_VAR = 7; |
||||
private static final int ANNOTATION_TARGET_UNION_CATCH = 8; |
||||
private static final int ANNOTATION_TARGET_UNION_OFFSET = 9; |
||||
private static final int ANNOTATION_TARGET_UNION_TYPE_ARGUMENT = 10; |
||||
|
||||
@SuppressWarnings("FieldCanBeLocal") private List<AnnotationLocation> locations; |
||||
@SuppressWarnings("FieldCanBeLocal") private List<AnnotationExprent> annotations; |
||||
|
||||
@Override |
||||
public void initContent(ConstantPool pool) throws IOException { |
||||
DataInputStream data = stream(); |
||||
|
||||
int len = data.readUnsignedByte(); |
||||
if (len > 0) { |
||||
locations = new ArrayList<AnnotationLocation>(len); |
||||
annotations = new ArrayList<AnnotationExprent>(len); |
||||
for (int i = 0; i < len; i++) { |
||||
locations.add(parseAnnotationLocation(data)); |
||||
annotations.add(StructAnnotationAttribute.parseAnnotation(data, pool)); |
||||
} |
||||
} |
||||
else { |
||||
locations = Collections.emptyList(); |
||||
annotations = Collections.emptyList(); |
||||
} |
||||
} |
||||
|
||||
private static AnnotationLocation parseAnnotationLocation(DataInputStream data) throws IOException { |
||||
AnnotationLocation ann_location = new AnnotationLocation(); |
||||
|
||||
// target type
|
||||
ann_location.target_type = data.readUnsignedByte(); |
||||
|
||||
// target union
|
||||
switch (ann_location.target_type) { |
||||
case ANNOTATION_TARGET_TYPE_GENERIC_CLASS: |
||||
case ANNOTATION_TARGET_TYPE_GENERIC_METHOD: |
||||
ann_location.target_union = ANNOTATION_TARGET_UNION_TYPE_PARAMETER; |
||||
break; |
||||
case ANNOTATION_TARGET_TYPE_EXTENDS_IMPLEMENTS: |
||||
ann_location.target_union = ANNOTATION_TARGET_UNION_SUPERTYPE; |
||||
break; |
||||
case ANNOTATION_TARGET_TYPE_GENERIC_CLASS_BOUND: |
||||
case ANNOTATION_TARGET_TYPE_GENERIC_METHOD_BOUND: |
||||
ann_location.target_union = ANNOTATION_TARGET_UNION_TYPE_PARAMETER_BOUND; |
||||
break; |
||||
case ANNOTATION_TARGET_TYPE_FIELD: |
||||
case ANNOTATION_TARGET_TYPE_RETURN: |
||||
case ANNOTATION_TARGET_TYPE_RECEIVER: |
||||
ann_location.target_union = ANNOTATION_TARGET_UNION_EMPTY; |
||||
break; |
||||
case ANNOTATION_TARGET_TYPE_FORMAL: |
||||
ann_location.target_union = ANNOTATION_TARGET_UNION_FORMAL_PARAMETER; |
||||
break; |
||||
case ANNOTATION_TARGET_TYPE_THROWS: |
||||
ann_location.target_union = ANNOTATION_TARGET_UNION_THROWS; |
||||
break; |
||||
case ANNOTATION_TARGET_TYPE_LOCAL_VARIABLE: |
||||
case ANNOTATION_TARGET_TYPE_RESOURCE_VARIABLE: |
||||
ann_location.target_union = ANNOTATION_TARGET_UNION_LOCAL_VAR; |
||||
break; |
||||
case ANNOTATION_TARGET_TYPE_EXCEPTION: |
||||
ann_location.target_union = ANNOTATION_TARGET_UNION_CATCH; |
||||
break; |
||||
case ANNOTATION_TARGET_TYPE_INSTANCEOF: |
||||
case ANNOTATION_TARGET_TYPE_NEW: |
||||
case ANNOTATION_TARGET_TYPE_DOUBLE_COLON_NEW: |
||||
case ANNOTATION_TARGET_TYPE_DOUBLE_COLON_ID: |
||||
ann_location.target_union = ANNOTATION_TARGET_UNION_OFFSET; |
||||
break; |
||||
case ANNOTATION_TARGET_TYPE_CAST: |
||||
case ANNOTATION_TARGET_TYPE_INVOCATION_CONSTRUCTOR: |
||||
case ANNOTATION_TARGET_TYPE_INVOCATION_METHOD: |
||||
case ANNOTATION_TARGET_TYPE_GENERIC_DOUBLE_COLON_NEW: |
||||
case ANNOTATION_TARGET_TYPE_GENERIC_DOUBLE_COLON_ID: |
||||
ann_location.target_union = ANNOTATION_TARGET_UNION_TYPE_ARGUMENT; |
||||
break; |
||||
default: |
||||
throw new RuntimeException("Unknown target type in a type annotation!"); |
||||
} |
||||
|
||||
// target union data
|
||||
|
||||
switch (ann_location.target_union) { |
||||
case ANNOTATION_TARGET_UNION_TYPE_PARAMETER: |
||||
case ANNOTATION_TARGET_UNION_FORMAL_PARAMETER: |
||||
ann_location.data = new int[]{data.readUnsignedByte()}; |
||||
break; |
||||
case ANNOTATION_TARGET_UNION_SUPERTYPE: |
||||
case ANNOTATION_TARGET_UNION_THROWS: |
||||
case ANNOTATION_TARGET_UNION_CATCH: |
||||
case ANNOTATION_TARGET_UNION_OFFSET: |
||||
ann_location.data = new int[]{data.readUnsignedShort()}; |
||||
break; |
||||
case ANNOTATION_TARGET_UNION_TYPE_PARAMETER_BOUND: |
||||
ann_location.data = new int[]{data.readUnsignedByte(), data.readUnsignedByte()}; |
||||
break; |
||||
case ANNOTATION_TARGET_UNION_EMPTY: |
||||
break; |
||||
case ANNOTATION_TARGET_UNION_LOCAL_VAR: |
||||
int table_length = data.readUnsignedShort(); |
||||
|
||||
ann_location.data = new int[table_length * 3 + 1]; |
||||
ann_location.data[0] = table_length; |
||||
|
||||
for (int i = 0; i < table_length; ++i) { |
||||
ann_location.data[3 * i + 1] = data.readUnsignedShort(); |
||||
ann_location.data[3 * i + 2] = data.readUnsignedShort(); |
||||
ann_location.data[3 * i + 3] = data.readUnsignedShort(); |
||||
} |
||||
break; |
||||
case ANNOTATION_TARGET_UNION_TYPE_ARGUMENT: |
||||
ann_location.data = new int[]{data.readUnsignedShort(), data.readUnsignedByte()}; |
||||
} |
||||
|
||||
// target path
|
||||
int path_length = data.readUnsignedByte(); |
||||
|
||||
ann_location.target_path_kind = new int[path_length]; |
||||
ann_location.target_argument_index = new int[path_length]; |
||||
|
||||
for (int i = 0; i < path_length; ++i) { |
||||
ann_location.target_path_kind[i] = data.readUnsignedByte(); |
||||
ann_location.target_argument_index[i] = data.readUnsignedByte(); |
||||
} |
||||
|
||||
return ann_location; |
||||
} |
||||
|
||||
private static class AnnotationLocation { |
||||
public int target_type; |
||||
public int target_union; |
||||
public int[] data; |
||||
public int[] target_path_kind; |
||||
public int[] target_argument_index; |
||||
} |
||||
} |
@ -0,0 +1,107 @@ |
||||
/* |
||||
* Copyright 2000-2016 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.modules.decompiler.exps.AnnotationExprent; |
||||
import org.jetbrains.java.decompiler.modules.decompiler.exps.TypeAnnotation; |
||||
import org.jetbrains.java.decompiler.struct.consts.ConstantPool; |
||||
|
||||
import java.io.DataInputStream; |
||||
import java.io.IOException; |
||||
import java.util.ArrayList; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
|
||||
public class StructTypeAnnotationAttribute extends StructGeneralAttribute { |
||||
private List<TypeAnnotation> annotations = Collections.emptyList(); |
||||
|
||||
@Override |
||||
public void initContent(ConstantPool pool) throws IOException { |
||||
DataInputStream data = stream(); |
||||
|
||||
int len = data.readUnsignedShort(); |
||||
if (len > 0) { |
||||
annotations = new ArrayList<>(len); |
||||
for (int i = 0; i < len; i++) { |
||||
annotations.add(parse(data, pool)); |
||||
} |
||||
} |
||||
else { |
||||
annotations = Collections.emptyList(); |
||||
} |
||||
} |
||||
|
||||
private static TypeAnnotation parse(DataInputStream data, ConstantPool pool) throws IOException { |
||||
int targetType = data.readUnsignedByte(); |
||||
int target = targetType << 24; |
||||
|
||||
switch (targetType) { |
||||
case TypeAnnotation.CLASS_TYPE_PARAMETER: |
||||
case TypeAnnotation.METHOD_TYPE_PARAMETER: |
||||
case TypeAnnotation.METHOD_PARAMETER: |
||||
target |= data.readUnsignedByte(); |
||||
break; |
||||
|
||||
case TypeAnnotation.SUPER_TYPE_REFERENCE: |
||||
case TypeAnnotation.CLASS_TYPE_PARAMETER_BOUND: |
||||
case TypeAnnotation.METHOD_TYPE_PARAMETER_BOUND: |
||||
case TypeAnnotation.THROWS_REFERENCE: |
||||
case TypeAnnotation.CATCH_CLAUSE: |
||||
case TypeAnnotation.EXPR_INSTANCEOF: |
||||
case TypeAnnotation.EXPR_NEW: |
||||
case TypeAnnotation.EXPR_CONSTRUCTOR_REF: |
||||
case TypeAnnotation.EXPR_METHOD_REF: |
||||
target |= data.readUnsignedShort(); |
||||
break; |
||||
|
||||
case TypeAnnotation.TYPE_ARG_CAST: |
||||
case TypeAnnotation.TYPE_ARG_CONSTRUCTOR_CALL: |
||||
case TypeAnnotation.TYPE_ARG_METHOD_CALL: |
||||
case TypeAnnotation.TYPE_ARG_CONSTRUCTOR_REF: |
||||
case TypeAnnotation.TYPE_ARG_METHOD_REF: |
||||
data.skipBytes(3); |
||||
break; |
||||
|
||||
case TypeAnnotation.LOCAL_VARIABLE: |
||||
case TypeAnnotation.RESOURCE_VARIABLE: |
||||
data.skipBytes(data.readUnsignedShort() * 6); |
||||
break; |
||||
|
||||
case TypeAnnotation.FIELD: |
||||
case TypeAnnotation.METHOD_RETURN_TYPE: |
||||
case TypeAnnotation.METHOD_RECEIVER: |
||||
break; |
||||
|
||||
default: |
||||
throw new RuntimeException("unknown target type: " + targetType); |
||||
} |
||||
|
||||
int pathLength = data.readUnsignedByte(); |
||||
byte[] path = null; |
||||
if (pathLength > 0) { |
||||
path = new byte[2 * pathLength]; |
||||
data.readFully(path); |
||||
} |
||||
|
||||
AnnotationExprent annotation = StructAnnotationAttribute.parseAnnotation(data, pool); |
||||
|
||||
return new TypeAnnotation(target, path, annotation); |
||||
} |
||||
|
||||
public List<TypeAnnotation> getAnnotations() { |
||||
return annotations; |
||||
} |
||||
} |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,44 @@ |
||||
package pkg; |
||||
|
||||
import java.lang.annotation.ElementType; |
||||
import java.lang.annotation.Target; |
||||
|
||||
class TypeAnnotations { |
||||
@TypeAnnotations.TA("field type") |
||||
private String f1; |
||||
@TypeAnnotations.MixA("field and type") |
||||
private String f2; |
||||
|
||||
@TypeAnnotations.TA("return type") |
||||
int m1() { |
||||
return 42;// 18 |
||||
} |
||||
|
||||
void m2(@TypeAnnotations.TA("parameter") int var1) { |
||||
}// 21 |
||||
|
||||
@Target({ElementType.FIELD, ElementType.TYPE_USE}) |
||||
@interface MixA { |
||||
String value(); |
||||
} |
||||
|
||||
@Target({ElementType.TYPE_USE}) |
||||
@interface TA { |
||||
String value(); |
||||
} |
||||
} |
||||
|
||||
class 'pkg/TypeAnnotations' { |
||||
method 'm1 ()I' { |
||||
0 13 |
||||
2 13 |
||||
} |
||||
|
||||
method 'm2 (I)V' { |
||||
0 17 |
||||
} |
||||
} |
||||
|
||||
Lines mapping: |
||||
18 <-> 14 |
||||
21 <-> 18 |
@ -0,0 +1,22 @@ |
||||
package pkg; |
||||
|
||||
import java.lang.annotation.*; |
||||
import java.util.*; |
||||
|
||||
class TypeAnnotations { |
||||
@Target(ElementType.TYPE_USE) |
||||
@interface TA { String value(); } |
||||
|
||||
@Target({ElementType.FIELD, ElementType.TYPE_USE}) |
||||
@interface MixA { String value(); } |
||||
|
||||
private @TA("field type") String f1; |
||||
|
||||
private @MixA("field and type") String f2; |
||||
|
||||
@TA("return type") int m1() { |
||||
return 42; |
||||
} |
||||
|
||||
void m2(@TA("parameter") int i) { } |
||||
} |
Loading…
Reference in new issue