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

Bug 399931 - Fix for toggling functions with return type from context.

Change-Id: I188d851500c4464d12977c82805679eee31663f2
Signed-off-by: Thomas Corbat <tcorbat@hsr.ch>
This commit is contained in:
Thomas Corbat 2015-04-23 08:34:26 +02:00
parent d997a7c313
commit ed3e9cf973
7 changed files with 489 additions and 60 deletions

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2006, 2014 IBM Corporation and others. * Copyright (c) 2006, 2015 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -157,6 +157,9 @@ public interface INodeFactory {
public IASTName newName(char[] name); public IASTName newName(char[] name);
/** @since 5.11 */
public IASTName newName(String name);
public IASTNullStatement newNullStatement(); public IASTNullStatement newNullStatement();
public IASTParameterDeclaration newParameterDeclaration(IASTDeclSpecifier declSpec, IASTDeclarator declarator); public IASTParameterDeclaration newParameterDeclaration(IASTDeclSpecifier declSpec, IASTDeclarator declarator);

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2006, 2014 IBM Corporation and others. * Copyright (c) 2006, 2015 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -278,6 +278,14 @@ public interface ICPPNodeFactory extends INodeFactory {
@Deprecated @Deprecated
public ICPPASTQualifiedName newQualifiedName(); public ICPPASTQualifiedName newQualifiedName();
/**
* Creates an {@link ICPPASTQualifiedName} and adds name qualifiers for the
* elements of {@code nameQualifiers}. {@code nameQualifiers} cannot contain decltype specifiers
* for creation of {@link ICPPASTDecltypeSpecifier}.
* @since 5.11
*/
public ICPPASTQualifiedName newQualifiedName(String[] nameQualifiers, String name);
/** /**
* @since 5.9 * @since 5.9
*/ */
@ -290,6 +298,11 @@ public interface ICPPNodeFactory extends INodeFactory {
@Override @Override
public ICPPASTName newName(char[] name); public ICPPASTName newName(char[] name);
/**
* @since 5.11
*/
public ICPPASTNamedTypeSpecifier newNamedTypeSpecifier(IASTName name);
/** /**
* Creates a range based for statement. * Creates a range based for statement.
* @since 5.3 * @since 5.3

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2006, 2014 IBM Corporation and others. * Copyright (c) 2006, 2015 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -365,6 +365,11 @@ public class CNodeFactory extends NodeFactory implements ICNodeFactory {
return new CASTName(name); return new CASTName(name);
} }
@Override
public IASTName newName(String name) {
return newName(name.toCharArray());
}
@Override @Override
public IASTNullStatement newNullStatement() { public IASTNullStatement newNullStatement() {
return new CASTNullStatement(); return new CASTNullStatement();

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2006, 2014 IBM Corporation and others. * Copyright (c) 2006, 2015 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -519,6 +519,16 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory {
return new CPPASTName(name); return new CPPASTName(name);
} }
@Override
public ICPPASTName newName(String name) {
return newName(name.toCharArray());
}
@Override
public ICPPASTNamedTypeSpecifier newNamedTypeSpecifier(IASTName name) {
return new CPPASTNamedTypeSpecifier(name);
}
@Override @Override
public ICPPASTNamespaceAlias newNamespaceAlias(IASTName alias, IASTName qualifiedName) { public ICPPASTNamespaceAlias newNamespaceAlias(IASTName alias, IASTName qualifiedName) {
return new CPPASTNamespaceAlias(alias, qualifiedName); return new CPPASTNamespaceAlias(alias, qualifiedName);
@ -621,6 +631,15 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory {
return new CPPASTQualifiedName(); return new CPPASTQualifiedName();
} }
@Override
public ICPPASTQualifiedName newQualifiedName(String[] nameQualifiers, String name) {
ICPPASTQualifiedName qualifiedName = newQualifiedName(newName(name));
for (String qualifier : nameQualifiers) {
qualifiedName.addNameSpecifier(newName(qualifier));
}
return qualifiedName;
}
@Override @Override
public ICPPASTRangeBasedForStatement newRangeBasedForStatement() { public ICPPASTRangeBasedForStatement newRangeBasedForStatement() {
return new CPPASTRangeBasedForStatement(); return new CPPASTRangeBasedForStatement();

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2008 Institute for Software, HSR Hochschule fuer Technik * Copyright (c) 2008, 2015 Institute for Software, HSR Hochschule fuer Technik
* Rapperswil, University of applied sciences and others * Rapperswil, University of applied sciences and others
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
@ -8,9 +8,11 @@
* *
* Contributors: * Contributors:
* Institute for Software - initial API and implementation * Institute for Software - initial API and implementation
* Thomas Corbat (IFS)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.rewrite.astwriter; package org.eclipse.cdt.internal.core.dom.rewrite.astwriter;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IBinding;
@ -80,11 +82,15 @@ public class NameWriter extends NodeWriter {
private boolean needsTemplateQualifier(ICPPASTTemplateId templId){ private boolean needsTemplateQualifier(ICPPASTTemplateId templId){
if (templId.getParent() instanceof ICPPASTQualifiedName) { if (templId.getParent() instanceof ICPPASTQualifiedName) {
ICPPASTQualifiedName qName = (ICPPASTQualifiedName) templId.getParent(); ICPPASTQualifiedName qName = (ICPPASTQualifiedName) templId.getParent();
return isDependentName(qName, templId); return !isPartOfFunctionDeclarator(qName) && isDependentName(qName, templId);
} }
return false; return false;
} }
private boolean isPartOfFunctionDeclarator(ICPPASTQualifiedName qName) {
return qName.getParent() instanceof IASTFunctionDeclarator;
}
private boolean isDependentName(ICPPASTQualifiedName qname, ICPPASTTemplateId tempId) { private boolean isDependentName(ICPPASTQualifiedName qname, ICPPASTTemplateId tempId) {
ICPPASTNameSpecifier[] segments = qname.getAllSegments(); ICPPASTNameSpecifier[] segments = qname.getAllSegments();
for (int i = 0; i < segments.length; ++i){ for (int i = 0; i < segments.length; ++i){

View file

@ -3273,4 +3273,282 @@ public class ToggleRefactoringTest extends RefactoringTestBase {
public void testToggleFunctionFailsOnSyntaxError_389299() throws Exception { public void testToggleFunctionFailsOnSyntaxError_389299() throws Exception {
assertRefactoringFailure(); assertRefactoringFailure();
} }
//A.h
//class test
//{
// typedef int M;
//public:
// M /*$*/f/*$$*/(){
// return 1;
// }
//};
//====================
//class test
//{
// typedef int M;
//public:
// M f();
//};
//
//inline test::M test::f() {
// return 1;
//}
public void testToggleFunctionWithScopedTypedefReturntype_399931() throws Exception {
assertRefactoringSuccess();
}
//A.h
//template<typename T1, typename T2>
//class Tpl {
// typedef T1 M;
//public:
// M /*$*/f/*$$*/(){
// return M();
// }
//};
//====================
//template<typename T1, typename T2>
//class Tpl {
// typedef T1 M;
//public:
// M f();
//};
//
//template<typename T1, typename T2>
//inline typename Tpl<T1, T2>::M Tpl<T1, T2>::f() {
// return M();
//}
public void testToggleFunctionWithScopedTypedefReturntypeFromTemplate_399931() throws Exception {
assertRefactoringSuccess();
}
//A.h
//template<typename TOuter>
//struct TplOuter {
// template<typename TInner>
// struct TplInner {
// typedef TInner R;
// R /*$*/f/*$$*/(){
// return R();
// }
// };
//};
//====================
//template<typename TOuter>
//struct TplOuter {
// template<typename TInner>
// struct TplInner {
// typedef TInner R;
// R f();
// };
//};
//
//template<typename TOuter>
//template<typename TInner>
//inline typename TplOuter<TOuter>::template TplInner<TInner>::R TplOuter<TOuter>::TplInner<
// TInner>::f() {
// return R();
//}
public void testToggleFunctionFromNestedTemplate_399931() throws Exception {
assertRefactoringSuccess();
}
//A.h
//template<typename Item>
//struct Bag {
// Bag /*$*/create/*$$*/(){
// return Bag();
// }
//};
//====================
//template<typename Item>
//struct Bag {
// Bag create();
//};
//
//template<typename Item>
//inline Bag<Item> Bag<Item>::create() {
// return Bag();
//}
public void testToggleFunctionWithTemplateReturnType_399931() throws Exception {
assertRefactoringSuccess();
}
//A.h
//template<typename Item>
//struct Bag {
//};
//
//template<typename Item>
//struct Bag<Item*> {
// Bag /*$*/create/*$$*/() {
// return Bag();
// }
//};
//====================
//template<typename Item>
//struct Bag {
//};
//
//template<typename Item>
//struct Bag<Item*> {
// Bag create();
//};
//
//template<typename Item>
//inline Bag<Item*> Bag<Item*>::create() {
// return Bag();
//}
public void testToggleMemberFunctionOfPartialSpecialization_399931() throws Exception {
assertRefactoringSuccess();
}
//A.h
//template<typename Item, typename T>
//struct Bag {
//};
//
//template<typename Item>
//struct Bag<Item*, int> {
// Bag /*$*/create/*$$*/() {
// return Bag();
// }
//};
//====================
//template<typename Item, typename T>
//struct Bag {
//};
//
//template<typename Item>
//struct Bag<Item*, int> {
// Bag create();
//};
//
//template<typename Item>
//inline Bag<Item*, int> Bag<Item*, int>::create() {
// return Bag();
//}
public void testToggleMemberFunctionOfPartialSpecializationWithTwoParameters_399931() throws Exception {
assertRefactoringSuccess();
}
//A.h
//template<typename Item, typename T>
//struct Bag {
//};
//
//template<typename Item>
//struct Bag<Item**, int**> {
// Bag /*$*/create/*$$*/() {
// return Bag();
// }
//};
//====================
//template<typename Item, typename T>
//struct Bag {
//};
//
//template<typename Item>
//struct Bag<Item**, int**> {
// Bag create();
//};
//
//template<typename Item>
//inline Bag<Item**, int**> Bag<Item**, int**>::create() {
// return Bag();
//}
public void testToggleMemberFunctionOfPartialSpecializationMultiplePointers_399931() throws Exception {
assertRefactoringSuccess();
}
//A.h
//template<typename Item>
//struct Bag {
//};
//
//template<>
//struct Bag<int> {
// Bag /*$*/create/*$$*/() {
// return Bag();
// }
//};
//====================
//template<typename Item>
//struct Bag {
//};
//
//template<>
//struct Bag<int> {
// Bag create();
//};
//
//inline Bag<int> Bag<int>::create() {
// return Bag();
//}
public void testToggleMemberFunctionOfFullSpecialization_399931() throws Exception {
assertRefactoringSuccess();
}
//A.h
//template<typename R>
//struct Qualifier {
// typedef R ReturnType;
//};
//
//template<typename T>
//struct ToggleType {
// typename Qualifier<int>::ReturnType /*$*/create/*$$*/() {
// return typename Qualifier<int>::ReturnType();
//}
//};
//====================
//template<typename R>
//struct Qualifier {
// typedef R ReturnType;
//};
//
//template<typename T>
//struct ToggleType {
// typename Qualifier<int>::ReturnType create();
//};
//
//template<typename T>
//inline typename Qualifier<int>::ReturnType ToggleType<T>::create() {
// return typename Qualifier<int>::ReturnType();
//}
public void testToggleWithTemplateQualifierInReturnType_399931() throws Exception {
assertRefactoringSuccess();
}
//A.h
//template<typename R>
//struct Qualifier {
// typedef R ReturnType;
//};
//
//template<typename T>
//struct ToggleType {
// typename Qualifier<T>::ReturnType /*$*/create/*$$*/() {
// return typename Qualifier<T>::ReturnType();
//}
//};
//====================
//template<typename R>
//struct Qualifier {
// typedef R ReturnType;
//};
//
//template<typename T>
//struct ToggleType {
// typename Qualifier<T>::ReturnType create();
//};
//
//template<typename T>
//inline typename Qualifier<T>::ReturnType ToggleType<T>::create() {
// return typename Qualifier<T>::ReturnType();
//}
public void testToggleWithTemplateArgumentDependentQualifierInReturnType_399931() throws Exception {
assertRefactoringSuccess();
}
} }

View file

@ -14,10 +14,13 @@
package org.eclipse.cdt.internal.ui.refactoring.togglefunction; package org.eclipse.cdt.internal.ui.refactoring.togglefunction;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.ListIterator;
import java.util.Stack; import java.util.Stack;
import org.eclipse.cdt.core.dom.ast.ASTNodeFactoryFactory;
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTComment; import org.eclipse.cdt.core.dom.ast.IASTComment;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
@ -31,34 +34,43 @@ import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTStandardFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTStandardFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionWithTryBlock; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionWithTryBlock;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNameSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypeId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNodeFactory;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.rewrite.ASTRewrite; import org.eclipse.cdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.cdt.core.dom.rewrite.ASTRewrite.CommentPosition; import org.eclipse.cdt.core.dom.rewrite.ASTRewrite.CommentPosition;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTCompoundStatement;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFunctionDefinition;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFunctionWithTryBlock;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNamedTypeSpecifier;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTQualifiedName;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTSimpleDeclaration;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTemplateId;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTypeId;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
import org.eclipse.cdt.internal.core.dom.rewrite.DeclarationGeneratorImpl;
import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector; import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector;
import org.eclipse.cdt.internal.ui.refactoring.utils.NodeHelper; import org.eclipse.cdt.internal.ui.refactoring.utils.NodeHelper;
public class ToggleNodeHelper extends NodeHelper { public class ToggleNodeHelper extends NodeHelper {
private static final String EMPTY_STRING = ""; //$NON-NLS-1$ private static final String EMPTY_STRING = ""; //$NON-NLS-1$
private static final ICPPNodeFactory factory = ASTNodeFactoryFactory.getDefaultCPPNodeFactory();
private static void removeParameterInitializations(IASTFunctionDeclarator funcDecl) { private static void removeParameterInitializations(IASTFunctionDeclarator funcDecl) {
for (IASTNode child : funcDecl.getChildren()) { for (IASTNode child : funcDecl.getChildren()) {
@ -84,7 +96,7 @@ public class ToggleNodeHelper extends NodeHelper {
static IASTSimpleDeclaration createDeclarationFromDefinition(IASTFunctionDefinition oldDefinition) { static IASTSimpleDeclaration createDeclarationFromDefinition(IASTFunctionDefinition oldDefinition) {
IASTDeclarator newDeclarator = oldDefinition.getDeclarator().copy(CopyStyle.withLocations); IASTDeclarator newDeclarator = oldDefinition.getDeclarator().copy(CopyStyle.withLocations);
IASTDeclSpecifier newDeclSpec = oldDefinition.getDeclSpecifier().copy(CopyStyle.withLocations); IASTDeclSpecifier newDeclSpec = oldDefinition.getDeclSpecifier().copy(CopyStyle.withLocations);
IASTSimpleDeclaration newDeclaration = new CPPASTSimpleDeclaration(newDeclSpec); IASTSimpleDeclaration newDeclaration = factory.newSimpleDeclaration(newDeclSpec);
newDeclaration.addDeclarator(newDeclarator); newDeclaration.addDeclarator(newDeclarator);
return newDeclaration; return newDeclaration;
} }
@ -95,11 +107,9 @@ public class ToggleNodeHelper extends NodeHelper {
ICPPASTFunctionDefinition newFunc = null; ICPPASTFunctionDefinition newFunc = null;
newFuncDecl = adjustParamNames(newFuncDecl, oldDefinition); newFuncDecl = adjustParamNames(newFuncDecl, oldDefinition);
if (oldDefinition instanceof ICPPASTFunctionWithTryBlock) { if (oldDefinition instanceof ICPPASTFunctionWithTryBlock) {
newFunc = new CPPASTFunctionWithTryBlock(newDeclSpec, newFuncDecl, newFunc = factory.newFunctionTryBlock(newDeclSpec, newFuncDecl, factory.newCompoundStatement());
new CPPASTCompoundStatement());
} else { } else {
newFunc = new CPPASTFunctionDefinition(newDeclSpec, newFuncDecl, newFunc = factory.newFunctionDefinition(newDeclSpec, newFuncDecl, factory.newCompoundStatement());
new CPPASTCompoundStatement());
} }
copyInitializerList(newFunc, oldDefinition); copyInitializerList(newFunc, oldDefinition);
return newFunc; return newFunc;
@ -127,49 +137,146 @@ public class ToggleNodeHelper extends NodeHelper {
static IASTFunctionDefinition getQualifiedNameDefinition(IASTFunctionDefinition oldDefinition, static IASTFunctionDefinition getQualifiedNameDefinition(IASTFunctionDefinition oldDefinition,
IASTTranslationUnit definitionUnit, IASTNode nameSpace) { IASTTranslationUnit definitionUnit, IASTNode nameSpace) {
ICPPASTDeclSpecifier newDeclSpecifier = createDeclSpecifier(oldDefinition);
ICPPASTDeclSpecifier newDeclSpec =
(ICPPASTDeclSpecifier) oldDefinition.getDeclSpecifier().copy(CopyStyle.withLocations);
newDeclSpec.setVirtual(false);
newDeclSpec.setInline(true);
newDeclSpec.setStorageClass(IASTDeclSpecifier.sc_unspecified);
IASTFunctionDeclarator newDeclarator = oldDefinition.getDeclarator().copy(CopyStyle.withLocations); IASTFunctionDeclarator newDeclarator = oldDefinition.getDeclarator().copy(CopyStyle.withLocations);
newDeclarator.setName(getQualifiedName(oldDefinition.getDeclarator(), nameSpace)); newDeclarator.setName(getQualifiedName(oldDefinition.getDeclarator(), nameSpace));
removeParameterInitializations(newDeclarator); removeParameterInitializations(newDeclarator);
ICPPASTFunctionDefinition newFunction = ICPPASTFunctionDefinition newFunction =
createFunctionSignatureWithEmptyBody(newDeclSpec, newDeclarator, oldDefinition); createFunctionSignatureWithEmptyBody(newDeclSpecifier, newDeclarator, oldDefinition);
return newFunction; return newFunction;
} }
private static ICPPASTDeclSpecifier createDeclSpecifier(IASTFunctionDefinition oldDefinition) {
IASTDeclSpecifier originalDeclSpecifier = oldDefinition.getDeclSpecifier();
ICPPASTDeclSpecifier newDeclSpecifier = (ICPPASTDeclSpecifier) originalDeclSpecifier.copy(CopyStyle.withLocations);
if (newDeclSpecifier instanceof ICPPASTNamedTypeSpecifier) {
ICPPASTNamedTypeSpecifier newNamedTypeSpecifier = (ICPPASTNamedTypeSpecifier) newDeclSpecifier;
IASTName typename = ((ICPPASTNamedTypeSpecifier) originalDeclSpecifier).getName();
IBinding typenameBinding = typename.resolveBinding();
adaptTemplateQualifiers(newNamedTypeSpecifier, typenameBinding);
}
newDeclSpecifier.setVirtual(false);
newDeclSpecifier.setInline(true);
newDeclSpecifier.setStorageClass(IASTDeclSpecifier.sc_unspecified);
return newDeclSpecifier;
}
private static void adaptTemplateQualifiers(ICPPASTNamedTypeSpecifier newDeclSpecifier,
IBinding typenameBinding) {
if (typenameBinding instanceof ICPPBinding) {
try {
String[] nameParts = ((ICPPBinding) typenameBinding).getQualifiedName();
String qualifiedName = typenameBinding.getName();
String[] nameQualifiers = Arrays.copyOf(nameParts, nameParts.length - 1);
ICPPASTQualifiedName qualifiedTypeName = factory.newQualifiedName(nameQualifiers, qualifiedName);
if (typenameBinding instanceof ICPPTemplateInstance) {
ICPPTemplateInstance templateInstance = (ICPPTemplateInstance) typenameBinding;
ICPPTemplateArgument[] templateArguments = templateInstance.getTemplateArguments();
IASTName lastName = qualifiedTypeName.getLastName();
ICPPASTTemplateId newTemplateId = createTemplateIdForArguments(lastName, templateArguments);
qualifiedTypeName.setLastName(newTemplateId);
}
boolean setTypename = adaptQualifiers(typenameBinding, qualifiedTypeName);
newDeclSpecifier.setName(qualifiedTypeName);
newDeclSpecifier.setIsTypename(setTypename);
} catch (DOMException e) {
CUIPlugin.log(e);
}
}
}
private static boolean adaptQualifiers(IBinding typenameBinding, ICPPASTQualifiedName qualifiedTypeName) {
boolean setTypename = false;
IBinding owner = typenameBinding.getOwner();
ICPPASTNameSpecifier[] qualifiers = qualifiedTypeName.getQualifier();
if (qualifiers.length > 0) {
int level = qualifiers.length - 1;
while (owner != null && level >= 0) {
IASTName qualifierName = (IASTName) qualifiers[level];
ICPPASTTemplateId newTemplateId = createTemplateIdForQualifier(qualifierName, owner);
if (newTemplateId != null) {
qualifiers[level] = newTemplateId;
newTemplateId.setParent(qualifiedTypeName);
setTypename = true;
}
owner = owner.getOwner();
level--;
}
}
return setTypename;
}
private static ICPPASTTemplateId createTemplateIdForQualifier(IASTName qualifierName, IBinding templateBinding) {
ICPPASTTemplateId newTemplateId = null;
if (templateBinding instanceof ICPPClassTemplate) {
ICPPClassTemplate classTemplateBinding = (ICPPClassTemplate) templateBinding;
newTemplateId = createTemplateId(qualifierName, classTemplateBinding);
} else if (templateBinding instanceof ICPPTemplateInstance) {
ICPPTemplateInstance instanceBinding = (ICPPTemplateInstance) templateBinding;
ICPPTemplateArgument[] templateArguments = instanceBinding.getTemplateArguments();
newTemplateId = createTemplateIdForArguments(qualifierName, templateArguments);
}
return newTemplateId;
}
private static ICPPASTTemplateId createTemplateIdForArguments(IASTName qualifierName, ICPPTemplateArgument[] templateArguments) {
ICPPASTTemplateId newTemplateId = factory.newTemplateId(qualifierName);
for (ICPPTemplateArgument templateArgument : templateArguments) {
IType type = templateArgument.getOriginalTypeValue();
DeclarationGeneratorImpl declarationGeneratorImpl = new DeclarationGeneratorImpl(factory);
IASTDeclarator abstractDeclarator = declarationGeneratorImpl.createDeclaratorFromType(type, EMPTY_STRING.toCharArray());
IType ultimateType = SemanticUtil.getUltimateType(type, false);
IASTName templateParameterName = factory.newName(ASTTypeUtil.getType(ultimateType, false));
ICPPASTNamedTypeSpecifier typeSpecifier = factory.newNamedTypeSpecifier(templateParameterName);
ICPPASTTypeId newTypeId = factory.newTypeId(typeSpecifier, abstractDeclarator);
newTemplateId.addTemplateArgument(newTypeId);
}
return newTemplateId;
}
private static ICPPASTTemplateId createTemplateId(IASTName qualifierName, ICPPClassTemplate ownerBinding) {
ICPPASTTemplateId newTemplateId = factory.newTemplateId(qualifierName);
for (ICPPTemplateParameter templateParameter : ownerBinding.getTemplateParameters()) {
IASTName abstractDeclaratorName = factory.newName();
ICPPASTDeclarator abstractDeclarator = factory.newDeclarator(abstractDeclaratorName);
ICPPASTName templateParameterName = factory.newName(templateParameter.getNameCharArray());
ICPPASTNamedTypeSpecifier typeSpecifier = factory.newNamedTypeSpecifier(templateParameterName);
ICPPASTTypeId newTypeId = factory.newTypeId(typeSpecifier, abstractDeclarator);
newTemplateId.addTemplateArgument(newTypeId);
}
return newTemplateId;
}
public static ICPPASTTemplateDeclaration getTemplateDeclaration( public static ICPPASTTemplateDeclaration getTemplateDeclaration(
IASTFunctionDefinition oldFunction, IASTFunctionDefinition newFunction) { IASTFunctionDefinition oldFunction, IASTFunctionDefinition newFunction) {
ArrayList<ICPPASTTemplateDeclaration> templateDeclarations = getAllTemplateDeclaration(oldFunction); ArrayList<ICPPASTTemplateDeclaration> templateDeclarations = getAllTemplateDeclarations(oldFunction);
return addTemplateDeclarationsInOrder(templateDeclarations, newFunction); return addTemplateDeclarationsInOrder(templateDeclarations, newFunction);
} }
private static ICPPASTTemplateDeclaration addTemplateDeclarationsInOrder( private static ICPPASTTemplateDeclaration addTemplateDeclarationsInOrder(
ArrayList<ICPPASTTemplateDeclaration> templDecs, IASTFunctionDefinition newFunction) { ArrayList<ICPPASTTemplateDeclaration> templDecs, IASTFunctionDefinition newFunction) {
ListIterator<ICPPASTTemplateDeclaration> iter1 = templDecs.listIterator();
ICPPASTTemplateDeclaration child = null; ICPPASTTemplateDeclaration child = null;
while (iter1.hasNext()) { for (ICPPASTTemplateDeclaration templateDeclaration : templDecs) {
child = iter1.next(); if (templateDeclaration.getTemplateParameters().length == 0) {
continue;
}
if (child == null) {
child = templateDeclaration;
child.setDeclaration(newFunction); child.setDeclaration(newFunction);
ListIterator<ICPPASTTemplateDeclaration> iter2 = iter1; } else {
if (iter2.hasNext()) { templateDeclaration.setDeclaration(child);
ICPPASTTemplateDeclaration parent = iter2.next(); child.setParent(templateDeclaration);
child.setParent(parent); child = templateDeclaration;
parent.setDeclaration(child);
child = parent;
} }
} }
return child; return child;
} }
private static ArrayList<ICPPASTTemplateDeclaration> getAllTemplateDeclaration(IASTNode node) { private static ArrayList<ICPPASTTemplateDeclaration> getAllTemplateDeclarations(IASTNode node) {
ArrayList<ICPPASTTemplateDeclaration> templdecs = new ArrayList<ICPPASTTemplateDeclaration>(); ArrayList<ICPPASTTemplateDeclaration> templdecs = new ArrayList<ICPPASTTemplateDeclaration>();
while (node.getParent() != null) { while (node.getParent() != null) {
node = node.getParent(); node = node.getParent();
@ -226,13 +333,13 @@ public class ToggleNodeHelper extends NodeHelper {
*/ */
static ICPPASTQualifiedName getQualifiedName(IASTFunctionDeclarator declarator, IASTNode limiter) { static ICPPASTQualifiedName getQualifiedName(IASTFunctionDeclarator declarator, IASTNode limiter) {
Stack<IASTNode> nodes = getQualifiedNames(declarator, limiter, declarator); Stack<IASTNode> nodes = getQualifiedNames(declarator, limiter, declarator);
CPPASTQualifiedName qName = reAssembleQualifiedName(nodes); ICPPASTQualifiedName qName = reAssembleQualifiedName(nodes);
qName.addName(declarator.getName().copy(CopyStyle.withLocations)); qName.addName(declarator.getName().copy(CopyStyle.withLocations));
return qName; return qName;
} }
private static CPPASTQualifiedName reAssembleQualifiedName(Stack<IASTNode> nodes) { private static ICPPASTQualifiedName reAssembleQualifiedName(Stack<IASTNode> nodes) {
CPPASTQualifiedName qName = new CPPASTQualifiedName(); ICPPASTQualifiedName qName = factory.newQualifiedName(null);
while (!nodes.isEmpty()) { while (!nodes.isEmpty()) {
IASTNode nnode = nodes.pop(); IASTNode nnode = nodes.pop();
if (nnode instanceof IASTCompositeTypeSpecifier) { if (nnode instanceof IASTCompositeTypeSpecifier) {
@ -258,10 +365,10 @@ public class ToggleNodeHelper extends NodeHelper {
} else if (node instanceof ICPPASTNamespaceDefinition) { } else if (node instanceof ICPPASTNamespaceDefinition) {
nodes.push(((ICPPASTNamespaceDefinition) node).copy(CopyStyle.withLocations)); nodes.push(((ICPPASTNamespaceDefinition) node).copy(CopyStyle.withLocations));
lastName = ((ICPPASTNamespaceDefinition) node).getName(); lastName = ((ICPPASTNamespaceDefinition) node).getName();
} else if (shouldAddTemplateBrackets(node)) { } else if (!(lastName instanceof ICPPASTTemplateId) && shouldAddTemplateBrackets(node)) {
if (!nodes.isEmpty()) if (!nodes.isEmpty())
nodes.pop(); nodes.pop();
ICPPASTTemplateId templateID = ToggleNodeHelper.getTemplateParameter(node, lastName); ICPPASTTemplateId templateID = getTemplateParameter(node, lastName);
nodes.add(templateID); nodes.add(templateID);
} }
} }
@ -271,21 +378,19 @@ public class ToggleNodeHelper extends NodeHelper {
private static boolean shouldAddTemplateBrackets(IASTNode node) { private static boolean shouldAddTemplateBrackets(IASTNode node) {
return node instanceof ICPPASTTemplateDeclaration return node instanceof ICPPASTTemplateDeclaration
&& !(((ICPPASTTemplateDeclaration) node).getDeclaration() && !(((ICPPASTTemplateDeclaration) node).getDeclaration()
instanceof CPPASTFunctionDefinition); instanceof ICPPASTFunctionDefinition);
} }
private static ICPPASTTemplateId getTemplateParameter(IASTNode node, IASTName name) { private static ICPPASTTemplateId getTemplateParameter(IASTNode node, IASTName name) {
ICPPASTTemplateId templateID = new CPPASTTemplateId(); ICPPASTTemplateId templateID = factory.newTemplateId(name.copy(CopyStyle.withLocations));
templateID.setTemplateName(name.copy(CopyStyle.withLocations));
for (IASTNode child : node.getChildren()) { for (IASTNode child : node.getChildren()) {
if (child instanceof ICPPASTSimpleTypeTemplateParameter) { if (child instanceof ICPPASTSimpleTypeTemplateParameter) {
ICPPASTSimpleTypeTemplateParameter tempChild = (ICPPASTSimpleTypeTemplateParameter) child; ICPPASTSimpleTypeTemplateParameter tempChild = (ICPPASTSimpleTypeTemplateParameter) child;
CPPASTNamedTypeSpecifier namedTypeSpecifier = new CPPASTNamedTypeSpecifier(); IASTName argumentName = tempChild.getName().copy(CopyStyle.withLocations);
namedTypeSpecifier.setName(tempChild.getName().copy(CopyStyle.withLocations)); ICPPASTNamedTypeSpecifier namedTypeSpecifier = factory.newNamedTypeSpecifier(argumentName);
CPPASTTypeId id = new CPPASTTypeId(); ICPPASTTypeId id = factory.newTypeId(namedTypeSpecifier, null);
id.setDeclSpecifier(namedTypeSpecifier);
templateID.addTemplateArgument(id); templateID.addTemplateArgument(id);
} }
} }