/******************************************************************************* * Copyright (c) 2005, 2013 BEA Systems, Inc. * 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: * tyeung@bea.com - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.apt.tests; import java.io.File; import java.util.HashSet; import junit.framework.Test; import junit.framework.TestSuite; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jdt.apt.tests.annotations.readannotation.CodeExample; import org.eclipse.jdt.apt.tests.plugin.AptTestsPlugin; import org.eclipse.jdt.core.BindingKey; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTParser; import org.eclipse.jdt.core.dom.ASTRequestor; import org.eclipse.jdt.core.dom.IAnnotationBinding; import org.eclipse.jdt.core.dom.IBinding; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.IVariableBinding; import org.eclipse.jdt.core.tests.builder.BuilderTests; import org.eclipse.jdt.core.tests.util.Util; /** * This test the dom layer of annotation support. No APT involved. * @author tyeung */ public class ReadAnnotationTests2 extends BuilderTests { private String[] NO_ANNOTATIONS = new String[0]; private ICompilationUnit[] NO_UNIT = new ICompilationUnit[0]; private int counter = 0; private String projectName = null; public ReadAnnotationTests2(final String name) { super( name ); } public static Test suite() { return new TestSuite( ReadAnnotationTests2.class ); } public String getProjectName() { return projectName; } public String getUniqueProjectName(){ projectName = ReadAnnotationTests.class.getName() + "Project" + counter; //$NON-NLS-1$ counter ++; return projectName; } public IPath getSourcePath() { IProject project = env.getProject( getProjectName() ); IFolder srcFolder = project.getFolder( "src" ); //$NON-NLS-1$ IPath srcRoot = srcFolder.getFullPath(); return srcRoot; } public IPath getBinaryPath(){ IProject project = env.getProject( getProjectName() ); IFolder srcFolder = project.getFolder( "binary" ); //$NON-NLS-1$ IPath lib = srcFolder.getFullPath(); return lib; } public IPath getOutputPath(){ IProject project = env.getProject( getProjectName() ); IFolder binFolder = project.getFolder( "bin" ); //$NON-NLS-1$ IPath bin = binFolder.getFullPath(); return bin; } private void addAllSources() { IPath srcRoot = getSourcePath(); // SimpleAnnotation.java env.addClass( srcRoot, CodeExample.PACKAGE_QUESTION, CodeExample.SIMPLE_ANNOTATION_CLASS, CodeExample.SIMPLE_ANNOTATION_CODE ); // RTVisibleAnnotation.java env.addClass( srcRoot, CodeExample.PACKAGE_QUESTION, CodeExample.RTVISIBLE_CLASS, CodeExample.RTVISIBLE_ANNOTATION_CODE); // RTInvisibleAnnotation.java env.addClass( srcRoot, CodeExample.PACKAGE_QUESTION, CodeExample.RTINVISIBLE_CLASS, CodeExample.RTINVISIBLE_ANNOTATION_CODE); // package-info.java env.addClass( srcRoot, CodeExample.PACKAGE_QUESTION, CodeExample.PACKAGE_INFO_CLASS, CodeExample.PACKAGE_INFO_CODE); // Color.java env.addClass( srcRoot, CodeExample.PACKAGE_QUESTION, CodeExample.COLOR_CLASS, CodeExample.COLOR_CODE); // AnnotationTest.java env.addClass( srcRoot, CodeExample.PACKAGE_QUESTION, CodeExample.ANNOTATION_TEST_CLASS, CodeExample.ANNOTATION_TEST_CODE); } private IProject setupTest() throws Exception { // project will be deleted by super-class's tearDown() method IPath projectPath = env.addProject( getUniqueProjectName(), "1.5" ); //$NON-NLS-1$ env.setOutputFolder(projectPath, "bin"); //$NON-NLS-1$ env.addExternalJars( projectPath, Util.getJavaClassLibs() ); IJavaProject jproj = env.getJavaProject(projectPath); jproj.setOption("org.eclipse.jdt.core.compiler.problem.deprecation", "ignore"); // remove old package fragment root so that names don't collide env.removePackageFragmentRoot( projectPath, "" ); //$NON-NLS-1$ env.addPackageFragmentRoot( projectPath, "src" ); //$NON-NLS-1$ return env.getProject(getProjectName()); } public void testSourceAnnotation() throws Exception { // reset the error reset the error; IProject project = setupTest(); addAllSources(); fullBuild( project.getFullPath() ); expectingNoProblems(); _testAnnotations(); } public void testBinaryAnnotation() throws Exception { IProject project = setupTest(); final File jar = TestUtil.getFileInPlugin(AptTestsPlugin.getDefault(), new Path("/resources/question.jar")); //$NON-NLS-1$ final String path = jar.getAbsolutePath(); env.addExternalJar(project.getFullPath(), path); fullBuild( project.getFullPath() ); expectingNoProblems(); _testAnnotations(); } private ITypeBinding getTypeBinding(final String key, final IJavaProject javaProj) { class BindingRequestor extends ASTRequestor { private ITypeBinding _result = null; public void acceptBinding(String bindingKey, IBinding binding) { if( binding != null && binding.getKind() == IBinding.TYPE ) _result = (ITypeBinding)binding; } } final BindingRequestor requestor = new BindingRequestor(); final ASTParser parser = ASTParser.newParser(AST.JLS8); parser.setResolveBindings(true); parser.setProject(javaProj); parser.setIgnoreMethodBodies(true); parser.createASTs(NO_UNIT, new String[]{key}, requestor, null); return requestor._result; } public void _testAnnotations() { final String typeKey = BindingKey.createTypeBindingKey("question.AnnotationTest"); final ITypeBinding typeBinding = getTypeBinding(typeKey, env.getJavaProject(getProjectName())); assertNotNull("failed to locate 'question.AnnotationTest'", typeBinding); assertEquals("Type name mismatch", "question.AnnotationTest", typeBinding.getQualifiedName()); // test package annotation final String[] expectedPkgAnnos = new String[]{ "@Deprecated()" }; assertAnnotation(expectedPkgAnnos, typeBinding.getPackage().getAnnotations() ); // test annotation on type. final String[] expectedTypeAnnos = new String[]{ "@Deprecated()", "@RTVisibleAnno(anno = @SimpleAnnotation(value = test), clazzes = {})", "@RTInvisibleAnno(value = question)" }; assertAnnotation(expectedTypeAnnos, typeBinding.getAnnotations()); final IVariableBinding[] fieldBindings = typeBinding.getDeclaredFields(); int counter = 0; assertEquals(5, fieldBindings.length); for(IVariableBinding fieldDecl : fieldBindings ){ final String name = "field" + counter; assertEquals("field name mismatch", name, fieldDecl.getName()); final String[] expected; switch(counter){ case 0: expected = new String[] { "@RTVisibleAnno(name = Foundation, boolValue = false, byteValue = 16, charValue = c, doubleValue = 99.0, floatValue = 9.0, intValue = 999, longValue = 3333, shortValue = 3, colors = {question.Color RED, question.Color BLUE}, anno = @SimpleAnnotation(value = core), simpleAnnos = {@SimpleAnnotation(value = org), @SimpleAnnotation(value = eclipse), @SimpleAnnotation(value = jdt)}, clazzes = {Object.class, String.class}, clazz = Object.class)", "@RTInvisibleAnno(value = org.eclipse.jdt.core)", "@Deprecated()" }; break; case 1: expected = new String[] { "@Deprecated()" }; break; case 2: expected = new String[] { "@RTVisibleAnno(anno = @SimpleAnnotation(value = field), clazzes = {})", "@RTInvisibleAnno(value = 2)" }; break; case 3: expected = new String[] { "@RTInvisibleAnno(value = 3)" }; break; case 4: expected = new String[] { "@SimpleAnnotation(value = 4)" }; break; default: expected = NO_ANNOTATIONS; } assertAnnotation(expected, fieldDecl.getAnnotations()); counter ++; } final IMethodBinding[] methodBindings = typeBinding.getDeclaredMethods(); counter = 0; assertEquals(7, methodBindings.length); for(IMethodBinding methodDecl : methodBindings ){ final String name = "method" + counter; assertEquals("method name mismatch", name, methodDecl.getName()); final String[] expected; switch(counter) { case 0: expected = new String[] { "@RTVisibleAnno(anno = @SimpleAnnotation(value = method0), clazzes = {})", "@RTInvisibleAnno(value = 0)", "@Deprecated()" }; break; case 1: expected = new String[] { "@Deprecated()" }; break; case 2: expected = new String[] { "@RTVisibleAnno(anno = @SimpleAnnotation(value = method2), clazzes = {})", "@RTInvisibleAnno(value = 2)" }; break; case 3: expected = new String[] { "@RTInvisibleAnno(value = 3)" }; break; case 4: expected = new String[] { "@SimpleAnnotation(value = method4)" }; break; case 5: case 6: default: expected = NO_ANNOTATIONS; } assertAnnotation(expected, methodDecl.getAnnotations()); if( counter == 5 ){ final int numParameters = methodDecl.getParameterTypes().length; for( int pCounter=0; pCounter<numParameters; pCounter++ ){ final String[] expectedParamAnnotations; switch( pCounter ) { case 1: expectedParamAnnotations = new String[] { "@Deprecated()" }; break; case 2: expectedParamAnnotations = new String[] { "@RTVisibleAnno(anno = @SimpleAnnotation(value = param2), clazzes = {})", "@RTInvisibleAnno(value = 2)" }; break; default: expectedParamAnnotations = NO_ANNOTATIONS; } assertAnnotation(expectedParamAnnotations, methodDecl.getParameterAnnotations(pCounter)); } } counter ++; } } private void assertAnnotation(final String[] expected, IAnnotationBinding[] annotations) { final int expectedLen = expected.length; assertEquals("annotation number mismatch", expected.length, annotations.length); //$NON-NLS-1$ final HashSet<String> expectedSet = new HashSet<String>(expectedLen * 4 / 3 + 1); for( int i=0; i<expectedLen; i++ ) expectedSet.add(expected[i]); int counter = 0; for( IAnnotationBinding mirror : annotations ){ if( counter >= expectedLen ) assertEquals("", mirror.toString()); //$NON-NLS-1$ else{ final String mirrorToString = mirror.toString(); final boolean contains = expectedSet.contains(mirrorToString); if( !contains ){ System.err.println(mirrorToString); System.err.println(expectedSet); } assertTrue("unexpected annotation " + mirrorToString, contains); //$NON-NLS-1$ expectedSet.remove(mirrorToString); } counter ++; } } }