From c7e0b780460627934b074a0759231c99a0bce1c3 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Thu, 15 May 2008 14:25:22 +0000 Subject: [PATCH] Separates refactoring base from utilities by Emanuel Graf, bug 232260. --- .../AddDeclarationNodeToClassChange.java | 30 +++- .../internal/ui/refactoring/CRefactoring.java | 169 +++--------------- .../ExtractConstantRefactoring.java | 8 +- .../ExtractFunctionRefactoring.java | 14 +- .../GenerateGettersAndSettersRefactoring.java | 3 +- .../hidemethod/HideMethodRefactoring.java | 24 --- .../ImplementMethodRefactoring.java | 2 +- .../refactoring/utils/DeclarationFinder.java | 74 ++++++++ .../utils/DeclarationFinderDO.java | 34 ++++ .../refactoring/utils/DefinitionFinder.java | 4 +- .../refactoring/utils/ExpressionFinder.java | 54 ++++++ .../ui/refactoring/utils/NameHelper.java | 57 +++--- .../ui/refactoring/utils/NodeFactory.java | 18 ++ .../ui/refactoring/utils/NodeHelper.java | 104 ++++++++++- .../ui/refactoring/utils/SelectionHelper.java | 87 ++++++++- 15 files changed, 459 insertions(+), 223 deletions(-) create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/DeclarationFinder.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/DeclarationFinderDO.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/ExpressionFinder.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/NodeFactory.java diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/AddDeclarationNodeToClassChange.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/AddDeclarationNodeToClassChange.java index 567a94b931a..7752a89fd00 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/AddDeclarationNodeToClassChange.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/AddDeclarationNodeToClassChange.java @@ -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 fieldNodes = new ArrayList(); 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 fieldNodes, boolean isField, ModificationCollector collector) { + new AddDeclarationNodeToClassChange(nodeClass, visibility, fieldNodes, collector, isField); + } + private AddDeclarationNodeToClassChange(ICPPASTCompositeTypeSpecifier nodeClass, VisibilityEnum visibility, ArrayList 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() { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring.java index ef8b395b61f..ebbbd67fe1d 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring.java @@ -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 findAllMarkedNames() { + final Vector namesVector = new Vector(); + + 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; + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractconstant/ExtractConstantRefactoring.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractconstant/ExtractConstantRefactoring.java index 146e39b804b..52da427325b 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractconstant/ExtractConstantRefactoring.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractconstant/ExtractConstantRefactoring.java @@ -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 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 locLiteralsToReplace = new ArrayList(); 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); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionRefactoring.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionRefactoring.java index 0c23e1c0860..9e810b8c2f8 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionRefactoring.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionRefactoring.java @@ -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; } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoring.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoring.java index ae206abb082..5bbba632fa5 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoring.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoring.java @@ -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); } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/hidemethod/HideMethodRefactoring.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/hidemethod/HideMethodRefactoring.java index 473b2b60d7f..f8c77aa95d1 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/hidemethod/HideMethodRefactoring.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/hidemethod/HideMethodRefactoring.java @@ -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 findAllMarkedNames() { - final Vector namesVector = new Vector(); - - 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) { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/implementmethod/ImplementMethodRefactoring.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/implementmethod/ImplementMethodRefactoring.java index 3cf383b9be4..121fa84341f 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/implementmethod/ImplementMethodRefactoring.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/implementmethod/ImplementMethodRefactoring.java @@ -131,7 +131,7 @@ public class ImplementMethodRefactoring extends CRefactoring { if (!insertLocation.hasFile()) { insertLocation.setInsertFile(file); insertLocation.setNodeToInsertAfter(NodeHelper - .getTopLevelParent(methodDeclaration)); + .findTopLevelParent(methodDeclaration)); } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/DeclarationFinder.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/DeclarationFinder.java new file mode 100644 index 00000000000..b8c2e733160 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/DeclarationFinder.java @@ -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 defName = new Container(); + 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(); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/DeclarationFinderDO.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/DeclarationFinderDO.java new file mode 100644 index 00000000000..04fb80a3100 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/DeclarationFinderDO.java @@ -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; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/DefinitionFinder.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/DefinitionFinder.java index 9e190f41238..1fe7811afda 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/DefinitionFinder.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/DefinitionFinder.java @@ -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 defName = new Container(); transUnit.accept(new CPPASTVisitor() { { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/ExpressionFinder.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/ExpressionFinder.java new file mode 100644 index 00000000000..46fd9ef03e1 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/ExpressionFinder.java @@ -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 expName = new Container(); + 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(); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/NameHelper.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/NameHelper.java index 73173b249f1..334d3cf15ad 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/NameHelper.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/NameHelper.java @@ -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 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(); + } + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/NodeFactory.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/NodeFactory.java new file mode 100644 index 00000000000..ebac1996d66 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/NodeFactory.java @@ -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); + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/NodeHelper.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/NodeHelper.java index e6a254fef55..59d9e4195cc 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/NodeHelper.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/NodeHelper.java @@ -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; + } + } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/SelectionHelper.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/SelectionHelper.java index fea4ccc9536..a45eb0bad6b 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/SelectionHelper.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/SelectionHelper.java @@ -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 container = new Container(); @@ -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); + } }