blob: 87a3c3ca8777ac4ac5d8347e6950d3855c6aa628 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2005 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.core.tests.builder;
import java.io.*;
import java.util.*;
import junit.framework.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.resources.*;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.compiler.*;
import org.eclipse.jdt.core.dom.*;
import org.eclipse.jdt.core.tests.util.Util;
public class ParticipantBuildTests extends Tests {
public ParticipantBuildTests(String name) {
super(name);
}
public void tearDown() throws Exception {
TestBuilderParticipant.PARTICIPANT = null;
super.tearDown();
}
public static Test suite() {
if (false) {
TestSuite suite = new TestSuite(ParticipantBuildTests.class.getName());
suite.addTest(new ParticipantBuildTests("testDefaultValue"));
return suite;
}
return new TestSuite(ParticipantBuildTests.class);
}
static class BuildTestParticipant extends CompilationParticipant {
BuildTestParticipant() {
TestBuilderParticipant.PARTICIPANT = this;
}
}
static class ParticipantProblem extends CategorizedProblem implements IProblem {
int counter = 0;
String message;
int id;
char[] filename;
ParticipantProblem(String message, String filename) {
this.message = message;
id = counter ++;
this.filename = filename.toCharArray();
}
public String[] getArguments() { return new String[0]; }
public int getID() { return id; }
public String getMessage() { return message; }
public char[] getOriginatingFileName() { return filename; }
public int getSourceStart() { return 0; }
public int getSourceEnd() { return 0; }
public int getSourceLineNumber() { return 1; }
public boolean isError() { return true; }
public boolean isWarning() { return false; }
public void setSourceEnd(int sourceEnd) {/* not needed */}
public void setSourceLineNumber(int lineNumber) {/* not needed */}
public void setSourceStart(int sourceStart) {/* not needed */}
public int getCategoryID() { return 0; }
public String getMarkerType() { return "Test_Marker"; }
}
CompilationUnit buildCompilationUnit(BuildContext file) {
IJavaProject javaProject = JavaCore.create(file.getFile().getProject());
ASTParser p = ASTParser.newParser(AST.JLS3);
p.setProject(javaProject);
p.setSource(file.getContents());
p.setResolveBindings(true);
p.setKind(ASTParser.K_COMPILATION_UNIT);
p.setUnitName(file.getFile().getName());
return (CompilationUnit) p.createAST(null);
}
public void testBuildStarting() throws JavaModelException {
IPath projectPath = env.addProject("Project"); //$NON-NLS-1$
env.addExternalJars(projectPath, Util.getJavaClassLibs());
env.removePackageFragmentRoot(projectPath, ""); //$NON-NLS-1$
IPath root = env.addPackageFragmentRoot(projectPath, "src"); //$NON-NLS-1$
env.setOutputFolder(projectPath, "bin"); //$NON-NLS-1$
env.addClass(root, "", "Test", //$NON-NLS-1$ //$NON-NLS-2$
"public class Test extends GeneratedType {}\n" //$NON-NLS-1$
);
// install compilationParticipant
new BuildTestParticipant() {
boolean createFile = true;
public void buildStarting(BuildContext[] files, boolean isBatchBuild) {
// want to add a gen'ed source file that is referenced from the initial file to see if its recompiled
if (!this.createFile) return;
this.createFile = false;
BuildContext result = files[0];
IFile genedType = result.getFile().getParent().getFile(new Path("GeneratedType.java")); //$NON-NLS-1$
try {
genedType.create(new ByteArrayInputStream("public class GeneratedType {}".getBytes()), true, null); //$NON-NLS-1$
} catch (CoreException e) {
e.printStackTrace();
}
result.recordAddedGeneratedFiles(new IFile[] {genedType});
}
};
fullBuild(projectPath);
expectingNoProblems();
}
public void testDefaultValue() throws JavaModelException {
IPath projectPath = env.addProject("Project", "1.5"); //$NON-NLS-1$ //$NON-NLS-2$
env.addExternalJars(projectPath, Util.getJavaClassLibs());
env.removePackageFragmentRoot(projectPath, ""); //$NON-NLS-1$
IPath root = env.addPackageFragmentRoot(projectPath, "src"); //$NON-NLS-1$
env.setOutputFolder(projectPath, "bin"); //$NON-NLS-1$
env.addClass(root, "test", "EntryPoint", //$NON-NLS-1$ //$NON-NLS-2$
"package test;\n" + //$NON-NLS-1$
"public class EntryPoint { ClassWithNestedAnnotation nestedAnnotation; }" //$NON-NLS-1$
);
env.addClass(root, "test", "ClassWithNestedAnnotation", //$NON-NLS-1$ //$NON-NLS-2$
"package test;\n" + //$NON-NLS-1$
"public class ClassWithNestedAnnotation {\n" + //$NON-NLS-1$
" public final int FOUR = 4; \n " + //$NON-NLS-1$
" public @interface NestedAnnotation {\n" + //$NON-NLS-1$
" public enum Character { Winnie, Tiger, Piglet, Eore; }\n" + //$NON-NLS-1$
" Character value() default Character.Eore; \n" + //$NON-NLS-1$
" }\n" + //$NON-NLS-1$
"}" //$NON-NLS-1$
);
// install compilationParticipant
new BuildTestParticipant() {
public boolean isAnnotationProcessor() {
return true;
}
public void processAnnotations(BuildContext[] files) {
for (int i = 0, total = files.length; i < total; i++) {
IFile file = files[i].getFile();
// Traversing the members of test.ClassWithNestedAnnotation through a reference in EntryPoint.java
if (!"EntryPoint.java".equals(file.getName())) continue; //$NON-NLS-1$
List problems = new ArrayList();
CompilationUnit unit = buildCompilationUnit(files[i]);
List types = unit.types();
for (int t = 0, l = types.size(); t < l; t++) {
AbstractTypeDeclaration typeDecl = (AbstractTypeDeclaration) types.get(t);
ITypeBinding typeBinding = typeDecl.resolveBinding();
if (typeBinding == null) continue;
IVariableBinding[] fieldBindings = typeBinding.getDeclaredFields();
for (int f = 0, fLength = fieldBindings.length; f < fLength; f++) {
IVariableBinding field = fieldBindings[f];
if ("nestedAnnotation".equals(field.getName())) {
ITypeBinding fieldType = field.getType();
ITypeBinding[] declaredTypes = fieldType.getDeclaredTypes();
for (int d = 0, dLength = declaredTypes.length; d < dLength; d++) {
if (!"NestedAnnotation".equals(declaredTypes[d].getName())) continue;
IMethodBinding[] annotationMethods = declaredTypes[d].getDeclaredMethods();
for (int m = 0, mLength = annotationMethods.length; m < mLength; m++) {
if (!"value".equals(annotationMethods[m].getName())) continue;
Object defaultValue = annotationMethods[m].getDefaultValue();
assertTrue("Wrong class", defaultValue instanceof IVariableBinding);
IVariableBinding variableBinding = (IVariableBinding) defaultValue;
String defaultString = variableBinding.getName();
String expected = "Eore";
if (!expected.equals(defaultString)) {
IProblem problem = new ParticipantProblem("expecting default = " + expected + " not " + defaultString, file.getName());
problems.add(problem);
}
}
}
IVariableBinding[] nestedFields = fieldType.getDeclaredFields();
for (int nf = 0, nfLength = nestedFields.length; nf < nfLength; nf++) {
if (!nestedFields[nf].getName().equals("FOUR")) continue;
Object constant = nestedFields[nf].getConstantValue();
String constantStr = constant == null ? "" : constant.toString();
String expected = "4";
if (!constantStr.equals(expected))
problems.add(new ParticipantProblem("expecting constant = " + expected + " not " + constantStr, file.getName()));
}
} else {
problems.add(new ParticipantProblem("found unexpected field " + field, file.getName()));
}
}
}
if (!problems.isEmpty()) {
IProblem[] problemArray = new IProblem[problems.size()];
problemArray = (IProblem[]) problems.toArray(problemArray);
files[i].recordNewProblems(problemArray);
}
}
}
};
fullBuild(projectPath);
expectingNoProblems();
}
public void testProcessAnnotationDeclarations() throws JavaModelException {
IPath projectPath = env.addProject("Project", "1.5"); //$NON-NLS-1$ //$NON-NLS-2$
env.addExternalJars(projectPath, Util.getJavaClassLibs());
env.removePackageFragmentRoot(projectPath, ""); //$NON-NLS-1$
IPath root = env.addPackageFragmentRoot(projectPath, "src"); //$NON-NLS-1$
env.setOutputFolder(projectPath, "bin"); //$NON-NLS-1$
env.addClass(root, "", "Test", //$NON-NLS-1$ //$NON-NLS-2$
"@interface TestAnnotation {}\n" + //$NON-NLS-1$
"public class Test extends GeneratedType {}\n" //$NON-NLS-1$
);
env.addClass(root, "", "Other", //$NON-NLS-1$ //$NON-NLS-2$
"public class Other { MissingAnnotation m; }\n" //$NON-NLS-1$
);
// install compilationParticipant
new BuildTestParticipant() {
int count = 2;
public boolean isAnnotationProcessor() {
return true;
}
public void processAnnotations(BuildContext[] files) {
// want to add a gen'ed source file that is referenced from the initial file to see if its recompiled
if (this.count == 2) {
this.count--;
BuildContext result = files[0];
IFile genedType = result.getFile().getParent().getFile(new Path("MissingAnnotation.java")); //$NON-NLS-1$
try {
genedType.create(new ByteArrayInputStream("public @interface MissingAnnotation {}".getBytes()), true, null); //$NON-NLS-1$
} catch (CoreException e) {
e.printStackTrace();
}
result.recordAddedGeneratedFiles(new IFile[] {genedType});
} else if (this.count == 1) {
this.count--;
BuildContext result = files[0];
IFile genedType = result.getFile().getParent().getFile(new Path("GeneratedType.java")); //$NON-NLS-1$
try {
genedType.create(new ByteArrayInputStream("public class GeneratedType {}".getBytes()), true, null); //$NON-NLS-1$
} catch (CoreException e) {
e.printStackTrace();
}
result.recordAddedGeneratedFiles(new IFile[] {genedType});
}
}
};
fullBuild(projectPath);
expectingNoProblems();
}
public void testProcessAnnotationQualifiedReferences() throws JavaModelException {
IPath projectPath = env.addProject("Project", "1.5"); //$NON-NLS-1$ //$NON-NLS-2$
env.addExternalJars(projectPath, Util.getJavaClassLibs());
env.removePackageFragmentRoot(projectPath, ""); //$NON-NLS-1$
IPath root = env.addPackageFragmentRoot(projectPath, "src"); //$NON-NLS-1$
env.setOutputFolder(projectPath, "bin"); //$NON-NLS-1$
env.addClass(root, "p1", "Test", //$NON-NLS-1$ //$NON-NLS-2$
"package p1;\n" + //$NON-NLS-1$
"@GeneratedAnnotation\n" + //$NON-NLS-1$
"public class Test { public void method() { p1.p2.GeneratedType.method(); } }\n" //$NON-NLS-1$
);
env.addClass(root, "p1", "GeneratedAnnotation", //$NON-NLS-1$ //$NON-NLS-2$
"package p1;\n" + //$NON-NLS-1$
"@interface GeneratedAnnotation{}\n" //$NON-NLS-1$
);
// install compilationParticipant
new BuildTestParticipant() {
public boolean isAnnotationProcessor() {
return true;
}
public void processAnnotations(BuildContext[] files) {
// want to add a gen'ed source file that is referenced from the initial file to see if its recompiled
BuildContext result = files[0];
IFile genedType = result.getFile().getProject().getFile(new Path("src/p1/p2/GeneratedType.java")); //$NON-NLS-1$
if (genedType.exists()) return;
try {
IFolder folder = (IFolder) genedType.getParent();
if(!folder.exists())
folder.create(true, true, null);
genedType.create(new ByteArrayInputStream("package p1.p2; public class GeneratedType { public static void method(){} }".getBytes()), true, null); //$NON-NLS-1$
} catch (CoreException e) {
e.printStackTrace();
}
result.recordAddedGeneratedFiles(new IFile[] {genedType});
}
};
fullBuild(projectPath);
expectingNoProblems();
}
public void testProcessAnnotationReferences() throws JavaModelException {
IPath projectPath = env.addProject("Project", "1.5"); //$NON-NLS-1$ //$NON-NLS-2$
env.addExternalJars(projectPath, Util.getJavaClassLibs());
env.removePackageFragmentRoot(projectPath, ""); //$NON-NLS-1$
IPath root = env.addPackageFragmentRoot(projectPath, "src"); //$NON-NLS-1$
env.setOutputFolder(projectPath, "bin"); //$NON-NLS-1$
env.addClass(root, "", "Test", //$NON-NLS-1$ //$NON-NLS-2$
"@GeneratedAnnotation\n" + //$NON-NLS-1$
"public class Test {}\n" //$NON-NLS-1$
);
// install compilationParticipant
new BuildTestParticipant() {
public boolean isAnnotationProcessor() {
return true;
}
public void processAnnotations(BuildContext[] files) {
// want to add a gen'ed source file that is referenced from the initial file to see if its recompiled
BuildContext result = files[0];
IFile genedType = result.getFile().getParent().getFile(new Path("GeneratedAnnotation.java")); //$NON-NLS-1$
if (genedType.exists()) return;
try {
genedType.create(new ByteArrayInputStream("@interface GeneratedAnnotation {}".getBytes()), true, null); //$NON-NLS-1$
} catch (CoreException e) {
e.printStackTrace();
}
result.recordAddedGeneratedFiles(new IFile[] {genedType});
}
};
fullBuild(projectPath);
expectingNoProblems();
}
public void testResolvedMethod() throws JavaModelException {
IPath projectPath = env.addProject("Project", "1.5"); //$NON-NLS-1$ //$NON-NLS-2$
env.addExternalJars(projectPath, Util.getJavaClassLibs());
env.removePackageFragmentRoot(projectPath, ""); //$NON-NLS-1$
IPath root = env.addPackageFragmentRoot(projectPath, "src"); //$NON-NLS-1$
env.setOutputFolder(projectPath, "bin"); //$NON-NLS-1$
env.addClass(root, "", "Try", //$NON-NLS-1$ //$NON-NLS-2$
"@SuppressWarnings(\"all\")\n" + //$NON-NLS-1$
"public class Try {}" //$NON-NLS-1$
);
// install compilationParticipant
new BuildTestParticipant() {
public boolean isAnnotationProcessor() {
return true;
}
public void processAnnotations(BuildContext[] files) {
for (int i = 0, total = files.length; i < total; i++) {
IFile file = files[i].getFile();
// Traversing the members of test.ClassWithNestedAnnotation through a reference in EntryPoint.java
if (!"Try.java".equals(file.getName())) continue; //$NON-NLS-1$
List problems = new ArrayList();
CompilationUnit unit = buildCompilationUnit(files[i]);
List types = unit.types();
for (int t = 0, l = types.size(); t < l; t++) {
AbstractTypeDeclaration typeDecl = (AbstractTypeDeclaration) types.get(t);
ITypeBinding typeBinding = typeDecl.resolveBinding();
if (typeBinding == null) continue;
typeBinding = typeBinding.getAnnotations()[0].getAnnotationType();
IAnnotationBinding targetValue = typeBinding.getAnnotations()[0];
IMethodBinding method = targetValue.getDeclaredMemberValuePairs()[0].getMethodBinding();
if (!"value".equals(method.getName()))
problems.add(new ParticipantProblem("method " + method.getName() + " not found", file.getName()));
}
if (!problems.isEmpty()) {
IProblem[] problemArray = new IProblem[problems.size()];
problemArray = (IProblem[]) problems.toArray(problemArray);
files[i].recordNewProblems(problemArray);
}
}
}
};
fullBuild(projectPath);
expectingNoProblems();
}
}