mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 22:52:11 +02:00
Patch for Devin Steffler.
This patch includes: - several enhancements made to the DOM AST View to improve performance - "Display Problems" button that will display all found IASTProblems in the AST via the Search View
This commit is contained in:
parent
85d1c00390
commit
bd9022596d
7 changed files with 318 additions and 166 deletions
|
@ -188,4 +188,30 @@ public class ArrayUtil {
|
||||||
if( array[i] == obj ) return true;
|
if( array[i] == obj ) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all of the nulls from the array and returns a new
|
||||||
|
* array that contains all of the non-null elements.
|
||||||
|
*
|
||||||
|
* If there are no nulls in the original array then the original
|
||||||
|
* array is returned.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Object[] removeNulls(Class c, Object[] array) {
|
||||||
|
if( array == null )
|
||||||
|
return (Object[]) Array.newInstance( c, 0 );
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
int j = 0;
|
||||||
|
Object[] newArray = new Object[array.length];
|
||||||
|
for( ; i < array.length; i++ ){
|
||||||
|
if( array[i] != null ) newArray[j++] = array[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j<i) return ArrayUtil.trim(c, newArray);
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,10 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionTryBlockDeclarator;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionTryBlockDeclarator;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
|
||||||
|
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||||
import org.eclipse.cdt.internal.core.parser.scanner2.LocationMap.ASTInclusionStatement;
|
import org.eclipse.cdt.internal.core.parser.scanner2.LocationMap.ASTInclusionStatement;
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
@ -46,6 +48,7 @@ import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
* @author dsteffle
|
* @author dsteffle
|
||||||
*/
|
*/
|
||||||
public class CPPPopulateASTViewAction extends CPPASTVisitor implements IPopulateDOMASTAction {
|
public class CPPPopulateASTViewAction extends CPPASTVisitor implements IPopulateDOMASTAction {
|
||||||
|
private static final int INITIAL_PROBLEM_SIZE = 4;
|
||||||
private static final int INITIAL_INCLUDE_STATEMENT_SIZE = 8;
|
private static final int INITIAL_INCLUDE_STATEMENT_SIZE = 8;
|
||||||
{
|
{
|
||||||
shouldVisitNames = true;
|
shouldVisitNames = true;
|
||||||
|
@ -64,6 +67,7 @@ public class CPPPopulateASTViewAction extends CPPASTVisitor implements IPopulate
|
||||||
|
|
||||||
TreeParent root = null;
|
TreeParent root = null;
|
||||||
IProgressMonitor monitor = null;
|
IProgressMonitor monitor = null;
|
||||||
|
IASTProblem[] astProblems = new IASTProblem[INITIAL_PROBLEM_SIZE];
|
||||||
|
|
||||||
public CPPPopulateASTViewAction(IASTTranslationUnit tu, IProgressMonitor monitor) {
|
public CPPPopulateASTViewAction(IASTTranslationUnit tu, IProgressMonitor monitor) {
|
||||||
root = new TreeParent(tu);
|
root = new TreeParent(tu);
|
||||||
|
@ -75,7 +79,8 @@ public class CPPPopulateASTViewAction extends CPPASTVisitor implements IPopulate
|
||||||
if (node == null) return PROCESS_CONTINUE;
|
if (node == null) return PROCESS_CONTINUE;
|
||||||
|
|
||||||
IASTNodeLocation[] nodeLocations = node.getNodeLocations();
|
IASTNodeLocation[] nodeLocations = node.getNodeLocations();
|
||||||
if (!(nodeLocations.length > 0 &&
|
// TODO Devin !(node instanceof ICPPASTLinkageSpecification) below is a hack job for bug 86993
|
||||||
|
if (!(node instanceof ICPPASTLinkageSpecification) && !(nodeLocations.length > 0 &&
|
||||||
nodeLocations[0].getNodeOffset() >= 0 &&
|
nodeLocations[0].getNodeOffset() >= 0 &&
|
||||||
nodeLocations[0].getNodeLength() > 0))
|
nodeLocations[0].getNodeLength() > 0))
|
||||||
return PROCESS_CONTINUE;
|
return PROCESS_CONTINUE;
|
||||||
|
@ -89,8 +94,14 @@ public class CPPPopulateASTViewAction extends CPPASTVisitor implements IPopulate
|
||||||
parent.addChild(tree);
|
parent.addChild(tree);
|
||||||
|
|
||||||
// set filter flags
|
// set filter flags
|
||||||
if (node instanceof IASTProblemHolder || node instanceof IASTProblem)
|
if (node instanceof IASTProblemHolder || node instanceof IASTProblem) {
|
||||||
tree.setFiltersFlag(TreeObject.FLAG_PROBLEM);
|
tree.setFiltersFlag(TreeObject.FLAG_PROBLEM);
|
||||||
|
|
||||||
|
if (node instanceof IASTProblemHolder)
|
||||||
|
astProblems = (IASTProblem[])ArrayUtil.append(IASTProblemHolder.class, astProblems, ((IASTProblemHolder)node).getProblem());
|
||||||
|
else
|
||||||
|
astProblems = (IASTProblem[])ArrayUtil.append(IASTProblemHolder.class, astProblems, node);
|
||||||
|
}
|
||||||
if (node instanceof IASTPreprocessorStatement)
|
if (node instanceof IASTPreprocessorStatement)
|
||||||
tree.setFiltersFlag(TreeObject.FLAG_PREPROCESSOR);
|
tree.setFiltersFlag(TreeObject.FLAG_PREPROCESSOR);
|
||||||
if (node instanceof IASTPreprocessorIncludeStatement)
|
if (node instanceof IASTPreprocessorIncludeStatement)
|
||||||
|
@ -247,20 +258,18 @@ public class CPPPopulateASTViewAction extends CPPASTVisitor implements IPopulate
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for(int i=0; i<statements.length; i++) {
|
for(int i=0; i<statements.length; i++) {
|
||||||
if (monitor != null && monitor.isCanceled()) return;
|
if (monitor != null && monitor.isCanceled()) return;
|
||||||
if (index+1 > includes.length) {
|
if (statements[i] instanceof IASTPreprocessorIncludeStatement) {
|
||||||
IASTPreprocessorIncludeStatement[] newIncludes = new IASTPreprocessorIncludeStatement[includes.length * 2];
|
if (index == includes.length) {
|
||||||
for (int j=0; j<includes.length; j++) {
|
includes = (IASTPreprocessorIncludeStatement[])ArrayUtil.append(IASTPreprocessorIncludeStatement.class, includes, statements[i]);
|
||||||
newIncludes[j] = includes[j];
|
index++;
|
||||||
}
|
} else {
|
||||||
includes = newIncludes;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (statements[i] instanceof IASTPreprocessorIncludeStatement)
|
|
||||||
includes[index++] = (IASTPreprocessorIncludeStatement)statements[i];
|
includes[index++] = (IASTPreprocessorIncludeStatement)statements[i];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// get the tree model elements corresponding to the includes
|
// get the tree model elements corresponding to the includes
|
||||||
TreeParent[] treeIncludes = new TreeParent[includes.length];
|
TreeParent[] treeIncludes = new TreeParent[index];
|
||||||
for (int i=0; i<treeIncludes.length; i++) {
|
for (int i=0; i<treeIncludes.length; i++) {
|
||||||
if (monitor != null && monitor.isCanceled()) return;
|
if (monitor != null && monitor.isCanceled()) return;
|
||||||
treeIncludes[i] = root.findTreeObject(includes[i], false);
|
treeIncludes[i] = root.findTreeObject(includes[i], false);
|
||||||
|
@ -269,14 +278,14 @@ public class CPPPopulateASTViewAction extends CPPASTVisitor implements IPopulate
|
||||||
// loop through the includes and make sure that all of the nodes
|
// loop through the includes and make sure that all of the nodes
|
||||||
// that are children of the TU are in the proper include (based on offset)
|
// that are children of the TU are in the proper include (based on offset)
|
||||||
TreeObject child = null;
|
TreeObject child = null;
|
||||||
for (int i=treeIncludes.length-1; i>=0; i--) {
|
outerLoop: for (int i=treeIncludes.length-1; i>=0; i--) {
|
||||||
if (treeIncludes[i] == null) continue;
|
if (treeIncludes[i] == null) continue;
|
||||||
|
|
||||||
for(int j=root.getChildren().length-1; j>=0; j--) {
|
for(int j=root.getChildren(false).length-1; j>=0; j--) {
|
||||||
if (monitor != null && monitor.isCanceled()) return;
|
if (monitor != null && monitor.isCanceled()) return;
|
||||||
child = root.getChildren()[j];
|
child = root.getChildren(false)[j];
|
||||||
|
|
||||||
if (treeIncludes[i] != child &&
|
if (child != null && treeIncludes[i] != child &&
|
||||||
includes[i] instanceof ASTInclusionStatement &&
|
includes[i] instanceof ASTInclusionStatement &&
|
||||||
((ASTNode)child.getNode()).getOffset() >= ((ASTInclusionStatement)includes[i]).startOffset &&
|
((ASTNode)child.getNode()).getOffset() >= ((ASTInclusionStatement)includes[i]).startOffset &&
|
||||||
((ASTNode)child.getNode()).getOffset() <= ((ASTInclusionStatement)includes[i]).endOffset) {
|
((ASTNode)child.getNode()).getOffset() <= ((ASTInclusionStatement)includes[i]).endOffset) {
|
||||||
|
@ -286,4 +295,8 @@ public class CPPPopulateASTViewAction extends CPPASTVisitor implements IPopulate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IASTProblem[] getASTProblems() {
|
||||||
|
return astProblems;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ import org.eclipse.cdt.core.dom.ast.IASTTypeId;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
|
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
|
||||||
import org.eclipse.cdt.core.dom.ast.c.CASTVisitor;
|
import org.eclipse.cdt.core.dom.ast.c.CASTVisitor;
|
||||||
import org.eclipse.cdt.core.dom.ast.c.ICASTDesignator;
|
import org.eclipse.cdt.core.dom.ast.c.ICASTDesignator;
|
||||||
|
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||||
import org.eclipse.cdt.internal.core.parser.scanner2.LocationMap.ASTInclusionStatement;
|
import org.eclipse.cdt.internal.core.parser.scanner2.LocationMap.ASTInclusionStatement;
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
@ -41,6 +42,7 @@ import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
* @author dsteffle
|
* @author dsteffle
|
||||||
*/
|
*/
|
||||||
public class CPopulateASTViewAction extends CASTVisitor implements IPopulateDOMASTAction {
|
public class CPopulateASTViewAction extends CASTVisitor implements IPopulateDOMASTAction {
|
||||||
|
private static final int INITIAL_PROBLEM_SIZE = 4;
|
||||||
private static final int INITIAL_INCLUDE_STATEMENT_SIZE = 8;
|
private static final int INITIAL_INCLUDE_STATEMENT_SIZE = 8;
|
||||||
{
|
{
|
||||||
shouldVisitNames = true;
|
shouldVisitNames = true;
|
||||||
|
@ -58,6 +60,7 @@ public class CPopulateASTViewAction extends CASTVisitor implements IPopulateDOMA
|
||||||
|
|
||||||
TreeParent root = null;
|
TreeParent root = null;
|
||||||
IProgressMonitor monitor = null;
|
IProgressMonitor monitor = null;
|
||||||
|
IASTProblem[] astProblems = new IASTProblem[INITIAL_PROBLEM_SIZE];
|
||||||
|
|
||||||
public CPopulateASTViewAction(IASTTranslationUnit tu, IProgressMonitor monitor) {
|
public CPopulateASTViewAction(IASTTranslationUnit tu, IProgressMonitor monitor) {
|
||||||
root = new TreeParent(tu);
|
root = new TreeParent(tu);
|
||||||
|
@ -83,13 +86,21 @@ public class CPopulateASTViewAction extends CASTVisitor implements IPopulateDOMA
|
||||||
parent.addChild(tree);
|
parent.addChild(tree);
|
||||||
|
|
||||||
// set filter flags
|
// set filter flags
|
||||||
if (node instanceof IASTProblemHolder || node instanceof IASTProblem)
|
if (node instanceof IASTProblemHolder || node instanceof IASTProblem) {
|
||||||
tree.setFiltersFlag(TreeObject.FLAG_PROBLEM);
|
tree.setFiltersFlag(TreeObject.FLAG_PROBLEM);
|
||||||
|
|
||||||
|
if (node instanceof IASTProblemHolder)
|
||||||
|
astProblems = (IASTProblem[])ArrayUtil.append(IASTProblemHolder.class, astProblems, ((IASTProblemHolder)node).getProblem());
|
||||||
|
else
|
||||||
|
astProblems = (IASTProblem[])ArrayUtil.append(IASTProblemHolder.class, astProblems, node);
|
||||||
|
}
|
||||||
if (node instanceof IASTPreprocessorStatement)
|
if (node instanceof IASTPreprocessorStatement)
|
||||||
tree.setFiltersFlag(TreeObject.FLAG_PREPROCESSOR);
|
tree.setFiltersFlag(TreeObject.FLAG_PREPROCESSOR);
|
||||||
if (node instanceof IASTPreprocessorIncludeStatement)
|
if (node instanceof IASTPreprocessorIncludeStatement)
|
||||||
tree.setFiltersFlag(TreeObject.FLAG_INCLUDE_STATEMENTS);
|
tree.setFiltersFlag(TreeObject.FLAG_INCLUDE_STATEMENTS);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return PROCESS_CONTINUE;
|
return PROCESS_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,20 +231,18 @@ public class CPopulateASTViewAction extends CASTVisitor implements IPopulateDOMA
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for(int i=0; i<statements.length; i++) {
|
for(int i=0; i<statements.length; i++) {
|
||||||
if (monitor != null && monitor.isCanceled()) return;
|
if (monitor != null && monitor.isCanceled()) return;
|
||||||
if (index+1 > includes.length) {
|
if (statements[i] instanceof IASTPreprocessorIncludeStatement) {
|
||||||
IASTPreprocessorIncludeStatement[] newIncludes = new IASTPreprocessorIncludeStatement[includes.length * 2];
|
if (index == includes.length) {
|
||||||
for (int j=0; j<includes.length; j++) {
|
includes = (IASTPreprocessorIncludeStatement[])ArrayUtil.append(IASTPreprocessorIncludeStatement.class, includes, statements[i]);
|
||||||
newIncludes[j] = includes[j];
|
index++;
|
||||||
}
|
} else {
|
||||||
includes = newIncludes;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (statements[i] instanceof IASTPreprocessorIncludeStatement)
|
|
||||||
includes[index++] = (IASTPreprocessorIncludeStatement)statements[i];
|
includes[index++] = (IASTPreprocessorIncludeStatement)statements[i];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// get the tree model elements corresponding to the includes
|
// get the tree model elements corresponding to the includes
|
||||||
TreeParent[] treeIncludes = new TreeParent[includes.length];
|
TreeParent[] treeIncludes = new TreeParent[index];
|
||||||
for (int i=0; i<treeIncludes.length; i++) {
|
for (int i=0; i<treeIncludes.length; i++) {
|
||||||
if (monitor != null && monitor.isCanceled()) return;
|
if (monitor != null && monitor.isCanceled()) return;
|
||||||
treeIncludes[i] = root.findTreeObject(includes[i], false);
|
treeIncludes[i] = root.findTreeObject(includes[i], false);
|
||||||
|
@ -242,14 +251,15 @@ public class CPopulateASTViewAction extends CASTVisitor implements IPopulateDOMA
|
||||||
// loop through the includes and make sure that all of the nodes
|
// loop through the includes and make sure that all of the nodes
|
||||||
// that are children of the TU are in the proper include (based on offset)
|
// that are children of the TU are in the proper include (based on offset)
|
||||||
TreeObject child = null;
|
TreeObject child = null;
|
||||||
for (int i=treeIncludes.length-1; i>=0; i--) {
|
outerLoop: for (int i=treeIncludes.length-1; i>=0; i--) {
|
||||||
if (treeIncludes[i] == null) continue;
|
if (treeIncludes[i] == null) continue;
|
||||||
|
|
||||||
for(int j=root.getChildren().length-1; j>=0; j--) {
|
for(int j=root.getChildren(false).length-1; j>=0; j--) {
|
||||||
if (monitor != null && monitor.isCanceled()) return;
|
if (monitor != null && monitor.isCanceled()) return;
|
||||||
child = root.getChildren()[j];
|
child = root.getChildren(false)[j];
|
||||||
|
|
||||||
if (treeIncludes[i] != child &&
|
if (child != null &&
|
||||||
|
treeIncludes[i] != child &&
|
||||||
includes[i] instanceof ASTInclusionStatement &&
|
includes[i] instanceof ASTInclusionStatement &&
|
||||||
((ASTNode)child.getNode()).getOffset() >= ((ASTInclusionStatement)includes[i]).startOffset &&
|
((ASTNode)child.getNode()).getOffset() >= ((ASTInclusionStatement)includes[i]).startOffset &&
|
||||||
((ASTNode)child.getNode()).getOffset() <= ((ASTInclusionStatement)includes[i]).endOffset) {
|
((ASTNode)child.getNode()).getOffset() <= ((ASTInclusionStatement)includes[i]).endOffset) {
|
||||||
|
@ -259,4 +269,8 @@ public class CPopulateASTViewAction extends CASTVisitor implements IPopulateDOMA
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IASTProblem[] getASTProblems() {
|
||||||
|
return astProblems;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,10 +131,12 @@ public class DOMAST extends ViewPart {
|
||||||
private static final String POPUPMENU = "#PopupMenu"; //$NON-NLS-1$
|
private static final String POPUPMENU = "#PopupMenu"; //$NON-NLS-1$
|
||||||
private static final String OPEN_DECLARATIONS = "Open Declarations"; //$NON-NLS-1$
|
private static final String OPEN_DECLARATIONS = "Open Declarations"; //$NON-NLS-1$
|
||||||
private static final String OPEN_REFERENCES = "Open References"; //$NON-NLS-1$
|
private static final String OPEN_REFERENCES = "Open References"; //$NON-NLS-1$
|
||||||
|
private static final String DISPLAY_PROBLEMS = "Display Problems"; //$NON-NLS-1$
|
||||||
TreeViewer viewer;
|
TreeViewer viewer;
|
||||||
private DrillDownAdapter drillDownAdapter;
|
private DrillDownAdapter drillDownAdapter;
|
||||||
private Action openDeclarationsAction;
|
private Action openDeclarationsAction;
|
||||||
private Action openReferencesAction;
|
private Action openReferencesAction;
|
||||||
|
private Action displayProblemsAction;
|
||||||
private Action displayNodeTypeAction;
|
private Action displayNodeTypeAction;
|
||||||
private Action displayNodeSignatureAction;
|
private Action displayNodeSignatureAction;
|
||||||
private Action displayExpressionAction;
|
private Action displayExpressionAction;
|
||||||
|
@ -167,6 +169,7 @@ public class DOMAST extends ViewPart {
|
||||||
private TreeParent invisibleRoot;
|
private TreeParent invisibleRoot;
|
||||||
private TreeParent tuTreeParent = null;
|
private TreeParent tuTreeParent = null;
|
||||||
private IASTTranslationUnit tu = null;
|
private IASTTranslationUnit tu = null;
|
||||||
|
private IASTProblem[] astProblems = null;
|
||||||
|
|
||||||
public ViewContentProvider() {
|
public ViewContentProvider() {
|
||||||
}
|
}
|
||||||
|
@ -343,7 +346,7 @@ public class DOMAST extends ViewPart {
|
||||||
return Status.CANCEL_STATUS;
|
return Status.CANCEL_STATUS;
|
||||||
|
|
||||||
if (monitor.isCanceled()) return Status.CANCEL_STATUS;
|
if (monitor.isCanceled()) return Status.CANCEL_STATUS;
|
||||||
monitor.beginTask(name, 7);
|
monitor.beginTask(name, 8);
|
||||||
start=System.currentTimeMillis();
|
start=System.currentTimeMillis();
|
||||||
|
|
||||||
IPopulateDOMASTAction action = null;
|
IPopulateDOMASTAction action = null;
|
||||||
|
@ -415,6 +418,12 @@ public class DOMAST extends ViewPart {
|
||||||
|
|
||||||
root.addChild(action.getTree());
|
root.addChild(action.getTree());
|
||||||
|
|
||||||
|
// get the IASTProblems from the action
|
||||||
|
if (action instanceof CPopulateASTViewAction)
|
||||||
|
astProblems = ((CPopulateASTViewAction)action).getASTProblems();
|
||||||
|
else if (action instanceof CPPPopulateASTViewAction)
|
||||||
|
astProblems = ((CPPPopulateASTViewAction)action).getASTProblems();
|
||||||
|
|
||||||
provider.setInvisibleRoot(root);
|
provider.setInvisibleRoot(root);
|
||||||
|
|
||||||
monitor.done();
|
monitor.done();
|
||||||
|
@ -426,8 +435,12 @@ public class DOMAST extends ViewPart {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IASTProblem[] getASTProblems() {
|
||||||
|
return astProblems;
|
||||||
|
}
|
||||||
|
|
||||||
private void initialize() {
|
private void initialize() {
|
||||||
invisibleRoot = new TreeParent(null); // blank the AST View, when the job above is complete it will update the AST View with the proper tree
|
invisibleRoot = new TreeParent(); // blank the AST View, when the job above is complete it will update the AST View with the proper tree
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setInvisibleRoot(TreeParent root) {
|
protected void setInvisibleRoot(TreeParent root) {
|
||||||
|
@ -533,6 +546,7 @@ public class DOMAST extends ViewPart {
|
||||||
class ViewLabelProvider extends LabelProvider {
|
class ViewLabelProvider extends LabelProvider {
|
||||||
|
|
||||||
public String getText(Object obj) {
|
public String getText(Object obj) {
|
||||||
|
if (obj == null) return "";
|
||||||
return obj.toString();
|
return obj.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -598,6 +612,7 @@ public class DOMAST extends ViewPart {
|
||||||
}
|
}
|
||||||
|
|
||||||
class NameSorter extends ViewerSorter {
|
class NameSorter extends ViewerSorter {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DOMAST() {
|
public DOMAST() {
|
||||||
|
@ -628,6 +643,7 @@ public class DOMAST extends ViewPart {
|
||||||
|
|
||||||
viewer.setLabelProvider(new ViewLabelProvider());
|
viewer.setLabelProvider(new ViewLabelProvider());
|
||||||
viewer.setInput(getViewSite());
|
viewer.setInput(getViewSite());
|
||||||
|
|
||||||
makeActions();
|
makeActions();
|
||||||
hookContextMenu();
|
hookContextMenu();
|
||||||
hookSingleClickAction();
|
hookSingleClickAction();
|
||||||
|
@ -757,6 +773,7 @@ public class DOMAST extends ViewPart {
|
||||||
manager.add(clearAction);
|
manager.add(clearAction);
|
||||||
manager.add(new Separator());
|
manager.add(new Separator());
|
||||||
manager.add(searchNamesAction);
|
manager.add(searchNamesAction);
|
||||||
|
manager.add(displayProblemsAction);
|
||||||
manager.add(new Separator());
|
manager.add(new Separator());
|
||||||
drillDownAdapter.addNavigationActions(manager);
|
drillDownAdapter.addNavigationActions(manager);
|
||||||
}
|
}
|
||||||
|
@ -840,6 +857,10 @@ public class DOMAST extends ViewPart {
|
||||||
openReferencesAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages()
|
openReferencesAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages()
|
||||||
.getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK));
|
.getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK));
|
||||||
|
|
||||||
|
displayProblemsAction = new DisplayProblemsResultAction();
|
||||||
|
displayProblemsAction.setText(DISPLAY_PROBLEMS);
|
||||||
|
displayProblemsAction.setImageDescriptor(DOMASTPluginImages.DESC_IASTProblem);
|
||||||
|
|
||||||
displayNodeTypeAction = new Action() {
|
displayNodeTypeAction = new Action() {
|
||||||
public void run() {
|
public void run() {
|
||||||
ISelection selection = viewer.getSelection();
|
ISelection selection = viewer.getSelection();
|
||||||
|
@ -1027,6 +1048,26 @@ public class DOMAST extends ViewPart {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class DisplayProblemsResultAction extends Action {
|
||||||
|
private static final String IASTPROBLEM = "IASTProblem"; //$NON-NLS-1$
|
||||||
|
private static final String PROBLEMS_FOUND = "Problems Found"; //$NON-NLS-1$
|
||||||
|
protected void displayProblems(IASTProblem[] problems, String queryLabel, String pattern) {
|
||||||
|
DOMQuery job = new DOMQuery(problems, queryLabel, pattern);
|
||||||
|
NewSearchUI.activateSearchResultView();
|
||||||
|
NewSearchUI.runQuery(job);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
if (viewer.getTree().getItems().length == 0) {
|
||||||
|
showMessage(DOM_AST_HAS_NO_CONTENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (viewer.getContentProvider() instanceof ViewContentProvider) {
|
||||||
|
displayProblems(((ViewContentProvider)viewer.getContentProvider()).getASTProblems(), PROBLEMS_FOUND, IASTPROBLEM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void hookSingleClickAction() {
|
private void hookSingleClickAction() {
|
||||||
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
|
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
|
||||||
public void selectionChanged(SelectionChangedEvent event) {
|
public void selectionChanged(SelectionChangedEvent event) {
|
||||||
|
|
|
@ -12,7 +12,9 @@ package org.eclipse.cdt.ui.tests.DOMAST;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
|
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
|
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTProblem;
|
||||||
import org.eclipse.cdt.core.model.ICElement;
|
import org.eclipse.cdt.core.model.ICElement;
|
||||||
import org.eclipse.cdt.core.search.BasicSearchMatch;
|
import org.eclipse.cdt.core.search.BasicSearchMatch;
|
||||||
import org.eclipse.cdt.core.search.IMatch;
|
import org.eclipse.cdt.core.search.IMatch;
|
||||||
|
@ -41,15 +43,15 @@ public class DOMQuery extends CSearchQuery implements ISearchQuery {
|
||||||
|
|
||||||
private static final String BLANK_STRING = ""; //$NON-NLS-1$
|
private static final String BLANK_STRING = ""; //$NON-NLS-1$
|
||||||
private CSearchResult _result;
|
private CSearchResult _result;
|
||||||
private IASTName[] names = null;
|
private IASTNode[] nodes = null;
|
||||||
private String queryLabel = null;
|
private String queryLabel = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public DOMQuery(IASTName[] names, String queryLabel, String pattern) {
|
public DOMQuery(IASTNode[] nodes, String queryLabel, String pattern) {
|
||||||
super(CTestPlugin.getWorkspace(), pattern, false, null, null, null, queryLabel, null);
|
super(CTestPlugin.getWorkspace(), pattern, false, null, null, null, queryLabel, null);
|
||||||
this.names = names;
|
this.nodes = nodes;
|
||||||
this.queryLabel = queryLabel;
|
this.queryLabel = queryLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,15 +68,15 @@ public class DOMQuery extends CSearchQuery implements ISearchQuery {
|
||||||
|
|
||||||
collector.aboutToStart();
|
collector.aboutToStart();
|
||||||
|
|
||||||
for (int i=0; i<names.length; i++) {
|
for (int i=0; i<nodes.length; i++) {
|
||||||
try {
|
try {
|
||||||
String fileName = null;
|
String fileName = null;
|
||||||
IFile file = null;
|
IFile file = null;
|
||||||
IPath path = null;
|
IPath path = null;
|
||||||
int start = 0;
|
int start = 0;
|
||||||
int end = 0;
|
int end = 0;
|
||||||
if ( names[i] != null ) {
|
if ( nodes[i] != null ) {
|
||||||
IASTNodeLocation [] location = names[i].getNodeLocations();
|
IASTNodeLocation [] location = nodes[i].getNodeLocations();
|
||||||
if( location.length > 0 && location[0] instanceof IASTFileLocation )
|
if( location.length > 0 && location[0] instanceof IASTFileLocation )
|
||||||
fileName = ((IASTFileLocation)location[0]).getFileName(); // TODO Devin this is in two places now, put into one, and fix up the location[0] for things like macros
|
fileName = ((IASTFileLocation)location[0]).getFileName(); // TODO Devin this is in two places now, put into one, and fix up the location[0] for things like macros
|
||||||
else
|
else
|
||||||
|
@ -83,11 +85,11 @@ public class DOMQuery extends CSearchQuery implements ISearchQuery {
|
||||||
path = new Path(fileName);
|
path = new Path(fileName);
|
||||||
file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(path);
|
file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(path);
|
||||||
|
|
||||||
if (names[i].getNodeLocations().length > 0) { // fix for 84223
|
if (nodes[i].getNodeLocations().length > 0) { // fix for 84223
|
||||||
start = names[i].getNodeLocations()[0].getNodeOffset();
|
start = nodes[i].getNodeLocations()[0].getNodeOffset();
|
||||||
end = names[i].getNodeLocations()[0].getNodeOffset() + names[i].getNodeLocations()[0].getNodeLength();
|
end = nodes[i].getNodeLocations()[0].getNodeOffset() + nodes[i].getNodeLocations()[0].getNodeLength();
|
||||||
|
|
||||||
collector.acceptMatch( createMatch(file, start, end, names[i], path ) );
|
collector.acceptMatch( createMatch(file, start, end, nodes[i], path ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (CoreException ce) {}
|
} catch (CoreException ce) {}
|
||||||
|
@ -99,7 +101,7 @@ public class DOMQuery extends CSearchQuery implements ISearchQuery {
|
||||||
return new Status(IStatus.OK, CTestPlugin.getPluginId(), 0, BLANK_STRING, null); //$NON-NLS-1$
|
return new Status(IStatus.OK, CTestPlugin.getPluginId(), 0, BLANK_STRING, null); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
|
||||||
public IMatch createMatch( Object fileResource, int start, int end, IASTName name, IPath referringElement ) {
|
public IMatch createMatch( Object fileResource, int start, int end, IASTNode node, IPath referringElement ) {
|
||||||
BasicSearchMatch result = new BasicSearchMatch();
|
BasicSearchMatch result = new BasicSearchMatch();
|
||||||
if( fileResource instanceof IResource )
|
if( fileResource instanceof IResource )
|
||||||
result.resource = (IResource) fileResource;
|
result.resource = (IResource) fileResource;
|
||||||
|
@ -111,7 +113,12 @@ public class DOMQuery extends CSearchQuery implements ISearchQuery {
|
||||||
result.parentName = BLANK_STRING; //$NON-NLS-1$
|
result.parentName = BLANK_STRING; //$NON-NLS-1$
|
||||||
result.referringElement = referringElement;
|
result.referringElement = referringElement;
|
||||||
|
|
||||||
result.name = name.toString();
|
if (node instanceof IASTName)
|
||||||
|
result.name = node.toString();
|
||||||
|
else if (node instanceof IASTProblem)
|
||||||
|
result.name = ((IASTProblem)node).getMessage();
|
||||||
|
else
|
||||||
|
result.name = node.toString();
|
||||||
|
|
||||||
result.type = ICElement.C_FIELD; // TODO Devin static for now, want something like BasicSearchResultCollector#setElementInfo
|
result.type = ICElement.C_FIELD; // TODO Devin static for now, want something like BasicSearchResultCollector#setElementInfo
|
||||||
result.visibility = ICElement.CPP_PUBLIC; // TODO Devin static for now, want something like BasicSearchResultCollector#setElementInfo
|
result.visibility = ICElement.CPP_PUBLIC; // TODO Devin static for now, want something like BasicSearchResultCollector#setElementInfo
|
||||||
|
|
|
@ -401,7 +401,7 @@ public class FindIASTNameTarget implements IFindReplaceTarget, IFindReplaceTarge
|
||||||
// get the TreeObject from the AST View's model corresponding to that name
|
// get the TreeObject from the AST View's model corresponding to that name
|
||||||
TreeObject treeNode = null;
|
TreeObject treeNode = null;
|
||||||
TreeItem treeItem = null;
|
TreeItem treeItem = null;
|
||||||
treeNode = tuTreeParent.findTreeObject(foundName, true, true);
|
treeNode = tuTreeParent.findTreeObject(foundName, true);
|
||||||
|
|
||||||
if (treeNode != null && treeNode.getParent() != null) {
|
if (treeNode != null && treeNode.getParent() != null) {
|
||||||
// found a matching TreeObject, so expand the tree to that object
|
// found a matching TreeObject, so expand the tree to that object
|
||||||
|
@ -413,7 +413,7 @@ public class FindIASTNameTarget implements IFindReplaceTarget, IFindReplaceTarge
|
||||||
((searchForward && index < matchingNames.length) ||
|
((searchForward && index < matchingNames.length) ||
|
||||||
(!searchForward && index >= 0))) {
|
(!searchForward && index >= 0))) {
|
||||||
foundName = findNextMatchingName( findString, searchForward, caseSensitive, wholeWord, regExSearch );
|
foundName = findNextMatchingName( findString, searchForward, caseSensitive, wholeWord, regExSearch );
|
||||||
treeNode = tuTreeParent.findTreeObject(foundName, true, true);
|
treeNode = tuTreeParent.findTreeObject(foundName, true);
|
||||||
|
|
||||||
if (treeNode != null && treeNode.getParent() != null) {
|
if (treeNode != null && treeNode.getParent() != null) {
|
||||||
// found a matching TreeObject, so expand the tree to that object
|
// found a matching TreeObject, so expand the tree to that object
|
||||||
|
|
|
@ -10,79 +10,101 @@
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
package org.eclipse.cdt.ui.tests.DOMAST;
|
package org.eclipse.cdt.ui.tests.DOMAST;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.Arrays;
|
||||||
import java.util.Iterator;
|
import java.util.Comparator;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
|
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
|
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author dsteffle
|
* @author dsteffle
|
||||||
*/
|
*/
|
||||||
public class TreeParent extends TreeObject {
|
public class TreeParent extends TreeObject {
|
||||||
private ArrayList children;
|
private static final TreeObject[] EMPTY_CHILDREN_ARRAY = new TreeObject[0];
|
||||||
|
private static final int DEFAULT_NODE_CHAIN_SIZE = 4;
|
||||||
|
private static final int DEFAULT_CHILDREN_SIZE = 4;
|
||||||
|
int index=0;
|
||||||
|
private TreeObject[] children;
|
||||||
|
boolean cleanupedElements = false;
|
||||||
|
|
||||||
|
public int getStartSearch() {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TreeParent() {
|
||||||
|
super(null);
|
||||||
|
children = EMPTY_CHILDREN_ARRAY;
|
||||||
|
}
|
||||||
|
|
||||||
public TreeParent(IASTNode node) {
|
public TreeParent(IASTNode node) {
|
||||||
super(node);
|
super(node);
|
||||||
children = new ArrayList();
|
children = new TreeObject[DEFAULT_CHILDREN_SIZE];
|
||||||
}
|
}
|
||||||
public void addChild(TreeObject child) {
|
public void addChild(TreeObject child) {
|
||||||
int index = 0;
|
if (index==children.length) {
|
||||||
for(int i=0; i<children.size(); i++) {
|
children = (TreeObject[])ArrayUtil.append(TreeObject.class, children, child);
|
||||||
TreeObject treeObj = (TreeObject)children.get(i);
|
index++;
|
||||||
int treeObjOffset = 0;
|
|
||||||
int childObjOffset = 0;
|
|
||||||
if( treeObj.getNode() instanceof ASTNode )
|
|
||||||
treeObjOffset = ((ASTNode)treeObj.getNode()).getOffset();
|
|
||||||
|
|
||||||
if( child.getNode() instanceof ASTNode )
|
|
||||||
childObjOffset = ((ASTNode)child.getNode()).getOffset();
|
|
||||||
|
|
||||||
if ( treeObjOffset < childObjOffset ){
|
|
||||||
index = i+1;
|
|
||||||
} else {
|
} else {
|
||||||
break;
|
children[index++] = child;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
children.add(index, child);
|
|
||||||
|
|
||||||
child.setParent(this);
|
child.setParent(this);
|
||||||
}
|
}
|
||||||
public void removeChild(TreeObject child) {
|
public void removeChild(TreeObject child) {
|
||||||
children.remove(child);
|
for(int i=0; i<children.length; i++) {
|
||||||
|
if (children[i] == child) {
|
||||||
|
children[i] = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
child.setParent(null);
|
child.setParent(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TreeObject[] getChildren(boolean cleanupElements) {
|
||||||
|
if (cleanupElements) {
|
||||||
|
return getChildren();
|
||||||
|
} else {
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public TreeObject [] getChildren() {
|
public TreeObject [] getChildren() {
|
||||||
return (TreeObject [])children.toArray(new TreeObject[children.size()]);
|
// remove null children from the array (if not already done so)
|
||||||
|
if (!cleanupedElements) {
|
||||||
|
// remove null elements
|
||||||
|
children = (TreeObject[])ArrayUtil.removeNulls(TreeObject.class, children);
|
||||||
|
|
||||||
|
// sort the elements
|
||||||
|
Arrays.sort(children, new Comparator() {
|
||||||
|
public int compare(Object a, Object b) {
|
||||||
|
if(a instanceof TreeObject && b instanceof TreeObject &&
|
||||||
|
((TreeObject)a).getNode() instanceof ASTNode &&
|
||||||
|
((TreeObject)b).getNode() instanceof ASTNode) {
|
||||||
|
return ((ASTNode)((TreeObject)a).getNode()).getOffset() - ((ASTNode)((TreeObject)b).getNode()).getOffset();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// need to also clean up the children's children, to make sure all nulls are removed (prevent expansion sign when there isn't one)
|
||||||
|
for(int i=0; i<children.length; i++) {
|
||||||
|
if (children[i] instanceof TreeParent) {
|
||||||
|
((TreeParent)children[i]).setChildren((TreeObject[])ArrayUtil.removeNulls(TreeObject.class, ((TreeParent)children[i]).getChildren()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanupedElements = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return children;
|
||||||
}
|
}
|
||||||
public boolean hasChildren() {
|
public boolean hasChildren() {
|
||||||
return children.size()>0;
|
return children.length>0;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the TreeParent whose IASTNode is the parent of the IASTNode.
|
|
||||||
*
|
|
||||||
* @param trees
|
|
||||||
* @param node
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private TreeParent findTreeParentForNode(TreeObject[] trees, IASTNode node) {
|
|
||||||
for (int i=0; i<trees.length; i++) {
|
|
||||||
|
|
||||||
if (trees[i] != null && trees[i] instanceof TreeParent) {
|
|
||||||
if ( ((TreeParent)trees[i]).getNode() == node.getParent() ) {
|
|
||||||
return (TreeParent)trees[i];
|
|
||||||
} else if ( ((TreeParent)trees[i]).hasChildren() ){
|
|
||||||
TreeParent tree = findTreeParentForNode( ((TreeParent)trees[i]).getChildren(), node );
|
|
||||||
if (tree != null) return tree;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null; // nothing found
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -94,15 +116,43 @@ public class TreeParent extends TreeObject {
|
||||||
public TreeParent findTreeParentForNode(IASTNode node) {
|
public TreeParent findTreeParentForNode(IASTNode node) {
|
||||||
if (node == null || node.getParent() == null) return null;
|
if (node == null || node.getParent() == null) return null;
|
||||||
|
|
||||||
Iterator itr = children.iterator();
|
IASTNode parentToFind = node.getParent();
|
||||||
while (itr.hasNext()) {
|
|
||||||
Object o = itr.next();
|
// first check this node before checking children
|
||||||
if (o != null && o instanceof TreeParent) {
|
if (this.getNode() == parentToFind) {
|
||||||
if ( ((TreeParent)o).getNode() == node.getParent() ) {
|
return this;
|
||||||
return (TreeParent)o;
|
}
|
||||||
} else if ( ((TreeParent)o).hasChildren() ){
|
|
||||||
TreeParent tree = findTreeParentForNode( ((TreeParent)o).getChildren(), node );
|
// build the chain of nodes... and use it to search the tree for the TreeParent that owns the node's parent
|
||||||
if (tree != null) return tree;
|
IASTNode[] nodeChain = new IASTNode[DEFAULT_NODE_CHAIN_SIZE];
|
||||||
|
IASTNode topNode = node.getParent();
|
||||||
|
ArrayUtil.append(IASTNode.class, nodeChain, node);
|
||||||
|
nodeChain = (IASTNode[])ArrayUtil.append(IASTNode.class, nodeChain, topNode);
|
||||||
|
while(topNode.getParent() != null && !(topNode.getParent() instanceof IASTTranslationUnit)) {
|
||||||
|
topNode = topNode.getParent();
|
||||||
|
nodeChain = (IASTNode[])ArrayUtil.append(IASTNode.class, nodeChain, topNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// loop through the chain of nodes and use it to only search the necessary children required to find the node
|
||||||
|
TreeObject[] childrenToSearch = children;
|
||||||
|
int j=getStartSearch();
|
||||||
|
outerLoop: for(int i=nodeChain.length-1; i>=0; i--) {
|
||||||
|
if (nodeChain[i] != null) {
|
||||||
|
parentToFind = nodeChain[i];
|
||||||
|
|
||||||
|
for(; j>=0; j--) { // use the TreeParent's index to start searching at the end of it's children (performance optimization)
|
||||||
|
if (j<childrenToSearch.length && childrenToSearch[j] instanceof TreeParent) {
|
||||||
|
if ( childrenToSearch[j].getNode() == node.getParent() ) {
|
||||||
|
return (TreeParent)childrenToSearch[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (childrenToSearch[j].getNode() == parentToFind) {
|
||||||
|
int pos = j;
|
||||||
|
j = ((TreeParent)childrenToSearch[pos]).getStartSearch();
|
||||||
|
childrenToSearch = ((TreeParent)childrenToSearch[pos]).getChildren(false);
|
||||||
|
continue outerLoop;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,30 +170,6 @@ public class TreeParent extends TreeObject {
|
||||||
return null; // nothing found
|
return null; // nothing found
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the TreeParent that corresponds to the IASTNode. This is the TreeParent
|
|
||||||
* that represents the IASTNode in the DOM AST View.
|
|
||||||
*
|
|
||||||
* @param trees
|
|
||||||
* @param node
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private TreeParent findTreeObject(TreeObject[] trees, IASTNode node, boolean useOffset, boolean useName) {
|
|
||||||
for (int i=0; i<trees.length; i++) {
|
|
||||||
|
|
||||||
if (trees[i] != null && trees[i] instanceof TreeParent) {
|
|
||||||
if ( equalNodes( ((TreeParent)trees[i]).getNode(), node, useOffset, useName ) ) {
|
|
||||||
return (TreeParent)trees[i];
|
|
||||||
} else if ( ((TreeParent)trees[i]).hasChildren() ){
|
|
||||||
TreeParent tree = findTreeObject( ((TreeParent)trees[i]).getChildren(), node, useOffset, useName );
|
|
||||||
if (tree != null) return tree;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null; // nothing found
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the TreeParent that corresponds to the IASTNode. This is the TreeParent
|
* Returns the TreeParent that corresponds to the IASTNode. This is the TreeParent
|
||||||
* that represents the IASTNode in the DOM AST View.
|
* that represents the IASTNode in the DOM AST View.
|
||||||
|
@ -152,32 +178,50 @@ public class TreeParent extends TreeObject {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public TreeParent findTreeObject(IASTNode node, boolean useOffset) {
|
public TreeParent findTreeObject(IASTNode node, boolean useOffset) {
|
||||||
return findTreeObject(node, useOffset, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the TreeParent that corresponds to the IASTNode. This is the TreeParent
|
|
||||||
* that represents the IASTNode in the DOM AST View.
|
|
||||||
*
|
|
||||||
* @param node
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public TreeParent findTreeObject(IASTNode node, boolean useOffset, boolean useName) {
|
|
||||||
if (node == null) return null;
|
if (node == null) return null;
|
||||||
|
|
||||||
Iterator itr = children.iterator();
|
IASTNode nodeToFind = node;
|
||||||
while (itr.hasNext()) {
|
|
||||||
Object o = itr.next();
|
|
||||||
if (o != null && o instanceof TreeParent) {
|
|
||||||
IASTNode treeNode = ((TreeParent)o).getNode();
|
|
||||||
|
|
||||||
if (equalNodes(node, ((TreeParent)o).getNode(), useOffset, useName))
|
// first check this node before checking children
|
||||||
return (TreeParent)o;
|
if (equalNodes(node, this.getNode(), useOffset)) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
// search the children
|
// build the chain of nodes... and use it to search the tree for the TreeParent that contains the node
|
||||||
if ( ((TreeParent)o).hasChildren() ){
|
IASTNode[] nodeChain = new IASTNode[DEFAULT_NODE_CHAIN_SIZE];
|
||||||
TreeParent tree = findTreeObject( ((TreeParent)o).getChildren(), node, useOffset, useName );
|
IASTNode topNode = node;
|
||||||
if (tree != null) return tree;
|
nodeChain = (IASTNode[])ArrayUtil.append(IASTNode.class, nodeChain, topNode);
|
||||||
|
while(topNode.getParent() != null && !(topNode.getParent() instanceof IASTTranslationUnit)) {
|
||||||
|
topNode = topNode.getParent();
|
||||||
|
nodeChain = (IASTNode[])ArrayUtil.append(IASTNode.class, nodeChain, topNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// loop through the chain of nodes and use it to only search the necessary children required to find the node
|
||||||
|
TreeObject[] childrenToSearch = children;
|
||||||
|
outerLoop: for(int i=nodeChain.length-1; i>=0; i--) {
|
||||||
|
if (nodeChain[i] != null) {
|
||||||
|
nodeToFind = nodeChain[i];
|
||||||
|
|
||||||
|
for(int j=0; j<childrenToSearch.length; j++) {
|
||||||
|
if (childrenToSearch[j] instanceof TreeParent) {
|
||||||
|
|
||||||
|
if ( equalNodes(childrenToSearch[j].getNode(), node, useOffset) ) {
|
||||||
|
return (TreeParent)childrenToSearch[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( equalNodes(childrenToSearch[j].getNode(), nodeToFind, useOffset) ) {
|
||||||
|
childrenToSearch = ((TreeParent)childrenToSearch[j]).getChildren(false);
|
||||||
|
continue outerLoop;
|
||||||
|
}
|
||||||
|
|
||||||
|
// since the nodeChain doesn't include #includes, if an #include is encountered then search it's children
|
||||||
|
if (childrenToSearch[j].getNode() instanceof IASTPreprocessorIncludeStatement) {
|
||||||
|
TreeParent foundParentInInclude = ((TreeParent)childrenToSearch[j]).findTreeObject(node, useOffset);
|
||||||
|
if(foundParentInInclude != null) {
|
||||||
|
return foundParentInInclude;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -185,16 +229,16 @@ public class TreeParent extends TreeObject {
|
||||||
return null; // nothing found
|
return null; // nothing found
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean equalNodes(IASTNode node1, IASTNode node2, boolean useOffset, boolean useName) {
|
private boolean equalNodes(IASTNode node1, IASTNode node2, boolean useOffset) {
|
||||||
if (useName &&
|
|
||||||
(!(node1 instanceof IASTName) || !(node2 instanceof IASTName) ||
|
|
||||||
!(((IASTName)node1).toString().equals(((IASTName)node2).toString())))) return false;
|
|
||||||
|
|
||||||
if (useOffset) {
|
if (useOffset) {
|
||||||
if (node1 instanceof ASTNode && node2 instanceof ASTNode) {
|
if (node1 instanceof ASTNode && node2 instanceof ASTNode) {
|
||||||
if (((ASTNode)node1).getOffset() == ((ASTNode)node2).getOffset() &&
|
if (((ASTNode)node1).getOffset() == ((ASTNode)node2).getOffset() &&
|
||||||
((ASTNode)node1).getLength() == ((ASTNode)node2).getLength())
|
((ASTNode)node1).getLength() == ((ASTNode)node2).getLength()) {
|
||||||
|
if (node1.getClass().equals(node2.getClass()))
|
||||||
return true;
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
IASTNodeLocation[] locs1 = node1.getNodeLocations();
|
IASTNodeLocation[] locs1 = node1.getNodeLocations();
|
||||||
IASTNodeLocation[] locs2 = node2.getNodeLocations();
|
IASTNodeLocation[] locs2 = node2.getNodeLocations();
|
||||||
|
@ -204,7 +248,10 @@ public class TreeParent extends TreeObject {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node1.getClass().equals(node2.getClass()))
|
||||||
return true;
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ( node1 == node2 )
|
if ( node1 == node2 )
|
||||||
|
@ -214,4 +261,8 @@ public class TreeParent extends TreeObject {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setChildren(TreeObject[] children) {
|
||||||
|
this.children = children;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Add table
Reference in a new issue