/******************************************************************************* * Copyright (c) 2013, 2016 GoPivotal, Inc. All Rights Reserved. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for * Bug 407191 - [1.8] Binary access support for type annotations *******************************************************************************/ package org.eclipse.jdt.core.tests.compiler.regression; import junit.framework.Test; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; import org.eclipse.jdt.internal.compiler.codegen.AnnotationTargetTypeConstants; import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation; import org.eclipse.jdt.internal.compiler.env.IBinaryElementValuePair; import org.eclipse.jdt.internal.compiler.env.IBinaryField; import org.eclipse.jdt.internal.compiler.env.IBinaryMethod; import org.eclipse.jdt.internal.compiler.env.IBinaryTypeAnnotation; @SuppressWarnings({ "rawtypes" }) public class ClassFileReaderTest_1_8 extends AbstractRegressionTest { static { } public static Test suite() { return buildMinimalComplianceTestSuite(testClass(), F_1_8); } public static Class testClass() { return ClassFileReaderTest_1_8.class; } public ClassFileReaderTest_1_8(String name) { super(name); } // Needed to run tests individually from JUnit protected void setUp() throws Exception { super.setUp(); this.complianceLevel = ClassFileConstants.JDK1_8; } public void test001_classTypeParameter() throws Exception { String source = "import java.lang.annotation.*;\n" + "public class X<@Foo T1,@Bar(iii=99) T2> {}\n" + "@Retention(RetentionPolicy.CLASS)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Foo {\n" + "}\n" + "@Retention(RetentionPolicy.CLASS)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Bar {\n" + " int iii() default -1;\n" + "}"; org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader classFileReader = getInternalClassFile("", "X", "X", source); IBinaryTypeAnnotation[] typeAnnotations = classFileReader.getTypeAnnotations(); assertEquals(2,typeAnnotations.length); assertEquals("@LFoo; CLASS_TYPE_PARAMETER(type_parameter_index=0)", printTypeAnnotation(typeAnnotations[0])); assertEquals("@LBar;(iii=(int)99) CLASS_TYPE_PARAMETER(type_parameter_index=1)", printTypeAnnotation(typeAnnotations[1])); } public void test001a_classTypeParameterDifferingRetentions() throws Exception { String source = "import java.lang.annotation.*;\n" + "public class X<@Foo T1,@Bar(iii=99) T2> {}\n" + "@Retention(RetentionPolicy.RUNTIME)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Foo {\n" + "}\n" + "@Retention(RetentionPolicy.CLASS)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Bar {\n" + " int iii() default -1;\n" + "}"; org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader classFileReader = getInternalClassFile("", "X", "X", source); IBinaryTypeAnnotation[] typeAnnotations = classFileReader.getTypeAnnotations(); assertEquals(2,typeAnnotations.length); assertEquals("@LBar;(iii=(int)99) CLASS_TYPE_PARAMETER(type_parameter_index=1)", printTypeAnnotation(typeAnnotations[0])); assertEquals("@LFoo; CLASS_TYPE_PARAMETER(type_parameter_index=0)", printTypeAnnotation(typeAnnotations[1])); } public void test002_methodTypeParameter() throws Exception { String source = "import java.lang.annotation.*;\n" + "public class X {\n" + " <@Foo T1, @Bar(3) T2> void foo(T1 t1,T2 t2) {}\n" + "}\n" + "@Retention(RetentionPolicy.CLASS)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Foo {\n" + "}\n" + "@Retention(RetentionPolicy.CLASS)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Bar {\n" + " int value() default -1;\n" + "}"; org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader cfr = getInternalClassFile("", "X", "X", source); IBinaryMethod method = getMethod(cfr,"foo"); assertNotNull(method); IBinaryTypeAnnotation[] typeAnnotations = method.getTypeAnnotations(); assertNotNull(typeAnnotations); assertEquals(2,typeAnnotations.length); assertEquals("@LFoo; METHOD_TYPE_PARAMETER(type_parameter_index=0)",printTypeAnnotation(typeAnnotations[0])); assertEquals("@LBar;(value=(int)3) METHOD_TYPE_PARAMETER(type_parameter_index=1)",printTypeAnnotation(typeAnnotations[1])); } public void test003_classExtends() throws Exception { this.complianceLevel = ClassFileConstants.JDK1_8; String source = "import java.lang.annotation.*;\n" + "public class X extends @Foo @Bar(iii=34) Object implements java.io.@Bar(iii=1) Serializable {\n" + "}\n" + "@Retention(RetentionPolicy.CLASS)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Foo {\n" + "}\n" + "@Retention(RetentionPolicy.CLASS)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Bar {\n" + " int iii() default -1;\n" + "}"; org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader classFileReader = getInternalClassFile("", "X", "X", source); IBinaryTypeAnnotation[] typeAnnotations = classFileReader.getTypeAnnotations(); assertEquals(3,typeAnnotations.length); assertEquals("@LFoo; CLASS_EXTENDS(type_index=-1)", printTypeAnnotation(typeAnnotations[0])); assertEquals("@LBar;(iii=(int)34) CLASS_EXTENDS(type_index=-1)", printTypeAnnotation(typeAnnotations[1])); assertEquals("@LBar;(iii=(int)1) CLASS_EXTENDS(type_index=0)", printTypeAnnotation(typeAnnotations[2])); } public void test004_classExtends() throws Exception { String source = "import java.lang.annotation.*;\n" + "public class X extends Y<@Foo String,@Bar Integer> implements I<@Foo String> {\n" + "}\n" + "class Y<T1, T2> {}\n" + "interface I<T1> {}\n" + "@Retention(RetentionPolicy.CLASS)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Foo {\n" + "}\n" + "@Retention(RetentionPolicy.CLASS)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Bar {\n" + " int iii() default -1;\n" + "}"; org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader classFileReader = getInternalClassFile("", "X", "X", source); IBinaryTypeAnnotation[] typeAnnotations = classFileReader.getTypeAnnotations(); assertEquals(3,typeAnnotations.length); assertEquals("@LFoo; CLASS_EXTENDS(type_index=-1), location=[TYPE_ARGUMENT(0)]", printTypeAnnotation(typeAnnotations[0])); assertEquals("@LBar; CLASS_EXTENDS(type_index=-1), location=[TYPE_ARGUMENT(1)]", printTypeAnnotation(typeAnnotations[1])); assertEquals("@LFoo; CLASS_EXTENDS(type_index=0), location=[TYPE_ARGUMENT(0)]", printTypeAnnotation(typeAnnotations[2])); } public void test005_classTypeParameterBound() throws Exception { String source = "import java.lang.annotation.*;\n" + "public class X<U, T extends Y<@Foo String @Bar(1)[][]@Bar(2)[]> & @Bar(3) Cloneable> {}\n" + "class Y<T> {}\n" + "@Retention(RetentionPolicy.CLASS)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Foo {\n" + "}\n" + "@Retention(RetentionPolicy.CLASS)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Bar {\n" + " int value() default -1;\n" + "}"; org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader classFileReader = getInternalClassFile("", "X", "X", source); IBinaryTypeAnnotation[] typeAnnotations = classFileReader.getTypeAnnotations(); assertEquals(4,typeAnnotations.length); assertEquals("@LFoo; CLASS_TYPE_PARAMETER_BOUND(type_parameter_index=1, bound_index=0), location=[TYPE_ARGUMENT(0), ARRAY, ARRAY, ARRAY]", printTypeAnnotation(typeAnnotations[0])); assertEquals("@LBar;(value=(int)1) CLASS_TYPE_PARAMETER_BOUND(type_parameter_index=1, bound_index=0), location=[TYPE_ARGUMENT(0)]", printTypeAnnotation(typeAnnotations[1])); assertEquals("@LBar;(value=(int)2) CLASS_TYPE_PARAMETER_BOUND(type_parameter_index=1, bound_index=0), location=[TYPE_ARGUMENT(0), ARRAY, ARRAY]", printTypeAnnotation(typeAnnotations[2])); assertEquals("@LBar;(value=(int)3) CLASS_TYPE_PARAMETER_BOUND(type_parameter_index=1, bound_index=1)", printTypeAnnotation(typeAnnotations[3])); } public void test006_methodTypeParameterBound() throws Exception { String source = "import java.lang.annotation.*;\n" + "public class X{\n" + " <T extends Y<@Foo Z @Bar(1)[][]@Bar(2)[]> & @Bar(3) Cloneable> void foo(T t) {}\n" + "}\n" + "class Y<T> {}\n" + "class Z {}\n" + "@Retention(RetentionPolicy.CLASS)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Foo {\n" + "}\n" + "@Retention(RetentionPolicy.CLASS)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Bar {\n" + " int value() default -1;\n" + "}"; org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader cfr = getInternalClassFile("", "X", "X", source); IBinaryMethod method = getMethod(cfr,"foo"); assertNotNull(method); IBinaryTypeAnnotation[] typeAnnotations = method.getTypeAnnotations(); assertNotNull(typeAnnotations); assertEquals(4,typeAnnotations.length); assertEquals("@LFoo; METHOD_TYPE_PARAMETER_BOUND(type_parameter_index=0, bound_index=0), location=[TYPE_ARGUMENT(0), ARRAY, ARRAY, ARRAY]",printTypeAnnotation(typeAnnotations[0])); assertEquals("@LBar;(value=(int)1) METHOD_TYPE_PARAMETER_BOUND(type_parameter_index=0, bound_index=0), location=[TYPE_ARGUMENT(0)]", printTypeAnnotation(typeAnnotations[1])); assertEquals("@LBar;(value=(int)2) METHOD_TYPE_PARAMETER_BOUND(type_parameter_index=0, bound_index=0), location=[TYPE_ARGUMENT(0), ARRAY, ARRAY]", printTypeAnnotation(typeAnnotations[2])); assertEquals("@LBar;(value=(int)3) METHOD_TYPE_PARAMETER_BOUND(type_parameter_index=0, bound_index=1)", printTypeAnnotation(typeAnnotations[3])); } public void test007_field() throws Exception { String source = "import java.lang.annotation.*;\n" + "import java.util.Map;\n" + "public class X{\n" + " @Foo Map<@Bar(1) String, @Bar(2) String @Bar(3)[] @Bar(4)[] @Bar(5)[]> field3;\n" + "}\n" + "class Y<T> {}\n" + "class Z {}\n" + "@Retention(RetentionPolicy.CLASS)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Foo {\n" + "}\n" + "@Retention(RetentionPolicy.CLASS)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Bar {\n" + " int value() default -1;\n" + "}"; org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader cfr = getInternalClassFile("", "X", "X", source); IBinaryField field = getField(cfr,"field3"); assertNotNull(field); IBinaryTypeAnnotation[] typeAnnotations = field.getTypeAnnotations(); assertNotNull(typeAnnotations); assertEquals(6,typeAnnotations.length); assertEquals("@LFoo; FIELD",printTypeAnnotation(typeAnnotations[0])); assertEquals("@LBar;(value=(int)1) FIELD, location=[TYPE_ARGUMENT(0)]", printTypeAnnotation(typeAnnotations[1])); assertEquals("@LBar;(value=(int)2) FIELD, location=[TYPE_ARGUMENT(1), ARRAY, ARRAY, ARRAY]", printTypeAnnotation(typeAnnotations[2])); assertEquals("@LBar;(value=(int)3) FIELD, location=[TYPE_ARGUMENT(1)]", printTypeAnnotation(typeAnnotations[3])); assertEquals("@LBar;(value=(int)4) FIELD, location=[TYPE_ARGUMENT(1), ARRAY]", printTypeAnnotation(typeAnnotations[4])); assertEquals("@LBar;(value=(int)5) FIELD, location=[TYPE_ARGUMENT(1), ARRAY, ARRAY]", printTypeAnnotation(typeAnnotations[5])); } public void test008_methodReturn() throws Exception { String source = "import java.lang.annotation.*;\n" + "import java.util.Map;\n" + "public class X{\n" + " @Bar(3) @Foo int foo() {\n" + " return 1;\n" + " }\n" + " @Bar(3) int @Foo [] foo2() {\n" + " return null;\n" + " }\n" + "}\n" + "@Retention(RetentionPolicy.CLASS)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Foo {\n" + "}\n" + "@Retention(RetentionPolicy.CLASS)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Bar {\n" + " int value() default -1;\n" + "}"; org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader cfr = getInternalClassFile("", "X", "X", source); IBinaryMethod method = getMethod(cfr,"foo"); assertNotNull(method); IBinaryTypeAnnotation[] typeAnnotations = method.getTypeAnnotations(); assertNotNull(typeAnnotations); assertEquals(2,typeAnnotations.length); assertEquals("@LBar;(value=(int)3) METHOD_RETURN",printTypeAnnotation(typeAnnotations[0])); assertEquals("@LFoo; METHOD_RETURN", printTypeAnnotation(typeAnnotations[1])); method = getMethod(cfr,"foo2"); assertNotNull(method); typeAnnotations = method.getTypeAnnotations(); assertNotNull(typeAnnotations); assertEquals(2,typeAnnotations.length); assertEquals("@LBar;(value=(int)3) METHOD_RETURN, location=[ARRAY]",printTypeAnnotation(typeAnnotations[0])); assertEquals("@LFoo; METHOD_RETURN", printTypeAnnotation(typeAnnotations[1])); } public void test009_methodReceiver() throws Exception { String source = "import java.lang.annotation.*;\n" + "import java.util.Map;\n" + "public class X{\n" + " void foo(@Bar(3) X this) {}\n" + "}\n" + "@Retention(RetentionPolicy.CLASS)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Foo {\n" + "}\n" + "@Retention(RetentionPolicy.CLASS)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Bar {\n" + " int value() default -1;\n" + "}"; org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader cfr = getInternalClassFile("", "X", "X", source); IBinaryMethod method = getMethod(cfr,"foo"); assertNotNull(method); IBinaryTypeAnnotation[] typeAnnotations = method.getTypeAnnotations(); assertNotNull(typeAnnotations); assertEquals(1,typeAnnotations.length); assertEquals("@LBar;(value=(int)3) METHOD_RECEIVER", printTypeAnnotation(typeAnnotations[0])); } public void test010_methodFormalParameter() throws Exception { String source = "import java.lang.annotation.*;\n" + "import java.util.Map;\n" + "public class X{\n" + " void foo(@Bar(3) String s, @Foo int i) {}\n" + "}\n" + "@Retention(RetentionPolicy.CLASS)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Foo {\n" + "}\n" + "@Retention(RetentionPolicy.CLASS)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Bar {\n" + " int value() default -1;\n" + "}"; org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader cfr = getInternalClassFile("", "X", "X", source); IBinaryMethod method = getMethod(cfr,"foo"); assertNotNull(method); IBinaryTypeAnnotation[] typeAnnotations = method.getTypeAnnotations(); assertNotNull(typeAnnotations); assertEquals(2,typeAnnotations.length); assertEquals("@LBar;(value=(int)3) METHOD_FORMAL_PARAMETER(method_formal_parameter_index=0)",printTypeAnnotation(typeAnnotations[0])); assertEquals("@LFoo; METHOD_FORMAL_PARAMETER(method_formal_parameter_index=1)",printTypeAnnotation(typeAnnotations[1])); } public void test011_throws() throws Exception { String source = "import java.lang.annotation.*;\n" + "import java.util.Map;\n" + "public class X{\n" + " void foo() throws @Foo Exception, @Bar(1) Throwable {}\n" + "}\n" + "@Retention(RetentionPolicy.CLASS)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Foo {\n" + "}\n" + "@Retention(RetentionPolicy.CLASS)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Bar {\n" + " int value() default -1;\n" + "}"; org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader cfr = getInternalClassFile("", "X", "X", source); IBinaryMethod method = getMethod(cfr,"foo"); assertNotNull(method); IBinaryTypeAnnotation[] typeAnnotations = method.getTypeAnnotations(); assertNotNull(typeAnnotations); assertEquals(2,typeAnnotations.length); assertEquals("@LFoo; THROWS(throws_type_index=0)",printTypeAnnotation(typeAnnotations[0])); assertEquals("@LBar;(value=(int)1) THROWS(throws_type_index=1)",printTypeAnnotation(typeAnnotations[1])); } public void test012_annotationMethodReturn() throws Exception { String source = "import java.lang.annotation.*;\n" + "import java.util.Map;\n" + "public @interface X{\n" + " @Bar(3) @Foo int foo();\n" + " @Bar(3) int @Foo [] foo2();\n" + " @Bar(7) @Foo String value() default \"aaa\";\n" + "}\n" + "@Retention(RetentionPolicy.CLASS)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Foo {\n" + "}\n" + "@Retention(RetentionPolicy.CLASS)\n" + "@Target(ElementType.TYPE_USE)\n" + "@interface Bar {\n" + " int value() default -1;\n" + "}"; org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader cfr = getInternalClassFile("", "X", "X", source); IBinaryMethod method = getMethod(cfr,"foo"); assertNotNull(method); IBinaryTypeAnnotation[] typeAnnotations = method.getTypeAnnotations(); assertNotNull(typeAnnotations); assertEquals(2,typeAnnotations.length); assertEquals("@LBar;(value=(int)3) METHOD_RETURN",printTypeAnnotation(typeAnnotations[0])); assertEquals("@LFoo; METHOD_RETURN", printTypeAnnotation(typeAnnotations[1])); method = getMethod(cfr,"foo2"); assertNotNull(method); typeAnnotations = method.getTypeAnnotations(); assertNotNull(typeAnnotations); assertEquals(2,typeAnnotations.length); assertEquals("@LBar;(value=(int)3) METHOD_RETURN, location=[ARRAY]",printTypeAnnotation(typeAnnotations[0])); assertEquals("@LFoo; METHOD_RETURN", printTypeAnnotation(typeAnnotations[1])); method = getMethod(cfr,"value"); assertNotNull(method); typeAnnotations = method.getTypeAnnotations(); assertNotNull(typeAnnotations); assertEquals(2,typeAnnotations.length); assertEquals("@LBar;(value=(int)7) METHOD_RETURN",printTypeAnnotation(typeAnnotations[0])); assertEquals("@LFoo; METHOD_RETURN", printTypeAnnotation(typeAnnotations[1])); assertEquals(((org.eclipse.jdt.internal.compiler.impl.Constant)method.getDefaultValue()).stringValue(), "aaa"); } /** * Produce a nicely formatted type annotation for testing. Exercises the API for type annotations. * Output examples:<br> * <tt>@Foo(id=34) CLASS_EXTENDS, type_index=-1, location=[ARRAY, INNER_TYPE, TYPE_ARGUMENT(0)]</tt><br> */ private String printTypeAnnotation(IBinaryTypeAnnotation typeAnnotation) { StringBuffer sb = new StringBuffer(); // The annotation: IBinaryAnnotation annotation = typeAnnotation.getAnnotation(); sb.append('@').append(annotation.getTypeName()); IBinaryElementValuePair[] pairs = annotation.getElementValuePairs(); if (pairs.length != 0) { sb.append('('); for (int i = 0; i < pairs.length; i++) { if (i > 0) { sb.append(','); } sb.append(pairs[i].getName()).append('=').append(pairs[i].getValue()); } sb.append(')'); } sb.append(' '); // target type int targetType = typeAnnotation.getTargetType(); switch (targetType) { case AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER: sb.append("CLASS_TYPE_PARAMETER(type_parameter_index=").append(typeAnnotation.getTypeParameterIndex()).append(')'); break; case AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER: sb.append("METHOD_TYPE_PARAMETER(type_parameter_index=").append(typeAnnotation.getTypeParameterIndex()).append(')'); break; case AnnotationTargetTypeConstants.CLASS_EXTENDS: sb.append("CLASS_EXTENDS(type_index=").append((short)typeAnnotation.getSupertypeIndex()).append(')'); break; case AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER_BOUND: sb.append("CLASS_TYPE_PARAMETER_BOUND(type_parameter_index="). append(typeAnnotation.getTypeParameterIndex()). append(", bound_index=").append(typeAnnotation.getBoundIndex()). append(')'); break; case AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER_BOUND: sb.append("METHOD_TYPE_PARAMETER_BOUND(type_parameter_index="). append(typeAnnotation.getTypeParameterIndex()). append(", bound_index=").append(typeAnnotation.getBoundIndex()). append(')'); break; case AnnotationTargetTypeConstants.FIELD: sb.append("FIELD"); break; case AnnotationTargetTypeConstants.METHOD_RETURN: sb.append("METHOD_RETURN"); break; case AnnotationTargetTypeConstants.METHOD_RECEIVER: sb.append("METHOD_RECEIVER"); break; case AnnotationTargetTypeConstants.METHOD_FORMAL_PARAMETER : sb.append("METHOD_FORMAL_PARAMETER(method_formal_parameter_index="). append(typeAnnotation.getMethodFormalParameterIndex()).append(')'); break; case AnnotationTargetTypeConstants.THROWS : sb.append("THROWS(throws_type_index="). append(typeAnnotation.getThrowsTypeIndex()).append(')'); break; default: throw new IllegalStateException("nyi "+targetType); } // location int[] typepath = typeAnnotation.getTypePath(); if (typepath != IBinaryTypeAnnotation.NO_TYPE_PATH) { sb.append(", location=["); //$NON-NLS-1$ for (int i = 0, max = typepath.length; i < max; i += 2) { if (i > 0) { sb.append(", "); //$NON-NLS-1$ } switch (typepath[i]) { case 0: sb.append("ARRAY"); //$NON-NLS-1$ break; case 1: sb.append("INNER_TYPE"); //$NON-NLS-1$ break; case 2: sb.append("WILDCARD"); //$NON-NLS-1$ break; case 3: sb.append("TYPE_ARGUMENT(").append(typepath[i+1]).append(')'); //$NON-NLS-1$ break; } } sb.append(']'); } return sb.toString(); } private IBinaryMethod getMethod(ClassFileReader cfr,String methodname) { IBinaryMethod[] methods = cfr.getMethods(); if (methods == null) { return null; } char[] methodnameAsCharArray = methodname.toCharArray(); for (int i = 0, max = methods.length; i < max; i++) { if (CharOperation.equals(methods[i].getSelector(),methodnameAsCharArray)) { return methods[i]; } } return null; } private IBinaryField getField(ClassFileReader cfr,String fieldname) { IBinaryField[] fields = cfr.getFields(); if (fields == null) { return null; } char[] fieldnameAsCharArray = fieldname.toCharArray(); for (int i = 0, max = fields.length; i < max; i++) { if (CharOperation.equals(fields[i].getName(),fieldnameAsCharArray)) { return fields[i]; } } return null; } }