blob: d41462a6c0a03b2b761a26c3fc04dc1daf7589b1 [file] [log] [blame]
package org.eclipse.photran.internal.core.model;
import java.lang.reflect.InvocationTargetException;
import java.util.LinkedList;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.internal.core.model.Parent;
import org.eclipse.photran.internal.core.analysis.loops.GenericASTVisitorWithLoops;
import org.eclipse.photran.internal.core.lexer.Terminal;
import org.eclipse.photran.internal.core.lexer.Token;
import org.eclipse.photran.internal.core.parser.IASTListNode;
import org.eclipse.photran.internal.core.parser.IASTNode;
/**
* THIS IS AN INTERNAL CLASS.
* <p>
* This AST visitor is used to build the model (i.e., Outline view) when the user chooses the
* "(Debugging) Show entire abstract syntax tree rather than Outline view" option in the workspace
* preferences.
* <p>
* The normal Outline view is created by a {@link FortranModelBuildingVisitor} instead.
*
* @author Jeff Overbey
*/
@SuppressWarnings("restriction")
public final class FortranParseTreeModelBuildingVisitor extends GenericASTVisitorWithLoops
{
// --INFRASTRUCTURE--------------------------------------------------
private org.eclipse.cdt.internal.core.model.TranslationUnit translationUnit;
private FortranModelBuilder modelBuilder;
public FortranParseTreeModelBuildingVisitor(
org.eclipse.cdt.internal.core.model.TranslationUnit translationUnit,
FortranModelBuilder modelBuilder)
{
this.translationUnit = translationUnit;
this.modelBuilder = modelBuilder;
}
private LinkedList<IASTNode> parentParseTreeNodeStack = new LinkedList<IASTNode>();
private LinkedList<FortranElement> parentElementStack = new LinkedList<FortranElement>();
private Parent getCurrentParent()
{
if (parentElementStack.isEmpty())
return translationUnit;
else
return (Parent)parentElementStack.getLast();
}
private boolean isCurrentParent(IASTNode node)
{
if (parentParseTreeNodeStack.isEmpty())
return false;
else
return node == (IASTNode)parentParseTreeNodeStack.getLast();
}
private void beginAddingChildrenFor(IASTNode parseTreeNode, FortranElement element)
{
parentParseTreeNodeStack.addLast(parseTreeNode);
parentElementStack.addLast(element);
}
private void doneAddingChildrenFor(IASTNode node)
{
if (isCurrentParent(node))
{
parentParseTreeNodeStack.removeLast();
parentElementStack.removeLast();
}
}
// --VISITOR METHODS-------------------------------------------------
private String methodNameDescPrefix = ""; //$NON-NLS-1$
@Override public void visitASTNode(IASTNode node)
{
FortranElement element = addElementForNode(node);
beginAddingChildrenFor(node, element);
addMethodDescriptions(node);
doneAddingChildrenFor(node);
}
private FortranElement addElementForNode(IASTNode node)
{
String description = methodNameDescPrefix + node.getClass().getSimpleName();
FortranElement element = new FortranElement.UnknownNode(getCurrentParent(), description);
// Token firstToken = ParseTreeSearcher.findFirstTokenIn(node);
// Token lastToken = ParseTreeSearcher.findLastTokenIn(node);
// if (firstToken != null && lastToken != null)
// {
// element.setPos(firstToken.getOffset(), (lastToken.getOffset() + lastToken.getLength())
// - firstToken.getOffset() - 1);
// element.setIdPos(firstToken.getOffset(), firstToken.getLength());
// element.setLines(firstToken.getStartLine(), lastToken.getEndLine());
// }
try
{
modelBuilder.addF90Element(element);
}
catch (CModelException e)
{
;
}
return element;
}
@SuppressWarnings("unchecked")
private void addMethodDescriptions(IASTNode node)
{
if (node instanceof IASTListNode<?>)
addListEltDescriptions((IASTListNode<? extends IASTNode>)node);
else
for (java.lang.reflect.Method m : node.getClass().getMethods())
if (shouldIncludeMethodDesc(node, m))
addMethodDesc(node, m);
}
private void addListEltDescriptions(IASTListNode< ? extends IASTNode> list)
{
for (int i = 0; i < list.size(); i++)
{
methodNameDescPrefix = "get(" + i + "): "; //$NON-NLS-1$ //$NON-NLS-2$
if (list.get(i) != null)
list.get(i).accept(this);
}
}
private boolean shouldIncludeMethodDesc(IASTNode node, java.lang.reflect.Method m)
{
return m.getDeclaringClass() == node.getClass()
&& m.getReturnType() != null
&& m.getParameterTypes().length == 0
&& !m.getName().equals("getParent") //$NON-NLS-1$
&& !m.getName().equals("getChildren") //$NON-NLS-1$
&& !m.getName().equals("findFirstToken") //$NON-NLS-1$
&& !m.getName().equals("findLastToken"); //$NON-NLS-1$
}
private void addMethodDesc(IASTNode node, java.lang.reflect.Method m)
{
try
{
methodNameDescPrefix = m.getName() + "(): "; //$NON-NLS-1$
if (IASTNode.class.isAssignableFrom(m.getReturnType()))
{
describeASTGetterMethod(node, m);
}
else if (m.getReturnType() != null)
{
describeOtherMethod(node, m);
}
}
catch (IllegalArgumentException e) {;}
catch (IllegalAccessException e) {;}
catch (InvocationTargetException e) {;}
catch (CModelException e) {;}
}
private void describeASTGetterMethod(IASTNode node, java.lang.reflect.Method m)
throws IllegalAccessException, InvocationTargetException, CModelException
{
IASTNode n = ((IASTNode)m.invoke(node, (Object[])null));
if (n == null)
modelBuilder.addF90Element(
new FortranElement.UnknownNode(getCurrentParent(),
methodNameDescPrefix + "null")); //$NON-NLS-1$
else
n.accept(this);
}
private void describeOtherMethod(IASTNode node, java.lang.reflect.Method m)
throws IllegalAccessException, InvocationTargetException, CModelException
{
Object n = m.invoke(node, (Object[])null);
if (n == null)
modelBuilder.addF90Element(
new FortranElement.UnknownNode(getCurrentParent(),
methodNameDescPrefix + "null")); //$NON-NLS-1$
else
modelBuilder.addF90Element(
new FortranElement.UnknownNode(getCurrentParent(),
methodNameDescPrefix + n));
}
@Override public void visitToken(Token token)
{
String description = methodNameDescPrefix + token.getClass().getSimpleName();
FortranElement element = new FortranElement.UnknownNode(getCurrentParent(), description);
modelBuilder.configureElement(element, token);
try
{
modelBuilder.addF90Element(element);
beginAddingChildrenFor(token, element);
modelBuilder.addF90Element(
new FortranElement.UnknownNode(getCurrentParent(),
"getTerminal(): Terminal." + findTerminal(token.getTerminal()))); //$NON-NLS-1$
modelBuilder.addF90Element(
new FortranElement.UnknownNode(getCurrentParent(),
"getText(): \"" + token.getText().replaceAll("\\n", "\\\\n") + "\"")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
modelBuilder.addF90Element(
new FortranElement.UnknownNode(getCurrentParent(),
"getPreprocessorDirective(): " + token.getPreprocessorDirective())); //$NON-NLS-1$
modelBuilder.addF90Element(
new FortranElement.UnknownNode(getCurrentParent(),
"getPhysicalFile(): " + token.getPhysicalFile())); //$NON-NLS-1$
modelBuilder.addF90Element(
new FortranElement.UnknownNode(getCurrentParent(),
"getFileOffset(): " + token.getFileOffset())); //$NON-NLS-1$
modelBuilder.addF90Element(
new FortranElement.UnknownNode(getCurrentParent(),
"getLogicalFile(): " + token.getLogicalFile())); //$NON-NLS-1$
modelBuilder.addF90Element(
new FortranElement.UnknownNode(getCurrentParent(),
"getStreamOffset(): " + token.getStreamOffset())); //$NON-NLS-1$
doneAddingChildrenFor(token);
}
catch (CModelException e)
{
;
}
}
private String findTerminal(Terminal terminal)
{
for (java.lang.reflect.Field f : Terminal.class.getFields())
{
try
{
if (f.get(null) == terminal)
return f.getName();
}
catch (IllegalArgumentException e)
{
;
}
catch (IllegalAccessException e)
{
;
}
}
return "?"; //$NON-NLS-1$
}
}