1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-05 07:15:39 +02:00

Bug 371840 - Only first declarator can be selected in declaration

containing multiple declarators
This commit is contained in:
sprigogin 2012-05-20 21:10:34 -07:00
parent ed4b23705c
commit 66131f1da6
7 changed files with 101 additions and 57 deletions

View file

@ -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() {

View file

@ -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();
}
}

View file

@ -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<AccessorDescriptor> {
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) {

View file

@ -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));

View file

@ -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<String> 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<String> getNamesToAvoid() {
Set<String> namesToAvoid = new HashSet<String>();
// 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() {

View file

@ -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);

View file

@ -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<IASTSimpleDeclaration> existingFields = new ArrayList<IASTSimpleDeclaration>();
final List<IASTDeclarator> existingFields = new ArrayList<IASTDeclarator>();
final List<IASTFunctionDefinition> existingFunctionDefinitions = new ArrayList<IASTFunctionDefinition>();
final List<IASTSimpleDeclaration> existingFunctionDeclarations = new ArrayList<IASTSimpleDeclaration>();
final SortedSet<AccessorDescriptor> selectedAccessors = new TreeSet<AccessorDescriptor>();
@ -110,7 +110,7 @@ public class GetterSetterContext implements ITreeContentProvider {
private List<FieldDescriptor> getFieldDescriptors() {
if (fieldDescriptors == null) {
fieldDescriptors = new ArrayList<FieldDescriptor>();
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]);
}
}