diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/RefactoringTestBase.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/RefactoringTestBase.java index 9741fc6801e..b163c61ca5e 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/RefactoringTestBase.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/RefactoringTestBase.java @@ -368,7 +368,7 @@ public abstract class RefactoringTestBase extends BaseTestCase { while ((read= reader.read(part)) != -1) buffer.append(part, 0, read); reader.close(); - return buffer.toString(); + return buffer.toString().replace("\r", ""); } protected void resetPreferences() { diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/gettersandsetters/GenerateGettersAndSettersTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/gettersandsetters/GenerateGettersAndSettersTest.java index aab86cd86db..e2ef1e4aa3f 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/gettersandsetters/GenerateGettersAndSettersTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/gettersandsetters/GenerateGettersAndSettersTest.java @@ -1599,4 +1599,36 @@ public class GenerateGettersAndSettersTest extends RefactoringTestBase { selectedSetters = new String[] { "mClass" }; assertRefactoringSuccess(); } + + //A.h + //class Foo { + // int a, *b, /*$*/c[2]/*$$*/; + //}; + //==================== + //class Foo { + //public: + // void setA(int a) { + // this->a = a; + // } + // + // int* getB() const { + // return b; + // } + // + // void setB(int* b) { + // this->b = b; + // } + // + // const int* getC() const { + // return c; + // } + // + //private: + // int a, *b, c[2]; + //}; + public void testMultipleDeclarators_371840() throws Exception { + selectedGetters = new String[] { "b", "c" }; + selectedSetters = new String[] { "a", "b" }; + assertRefactoringSuccess(); + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/AccessorDescriptor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/AccessorDescriptor.java index 45beb6d1d3c..644a197a1fc 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/AccessorDescriptor.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/AccessorDescriptor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011 Google, Inc and others. + * Copyright (c) 2011, 2012 Google, Inc 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 @@ -45,7 +45,7 @@ public class AccessorDescriptor implements Comparable { this.fieldName = fieldDescriptor.getFieldName(); if (accessorName != null) { this.accessorFactory = AccessorFactory.createFactory(kind, fieldName, - fieldDescriptor.getFieldDeclaration(), accessorName); + fieldDescriptor.getFieldDeclarator(), accessorName); this.accessorDeclaration = accessorFactory.createDeclaration(); for (IASTFunctionDefinition currentDefinition : context.existingFunctionDefinitions) { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/AccessorFactory.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/AccessorFactory.java index 9ee966e281a..11638a05ca7 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/AccessorFactory.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/AccessorFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2011 Institute for Software, HSR Hochschule fuer Technik + * Copyright (c) 2008, 2012 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 @@ -55,26 +55,29 @@ import org.eclipse.cdt.internal.ui.refactoring.gettersandsetters.AccessorDescrip public abstract class AccessorFactory { protected final IASTName fieldName; - protected final IASTSimpleDeclaration fieldDeclaration; + protected final IASTDeclarator fieldDeclarator; + private final IASTDeclSpecifier declSpecifier; protected final String accessorName; protected boolean passByReference; public static AccessorFactory createFactory(AccessorKind kind, IASTName fieldName, - IASTSimpleDeclaration fieldDeclaration, String accessorName) { + IASTDeclarator declarator, String accessorName) { if (kind == AccessorKind.GETTER) { - return new GetterFactory(fieldName, fieldDeclaration, accessorName); + return new GetterFactory(fieldName, declarator, accessorName); } else { - return new SetterFactory(fieldName, fieldDeclaration, accessorName); + return new SetterFactory(fieldName, declarator, accessorName); } } - protected AccessorFactory(IASTName fieldName, IASTSimpleDeclaration fieldDeclaration, - String accessorName) { + protected AccessorFactory(IASTName fieldName, IASTDeclarator fieldDeclarator, String accessorName) { this.fieldName = fieldName; - this.fieldDeclaration = fieldDeclaration; + this.fieldDeclarator = fieldDeclarator; this.accessorName = accessorName; - IType type = CPPVisitor.createType(fieldDeclaration.getDeclSpecifier()); - passByReference = TypeHelper.shouldBePassedByReference(type, fieldDeclaration.getTranslationUnit()); + IASTSimpleDeclaration declaration = + CPPVisitor.findAncestorWithType(fieldDeclarator, IASTSimpleDeclaration.class); + this.declSpecifier = declaration.getDeclSpecifier(); + IType type = CPPVisitor.createType(declSpecifier); + passByReference = TypeHelper.shouldBePassedByReference(type, fieldDeclarator.getTranslationUnit()); } /** @@ -90,16 +93,16 @@ public abstract class AccessorFactory { public abstract IASTFunctionDefinition createDefinition(ICPPASTQualifiedName className); protected IASTDeclSpecifier getParamOrReturnDeclSpecifier() { - IASTDeclSpecifier declSpec = fieldDeclaration.getDeclSpecifier().copy(CopyStyle.withLocations); - if (passByReference || fieldDeclaration.getDeclarators()[0] instanceof IASTArrayDeclarator) { + IASTDeclSpecifier declSpec = declSpecifier.copy(CopyStyle.withLocations); + if (passByReference || fieldDeclarator instanceof IASTArrayDeclarator) { declSpec.setConst(true); } return declSpec; } private static class GetterFactory extends AccessorFactory { - GetterFactory(IASTName fieldName, IASTSimpleDeclaration fieldDeclaration, String getterName) { - super(fieldName, fieldDeclaration, getterName); + GetterFactory(IASTName fieldName, IASTDeclarator fieldDeclarator, String getterName) { + super(fieldName, fieldDeclarator, getterName); } @Override @@ -142,7 +145,7 @@ public abstract class AccessorFactory { getterName.setName(accessorName.toCharArray()); // Copy declarator hierarchy - IASTDeclarator topDeclarator = fieldDeclaration.getDeclarators()[0].copy(CopyStyle.withLocations); + IASTDeclarator topDeclarator = fieldDeclarator.copy(CopyStyle.withLocations); if (topDeclarator instanceof IASTArrayDeclarator) { boolean isCpp = topDeclarator instanceof ICPPASTArrayDeclarator; @@ -190,8 +193,8 @@ public abstract class AccessorFactory { } private static class SetterFactory extends AccessorFactory { - SetterFactory(IASTName fieldName, IASTSimpleDeclaration fieldDeclaration, String setterName) { - super(fieldName, fieldDeclaration, setterName); + SetterFactory(IASTName fieldName, IASTDeclarator fieldDeclarator, String setterName) { + super(fieldName, fieldDeclarator, setterName); } @Override @@ -215,7 +218,7 @@ public abstract class AccessorFactory { CPPASTCompoundStatement compound = new CPPASTCompoundStatement(); CPPASTExpressionStatement exprStmt = new CPPASTExpressionStatement(); CPPASTBinaryExpression binExpr = new CPPASTBinaryExpression(); - IASTDeclarator innerDeclarator = fieldDeclaration.getDeclarators()[0]; + IASTDeclarator innerDeclarator = fieldDeclarator; while (innerDeclarator.getNestedDeclarator() != null) { innerDeclarator = innerDeclarator.getNestedDeclarator(); } @@ -252,7 +255,7 @@ public abstract class AccessorFactory { declarator.setName(setterName); } CPPASTParameterDeclaration parameterDeclaration = new CPPASTParameterDeclaration(); - IASTDeclarator parameterDeclarator = fieldDeclaration.getDeclarators()[0].copy(CopyStyle.withLocations); + IASTDeclarator parameterDeclarator = fieldDeclarator.copy(CopyStyle.withLocations); parameterDeclarator.setName(getSetterParameterName()); if (passByReference) { parameterDeclarator.addPointerOperator(new CPPASTReferenceOperator(false)); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/FieldDescriptor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/FieldDescriptor.java index c627a0eee34..2c77c29278f 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/FieldDescriptor.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/FieldDescriptor.java @@ -1,3 +1,13 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 Google, Inc 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: + * Sergey Prigogin (Google) - initial API and implementation + *******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring.gettersandsetters; import java.util.ArrayList; @@ -6,9 +16,9 @@ import java.util.List; import java.util.Set; import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTDeclarator; 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.IArrayType; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IPointerType; @@ -23,21 +33,21 @@ import org.eclipse.cdt.internal.ui.refactoring.gettersandsetters.AccessorDescrip class FieldDescriptor { private final IASTName fieldName; - private final IASTSimpleDeclaration fieldDeclaration; + private final IASTDeclarator fieldDeclarator; private final AccessorDescriptor getter; private final AccessorDescriptor setter; private final AccessorDescriptor[] childNodes; private final GetterSetterContext context; - FieldDescriptor(IASTSimpleDeclaration fieldDeclaration, GetterSetterContext context) { - this.fieldName = GetterSetterContext.getDeclarationName(fieldDeclaration); - this.fieldDeclaration = fieldDeclaration; + FieldDescriptor(IASTDeclarator field, GetterSetterContext context) { + this.fieldName = GetterSetterContext.getDeclaratorName(field); + this.fieldDeclarator = field; this.context = context; Set namesToAvoid = getNamesToAvoid(); String name = GetterSetterNameGenerator.generateGetterName(fieldName, namesToAvoid); this.getter = new AccessorDescriptor(AccessorKind.GETTER, name, this); name = GetterSetterNameGenerator.generateSetterName(fieldName, namesToAvoid); - if (!isAssignable(fieldDeclaration)) + if (!isAssignable(field)) name = null; this.setter = new AccessorDescriptor(AccessorKind.SETTER, name, this); @@ -54,8 +64,8 @@ class FieldDescriptor { private Set getNamesToAvoid() { Set namesToAvoid = new HashSet(); // Add field names. - for (IASTSimpleDeclaration fieldDeclaration : context.existingFields) { - namesToAvoid.add(String.valueOf(GetterSetterContext.getDeclarationName(fieldDeclaration).getSimpleID())); + for (IASTDeclarator fieldDeclarator : context.existingFields) { + namesToAvoid.add(String.valueOf(GetterSetterContext.getDeclaratorName(fieldDeclarator).getSimpleID())); } // Add constructor name. if (!context.existingFields.isEmpty()) { @@ -69,8 +79,8 @@ class FieldDescriptor { return namesToAvoid; } - private static boolean isAssignable(IASTSimpleDeclaration declaration) { - IASTName name = GetterSetterContext.getDeclarationName(declaration); + private static boolean isAssignable(IASTDeclarator fieldDeclarator) { + IASTName name = GetterSetterContext.getDeclaratorName(fieldDeclarator); IBinding binding = name.resolveBinding(); if (!(binding instanceof ICPPField)) return false; @@ -107,8 +117,8 @@ class FieldDescriptor { return fieldName; } - public IASTSimpleDeclaration getFieldDeclaration() { - return fieldDeclaration; + public IASTDeclarator getFieldDeclarator() { + return fieldDeclarator; } public AccessorDescriptor getGetter() { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoring.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoring.java index 854a0ab8ed1..e81c6c41394 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoring.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoring.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2011 Institute for Software, HSR Hochschule fuer Technik + * Copyright (c) 2008, 2012 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 @@ -26,7 +26,6 @@ import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; import org.eclipse.ltk.core.refactoring.RefactoringStatus; import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; -import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; @@ -44,6 +43,7 @@ import org.eclipse.cdt.core.dom.rewrite.ASTRewrite; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.dom.rewrite.astwriter.ContainerNode; import org.eclipse.cdt.internal.ui.refactoring.CRefactoring; @@ -87,7 +87,6 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring { } } - private static final String MEMBER_DECLARATION = "MEMBER_DECLARATION"; //$NON-NLS-1$ private final GetterSetterContext context; private InsertLocation definitionInsertLocation; @@ -195,27 +194,23 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring { @Override public int visit(IASTDeclaration declaration) { if (declaration instanceof IASTSimpleDeclaration) { - IASTSimpleDeclaration fieldDeclaration = (IASTSimpleDeclaration) declaration; - ASTNodeProperty props = fieldDeclaration.getPropertyInParent(); - if (props.getName().contains(MEMBER_DECLARATION)) { - final IASTDeclarator[] declarators = fieldDeclaration.getDeclarators(); - if (declarators.length > 0) { - IASTDeclarator innermostDeclarator = declarators[0]; + IASTSimpleDeclaration simpleDeclaration = (IASTSimpleDeclaration) declaration; + if (simpleDeclaration.getPropertyInParent() == IASTCompositeTypeSpecifier.MEMBER_DECLARATION) { + for (IASTDeclarator declarator : simpleDeclaration.getDeclarators()) { + IASTDeclarator innermostDeclarator = declarator; while (innermostDeclarator.getNestedDeclarator() != null) { innermostDeclarator = innermostDeclarator.getNestedDeclarator(); } if ((innermostDeclarator instanceof IASTFunctionDeclarator)) { - context.existingFunctionDeclarations.add(fieldDeclaration); - } else if (fieldDeclaration.isPartOfTranslationUnitFile()) { - context.existingFields.add(fieldDeclaration); + context.existingFunctionDeclarations.add(simpleDeclaration); + } else if (simpleDeclaration.isPartOfTranslationUnitFile()) { + context.existingFields.add(declarator); } } } - } - if (declaration instanceof IASTFunctionDefinition) { + } else if (declaration instanceof IASTFunctionDefinition) { IASTFunctionDefinition functionDefinition = (IASTFunctionDefinition) declaration; - ASTNodeProperty props = functionDefinition.getPropertyInParent(); - if (props.getName().contains(MEMBER_DECLARATION)) { + if (functionDefinition.getPropertyInParent() == IASTCompositeTypeSpecifier.MEMBER_DECLARATION) { context.existingFunctionDefinitions.add(functionDefinition); } } @@ -246,7 +241,7 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring { addDefinition(collector, definitions, pm); } ICPPASTCompositeTypeSpecifier classDefinition = - (ICPPASTCompositeTypeSpecifier) context.existingFields.get(context.existingFields.size() - 1).getParent(); + CPPVisitor.findAncestorWithType(context.existingFields.get(0), ICPPASTCompositeTypeSpecifier.class); ClassMemberInserter.createChange(classDefinition, VisibilityEnum.v_public, getterAndSetters, false, collector); @@ -275,7 +270,8 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring { return; } - IASTSimpleDeclaration decl = context.existingFields.get(0); + IASTSimpleDeclaration decl = + CPPVisitor.findAncestorWithType(context.existingFields.get(0), IASTSimpleDeclaration.class); MethodDefinitionInsertLocationFinder locationFinder = new MethodDefinitionInsertLocationFinder(); InsertLocation location = locationFinder.find(tu, decl.getFileLocation(), decl.getParent(), refactoringContext, pm); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GetterSetterContext.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GetterSetterContext.java index e915b736b81..19d831f206b 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GetterSetterContext.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GetterSetterContext.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2011 Institute for Software, HSR Hochschule fuer Technik + * Copyright (c) 2008, 2012 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 @@ -28,7 +28,7 @@ import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.internal.ui.refactoring.gettersandsetters.AccessorDescriptor.AccessorKind; public class GetterSetterContext implements ITreeContentProvider { - final List existingFields = new ArrayList(); + final List existingFields = new ArrayList(); final List existingFunctionDefinitions = new ArrayList(); final List existingFunctionDeclarations = new ArrayList(); final SortedSet selectedAccessors = new TreeSet(); @@ -110,7 +110,7 @@ public class GetterSetterContext implements ITreeContentProvider { private List getFieldDescriptors() { if (fieldDescriptors == null) { fieldDescriptors = new ArrayList(); - for (IASTSimpleDeclaration field : existingFields) { + for (IASTDeclarator field : existingFields) { FieldDescriptor descriptor = new FieldDescriptor(field, this); if (descriptor.missingGetterOrSetter()) { fieldDescriptors.add(descriptor); @@ -120,11 +120,14 @@ public class GetterSetterContext implements ITreeContentProvider { return fieldDescriptors; } - static IASTName getDeclarationName(IASTSimpleDeclaration declaration) { - IASTDeclarator declarator = declaration.getDeclarators()[0]; + static IASTName getDeclaratorName(IASTDeclarator declarator) { while (declarator.getNestedDeclarator() != null) { declarator = declarator.getNestedDeclarator(); } return declarator.getName(); } + + static IASTName getDeclarationName(IASTSimpleDeclaration declaration) { + return getDeclaratorName(declaration.getDeclarators()[0]); + } }