/*******************************************************************************
* Copyright (c) 2011, 2016 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
* Sergey Prigogin (Google)
******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.togglefunction;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jface.text.ITextSelection;
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.index.IIndex;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.CoreModelUtil;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
import org.eclipse.cdt.internal.corext.util.CModelUtil;
import org.eclipse.cdt.internal.ui.editor.SourceHeaderPartnerFinder;
import org.eclipse.cdt.internal.ui.refactoring.CRefactoringContext;
import org.eclipse.cdt.internal.ui.refactoring.IndexToASTNameHelper;
public class ToggleRefactoringContext {
private IASTFunctionDefinition targetDefinition;
private IASTFunctionDeclarator targetDeclaration;
private IASTTranslationUnit targetDefinitionAST;
private IASTTranslationUnit targetDeclarationAST;
private final CRefactoringContext refactoringContext;
private final IIndex index;
private final ITranslationUnit selectionTU;
private IASTTranslationUnit selectionAST;
private IBinding binding;
private IASTName selectionName;
private boolean defaultAnswer;
private boolean settedDefaultAnswer;
public ToggleRefactoringContext(CRefactoringContext refactoringContext, IIndex index,
ITranslationUnit translationUnit, ITextSelection selection)
throws OperationCanceledException, CoreException {
this.refactoringContext = refactoringContext;
this.index = index;
this.selectionTU = translationUnit;
findSelectionAST();
findSelectedFunctionDeclarator(selection);
findBinding();
findDeclaration();
findDefinition();
}
public void findSelectedFunctionDeclarator(ITextSelection selection) {
selectionName = new DeclaratorFinder(selection, selectionAST).getName();
}
public void findBinding() {
try {
binding = index.findBinding(selectionName);
if(binding == null) {
binding = selectionName.resolveBinding();
}
} catch (CoreException e) {
CUIPlugin.log(e);
}
}
// Declaration may still be null afterwards, but thats ok.
public void findDeclaration() {
try {
IIndexName[] decnames = index.findNames(binding, IIndex.FIND_DECLARATIONS);
if (decnames.length > 1)
throw new NotSupportedException(
Messages.ToggleRefactoringContext_MultipleDeclarations);
for (IIndexName iname : decnames) {
selectionAST = getASTForIndexName(iname);
IASTName astname = IndexToASTNameHelper.findMatchingASTName(
selectionAST, iname, index);
if (astname != null) {
targetDeclaration = findFunctionDeclarator(astname);
targetDeclarationAST = selectionAST;
break;
}
}
} catch (CoreException e) {
CUIPlugin.log(e);
}
}
public void findDefinition() {
try {
IIndexName[] defnames = index.findNames(binding, IIndex.FIND_DEFINITIONS);
if (defnames.length > 1) {
throw new NotSupportedException(Messages.ToggleRefactoringContext_MultipleDefinitions);
}
for (IIndexName iname : defnames) {
IASTTranslationUnit unit = getASTForIndexName(iname);
IASTName astname = IndexToASTNameHelper.findMatchingASTName(unit, iname, index);
if (astname != null) {
targetDefinition = findFunctionDefinition(astname);
targetDefinitionAST = unit;
break;
}
}
} catch (CoreException e) {
CUIPlugin.log(e);
}
if (targetDefinition == null)
throw new NotSupportedException(Messages.ToggleRefactoringContext_NoDefinitionFound);
}
public IASTFunctionDeclarator getDeclaration() {
return targetDeclaration;
}
public IASTFunctionDefinition getDefinition() {
return targetDefinition;
}
public IASTTranslationUnit getDeclarationAST() {
return targetDeclarationAST;
}
public IASTTranslationUnit getDefinitionAST() {
return targetDefinitionAST;
}
public ITranslationUnit getSelectionTU() {
return selectionTU;
}
public IFile getSelectionFile() {
return (IFile) selectionTU.getResource();
}
public IASTTranslationUnit getASTForPartnerFile() throws CoreException {
ITranslationUnit tu =
SourceHeaderPartnerFinder.getPartnerTranslationUnit(selectionTU, refactoringContext);
if (tu == null)
return null;
return refactoringContext.getAST(tu, null);
}
private void findSelectionAST() throws OperationCanceledException, CoreException {
selectionAST = refactoringContext.getAST(selectionTU, null);
if (selectionAST == null)
throw new NotSupportedException(Messages.ToggleRefactoringContext_NoTuFound);
}
private IASTTranslationUnit getASTForIndexName(IIndexName indexName)
throws CModelException, CoreException {
if (isSameFileAsInTU(indexName)) {
return selectionAST;
}
ITranslationUnit tu = CoreModelUtil.findTranslationUnitForLocation(
indexName.getFile().getLocation(), null);
if (tu == null)
return null;
return refactoringContext.getAST(tu, null);
}
private boolean isSameFileAsInTU(IIndexName indexName) {
return indexName.getFileLocation().getFileName().equals(
selectionAST.getFileLocation().getFileName());
}
private IASTFunctionDeclarator findFunctionDeclarator(IASTNode node) {
if (node instanceof IASTSimpleDeclaration) {
return (IASTFunctionDeclarator) ((IASTSimpleDeclaration) node).getDeclarators()[0];
}
return ASTQueries.findAncestorWithType(node, IASTFunctionDeclarator.class);
}
private IASTFunctionDefinition findFunctionDefinition(IASTNode node) {
return ASTQueries.findAncestorWithType(node, IASTFunctionDefinition.class);
}
public void setDefaultAnswer(boolean defaultAnswer) {
this.defaultAnswer = defaultAnswer;
}
public boolean getDefaultAnswer() {
return defaultAnswer;
}
public void setSettedDefaultAnswer(boolean settedDefaultAnswer) {
this.settedDefaultAnswer = settedDefaultAnswer;
}
public boolean isSettedDefaultAnswer() {
return settedDefaultAnswer;
}
public IASTTranslationUnit getAST(IFile file, IProgressMonitor pm)
throws OperationCanceledException, CoreException {
ITranslationUnit tu = CoreModelUtil.findTranslationUnit(file);
if (tu == null)
return null;
tu = CModelUtil.toWorkingCopy(tu);
return refactoringContext.getAST(tu, pm);
}
}