Skip to Main Content

Java APIs

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Javac AST Symbol Resolving for JavacTask.parse()

807565Oct 22 2010 — edited Nov 2 2010
Hello!

I am currently working on a source code processor, based on an AST. I use the original javac library. I know that the javac package is not provided as API, but it suffices for a first prototype.

I parse a file (multiple files) with JavacTask.parse() and descent into the AST. Please don't hit me for the solution using Reflection! The interesting lines are on *321-328*, where I try to resolve the Symbols manually, because it seems all .sym properties are set to null.

I don't understand how to resolve the AST previous to descent into it. Is it possible to resolve Symbols with the original library code?


Warning, big Code:
package runtimeLoader;

import java.io.StringWriter;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Stack;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

import runtimeLoader.RuntimeLoader.Trace.RuntimeLoaderTrace;

import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.util.JavacTask;
import com.sun.source.util.TreeScanner;
import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.api.JavacTrees;
import com.sun.tools.javac.code.Scope;
import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.code.Symbol.PackageSymbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.TypeTags;
import com.sun.tools.javac.comp.AttrContext;
import com.sun.tools.javac.comp.Env;
import com.sun.tools.javac.comp.Resolve;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCAssign;
import com.sun.tools.javac.tree.JCTree.JCBlock;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
import com.sun.tools.javac.tree.JCTree.JCIdent;
import com.sun.tools.javac.tree.JCTree.JCLabeledStatement;
import com.sun.tools.javac.tree.JCTree.JCLiteral;
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
import com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree;
import com.sun.tools.javac.tree.JCTree.JCStatement;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.tree.Pretty;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Name;
import com.sun.tools.javac.util.Name.Table;

public class Compile {

	/*
	 * parse, pretty, store temp
	 * copy tree, process, pretty, store, compile, EXECUTE, TEST
	 * process back, pretty, COMPARE EQUAL
	 * 
	 * 
	 * 
	 * nested vars
	 * nested classes, methods
	 * vars there
	 */

	static class ReferenceList {
		public Object ref;
		public LinkedList list = new LinkedList();

		public ReferenceList(Object ref) {
			this.ref = ref;
			list.add(ref);
		}
	}

	static class TraceStructure {
		public JCMethodInvocation call = null;
		public JCStatement stat = null;
		public LinkedList<TraceStructure> stats = new LinkedList<TraceStructure>();
	}

	enum UpdateAction {
		UPDATE_CLEANUP,
		UPDATE_PROCESS,
		SCAN_CODE,
		SCAN_SYMBOLS,
		SCAN_RESOLVE,
	}

	static boolean traceHeader = false;
	static boolean traceCall = false;

	static Resolve resolve = null;
	//static TreeScanner treeScanner = null;

	static Stack objectRefStack = new Stack();
	static LinkedList<JCVariableDecl> variableList = new LinkedList<JCVariableDecl>();
	static LinkedList<JCMethodDecl> methodList = new LinkedList<JCMethodDecl>();
	static TraceStructure traceStructure = null;

	public static boolean traceMethod(JCMethodDecl method) {
		boolean traceMethod = false;
		for (JCAnnotation anno : method.mods.annotations) {
			if (anno.annotationType instanceof JCIdent) {
				if ("RuntimeLoaderTrace".equals(((JCIdent) anno.annotationType).name.toString())) {
					traceMethod = true;
					break;
				}
			}
		}

		return traceMethod;
	}

	public static boolean findMethod(JCMethodDecl method, Object instance) {
		boolean traceMethod = false;
		for (JCAnnotation anno : method.mods.annotations) {
			if (anno.annotationType instanceof JCIdent) {
				if ("RuntimeLoaderTrace".equals(((JCIdent) anno.annotationType).name.toString())) {
					traceMethod = true;
					break;
				}
			}
		}

		return traceMethod;
	}

	public static void updateTreeRecur(ReferenceList objectRef, UpdateAction action) throws Exception {
		Field[] sourceFieldList = objectRef.ref.getClass().getDeclaredFields();

		HashMap<String, Field> sourceFieldMap = new HashMap<String, Field>();

		if (!traceHeader) {
			for (Field sourceField : sourceFieldList) {
				Object value = sourceField.get(objectRef.ref);
				String name = sourceField.getName();

				if (value instanceof List) {
					List sourceList = (List) value;
					ListBuffer targetListBuffer = new ListBuffer();

					//System.out.println(objectRef.ref.getClass().getName());
					if (UpdateAction.UPDATE_PROCESS.equals(action)
								&& objectRefStack.lastElement() instanceof JCMethodDecl
								&& objectRef.ref instanceof JCBlock
								&& "stats".equals(name)) {

						if (traceMethod((JCMethodDecl) objectRefStack.lastElement())) {
							Table table1 = ((JCMethodDecl) objectRefStack.lastElement()).getName().table;

							variableList.clear();
							traceStructure = new TraceStructure();

							// Analyze

							updateTreeRecur(new ReferenceList(objectRef.ref), UpdateAction.SCAN_CODE);

							// Header

							targetListBuffer.append(
									new CustomLabeledStatement(Name.fromString(table1, "RuntimeLoaderT1"),
											new CustomBlock(0, new ListBuffer().toList())));

							targetListBuffer.append(
									new CustomLabeledStatement(Name.fromString(table1, "RuntimeLoaderT2"),
											new CustomBlock(0, new ListBuffer().toList())));

							// Variables

							for (JCVariableDecl variable : variableList) {
								//System.out.println(variable.getType().getClass().getName());
								if (variable.getType() instanceof JCPrimitiveTypeTree) {
									int typetag = ((JCPrimitiveTypeTree) variable.getType()).typetag;
									variable.init = new CustomLiteral(typetag, 0);
								}
								else {
									variable.init = new CustomLiteral(TypeTags.BOT, null);
								}
								targetListBuffer.append(variable);
							}

							// Trace

							targetListBuffer.append(
									new CustomLabeledStatement(Name.fromString(table1, "RuntimeLoaderC"),
											new CustomBlock(0, new ListBuffer().toList())));

						}

					}

					for (Object sourceObject : sourceList) {
						ReferenceList targetObjectRef = new ReferenceList(sourceObject);

						objectRefStack.push(objectRef.ref);
						updateTreeRecur(targetObjectRef, action);
						objectRefStack.pop();

						if (targetObjectRef.ref != null) {
							targetObjectRef.list.set(0, targetObjectRef.ref);
							for (Object targetObject : targetObjectRef.list) {
								if (targetObject != null) {
									targetListBuffer.append(targetObject);
								}
							}
						}
					}

					sourceField.set(objectRef.ref, targetListBuffer.toList());
				}
				else if (value instanceof JCTree) {
					ReferenceList valueRef = new ReferenceList(value);

					objectRefStack.push(objectRef.ref);
					updateTreeRecur(valueRef, action);
					objectRefStack.pop();

					if (valueRef.ref == null) {
						objectRef.ref = null;
						return;
					}
					sourceField.set(objectRef.ref, valueRef.ref);
				}
			}
		}

		if (UpdateAction.UPDATE_CLEANUP.equals(action)) {
			if (objectRef.ref instanceof JCLabeledStatement) {
				String label1 = ((JCLabeledStatement) objectRef.ref).label.toString();
				if ("RuntimeLoaderT1".equals(label1)) {
					traceHeader = true;
					objectRef.ref = null;
					return;
				}
				else if ("RuntimeLoaderT2".equals(label1)) {
					traceHeader = false;
					objectRef.ref = null;
					return;
				}
				else if ("RuntimeLoaderC".equals(label1)) {
					objectRef.ref = ((JCLabeledStatement) objectRef.ref).body;
					if (objectRef.ref instanceof JCBlock) {
						switch (((JCBlock) objectRef.ref).stats.size()) {
						case 0:
							objectRef.ref = null;
							return;
						case 1:
							objectRef.ref = ((JCBlock) objectRef.ref).stats.get(0);
							break;
						}
					}
				}
			}

			if (traceHeader) {
				objectRef.ref = null;
				return;
			}
		}
		else if (UpdateAction.SCAN_CODE.equals(action)) {
			if (objectRef.ref instanceof JCVariableDecl) {
				JCVariableDecl object1 = (JCVariableDecl) objectRef.ref;
				variableList.add(object1);

				objectRef.ref = new CustomAssign(object1.vartype, object1.init);
			}
			else if (objectRef.ref instanceof JCMethodInvocation) {
				JCMethodInvocation object1 = (JCMethodInvocation) objectRef.ref;

				//System.out.println(object1.meth);

				if (object1.meth instanceof JCIdent) {

					System.out.println(((JCIdent)object1.meth).sym);
					/*if(((JCIdent)object1.meth).sym instanceof MethodSymbol) {
						System.out.println(((MethodSymbol)((JCIdent)object1.meth).sym).code);
					}*/
				}
				else if (object1.meth instanceof JCFieldAccess) {
					System.out.println(((JCFieldAccess) object1.meth).sym);
					//System.out.println(((JCFieldAccess) object1.meth).getExpression() + " " + ((JCFieldAccess) object1.meth).name);

				}
			}
		}
		else if (UpdateAction.SCAN_SYMBOLS.equals(action)) {
			if (objectRef.ref instanceof JCMethodDecl) {
				JCMethodDecl object1 = (JCMethodDecl) objectRef.ref;

				
				//resolve.resolveInternalMethod(object1.pos(), null, object1.type, object1.getName(), object1.);
				
				System.out.println(object1.sym);
				
				
				methodList.add(object1);
			}
			if (objectRef.ref instanceof JCMethodInvocation) {
				JCMethodInvocation object1 = (JCMethodInvocation) objectRef.ref;
				Name name = null;
				Type type = null;
				
				System.out.println(object1.meth.getClass().getName());

				if (object1.meth instanceof JCIdent) {
					name = ((JCIdent)object1.meth).name;
					type = ((JCIdent)object1.meth).type;

					//System.out.println(object1.type);
					//System.out.println(((JCIdent)object1.meth).type);
				}
				else if (object1.meth instanceof JCFieldAccess) {
					name = ((JCFieldAccess)object1.meth).name;
					type = ((JCFieldAccess)object1.meth).type;
				}

				//type = new Type(TypeTags.VOID, null);
				//type = new Type(TypeTags.VOID, new TypeSymbol());
				
				ListBuffer<Type> argtypeListBuffer = new ListBuffer<Type>();
				AttrContext attrContext = new AttrContext();
				Env<AttrContext> env = new Env<AttrContext>((JCTree) objectRef.ref, attrContext);

				System.out.println(type);
				System.out.println(type.tsym);
				
				resolve.resolveInternalMethod(object1.pos(), env, type, name, argtypeListBuffer.toList(), null);
				
			}
		}
	}

	public static void main(String[] args) throws Exception {
		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
		StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
		Iterable<? extends JavaFileObject> fileObjects = fileManager.getJavaFileObjects(
				"C:/Users/user2/workspace/runtimeLoader/src/runtimeLoader/Test.java"
				//"C:/Users/user2/workspace/runtimeLoader/src/runtimeLoader/Test2.java"
				);
		JavacTaskImpl javacTaskImpl = (JavacTaskImpl) compiler.getTask(null, fileManager, null, null, null, fileObjects);

		Iterable<? extends CompilationUnitTree> treeList = javacTaskImpl.parse();

		resolve = Resolve.instance(javacTaskImpl.getContext());

		for (CompilationUnitTree sourceTree : treeList) {
			/*treeScanner = new SourceTreeProcessor();
			sourceTree.accept(treeScanner, null);*/
			
			/*System.out.println(
					JavacTrees.instance(
							javacTaskImpl).getScope(
									JavacTrees.instance(javacTaskImpl).getPath(
											sourceTree, sourceTree)).getEnv());*/
			
			objectRefStack.clear();
			objectRefStack.push(new Object());
			updateTreeRecur(new ReferenceList(sourceTree), UpdateAction.SCAN_SYMBOLS);
		}

		/*for (CompilationUnitTree sourceTree : treeList) {
			objectRefStack.clear();
			objectRefStack.push(new Object());
			updateTreeRecur(new ReferenceList(sourceTree), UpdateAction.UPDATE_CLEANUP);
			updateTreeRecur(new ReferenceList(sourceTree), UpdateAction.UPDATE_PROCESS);

			StringWriter s = new StringWriter();
			new Pretty(s, false).printExpr((JCTree) sourceTree);

			//System.out.println(s.toString());
		}*/
	}

	/*private static class SourceTreeProcessor extends TreeScanner<Void, Void> {

		@Override
		public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
			//System.out.println(node.getMethodSelect().);
			return super.visitMethodInvocation(node, p);
		}
	}*/

	static class CustomLabeledStatement extends JCLabeledStatement {
		protected CustomLabeledStatement(Name arg0, JCStatement arg1) {
			super(arg0, arg1);
		}
	}

	static class CustomBlock extends JCBlock {
		protected CustomBlock(long arg0, List<JCStatement> arg1) {
			super(arg0, arg1);
		}
	}

	static class CustomAssign extends JCAssign {
		protected CustomAssign(JCExpression arg0, JCExpression arg1) {
			super(arg0, arg1);
		}
	}

	static class CustomLiteral extends JCLiteral {
		protected CustomLiteral(int arg0, Object arg1) {
			super(arg0, arg1);
		}
	}
}
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Nov 30 2010
Added on Oct 22 2010
2 comments
2,413 views