/*******************************************************************************
* Copyright (c) 2008, 2009 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.resources.IFile;
import org.eclipse.core.resources.IWorkspaceRoot;
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.ASTVisitor;
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.internal.ui.refactoring.Container;
/**
* Helper class to support operations concerning a selection.
*
* @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>();
translationUnit.accept(new ASTVisitor() {
{
shouldVisitDeclarations = true;
}
@Override
public int visit(IASTDeclaration declaration) {
if (declaration instanceof IASTSimpleDeclaration &&
isSelectionOnExpression(textSelection, declaration)) {
container.setObject((IASTSimpleDeclaration) declaration);
}
return super.visit(declaration);
}
});
return container.getObject();
}
public static boolean isSelectionOnExpression(Region textSelection, IASTNode expression) {
Region exprPos = createExpressionPosition(expression);
int exprStart = exprPos.getOffset();
int selStart = textSelection.getOffset();
int selEnd = selStart + textSelection.getLength();
return exprStart + exprPos.getLength() >= selStart && exprStart <= selEnd;
}
public static boolean isExpressionWhollyInSelection(Region textSelection, IASTNode expression) {
Region exprPos = createExpressionPosition(expression);
int exprStart = exprPos.getOffset();
int selStart = textSelection.getOffset();
int selEnd = selStart + textSelection.getLength();
return exprStart >= selStart && exprStart + exprPos.getLength() <= selEnd;
}
public static boolean isInSameFile(IASTNode node, IFile file) {
IPath path = new Path(node.getContainingFilename());
IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
IFile locFile = workspaceRoot.getFile(file.getLocation());
IFile tmpFile = workspaceRoot.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 = Integer.MAX_VALUE;
int nodeLength = 0;
IASTNodeLocation[] nodeLocations = expression.getNodeLocations();
if (nodeLocations.length != 1) {
for (IASTNodeLocation location : nodeLocations) {
if (location instanceof IASTMacroExpansionLocation) {
IASTMacroExpansionLocation macroLoc = (IASTMacroExpansionLocation) location;
int nodeOffset = macroLoc.asFileLocation().getNodeOffset();
if (nodeOffset < start) {
start = nodeOffset;
}
nodeLength += macroLoc.asFileLocation().getNodeLength();
} else {
IASTFileLocation loc = expression.getFileLocation();
int nodeOffset = loc.getNodeOffset();
if (nodeOffset < start) {
start = nodeOffset;
}
nodeLength = loc.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);
}
}