return null;
}
+ public String getProcessor() {
+ return null;
+ }
+
+ public String getProcessorPath() {
+ return null;
+ }
+
}
*/
public String getProjectEncoding();
+ /**
+ * @return the list of processor classes to execute
+ */
+ public String getProcessor();
+
+ /**
+ * @return the processor path where the specified processor(s) can be found
+ */
+ public String getProcessorPath();
+
}
if (l == null) {
return null;
}
+ // If the processor options are specified build the command line options for the JDT compiler to see
+ String processor = compilerConfig.getProcessor();
+ if (processor != null && processor.length() != 0) {
+ l.add("-processor");
+ l.add(processor);
+ }
+ String processorPath = compilerConfig.getProcessorPath();
+ if (processorPath != null && processorPath.length() != 0) {
+ l.add("-processorpath");
+ l.add(processorPath);
+ }
List<String> xmlfiles = compilerConfig.getProjectXmlConfigFiles();
if (xmlfiles != null && !xmlfiles.isEmpty()) {
args = new String[l.size() + xmlfiles.size() + 1];
config.setProceedOnError(true);
config.setProjectEncoding(compilerConfig.getProjectEncoding());
+ config.setProcessor(compilerConfig.getProcessor());
+ config.setProcessorPath(compilerConfig.getProcessorPath());
return config;
}
return null;
}
+ public String getProcessor() {
+ return null;
+ }
+
+ public String getProcessorPath() {
+ return null;
+ }
+
}
return null;
}
+ public String getProcessor() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public String getProcessorPath() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
}
/* *******************************************************************
- * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * Copyright (c) 2002 - 2014 Contributors
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
* Adrian Colyer added constructor to populate javaOptions with
* default settings - 01.20.2003
* Bugzilla #29768, 29769
+ * Andy Clement
* ******************************************************************/
package org.aspectj.ajdt.internal.core.builder;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
-import org.aspectj.ajdt.ajc.BuildArgParser;
+import org.aspectj.ajdt.ajc.BuildArgParser;
import org.aspectj.ajdt.internal.compiler.CompilationResultDestinationManager;
import org.aspectj.util.FileUtil;
private List<File> changedFiles;
private List<File> files = new ArrayList<File>();
private List<File> xmlfiles = new ArrayList<File>();
+ private String processor;
+ private String processorPath;
private List<BinarySourceFile> binaryFiles = new ArrayList<BinarySourceFile>(); // .class files in indirs...
private List<File> inJars = new ArrayList<File>();
private List<File> inPath = new ArrayList<File>();
public List<File> getXmlFiles() {
return xmlfiles;
}
+
+ public void setProcessor(String processor) {
+ this.processor = processor;
+ }
+
+ /**
+ * @return the list of processor classes to execute
+ */
+ public String getProcessor() {
+ return this.processor;
+ }
+
+ public void setProcessorPath(String processorPath) {
+ this.processorPath = processorPath;
+ }
+
+ /**
+ * @return the processor path which can be searched for processors (via META-INF/services)
+ */
+ public String getProcessorPath() {
+ return this.processorPath;
+ }
/**
* returned files includes all .class files found in a directory on the inpath, but does not include .class files contained
int OUTPUTDESTINATIONS_CHANGED = 0x0100;
int INJARS_CHANGED = 0x0200; // deprecated, not in use any more
int XMLCONFIG_CHANGED = 0x0400;
+ int PROCESSOR_CHANGED = 0x0800;
int EVERYTHING = 0xffff;
}
return null;
}
+ public String getProcessor() {
+ return null;
+ }
+
+ public String getProcessorPath() {
+ return null;
+ }
+
}
class MyOutputLocationManager implements IOutputLocationManager {
--- /dev/null
+public class Code {
+ public static void main(String []argv) {
+ new Code().run();
+ }
+
+ public static void runner() {
+ new Code().run();
+ }
+
+ public void run() {
+ aaa();
+ bbb();
+ ccc();
+ ddd();
+ }
+
+ @SuppressWarnings("rawtypes")
+ public void aaa() {}
+
+ public void bbb() {}
+
+ @SuppressWarnings("rawtypes")
+ public void ccc() {}
+
+ public void ddd() {}
+}
--- /dev/null
+public class Code {
+ public static void main(String []argv) {
+ new Code().run();
+ }
+
+ public static void runner() {
+ new Code().run();
+ }
+
+ public void run() {
+ aaa();
+ bbb();
+ ccc();
+ ddd();
+ }
+
+ @SuppressWarnings("rawtypes")
+ public void aaa() {}
+
+ public void bbb() {}
+
+ @SuppressWarnings("rawtypes")
+ public void ccc() {}
+
+ public void ddd() {}
+}
--- /dev/null
+import java.io.*;
+import javax.tools.*;
+import java.util.*;
+import javax.annotation.processing.*;
+import javax.lang.model.*;
+import javax.lang.model.element.*;
+
+@SupportedAnnotationTypes(value= {"*"})
+@SupportedSourceVersion(SourceVersion.RELEASE_6)
+public class DemoProcessor extends AbstractProcessor {
+
+ private Filer filer;
+
+ @Override
+ public void init(ProcessingEnvironment env) {
+ filer = env.getFiler();
+ }
+
+ @Override
+ public boolean process(Set elements, RoundEnvironment env) {
+System.out.println("Processor running");
+ // Discover anything marked with @SuppressWarnings
+ for (Element element: env.getElementsAnnotatedWith(SuppressWarnings.class)) {
+ if (element.getKind() == ElementKind.METHOD) {
+ // For any methods we find, create an aspect:
+ String methodName = element.getSimpleName().toString();
+ String aspectText =
+ "public aspect Advise_"+methodName+" {\n"+
+ " before(): execution(* "+methodName+"(..)) {\n"+
+ " System.out.println(\""+methodName+" running\");\n"+
+ " }\n"+
+ "}\n";
+ try {
+ JavaFileObject file = filer.createSourceFile("Advise_"+methodName, element);
+ file.openWriter().append(aspectText).close();
+ System.out.println("Generated aspect to advise "+element.getSimpleName());
+ } catch (IOException ioe) {
+ // already creates message can appear if processor runs more than once
+ if (!ioe.getMessage().contains("already created")) {
+ ioe.printStackTrace();
+ }
+ }
+ }
+ }
+ return true;
+ }
+}
--- /dev/null
+import java.io.*;
+import javax.tools.*;
+import java.util.*;
+import javax.annotation.processing.*;
+import javax.lang.model.*;
+import javax.lang.model.element.*;
+
+@SupportedAnnotationTypes(value= {"*"})
+@SupportedSourceVersion(SourceVersion.RELEASE_6)
+public class DemoProcessor extends AbstractProcessor {
+
+ private Filer filer;
+
+ @Override
+ public void init(ProcessingEnvironment env) {
+ filer = env.getFiler();
+ }
+
+ @Override
+ public boolean process(Set elements, RoundEnvironment env) {
+System.out.println("Processor running");
+ // Discover anything marked with @SuppressWarnings
+ for (Element element: env.getElementsAnnotatedWith(SuppressWarnings.class)) {
+ if (element.getKind() == ElementKind.METHOD) {
+ // For any methods we find, create an aspect:
+ String methodName = element.getSimpleName().toString();
+ String aspectText =
+ "public aspect Advise_"+methodName+" {\n"+
+ " before(): execution(* "+methodName+"(..)) {\n"+
+ " System.out.println(\""+methodName+" running\");\n"+
+ " }\n"+
+ "}\n";
+ try {
+ JavaFileObject file = filer.createSourceFile("Advise_"+methodName, element);
+ file.openWriter().append(aspectText).close();
+ System.out.println("Generated aspect to advise "+element.getSimpleName());
+ } catch (IOException ioe) {
+ // already creates message can appear if processor runs more than once
+ if (!ioe.getMessage().contains("already created")) {
+ ioe.printStackTrace();
+ }
+ }
+ }
+ }
+ return true;
+ }
+}
--- /dev/null
+DemoProcessor
--- /dev/null
+import java.io.*;
+import javax.tools.*;
+import java.util.*;
+import javax.annotation.processing.*;
+import javax.lang.model.*;
+import javax.lang.model.element.*;
+
+@SupportedAnnotationTypes(value= {"java.lang.SuppressWarnings"})
+@SupportedSourceVersion(SourceVersion.RELEASE_6)
+public class DemoProcessor2 extends AbstractProcessor {
+
+ private Filer filer;
+
+ @Override
+ public void init(ProcessingEnvironment env) {
+ filer = env.getFiler();
+ }
+
+ @Override
+ public boolean process(Set elements, RoundEnvironment env) {
+System.out.println("Processor (around) running");
+ // Discover anything marked with @SuppressWarnings
+ for (Element element: env.getElementsAnnotatedWith(SuppressWarnings.class)) {
+ if (element.getKind() == ElementKind.METHOD) {
+ // For any methods we find, create an aspect:
+ String methodName = element.getSimpleName().toString();
+ String aspectText =
+ "public aspect AroundAdvise_"+methodName+" {\n"+
+ " void around(): execution(* "+methodName+"(..)) {\n"+
+ " System.out.println(\"Around advice on "+methodName+" running\");\n"+
+ " }\n"+
+ "}\n";
+ try {
+ JavaFileObject file = filer.createSourceFile("AroundAdvise_"+methodName, element);
+ file.openWriter().append(aspectText).close();
+ System.out.println("Generated aspect with around advice to advise "+element.getSimpleName());
+ } catch (IOException ioe) {
+ // already creates message can appear if processor runs more than once
+ if (!ioe.getMessage().contains("already created")) {
+ ioe.printStackTrace();
+ }
+ }
+ }
+ }
+ return false;
+ }
+}
--- /dev/null
+DemoProcessor2
import org.aspectj.systemtest.ajc166.AllTestsAspectJ166;
import org.aspectj.systemtest.ajc167.AllTestsAspectJ167;
import org.aspectj.systemtest.ajc169.AllTestsAspectJ169;
+import org.aspectj.systemtest.incremental.tools.AnnotationProcessingTests;
public class AllTests16 {
suite.addTest(AllTestsAspectJ1610.suite());
suite.addTest(AllTestsAspectJ1611.suite());
suite.addTest(AllTestsAspectJ1612.suite());
+ suite.addTestSuite(AnnotationProcessingTests.class);
// $JUnit-END$
return suite;
}
package org.aspectj.systemtest.incremental.tools;
import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
+import java.io.PrintStream;
import java.io.PrintWriter;
+import java.net.URL;
+import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
AjState.FORCE_INCREMENTAL_DURING_TESTING = false;
}
+ protected String runMethod(String projectName, String classname, String methodname) throws Exception {
+ File f = getProjectOutputRelativePath(projectName, "");
+ ClassLoader cl = new URLClassLoader(new URL[] { f.toURI().toURL() });
+ Class<?> clazz = Class.forName(classname, false, cl);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintStream realOut = System.out;
+ try {
+ System.setOut(new PrintStream(baos));
+ clazz.getDeclaredMethod(methodname).invoke(null);
+ } finally {
+ System.setOut(realOut);
+ }
+ return new String(baos.toByteArray());
+ }
+
+ protected File getProjectOutputRelativePath(String p, String filename) {
+ File projDir = new File(getWorkingDir(), p);
+ return new File(projDir, "bin" + File.separator + filename);
+ }
+
public void build(String projectName) {
constructUpToDateLstFile(projectName, "build.lst");
doBuild(projectName);
((MultiProjTestCompilerConfiguration) compiler.getCompilerConfiguration()).setAspectPath(aspectpath);
}
+ public void configureProcessor(String projectName, String processor) {
+ AjCompiler compiler = CompilerFactory.getCompilerForProjectWithDir(sandboxDir + File.separator + projectName);
+ ((MultiProjTestCompilerConfiguration) compiler.getCompilerConfiguration()).setProcessor(processor);
+ }
+
+ public void configureProcessorPath(String projectName, String processorPath) {
+ AjCompiler compiler = CompilerFactory.getCompilerForProjectWithDir(sandboxDir + File.separator + projectName);
+ ((MultiProjTestCompilerConfiguration) compiler.getCompilerConfiguration()).setProcessorPath(processorPath);
+ }
+
public void configureAspectPath(String projectName, File aspectpath) {
AjCompiler compiler = CompilerFactory.getCompilerForProjectWithDir(sandboxDir + File.separator + projectName);
Set<File> s = new HashSet<File>();
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2014 Contributors
+ * 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 - initial API and implementation
+ *******************************************************************************/
+package org.aspectj.systemtest.incremental.tools;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+
+public class AnnotationProcessingTests extends AbstractMultiProjectIncrementalAjdeInteractionTestbed {
+
+ // Basic test: turns on annotation processing and tries to run the DemoProcessor
+ public void testAnnotationProcessing1() throws Exception {
+ createAndBuildAnnotationProcessorProject("ProcessorProject");
+ initialiseProject("ProcessorConsumer1");
+ configureProcessorOptions("ProcessorConsumer1","DemoProcessor");
+ configureNonStandardCompileOptions("ProcessorConsumer1", "-showWeaveInfo");
+
+ Hashtable<String, String> javaOptions = new Hashtable<String, String>();
+ javaOptions.put("org.eclipse.jdt.core.compiler.compliance", "1.6");
+ javaOptions.put("org.eclipse.jdt.core.compiler.codegen.targetPlatform", "1.6");
+ javaOptions.put("org.eclipse.jdt.core.compiler.source", "1.6");
+ javaOptions.put("org.eclipse.jdt.core.compiler.processAnnotations","enabled");
+ configureJavaOptionsMap("ProcessorConsumer1", javaOptions);
+
+ configureNewProjectDependency("ProcessorConsumer1", "ProcessorProject");
+ configureNonStandardCompileOptions("ProcessorConsumer1", "-showWeaveInfo");
+ build("ProcessorConsumer1");
+ checkWasFullBuild();
+ checkCompiledFiles("ProcessorConsumer1","Advise_ccc.java","Advise_aaa.java","Code.java");
+ assertEquals(2,getWeavingMessages("ProcessorConsumer1").size());
+ String out = runMethod("ProcessorConsumer1", "Code", "runner");
+ assertEquals("aaa running\nccc running\n",out);
+ }
+
+ // services file in processor project
+ public void testAnnotationProcessing2() throws Exception {
+ createAndBuildAnnotationProcessorProject("ProcessorProject2"); // This has a META-INF services entry for DemoProcessor
+
+ initialiseProject("ProcessorConsumer2");
+ // Paths here are the path to DemoProcessor (compiled into the output folder of the ProcessorProject2) and the path to
+ // the META-INF file declaring DemoProcessor (since it is not copied to that same output folder) - this exists in the test src
+ // folder for ProcessorProject2
+ configureProcessorPath("ProcessorConsumer2", getCompilerForProjectWithName("ProcessorProject2").getCompilerConfiguration().getOutputLocationManager().getDefaultOutputLocation().toString()+File.pathSeparator+
+ new File(testdataSrcDir + File.separatorChar + "ProcessorProject2" + File.separatorChar + "base"+File.separatorChar+"src").toString());
+
+ Hashtable<String, String> javaOptions = new Hashtable<String, String>();
+ javaOptions.put("org.eclipse.jdt.core.compiler.compliance", "1.6");
+ javaOptions.put("org.eclipse.jdt.core.compiler.codegen.targetPlatform", "1.6");
+ javaOptions.put("org.eclipse.jdt.core.compiler.source", "1.6");
+ javaOptions.put("org.eclipse.jdt.core.compiler.processAnnotations","enabled");
+ configureJavaOptionsMap("ProcessorConsumer2", javaOptions);
+ initialiseProject("ProcessorConsumer2");
+ configureNewProjectDependency("ProcessorConsumer2", "ProcessorProject");
+ configureNonStandardCompileOptions("ProcessorConsumer2", "-showWeaveInfo");
+ build("ProcessorConsumer2");
+ checkWasFullBuild();
+ checkCompiledFiles("ProcessorConsumer2","Advise_ccc.java","Advise_aaa.java","Code.java");
+ assertEquals(2,getWeavingMessages("ProcessorConsumer2").size());
+ String out = runMethod("ProcessorConsumer2", "Code", "runner");
+ assertEquals("aaa running\nccc running\n",out);
+ }
+
+ // Two processors
+ public void testAnnotationProcessing3() throws Exception {
+ createAndBuildAnnotationProcessorProject("ProcessorProject2");
+ createAndBuildAnnotationProcessorProject("ProcessorProject3");
+ initialiseProject("ProcessorConsumer1");
+ // Paths here are the path to DemoProcessor/DemoProcessor2 compiled code and the path to
+ // the META-INF file declaring DemoProcessor/DemoProcessor2 (since they are not copied to that same output folder) -
+ // these exists in the test src folders for ProcessorProject2/ProcessorProject3
+ configureProcessorPath("ProcessorConsumer1",
+ getCompilerForProjectWithName("ProcessorProject3").getCompilerConfiguration().getOutputLocationManager().getDefaultOutputLocation().toString()+File.pathSeparator+
+ new File(testdataSrcDir + File.separatorChar + "ProcessorProject3" + File.separatorChar + "base"+File.separatorChar+"src").toString()
+ +File.pathSeparator+
+ getCompilerForProjectWithName("ProcessorProject2").getCompilerConfiguration().getOutputLocationManager().getDefaultOutputLocation().toString()+File.pathSeparator+
+ new File(testdataSrcDir + File.separatorChar + "ProcessorProject2" + File.separatorChar + "base"+File.separatorChar+"src").toString()
+ );
+
+ // The order here is DemoProcessor2 then DemoProcessor - to get the second one to run I changed DemoProcessor2 to operate on a
+ // specific annotation (java.lang.SuppressWarnings) and return false at the end
+
+ configureNonStandardCompileOptions("ProcessorConsumer1", "-showWeaveInfo");
+
+ Hashtable<String, String> javaOptions = new Hashtable<String, String>();
+ javaOptions.put("org.eclipse.jdt.core.compiler.compliance", "1.6");
+ javaOptions.put("org.eclipse.jdt.core.compiler.codegen.targetPlatform", "1.6");
+ javaOptions.put("org.eclipse.jdt.core.compiler.source", "1.6");
+ javaOptions.put("org.eclipse.jdt.core.compiler.processAnnotations","enabled");
+ configureJavaOptionsMap("ProcessorConsumer1", javaOptions);
+
+ configureNewProjectDependency("ProcessorConsumer1", "ProcessorProject");
+ configureNonStandardCompileOptions("ProcessorConsumer1", "-showWeaveInfo");
+ build("ProcessorConsumer1");
+ checkWasFullBuild();
+ checkCompiledFiles("ProcessorConsumer1","Advise_ccc.java","Advise_aaa.java","Code.java","AroundAdvise_ccc.java","AroundAdvise_aaa.java");
+ assertEquals(4,getWeavingMessages("ProcessorConsumer1").size());
+ String out = runMethod("ProcessorConsumer1", "Code", "runner");
+ assertEquals("aaa running\nAround advice on aaa running\nccc running\nAround advice on ccc running\n",out);
+ }
+
+ // Tests:
+ // TODO Incremental compilation - what does that mean with annotation processors?
+
+ // ---
+
+ private void createAndBuildAnnotationProcessorProject(String processorProjectName) {
+ initialiseProject(processorProjectName);
+ build(processorProjectName);
+ checkWasFullBuild();
+ assertNoErrors(processorProjectName);
+ }
+
+ private void configureProcessorOptions(String projectName, String processor) {
+ configureProcessor(projectName, "DemoProcessor");
+ // Assume all processors from processor project
+ configureProcessorPath(projectName, getCompilerForProjectWithName("ProcessorProject").getCompilerConfiguration().getOutputLocationManager().getDefaultOutputLocation().toString());
+ }
+
+ private void checkCompiledFiles(String projectName, String... expectedCompiledFiles) {
+ List<String> compiledFiles = new ArrayList<String>(getCompiledFiles(projectName));
+ if (compiledFiles.size()!=expectedCompiledFiles.length) {
+ fail("Expected #"+expectedCompiledFiles.length+" files to be compiled but found that #"+compiledFiles.size()+" files were compiled.\nCompiled="+compiledFiles);
+ }
+ for (String expectedCompiledFile: expectedCompiledFiles) {
+ String toRemove = null;
+ for (String compiledFile: compiledFiles) {
+ String cfile = compiledFile.substring(compiledFile.lastIndexOf("/")+1);
+ if (cfile.equals(expectedCompiledFile)) {
+ toRemove = compiledFile;
+ break;
+ }
+ }
+ if (toRemove!=null) compiledFiles.remove(toRemove);
+ }
+ // Anything left in compiledFiles wasn't expected to be built
+ if (compiledFiles.size()!=0) {
+ fail("These were not expected to be compiled: "+compiledFiles);
+ }
+ }
+
+
+}
private Set<File> inpath;
private String encoding = null;
private String outjar;
+ private String processor;
+ private String processorPath;
private String nonstandardoptions;
private List modifiedFiles;
private List modifiedDirs;
this.outjar = outjar;
this.changed |= ICompilerConfiguration.OUTJAR_CHANGED;
}
+
+ public void setProcessor(String processor) {
+ this.processor = processor;
+ this.changed |= ICompilerConfiguration.PROCESSOR_CHANGED;
+ }
+
+ public void setProcessorPath(String processorPath) {
+ this.processorPath = processorPath;
+ this.changed |= ICompilerConfiguration.PROCESSOR_CHANGED;
+ }
public void setJavaOptions(Map javaOptions) {
this.javaOptionsMap = javaOptions;
return this.encoding;
}
+ public String getProcessor() {
+ return this.processor;
+ }
+
+ public String getProcessorPath() {
+ return this.processorPath;
+ }
+
}
runMethod(p, "demo.ConverterTest", "run");
}
- private void runMethod(String projectName, String classname, String methodname) throws Exception {
- File f = getProjectOutputRelativePath(projectName, "");
- ClassLoader cl = new URLClassLoader(new URL[] { f.toURI().toURL() });
- Class<?> clazz = Class.forName(classname, false, cl);
- clazz.getDeclaredMethod(methodname).invoke(null);
- }
public void testIncrementalITDInners4() throws Exception {
String p = "prInner4";
checkCompileWeaveCount("P1", 5, 3); // we compile X and A (the delta)
// find out that
// an aspect has changed, go back to the source
- // and compile X,A,C, then weave them all.
+ // and compile X,A,C, then weave the all.
build("P1");
long timeTakenForSimpleIncBuild = getTimeTakenForBuild("P1");
// I don't think this test will have timing issues as the times should
+ "ms second=" + timeTakenForSimpleIncBuild + "ms", timeTakenForSimpleIncBuild < timeTakenForFullBuildAndWeave);
}
+ @SuppressWarnings("rawtypes")
public void testBuildingTwoProjectsInTurns() {
initialiseProject("P1");
initialiseProject("P2");
build("P2");
checkWasntFullBuild();
}
-
+
public void testBuildingBrokenCode_pr240360() {
initialiseProject("pr240360");
// configureNonStandardCompileOptions("pr240360","-proceedOnError");
}
}
- protected File getProjectOutputRelativePath(String p, String filename) {
- File projDir = new File(getWorkingDir(), p);
- return new File(projDir, "bin" + File.separator + filename);
- }
-
}
\ No newline at end of file