/**
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Eclipse Public License (EPL).
* Please see the license.txt included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
/*
* Created on Jun 10, 2006
* @author Fabio
*/
package org.python.pydev.parser.visitors.scope;
import java.util.List;
import org.python.pydev.parser.jython.SimpleNode;
import org.python.pydev.parser.jython.ast.Assign;
import org.python.pydev.parser.jython.ast.FunctionDef;
import org.python.pydev.parser.jython.ast.If;
import org.python.pydev.parser.jython.ast.Import;
import org.python.pydev.parser.jython.ast.ImportFrom;
import org.python.pydev.parser.jython.ast.commentType;
import org.python.pydev.parser.visitors.NodeUtils;
public class OutlineCreatorVisitor extends EasyASTIteratorWithChildrenVisitor {
public static OutlineCreatorVisitor create(SimpleNode ast) {
OutlineCreatorVisitor visitor = new OutlineCreatorVisitor();
if (ast == null) {
return visitor;
}
try {
ast.accept(visitor);
} catch (Exception e) {
throw new RuntimeException(e);
}
return visitor;
}
private boolean isInAssign;
@Override
public void traverse(SimpleNode node) throws Exception {
checkSpecials(node.specialsBefore);
super.traverse(node);
checkSpecials(node.specialsAfter);
}
@Override
public void traverse(FunctionDef node) throws Exception {
checkSpecials(node.specialsBefore);
super.traverse(node);
checkSpecials(node.specialsAfter);
}
/**
* @see org.python.pydev.parser.jython.ast.VisitorBase#visitImport(org.python.pydev.parser.jython.ast.Import)
*/
public Object visitImport(Import node) throws Exception {
atomic(node);
return super.visitImport(node);
}
/**
* @see org.python.pydev.parser.jython.ast.VisitorBase#visitImportFrom(org.python.pydev.parser.jython.ast.ImportFrom)
*/
public Object visitImportFrom(ImportFrom node) throws Exception {
atomic(node);
return super.visitImportFrom(node);
}
@Override
public Object visitAssign(Assign node) throws Exception {
isInAssign = true;
try {
DefinitionsASTIteratorVisitor.visitAssign(this, node, false);
} finally {
isInAssign = false;
}
traverse(node);
return null;
}
@Override
public Object visitIf(If node) throws Exception {
if (NodeUtils.isIfMAinNode(node)) {
atomic(node);
return null;
} else {
return super.visitIf(node);
}
}
@Override
protected void doAddNode(ASTEntry entry) {
SimpleNode node = entry.node;
if (node instanceof commentType) {
commentType type = (commentType) node;
if (type.beginColumn == 1) {
entry.parent = null; //top-level
} else {
//try to match it to some other indentation already set.
ASTEntryWithChildren lastAdded = null;
if (nodes != null && nodes.size() > 0) {
lastAdded = (ASTEntryWithChildren) nodes.get(nodes.size() - 1);
}
while (lastAdded != null) {
if (lastAdded.node == null) {
break;
}
//if it is equal to the indentation of this node, it's parent is the same, if it is higher
//it is a child or a child's child...
if (lastAdded.node.beginColumn == node.beginColumn) {
entry.parent = lastAdded.parent;
break;
} else if (node.beginColumn > lastAdded.node.beginColumn) {
//it's higher, so, check the last children of lastAdded for a possible parent...
entry.parent = lastAdded;
List<ASTEntryWithChildren> children = lastAdded.children;
if (children != null && children.size() > 0) {
lastAdded = children.get(children.size() - 1);
} else {
break;
}
} else {
//it's less, so, the parent is already set...
break;
}
}
}
}
super.doAddNode(entry);
}
private void checkSpecials(List<Object> specials) {
if (specials == null || isInAssign) {
return;
}
for (Object object : specials) {
if (object instanceof commentType) {
commentType type = (commentType) object;
String trimmed = type.id.trim();
if (trimmed.startsWith("#---") || trimmed.endsWith("---")) {
atomic(type);
}
}
}
}
}