From ed3e9cf973d25a4e96a7b6b65ecaa2b597c173b9 Mon Sep 17 00:00:00 2001 From: Thomas Corbat Date: Thu, 23 Apr 2015 08:34:26 +0200 Subject: [PATCH] Bug 399931 - Fix for toggling functions with return type from context. Change-Id: I188d851500c4464d12977c82805679eee31663f2 Signed-off-by: Thomas Corbat --- .../org/eclipse/cdt/core/dom/ast/INodeFactory.java | 7 +- .../cdt/core/dom/ast/cpp/ICPPNodeFactory.java | 15 +- .../internal/core/dom/parser/c/CNodeFactory.java | 9 +- .../core/dom/parser/cpp/CPPNodeFactory.java | 21 +- .../core/dom/rewrite/astwriter/NameWriter.java | 12 +- .../togglefunction/ToggleRefactoringTest.java | 278 +++++++++++++++++++++ .../togglefunction/ToggleNodeHelper.java | 207 +++++++++++---- 7 files changed, 489 insertions(+), 60 deletions(-) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/INodeFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/INodeFactory.java index 4c72cb1..e41a6a5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/INodeFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/INodeFactory.java @@ -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 * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -156,7 +156,10 @@ public interface INodeFactory { public IASTName newName(); public IASTName newName(char[] name); - + + /** @since 5.11 */ + public IASTName newName(String name); + public IASTNullStatement newNullStatement(); public IASTParameterDeclaration newParameterDeclaration(IASTDeclSpecifier declSpec, IASTDeclarator declarator); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java index 8553b66..091b13e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java @@ -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 * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -279,6 +279,14 @@ public interface ICPPNodeFactory extends INodeFactory { 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 */ @Override @@ -291,6 +299,11 @@ public interface ICPPNodeFactory extends INodeFactory { public ICPPASTName newName(char[] name); /** + * @since 5.11 + */ + public ICPPASTNamedTypeSpecifier newNamedTypeSpecifier(IASTName name); + + /** * Creates a range based for statement. * @since 5.3 */ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CNodeFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CNodeFactory.java index f4f35db..681a1f3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CNodeFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CNodeFactory.java @@ -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 * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -364,7 +364,12 @@ public class CNodeFactory extends NodeFactory implements ICNodeFactory { public IASTName newName(char[] name) { return new CASTName(name); } - + + @Override + public IASTName newName(String name) { + return newName(name.toCharArray()); + } + @Override public IASTNullStatement newNullStatement() { return new CASTNullStatement(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java index 1c70b6c..34a62ea 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java @@ -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 * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -520,6 +520,16 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory { } @Override + public ICPPASTName newName(String name) { + return newName(name.toCharArray()); + } + + @Override + public ICPPASTNamedTypeSpecifier newNamedTypeSpecifier(IASTName name) { + return new CPPASTNamedTypeSpecifier(name); + } + + @Override public ICPPASTNamespaceAlias newNamespaceAlias(IASTName alias, IASTName qualifiedName) { return new CPPASTNamespaceAlias(alias, qualifiedName); } @@ -622,6 +632,15 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory { } @Override + public ICPPASTQualifiedName newQualifiedName(String[] nameQualifiers, String name) { + ICPPASTQualifiedName qualifiedName = newQualifiedName(newName(name)); + for (String qualifier : nameQualifiers) { + qualifiedName.addNameSpecifier(newName(qualifier)); + } + return qualifiedName; + } + + @Override public ICPPASTRangeBasedForStatement newRangeBasedForStatement() { return new CPPASTRangeBasedForStatement(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/NameWriter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/NameWriter.java index f66d337..a8a86aa 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/NameWriter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/NameWriter.java @@ -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 * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -8,9 +8,11 @@ * * Contributors: * Institute for Software - initial API and implementation + * Thomas Corbat (IFS) *******************************************************************************/ 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.IASTNode; import org.eclipse.cdt.core.dom.ast.IBinding; @@ -80,11 +82,15 @@ public class NameWriter extends NodeWriter { private boolean needsTemplateQualifier(ICPPASTTemplateId templId){ if (templId.getParent() instanceof ICPPASTQualifiedName) { ICPPASTQualifiedName qName = (ICPPASTQualifiedName) templId.getParent(); - return isDependentName(qName, templId); + return !isPartOfFunctionDeclarator(qName) && isDependentName(qName, templId); } return false; } - + + private boolean isPartOfFunctionDeclarator(ICPPASTQualifiedName qName) { + return qName.getParent() instanceof IASTFunctionDeclarator; + } + private boolean isDependentName(ICPPASTQualifiedName qname, ICPPASTTemplateId tempId) { ICPPASTNameSpecifier[] segments = qname.getAllSegments(); for (int i = 0; i < segments.length; ++i){ diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/togglefunction/ToggleRefactoringTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/togglefunction/ToggleRefactoringTest.java index 77b09d1..0414dcf 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/togglefunction/ToggleRefactoringTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/togglefunction/ToggleRefactoringTest.java @@ -3273,4 +3273,282 @@ public class ToggleRefactoringTest extends RefactoringTestBase { public void testToggleFunctionFailsOnSyntaxError_389299() throws Exception { 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 + //class Tpl { + // typedef T1 M; + //public: + // M /*$*/f/*$$*/(){ + // return M(); + // } + //}; + //==================== + //template + //class Tpl { + // typedef T1 M; + //public: + // M f(); + //}; + // + //template + //inline typename Tpl::M Tpl::f() { + // return M(); + //} + public void testToggleFunctionWithScopedTypedefReturntypeFromTemplate_399931() throws Exception { + assertRefactoringSuccess(); + } + + //A.h + //template + //struct TplOuter { + // template + // struct TplInner { + // typedef TInner R; + // R /*$*/f/*$$*/(){ + // return R(); + // } + // }; + //}; + //==================== + //template + //struct TplOuter { + // template + // struct TplInner { + // typedef TInner R; + // R f(); + // }; + //}; + // + //template + //template + //inline typename TplOuter::template TplInner::R TplOuter::TplInner< + // TInner>::f() { + // return R(); + //} + public void testToggleFunctionFromNestedTemplate_399931() throws Exception { + assertRefactoringSuccess(); + } + + //A.h + //template + //struct Bag { + // Bag /*$*/create/*$$*/(){ + // return Bag(); + // } + //}; + //==================== + //template + //struct Bag { + // Bag create(); + //}; + // + //template + //inline Bag Bag::create() { + // return Bag(); + //} + public void testToggleFunctionWithTemplateReturnType_399931() throws Exception { + assertRefactoringSuccess(); + } + + //A.h + //template + //struct Bag { + //}; + // + //template + //struct Bag { + // Bag /*$*/create/*$$*/() { + // return Bag(); + // } + //}; + //==================== + //template + //struct Bag { + //}; + // + //template + //struct Bag { + // Bag create(); + //}; + // + //template + //inline Bag Bag::create() { + // return Bag(); + //} + public void testToggleMemberFunctionOfPartialSpecialization_399931() throws Exception { + assertRefactoringSuccess(); + } + + //A.h + //template + //struct Bag { + //}; + // + //template + //struct Bag { + // Bag /*$*/create/*$$*/() { + // return Bag(); + // } + //}; + //==================== + //template + //struct Bag { + //}; + // + //template + //struct Bag { + // Bag create(); + //}; + // + //template + //inline Bag Bag::create() { + // return Bag(); + //} + public void testToggleMemberFunctionOfPartialSpecializationWithTwoParameters_399931() throws Exception { + assertRefactoringSuccess(); + } + + //A.h + //template + //struct Bag { + //}; + // + //template + //struct Bag { + // Bag /*$*/create/*$$*/() { + // return Bag(); + // } + //}; + //==================== + //template + //struct Bag { + //}; + // + //template + //struct Bag { + // Bag create(); + //}; + // + //template + //inline Bag Bag::create() { + // return Bag(); + //} + public void testToggleMemberFunctionOfPartialSpecializationMultiplePointers_399931() throws Exception { + assertRefactoringSuccess(); + } + + //A.h + //template + //struct Bag { + //}; + // + //template<> + //struct Bag { + // Bag /*$*/create/*$$*/() { + // return Bag(); + // } + //}; + //==================== + //template + //struct Bag { + //}; + // + //template<> + //struct Bag { + // Bag create(); + //}; + // + //inline Bag Bag::create() { + // return Bag(); + //} + public void testToggleMemberFunctionOfFullSpecialization_399931() throws Exception { + assertRefactoringSuccess(); + } + + //A.h + //template + //struct Qualifier { + // typedef R ReturnType; + //}; + // + //template + //struct ToggleType { + // typename Qualifier::ReturnType /*$*/create/*$$*/() { + // return typename Qualifier::ReturnType(); + //} + //}; + //==================== + //template + //struct Qualifier { + // typedef R ReturnType; + //}; + // + //template + //struct ToggleType { + // typename Qualifier::ReturnType create(); + //}; + // + //template + //inline typename Qualifier::ReturnType ToggleType::create() { + // return typename Qualifier::ReturnType(); + //} + public void testToggleWithTemplateQualifierInReturnType_399931() throws Exception { + assertRefactoringSuccess(); + } + + //A.h + //template + //struct Qualifier { + // typedef R ReturnType; + //}; + // + //template + //struct ToggleType { + // typename Qualifier::ReturnType /*$*/create/*$$*/() { + // return typename Qualifier::ReturnType(); + //} + //}; + //==================== + //template + //struct Qualifier { + // typedef R ReturnType; + //}; + // + //template + //struct ToggleType { + // typename Qualifier::ReturnType create(); + //}; + // + //template + //inline typename Qualifier::ReturnType ToggleType::create() { + // return typename Qualifier::ReturnType(); + //} + public void testToggleWithTemplateArgumentDependentQualifierInReturnType_399931() throws Exception { + assertRefactoringSuccess(); + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleNodeHelper.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleNodeHelper.java index f54213c..9cffbc5 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleNodeHelper.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/togglefunction/ToggleNodeHelper.java @@ -14,10 +14,13 @@ package org.eclipse.cdt.internal.ui.refactoring.togglefunction; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; -import java.util.ListIterator; 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.IASTCompositeTypeSpecifier; 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.IASTStandardFunctionDeclarator; 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.ICPPASTConstructorChainInitializer; 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.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.ICPPASTQualifiedName; 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.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.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.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.utils.NodeHelper; public class ToggleNodeHelper extends NodeHelper { private static final String EMPTY_STRING = ""; //$NON-NLS-1$ + private static final ICPPNodeFactory factory = ASTNodeFactoryFactory.getDefaultCPPNodeFactory(); private static void removeParameterInitializations(IASTFunctionDeclarator funcDecl) { for (IASTNode child : funcDecl.getChildren()) { @@ -84,7 +96,7 @@ public class ToggleNodeHelper extends NodeHelper { static IASTSimpleDeclaration createDeclarationFromDefinition(IASTFunctionDefinition oldDefinition) { IASTDeclarator newDeclarator = oldDefinition.getDeclarator().copy(CopyStyle.withLocations); IASTDeclSpecifier newDeclSpec = oldDefinition.getDeclSpecifier().copy(CopyStyle.withLocations); - IASTSimpleDeclaration newDeclaration = new CPPASTSimpleDeclaration(newDeclSpec); + IASTSimpleDeclaration newDeclaration = factory.newSimpleDeclaration(newDeclSpec); newDeclaration.addDeclarator(newDeclarator); return newDeclaration; } @@ -95,11 +107,9 @@ public class ToggleNodeHelper extends NodeHelper { ICPPASTFunctionDefinition newFunc = null; newFuncDecl = adjustParamNames(newFuncDecl, oldDefinition); if (oldDefinition instanceof ICPPASTFunctionWithTryBlock) { - newFunc = new CPPASTFunctionWithTryBlock(newDeclSpec, newFuncDecl, - new CPPASTCompoundStatement()); + newFunc = factory.newFunctionTryBlock(newDeclSpec, newFuncDecl, factory.newCompoundStatement()); } else { - newFunc = new CPPASTFunctionDefinition(newDeclSpec, newFuncDecl, - new CPPASTCompoundStatement()); + newFunc = factory.newFunctionDefinition(newDeclSpec, newFuncDecl, factory.newCompoundStatement()); } copyInitializerList(newFunc, oldDefinition); return newFunc; @@ -127,49 +137,146 @@ public class ToggleNodeHelper extends NodeHelper { static IASTFunctionDefinition getQualifiedNameDefinition(IASTFunctionDefinition oldDefinition, IASTTranslationUnit definitionUnit, IASTNode nameSpace) { - - ICPPASTDeclSpecifier newDeclSpec = - (ICPPASTDeclSpecifier) oldDefinition.getDeclSpecifier().copy(CopyStyle.withLocations); - - newDeclSpec.setVirtual(false); - newDeclSpec.setInline(true); - newDeclSpec.setStorageClass(IASTDeclSpecifier.sc_unspecified); - + ICPPASTDeclSpecifier newDeclSpecifier = createDeclSpecifier(oldDefinition); IASTFunctionDeclarator newDeclarator = oldDefinition.getDeclarator().copy(CopyStyle.withLocations); newDeclarator.setName(getQualifiedName(oldDefinition.getDeclarator(), nameSpace)); removeParameterInitializations(newDeclarator); - + ICPPASTFunctionDefinition newFunction = - createFunctionSignatureWithEmptyBody(newDeclSpec, newDeclarator, oldDefinition); - + createFunctionSignatureWithEmptyBody(newDeclSpecifier, newDeclarator, oldDefinition); + 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( IASTFunctionDefinition oldFunction, IASTFunctionDefinition newFunction) { - ArrayList templateDeclarations = getAllTemplateDeclaration(oldFunction); + ArrayList templateDeclarations = getAllTemplateDeclarations(oldFunction); return addTemplateDeclarationsInOrder(templateDeclarations, newFunction); } private static ICPPASTTemplateDeclaration addTemplateDeclarationsInOrder( ArrayList templDecs, IASTFunctionDefinition newFunction) { - ListIterator iter1 = templDecs.listIterator(); ICPPASTTemplateDeclaration child = null; - while (iter1.hasNext()) { - child = iter1.next(); - child.setDeclaration(newFunction); - ListIterator iter2 = iter1; - if (iter2.hasNext()) { - ICPPASTTemplateDeclaration parent = iter2.next(); - child.setParent(parent); - parent.setDeclaration(child); - child = parent; + for (ICPPASTTemplateDeclaration templateDeclaration : templDecs) { + if (templateDeclaration.getTemplateParameters().length == 0) { + continue; + } + if (child == null) { + child = templateDeclaration; + child.setDeclaration(newFunction); + } else { + templateDeclaration.setDeclaration(child); + child.setParent(templateDeclaration); + child = templateDeclaration; } } return child; } - private static ArrayList getAllTemplateDeclaration(IASTNode node) { + private static ArrayList getAllTemplateDeclarations(IASTNode node) { ArrayList templdecs = new ArrayList(); while (node.getParent() != null) { node = node.getParent(); @@ -226,13 +333,13 @@ public class ToggleNodeHelper extends NodeHelper { */ static ICPPASTQualifiedName getQualifiedName(IASTFunctionDeclarator declarator, IASTNode limiter) { Stack nodes = getQualifiedNames(declarator, limiter, declarator); - CPPASTQualifiedName qName = reAssembleQualifiedName(nodes); + ICPPASTQualifiedName qName = reAssembleQualifiedName(nodes); qName.addName(declarator.getName().copy(CopyStyle.withLocations)); return qName; } - private static CPPASTQualifiedName reAssembleQualifiedName(Stack nodes) { - CPPASTQualifiedName qName = new CPPASTQualifiedName(); + private static ICPPASTQualifiedName reAssembleQualifiedName(Stack nodes) { + ICPPASTQualifiedName qName = factory.newQualifiedName(null); while (!nodes.isEmpty()) { IASTNode nnode = nodes.pop(); if (nnode instanceof IASTCompositeTypeSpecifier) { @@ -258,10 +365,10 @@ public class ToggleNodeHelper extends NodeHelper { } else if (node instanceof ICPPASTNamespaceDefinition) { nodes.push(((ICPPASTNamespaceDefinition) node).copy(CopyStyle.withLocations)); lastName = ((ICPPASTNamespaceDefinition) node).getName(); - } else if (shouldAddTemplateBrackets(node)) { + } else if (!(lastName instanceof ICPPASTTemplateId) && shouldAddTemplateBrackets(node)) { if (!nodes.isEmpty()) nodes.pop(); - ICPPASTTemplateId templateID = ToggleNodeHelper.getTemplateParameter(node, lastName); + ICPPASTTemplateId templateID = getTemplateParameter(node, lastName); nodes.add(templateID); } } @@ -271,21 +378,19 @@ public class ToggleNodeHelper extends NodeHelper { private static boolean shouldAddTemplateBrackets(IASTNode node) { return node instanceof ICPPASTTemplateDeclaration && !(((ICPPASTTemplateDeclaration) node).getDeclaration() - instanceof CPPASTFunctionDefinition); + instanceof ICPPASTFunctionDefinition); } private static ICPPASTTemplateId getTemplateParameter(IASTNode node, IASTName name) { - ICPPASTTemplateId templateID = new CPPASTTemplateId(); - templateID.setTemplateName(name.copy(CopyStyle.withLocations)); + ICPPASTTemplateId templateID = factory.newTemplateId(name.copy(CopyStyle.withLocations)); for (IASTNode child : node.getChildren()) { if (child instanceof ICPPASTSimpleTypeTemplateParameter) { ICPPASTSimpleTypeTemplateParameter tempChild = (ICPPASTSimpleTypeTemplateParameter) child; - - CPPASTNamedTypeSpecifier namedTypeSpecifier = new CPPASTNamedTypeSpecifier(); - namedTypeSpecifier.setName(tempChild.getName().copy(CopyStyle.withLocations)); - - CPPASTTypeId id = new CPPASTTypeId(); - id.setDeclSpecifier(namedTypeSpecifier); + + IASTName argumentName = tempChild.getName().copy(CopyStyle.withLocations); + ICPPASTNamedTypeSpecifier namedTypeSpecifier = factory.newNamedTypeSpecifier(argumentName); + + ICPPASTTypeId id = factory.newTypeId(namedTypeSpecifier, null); templateID.addTemplateArgument(id); } } -- 2.7.4