From a5ad3bdbf48e3d893f3e871682d7548f17b85f8e Mon Sep 17 00:00:00 2001
From: Michal Srb <msrb@redhat.com>
Date: Wed, 25 Jun 2014 18:53:52 +0200
Subject: [PATCH] Port to JSR-269

Initial attempt
---
 .../com.sun.mirror.apt.AnnotationProcessorFactory  |   1 -
 .../services/javax.annotation.processing.Processor |   1 +
 .../yuanheng/cookcc/input/javaap/ClassVisitor.java | 190 ++++++++++-----------
 .../cookcc/input/javaap/CookCCAptFactory.java      |  97 -----------
 .../cookcc/input/javaap/CookCCProcessor.java       |  83 +++++++--
 .../cookcc/input/javaap/CookCCVisitor.java         | 145 ++++++----------
 .../yuanheng/cookcc/input/javaap/EnumVisitor.java  |  82 +++------
 7 files changed, 228 insertions(+), 371 deletions(-)
 delete mode 100644 javaap_src/META-INF/services/com.sun.mirror.apt.AnnotationProcessorFactory
 create mode 100644 javaap_src/META-INF/services/javax.annotation.processing.Processor
 delete mode 100644 javaap_src/org/yuanheng/cookcc/input/javaap/CookCCAptFactory.java

diff --git a/javaap_src/META-INF/services/com.sun.mirror.apt.AnnotationProcessorFactory b/javaap_src/META-INF/services/com.sun.mirror.apt.AnnotationProcessorFactory
deleted file mode 100644
index c3a572f..0000000
--- a/javaap_src/META-INF/services/com.sun.mirror.apt.AnnotationProcessorFactory
+++ /dev/null
@@ -1 +0,0 @@
-org.yuanheng.cookcc.input.javaap.CookCCAptFactory
\ No newline at end of file
diff --git a/javaap_src/META-INF/services/javax.annotation.processing.Processor b/javaap_src/META-INF/services/javax.annotation.processing.Processor
new file mode 100644
index 0000000..3f398d6
--- /dev/null
+++ b/javaap_src/META-INF/services/javax.annotation.processing.Processor
@@ -0,0 +1 @@
+org.yuanheng.cookcc.input.javaap.CookCCProcessor
diff --git a/javaap_src/org/yuanheng/cookcc/input/javaap/ClassVisitor.java b/javaap_src/org/yuanheng/cookcc/input/javaap/ClassVisitor.java
index a885852..48ca76a 100644
--- a/javaap_src/org/yuanheng/cookcc/input/javaap/ClassVisitor.java
+++ b/javaap_src/org/yuanheng/cookcc/input/javaap/ClassVisitor.java
@@ -27,24 +27,41 @@
 
 package org.yuanheng.cookcc.input.javaap;
 
+import java.io.File;
+import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Map;
 
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.type.NoType;
+import javax.lang.model.util.SimpleElementVisitor6;
+import javax.lang.model.util.Types;
+
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.tree.LineMap;
+import com.sun.source.tree.Tree;
+import com.sun.source.util.SourcePositions;
+import com.sun.source.util.TreePath;
+import com.sun.source.util.Trees;
+
 import org.yuanheng.cookcc.*;
 import org.yuanheng.cookcc.doc.*;
 
-import com.sun.mirror.declaration.*;
-import com.sun.mirror.type.ClassType;
-import com.sun.mirror.type.DeclaredType;
-import com.sun.mirror.util.DeclarationVisitor;
-import com.sun.mirror.util.SourcePosition;
-
 /**
  * @author Heng Yuan
  * @version $Id: ClassVisitor.java 674 2009-07-22 03:18:36Z superduperhengyuan $
  */
-class ClassVisitor implements DeclarationVisitor
+class ClassVisitor<R, P> extends SimpleElementVisitor6<R, P>
 {
 	private final static String PROP_OUTPUT = "outputClass";
 	private final static String PROP_INPUT = "inputClass";
@@ -124,26 +141,47 @@ class ClassVisitor implements DeclarationVisitor
 		return buffer.toString ();
 	}
 
-	static int getAnnotationLineNumber (MethodDeclaration method, String className)
+	private static File getFile(Element element, ProcessingEnvironment env) {
+	    Trees trees = Trees.instance(env);
+	    SourcePositions sourcePositions = trees.getSourcePositions();
+	    TreePath treePath = trees.getPath(element);
+	    CompilationUnitTree compUnitTree = treePath.getCompilationUnit();
+
+	    return new File(compUnitTree.getSourceFile().toUri().getPath());
+	}
+
+	private static int getLineNumber(Element element, ProcessingEnvironment env) {
+	    Trees trees = Trees.instance(env);
+	    SourcePositions sourcePositions = trees.getSourcePositions();
+	    TreePath treePath = trees.getPath(element);
+	    CompilationUnitTree compUnitTree = treePath.getCompilationUnit();
+	    Tree leaf = treePath.getLeaf();
+	    long startPos = sourcePositions.getStartPosition(compUnitTree, leaf);
+	    long endPos = sourcePositions.getEndPosition(compUnitTree, leaf);
+	    LineMap lineMap = compUnitTree.getLineMap();
+
+	    return (int) lineMap.getLineNumber(startPos);
+	}
+
+	static int getAnnotationLineNumber (ExecutableElement method, String className, ProcessingEnvironment env)
 	{
 		for (AnnotationMirror mirror : method.getAnnotationMirrors ())
 		{
-			if (!className.equals (mirror.getAnnotationType ().getDeclaration ().getQualifiedName ()))
+			if (!className.equals (((TypeElement) mirror.getAnnotationType ().asElement()).getQualifiedName ()))
 				continue;
-			SourcePosition pos = mirror.getPosition ();
-			return pos == null ? 0 : pos.line ();
+			return getLineNumber(mirror.getAnnotationType().asElement(), env);
 		}
 		return 0;
 	}
 
-	static int[] getAnnotationArrayLineNumbers (MethodDeclaration method, String className, String attr)
+	static int[] getAnnotationArrayLineNumbers (ExecutableElement method, String className, String attr, ProcessingEnvironment env)
 	{
 		for (AnnotationMirror mirror : method.getAnnotationMirrors ())
 		{
-			if (!className.equals (mirror.getAnnotationType ().getDeclaration ().getQualifiedName ()))
+			if (!className.equals (((TypeElement) mirror.getAnnotationType().asElement()).getQualifiedName ()))
 				continue;
-			Map<AnnotationTypeElementDeclaration, AnnotationValue> map = mirror.getElementValues ();
-			for (AnnotationTypeElementDeclaration key : map.keySet ())
+			Map<? extends ExecutableElement, ? extends AnnotationValue> map = mirror.getElementValues ();
+			for (ExecutableElement key : map.keySet ())
 			{
 				if (!attr.equals (key.getSimpleName ()))
 					continue;
@@ -155,11 +193,7 @@ class ClassVisitor implements DeclarationVisitor
 				for (Object o : c)
 				{
 					AnnotationValue v = (AnnotationValue)o;
-					SourcePosition pos = v.getPosition ();
-					if (pos == null)
-						returnVal[i++] = 0;
-					else
-						returnVal[i++] = pos.line ();
+					returnVal[i++] = getLineNumber((Element) v.getValue(), env);
 				}
 				return returnVal;
 			}
@@ -167,11 +201,10 @@ class ClassVisitor implements DeclarationVisitor
 		return null;
 	}
 
-	private static String computeOutputClass (ClassType classType)
+	private static String computeOutputClass (DeclaredType classType, ProcessingEnvironment env)
 	{
-		DeclaredType containingType = classType.getContainingType ();
-		if (containingType == null)
-			return classType.getDeclaration ().getQualifiedName ();
+		if (classType.getEnclosingType() == env.getTypeUtils().getNoType(TypeKind.NONE))
+			return ((TypeElement) classType.asElement()).getQualifiedName().toString();
 		throw new IllegalArgumentException ("The generated class cannot be a nested class.");
 	}
 
@@ -231,34 +264,32 @@ class ClassVisitor implements DeclarationVisitor
 		getLexer ().addShortcut (shortcutDoc);
 	}
 
-	private void parseLexs (Lexs lexs, MethodDeclaration method)
+	private void parseLexs (Lexs lexs, ExecutableElement method)
 	{
 		if (lexs == null)
 			return;
 
-		int[] pos = getAnnotationArrayLineNumbers (method, Lexs.class.getName (), "patterns");
+		int[] pos = getAnnotationArrayLineNumbers (method, Lexs.class.getName (), "patterns", m_parent.getEnv());
 		int i = 0;
 		for (Lex lex : lexs.patterns ())
 			parseLex (lex, method, pos == null ? 0 : pos[i++]);
 	}
 
-	private void parseLex (Lex lex, MethodDeclaration method, int lineNumber)
+	private void parseLex (Lex lex, ExecutableElement method, int lineNumber)
 	{
 		if (lex == null)
 			return;
 
 		RuleDoc rule = new RuleDoc (getLexer ());
 
-		SourcePosition pos = method.getPosition ();
-		if (pos != null)
-			rule.setLineNumber (pos.line ());
+		rule.setLineNumber (getLineNumber(method, m_parent.getEnv()));
 
 		rule.setAction (getLexAction (method, lex.token ()));
 
 		PatternDoc pattern = new PatternDoc ();
 		pattern.setPattern (lex.pattern ());
 		if (lineNumber < 0)
-			pattern.setLineNumber (getAnnotationLineNumber (method, Lex.class.getName ()));
+			pattern.setLineNumber (getAnnotationLineNumber (method, Lex.class.getName (), m_parent.getEnv()));
 		else
 			pattern.setLineNumber (lineNumber);
 
@@ -266,18 +297,18 @@ class ClassVisitor implements DeclarationVisitor
 		rule.addStates (lex.state ());
 	}
 
-	private void parseRules (Rules rules, MethodDeclaration method)
+	private void parseRules (Rules rules, ExecutableElement method)
 	{
 		if (rules == null)
 			return;
 
-		int[] pos = getAnnotationArrayLineNumbers (method, Rules.class.getName (), "rules");
+		int[] pos = getAnnotationArrayLineNumbers (method, Rules.class.getName (), "rules", m_parent.getEnv());
 		int i = 0;
 		for (Rule rule : rules.rules ())
 			parseRule (rule, method, pos == null ? 0 : pos[i++]);
 	}
 
-	private void parseRule (Rule rule, MethodDeclaration method, int lineNumber)
+	private void parseRule (Rule rule, ExecutableElement method, int lineNumber)
 	{
 		if (rule == null)
 			return;
@@ -286,7 +317,7 @@ class ClassVisitor implements DeclarationVisitor
 		RhsDoc rhs = new RhsDoc ();
 		rhs.setTerms (rule.rhs ());
 		if (lineNumber < 0)
-			rhs.setLineNumber (getAnnotationLineNumber (method, Rule.class.getName ()));
+			rhs.setLineNumber (getAnnotationLineNumber (method, Rule.class.getName (), m_parent.getEnv()));
 		else
 			rhs.setLineNumber (lineNumber);
 		String precedence = rule.precedence ().trim ();
@@ -297,7 +328,7 @@ class ClassVisitor implements DeclarationVisitor
 		grammar.addRhs (rhs);
 	}
 
-	private String getLexAction (MethodDeclaration method, String token)
+	private String getLexAction (ExecutableElement method, String token)
 	{
 		StringBuffer buffer = new StringBuffer ();
 
@@ -323,7 +354,7 @@ class ClassVisitor implements DeclarationVisitor
 		return buffer.toString ();
 	}
 
-	private String getParseAction (MethodDeclaration method, String args)
+	private String getParseAction (ExecutableElement method, String args)
 	{
 		if (args == null)
 			args = "";
@@ -337,7 +368,7 @@ class ClassVisitor implements DeclarationVisitor
 
 		buffer.append (THIS_STR).append (method.getSimpleName ()).append (" (");
 
-		ParameterDeclaration[] params = method.getParameters ().toArray (new ParameterDeclaration[method.getParameters ().size ()]);
+		VariableElement[] params = method.getParameters ().toArray (new VariableElement[method.getParameters ().size ()]);
 
 		int[] argv = getArgs (args);
 
@@ -349,7 +380,7 @@ class ClassVisitor implements DeclarationVisitor
 			if (i > 0)
 				buffer.append (", ");
 			int v = argv[i];
-			String cl = params[i].getType ().toString ();
+	        String cl = params[i].asType().toString();
 			if ("java.lang.Object" != cl)
 				buffer.append ("(").append (cl).append (")");
 			buffer.append ("yyGetValue (").append (v).append (")");
@@ -360,35 +391,23 @@ class ClassVisitor implements DeclarationVisitor
 		return buffer.toString ();
 	}
 
-	public void visitDeclaration (Declaration declaration)
-	{
-	}
-
-	public void visitPackageDeclaration (PackageDeclaration packageDeclaration)
-	{
-	}
-
-	public void visitMemberDeclaration (MemberDeclaration memberDeclaration)
-	{
-	}
-
-	public void visitTypeDeclaration (TypeDeclaration typeDeclaration)
-	{
-	}
-
-	public void visitClassDeclaration (ClassDeclaration classDeclaration)
+	@Override
+	public R visitType(TypeElement classDeclaration, P p)
 	{
 		CookCCOption option = classDeclaration.getAnnotation (CookCCOption.class);
 		if (option == null)
-			return;
+			return DEFAULT_VALUE;
 		m_option = option;
 
+		ProcessingEnvironment env = (ProcessingEnvironment) p;
+
 		m_doc.setMain (false);
-		String inputClass = classDeclaration.getQualifiedName ();
+		String inputClass = classDeclaration.getQualifiedName().toString();
 		m_doc.setProperty (PROP_INPUT, inputClass);
-		ClassType superClassType = classDeclaration.getSuperclass ();
-		ClassDeclaration superClass = superClassType.getDeclaration ();
-		m_doc.setProperty (PROP_OUTPUT, computeOutputClass (superClassType));
+		DeclaredType superClassType = (DeclaredType) classDeclaration.getSuperclass();
+		TypeElement superClass = (TypeElement) superClassType.asElement();
+
+		m_doc.setProperty (PROP_OUTPUT, computeOutputClass (superClassType, m_parent.getEnv()));
 
 		if (superClass.getModifiers ().contains (Modifier.PUBLIC))
 			m_doc.setProperty (PROP_PUBLIC, Boolean.TRUE);
@@ -402,46 +421,21 @@ class ClassVisitor implements DeclarationVisitor
 		// try to get the file header
 		try
 		{
-			m_doc.addCode ("fileheader", generateFileHeader (FileHeaderScanner.getFileHeader (superClass.getPosition ().file ())));
+		    File file = getFile(superClass, env);
+			m_doc.addCode ("fileheader", generateFileHeader (FileHeaderScanner.getFileHeader (file)));
 		}
 		catch (Exception ex)
 		{
 		}
 		// try to get the class header
-		m_doc.addCode ("classheader", generateClassHeader (superClass.getDocComment ()));
-
-		m_parent.addDocument (classDeclaration.getQualifiedName (), m_doc);
-	}
-
-	public void visitEnumDeclaration (EnumDeclaration enumDeclaration)
-	{
-	}
-
-	public void visitInterfaceDeclaration (InterfaceDeclaration interfaceDeclaration)
-	{
-	}
-
-	public void visitAnnotationTypeDeclaration (AnnotationTypeDeclaration annotationTypeDeclaration)
-	{
-	}
-
-	public void visitFieldDeclaration (FieldDeclaration fieldDeclaration)
-	{
-	}
-
-	public void visitEnumConstantDeclaration (EnumConstantDeclaration enumConstantDeclaration)
-	{
-	}
+		m_doc.addCode ("classheader", generateClassHeader (m_parent.getEnv().getElementUtils().getDocComment(superClass)));
 
-	public void visitExecutableDeclaration (ExecutableDeclaration executableDeclaration)
-	{
-	}
+		m_parent.addDocument (classDeclaration.getQualifiedName().toString(), m_doc);
 
-	public void visitConstructorDeclaration (ConstructorDeclaration constructorDeclaration)
-	{
+        return DEFAULT_VALUE;
 	}
 
-	public void visitMethodDeclaration (MethodDeclaration method)
+	public void visitExecutableElement (ExecutableElement method)
 	{
 		parseLexs (method.getAnnotation (Lexs.class), method);
 		parseLex (method.getAnnotation (Lex.class), method, -1);
@@ -450,16 +444,4 @@ class ClassVisitor implements DeclarationVisitor
 		parseRules (method.getAnnotation (Rules.class), method);
 		parseRule (method.getAnnotation (Rule.class), method, -1);
 	}
-
-	public void visitAnnotationTypeElementDeclaration (AnnotationTypeElementDeclaration annotationTypeElementDeclaration)
-	{
-	}
-
-	public void visitParameterDeclaration (ParameterDeclaration parameterDeclaration)
-	{
-	}
-
-	public void visitTypeParameterDeclaration (TypeParameterDeclaration typeParameterDeclaration)
-	{
-	}
 }
\ No newline at end of file
diff --git a/javaap_src/org/yuanheng/cookcc/input/javaap/CookCCAptFactory.java b/javaap_src/org/yuanheng/cookcc/input/javaap/CookCCAptFactory.java
deleted file mode 100644
index 3d3957c..0000000
--- a/javaap_src/org/yuanheng/cookcc/input/javaap/CookCCAptFactory.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2008, Heng Yuan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of the Heng Yuan nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY Heng Yuan ''AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Heng Yuan BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.yuanheng.cookcc.input.javaap;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Set;
-
-import com.sun.mirror.apt.AnnotationProcessor;
-import com.sun.mirror.apt.AnnotationProcessorEnvironment;
-import com.sun.mirror.apt.AnnotationProcessorFactory;
-import com.sun.mirror.declaration.AnnotationTypeDeclaration;
-
-/**
- * @author Heng Yuan
- * @version $Id: CookCCAptFactory.java 486 2008-11-09 15:09:57Z superduperhengyuan $
- */
-public class CookCCAptFactory implements AnnotationProcessorFactory
-{
-	private final static Collection<String> s_supportedOptions = Collections.emptySet ();
-	private final static Collection<String> s_supportedAnnotationTypes = Collections.unmodifiableCollection (Arrays.asList ("org.yuanheng.cookcc.*"));
-
-//	static
-//	{
-//		// compute all possible options across all output languages
-//
-//		HashSet<String> options = new HashSet<String> ();
-//
-//		addOptions (options, Main.getOptions ());
-//
-//		for (String lang : Main.getLanguages ())
-//		{
-//			try
-//			{
-//				CodeGen codeGen = Main.getCodeGen (lang);
-//				addOptions (options, codeGen.getOptions ());
-//			}
-//			catch (Throwable t)
-//			{
-//			}
-//		}
-//		s_supportedOptions = options;
-//	}
-//
-//	private static void addOptions (HashSet<String> optionSet, OptionMap optionMap)
-//	{
-//		for (String option : optionMap.getAvailableOptions ())
-//			optionSet.add ("-A" + option.substring (1));
-//	}
-
-	public Collection<String> supportedOptions ()
-	{
-		return s_supportedOptions;
-	}
-
-	public Collection<String> supportedAnnotationTypes ()
-	{
-		return s_supportedAnnotationTypes;
-	}
-
-	public AnnotationProcessor getProcessorFor (Set<AnnotationTypeDeclaration> annotationTypeDeclarations, AnnotationProcessorEnvironment env)
-	{
-		try
-		{
-			return new CookCCProcessor (env);
-		}
-		catch (Exception ex)
-		{
-			throw new IllegalArgumentException ("Invalid CookCC options");
-		}
-	}
-}
diff --git a/javaap_src/org/yuanheng/cookcc/input/javaap/CookCCProcessor.java b/javaap_src/org/yuanheng/cookcc/input/javaap/CookCCProcessor.java
index 5753fb2..6b6b478 100644
--- a/javaap_src/org/yuanheng/cookcc/input/javaap/CookCCProcessor.java
+++ b/javaap_src/org/yuanheng/cookcc/input/javaap/CookCCProcessor.java
@@ -26,8 +26,13 @@
  */
 package org.yuanheng.cookcc.input.javaap;
 
+import java.lang.annotation.Annotation;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 
 import org.yuanheng.cookcc.Main;
 import org.yuanheng.cookcc.OptionMap;
@@ -37,18 +42,31 @@ import org.yuanheng.cookcc.codegen.options.ClassOption;
 import org.yuanheng.cookcc.doc.Document;
 import org.yuanheng.cookcc.interfaces.CodeGen;
 
-import com.sun.mirror.apt.AnnotationProcessor;
-import com.sun.mirror.apt.AnnotationProcessorEnvironment;
-import com.sun.mirror.declaration.TypeDeclaration;
-import com.sun.mirror.util.DeclarationVisitors;
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.RoundEnvironment;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+
 
 /**
  * @author Heng Yuan
  * @version $Id: CookCCProcessor.java 486 2008-11-09 15:09:57Z superduperhengyuan $
  */
-class CookCCProcessor implements AnnotationProcessor
+public class CookCCProcessor extends AbstractProcessor
 {
-	static Map<String, String> convertOptions (Map<String, String> aptOptions)
+
+    private Set<String> s_supportedOptions = Collections.emptySet();
+    private Set<String> s_supportedAnnotationTypes = new HashSet<String> (Arrays.asList(
+                    "org.yuanheng.cookcc.CookCCOption",
+                    "org.yuanheng.cookcc.CookCCToken",
+                    "org.yuanheng.cookcc.TokenGroup",
+                    "org.yuanheng.cookcc.Lex",
+                    "org.yuanheng.cookcc.Lexs",
+                    "org.yuanheng.cookcc.Rule"));
+
+	private static Map<String, String> convertOptions (Map<String, String> aptOptions)
 	{
 		HashMap<String, String> ccOptions = new HashMap<String, String> ();
 		for (String option : aptOptions.keySet ())
@@ -68,22 +86,50 @@ class CookCCProcessor implements AnnotationProcessor
 		return ccOptions;
 	}
 
-	private final AnnotationProcessorEnvironment m_env;
-	private final CodeGen m_codeGen;
+	private CodeGen m_codeGen;
 
-	CookCCProcessor (AnnotationProcessorEnvironment env) throws Exception
-	{
-		m_env = env;
-		Map<String, String> ccOptions = convertOptions (env.getOptions ());
-		Main.parseOptions (ccOptions);
-		m_codeGen = Main.getCodeGen ();
-	}
+	@Override
+    public synchronized void init(ProcessingEnvironment processingEnv) {
+        super.init(processingEnv);
+        Map<String, String> ccOptions = convertOptions (processingEnv.getOptions ());
+        try {
+            Main.parseOptions (ccOptions);
+            m_codeGen = Main.getCodeGen ();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
 
-	public void process ()
+    @Override
+    public Set<String> getSupportedAnnotationTypes() {
+        return s_supportedAnnotationTypes;
+    }
+
+    @Override
+    public Set<String> getSupportedOptions() {
+        return s_supportedOptions;
+    }
+
+	@Override
+    public SourceVersion getSupportedSourceVersion() {
+        return SourceVersion.RELEASE_8;
+    }
+
+    @Override
+	public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv)
 	{
 		CookCCVisitor visitor = new CookCCVisitor ();
-		for (TypeDeclaration typeDecl : m_env.getSpecifiedTypeDeclarations ())
-			typeDecl.accept (DeclarationVisitors.getDeclarationScanner (visitor, DeclarationVisitors.NO_OP));
+		visitor.setEnv(this.processingEnv);
+		Set<Element> allElements = new HashSet<Element>();
+		for (String annotation: getSupportedAnnotationTypes()) {
+		    try {
+                allElements.addAll(roundEnv.getElementsAnnotatedWith((Class<? extends Annotation>) Class.forName(annotation)));
+            } catch (ClassNotFoundException e) {
+                throw new RuntimeException("Unknown annotation " + annotation, e);
+            }
+		}
+		for (Element typeDecl : allElements)
+		    typeDecl.accept (visitor, null);
 		visitor.process ();
 		Document[] docs = visitor.getDocuments ();
 		OptionMap options = m_codeGen.getOptions ();
@@ -109,5 +155,6 @@ class CookCCProcessor implements AnnotationProcessor
 				ex.printStackTrace ();
 			}
 		}
+		return true;
 	}
 }
diff --git a/javaap_src/org/yuanheng/cookcc/input/javaap/CookCCVisitor.java b/javaap_src/org/yuanheng/cookcc/input/javaap/CookCCVisitor.java
index b69be72..164f59f 100644
--- a/javaap_src/org/yuanheng/cookcc/input/javaap/CookCCVisitor.java
+++ b/javaap_src/org/yuanheng/cookcc/input/javaap/CookCCVisitor.java
@@ -32,22 +32,37 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.TypeParameterElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.util.SimpleElementVisitor6;
+
 import org.yuanheng.cookcc.codegen.TemplatedCodeGen;
 import org.yuanheng.cookcc.doc.Document;
 import org.yuanheng.cookcc.doc.TokensDoc;
 
-import com.sun.mirror.declaration.*;
-import com.sun.mirror.util.DeclarationVisitor;
-
 import freemarker.template.Template;
 
 /**
  * @author Heng Yuan
  * @version $Id: CookCCVisitor.java 486 2008-11-09 15:09:57Z superduperhengyuan $
  */
-class CookCCVisitor implements DeclarationVisitor
+class CookCCVisitor<R, P> extends SimpleElementVisitor6<R, P>
 {
 	public final static String TEMPLATE_URI = "resources/templates/javaap/javaap.ftl";
+	private ProcessingEnvironment env;
+
+	public ProcessingEnvironment getEnv() {
+	    return this.env;
+	}
+
+	public void setEnv(ProcessingEnvironment env) {
+	    this.env = env;
+	}
 
 	private static class Resources
 	{
@@ -76,7 +91,7 @@ class CookCCVisitor implements DeclarationVisitor
 
 	private final Map<String, Document> m_docs = new HashMap<String, Document> ();
 	private final Map<String, Collection<TokensDoc>> m_tokens = new HashMap<String, Collection<TokensDoc>> ();
-	private DeclarationVisitor m_visitor;
+	private SimpleElementVisitor6 m_visitor;
 
 	void addDocument (String className, Document document)
 	{
@@ -166,99 +181,47 @@ class CookCCVisitor implements DeclarationVisitor
 		addDefaultCode ();
 	}
 
-	public void visitDeclaration (Declaration declaration)
-	{
-		if (m_visitor != null)
-			m_visitor.visitDeclaration (declaration);
-	}
-
-	public void visitPackageDeclaration (PackageDeclaration packageDeclaration)
-	{
-		if (m_visitor != null)
-			m_visitor.visitPackageDeclaration (packageDeclaration);
-	}
-
-	public void visitMemberDeclaration (MemberDeclaration memberDeclaration)
-	{
-		if (m_visitor != null)
-			m_visitor.visitMemberDeclaration (memberDeclaration);
-	}
-
-	public void visitTypeDeclaration (TypeDeclaration typeDeclaration)
-	{
-		if (m_visitor != null)
-			m_visitor.visitTypeDeclaration (typeDeclaration);
-	}
-
-	public void visitClassDeclaration (ClassDeclaration classDeclaration)
-	{
-		m_visitor = new ClassVisitor (this);
-		m_visitor.visitClassDeclaration (classDeclaration);
-	}
-
-	public void visitEnumDeclaration (EnumDeclaration enumDeclaration)
-	{
-		m_visitor = new EnumVisitor (this);
-		m_visitor.visitEnumDeclaration (enumDeclaration);
-	}
-
-	public void visitInterfaceDeclaration (InterfaceDeclaration interfaceDeclaration)
-	{
-		if (m_visitor != null)
-			m_visitor.visitInterfaceDeclaration (interfaceDeclaration);
-	}
-
-	public void visitAnnotationTypeDeclaration (AnnotationTypeDeclaration annotationTypeDeclaration)
-	{
-		if (m_visitor != null)
-			m_visitor.visitAnnotationTypeDeclaration (annotationTypeDeclaration);
-	}
-
-	public void visitFieldDeclaration (FieldDeclaration fieldDeclaration)
-	{
-		if (m_visitor != null)
-			m_visitor.visitFieldDeclaration (fieldDeclaration);
-	}
-
-	public void visitEnumConstantDeclaration (EnumConstantDeclaration enumConstantDeclaration)
-	{
-		if (m_visitor != null)
-			m_visitor.visitEnumConstantDeclaration (enumConstantDeclaration);
-	}
-
-	public void visitExecutableDeclaration (ExecutableDeclaration executableDeclaration)
-	{
-		if (m_visitor != null)
-			m_visitor.visitExecutableDeclaration (executableDeclaration);
-	}
-
-	public void visitConstructorDeclaration (ConstructorDeclaration constructorDeclaration)
-	{
-		if (m_visitor != null)
-			m_visitor.visitConstructorDeclaration (constructorDeclaration);
+	@Override
+	public R visitPackage(PackageElement e, P p) {
+		if (m_visitor != null) {
+			return (R) m_visitor.visitPackage(e, p);
+		}
+		return DEFAULT_VALUE;
 	}
 
-	public void visitMethodDeclaration (MethodDeclaration methodDeclaration)
-	{
-		if (m_visitor != null)
-			m_visitor.visitMethodDeclaration (methodDeclaration);
+	@Override
+	public R visitVariable(VariableElement e, P p) {
+		if (m_visitor != null) {
+			return (R) m_visitor.visitVariable(e, p);
+		}
+		return DEFAULT_VALUE;
 	}
 
-	public void visitAnnotationTypeElementDeclaration (AnnotationTypeElementDeclaration annotationTypeElementDeclaration)
-	{
-		if (m_visitor != null)
-			m_visitor.visitAnnotationTypeElementDeclaration (annotationTypeElementDeclaration);
+	@Override
+	public R visitExecutable(ExecutableElement e, P p) {
+		if (m_visitor != null) {
+			return (R) m_visitor.visitExecutable(e, p);
+		}
+		return DEFAULT_VALUE;
 	}
 
-	public void visitParameterDeclaration (ParameterDeclaration parameterDeclaration)
-	{
-		if (m_visitor != null)
-			m_visitor.visitParameterDeclaration (parameterDeclaration);
+	@Override
+	public R visitTypeParameter(TypeParameterElement e, P p) {
+		if (m_visitor != null) {
+			return (R) m_visitor.visitTypeParameter(e, p);
+		}
+		return DEFAULT_VALUE;
 	}
 
-	public void visitTypeParameterDeclaration (TypeParameterDeclaration typeParameterDeclaration)
-	{
-		if (m_visitor != null)
-			m_visitor.visitTypeParameterDeclaration (typeParameterDeclaration);
+	public R visitType(TypeElement classDeclaration, P p) {
+		if (classDeclaration.getKind() == ElementKind.CLASS) {
+			m_visitor = new ClassVisitor(this);
+			m_visitor.visitType(classDeclaration, p);
+		}
+		if (classDeclaration.getKind() == ElementKind.ENUM) {
+			m_visitor = new EnumVisitor(this);
+			m_visitor.visitType(classDeclaration, p);
+		}
+		return DEFAULT_VALUE;
 	}
 }
\ No newline at end of file
diff --git a/javaap_src/org/yuanheng/cookcc/input/javaap/EnumVisitor.java b/javaap_src/org/yuanheng/cookcc/input/javaap/EnumVisitor.java
index 4e846bc..4bc7a3b 100644
--- a/javaap_src/org/yuanheng/cookcc/input/javaap/EnumVisitor.java
+++ b/javaap_src/org/yuanheng/cookcc/input/javaap/EnumVisitor.java
@@ -29,18 +29,20 @@ package org.yuanheng.cookcc.input.javaap;
 import java.util.Collection;
 import java.util.LinkedList;
 
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.util.SimpleElementVisitor6;
+
 import org.yuanheng.cookcc.CookCCToken;
 import org.yuanheng.cookcc.TokenGroup;
 import org.yuanheng.cookcc.doc.TokensDoc;
 
-import com.sun.mirror.declaration.*;
-import com.sun.mirror.util.DeclarationVisitor;
-
 /**
  * @author Heng Yuan
  * @version $Id: EnumVisitor.java 486 2008-11-09 15:09:57Z superduperhengyuan $
  */
-class EnumVisitor implements DeclarationVisitor
+class EnumVisitor<R, P> extends SimpleElementVisitor6<R, P>
 {
 	private final CookCCVisitor m_parent;
 	private final Collection<TokensDoc> m_tokens = new LinkedList<TokensDoc> ();
@@ -52,46 +54,14 @@ class EnumVisitor implements DeclarationVisitor
 		m_parent = parent;
 	}
 
-	public void visitDeclaration (Declaration declaration)
-	{
-	}
-
-	public void visitPackageDeclaration (PackageDeclaration packageDeclaration)
-	{
-	}
-
-	public void visitMemberDeclaration (MemberDeclaration memberDeclaration)
-	{
-	}
-
-	public void visitTypeDeclaration (TypeDeclaration typeDeclaration)
-	{
-	}
-
-	public void visitClassDeclaration (ClassDeclaration classDeclaration)
-	{
-	}
-
-	public void visitEnumDeclaration (EnumDeclaration enumDeclaration)
+	public void visitEnumDeclaration (TypeElement enumDeclaration)
 	{
 		if (enumDeclaration.getAnnotation (CookCCToken.class) == null)
 			return;
-		m_parent.addTokenEnum (enumDeclaration.getQualifiedName (), m_tokens);
-	}
-
-	public void visitInterfaceDeclaration (InterfaceDeclaration interfaceDeclaration)
-	{
-	}
-
-	public void visitAnnotationTypeDeclaration (AnnotationTypeDeclaration annotationTypeDeclaration)
-	{
-	}
-
-	public void visitFieldDeclaration (FieldDeclaration fieldDeclaration)
-	{
+		m_parent.addTokenEnum (enumDeclaration.getQualifiedName().toString(), m_tokens);
 	}
 
-	public void visitEnumConstantDeclaration (EnumConstantDeclaration enumConstantDeclaration)
+	private void visitEnumConstantDeclaration (VariableElement enumConstantDeclaration)
 	{
 		TokenGroup tg = null;
 		if (m_doc == null || (tg = enumConstantDeclaration.getAnnotation (TokenGroup.class)) != null)
@@ -101,30 +71,22 @@ class EnumVisitor implements DeclarationVisitor
 				m_doc.setType (tg.type ().toString ());
 			m_tokens.add (m_doc);
 		}
-		m_doc.addTokens (enumConstantDeclaration.getSimpleName ());
-	}
-
-	public void visitExecutableDeclaration (ExecutableDeclaration executableDeclaration)
-	{
-	}
-
-	public void visitConstructorDeclaration (ConstructorDeclaration constructorDeclaration)
-	{
+		m_doc.addTokens (enumConstantDeclaration.getSimpleName().toString());
 	}
 
-	public void visitMethodDeclaration (MethodDeclaration methodDeclaration)
-	{
-	}
-
-	public void visitAnnotationTypeElementDeclaration (AnnotationTypeElementDeclaration annotationTypeElementDeclaration)
-	{
-	}
-
-	public void visitParameterDeclaration (ParameterDeclaration parameterDeclaration)
-	{
+	@Override
+	public R visitVariable(VariableElement e, P p) {
+		if (e.getKind() == ElementKind.ENUM_CONSTANT) {
+			visitEnumConstantDeclaration(e);
+		}
+		return DEFAULT_VALUE;
 	}
 
-	public void visitTypeParameterDeclaration (TypeParameterDeclaration typeParameterDeclaration)
-	{
+	@Override
+	public R visitType(TypeElement e, P p) {
+		if (e.getKind() == ElementKind.ENUM) {
+			visitEnumDeclaration(e);
+		}
+		return DEFAULT_VALUE;
 	}
 }
\ No newline at end of file
-- 
1.9.3

