/*
* Copyright (C) 2010-2015 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package lombok.ast.ecj;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.ast.CombinedBinaryExpression;
import org.eclipse.jdt.internal.compiler.ast.IntLiteralMinValue;
import org.eclipse.jdt.internal.compiler.ast.Javadoc;
import org.eclipse.jdt.internal.compiler.ast.LongLiteralMinValue;
/**
* This class generates the EcjAstVisitor that we use, because Eclipse's own visitor sucks,
* at least for our purposes.
*
* Technically we should not check in the generated file and run this on every build, but its not
* like the eclipse org.eclipse.jdt.internal.compiler.ast package gets changed every day, so, we don't bother.
*/
class GenerateEcjTreeVisitorCode {
private static final String COPYRIGHT_NOTICE = "/*\n" +
" * Copyright (C) 2010 The Project Lombok Authors.\n" +
" * \n" +
" * Permission is hereby granted, free of charge, to any person obtaining a copy\n" +
" * of this software and associated documentation files (the \"Software\"), to deal\n" +
" * in the Software without restriction, including without limitation the rights\n" +
" * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n" +
" * copies of the Software, and to permit persons to whom the Software is\n" +
" * furnished to do so, subject to the following conditions:\n" +
" * \n" +
" * The above copyright notice and this permission notice shall be included in\n" +
" * all copies or substantial portions of the Software.\n" +
" * \n" +
" * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n" +
" * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n" +
" * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n" +
" * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n" +
" * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n" +
" * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n" +
" * THE SOFTWARE.\n" +
" */\n";
public static void main(String[] args) throws Exception {
List<Class<?>> visits = findVisits();
StringBuilder out = new StringBuilder();
prefix(out);
for (Class<?> c : visits) instanceofGen(out, c);
infix(out);
for (Class<?> c : visits) methodGen(out, c);
suffix(out);
System.out.println(out.toString());
}
private static final Class<?>[] EXTRA_TYPES = {
CombinedBinaryExpression.class,
IntLiteralMinValue.class,
LongLiteralMinValue.class,
Javadoc.class,
};
static List<Class<?>> findVisits() {
List<Class<?>> visits = new ArrayList<Class<?>>();
for (Method m : ASTVisitor.class.getMethods()) {
if (m.getName().equals("visit") && m.getParameterTypes().length > 0) {
Class<?> t = m.getParameterTypes()[0];
if (!visits.contains(t) && !t.getSimpleName().startsWith("Javadoc")) visits.add(t);
}
}
for (Class<?> extra : EXTRA_TYPES) {
if (!visits.contains(extra)) visits.add(extra);
}
return visits;
}
private static void prefix(StringBuilder out) {
out.append(COPYRIGHT_NOTICE);
out.append("package lombok.ast.ecj;\n\n");
out.append("import org.eclipse.jdt.internal.compiler.ast.*;\n\n");
out.append("public abstract class EcjTreeVisitor {\n");
out.append("\tpublic void visitEcjNode(ASTNode node) {\n");
out.append("\t\tif (node == null) return;\n\t\tClass<?> clazz = node.getClass();\n\t\t\n");
}
private static void instanceofGen(StringBuilder out, Class<?> c) {
out.append("\t\tif (clazz == ").append(c.getSimpleName());
out.append(".class) {\n\t\t\tvisit").append(c.getSimpleName()).append("((").append(c.getSimpleName());
out.append(") node);\n\t\t\treturn;\n\t\t}\n");
}
private static void infix(StringBuilder out) {
out.append("\t\t\n\t\tvisitOther(node);\n");
out.append("\t}\n\t\n");
out.append("\tpublic void visitOther(ASTNode node) {\n");
out.append("\t\tthrow new UnsupportedOperationException(\"Unknown ASTNode child: \" + ");
out.append("node.getClass().getSimpleName());\n\t}\n\t\n");
out.append("\tpublic void visitAny(ASTNode node) {\n");
out.append("\t\tthrow new UnsupportedOperationException(\"visit\" + node.getClass().getSimpleName()");
out.append(" + \" not implemented\");\n\t}\n");
}
private static void methodGen(StringBuilder out, Class<?> c) {
out.append("\t\n\tpublic void visit").append(c.getSimpleName()).append("(");
out.append(c.getSimpleName()).append(" node) {\n");
out.append("\t\tvisitAny(node);\n\t}\n");
}
private static void suffix(StringBuilder out) {
out.append("}\n");
}
}