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:
parent
ed4b23705c
commit
66131f1da6
7 changed files with 101 additions and 57 deletions
|
@ -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() {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue