1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-06 17:26:01 +02:00

Proper handling of visibility for extracted inline functions.

This commit is contained in:
sprigogin 2012-03-26 19:44:13 -04:00
parent c73b8c8a4a
commit 73337a5882
4 changed files with 176 additions and 98 deletions

View file

@ -48,6 +48,47 @@ import org.eclipse.cdt.internal.ui.refactoring.utils.VisibilityEnum;
* @author Mirko Stocker
*/
public class ClassMemberInserter {
public static class InsertionInfo {
private final IASTNode parentNode;
/**
* The node before which the new node should be inserted. A null value indicates insertion
* to the end of parentNode
*/
private IASTNode insertBeforeNode; //
/** Visibility label to insert before the new node or null. */
private ICPPASTVisibilityLabel prologue;
/** Visibility label to insert after the new node or null. */
private ICPPASTVisibilityLabel epilogue;
public InsertionInfo(IASTNode parentNode, IASTNode insertBeforeNode) {
this.parentNode = parentNode;
this.insertBeforeNode = insertBeforeNode;
}
public InsertionInfo(IASTNode parentNode) {
this(parentNode, null);
}
public IASTNode getParentNode() {
return parentNode;
}
public IASTNode getInsertBeforeNode() {
return insertBeforeNode;
}
public ICPPASTVisibilityLabel getPrologue() {
return prologue;
}
public ICPPASTVisibilityLabel getEpilogue() {
return epilogue;
}
}
// Not instantiatable. All methods are static.
private ClassMemberInserter() {
}
public static void createChange(ICPPASTCompositeTypeSpecifier classNode,
VisibilityEnum visibility, IASTNode nodeToAdd, boolean isField,
@ -58,7 +99,23 @@ public class ClassMemberInserter {
public static void createChange(ICPPASTCompositeTypeSpecifier classNode,
VisibilityEnum visibility, List<IASTNode> nodesToAdd, boolean isField,
ModificationCollector collector) {
InsertionInfo info = findInsertionPoint(classNode, visibility, isField);
nodesToAdd = new ArrayList<IASTNode>(nodesToAdd);
if (info.getPrologue() != null)
nodesToAdd.add(0, info.getPrologue());
if (info.getEpilogue() != null)
nodesToAdd.add(info.getEpilogue());
ASTRewrite rewrite = collector.rewriterForTranslationUnit(classNode.getTranslationUnit());
for (IASTNode node : nodesToAdd) {
rewrite.insertBefore(info.getParentNode(), info.getInsertBeforeNode(), node,
createEditDescription(classNode));
}
}
public static InsertionInfo findInsertionPoint(ICPPASTCompositeTypeSpecifier classNode,
VisibilityEnum visibility, boolean isField) {
InsertionInfo info = new InsertionInfo(classNode);
VisibilityEnum defaultVisibility = classNode.getKey() == IASTCompositeTypeSpecifier.k_struct ?
VisibilityEnum.v_public : VisibilityEnum.v_private;
VisibilityEnum currentVisibility = defaultVisibility;
@ -105,24 +162,19 @@ public class ClassMemberInserter {
if (index < 0)
index = lastPrecedingVisibilityIndex;
index++;
IASTNode nextNode = index < members.length ? members[index] : null;
if (index < members.length)
info.insertBeforeNode = members[index];
if (lastMatchingVisibilityIndex < 0 &&
!(index == 0 && classNode.getKey() == IASTCompositeTypeSpecifier.k_struct && visibility == defaultVisibility)) {
nodesToAdd.add(0, new CPPASTVisibilityLabel(visibility.getVisibilityLabelValue()));
if (index == 0 && nextNode != null && !(nextNode instanceof ICPPASTVisibilityLabel)) {
nodesToAdd.add(new CPPASTVisibilityLabel(defaultVisibility.getVisibilityLabelValue()));
!(index == 0 && classNode.getKey() == IASTCompositeTypeSpecifier.k_struct &&
visibility == defaultVisibility)) {
info.prologue = new CPPASTVisibilityLabel(visibility.getVisibilityLabelValue());
if (index == 0 && info.insertBeforeNode != null &&
!(info.insertBeforeNode instanceof ICPPASTVisibilityLabel)) {
info.epilogue = new CPPASTVisibilityLabel(defaultVisibility.getVisibilityLabelValue());
}
}
ASTRewrite rewrite = collector.rewriterForTranslationUnit(classNode.getTranslationUnit());
for (IASTNode node : nodesToAdd) {
rewrite.insertBefore(classNode, nextNode, node, createEditDescription(classNode));
}
}
// Not instantiatable. All methods are static.
private ClassMemberInserter() {
return info;
}
private static TextEditGroup createEditDescription(ICPPASTCompositeTypeSpecifier classNode) {

View file

@ -26,8 +26,8 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding;
/**
* Represents a function or method and adds some useful helper methods to
* determine if methods are in the same class.
* Represents a function or method and adds some useful helper methods to determine
* if two methods are in the same class.
*/
public class MethodContext {
public enum ContextType { NONE, FUNCTION, METHOD }

View file

@ -38,8 +38,8 @@ public class ExtractFunctionInformation {
private boolean virtual;
/**
* Returns the function declarator of the method / function from were the statements
* are extacted from.
* Returns the function declarator of the method or function from were the statements
* are extracted from.
* @return the function declarator or null
*/
public ICPPASTFunctionDeclarator getDeclarator() {

View file

@ -108,6 +108,7 @@ import org.eclipse.cdt.internal.core.dom.rewrite.astwriter.ASTWriterVisitor;
import org.eclipse.cdt.internal.ui.refactoring.CRefactoring;
import org.eclipse.cdt.internal.ui.refactoring.CRefactoringDescriptor;
import org.eclipse.cdt.internal.ui.refactoring.ClassMemberInserter;
import org.eclipse.cdt.internal.ui.refactoring.ClassMemberInserter.InsertionInfo;
import org.eclipse.cdt.internal.ui.refactoring.Container;
import org.eclipse.cdt.internal.ui.refactoring.MethodContext;
import org.eclipse.cdt.internal.ui.refactoring.MethodContext.ContextType;
@ -379,9 +380,10 @@ public class ExtractFunctionRefactoring extends CRefactoring {
}
private void createMethodDefinition(final IASTName methodName, MethodContext context,
IASTNode firstNode, ModificationCollector collector) {
IASTFunctionDefinition node = CPPVisitor.findAncestorWithType(firstNode, IASTFunctionDefinition.class);
if (node != null) {
IASTNode firstExtractedNode, ModificationCollector collector) {
IASTFunctionDefinition functionToExtractFrom =
CPPVisitor.findAncestorWithType(firstExtractedNode, IASTFunctionDefinition.class);
if (functionToExtractFrom != null) {
String title;
if (context.getType() == MethodContext.ContextType.METHOD) {
title = Messages.ExtractFunctionRefactoring_CreateMethodDef;
@ -389,8 +391,8 @@ public class ExtractFunctionRefactoring extends CRefactoring {
title = Messages.ExtractFunctionRefactoring_CreateFunctionDef;
}
ASTRewrite rewriter = collector.rewriterForTranslationUnit(node.getTranslationUnit());
addMethod(methodName, context, rewriter, node, new TextEditGroup(title));
ASTRewrite rewriter = collector.rewriterForTranslationUnit(functionToExtractFrom.getTranslationUnit());
addMethod(methodName, context, rewriter, functionToExtractFrom, new TextEditGroup(title));
}
}
@ -584,7 +586,7 @@ public class ExtractFunctionRefactoring extends CRefactoring {
}
private void addMethod(IASTName methodName, MethodContext context, ASTRewrite rewrite,
IASTNode insertPoint, TextEditGroup group) {
IASTNode functionToExtractFrom, TextEditGroup group) {
ICPPASTQualifiedName qname = new CPPASTQualifiedName();
if (context.getType() == ContextType.METHOD) {
if (context.getMethodQName() != null) {
@ -611,7 +613,8 @@ public class ExtractFunctionRefactoring extends CRefactoring {
func.setBody(compound);
ASTRewrite subRewrite;
IASTNode parent = insertPoint.getParent();
IASTNode parent = functionToExtractFrom.getParent();
IASTNode nodeToInsert = func;
if (parent instanceof ICPPASTTemplateDeclaration) {
ICPPASTTemplateDeclaration parentTemplate = (ICPPASTTemplateDeclaration) parent;
CPPASTTemplateDeclaration templateDeclaration = new CPPASTTemplateDeclaration();
@ -621,10 +624,33 @@ public class ExtractFunctionRefactoring extends CRefactoring {
templateDeclaration.addTemplateParameter(param.copy(CopyStyle.withLocations));
}
functionToExtractFrom = parentTemplate;
templateDeclaration.setDeclaration(func);
subRewrite = rewrite.insertBefore(parent.getParent(), parent, templateDeclaration, group);
nodeToInsert = templateDeclaration;
parent = parent.getParent();
}
InsertionInfo insertion;
if (parent instanceof ICPPASTCompositeTypeSpecifier) {
// Inserting into a class declaration
insertion = ClassMemberInserter.findInsertionPoint((ICPPASTCompositeTypeSpecifier) parent,
info.getVisibility(), false);
} else {
subRewrite = rewrite.insertBefore(parent, insertPoint, func, group);
// Inserting into a translation unit or a namespace.
// TODO(sprigogin): Use insertBeforeNode instead of functionToExtractFrom when creating InsertionInfo
// IASTNode insertBeforeNode = info.getMethodContext().getType() == ContextType.METHOD ?
// null : functionToExtractFrom;
insertion = new InsertionInfo(parent, functionToExtractFrom);
}
if (insertion.getPrologue() != null) {
rewrite.insertBefore(insertion.getParentNode(),
insertion.getInsertBeforeNode(), insertion.getPrologue(), group);
}
subRewrite = rewrite.insertBefore(insertion.getParentNode(),
insertion.getInsertBeforeNode(), nodeToInsert, group);
if (insertion.getEpilogue() != null) {
rewrite.insertBefore(insertion.getParentNode(),
insertion.getInsertBeforeNode(), insertion.getEpilogue(), group);
}
extractor.constructMethodBody(compound, container.getNodesToWrite(),