| /******************************************************************************* |
| * Copyright (c) 2013, 2019 GoPivotal, Inc. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * 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 java.io.File; |
| |
| 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"); |
| } |
| |
| public void testBug548596() { |
| /*- |
| * Test548596.jar contains classes for the following kotlin code (compiled with kotlin 1.3.21): |
| * package k; |
| * class A { |
| * class B { |
| * class C { |
| * // |
| * } |
| * } |
| * } |
| */ |
| String[] libs = getDefaultClassPaths(); |
| int len = libs.length; |
| System.arraycopy(libs, 0, libs = new String[len+1], 0, len); |
| libs[libs.length-1] = this.getCompilerTestsPluginDirectoryPath() + File.separator + "workspace" + File.separator + "Test548596.jar"; |
| |
| runConformTest( |
| new String[] { |
| "j/Usage.java", |
| "package j;\n" + |
| "\n" + |
| "import k.A.B.C;\n" + |
| "\n" + |
| "public class Usage {\n" + |
| " C c;\n" + |
| "}" |
| }, |
| "", |
| libs, |
| false, |
| null |
| ); |
| } |
| |
| /** |
| * 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; |
| } |
| |
| } |