/*******************************************************************************
* 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
******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.togglefunction;
import java.util.List;
import org.eclipse.text.edits.TextEditGroup;
import org.eclipse.cdt.core.dom.ast.IASTComment;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNode.CopyStyle;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionWithTryBlock;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
import org.eclipse.cdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.cdt.core.dom.rewrite.ASTRewrite.CommentPosition;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTSimpleDeclaration;
import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector;
public class ToggleFromInHeaderToClassStrategy implements IToggleRefactoringStrategy {
private TextEditGroup infoText;
private ToggleRefactoringContext context;
public ToggleFromInHeaderToClassStrategy(ToggleRefactoringContext context) {
if (isFreeFunction(context))
throw new NotSupportedException(Messages.ToggleFromInHeaderToClassStrategy_CanNotToggleTemplateFreeFunction);
this.context = context;
this.infoText = new TextEditGroup(Messages.EditGroupName);
}
private boolean isFreeFunction(ToggleRefactoringContext context) {
return isNotInsideAClass(context.getDefinition().getDeclarator(),
context.getDeclaration());
}
boolean isNotInsideAClass(IASTFunctionDeclarator declarator, IASTFunctionDeclarator backup) {
if (declarator.getName() instanceof ICPPASTQualifiedName) {
declarator = backup;
}
return (ASTQueries.findAncestorWithType(declarator, IASTCompositeTypeSpecifier.class) == null);
}
@Override
public void run(ModificationCollector modifications) {
ASTRewrite rewriter = removeDefinition(modifications);
IASTFunctionDefinition newDefinition = getNewDefinition();
replaceDeclarationWithDefinition(rewriter, newDefinition);
IASTNode parentTemplateDeclaration =
ToggleNodeHelper.getParentTemplateDeclaration(context.getDeclaration());
if (!(parentTemplateDeclaration instanceof ICPPASTTemplateDeclaration)) {
restoreLeadingComments(rewriter, newDefinition);
}
}
private void restoreLeadingComments(ASTRewrite rewriter, IASTFunctionDefinition newDefinition) {
List<IASTComment>comments = rewriter.getComments(context.getDefinition().getParent(), CommentPosition.leading);
if(comments != null) {
for (IASTComment comment : comments) {
rewriter.addComment(newDefinition, comment, CommentPosition.leading);
rewriter.remove(comment, infoText);
}
}
}
private ASTRewrite removeDefinition(ModificationCollector modifications) {
ASTRewrite rewriter = modifications.rewriterForTranslationUnit(context.getDefinitionAST());
IASTNode parentRemovePoint = ToggleNodeHelper.getParentRemovePoint(context.getDefinition());
rewriter.remove(parentRemovePoint, infoText);
return rewriter;
}
private IASTFunctionDefinition getNewDefinition() {
IASTFunctionDefinition newDefinition = ToggleNodeHelper.createInClassDefinition(
context.getDeclaration(), context.getDefinition(), context.getDefinitionAST());
newDefinition.setBody(context.getDefinition().getBody().copy(CopyStyle.withLocations));
if (newDefinition instanceof ICPPASTFunctionWithTryBlock) {
ICPPASTFunctionWithTryBlock newTryFun = (ICPPASTFunctionWithTryBlock) newDefinition;
ICPPASTFunctionWithTryBlock oldTryFun = (ICPPASTFunctionWithTryBlock) context.getDefinition();
for (ICPPASTCatchHandler catchH : oldTryFun.getCatchHandlers()) {
newTryFun.addCatchHandler(catchH.copy(CopyStyle.withLocations));
}
}
IASTNode parent = ASTQueries.findAncestorWithType(context.getDefinition(), ICPPASTCompositeTypeSpecifier.class);
if (parent != null) {
newDefinition.setParent(parent);
} else {
newDefinition.setParent(context.getDefinitionAST());
}
return newDefinition;
}
private ASTRewrite replaceDeclarationWithDefinition(ASTRewrite rewriter,
IASTFunctionDefinition newDefinition) {
IASTSimpleDeclaration fullDeclaration = ASTQueries.findAncestorWithType(context.getDeclaration(), CPPASTSimpleDeclaration.class);
ASTRewrite newRewriter = rewriter.replace(fullDeclaration, newDefinition, infoText);
return newRewriter;
}
}