1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Separates refactoring base from utilities by Emanuel Graf, bug 232260.

This commit is contained in:
Markus Schorn 2008-05-15 14:25:22 +00:00
parent 2ce7d65442
commit c7e0b78046
15 changed files with 459 additions and 223 deletions

View file

@ -11,9 +11,12 @@
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring;
import java.util.ArrayList;
import org.eclipse.osgi.util.NLS;
import org.eclipse.text.edits.TextEditGroup;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
@ -38,17 +41,28 @@ public class AddDeclarationNodeToClassChange {
private final ICPPASTCompositeTypeSpecifier nodeClass;
private final VisibilityEnum visibility;
private final IASTNode fieldNodes;
private ArrayList<IASTNode> fieldNodes = new ArrayList<IASTNode>();
private final ModificationCollector collector;
public static void createChange(ICPPASTCompositeTypeSpecifier nodeClass, VisibilityEnum visibility, IASTNode fieldNodes, boolean isField, ModificationCollector collector) {
new AddDeclarationNodeToClassChange(nodeClass, visibility, fieldNodes, collector, isField);
}
public static void createChange(ICPPASTCompositeTypeSpecifier nodeClass, VisibilityEnum visibility, ArrayList<IASTNode> fieldNodes, boolean isField, ModificationCollector collector) {
new AddDeclarationNodeToClassChange(nodeClass, visibility, fieldNodes, collector, isField);
}
private AddDeclarationNodeToClassChange(ICPPASTCompositeTypeSpecifier nodeClass, VisibilityEnum visibility, ArrayList<IASTNode> fieldNodes, ModificationCollector collector, boolean isField) {
this.fieldNodes = fieldNodes;
this.nodeClass = nodeClass;
this.visibility = visibility;
this.collector = collector;
createRewrites(isField);
}
private AddDeclarationNodeToClassChange(ICPPASTCompositeTypeSpecifier nodeClass, VisibilityEnum visibility, IASTNode fieldNodes, ModificationCollector collector, boolean isField) {
this.nodeClass = nodeClass;
this.visibility = visibility;
this.fieldNodes = fieldNodes;
this.fieldNodes.add(fieldNodes);
this.collector = collector;
createRewrites(isField);
}
@ -58,8 +72,10 @@ public class AddDeclarationNodeToClassChange {
int lastFieldDeclaration = -1;
IASTDeclaration[] members = nodeClass.getMembers();
// XXX Don't we have to differentiate between the default visibility in a class and a struct?
VisibilityEnum currentVisibility = VisibilityEnum.v_private;
if(IASTCompositeTypeSpecifier.k_struct == nodeClass.getKey()) {
currentVisibility = VisibilityEnum.v_public;
}
// Find the insert location by iterating over the elements of the class
// and remembering the last element with the matching visibility
@ -119,7 +135,9 @@ public class AddDeclarationNodeToClassChange {
private void insertBefore(IASTNode nearestNode) {
ASTRewrite rewrite = collector.rewriterForTranslationUnit(nearestNode.getTranslationUnit());
rewrite.insertBefore(nearestNode.getParent(), nearestNode, fieldNodes, createEditDescription());
for(IASTNode node: fieldNodes) {
rewrite.insertBefore(nearestNode.getParent(), nearestNode, node, createEditDescription());
}
}
private void insertAtTheEnd(VisibilityEnum currentVisibility) {
@ -131,7 +149,9 @@ public class AddDeclarationNodeToClassChange {
rewrite.insertBefore(nodeClass, null, label, createEditDescription());
}
rewrite.insertBefore(nodeClass, null, fieldNodes, createEditDescription());
for(IASTNode node: fieldNodes) {
rewrite.insertBefore(nodeClass, null, node, createEditDescription());
}
}
private TextEditGroup createEditDescription() {

View file

@ -11,16 +11,14 @@
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring;
import java.util.Vector;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ltk.core.refactoring.Change;
@ -31,23 +29,16 @@ import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTMacroExpansionLocation;
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.IASTProblem;
import org.eclipse.cdt.core.dom.ast.IASTProblemDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTProblemExpression;
import org.eclipse.cdt.core.dom.ast.IASTProblemStatement;
import org.eclipse.cdt.core.dom.ast.IASTProblemTypeId;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
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.IBinding;
import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.model.CModelException;
@ -63,6 +54,8 @@ import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousExpression;
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousStatement;
import org.eclipse.cdt.internal.core.dom.parser.IASTDeclarationAmbiguity;
import org.eclipse.cdt.internal.ui.refactoring.utils.SelectionHelper;
/**
* The baseclass for all other refactorings, provides some common implementations for
* condition checking, change generating, selection handling and translation unit loading.
@ -97,7 +90,7 @@ public abstract class CRefactoring extends Refactoring {
}
else {
this.file = file;
this.region = getRegion(selection);
this.region = SelectionHelper.getRegion(selection);
}
this.initStatus=new RefactoringStatus();
@ -270,14 +263,6 @@ public abstract class CRefactoring extends Refactoring {
return name;
}
private Region getRegion(ISelection selection) {
if (selection instanceof ITextSelection) {
final ITextSelection txtSelection= (ITextSelection) selection;
return new Region(txtSelection.getOffset(), txtSelection.getLength());
}
return null;
}
protected boolean loadTranslationUnit(RefactoringStatus status,
IProgressMonitor mon) {
SubMonitor subMonitor = SubMonitor.convert(mon, 10);
@ -312,116 +297,6 @@ public abstract class CRefactoring extends Refactoring {
return tu.getAST(fIndex, AST_STYLE);
}
private static class ExpressionPosition {
public int start;
public int end;
@Override
public String toString() {
return String.format("Position ranges from %d to %d and has a length of %d", Integer.valueOf(start), //$NON-NLS-1$
Integer.valueOf(end), Integer.valueOf(end - start));
}
}
protected static ExpressionPosition createExpressionPosition(IASTNode expression) {
ExpressionPosition selection = new ExpressionPosition();
int nodeLength = 0;
IASTNodeLocation[] nodeLocations = expression.getNodeLocations();
if (nodeLocations.length != 1) {
for (IASTNodeLocation location : nodeLocations) {
if (location instanceof IASTMacroExpansionLocation) {
IASTMacroExpansionLocation macroLoc = (IASTMacroExpansionLocation) location;
selection.start = macroLoc.asFileLocation().getNodeOffset();
nodeLength = macroLoc.asFileLocation().getNodeLength();
}
}
} else {
if (nodeLocations[0] instanceof IASTMacroExpansionLocation) {
IASTMacroExpansionLocation macroLoc = (IASTMacroExpansionLocation) nodeLocations[0];
selection.start = macroLoc.asFileLocation().getNodeOffset();
nodeLength = macroLoc.asFileLocation().getNodeLength();
} else {
IASTFileLocation loc = expression.getFileLocation();
selection.start = loc.getNodeOffset();
nodeLength = loc.getNodeLength();
}
}
selection.end = selection.start + nodeLength;
return selection;
}
protected boolean isExpressionWhollyInSelection(Region textSelection, IASTNode expression) {
ExpressionPosition exprPos = createExpressionPosition(expression);
int selStart = textSelection.getOffset();
int selEnd = textSelection.getLength() + selStart;
return exprPos.start >= selStart && exprPos.end <= selEnd;
}
public static boolean isSelectionOnExpression(Region textSelection, IASTNode expression) {
ExpressionPosition exprPos = createExpressionPosition(expression);
int selStart = textSelection.getOffset();
int selEnd = textSelection.getLength() + selStart;
return exprPos.end > selStart && exprPos.start < selEnd;
}
protected boolean isInSameFile(IASTNode node) {
IPath path = new Path(node.getContainingFilename());
IFile locFile = ResourcesPlugin.getWorkspace().getRoot().getFile(file.getLocation());
IFile tmpFile = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
return locFile.equals(tmpFile);
}
protected boolean isInSameFileSelection(Region textSelection, IASTNode node) {
if( isInSameFile(node) ) {
return isSelectionOnExpression(textSelection, node);
}
return false;
}
protected boolean isSelectedFile(Region textSelection, IASTNode node) {
if( isInSameFile(node) ) {
return isExpressionWhollyInSelection(textSelection, node);
}
return false;
}
protected MethodContext findContext(IASTNode node) {
boolean found = false;
MethodContext context = new MethodContext();
context.setType(MethodContext.ContextType.NONE);
IASTName name = null;
while(node != null && !found){
node = node.getParent();
if(node instanceof IASTFunctionDeclarator){
name=((IASTFunctionDeclarator)node).getName();
found = true;
context.setType(MethodContext.ContextType.FUNCTION);
} else if (node instanceof IASTFunctionDefinition){
name=((IASTFunctionDefinition)node).getDeclarator().getName();
found = true;
context.setType(MethodContext.ContextType.FUNCTION);
}
}
if(name instanceof ICPPASTQualifiedName){
ICPPASTQualifiedName qname =( ICPPASTQualifiedName )name;
context.setMethodQName(qname);
IBinding bind = qname.resolveBinding();
IASTName[] decl = unit.getDeclarationsInAST(bind);//TODO HSR funktioniert nur fuer namen aus der aktuellen Translationunit
for (IASTName tmpname : decl) {
IASTNode methoddefinition = tmpname.getParent().getParent();
if (methoddefinition instanceof IASTSimpleDeclaration) {
context.setMethodDeclarationName(tmpname);
context.setType(MethodContext.ContextType.METHOD);
}
}
}
return context;
}
protected boolean translationUnitHasProblem() {
ProblemFinder pf = new ProblemFinder(initStatus);
unit.accept(pf);
@ -434,16 +309,6 @@ public abstract class CRefactoring extends Refactoring {
return af.ambiguityFound();
}
protected IASTSimpleDeclaration findSimpleDeclarationInParents(IASTNode node) {
while(node != null){
if (node instanceof IASTSimpleDeclaration) {
return (IASTSimpleDeclaration) node;
}
node = node.getParent();
}
return null;
}
public void lockIndex() throws CoreException, InterruptedException {
if (fIndex == null) {
ICProject[] projects= CoreModel.getDefault().getCModel().getCProjects();
@ -462,4 +327,26 @@ public abstract class CRefactoring extends Refactoring {
public IIndex getIndex() {
return fIndex;
}
protected Vector<IASTName> findAllMarkedNames() {
final Vector<IASTName> namesVector = new Vector<IASTName>();
unit.accept(new CPPASTVisitor() {
{
shouldVisitNames = true;
}
@Override
public int visit(IASTName name) {
if (SelectionHelper.isInSameFileSelection(region, name, file)) {
if (!(name instanceof ICPPASTQualifiedName)) {
namesVector.add(name);
}
}
return super.visit(name);
}
});
return namesVector;
}
}

View file

@ -64,6 +64,8 @@ import org.eclipse.cdt.internal.ui.refactoring.CRefactoring;
import org.eclipse.cdt.internal.ui.refactoring.MethodContext;
import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector;
import org.eclipse.cdt.internal.ui.refactoring.NameNVisibilityInformation;
import org.eclipse.cdt.internal.ui.refactoring.utils.NodeHelper;
import org.eclipse.cdt.internal.ui.refactoring.utils.SelectionHelper;
import org.eclipse.cdt.internal.ui.refactoring.utils.TranslationUnitHelper;
/**
@ -218,7 +220,7 @@ public class ExtractConstantRefactoring extends CRefactoring {
private boolean isOneMarked(Collection<IASTLiteralExpression> literalExpressionVector, Region textSelection) {
boolean oneMarked = false;
for (IASTLiteralExpression expression : literalExpressionVector) {
boolean isInSameFileSelection = isInSameFileSelection(textSelection, expression);
boolean isInSameFileSelection = SelectionHelper.isInSameFileSelection(textSelection, expression, file);
if(isInSameFileSelection){
if(target == null) {
target = expression;
@ -259,13 +261,13 @@ public class ExtractConstantRefactoring extends CRefactoring {
protected void collectModifications(IProgressMonitor pm, ModificationCollector collector)
throws CoreException, OperationCanceledException {
MethodContext context = findContext(target);
MethodContext context = NodeHelper.findMethodContext(target);
Collection<IASTExpression> locLiteralsToReplace = new ArrayList<IASTExpression>();
if(context.getType() == MethodContext.ContextType.METHOD){
for (IASTExpression expression : literalsToReplace) {
MethodContext exprContext = findContext(expression);
MethodContext exprContext = NodeHelper.findMethodContext(expression);
if(exprContext.getType() == MethodContext.ContextType.METHOD){
if( MethodContext.isSameClass(exprContext.getMethodQName(), context.getMethodQName())){
locLiteralsToReplace.add(expression);

View file

@ -98,6 +98,8 @@ import org.eclipse.cdt.internal.ui.refactoring.MethodContext.ContextType;
import org.eclipse.cdt.internal.ui.refactoring.NodeContainer.NameInformation;
import org.eclipse.cdt.internal.ui.refactoring.utils.ASTHelper;
import org.eclipse.cdt.internal.ui.refactoring.utils.CPPASTAllVisitor;
import org.eclipse.cdt.internal.ui.refactoring.utils.NodeHelper;
import org.eclipse.cdt.internal.ui.refactoring.utils.SelectionHelper;
public class ExtractFunctionRefactoring extends CRefactoring {
@ -187,7 +189,7 @@ public class ExtractFunctionRefactoring extends CRefactoring {
}
info.setDeclarator(getDeclaration(container.getNodesToWrite().get(0)));
MethodContext context = findContext(container.getNodesToWrite().get(0));
MethodContext context = NodeHelper.findMethodContext(container.getNodesToWrite().get(0));
info.setMethodContext(context);
sm.done();
return status;
@ -244,7 +246,7 @@ public class ExtractFunctionRefactoring extends CRefactoring {
final IASTName astMethodName = new CPPASTName(info.getMethodName()
.toCharArray());
MethodContext context = findContext(container.getNodesToWrite().get(0));
MethodContext context = NodeHelper.findMethodContext(container.getNodesToWrite().get(0));
if (context.getType() == ContextType.METHOD) {
ICPPASTCompositeTypeSpecifier classDeclaration = (ICPPASTCompositeTypeSpecifier) context
@ -273,7 +275,7 @@ public class ExtractFunctionRefactoring extends CRefactoring {
final IASTName astMethodName = new CPPASTName(info.getMethodName()
.toCharArray());
MethodContext context = findContext(container.getNodesToWrite().get(0));
MethodContext context = NodeHelper.findMethodContext(container.getNodesToWrite().get(0));
// Create Declaration in Class
if (context.getType() == ContextType.METHOD) {
@ -781,7 +783,7 @@ public class ExtractFunctionRefactoring extends CRefactoring {
private IASTNode getReturnAssignment(IASTExpressionStatement stmt,
IASTFunctionCallExpression callExpression, IASTName retname) {
if (info.getReturnVariable().equals(info.getInScopeDeclaredVariable())) {
IASTSimpleDeclaration orgDecl = findSimpleDeclarationInParents(info
IASTSimpleDeclaration orgDecl = NodeHelper.findSimpleDeclarationInParents(info
.getReturnVariable().getDeclaration());
IASTSimpleDeclaration decl = new CPPASTSimpleDeclaration();
@ -848,7 +850,7 @@ public class ExtractFunctionRefactoring extends CRefactoring {
@Override
public int visit(IASTStatement stmt) {
if (!(stmt instanceof IASTCompoundStatement)
&& isSelectedFile(region, stmt)) {
&& SelectionHelper.isSelectedFile(region, stmt, file)) {
container.add(stmt);
return PROCESS_SKIP;
}
@ -857,7 +859,7 @@ public class ExtractFunctionRefactoring extends CRefactoring {
@Override
public int visit(IASTExpression expression) {
if (isSelectedFile(region, expression)) {
if (SelectionHelper.isSelectedFile(region, expression, file)) {
container.add(expression);
return PROCESS_SKIP;
}

View file

@ -32,6 +32,7 @@ import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.internal.ui.refactoring.AddDeclarationNodeToClassChange;
import org.eclipse.cdt.internal.ui.refactoring.CRefactoring;
import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector;
import org.eclipse.cdt.internal.ui.refactoring.utils.SelectionHelper;
import org.eclipse.cdt.internal.ui.refactoring.utils.VisibilityEnum;
/**
@ -84,7 +85,7 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring {
if ((declarators[0] instanceof IASTFunctionDeclarator)) {
context.existingFunctionDeclarations.add(fieldDeclaration);
} else {
if(isInSameFile(fieldDeclaration)){
if(SelectionHelper.isInSameFile(fieldDeclaration, file)){
context.existingFields.add(fieldDeclaration);
}
}

View file

@ -31,7 +31,6 @@ import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.cdt.core.model.ICElement;
@ -101,29 +100,6 @@ public class HideMethodRefactoring extends CRefactoring {
return initStatus;
}
private Vector<IASTName> findAllMarkedNames() {
final Vector<IASTName> namesVector = new Vector<IASTName>();
unit.accept(new CPPASTVisitor(){
{
shouldVisitNames = true;
}
@Override
public int visit(IASTName name) {
if( isInSameFileSelection(region, name) ) {
if (!(name instanceof ICPPASTQualifiedName)) {
namesVector.add(name);
}
}
return super.visit(name);
}
});
return namesVector;
}
protected IASTSimpleDeclaration findSimpleDeclaration(IASTNode fieldToFoundDecl) {
while(fieldToFoundDecl != null){
if (fieldToFoundDecl instanceof IASTSimpleDeclaration) {

View file

@ -131,7 +131,7 @@ public class ImplementMethodRefactoring extends CRefactoring {
if (!insertLocation.hasFile()) {
insertLocation.setInsertFile(file);
insertLocation.setNodeToInsertAfter(NodeHelper
.getTopLevelParent(methodDeclaration));
.findTopLevelParent(methodDeclaration));
}
}

View file

@ -0,0 +1,74 @@
/*******************************************************************************
* Copyright (c) 2008 Institute for Software, HSR Hochschule fuer Technik
* Rapperswil, University of applied sciences and others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Institute for Software - initial API and implementation
******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.utils;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.internal.ui.refactoring.Container;
/**
* @author Guido Zgraggen IFS
*/
public class DeclarationFinder {
public static DeclarationFinderDO getDeclaration(IASTName name, IIndex index) throws CoreException {
IIndexBinding binding = index.findBinding(name);
IIndexName[] pdomref = index.findDeclarations(binding);
IIndexName[] allNamesPDom = index.findNames(binding, IIndex.FIND_REFERENCES);
if (pdomref == null || pdomref.length < 1) {
return null;
}
String filename2 = pdomref[0].getFileLocation().getFileName();
IASTTranslationUnit transUnit = TranslationUnitHelper.loadTranslationUnit(filename2);
IASTName declName = DeclarationFinder.findDeclarationInTranslationUnit(transUnit, pdomref[0]);
return new DeclarationFinderDO(allNamesPDom, transUnit, filename2, declName);
}
public static IASTName findDeclarationInTranslationUnit(IASTTranslationUnit transUnit, final IIndexName indexName) {
final Container<IASTName> defName = new Container<IASTName>();
transUnit.accept(new CPPASTVisitor() {
{
shouldVisitNames = true;
}
@Override
public int visit(IASTName name) {
if (name.isDeclaration() && name.getNodeLocations().length > 0) {
IASTNodeLocation nodeLocation = name.getNodeLocations()[0];
if (indexName.getNodeOffset() == nodeLocation.getNodeOffset()
&& indexName.getNodeLength() == nodeLocation.getNodeLength()
&& new Path(indexName.getFileLocation().getFileName()).equals(new Path(nodeLocation.asFileLocation().getFileName()))) {
defName.setObject(name);
return ASTVisitor.PROCESS_ABORT;
}
}
return ASTVisitor.PROCESS_CONTINUE;
}
});
return defName.getObject();
}
}

View file

@ -0,0 +1,34 @@
/*******************************************************************************
* Copyright (c) 2008 Institute for Software, HSR Hochschule fuer Technik
* Rapperswil, University of applied sciences and others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Institute for Software - initial API and implementation
******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.utils;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.index.IIndexName;
/**
* @author Guido Zgraggen IFS
*
*/
public class DeclarationFinderDO {
public IASTTranslationUnit transUnit = null;
public String filename = null;
public IIndexName[] allNamesPDom = null;
public IASTName name = null;
public DeclarationFinderDO(IIndexName[] allNamesPDom2, IASTTranslationUnit transUnit2, String filename2, IASTName name2) {
this.transUnit = transUnit2;
this.filename = filename2;
this.allNamesPDom = allNamesPDom2;
this.name = name2;
}
}

View file

@ -78,10 +78,10 @@ public class DefinitionFinder {
} else {
transUnit = parsedFiles.get(pdomref[0].getFileLocation().getFileName());
}
return findDefinitionInTranslationUnit(transUnit, methodName, pdomref[0]);
return findDefinitionInTranslationUnit(transUnit, pdomref[0]);
}
private static IASTName findDefinitionInTranslationUnit(IASTTranslationUnit transUnit, final IASTName name2, final IIndexName indexName) {
private static IASTName findDefinitionInTranslationUnit(IASTTranslationUnit transUnit, final IIndexName indexName) {
final Container<IASTName> defName = new Container<IASTName>();
transUnit.accept(new CPPASTVisitor() {
{

View file

@ -0,0 +1,54 @@
/*******************************************************************************
* Copyright (c) 2008 Institute for Software, HSR Hochschule fuer Technik
* Rapperswil, University of applied sciences and others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Institute for Software - initial API and implementation
******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.utils;
import org.eclipse.core.runtime.Path;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.internal.ui.refactoring.Container;
/**
* @author Guido Zgraggen IFS
*/
public class ExpressionFinder {
public static IASTName findExpressionInTranslationUnit(IASTTranslationUnit transUnit, final IIndexName indexName) {
final Container<IASTName> expName = new Container<IASTName>();
transUnit.accept(new CPPASTVisitor() {
{
shouldVisitNames = true;
}
@Override
public int visit(IASTName name) {
if (name.isReference() && name.getNodeLocations().length > 0) {
IASTNodeLocation nodeLocation = name.getNodeLocations()[0];
if (indexName.getNodeOffset() == nodeLocation.getNodeOffset()
&& indexName.getNodeLength() == nodeLocation.getNodeLength()
&& new Path(indexName.getFileLocation().getFileName()).equals(new Path(nodeLocation.asFileLocation().getFileName()))) {
expName.setObject(name);
return ASTVisitor.PROCESS_ABORT;
}
}
return ASTVisitor.PROCESS_CONTINUE;
}
});
return expName.getObject();
}
}

View file

@ -15,12 +15,13 @@ import java.util.regex.Pattern;
import org.eclipse.core.resources.IFile;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.parser.Keywords;
import org.eclipse.cdt.core.parser.util.CharArrayIntMap;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTQualifiedName;
@ -37,7 +38,15 @@ public class NameHelper {
public static boolean isValidLocalVariableName(String name) {
boolean valid = Pattern.compile(localVariableRegexp).matcher(name).matches();
return valid; /* && Keyword.getKeyword(stringToValidate, stringToValidate.length()) == null*/ //TODO Check for keywords?;
return valid;
}
public static boolean isKeyword(String name) {
CharArrayIntMap keywords = new CharArrayIntMap(0, -1);
Keywords.addKeywordsC(keywords);
Keywords.addKeywordsCpp(keywords);
Keywords.addKeywordsPreprocessor(keywords);
return keywords.containsKey(name.toCharArray());
}
/**
@ -69,34 +78,6 @@ public class NameHelper {
return qname;
}
public static IASTFunctionDefinition getAncestorFunctionDefinition(IASTName startNode) {
return (IASTFunctionDefinition) getAncestorDefinition(startNode, IASTFunctionDefinition.class);
}
public static IASTSimpleDeclaration getAncestorFunctionDeclaration(IASTName startNode) {
return (IASTSimpleDeclaration) getAncestorDefinition(startNode, IASTSimpleDeclaration.class);
}
public static ICPPASTCompositeTypeSpecifier getAncestorClassDefinition(IASTName startNode) {
return (ICPPASTCompositeTypeSpecifier) getAncestorDefinition(startNode, ICPPASTCompositeTypeSpecifier.class);
}
public static IASTNode getAncestorDefinition(IASTName startNode, Class<? extends IASTNode> type) {
IASTNode node = startNode;
while(node != null ){
if(type.isInstance(node)) {
return node;
}
node = node.getParent();
}
return null;
}
public static String trimFieldName(String fieldName){
char[] letters = fieldName.toCharArray();
int start = 0;
@ -129,6 +110,14 @@ public class NameHelper {
name = Character.toUpperCase(name.charAt(0)) + name.substring(1);
}
return name;
}
}
public static String getTypeName(IASTParameterDeclaration parameter) {
IASTDeclSpecifier parameterDeclSpecifier = parameter.getDeclSpecifier();
if (parameterDeclSpecifier instanceof ICPPASTNamedTypeSpecifier) {
return ((ICPPASTNamedTypeSpecifier) parameterDeclSpecifier).getName().getRawSignature();
} else {
return parameterDeclSpecifier.getRawSignature();
}
}
}

View file

@ -0,0 +1,18 @@
package org.eclipse.cdt.internal.ui.refactoring.utils;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTDeclarator;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNamedTypeSpecifier;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTParameterDeclaration;
public class NodeFactory {
public static IASTParameterDeclaration createParameterDeclaration(String paramType, String paramName) {
CPPASTNamedTypeSpecifier type = new CPPASTNamedTypeSpecifier(new CPPASTName(paramType.toCharArray()), false);
CPPASTDeclarator declarator = new CPPASTDeclarator(new CPPASTName(paramName.toCharArray()));
return new CPPASTParameterDeclaration(type,declarator);
}
}

View file

@ -11,17 +11,30 @@
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.utils;
import org.eclipse.core.runtime.Path;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNamespaceDefinition;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit;
import org.eclipse.cdt.internal.ui.refactoring.MethodContext;
/**
* General class for common Node operations.
*
* @author Lukas Felber
* @author Lukas Felber & Guido Zgraggen
*
*/
public class NodeHelper {
@ -54,10 +67,95 @@ public class NodeHelper {
return null;
}
public static IASTNode getTopLevelParent(IASTNode currentNode) {
public static IASTNode findTopLevelParent(IASTNode currentNode) {
while(currentNode != null && currentNode.getParent() != null && currentNode.getParent().getParent() != null) {
return getTopLevelParent(currentNode.getParent());
return findTopLevelParent(currentNode.getParent());
}
return currentNode;
}
public static boolean isSameNode(IASTNode node1, IASTNode node2) {
if(node1 == null || node2 == null) {
return false;
}
return node1.getNodeLocations()[0].getNodeOffset() == node2.getNodeLocations()[0].getNodeOffset()
&& node1.getNodeLocations()[0].getNodeLength() == node2.getNodeLocations()[0].getNodeLength()
&& new Path(node1.getFileLocation().getFileName()).equals(new Path(node2.getFileLocation().getFileName()));
}
public static IASTSimpleDeclaration findSimpleDeclarationInParents(IASTNode node) {
while(node != null){
if (node instanceof IASTSimpleDeclaration) {
return (IASTSimpleDeclaration) node;
}
node = node.getParent();
}
return null;
}
public static MethodContext findMethodContext(IASTNode node) {
IASTTranslationUnit translationUnit = node.getTranslationUnit();
boolean found = false;
MethodContext context = new MethodContext();
context.setType(MethodContext.ContextType.NONE);
IASTName name = null;
while(node != null && !found){
node = node.getParent();
if(node instanceof IASTFunctionDeclarator){
name=((IASTFunctionDeclarator)node).getName();
found = true;
context.setType(MethodContext.ContextType.FUNCTION);
} else if (node instanceof IASTFunctionDefinition){
name=((IASTFunctionDefinition)node).getDeclarator().getName();
found = true;
context.setType(MethodContext.ContextType.FUNCTION);
}
}
if(name instanceof ICPPASTQualifiedName){
ICPPASTQualifiedName qname =( ICPPASTQualifiedName )name;
context.setMethodQName(qname);
IBinding bind = qname.resolveBinding();
IASTName[] decl = translationUnit.getDeclarationsInAST(bind);//TODO HSR works only for names in the current translationUnit
for (IASTName tmpname : decl) {
IASTNode methoddefinition = tmpname.getParent().getParent();
if (methoddefinition instanceof IASTSimpleDeclaration) {
context.setMethodDeclarationName(tmpname);
context.setType(MethodContext.ContextType.METHOD);
}
}
}
return context;
}
public static IASTCompoundStatement findCompoundStatementInParent(IASTNode node) {
while(node != null){
if (node instanceof IASTCompoundStatement) {
return (IASTCompoundStatement) node;
}
node = node.getParent();
}
return null;
}
public static IASTCompositeTypeSpecifier findEnclosingClass(IASTNode node) {
while(!(node instanceof IASTCompositeTypeSpecifier)){
if(node instanceof IASTTranslationUnit) {
return null;
}
node = node.getParent();
}
return (IASTCompositeTypeSpecifier) node;
}
public static IASTFunctionDefinition findFunctionDefinition(IASTNode node) {
while(node != null){
if (node instanceof IASTFunctionDefinition) {
return (IASTFunctionDefinition) node;
}
node = node.getParent();
}
return null;
}
}

View file

@ -11,24 +11,41 @@
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.utils;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTMacroExpansionLocation;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor;
import org.eclipse.cdt.internal.ui.refactoring.CRefactoring;
import org.eclipse.cdt.internal.ui.refactoring.Container;
/**
* Helper class to suport operations conserning a selection.
*
* @author Mirko Stocker
* @author Mirko Stocker, Lukas Felber
*
*/
public class SelectionHelper {
public static Region getRegion(ISelection selection) {
if (selection instanceof ITextSelection) {
final ITextSelection txtSelection= (ITextSelection) selection;
return new Region(txtSelection.getOffset(), txtSelection.getLength());
}
return null;
}
public static IASTSimpleDeclaration findFirstSelectedDeclaration(final Region textSelection, IASTTranslationUnit translationUnit) {
final Container<IASTSimpleDeclaration> container = new Container<IASTSimpleDeclaration>();
@ -39,7 +56,7 @@ public class SelectionHelper {
}
@Override
public int visit(IASTDeclaration declaration) {
if (declaration instanceof IASTSimpleDeclaration && CRefactoring.isSelectionOnExpression(textSelection, declaration)) {
if (declaration instanceof IASTSimpleDeclaration && isSelectionOnExpression(textSelection, declaration)) {
container.setObject((IASTSimpleDeclaration) declaration);
}
return super.visit(declaration);
@ -48,4 +65,68 @@ public class SelectionHelper {
return container.getObject();
}
public static boolean isSelectionOnExpression(Region textSelection, IASTNode expression) {
Region exprPos = createExpressionPosition(expression);
int selStart = textSelection.getOffset();
int selEnd = textSelection.getLength() + selStart;
return exprPos.getOffset()+exprPos.getLength() > selStart && exprPos.getOffset() < selEnd;
}
public static boolean isExpressionWhollyInSelection(Region textSelection, IASTNode expression) {
Region exprPos = createExpressionPosition(expression);
int selStart = textSelection.getOffset();
int selEnd = textSelection.getLength() + selStart;
return exprPos.getOffset() >= selStart && exprPos.getOffset()+exprPos.getLength() <= selEnd;
}
public static boolean isInSameFile(IASTNode node, IFile file) {
IPath path = new Path(node.getContainingFilename());
IFile locFile = ResourcesPlugin.getWorkspace().getRoot().getFile(file.getLocation());
IFile tmpFile = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
return locFile.equals(tmpFile);
}
public static boolean isInSameFileSelection(Region textSelection, IASTNode node, IFile file) {
if( isInSameFile(node, file) ) {
return SelectionHelper.isSelectionOnExpression(textSelection, node);
}
return false;
}
public static boolean isSelectedFile(Region textSelection, IASTNode node, IFile file) {
if( isInSameFile(node, file) ) {
return isExpressionWhollyInSelection(textSelection, node);
}
return false;
}
protected static Region createExpressionPosition(IASTNode expression) {
int start = 0;
int nodeLength = 0;
IASTNodeLocation[] nodeLocations = expression.getNodeLocations();
if (nodeLocations.length != 1) {
for (IASTNodeLocation location : nodeLocations) {
if (location instanceof IASTMacroExpansionLocation) {
IASTMacroExpansionLocation macroLoc = (IASTMacroExpansionLocation) location;
start = macroLoc.asFileLocation().getNodeOffset();
nodeLength = macroLoc.asFileLocation().getNodeLength();
}
}
} else {
if (nodeLocations[0] instanceof IASTMacroExpansionLocation) {
IASTMacroExpansionLocation macroLoc = (IASTMacroExpansionLocation) nodeLocations[0];
start = macroLoc.asFileLocation().getNodeOffset();
nodeLength = macroLoc.asFileLocation().getNodeLength();
} else {
IASTFileLocation loc = expression.getFileLocation();
start = loc.getNodeOffset();
nodeLength = loc.getNodeLength();
}
}
return new Region(start, nodeLength);
}
}