1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-11 10:15:39 +02:00

Patch for Devin Steffler.

IASTTranslationUnit#getNodeForLocation()
Selection in DOM AST View.
This commit is contained in:
John Camelon 2005-02-23 17:21:40 +00:00
parent 7945749d49
commit 511c556400
14 changed files with 959 additions and 195 deletions

View file

@ -61,9 +61,7 @@ public interface IASTTranslationUnit extends IASTNode {
public IASTNodeLocation[] getLocationInfo(int offset, int length);
public IASTNode[] selectNodesForLocation(String path, int offset, int length);
public IASTNode[] selectNodesForLocation(int offset, int length);
public IASTNode selectNodeForLocation(String path, int offset, int length);
public IASTPreprocessorMacroDefinition[] getMacroDefinitions();

View file

@ -11,20 +11,34 @@ package org.eclipse.cdt.internal.core.dom.parser.c;
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTArrayModifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
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.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
import org.eclipse.cdt.core.dom.ast.IASTProblem;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IASTVisitor;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.c.ICASTDesignator;
import org.eclipse.cdt.core.parser.ast.IASTEnumerator;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.IRequiresLocationInformation;
import org.eclipse.cdt.internal.core.parser.scanner2.ILocationResolver;
import org.eclipse.cdt.internal.core.parser.scanner2.InvalidPreprocessorNodeException;
/**
* @author jcamelon
@ -126,13 +140,172 @@ public class CASTTranslationUnit extends CASTNode implements IASTTranslationUnit
return resolver.getLocations(offset,length);
}
private class CFindNodeForOffsetAction extends CVisitor.CBaseVisitorAction {
{
processNames = true;
processDeclarations = true;
processInitializers = true;
processParameterDeclarations = true;
processDeclarators = true;
processDeclSpecifiers = true;
processDesignators = true;
processExpressions = true;
processStatements = true;
processTypeIds = true;
processEnumerators = true;
}
IASTNode foundNode = null;
int offset = 0;
int length = 0;
/**
*
*/
public CFindNodeForOffsetAction(int offset, int length) {
this.offset = offset;
this.length = length;
}
public int processNode(IASTNode node) {
if (foundNode != null)
return PROCESS_ABORT;
if (node instanceof ASTNode &&
((ASTNode)node).getOffset() == offset &&
((ASTNode)node).getLength() == length) {
foundNode = node;
return PROCESS_ABORT;
}
// skip the rest of this node if the selection is outside of its bounds
if (node instanceof ASTNode &&
offset > ((ASTNode)node).getOffset() + ((ASTNode)node).getLength())
return PROCESS_SKIP;
return PROCESS_CONTINUE;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.cpp.CPPVisitor.CPPBaseVisitorAction#processDeclaration(org.eclipse.cdt.core.dom.ast.IASTDeclaration)
*/
public int processDeclaration(IASTDeclaration declaration) {
// use declarations to determine if the search has gone past the offset (i.e. don't know the order the visitor visits the nodes)
if (declaration instanceof ASTNode && ((ASTNode)declaration).getOffset() > offset)
return PROCESS_ABORT;
return processNode(declaration);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.cpp.CPPVisitor.CPPBaseVisitorAction#processDeclarator(org.eclipse.cdt.core.dom.ast.IASTDeclarator)
*/
public int processDeclarator(IASTDeclarator declarator) {
int ret = processNode(declarator);
IASTPointerOperator[] ops = declarator.getPointerOperators();
for(int i=0; i<ops.length; i++)
processNode(ops[i]);
if (declarator instanceof IASTArrayDeclarator) {
IASTArrayModifier[] mods = ((IASTArrayDeclarator)declarator).getArrayModifiers();
for(int i=0; i<mods.length; i++)
processNode(mods[i]);
}
return ret;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processDesignator(org.eclipse.cdt.core.dom.ast.c.ICASTDesignator)
*/
public int processDesignator(ICASTDesignator designator) {
return processNode(designator);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processDeclSpecifier(org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier)
*/
public int processDeclSpecifier(IASTDeclSpecifier declSpec) {
return processNode(declSpec);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processEnumerator(org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator)
*/
public int processEnumerator(IASTEnumerator enumerator) {
return processNode((IASTNode)enumerator);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processExpression(org.eclipse.cdt.core.dom.ast.IASTExpression)
*/
public int processExpression(IASTExpression expression) {
return processNode(expression);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processInitializer(org.eclipse.cdt.core.dom.ast.IASTInitializer)
*/
public int processInitializer(IASTInitializer initializer) {
return processNode(initializer);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processName(org.eclipse.cdt.core.dom.ast.IASTName)
*/
public int processName(IASTName name) {
if ( name.toString() != null )
return processNode(name);
return PROCESS_CONTINUE;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processParameterDeclaration(org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration)
*/
public int processParameterDeclaration(
IASTParameterDeclaration parameterDeclaration) {
return processNode(parameterDeclaration);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processStatement(org.eclipse.cdt.core.dom.ast.IASTStatement)
*/
public int processStatement(IASTStatement statement) {
return processNode(statement);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processTypeId(org.eclipse.cdt.core.dom.ast.IASTTypeId)
*/
public int processTypeId(IASTTypeId typeId) {
return processNode(typeId);
}
public IASTNode getNode() {
return foundNode;
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IASTTranslationUnit#getNodeForLocation(org.eclipse.cdt.core.dom.ast.IASTNodeLocation)
*/
public IASTNode[] selectNodesForLocation(String path, int offset, int length) {
// TODO Auto-generated method stub
return null;
public IASTNode selectNodeForLocation(String path, int realOffset, int realLength) {
IASTNode node = null;
try {
node = resolver.getPreprocessorNode(path, realOffset, realLength);
} catch (InvalidPreprocessorNodeException ipne) {
// extract global offset from the exception, use it to get the node from the AST if it's valid
int globalOffset = ipne.getGlobalOffset();
if (globalOffset >= 0) {
CFindNodeForOffsetAction nodeFinder = new CFindNodeForOffsetAction(globalOffset, realLength);
getVisitor().visitTranslationUnit(nodeFinder);
node = nodeFinder.getNode();
}
}
return node;
}
@ -189,13 +362,6 @@ public class CASTTranslationUnit extends CASTNode implements IASTTranslationUnit
this.resolver = resolver;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IASTTranslationUnit#selectNodesForLocation(int, int)
*/
public IASTNode[] selectNodesForLocation(int offset, int length) {
return selectNodesForLocation( "", offset, length ); //$NON-NLS-1$
}
/* (non-Javadoc)
* @see java.lang.Object#finalize()

View file

@ -11,24 +11,42 @@
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTArrayModifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
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.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
import org.eclipse.cdt.core.dom.ast.IASTProblem;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IASTVisitor;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.c.ICASTDesignator;
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.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionTryBlockDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisitor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope;
import org.eclipse.cdt.core.parser.ast.IASTEnumerator;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.IRequiresLocationInformation;
import org.eclipse.cdt.internal.core.parser.scanner2.ILocationResolver;
import org.eclipse.cdt.internal.core.parser.scanner2.InvalidPreprocessorNodeException;
/**
* @author jcamelon
@ -146,13 +164,189 @@ public class CPPASTTranslationUnit extends CPPASTNode implements
return resolver.getLocations(offset, length);
}
private class CPPFindNodeForOffsetAction extends CPPVisitor.CPPBaseVisitorAction {
{
processNames = true;
processDeclarations = true;
processInitializers = true;
processParameterDeclarations = true;
processDeclarators = true;
processDeclSpecifiers = true;
processExpressions = true;
processStatements = true;
processTypeIds = true;
processEnumerators = true;
processBaseSpecifiers = true;
processNamespaces = true;
}
IASTNode foundNode = null;
int offset = 0;
int length = 0;
/**
*
*/
public CPPFindNodeForOffsetAction(int offset, int length) {
this.offset = offset;
this.length = length;
}
public int processNode(IASTNode node) {
if (foundNode != null)
return PROCESS_ABORT;
if (node instanceof ASTNode &&
((ASTNode)node).getOffset() == offset &&
((ASTNode)node).getLength() == length) {
foundNode = node;
return PROCESS_ABORT;
}
// skip the rest of this node if the selection is outside of its bounds
if (node instanceof ASTNode &&
offset > ((ASTNode)node).getOffset() + ((ASTNode)node).getLength())
return PROCESS_SKIP;
return PROCESS_CONTINUE;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.cpp.CPPVisitor.CPPBaseVisitorAction#processDeclaration(org.eclipse.cdt.core.dom.ast.IASTDeclaration)
*/
public int processDeclaration(IASTDeclaration declaration) {
// use declarations to determine if the search has gone past the offset (i.e. don't know the order the visitor visits the nodes)
if (declaration instanceof ASTNode && ((ASTNode)declaration).getOffset() > offset)
return PROCESS_ABORT;
return processNode(declaration);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.cpp.CPPVisitor.CPPBaseVisitorAction#processDeclarator(org.eclipse.cdt.core.dom.ast.IASTDeclarator)
*/
public int processDeclarator(IASTDeclarator declarator) {
int ret = processNode(declarator);
IASTPointerOperator[] ops = declarator.getPointerOperators();
for(int i=0; i<ops.length; i++)
processNode(ops[i]);
if (declarator instanceof IASTArrayDeclarator) {
IASTArrayModifier[] mods = ((IASTArrayDeclarator)declarator).getArrayModifiers();
for(int i=0; i<mods.length; i++)
processNode(mods[i]);
}
if (declarator instanceof ICPPASTFunctionDeclarator) {
ICPPASTConstructorChainInitializer[] chainInit = ((ICPPASTFunctionDeclarator)declarator).getConstructorChain();
for(int i=0; i<chainInit.length; i++) {
processNode(chainInit[i]);
}
if( declarator instanceof ICPPASTFunctionTryBlockDeclarator ){
ICPPASTCatchHandler [] catchHandlers = ((ICPPASTFunctionTryBlockDeclarator)declarator).getCatchHandlers();
for( int i = 0; i < catchHandlers.length; i++ ){
processNode(catchHandlers[i]);
}
}
}
return ret;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processDesignator(org.eclipse.cdt.core.dom.ast.c.ICASTDesignator)
*/
public int processDesignator(ICASTDesignator designator) {
return processNode(designator);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processDeclSpecifier(org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier)
*/
public int processDeclSpecifier(IASTDeclSpecifier declSpec) {
return processNode(declSpec);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processEnumerator(org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator)
*/
public int processEnumerator(IASTEnumerator enumerator) {
return processNode((IASTNode)enumerator);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processExpression(org.eclipse.cdt.core.dom.ast.IASTExpression)
*/
public int processExpression(IASTExpression expression) {
return processNode(expression);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processInitializer(org.eclipse.cdt.core.dom.ast.IASTInitializer)
*/
public int processInitializer(IASTInitializer initializer) {
return processNode(initializer);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processName(org.eclipse.cdt.core.dom.ast.IASTName)
*/
public int processName(IASTName name) {
if ( name.toString() != null )
return processNode(name);
return PROCESS_CONTINUE;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processParameterDeclaration(org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration)
*/
public int processParameterDeclaration(
IASTParameterDeclaration parameterDeclaration) {
return processNode(parameterDeclaration);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processStatement(org.eclipse.cdt.core.dom.ast.IASTStatement)
*/
public int processStatement(IASTStatement statement) {
return processNode(statement);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processTypeId(org.eclipse.cdt.core.dom.ast.IASTTypeId)
*/
public int processTypeId(IASTTypeId typeId) {
return processNode(typeId);
}
public IASTNode getNode() {
return foundNode;
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.core.dom.ast.IASTTranslationUnit#getNodeForLocation(org.eclipse.cdt.core.dom.ast.IASTNodeLocation)
*/
public IASTNode[] selectNodesForLocation(String path, int offset, int length) {
return null;
public IASTNode selectNodeForLocation(String path, int realOffset, int realLength) {
IASTNode node = null;
try {
node = resolver.getPreprocessorNode(path, realOffset, realLength);
} catch (InvalidPreprocessorNodeException ipne) {
// extract global offset from the exception, use it to get the node from the AST if it's valid
int globalOffset = ipne.getGlobalOffset();
if (globalOffset >= 0) {
CPPFindNodeForOffsetAction nodeFinder = new CPPFindNodeForOffsetAction(globalOffset, realLength);
getVisitor().visitTranslationUnit(nodeFinder);
node = nodeFinder.getNode();
}
}
return node;
}
/*
@ -213,19 +407,6 @@ public class CPPASTTranslationUnit extends CPPASTNode implements
this.resolver = resolver;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.core.dom.ast.IASTTranslationUnit#selectNodesForLocation(int,
* int)
*/
public IASTNode[] selectNodesForLocation(int offset, int length) {
if (resolver == null)
return EMPTY_NODE_ARRAY;
return selectNodesForLocation(resolver.getTranslationUnitPath(),
offset, length); //$NON-NLS-1$
}
/*
* (non-Javadoc)
*

View file

@ -10,6 +10,7 @@
**********************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner2;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
@ -26,7 +27,6 @@ public interface ILocationResolver {
public IASTPreprocessorStatement [] getAllPreprocessorStatements();
public IASTNodeLocation [] getLocations( int offset, int length );
public IASTNodeLocation getLocation( int offset );
public char [] getUnpreprocessedSignature( IASTNodeLocation [] locations );
@ -35,5 +35,7 @@ public interface ILocationResolver {
public String getTranslationUnitPath();
public void cleanup();
public IASTNode getPreprocessorNode( String path, int offset, int length ) throws InvalidPreprocessorNodeException;
}

View file

@ -0,0 +1,36 @@
/**********************************************************************
* Copyright (c) 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
**********************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner2;
/**
* @author dsteffle
*/
public class InvalidPreprocessorNodeException extends Exception {
public InvalidPreprocessorNodeException(String message) {
super(message);
}
public InvalidPreprocessorNodeException(String message, int offset) {
super(message);
globalOffset = offset;
}
private int globalOffset = -1;
public int getGlobalOffset() {
return globalOffset;
}
public void setGlobalOffset(int offset) {
globalOffset = offset;
}
}

View file

@ -46,7 +46,9 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
*/
public class LocationMap implements ILocationResolver, IScannerPreprocessorLog {
/**
private static final String NOT_VALID_MACRO = "Not a valid macro selection"; //$NON-NLS-1$
private static final String TU_INCLUDE_NOT_FOUND = "File searching does not match TU or #includes."; //$NON-NLS-1$
/**
* @author jcamelon
*/
static class ASTEndif extends ScannerASTNode implements
@ -1024,32 +1026,39 @@ public class LocationMap implements ILocationResolver, IScannerPreprocessorLog {
collectContexts(V_PREPROCESSOR, tu, contexts, 0);
IASTPreprocessorStatement[] result = new IASTPreprocessorStatement[size];
for (int i = 0; i < size; ++i) {
if (contexts[i] instanceof _Inclusion)
result[i] = createASTInclusion(((_Inclusion) contexts[i]));
else if (contexts[i] instanceof _MacroDefinition)
result[i] = createASTMacroDefinition((_MacroDefinition) contexts[i]);
else if (contexts[i] instanceof _Undef)
result[i] = createASTUndef((_Undef) contexts[i]);
else if (contexts[i] instanceof _Pragma)
result[i] = createASTPragma((_Pragma) contexts[i]);
else if (contexts[i] instanceof _Error)
result[i] = createASTError((_Error) contexts[i]);
else if (contexts[i] instanceof _If)
result[i] = createASTIf((_If) contexts[i]);
else if (contexts[i] instanceof _Ifdef)
result[i] = createASTIfdef((_Ifdef) contexts[i]);
else if (contexts[i] instanceof _Ifndef)
result[i] = createASTIfndef((_Ifndef) contexts[i]);
else if (contexts[i] instanceof _Else)
result[i] = createASTElse((_Else) contexts[i]);
else if (contexts[i] instanceof _Elif)
result[i] = createASTElif((_Elif) contexts[i]);
else if (contexts[i] instanceof _Endif)
result[i] = createASTEndif((_Endif) contexts[i]);
result[i] = createPreprocessorStatement(contexts[i]);
}
return result;
}
private IASTPreprocessorStatement createPreprocessorStatement(_Context context) {
IASTPreprocessorStatement result = null;
if (context instanceof _Inclusion)
result = createASTInclusion(((_Inclusion) context));
else if (context instanceof _MacroDefinition)
result = createASTMacroDefinition((_MacroDefinition) context);
else if (context instanceof _Undef)
result = createASTUndef((_Undef) context);
else if (context instanceof _Pragma)
result = createASTPragma((_Pragma) context);
else if (context instanceof _Error)
result = createASTError((_Error) context);
else if (context instanceof _If)
result = createASTIf((_If) context);
else if (context instanceof _Ifdef)
result = createASTIfdef((_Ifdef) context);
else if (context instanceof _Ifndef)
result = createASTIfndef((_Ifndef) context);
else if (context instanceof _Else)
result = createASTElse((_Else) context);
else if (context instanceof _Elif)
result = createASTElif((_Elif) context);
else if (context instanceof _Endif)
result = createASTEndif((_Endif) context);
return result;
}
/**
* @param endif
@ -1280,16 +1289,6 @@ public class LocationMap implements ILocationResolver, IScannerPreprocessorLog {
return bestContext;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.internal.core.parser.scanner2.ILocationResolver#getLocation(int)
*/
public IASTNodeLocation getLocation(int offset) {
// TODO Auto-generated method stub
return null;
}
/*
* (non-Javadoc)
*
@ -1693,5 +1692,94 @@ public class LocationMap implements ILocationResolver, IScannerPreprocessorLog {
currentContext.addSubContext(new _Ifndef(currentContext, startOffset,
endOffset, taken));
}
private _Context findInclusion(_CompositeContext context, String path) {
_Context foundContext = null;
List contexts = context.getSubContexts();
for (int i=0; foundContext == null && i<contexts.size(); i++) {
if (contexts.get(i) instanceof _Inclusion) {
context = (_Inclusion)contexts.get(i);
// check if the file matches the #include
if (CharArrayUtils.equals(((_Inclusion)context).reader.filename, path.toCharArray())) {
foundContext = context;
} else {
foundContext = findInclusion(context, path);
}
}
}
return foundContext;
}
private IASTNode getPreprocessorNode(int globalOffset, int length, _Context startContext) throws InvalidPreprocessorNodeException {
IASTNode result = null;
if (!(startContext instanceof _CompositeContext)) throw new InvalidPreprocessorNodeException(NOT_VALID_MACRO, globalOffset);
List contexts = ((_CompositeContext)startContext).getSubContexts();
// check if a macro in the location map is the selection
for (int i=0; result == null && i<contexts.size(); i++) {
if (contexts.get(i) instanceof _Context) {
_Context context = (_Context)contexts.get(i);
// if offset is past the _Context then increment globalOffset
if (globalOffset > context.context_directive_end) {
globalOffset += context.context_ends - context.context_directive_end;
}
// check if the _Context is the selection
if (globalOffset == context.context_directive_start &&
length == context.context_directive_end - context.context_directive_start) {
result = createPreprocessorStatement(context);
}
// check if a sub node of the macro is the selection // TODO determine how this can be kept in sync with logic in getAllPreprocessorStatements (i.e. 1:1 mapping)
if (context instanceof _MacroDefinition) {
if (globalOffset == ((_MacroDefinition)context).nameOffset
&& length == ((_MacroDefinition)context).name.length)
result = createASTMacroDefinition((_MacroDefinition)context).getName();
}
// stop searching the _Contexts if they've gone past the selection
if (globalOffset < context.context_directive_end)
break;
}
}
if (result == null)
throw new InvalidPreprocessorNodeException(NOT_VALID_MACRO, globalOffset);
return result;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.parser.scanner2.ILocationResolver#getPreprocessorNode(int, int)
*/
public IASTNode getPreprocessorNode(String path, int offset, int length) throws InvalidPreprocessorNodeException {
IASTNode result = null;
int globalOffset = 0;
_Context foundContext = tu;
// is the selection in TU or an #include else it's an exception
if (CharArrayUtils.equals(tu.reader.filename, path.toCharArray())) {
globalOffset = offset; // in TU so start at the real offset
} else {
foundContext = findInclusion(tu, path);
if (foundContext == null) {
throw new InvalidPreprocessorNodeException(TU_INCLUDE_NOT_FOUND, globalOffset);
} else if (foundContext instanceof _Inclusion){
globalOffset = foundContext.context_directive_end + offset; // start at #include's directive_end + real offset
}
}
result = getPreprocessorNode(globalOffset, length, foundContext);
if (result == null)
throw new InvalidPreprocessorNodeException(NOT_VALID_MACRO, globalOffset);
return result;
}
}

View file

@ -92,6 +92,15 @@
</or>
</visibility>
</viewerContribution>
<viewerContribution
targetID="#CEditorContext"
id="org.eclipse.cdt.ui.tests.cEditorContribution">
<action
label="Show IASTNode in DOM View"
class="org.eclipse.cdt.ui.tests.DOMAST.ShowInDOMViewAction"
menubarPath="additions"
id="org.eclipse.cdt.ui.tests.DOMAST.ShowInDOMViewAction1"/>
</viewerContribution>
</extension>
<extension
point="org.eclipse.cdt.ui.CElementFilters">

View file

@ -263,7 +263,7 @@ public class CPPPopulateASTViewAction extends CPPBaseVisitorAction implements IP
TreeParent[] treeIncludes = new TreeParent[includes.length];
for (int i=0; i<treeIncludes.length; i++) {
if (monitor != null && monitor.isCanceled()) return;
treeIncludes[i] = root.findTreeObject(includes[i]);
treeIncludes[i] = root.findTreeObject(includes[i], false);
}
// loop through the includes and make sure that all of the nodes

View file

@ -236,7 +236,7 @@ public class CPopulateASTViewAction extends CBaseVisitorAction implements IPopul
TreeParent[] treeIncludes = new TreeParent[includes.length];
for (int i=0; i<treeIncludes.length; i++) {
if (monitor != null && monitor.isCanceled()) return;
treeIncludes[i] = root.findTreeObject(includes[i]);
treeIncludes[i] = root.findTreeObject(includes[i], false);
}
// loop through the includes and make sure that all of the nodes

View file

@ -67,6 +67,7 @@ import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
@ -83,6 +84,7 @@ import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IActionBars;
@ -90,41 +92,32 @@ import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.DrillDownAdapter;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.progress.WorkbenchJob;
/**
* This sample class demonstrates how to plug-in a new workbench view. The view
* shows data obtained from the model. The sample creates a dummy model on the
* fly, but a real implementation would connect to the model available either in
* this or another plug-in (e.g. the workspace). The view is connected to the
* model using a content provider.
* <p>
* The view uses a label provider to define how model objects should be
* presented in the view. Each view can present the same model objects using
* different labels and icons, if needed. Alternatively, a single label provider
* can be shared between views in order to ensure that objects of the same type
* are presented in the same way everywhere.
* <p>
* This is a simple DOM AST View used for development testing.
*/
public class DOMAST extends ViewPart {
private static final String DOM_AST_HAS_NO_CONTENT = "DOM AST has no content"; //$NON-NLS-1$
private static final String SEARCH_FOR_IASTNAME = "Search for IASTName"; //$NON-NLS-1$
private static final String CLEAR = "Clear"; //$NON-NLS-1$
private static final String DOMAST_FILTER_GROUP_ID = "org.eclipse.cdt.ui.tests.DOMAST.DOMASTFilterGroup"; //$NON-NLS-1$
private static final String NOT_VALID_COMPILATION_UNIT = "The active editor does not contain a valid compilation unit."; //$NON-NLS-1$
private static final String EXTENSION_CXX = "CXX"; //$NON-NLS-1$
private static final String EXTENSION_CPP = "CPP"; //$NON-NLS-1$
private static final String EXTENSION_CC = "CC"; //$NON-NLS-1$
private static final String EXTENSION_C = "C"; //$NON-NLS-1$
private static final String NOT_VALID_COMPILATION_UNIT = "The active editor does not contain a valid compilation unit."; //$NON-NLS-1$
private static final String DOM_AST_HAS_NO_CONTENT = "DOM AST has no content"; //$NON-NLS-1$
private static final String SEARCH_FOR_IASTNAME = "Search for IASTName"; //$NON-NLS-1$
private static final String CLEAR = "Clear"; //$NON-NLS-1$
private static final String DOMAST_FILTER_GROUP_ID = "org.eclipse.cdt.ui.tests.DOMAST.DOMASTFilterGroup"; //$NON-NLS-1$
private static final String LOAD_ACTIVE_EDITOR = "Load Active Editor"; //$NON-NLS-1$
private static final String COLLAPSE_ALL = "Collapse ALL"; //$NON-NLS-1$
private static final String EXPAND_ALL = "Expand All"; //$NON-NLS-1$
private static final String REFRESH_DOM_AST = "Refresh DOM AST"; //$NON-NLS-1$
private static final String VIEW_NAME = "DOM View"; //$NON-NLS-1$
public static final String VIEW_NAME = "DOM View"; //$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_REFERENCES = "Open References"; //$NON-NLS-1$
@ -144,6 +137,8 @@ public class DOMAST extends ViewPart {
private ParserLanguage lang = null;
private CustomFiltersActionGroup customFiltersActionGroup;
private static ViewContentProvider.StartInitializingASTView initializeASTViewJob = null;
/*
* The content provider class is responsible for providing objects to the
@ -167,8 +162,8 @@ public class DOMAST extends ViewPart {
}
public ViewContentProvider(IFile file, Object[] expanded) {
StartInitializingASTView job = new StartInitializingASTView(new InitializeView(POPULATING_AST_VIEW, this, viewer, file), expanded);
job.schedule();
initializeASTViewJob = new StartInitializingASTView(new InitializeView(POPULATING_AST_VIEW, this, viewer, file), expanded);
initializeASTViewJob.schedule();
}
@ -177,6 +172,7 @@ public class DOMAST extends ViewPart {
for(int i=0; i<invisibleRoot.getChildren().length; i++) {
if (invisibleRoot.getChildren()[i] instanceof TreeParent && invisibleRoot.getChildren()[i].getNode() instanceof IASTTranslationUnit){
tuTreeParent = (TreeParent)invisibleRoot.getChildren()[i];
return tuTreeParent;
}
}
}
@ -452,6 +448,72 @@ public class DOMAST extends ViewPart {
*/
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
private TreeItem expandTreeToTreeObject(TreeItem[] treeItems, TreeObject treeObj) {
for (int i=0; i<treeItems.length; i++) {
if (treeItems[i].getData() == treeObj) {
return treeItems[i];
}
TreeParent parent = treeObj.getParent();
if (parent == null) return null;
while (parent != treeItems[i].getData()) {
parent = parent.getParent();
if (parent == null) break;
}
if (parent == treeItems[i].getData()) {
treeItems[i].setExpanded(true);
viewer.refresh();
return expandTreeToTreeObject(treeItems[i].getItems(), treeObj);
}
}
return null; // nothing found
}
private TreeItem expandTreeToTreeObject(TreeObject treeObj) {
return expandTreeToTreeObject(viewer.getTree().getItems(), treeObj);
}
/**
* Find an ASTNode in the tree and expand the tree to that node.
* Returns true if successful, false otherwise.
*
* @param offset
* @param findString
* @param searchForward
* @param caseSensitive
* @param wholeWord
* @param regExSearch
* @return
*/
public boolean findAndSelect(IASTNode node, boolean useOffset) {
// get the TreeObject from the AST View's model corresponding to the IASTNode
TreeObject treeNode = null;
TreeItem treeItem = null;
treeNode = getTUTreeParent().findTreeObject(node, useOffset);
if (treeNode != null && treeNode.getParent() != null) {
// found a matching TreeObject, so expand the tree to that object
treeItem = expandTreeToTreeObject(treeNode);
}
// select the node that was found (and is now displayed)
if (treeItem != null) {
TreeItem[] items = new TreeItem[1];
items[0] = treeItem;
treeItem.getParent().setSelection(items);
return true;
}
return false;
}
}
class ViewLabelProvider extends LabelProvider {
@ -559,7 +621,10 @@ public class DOMAST extends ViewPart {
public void setContentProvider(ViewContentProvider vcp) {
viewer.setContentProvider(vcp);
}
public IContentProvider getContentProvider() {
return viewer.getContentProvider();
}
private void hookContextMenu() {
@ -628,35 +693,7 @@ public class DOMAST extends ViewPart {
private void makeActions() {
loadActiveEditorAction = new Action() {
public void run() {
// get the active editor
IEditorPart editor = getActiveEditor();
if (editor instanceof CEditor) {
IViewPart tempView = null;
try {
tempView = getSite().getPage().showView(OpenDOMViewAction.VIEW_ID);
} catch (PartInitException pie) {}
if (tempView != null) {
if (tempView instanceof DOMAST) {
IFile aFile = ((CEditor)editor).getInputFile();
// check if the file is a valid "compilation unit" (based on file extension)
String ext = aFile.getFileExtension().toUpperCase();
if (!(ext.equals(EXTENSION_C) || ext.equals(EXTENSION_CC) || ext.equals(EXTENSION_CPP) || ext.equals(EXTENSION_CXX))) {
showMessage(NOT_VALID_COMPILATION_UNIT);
return;
}
((DOMAST)tempView).setFile(aFile);
((DOMAST)tempView).setPart(editor);
((DOMAST)tempView).setLang(getLanguageFromFile(aFile));
((DOMAST)tempView).setContentProvider(((DOMAST)tempView).new ViewContentProvider(((CEditor)editor).getInputFile()));
}
}
getSite().getPage().activate(tempView);
}
openDOMASTView(getActiveEditor());
}
};
loadActiveEditorAction.setText(LOAD_ACTIVE_EDITOR);
@ -747,18 +784,7 @@ public class DOMAST extends ViewPart {
return editor;
}
private ParserLanguage getLanguageFromFile(IFile file) {
IProject project = file.getProject();
ICFileType type = CCorePlugin.getDefault().getFileType(project, file.getFullPath().lastSegment());
String lid = type.getLanguage().getId();
if ( lid != null && lid.equals(ICFileTypeConstants.LANG_CXX) ) {
return ParserLanguage.CPP;
}
return ParserLanguage.C;
}
private class ASTHighlighterAction extends Action {
IEditorPart aPart = null;
@ -913,4 +939,105 @@ public class DOMAST extends ViewPart {
this.file = file;
}
private class RunAfterViewOpenJob extends Job {
Runnable runner = null;
/**
*
*/
public RunAfterViewOpenJob(String name, Runnable runner) {
super(name);
this.runner = runner;
}
/* (non-Javadoc)
* @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
*/
protected IStatus run(IProgressMonitor monitor) {
try {
initializeASTViewJob.join();
CTestPlugin.getStandardDisplay().asyncExec(runner);
} catch (InterruptedException ie) {}
return Status.OK_STATUS;
}
}
/**
* Open the DOM AST View and return a reference to it. This helper method can also be used to run an
* Action after the DOM AST View has been fully loaded (like find/select nodes in the view).
*
* Note: The action is not guaranteed to run. An example would be if loading the view is canceled.
*
* @param editor
* @param action
* @return
*/
public static IViewPart openDOMASTViewRunAction(IEditorPart editor, Runnable runnable, String nameOfJob) {
IViewPart view = openDOMASTView(editor);
if (view == null) return null;
RunAfterViewOpenJob job = ((DOMAST)view).new RunAfterViewOpenJob(nameOfJob, runnable);
job.schedule();
return view;
}
/**
* Open the DOM AST View and return a reference to it.
*
* @param editor
* @return
*/
public static IViewPart openDOMASTView(IEditorPart editor) {
IWorkbenchPartSite site = editor.getSite();
Shell shell = site.getShell();
IViewPart tempView = null;
// get the active editor
if (editor instanceof CEditor) {
try {
tempView = site.getPage().showView(OpenDOMViewAction.VIEW_ID);
} catch (PartInitException pie) {}
if (tempView != null) {
if (tempView instanceof DOMAST) {
IFile aFile = ((CEditor)editor).getInputFile();
// check if the file is a valid "compilation unit" (based on file extension)
String ext = aFile.getFileExtension().toUpperCase();
if (!(ext.equals(EXTENSION_C) || ext.equals(EXTENSION_CC) || ext.equals(EXTENSION_CPP) || ext.equals(EXTENSION_CXX))) {
MessageDialog.openInformation(shell, DOMAST.VIEW_NAME, NOT_VALID_COMPILATION_UNIT);
return null;
}
((DOMAST)tempView).setFile(aFile);
((DOMAST)tempView).setPart(editor);
((DOMAST)tempView).setLang(getLanguageFromFile(aFile));
((DOMAST)tempView).setContentProvider(((DOMAST)tempView).new ViewContentProvider(((CEditor)editor).getInputFile()));
}
}
site.getPage().activate(tempView);
}
return tempView;
}
public static ParserLanguage getLanguageFromFile(IFile file) {
IProject project = file.getProject();
ICFileType type = CCorePlugin.getDefault().getFileType(project, file.getFullPath().lastSegment());
String lid = type.getLanguage().getId();
if ( lid != null && lid.equals(ICFileTypeConstants.LANG_CXX) ) {
return ParserLanguage.CPP;
}
return ParserLanguage.C;
}
}

View file

@ -11,6 +11,7 @@
package org.eclipse.cdt.ui.tests.DOMAST;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -401,11 +402,11 @@ public class FindIASTNameTarget implements IFindReplaceTarget, IFindReplaceTarge
// get the TreeObject from the AST View's model corresponding to that name
TreeObject treeNode = null;
TreeItem treeItem = null;
treeNode = tuTreeParent.findTreeObjectForIASTName(foundName);
treeNode = tuTreeParent.findTreeObject(foundName, true, true);
if (treeNode != null && treeNode.getParent() != null) {
// found a matching TreeObject, so expand the tree to that object
treeItem = expandTreeToTreeObject(treeNode); // TODO Devin test this
treeItem = expandTreeToTreeObject(treeNode);
}
// loop until the next name within the matchingNames list is found in the tree
@ -413,11 +414,11 @@ public class FindIASTNameTarget implements IFindReplaceTarget, IFindReplaceTarge
((searchForward && index < matchingNames.length) ||
(!searchForward && index >= 0))) {
foundName = findNextMatchingName( findString, searchForward, caseSensitive, wholeWord, regExSearch );
treeNode = tuTreeParent.findTreeObjectForIASTName(foundName);
treeNode = tuTreeParent.findTreeObject(foundName, true, true);
if (treeNode != null && treeNode.getParent() != null) {
// found a matching TreeObject, so expand the tree to that object
treeItem = expandTreeToTreeObject(treeNode); // TODO Devin test this
treeItem = expandTreeToTreeObject(treeNode);
}
}
@ -440,5 +441,5 @@ public class FindIASTNameTarget implements IFindReplaceTarget, IFindReplaceTarge
// TODO Auto-generated method stub
}
}

View file

@ -116,5 +116,5 @@ public class OpenDOMViewAction implements IViewActionDelegate, IEditorActionDele
*/
public void setActivePart(IAction action, IWorkbenchPart targetPart) {
}
}

View file

@ -0,0 +1,173 @@
/**********************************************************************
* Copyright (c) 2005 IBM Canada and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v0.5
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v05.html
*
* Contributors:
* IBM Rational Software - Initial API and implementation
**********************************************************************/
package org.eclipse.cdt.ui.tests.DOMAST;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTNode;
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.internal.ui.editor.CEditor;
import org.eclipse.cdt.internal.ui.util.ExternalEditorInput;
import org.eclipse.cdt.ui.testplugin.CTestPlugin;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.swt.widgets.Event;
import org.eclipse.ui.IEditorActionDelegate;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.actions.ActionDelegate;
/**
* @author dsteffle
*/
public class ShowInDOMViewAction extends ActionDelegate implements
IEditorActionDelegate {
CEditor editor = null;
IASTTranslationUnit tu = null;
IViewPart view = null;
String file = null;
/* (non-Javadoc)
* @see org.eclipse.ui.IEditorActionDelegate#setActiveEditor(org.eclipse.jface.action.IAction, org.eclipse.ui.IEditorPart)
*/
public void setActiveEditor(IAction action, IEditorPart targetEditor) {
if (targetEditor instanceof CEditor)
editor = (CEditor)targetEditor;
}
/* (non-Javadoc)
* @see org.eclipse.ui.actions.ActionDelegate#runWithEvent(org.eclipse.jface.action.IAction, org.eclipse.swt.widgets.Event)
*/
public void runWithEvent(IAction action, Event event) {
TextSelection selection = null;
if (editor != null &&
editor.getSelectionProvider().getSelection() instanceof TextSelection) {
selection = (TextSelection)editor.getSelectionProvider().getSelection();
}
if (selection != null) {
if (!isFileInView()) {
view = DOMAST.openDOMASTViewRunAction(editor, new FindDisplayNode(selection.getOffset(), selection.getLength()), "Find Node in AST DOM View");
} else {
new FindDisplayNode(selection.getOffset(), selection.getLength()).run();
}
}
}
private void showMessage(String message) {
MessageDialog.openInformation(CTestPlugin.getStandardDisplay().getActiveShell(), DOMAST.VIEW_NAME, message);
}
private boolean isFileInView() {
if( editor.getInputFile() != null )
file = editor.getInputFile().getLocation().toOSString();
else
{
if( editor.getEditorInput() instanceof ExternalEditorInput )
file = ((ExternalEditorInput)editor.getEditorInput()).getStorage().getFullPath().toOSString();
}
if (file == null) return false;
try {
view = editor.getSite().getPage().showView(OpenDOMViewAction.VIEW_ID);
} catch (PartInitException pie) {}
if (view != null) {
if (view instanceof DOMAST) {
IContentProvider provider = ((DOMAST)view).getContentProvider();
if (provider != null && provider instanceof DOMAST.ViewContentProvider) {
tu = ((DOMAST.ViewContentProvider)provider).getTU();
if (tu != null) {
String fileName = null;
// check if file is tu
IASTNodeLocation[] locs = tu.getNodeLocations();
for (int i=0; i<locs.length; i++) {
if (locs[i] instanceof IASTFileLocation) {
fileName = ((IASTFileLocation)locs[i]).getFileName();
}
}
if (fileName == null) return false;
if (fileName.equals(file) ) {
return true;
}
// check the #includes on the TU (i.e. check if selecting something from a header file shown in DOM View)
IASTPreprocessorIncludeStatement[] includes = tu.getIncludeDirectives();
for(int i=0; i<includes.length; i++) {
if (includes[i].getPath().equals(file)) {
return true;
}
}
}
}
}
}
return false; // not a valid editor
}
private class FindDisplayNode implements Runnable {
private static final String IASTNode_NOT_FOUND = "IASTNode not found for the selection. Try refreshing the AST View if changes were made to the source.";
int offset = 0;
int length = 0;
public FindDisplayNode(int offset, int length) {
this.offset = offset;
this.length = length;
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.Action#run()
*/
public void run() {
// TODO Auto-generated method stub
if (view instanceof DOMAST) {
IContentProvider provider = ((DOMAST)view).getContentProvider();
if (provider != null && provider instanceof DOMAST.ViewContentProvider) {
tu = ((DOMAST.ViewContentProvider)provider).getTU();
if( editor.getInputFile() != null )
file = editor.getInputFile().getLocation().toOSString();
else
{
if( editor.getEditorInput() instanceof ExternalEditorInput )
file = ((ExternalEditorInput)editor.getEditorInput()).getStorage().getFullPath().toOSString();
}
}
}
// the selection is within a file currently shown in the DOM AST View
if (tu != null && file != null && view instanceof DOMAST) {
IASTNode node = tu.selectNodeForLocation(file, offset, length);
if (node != null && ((DOMAST)view).getContentProvider() instanceof DOMAST.ViewContentProvider) {
((DOMAST.ViewContentProvider)((DOMAST)view).getContentProvider()).findAndSelect(node, true); // use offsets when searching for node equality
} else {
showMessage(IASTNode_NOT_FOUND);
}
}
}
}
}

View file

@ -15,6 +15,7 @@ import java.util.Iterator;
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.internal.core.dom.parser.ASTNode;
/**
@ -127,14 +128,14 @@ public class TreeParent extends TreeObject {
* @param node
* @return
*/
private TreeParent findTreeObject(TreeObject[] trees, IASTNode node) {
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 ( ((TreeParent)trees[i]).getNode() == node ) {
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 );
TreeParent tree = findTreeObject( ((TreeParent)trees[i]).getChildren(), node, useOffset, useName );
if (tree != null) return tree;
}
}
@ -150,65 +151,32 @@ public class TreeParent extends TreeObject {
* @param node
* @return
*/
public TreeParent findTreeObject(IASTNode node) {
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;
Iterator itr = children.iterator();
while (itr.hasNext()) {
Object o = itr.next();
if (o != null && o instanceof TreeParent) {
if ( ((TreeParent)o).getNode() == node ) {
return (TreeParent)o;
} else if ( ((TreeParent)o).hasChildren() ){
TreeParent tree = findTreeObject( ((TreeParent)o).getChildren(), node );
if (tree != null) return tree;
}
}
}
return null; // nothing found
}
/**
* Returns the TreeParent that corresponds to the IASTName. This is based on string and offset equality.
*
* @param node
* @return
*/
public TreeParent findTreeObjectForIASTName(IASTName name) {
if (name == null) return null;
Iterator itr = children.iterator();
while (itr.hasNext()) {
Object o = itr.next();
if (o != null && o instanceof TreeParent) {
if (treeParentHasName((TreeParent)o, name)) return (TreeParent)o;
if ( ((TreeParent)o).hasChildren() ){
TreeParent tree = findTreeObjectForIASTName( ((TreeParent)o).getChildren(), name );
if (tree != null) return tree;
}
}
}
return null; // nothing found
}
/**
* Returns the TreeParent that corresponds to the IASTName. This is based on string and offset equality.
*
* @param trees
* @param node
* @return
*/
private TreeParent findTreeObjectForIASTName(TreeObject[] trees, IASTName name) {
for (int i=0; i<trees.length; i++) {
if (trees[i] != null && trees[i] instanceof TreeParent) {
if (treeParentHasName((TreeParent)trees[i], name)) return (TreeParent)trees[i];
IASTNode treeNode = ((TreeParent)o).getNode();
if ( ((TreeParent)trees[i]).hasChildren() ){
TreeParent tree = findTreeObjectForIASTName( ((TreeParent)trees[i]).getChildren(), name );
if (equalNodes(node, ((TreeParent)o).getNode(), useOffset, useName))
return (TreeParent)o;
// search the children
if ( ((TreeParent)o).hasChildren() ){
TreeParent tree = findTreeObject( ((TreeParent)o).getChildren(), node, useOffset, useName );
if (tree != null) return tree;
}
}
@ -216,16 +184,31 @@ public class TreeParent extends TreeObject {
return null; // nothing found
}
private boolean treeParentHasName(TreeParent tp, IASTName name) {
if ( tp.getNode() instanceof IASTName &&
tp.getNode() instanceof ASTNode &&
name instanceof ASTNode) {
IASTName treeName = (IASTName)tp.getNode();
ASTNode treeNode = (ASTNode)tp.getNode();
if (treeName.toString().equals(name.toString()) && treeNode.getOffset() == ((ASTNode)name).getOffset() ) {
private boolean equalNodes(IASTNode node1, IASTNode node2, boolean useOffset, boolean useName) {
if (useName &&
(!(node1 instanceof IASTName) || !(node2 instanceof IASTName) ||
!(((IASTName)node1).toString().equals(((IASTName)node2).toString())))) return false;
if (useOffset) {
if (node1 instanceof ASTNode && node2 instanceof ASTNode) {
if (((ASTNode)node1).getOffset() == ((ASTNode)node2).getOffset() &&
((ASTNode)node1).getLength() == ((ASTNode)node2).getLength())
return true;
} else {
IASTNodeLocation[] locs1 = node1.getNodeLocations();
IASTNodeLocation[] locs2 = node2.getNodeLocations();
for(int i=0; i<locs1.length && i<locs2.length; i++) {
if (locs1[i].getNodeOffset() != locs2[i].getNodeOffset() ||
locs1[i].getNodeLength() != locs2[i].getNodeLength())
return false;
}
return true;
}
} else {
if ( node1 == node2 )
return true;
}
return false;