/******************************************************************************* * Copyright (c) 2011 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: * Martin Schwab & Thomas Kallenberg - initial API and implementation ******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring.togglefunction; import org.eclipse.jface.text.ITextSelection; import org.eclipse.cdt.core.dom.ast.IASTDeclarator; 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.IASTStatement; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; /** * Given a selection and a translation unit, this class finds a * ICPPASTFunctionDeclarator if possible. Special case: Nested local functions * are skipped during search. */ public class DeclaratorFinder { private IASTFunctionDeclarator foundDeclarator; public DeclaratorFinder(ITextSelection selection, IASTTranslationUnit unit) { foundDeclarator = findDeclaratorInSelection(selection, unit); if (foundDeclarator == null) { throw new NotSupportedException(Messages.DeclaratorFinder_NoDeclarator); } if (isPartOfAStatement(foundDeclarator)) { throw new NotSupportedException(Messages.DeclaratorFinder_NestedFunction); } } public IASTName getName() { return foundDeclarator.getName(); } private IASTFunctionDeclarator findDeclaratorInSelection( ITextSelection selection, IASTTranslationUnit unit) { IASTNode firstNodeInsideSelection = unit.getNodeSelector(null) .findFirstContainedNode(selection.getOffset(), selection.getLength()); IASTFunctionDeclarator declarator = findDeclaratorInAncestors(firstNodeInsideSelection); if (declarator == null) { firstNodeInsideSelection = unit.getNodeSelector(null).findEnclosingNode( selection.getOffset(), selection.getLength()); declarator = findDeclaratorInAncestors(firstNodeInsideSelection); } return declarator; } private IASTFunctionDeclarator findDeclaratorInAncestors(IASTNode node) { while (node != null) { IASTFunctionDeclarator declarator = extractDeclarator(node); if (node instanceof ICPPASTTemplateDeclaration) { declarator = extractDeclarator(((ICPPASTTemplateDeclaration) node).getDeclaration()); } if (declarator != null) { return declarator; } node = node.getParent(); } return null; } private IASTFunctionDeclarator extractDeclarator(IASTNode node) { if (node instanceof ICPPASTTemplateDeclaration) { node = ((ICPPASTTemplateDeclaration) node).getDeclaration(); } if (node instanceof IASTFunctionDeclarator) { return (IASTFunctionDeclarator) node; } if (node instanceof IASTFunctionDefinition) { return ((IASTFunctionDefinition) node).getDeclarator(); } if (node instanceof IASTSimpleDeclaration) { IASTDeclarator[] declarators = ((IASTSimpleDeclaration) node).getDeclarators(); if (declarators.length > 1) { throw new NotSupportedException(Messages.DeclaratorFinder_MultipleDeclarators); } if (declarators.length == 1 && declarators[0] instanceof IASTFunctionDeclarator) return (IASTFunctionDeclarator) declarators[0]; } return null; } private boolean isPartOfAStatement(IASTNode node) { return ToggleNodeHelper.getAncestorOfType(node, IASTStatement.class) != null; } }