aboutsummaryrefslogtreecommitdiff
path: root/original_panno/com/hanhuy/panno/processing/ASTTreeToSource.java
diff options
context:
space:
mode:
authorReinier Zwitserloot <reinier@tipit.to>2009-06-08 22:26:30 +0200
committerReinier Zwitserloot <reinier@tipit.to>2009-06-08 22:26:30 +0200
commit1677c4a52a0aea1b955f7c2c7d096903d4a8c5ce (patch)
tree29de8d12d774f026c0f317e229532befaeb2d096 /original_panno/com/hanhuy/panno/processing/ASTTreeToSource.java
downloadlombok-1677c4a52a0aea1b955f7c2c7d096903d4a8c5ce.tar.gz
lombok-1677c4a52a0aea1b955f7c2c7d096903d4a8c5ce.tar.bz2
lombok-1677c4a52a0aea1b955f7c2c7d096903d4a8c5ce.zip
Initial commit. As a proof of concept, it already works in javac and eclipse!
Diffstat (limited to 'original_panno/com/hanhuy/panno/processing/ASTTreeToSource.java')
-rw-r--r--original_panno/com/hanhuy/panno/processing/ASTTreeToSource.java320
1 files changed, 320 insertions, 0 deletions
diff --git a/original_panno/com/hanhuy/panno/processing/ASTTreeToSource.java b/original_panno/com/hanhuy/panno/processing/ASTTreeToSource.java
new file mode 100644
index 00000000..2e7dc641
--- /dev/null
+++ b/original_panno/com/hanhuy/panno/processing/ASTTreeToSource.java
@@ -0,0 +1,320 @@
+/*
+ * Copyright 2007 Perry Nguyen <pfnguyen@hanhuy.com> Licensed under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.hanhuy.panno.processing;
+
+import java.util.Map;
+import java.util.Stack;
+
+import javax.annotation.processing.Messager;
+import javax.lang.model.element.Modifier;
+import javax.tools.Diagnostic;
+
+import com.hanhuy.panno.Property;
+import com.sun.source.tree.AnnotationTree;
+import com.sun.source.tree.BlockTree;
+import com.sun.source.tree.ClassTree;
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.tree.IdentifierTree;
+import com.sun.source.tree.ImportTree;
+import com.sun.source.tree.MethodTree;
+import com.sun.source.tree.StatementTree;
+import com.sun.source.tree.VariableTree;
+import com.sun.source.util.TreeScanner;
+
+/**
+ * Old attempt to get the annotation working, have a better approach now.
+ */
+@Deprecated
+class ASTTreeToSource extends TreeScanner<Void, StringBuilder> {
+ public final static String PROPERTY_ANNOTATION_FULL = "com.hanhuy.panno.Property";
+ public final static String PROPERTY_ANNOTATION = "Property";
+
+ private final Stack<String> currentClassNameStack = new Stack<String>();
+ private final Messager messager;
+ private final Map<String, Property> fieldMap;
+ private String currentClassName;
+ private String currentField;
+ private String currentType;
+
+ ASTTreeToSource(Map<String, Property> fieldMap, Messager messager) {
+ this.fieldMap = fieldMap;
+ this.messager = messager;
+ }
+
+ /**
+ * Handle initializer blocks, both static and non.
+ */
+ @Override
+ public Void visitBlock(BlockTree node, StringBuilder p) {
+ p.append("\n");
+ if ( node.isStatic() ) p.append("static ");
+ p.append("{\n");
+ for ( StatementTree st : node.getStatements() ) {
+ p.append(st);
+ p.append(";");
+ }
+ p.append("\n}\n");
+ return null;
+ }
+
+ /**
+ * Detect our annotation and add accessors if necessary.
+ */
+ @Override
+ public Void visitAnnotation(AnnotationTree node, StringBuilder p) {
+ String anno = ((IdentifierTree)node.getAnnotationType()).getName().toString();
+ if ( anno != null && PROPERTY_ANNOTATION.equals(anno.trim()) ) {
+ Property pAnno = fieldMap.get(currentClassName + "." + currentField);
+
+ String propName = currentField;
+ if ( !"".equals(pAnno.name()) ) propName = pAnno.name();
+ propName = PropertyProcessor.ucfirst(propName);
+
+ if ( pAnno.writeOnly() && pAnno.readOnly() ) {
+ messager.printMessage(Diagnostic.Kind.ERROR, "@Property's writeOnly and readOnly may not both be true");
+ }
+
+ if ( !"boolean".equals(currentType) && pAnno.useGet() ) {
+ messager.printMessage(Diagnostic.Kind.WARNING, "@Property's useGet is only for booleans");
+ }
+
+ if ( !pAnno.writeOnly() ) {
+ // generate a getter
+ p.append("\n");
+ p.append("public ");
+ p.append(currentType);
+ if ( !"boolean".equals(currentType) || pAnno.useGet() ) p.append(" get");
+ else p.append(" is");
+ p.append(propName);
+ p.append("() { return ");
+ p.append(currentField);
+ p.append("; }");
+ }
+ if ( !pAnno.readOnly() ) {
+ // generate a setter
+ p.append("\n");
+ p.append("public void set");
+ p.append(propName);
+ p.append("(");
+ p.append(currentType);
+ p.append(" ");
+ p.append(currentField);
+ p.append(") { this.");
+ p.append(currentField);
+ p.append(" = ");
+ p.append(currentField);
+ p.append("; }");
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gather file information. Then continue to visit classes.
+ */
+ @Override
+ public Void visitCompilationUnit(CompilationUnitTree node, StringBuilder p) {
+ new Exception("Visit CUT: " + node.getSourceFile()).printStackTrace();
+ p.append("// Generated from: ");
+ p.append(node.getSourceFile());
+ p.append("\n\npackage ");
+ p.append(node.getPackageName());
+ p.append(";\n\n");
+
+ for ( ImportTree it : node.getImports() ) {
+ if ( PROPERTY_ANNOTATION_FULL.equals(it.getQualifiedIdentifier().toString().trim()) ) {
+ continue;
+ }
+ p.append("import ");
+ if ( it.isStatic() ) p.append("static ");
+ p.append(it.getQualifiedIdentifier());
+ p.append(";\n");
+ }
+ super.visitCompilationUnit(node, p);
+ return null;
+ }
+
+ private void pushClass(String className) {
+ currentClassName = className;
+ currentClassNameStack.push(currentClassName);
+ }
+
+ private void popClass() {
+ currentClassNameStack.pop();
+ if ( currentClassNameStack.size() > 0 ) currentClassName = currentClassNameStack.peek();
+ }
+
+ /**
+ * Reproduce class declarations, and go on to handle methods, blocks and
+ * variables.
+ */
+ @Override
+ public Void visitClass(ClassTree node, StringBuilder p) {
+ pushClass(node.getSimpleName().toString());
+
+ // Check to see if this is an enum
+ // I have no idea what will happen if we encounter an AST
+ // implementation that is not Sun's (or if this has changed in java7)
+ if ( node instanceof com.sun.tools.javac.tree.JCTree.JCClassDecl ) {
+ com.sun.tools.javac.tree.JCTree.JCClassDecl jcd = (com.sun.tools.javac.tree.JCTree.JCClassDecl)node;
+ if ( (jcd.mods.flags & 16384L) != 0L ) {
+ p.append(node.getModifiers());
+ p.append(" enum ");
+ p.append(currentClassName);
+ appendEnumBody(jcd.defs, p);
+
+ popClass();
+
+ return null;
+ }
+ }
+
+ p.append("\n");
+ p.append(node.getModifiers());
+ p.append(" class ");
+ p.append(currentClassName);
+ if ( node.getTypeParameters().size() > 0 ) {
+ p.append("<");
+ p.append(node.getTypeParameters());
+ p.append(">");
+ }
+ if ( node.getExtendsClause() != null ) {
+ p.append("\nextends ");
+ p.append(node.getExtendsClause());
+ }
+ if ( node.getImplementsClause().size() > 0 ) {
+ p.append("\nimplements ");
+ p.append(node.getImplementsClause());
+ }
+
+ p.append("\n{");
+ super.visitClass(node, p);
+ p.append("\n}\n");
+
+ popClass();
+
+ return null;
+ }
+
+ /**
+ * Enums appear to be a special case. We must reconstitute its source in a
+ * different manner from the rest. Need to remove any 'super()' statements
+ * and print the lines appropriately.
+ */
+ public void appendEnumBody(com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree> list, StringBuilder p) {
+ p.append("{\n");
+ boolean flag = true;
+
+ for ( com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree> list1 = list; list1.nonEmpty(); list1 = list1.tail ) {
+
+ if ( !isEnumerator(list1.head) ) continue;
+
+ if ( !flag ) p.append(",\n");
+
+ p.append(list1.head);
+ flag = false;
+ }
+
+ p.append(";\n");
+ for ( com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree> list2 = list; list2.nonEmpty(); list2 = list2.tail ) {
+ if ( !isEnumerator(list2.head) ) {
+ if ( list2.head instanceof MethodTree ) visitMethod((MethodTree)list2.head, p);
+ else p.append(list2.head);
+ p.append("\n");
+ }
+ }
+
+ p.append("}");
+ }
+
+ private boolean isEnumerator(com.sun.tools.javac.tree.JCTree jctree) {
+ return jctree.tag == 5 && (((com.sun.tools.javac.tree.JCTree.JCVariableDecl)jctree).mods.flags & 16384L) != 0L;
+ }
+
+ /**
+ * Reconstitute methods. We could just do node.toString() here, but
+ * constructors need to be renamed from &lt;init&gt; to the class name, so
+ * handle all methods.
+ */
+ @Override
+ public Void visitMethod(MethodTree node, StringBuilder p) {
+ p.append("\n");
+ p.append(node.getModifiers());
+ p.append(" ");
+ if ( node.getReturnType() != null ) p.append(node.getReturnType());
+ if ( node.getTypeParameters().size() > 0 ) {
+ p.append(" <");
+ p.append(node.getTypeParameters());
+ p.append(">");
+ }
+ p.append(" ");
+ if ( node.getName() != null && "<init>".equals(node.getName().toString().trim()) ) p.append(currentClassName);
+ else p.append(node.getName());
+
+ p.append("(");
+ p.append(node.getParameters());
+ p.append(")");
+ if ( node.getThrows().size() > 0 ) {
+ p.append("\nthrows ");
+ p.append(node.getThrows());
+ }
+
+ p.append(" {\n");
+ // this needs to be done for enums, otherwise we'll get a compile error
+ // if we didn't need this case, we'd just do p.append(node.getBody())
+ for ( StatementTree st : node.getBody().getStatements() ) {
+ if ( "super()".equals(st.toString().trim()) ) continue;
+ p.append(st);
+ if ( p.charAt(p.length() - 1) != ';' ) p.append(";\n");
+ }
+ p.append("\n}\n");
+ return null;
+ }
+
+ /**
+ * Reconstitute class fields. While doing so, search for our annotation to
+ * perform processing.
+ */
+ @Override
+ public Void visitVariable(VariableTree node, StringBuilder p) {
+ currentField = node.getName().toString();
+ currentType = node.getType().toString();
+ p.append("\n");
+
+ for ( AnnotationTree a : node.getModifiers().getAnnotations() ) {
+ String anno = ((IdentifierTree)a.getAnnotationType()).getName().toString();
+ if ( !PROPERTY_ANNOTATION.equals(anno) ) {
+ p.append(a);
+ p.append("\n");
+ }
+ }
+
+ for ( Modifier m : node.getModifiers().getFlags() ) {
+ p.append(m.toString());
+ p.append(" ");
+ }
+ p.append(" ");
+ p.append(currentType);
+ p.append(" ");
+ p.append(currentField);
+
+ if ( node.getInitializer() != null ) {
+ p.append(" = ");
+ p.append(node.getInitializer());
+ }
+ p.append(";");
+ super.visitVariable(node, p);
+ return null;
+ }
+}