mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 273525 - Generate Getters and Setters is very slow.
This commit is contained in:
parent
0823fc1277
commit
c12a4d8b9b
16 changed files with 937 additions and 167 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2004, 2010 IBM Corporation and others.
|
* Copyright (c) 2004, 2011 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
|
||||||
|
@ -75,6 +75,7 @@ import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.ICompositeType;
|
import org.eclipse.cdt.core.dom.ast.ICompositeType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IEnumeration;
|
import org.eclipse.cdt.core.dom.ast.IEnumeration;
|
||||||
import org.eclipse.cdt.core.dom.ast.IEnumerator;
|
import org.eclipse.cdt.core.dom.ast.IEnumerator;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IField;
|
||||||
import org.eclipse.cdt.core.dom.ast.IFunction;
|
import org.eclipse.cdt.core.dom.ast.IFunction;
|
||||||
import org.eclipse.cdt.core.dom.ast.IFunctionType;
|
import org.eclipse.cdt.core.dom.ast.IFunctionType;
|
||||||
import org.eclipse.cdt.core.dom.ast.ILabel;
|
import org.eclipse.cdt.core.dom.ast.ILabel;
|
||||||
|
@ -1409,12 +1410,26 @@ public class CPPVisitor extends ASTQueries {
|
||||||
if (nameBinding.equals(binding)) {
|
if (nameBinding.equals(binding)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// a using declaration is a declaration for the references of its delegates
|
// A using declaration is a declaration for the references of its delegates
|
||||||
if (nameBinding instanceof ICPPUsingDeclaration) {
|
if (nameBinding instanceof ICPPUsingDeclaration) {
|
||||||
if (ArrayUtil.contains(((ICPPUsingDeclaration) nameBinding).getDelegates(), binding)) {
|
if (ArrayUtil.contains(((ICPPUsingDeclaration) nameBinding).getDelegates(), binding)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Handle the case when one of the bindings is from the index and another
|
||||||
|
// one is from an AST.
|
||||||
|
if ((nameBinding instanceof IIndexBinding) != (binding instanceof IIndexBinding) &&
|
||||||
|
SemanticUtil.isSameOwner(nameBinding.getOwner(), binding.getOwner())) {
|
||||||
|
if (nameBinding instanceof IFunction && binding instanceof IFunction) {
|
||||||
|
if (((IFunction) nameBinding).getType().isSameType(((IFunction) binding).getType())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (nameBinding instanceof IField && binding instanceof IField) {
|
||||||
|
if (((IField) nameBinding).getType().isSameType(((IField) binding).getType())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -914,32 +914,35 @@ getters=name
|
||||||
//@C.cpp
|
//@C.cpp
|
||||||
#include "C.h"
|
#include "C.h"
|
||||||
|
|
||||||
int Person::SocSecNo(){
|
namespace Personal {
|
||||||
|
|
||||||
|
int Person::SocSecNo() {
|
||||||
return socSecNo;
|
return socSecNo;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
} // namespace Personal
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//=
|
//=
|
||||||
#include "C.h"
|
#include "C.h"
|
||||||
|
|
||||||
int Person::SocSecNo(){
|
namespace Personal {
|
||||||
|
char *Person::getName() const
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Person::SocSecNo() {
|
||||||
return socSecNo;
|
return socSecNo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace Personal
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *Person::getName() const
|
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//@C.h
|
//@C.h
|
||||||
#ifndef C_H_
|
#ifndef C_H_
|
||||||
#define C_H_
|
#define C_H_
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2008, 2009 Institute for Software, HSR Hochschule fuer Technik
|
* Copyright (c) 2008, 2011 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,6 +8,7 @@
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Institute for Software - initial API and implementation
|
* Institute for Software - initial API and implementation
|
||||||
|
* Sergey Prigogin (Google)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.ui.tests.refactoring;
|
package org.eclipse.cdt.ui.tests.refactoring;
|
||||||
|
|
||||||
|
@ -24,15 +25,16 @@ import org.eclipse.cdt.core.dom.IPDOMManager;
|
||||||
import org.eclipse.cdt.core.index.IIndexManager;
|
import org.eclipse.cdt.core.index.IIndexManager;
|
||||||
import org.eclipse.cdt.ui.testplugin.CTestPlugin;
|
import org.eclipse.cdt.ui.testplugin.CTestPlugin;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.ui.refactoring.RefactoringASTCache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Emanuel Graf
|
* @author Emanuel Graf
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public abstract class RefactoringTest extends RefactoringBaseTest {
|
public abstract class RefactoringTest extends RefactoringBaseTest {
|
||||||
|
|
||||||
private static final String CONFIG_FILE_NAME = ".config"; //$NON-NLS-1$
|
private static final String CONFIG_FILE_NAME = ".config"; //$NON-NLS-1$
|
||||||
|
|
||||||
protected String fileName;
|
protected String fileName;
|
||||||
|
protected RefactoringASTCache astCache;
|
||||||
|
|
||||||
public RefactoringTest(String name, Vector<TestSourceFile> files) {
|
public RefactoringTest(String name, Vector<TestSourceFile> files) {
|
||||||
super(name, files);
|
super(name, files);
|
||||||
|
@ -52,6 +54,13 @@ public abstract class RefactoringTest extends RefactoringBaseTest {
|
||||||
CCorePlugin.getIndexManager().reindex(cproject);
|
CCorePlugin.getIndexManager().reindex(cproject);
|
||||||
boolean joined = CCorePlugin.getIndexManager().joinIndexer(IIndexManager.FOREVER, NULL_PROGRESS_MONITOR);
|
boolean joined = CCorePlugin.getIndexManager().joinIndexer(IIndexManager.FOREVER, NULL_PROGRESS_MONITOR);
|
||||||
assertTrue(joined);
|
assertTrue(joined);
|
||||||
|
astCache = new RefactoringASTCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void tearDown() throws Exception {
|
||||||
|
astCache.dispose();
|
||||||
|
super.tearDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeConfiguration(Vector<TestSourceFile> files) {
|
private void initializeConfiguration(Vector<TestSourceFile> files) {
|
||||||
|
@ -76,7 +85,6 @@ public abstract class RefactoringTest extends RefactoringBaseTest {
|
||||||
initCommonFields(refactoringProperties);
|
initCommonFields(refactoringProperties);
|
||||||
configureRefactoring(refactoringProperties);
|
configureRefactoring(refactoringProperties);
|
||||||
files.remove(configFile);
|
files.remove(configFile);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initCommonFields(Properties refactoringProperties) {
|
private void initCommonFields(Properties refactoringProperties) {
|
||||||
|
@ -84,8 +92,8 @@ public abstract class RefactoringTest extends RefactoringBaseTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void assertConditionsOk(RefactoringStatus conditions) {
|
protected void assertConditionsOk(RefactoringStatus conditions) {
|
||||||
assertTrue(conditions.isOK() ? "OK" : "Error or Warning in Conditions: " + conditions.getEntries()[0].getMessage() //$NON-NLS-1$ //$NON-NLS-2$
|
assertTrue(conditions.isOK() ? "OK" : "Error or Warning in Conditions: " + conditions.getEntries()[0].getMessage(), //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
, conditions.isOK());
|
conditions.isOK());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void assertConditionsWarning(RefactoringStatus conditions, int number) {
|
protected void assertConditionsWarning(RefactoringStatus conditions, int number) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2008, 2009 Institute for Software, HSR Hochschule fuer Technik
|
* Copyright (c) 2008, 2011 Institute for Software, HSR Hochschule fuer Technik
|
||||||
* Rapperswil, University of applied sciences
|
* Rapperswil, University of applied sciences
|
||||||
* 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
|
||||||
|
@ -9,10 +9,12 @@
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Emanuel Graf & Leo Buettiker - initial API and implementation
|
* Emanuel Graf & Leo Buettiker - initial API and implementation
|
||||||
* Thomas Corbat - implementation
|
* Thomas Corbat - implementation
|
||||||
|
* Sergey Prigogin (Google)
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.eclipse.cdt.ui.tests.refactoring.gettersandsetters;
|
package org.eclipse.cdt.ui.tests.refactoring.gettersandsetters;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
|
@ -22,6 +24,8 @@ import org.eclipse.ltk.core.refactoring.Change;
|
||||||
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
|
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
|
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
|
||||||
|
import org.eclipse.cdt.core.model.CoreModel;
|
||||||
|
import org.eclipse.cdt.core.model.ICElement;
|
||||||
import org.eclipse.cdt.ui.tests.refactoring.RefactoringTest;
|
import org.eclipse.cdt.ui.tests.refactoring.RefactoringTest;
|
||||||
import org.eclipse.cdt.ui.tests.refactoring.TestSourceFile;
|
import org.eclipse.cdt.ui.tests.refactoring.TestSourceFile;
|
||||||
|
|
||||||
|
@ -30,19 +34,16 @@ import org.eclipse.cdt.internal.ui.refactoring.gettersandsetters.GetterAndSetter
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Thomas Corbat
|
* @author Thomas Corbat
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class GenerateGettersAndSettersTest extends RefactoringTest {
|
public class GenerateGettersAndSettersTest extends RefactoringTest {
|
||||||
|
|
||||||
protected boolean fatalError;
|
protected boolean fatalError;
|
||||||
private int warnings;
|
private int warnings;
|
||||||
private ArrayList<String> selectedGetters;
|
private List<String> selectedGetters;
|
||||||
private ArrayList<String> selectedSetters;
|
private List<String> selectedSetters;
|
||||||
private GenerateGettersAndSettersRefactoring refactoring;
|
private GenerateGettersAndSettersRefactoring refactoring;
|
||||||
private boolean keepInHeader;
|
private boolean keepInHeader;
|
||||||
private int infos;
|
private int infos;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param name
|
* @param name
|
||||||
* @param files
|
* @param files
|
||||||
|
@ -53,61 +54,54 @@ public class GenerateGettersAndSettersTest extends RefactoringTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void runTest() throws Throwable {
|
protected void runTest() throws Throwable {
|
||||||
IFile refFile = project.getFile(fileName);
|
IFile file = project.getFile(fileName);
|
||||||
refactoring = new GenerateGettersAndSettersRefactoring(refFile, selection, null, cproject);
|
ICElement element = CoreModel.getDefault().create(file);
|
||||||
|
refactoring = new GenerateGettersAndSettersRefactoring(element, selection, cproject, astCache);
|
||||||
RefactoringStatus initialConditions = refactoring.checkInitialConditions(NULL_PROGRESS_MONITOR);
|
RefactoringStatus initialConditions = refactoring.checkInitialConditions(NULL_PROGRESS_MONITOR);
|
||||||
|
|
||||||
|
if (fatalError) {
|
||||||
if(fatalError){
|
|
||||||
assertConditionsFatalError(initialConditions);
|
assertConditionsFatalError(initialConditions);
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
assertConditionsOk(initialConditions);
|
assertConditionsOk(initialConditions);
|
||||||
executeRefactoring();
|
executeRefactoring();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void executeRefactoring() throws CoreException, Exception {
|
private void executeRefactoring() throws CoreException, Exception {
|
||||||
|
|
||||||
selectFields();
|
selectFields();
|
||||||
refactoring.getContext().setImplementationInHeader(keepInHeader);
|
refactoring.getContext().setImplementationInHeader(keepInHeader);
|
||||||
RefactoringStatus finalConditions = refactoring.checkFinalConditions(NULL_PROGRESS_MONITOR);
|
RefactoringStatus finalConditions = refactoring.checkFinalConditions(NULL_PROGRESS_MONITOR);
|
||||||
Change createChange = refactoring.createChange(NULL_PROGRESS_MONITOR);
|
Change createChange = refactoring.createChange(NULL_PROGRESS_MONITOR);
|
||||||
if(warnings > 0){
|
if (warnings > 0) {
|
||||||
assertConditionsWarning(finalConditions, warnings);
|
assertConditionsWarning(finalConditions, warnings);
|
||||||
}else if(infos >0) {
|
} else if (infos > 0) {
|
||||||
assertConditionsInfo(finalConditions, infos);
|
assertConditionsInfo(finalConditions, infos);
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
assertConditionsOk(finalConditions);
|
assertConditionsOk(finalConditions);
|
||||||
}
|
}
|
||||||
|
|
||||||
createChange.perform(NULL_PROGRESS_MONITOR);
|
createChange.perform(NULL_PROGRESS_MONITOR);
|
||||||
|
|
||||||
compareFiles(fileMap);
|
compareFiles(fileMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void selectFields() {
|
private void selectFields() {
|
||||||
GetterAndSetterContext context = refactoring.getContext();
|
GetterAndSetterContext context = refactoring.getContext();
|
||||||
|
|
||||||
for(IASTSimpleDeclaration currentDecl : context.existingFields){
|
for (IASTSimpleDeclaration currentDecl : context.existingFields) {
|
||||||
String name = currentDecl.getDeclarators()[0].getName().getRawSignature();
|
String name = currentDecl.getDeclarators()[0].getName().getRawSignature();
|
||||||
if(selectedGetters.contains(name) ){
|
if (selectedGetters.contains(name)) {
|
||||||
selectedGetters.remove(name);
|
selectedGetters.remove(name);
|
||||||
context.selectedFunctions.add(context.createGetterInserter(currentDecl));
|
context.selectedFunctions.add(context.createGetterInserter(currentDecl));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(selectedSetters.contains(name) ){
|
if (selectedSetters.contains(name)) {
|
||||||
selectedSetters.remove(name);
|
selectedSetters.remove(name);
|
||||||
context.selectedFunctions.add(context.createSetterInserter(currentDecl));
|
context.selectedFunctions.add(context.createSetterInserter(currentDecl));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configureRefactoring(Properties refactoringProperties) {
|
protected void configureRefactoring(Properties refactoringProperties) {
|
||||||
fatalError = Boolean.valueOf(refactoringProperties.getProperty("fatalerror", "false")).booleanValue(); //$NON-NLS-1$//$NON-NLS-2$
|
fatalError = Boolean.valueOf(refactoringProperties.getProperty("fatalerror", "false")).booleanValue(); //$NON-NLS-1$//$NON-NLS-2$
|
||||||
|
@ -118,13 +112,12 @@ public class GenerateGettersAndSettersTest extends RefactoringTest {
|
||||||
keepInHeader = Boolean.valueOf(refactoringProperties.getProperty("inHeader", "false"));
|
keepInHeader = Boolean.valueOf(refactoringProperties.getProperty("inHeader", "false"));
|
||||||
|
|
||||||
selectedGetters = new ArrayList<String>();
|
selectedGetters = new ArrayList<String>();
|
||||||
for(String getterName : getters.split(",")){ //$NON-NLS-1$
|
for (String getterName : getters.split(",")) { //$NON-NLS-1$
|
||||||
selectedGetters.add(getterName);
|
selectedGetters.add(getterName);
|
||||||
}
|
}
|
||||||
selectedSetters = new ArrayList<String>();
|
selectedSetters = new ArrayList<String>();
|
||||||
for(String setterName : setters.split(",")){ //$NON-NLS-1$
|
for (String setterName : setters.split(",")) { //$NON-NLS-1$
|
||||||
selectedSetters.add(setterName);
|
selectedSetters.add(setterName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,250 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2008, 2011 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
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Institute for Software - initial API and implementation
|
||||||
|
* Sergey Prigogin (Google)
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.internal.ui.refactoring;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.OperationCanceledException;
|
||||||
|
import org.eclipse.core.runtime.SubMonitor;
|
||||||
|
import org.eclipse.jface.text.ITextSelection;
|
||||||
|
import org.eclipse.jface.text.Region;
|
||||||
|
import org.eclipse.jface.viewers.ISelection;
|
||||||
|
import org.eclipse.ltk.core.refactoring.Change;
|
||||||
|
import org.eclipse.ltk.core.refactoring.Refactoring;
|
||||||
|
import org.eclipse.ltk.core.refactoring.RefactoringChangeDescriptor;
|
||||||
|
import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
|
||||||
|
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
|
||||||
|
import org.eclipse.osgi.util.NLS;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTProblem;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTProblemDeclaration;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTProblemExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTProblemStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTProblemTypeId;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
|
||||||
|
import org.eclipse.cdt.core.model.CModelException;
|
||||||
|
import org.eclipse.cdt.core.model.ICElement;
|
||||||
|
import org.eclipse.cdt.core.model.ICProject;
|
||||||
|
import org.eclipse.cdt.core.model.ISourceRange;
|
||||||
|
import org.eclipse.cdt.core.model.ISourceReference;
|
||||||
|
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||||
|
import org.eclipse.cdt.ui.CUIPlugin;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.corext.util.CModelUtil;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.ui.refactoring.utils.SelectionHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base class for all AST based refactorings, provides some common implementations for
|
||||||
|
* AST creation, condition checking, change generating, and selection handling.
|
||||||
|
* This class is intended as a replacement for CRefactoring.
|
||||||
|
*/
|
||||||
|
public abstract class CRefactoring2 extends Refactoring {
|
||||||
|
protected String name = Messages.Refactoring_name;
|
||||||
|
protected final ICProject project;
|
||||||
|
protected final ITranslationUnit tu;
|
||||||
|
protected final RefactoringStatus initStatus;
|
||||||
|
protected final RefactoringASTCache astCache;
|
||||||
|
protected Region selectedRegion;
|
||||||
|
|
||||||
|
public CRefactoring2(ICElement element, ISelection selection, ICProject project,
|
||||||
|
RefactoringASTCache astCache) {
|
||||||
|
this.project = project;
|
||||||
|
this.astCache = astCache;
|
||||||
|
this.initStatus= new RefactoringStatus();
|
||||||
|
if (!(element instanceof ISourceReference)) {
|
||||||
|
this.tu = null;
|
||||||
|
initStatus.addFatalError(Messages.Refactoring_SelectionNotValid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ISourceReference sourceRef= (ISourceReference) element;
|
||||||
|
tu = CModelUtil.toWorkingCopy(sourceRef.getTranslationUnit());
|
||||||
|
|
||||||
|
if (selection instanceof ITextSelection) {
|
||||||
|
this.selectedRegion = SelectionHelper.getRegion(selection);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
ISourceRange sourceRange = sourceRef.getSourceRange();
|
||||||
|
this.selectedRegion = new Region(sourceRange.getIdStartPos(), sourceRange.getIdLength());
|
||||||
|
} catch (CModelException e) {
|
||||||
|
CUIPlugin.log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ProblemFinder extends ASTVisitor {
|
||||||
|
private boolean problemFound = false;
|
||||||
|
private final RefactoringStatus status;
|
||||||
|
|
||||||
|
public ProblemFinder(RefactoringStatus status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
shouldVisitProblems = true;
|
||||||
|
shouldVisitDeclarations = true;
|
||||||
|
shouldVisitExpressions = true;
|
||||||
|
shouldVisitStatements = true;
|
||||||
|
shouldVisitTypeIds = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int visit(IASTProblem problem) {
|
||||||
|
addWarningToState();
|
||||||
|
return ASTVisitor.PROCESS_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int visit(IASTDeclaration declaration) {
|
||||||
|
if (declaration instanceof IASTProblemDeclaration) {
|
||||||
|
addWarningToState();
|
||||||
|
}
|
||||||
|
return ASTVisitor.PROCESS_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int visit(IASTExpression expression) {
|
||||||
|
if (expression instanceof IASTProblemExpression) {
|
||||||
|
addWarningToState();
|
||||||
|
}
|
||||||
|
return ASTVisitor.PROCESS_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int visit(IASTStatement statement) {
|
||||||
|
if (statement instanceof IASTProblemStatement) {
|
||||||
|
addWarningToState();
|
||||||
|
}
|
||||||
|
return ASTVisitor.PROCESS_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int visit(IASTTypeId typeId) {
|
||||||
|
if (typeId instanceof IASTProblemTypeId) {
|
||||||
|
addWarningToState();
|
||||||
|
}
|
||||||
|
return ASTVisitor.PROCESS_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasProblem() {
|
||||||
|
return problemFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addWarningToState() {
|
||||||
|
if (!problemFound) {
|
||||||
|
status.addWarning(Messages.Refactoring_CompileErrorInTU);
|
||||||
|
problemFound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RefactoringStatus checkFinalConditions(IProgressMonitor pm)
|
||||||
|
throws CoreException, OperationCanceledException {
|
||||||
|
return new RefactoringStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RefactoringStatus checkInitialConditions(IProgressMonitor pm)
|
||||||
|
throws CoreException, OperationCanceledException {
|
||||||
|
SubMonitor sm = SubMonitor.convert(pm, 10);
|
||||||
|
sm.subTask(Messages.Refactoring_PM_LoadTU);
|
||||||
|
if (isProgressMonitorCanceld(sm, initStatus)) {
|
||||||
|
return initStatus;
|
||||||
|
}
|
||||||
|
IASTTranslationUnit ast = getAST(tu, sm);
|
||||||
|
if (ast == null) {
|
||||||
|
initStatus.addError(NLS.bind(Messages.Refactoring_ParsingError, tu.getPath()));
|
||||||
|
return initStatus;
|
||||||
|
}
|
||||||
|
if (isProgressMonitorCanceld(sm, initStatus)) {
|
||||||
|
return initStatus;
|
||||||
|
}
|
||||||
|
sm.subTask(Messages.Refactoring_PM_CheckTU);
|
||||||
|
checkAST(ast);
|
||||||
|
sm.worked(2);
|
||||||
|
sm.subTask(Messages.Refactoring_PM_InitRef);
|
||||||
|
sm.done();
|
||||||
|
return initStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static boolean isProgressMonitorCanceld(IProgressMonitor sm, RefactoringStatus status) {
|
||||||
|
if (sm.isCanceled()) {
|
||||||
|
status.addFatalError(Messages.Refactoring_CanceledByUser);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Change createChange(IProgressMonitor pm) throws CoreException, OperationCanceledException {
|
||||||
|
ModificationCollector collector = new ModificationCollector();
|
||||||
|
collectModifications(pm, collector);
|
||||||
|
CCompositeChange finalChange = collector.createFinalChange();
|
||||||
|
finalChange.setDescription(new RefactoringChangeDescriptor(getRefactoringDescriptor()));
|
||||||
|
return finalChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected RefactoringDescriptor getRefactoringDescriptor();
|
||||||
|
|
||||||
|
abstract protected void collectModifications(IProgressMonitor pm, ModificationCollector collector)
|
||||||
|
throws CoreException, OperationCanceledException;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IASTTranslationUnit getAST(ITranslationUnit tu, IProgressMonitor pm)
|
||||||
|
throws CoreException, OperationCanceledException {
|
||||||
|
return astCache.getAST(tu, pm);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean checkAST(IASTTranslationUnit ast) {
|
||||||
|
ProblemFinder problemFinder = new ProblemFinder(initStatus);
|
||||||
|
ast.accept(problemFinder);
|
||||||
|
return problemFinder.hasProblem();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<IASTName> findAllMarkedNames(IASTTranslationUnit ast) {
|
||||||
|
final List<IASTName> names = new ArrayList<IASTName>();
|
||||||
|
|
||||||
|
ast.accept(new ASTVisitor() {
|
||||||
|
{
|
||||||
|
shouldVisitNames = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int visit(IASTName name) {
|
||||||
|
if (name.isPartOfTranslationUnitFile() &&
|
||||||
|
SelectionHelper.isSelectionOnExpression(selectedRegion, name) &&
|
||||||
|
!(name instanceof ICPPASTQualifiedName)) {
|
||||||
|
names.add(name);
|
||||||
|
}
|
||||||
|
return super.visit(name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2008, 2009 Institute for Software, HSR Hochschule fuer Technik
|
* Copyright (c) 2008, 2011 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,13 +8,13 @@
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Institute for Software - initial API and implementation
|
* Institute for Software - initial API and implementation
|
||||||
|
* Sergey Prigogin (Google)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.ui.refactoring;
|
package org.eclipse.cdt.internal.ui.refactoring;
|
||||||
|
|
||||||
import org.eclipse.osgi.util.NLS;
|
import org.eclipse.osgi.util.NLS;
|
||||||
|
|
||||||
public final class Messages extends NLS {
|
public final class Messages extends NLS {
|
||||||
|
|
||||||
public static String DeleteFileChange_0;
|
public static String DeleteFileChange_0;
|
||||||
public static String DeleteFileChange_1;
|
public static String DeleteFileChange_1;
|
||||||
public static String Refactoring_name;
|
public static String Refactoring_name;
|
||||||
|
@ -33,6 +33,7 @@ public final class Messages extends NLS {
|
||||||
public static String Refactoring_SelectionNotValid;
|
public static String Refactoring_SelectionNotValid;
|
||||||
public static String Refactoring_CantLoadTU;
|
public static String Refactoring_CantLoadTU;
|
||||||
public static String Refactoring_Ambiguity;
|
public static String Refactoring_Ambiguity;
|
||||||
|
public static String Refactoring_ParsingError;
|
||||||
public static String NodeContainer_Name;
|
public static String NodeContainer_Name;
|
||||||
public static String NO_FILE;
|
public static String NO_FILE;
|
||||||
public static String RefactoringSaveHelper_unexpected_exception;
|
public static String RefactoringSaveHelper_unexpected_exception;
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#
|
#
|
||||||
# Contributors:
|
# Contributors:
|
||||||
# Institute for Software - initial API and implementation
|
# Institute for Software - initial API and implementation
|
||||||
|
# Sergey Prigogin (Google)
|
||||||
###############################################################################
|
###############################################################################
|
||||||
DeleteFileChange_0=Delete File
|
DeleteFileChange_0=Delete File
|
||||||
DeleteFileChange_1=File doesn't exist.
|
DeleteFileChange_1=File doesn't exist.
|
||||||
|
@ -18,7 +19,7 @@ Refactoring_PM_InitRef=Initialize Refactoring
|
||||||
Refactoring_PM_ParseTU=Parse Translation Unit
|
Refactoring_PM_ParseTU=Parse Translation Unit
|
||||||
Refactoring_PM_MergeComments=Merge Comments
|
Refactoring_PM_MergeComments=Merge Comments
|
||||||
Refactoring_CanceledByUser=Refactoring canceled by user.
|
Refactoring_CanceledByUser=Refactoring canceled by user.
|
||||||
Refactoring_CompileErrorInTU=The Translation Unit contains one or several problems. This can be caused by a syntax error in the code or a parser flaw. The refactoring will possibly fail.
|
Refactoring_CompileErrorInTU=The translation unit contains one or several problems. This can be caused by a syntax error in the code or a parser flaw. The refactoring will possibly fail.
|
||||||
AddDeclarationNodeToClassChange_AddDeclaration=Add Declaration to Class {0}.
|
AddDeclarationNodeToClassChange_AddDeclaration=Add Declaration to Class {0}.
|
||||||
CreateFileChange_CreateFile=Create file: {0}
|
CreateFileChange_CreateFile=Create file: {0}
|
||||||
CreateFileChange_UnknownLoc=Unknown Location: {0}
|
CreateFileChange_UnknownLoc=Unknown Location: {0}
|
||||||
|
@ -27,6 +28,7 @@ CRefactoring_FileNotFound=The file {0} is not on the build path of a C/C++ proje
|
||||||
Refactoring_SelectionNotValid=Selection is not valid.
|
Refactoring_SelectionNotValid=Selection is not valid.
|
||||||
Refactoring_CantLoadTU=Can not load translation unit.
|
Refactoring_CantLoadTU=Can not load translation unit.
|
||||||
Refactoring_Ambiguity=Translation unit is ambiguous.
|
Refactoring_Ambiguity=Translation unit is ambiguous.
|
||||||
|
Refactoring_ParsingError=Unable to parse {0}.
|
||||||
NO_FILE=File not found.
|
NO_FILE=File not found.
|
||||||
NodeContainer_Name=name:
|
NodeContainer_Name=name:
|
||||||
RefactoringSaveHelper_unexpected_exception=An unexpected exception occurred. See the error log for more details.
|
RefactoringSaveHelper_unexpected_exception=An unexpected exception occurred. See the error log for more details.
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2010, 2011 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;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.Assert;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.OperationCanceledException;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
import org.eclipse.ui.services.IDisposable;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.CCorePlugin;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
|
import org.eclipse.cdt.core.index.IIndex;
|
||||||
|
import org.eclipse.cdt.core.model.CoreModel;
|
||||||
|
import org.eclipse.cdt.core.model.ICProject;
|
||||||
|
import org.eclipse.cdt.core.model.ILanguage;
|
||||||
|
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable;
|
||||||
|
import org.eclipse.cdt.internal.corext.util.CModelUtil;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.ui.editor.ASTProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache containing ASTs for the translation units participating in refactoring.
|
||||||
|
* The cache object has to be disposed of after use. Failure to do so may cause
|
||||||
|
* loss of index lock.
|
||||||
|
*/
|
||||||
|
public class RefactoringASTCache implements IDisposable {
|
||||||
|
private IIndex fIndex;
|
||||||
|
private Map<ITranslationUnit, IASTTranslationUnit> fASTCache;
|
||||||
|
private boolean fDisposed;
|
||||||
|
|
||||||
|
public RefactoringASTCache() {
|
||||||
|
fASTCache = new HashMap<ITranslationUnit, IASTTranslationUnit>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an AST for the given translation unit. The AST is built for the working
|
||||||
|
* copy of the translation unit if such working copy exists. The returned AST is a shared
|
||||||
|
* one whenever possible.
|
||||||
|
* NOTE: No references to the AST or its nodes can be kept after calling the {@link #dispose()} method.
|
||||||
|
* @param tu The translation unit.
|
||||||
|
* @param pm A progress monitor.
|
||||||
|
* @return An AST, or <code>null</code> if the AST cannot be obtained.
|
||||||
|
*/
|
||||||
|
public IASTTranslationUnit getAST(ITranslationUnit tu, IProgressMonitor pm)
|
||||||
|
throws CoreException, OperationCanceledException {
|
||||||
|
Assert.isTrue(!fDisposed, "RefactoringASTCache is already disposed"); //$NON-NLS-1$
|
||||||
|
if (fIndex == null) {
|
||||||
|
ICProject[] projects;
|
||||||
|
projects = CoreModel.getDefault().getCModel().getCProjects();
|
||||||
|
IIndex index = CCorePlugin.getIndexManager().getIndex(projects);
|
||||||
|
try {
|
||||||
|
index.acquireReadLock();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new OperationCanceledException();
|
||||||
|
}
|
||||||
|
fIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
tu= CModelUtil.toWorkingCopy(tu);
|
||||||
|
IASTTranslationUnit ast= fASTCache.get(tu);
|
||||||
|
if (ast == null) {
|
||||||
|
// Try to get a shared AST before creating our own.
|
||||||
|
final IASTTranslationUnit[] astHolder = new IASTTranslationUnit[1];
|
||||||
|
ASTProvider.getASTProvider().runOnAST(tu, ASTProvider.WAIT_IF_OPEN, pm, new ASTRunnable() {
|
||||||
|
public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) throws CoreException {
|
||||||
|
// Leaking of AST outside of runOnAST method is dangerous, but it does not cause
|
||||||
|
// harm here since the index remains locked for the duration of the AST life span.
|
||||||
|
astHolder[0] = ast;
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ast = astHolder[0];
|
||||||
|
if (ast == null) {
|
||||||
|
int options= ITranslationUnit.AST_CONFIGURE_USING_SOURCE_CONTEXT |
|
||||||
|
ITranslationUnit.AST_SKIP_INDEXED_HEADERS;
|
||||||
|
ast= tu.getAST(fIndex, options);
|
||||||
|
fASTCache.put(tu, ast);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pm != null) {
|
||||||
|
pm.done();
|
||||||
|
}
|
||||||
|
return ast;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the index that can be safely used for reading until the cache is disposed.
|
||||||
|
*
|
||||||
|
* @return The index.
|
||||||
|
*/
|
||||||
|
public IIndex getIndex() {
|
||||||
|
Assert.isTrue(!fDisposed, "RefactoringASTCache is already disposed"); //$NON-NLS-1$
|
||||||
|
return fIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see IDisposable#dispose()
|
||||||
|
*/
|
||||||
|
public void dispose() {
|
||||||
|
Assert.isTrue(!fDisposed, "RefactoringASTCache.dispose() called more than once"); //$NON-NLS-1$
|
||||||
|
fDisposed = true;
|
||||||
|
if (fIndex != null) {
|
||||||
|
fIndex.releaseReadLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void finalize() throws Throwable {
|
||||||
|
Assert.isTrue(fDisposed, "RefactoringASTCache was not disposed"); //$NON-NLS-1$
|
||||||
|
super.finalize();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011 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;
|
||||||
|
|
||||||
|
import org.eclipse.jface.viewers.ISelection;
|
||||||
|
import org.eclipse.jface.window.IShellProvider;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.model.ICElement;
|
||||||
|
import org.eclipse.cdt.core.model.ICProject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for all refactoring runners. This class is intended as a replacement
|
||||||
|
* for RefactoringRunner.
|
||||||
|
*/
|
||||||
|
public abstract class RefactoringRunner2 {
|
||||||
|
protected final ISelection selection;
|
||||||
|
protected final ICElement element;
|
||||||
|
protected final IShellProvider shellProvider;
|
||||||
|
protected final ICProject project;
|
||||||
|
protected final RefactoringStarter starter;
|
||||||
|
|
||||||
|
public RefactoringRunner2(ICElement element, ISelection selection,
|
||||||
|
IShellProvider shellProvider, ICProject cProject) {
|
||||||
|
this.selection = selection;
|
||||||
|
this.element= element;
|
||||||
|
this.shellProvider= shellProvider;
|
||||||
|
this.project = cProject;
|
||||||
|
this.starter = new RefactoringStarter();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void run() {
|
||||||
|
RefactoringASTCache astCache = new RefactoringASTCache();
|
||||||
|
try {
|
||||||
|
run(astCache);
|
||||||
|
} finally {
|
||||||
|
astCache.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void run(RefactoringASTCache astCache);
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2008, 2009 Institute for Software, HSR Hochschule fuer Technik
|
* Copyright (c) 2008, 2011 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,17 +8,17 @@
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Institute for Software - initial API and implementation
|
* Institute for Software - initial API and implementation
|
||||||
|
* Sergey Prigogin (Google)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.ui.refactoring.gettersandsetters;
|
package org.eclipse.cdt.internal.ui.refactoring.gettersandsetters;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.eclipse.core.resources.IFile;
|
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
import org.eclipse.core.runtime.OperationCanceledException;
|
import org.eclipse.core.runtime.OperationCanceledException;
|
||||||
import org.eclipse.core.runtime.SubMonitor;
|
import org.eclipse.core.runtime.SubMonitor;
|
||||||
import org.eclipse.jface.text.Region;
|
|
||||||
import org.eclipse.jface.viewers.ISelection;
|
import org.eclipse.jface.viewers.ISelection;
|
||||||
import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
|
import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
|
||||||
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
|
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
|
||||||
|
@ -43,20 +43,20 @@ import org.eclipse.cdt.core.model.ICProject;
|
||||||
|
|
||||||
import org.eclipse.cdt.internal.core.dom.rewrite.astwriter.ContainerNode;
|
import org.eclipse.cdt.internal.core.dom.rewrite.astwriter.ContainerNode;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.ui.refactoring.CRefactoring2;
|
||||||
import org.eclipse.cdt.internal.ui.refactoring.AddDeclarationNodeToClassChange;
|
import org.eclipse.cdt.internal.ui.refactoring.AddDeclarationNodeToClassChange;
|
||||||
import org.eclipse.cdt.internal.ui.refactoring.CRefactoring;
|
|
||||||
import org.eclipse.cdt.internal.ui.refactoring.Container;
|
import org.eclipse.cdt.internal.ui.refactoring.Container;
|
||||||
import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector;
|
import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector;
|
||||||
import org.eclipse.cdt.internal.ui.refactoring.implementmethod.InsertLocation;
|
import org.eclipse.cdt.internal.ui.refactoring.RefactoringASTCache;
|
||||||
import org.eclipse.cdt.internal.ui.refactoring.implementmethod.MethodDefinitionInsertLocationFinder;
|
import org.eclipse.cdt.internal.ui.refactoring.implementmethod.InsertLocation2;
|
||||||
|
import org.eclipse.cdt.internal.ui.refactoring.implementmethod.MethodDefinitionInsertLocationFinder2;
|
||||||
import org.eclipse.cdt.internal.ui.refactoring.utils.NodeHelper;
|
import org.eclipse.cdt.internal.ui.refactoring.utils.NodeHelper;
|
||||||
import org.eclipse.cdt.internal.ui.refactoring.utils.SelectionHelper;
|
|
||||||
import org.eclipse.cdt.internal.ui.refactoring.utils.VisibilityEnum;
|
import org.eclipse.cdt.internal.ui.refactoring.utils.VisibilityEnum;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Thomas Corbat
|
* @author Thomas Corbat
|
||||||
*/
|
*/
|
||||||
public class GenerateGettersAndSettersRefactoring extends CRefactoring {
|
public class GenerateGettersAndSettersRefactoring extends CRefactoring2 {
|
||||||
|
|
||||||
private final class CompositeTypeSpecFinder extends ASTVisitor {
|
private final class CompositeTypeSpecFinder extends ASTVisitor {
|
||||||
private final int start;
|
private final int start;
|
||||||
|
@ -74,7 +74,7 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring {
|
||||||
public int visit(IASTDeclSpecifier declSpec) {
|
public int visit(IASTDeclSpecifier declSpec) {
|
||||||
if (declSpec instanceof IASTCompositeTypeSpecifier) {
|
if (declSpec instanceof IASTCompositeTypeSpecifier) {
|
||||||
IASTFileLocation loc = declSpec.getFileLocation();
|
IASTFileLocation loc = declSpec.getFileLocation();
|
||||||
if (start > loc.getNodeOffset() && start < loc.getNodeOffset()+ loc.getNodeLength()) {
|
if (start > loc.getNodeOffset() && start < loc.getNodeOffset() + loc.getNodeLength()) {
|
||||||
container.setObject((IASTCompositeTypeSpecifier) declSpec);
|
container.setObject((IASTCompositeTypeSpecifier) declSpec);
|
||||||
return ASTVisitor.PROCESS_ABORT;
|
return ASTVisitor.PROCESS_ABORT;
|
||||||
}
|
}
|
||||||
|
@ -85,12 +85,13 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String MEMBER_DECLARATION = "MEMBER_DECLARATION"; //$NON-NLS-1$
|
private static final String MEMBER_DECLARATION = "MEMBER_DECLARATION"; //$NON-NLS-1$
|
||||||
private final GetterAndSetterContext context = new GetterAndSetterContext();
|
private final GetterAndSetterContext context;
|
||||||
private InsertLocation definitionInsertLocation;
|
private InsertLocation2 definitionInsertLocation;
|
||||||
|
|
||||||
public GenerateGettersAndSettersRefactoring(IFile file, ISelection selection, ICElement element,
|
public GenerateGettersAndSettersRefactoring(ICElement element, ISelection selection,
|
||||||
ICProject project) {
|
ICProject project, RefactoringASTCache astCache) {
|
||||||
super(file, selection, element, project);
|
super(element, selection, project, astCache);
|
||||||
|
context = new GetterAndSetterContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -105,7 +106,7 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring {
|
||||||
|
|
||||||
if (!initStatus.hasFatalError()) {
|
if (!initStatus.hasFatalError()) {
|
||||||
initRefactoring(pm);
|
initRefactoring(pm);
|
||||||
if (context.existingFields.size() == 0) {
|
if (context.existingFields.isEmpty()) {
|
||||||
initStatus.addFatalError(Messages.GenerateGettersAndSettersRefactoring_NoFields);
|
initStatus.addFatalError(Messages.GenerateGettersAndSettersRefactoring_NoFields);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,30 +117,24 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring {
|
||||||
public RefactoringStatus checkFinalConditions(IProgressMonitor pm)
|
public RefactoringStatus checkFinalConditions(IProgressMonitor pm)
|
||||||
throws CoreException, OperationCanceledException {
|
throws CoreException, OperationCanceledException {
|
||||||
RefactoringStatus finalStatus = null;
|
RefactoringStatus finalStatus = null;
|
||||||
try {
|
|
||||||
lockIndex();
|
|
||||||
finalStatus = super.checkFinalConditions(pm);
|
finalStatus = super.checkFinalConditions(pm);
|
||||||
if (!context.isImplementationInHeader()) {
|
if (!context.isImplementationInHeader()) {
|
||||||
definitionInsertLocation = findInsertLocation();
|
definitionInsertLocation = findInsertLocation();
|
||||||
if (file.equals(definitionInsertLocation.getInsertFile())) {
|
if (definitionInsertLocation == null || tu.equals(definitionInsertLocation.getTranslationUnit())) {
|
||||||
finalStatus.addInfo(Messages.GenerateGettersAndSettersRefactoring_NoImplFile);
|
finalStatus.addInfo(Messages.GenerateGettersAndSettersRefactoring_NoImplFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
|
||||||
} finally {
|
|
||||||
unlockIndex();
|
|
||||||
}
|
|
||||||
return finalStatus;
|
return finalStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initRefactoring(IProgressMonitor pm) {
|
private void initRefactoring(IProgressMonitor pm) throws OperationCanceledException, CoreException {
|
||||||
loadTranslationUnit(initStatus, pm);
|
IASTTranslationUnit ast = astCache.getAST(tu, null);
|
||||||
context.selectedName = getSelectedName();
|
context.selectedName = getSelectedName(ast);
|
||||||
IASTCompositeTypeSpecifier compositeTypeSpecifier = null;
|
IASTCompositeTypeSpecifier compositeTypeSpecifier = null;
|
||||||
if (context.selectedName != null) {
|
if (context.selectedName != null) {
|
||||||
compositeTypeSpecifier = getCompositeTypeSpecifier(context.selectedName);
|
compositeTypeSpecifier = getCompositeTypeSpecifier(context.selectedName);
|
||||||
} else {
|
} else {
|
||||||
compositeTypeSpecifier = findCurrentCompositeTypeSpecifier();
|
compositeTypeSpecifier = findCurrentCompositeTypeSpecifier(ast);
|
||||||
}
|
}
|
||||||
if (compositeTypeSpecifier != null) {
|
if (compositeTypeSpecifier != null) {
|
||||||
findDeclarations(compositeTypeSpecifier);
|
findDeclarations(compositeTypeSpecifier);
|
||||||
|
@ -148,8 +143,9 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IASTCompositeTypeSpecifier findCurrentCompositeTypeSpecifier() {
|
private IASTCompositeTypeSpecifier findCurrentCompositeTypeSpecifier(IASTTranslationUnit ast)
|
||||||
final int start = region.getOffset();
|
throws OperationCanceledException, CoreException {
|
||||||
|
final int start = selectedRegion.getOffset();
|
||||||
Container<IASTCompositeTypeSpecifier> container = new Container<IASTCompositeTypeSpecifier>();
|
Container<IASTCompositeTypeSpecifier> container = new Container<IASTCompositeTypeSpecifier>();
|
||||||
ast.accept(new CompositeTypeSpecFinder(start, container));
|
ast.accept(new CompositeTypeSpecFinder(start, container));
|
||||||
return container.getObject();
|
return container.getObject();
|
||||||
|
@ -163,12 +159,12 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring {
|
||||||
return (IASTCompositeTypeSpecifier) node;
|
return (IASTCompositeTypeSpecifier) node;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IASTName getSelectedName() {
|
private IASTName getSelectedName(IASTTranslationUnit ast) {
|
||||||
ArrayList<IASTName> names = findAllMarkedNames();
|
List<IASTName> names = findAllMarkedNames(ast);
|
||||||
if (names.size() < 1) {
|
if (names.size() < 1) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return names.get(names.size()-1);
|
return names.get(names.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void findDeclarations(IASTCompositeTypeSpecifier compositeTypeSpecifier) {
|
protected void findDeclarations(IASTCompositeTypeSpecifier compositeTypeSpecifier) {
|
||||||
|
@ -191,14 +187,12 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring {
|
||||||
}
|
}
|
||||||
if ((innermostDeclarator instanceof IASTFunctionDeclarator)) {
|
if ((innermostDeclarator instanceof IASTFunctionDeclarator)) {
|
||||||
context.existingFunctionDeclarations.add(fieldDeclaration);
|
context.existingFunctionDeclarations.add(fieldDeclaration);
|
||||||
} else {
|
} else if (fieldDeclaration.isPartOfTranslationUnitFile()) {
|
||||||
if (SelectionHelper.isInSameFile(fieldDeclaration, file)) {
|
|
||||||
context.existingFields.add(fieldDeclaration);
|
context.existingFields.add(fieldDeclaration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (declaration instanceof IASTFunctionDefinition) {
|
if (declaration instanceof IASTFunctionDefinition) {
|
||||||
IASTFunctionDefinition functionDefinition = (IASTFunctionDefinition) declaration;
|
IASTFunctionDefinition functionDefinition = (IASTFunctionDefinition) declaration;
|
||||||
ASTNodeProperty props = functionDefinition.getPropertyInParent();
|
ASTNodeProperty props = functionDefinition.getPropertyInParent();
|
||||||
|
@ -214,10 +208,8 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring {
|
||||||
@Override
|
@Override
|
||||||
protected void collectModifications(IProgressMonitor pm,ModificationCollector collector)
|
protected void collectModifications(IProgressMonitor pm,ModificationCollector collector)
|
||||||
throws CoreException, OperationCanceledException {
|
throws CoreException, OperationCanceledException {
|
||||||
try {
|
List<IASTNode> getterAndSetters = new ArrayList<IASTNode>();
|
||||||
lockIndex();
|
List<IASTFunctionDefinition> definitions = new ArrayList<IASTFunctionDefinition>();
|
||||||
ArrayList<IASTNode> getterAndSetters = new ArrayList<IASTNode>();
|
|
||||||
ArrayList<IASTFunctionDefinition> definitions = new ArrayList<IASTFunctionDefinition>();
|
|
||||||
for (GetterSetterInsertEditProvider currentProvider : context.selectedFunctions) {
|
for (GetterSetterInsertEditProvider currentProvider : context.selectedFunctions) {
|
||||||
if (context.isImplementationInHeader()) {
|
if (context.isImplementationInHeader()) {
|
||||||
getterAndSetters.add(currentProvider.getFunctionDefinition(false));
|
getterAndSetters.add(currentProvider.getFunctionDefinition(false));
|
||||||
|
@ -234,18 +226,14 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring {
|
||||||
|
|
||||||
AddDeclarationNodeToClassChange.createChange(classDefinition, VisibilityEnum.v_public,
|
AddDeclarationNodeToClassChange.createChange(classDefinition, VisibilityEnum.v_public,
|
||||||
getterAndSetters, false, collector);
|
getterAndSetters, false, collector);
|
||||||
} catch (InterruptedException e) {
|
|
||||||
} finally {
|
|
||||||
unlockIndex();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addDefinition(ModificationCollector collector, ArrayList<IASTFunctionDefinition> definitions)
|
private void addDefinition(ModificationCollector collector, List<IASTFunctionDefinition> definitions)
|
||||||
throws CoreException {
|
throws CoreException {
|
||||||
InsertLocation location = findInsertLocation();
|
InsertLocation2 location = findInsertLocation();
|
||||||
IASTTranslationUnit targetUnit = location.getTargetTranslationUnit();
|
IASTNode parent = location.getParentOfNodeToInsertBefore();
|
||||||
IASTNode parent = location.getPartenOfNodeToInsertBefore();
|
IASTTranslationUnit ast = parent.getTranslationUnit();
|
||||||
ASTRewrite rewrite = collector.rewriterForTranslationUnit(targetUnit);
|
ASTRewrite rewrite = collector.rewriterForTranslationUnit(ast);
|
||||||
IASTNode nodeToInsertBefore = location.getNodeToInsertBefore();
|
IASTNode nodeToInsertBefore = location.getNodeToInsertBefore();
|
||||||
ContainerNode cont = new ContainerNode();
|
ContainerNode cont = new ContainerNode();
|
||||||
for (IASTFunctionDefinition functionDefinition : definitions) {
|
for (IASTFunctionDefinition functionDefinition : definitions) {
|
||||||
|
@ -258,18 +246,13 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring {
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Region getRegion() {
|
private InsertLocation2 findInsertLocation() throws CoreException {
|
||||||
return region;
|
|
||||||
}
|
|
||||||
|
|
||||||
private InsertLocation findInsertLocation() throws CoreException {
|
|
||||||
IASTSimpleDeclaration decl = context.existingFields.get(0);
|
IASTSimpleDeclaration decl = context.existingFields.get(0);
|
||||||
InsertLocation insertLocation = MethodDefinitionInsertLocationFinder.find(decl.getFileLocation(),
|
InsertLocation2 insertLocation = MethodDefinitionInsertLocationFinder2.find(
|
||||||
decl.getParent(), file);
|
decl.getFileLocation(), decl.getParent(), astCache);
|
||||||
|
|
||||||
if (!insertLocation.hasFile() || NodeHelper.isContainedInTemplateDeclaration(decl)) {
|
if (insertLocation.getFile() == null || NodeHelper.isContainedInTemplateDeclaration(decl)) {
|
||||||
insertLocation.setInsertFile(file);
|
insertLocation.setNodeToInsertAfter(NodeHelper.findTopLevelParent(decl), tu);
|
||||||
insertLocation.setNodeToInsertAfter(NodeHelper.findTopLevelParent(decl));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return insertLocation;
|
return insertLocation;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2008, 2009 Institute for Software, HSR Hochschule fuer Technik
|
* Copyright (c) 2008, 2011 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,44 +8,46 @@
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Institute for Software - initial API and implementation
|
* Institute for Software - initial API and implementation
|
||||||
|
* Sergey Prigogin (Google)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.ui.refactoring.gettersandsetters;
|
package org.eclipse.cdt.internal.ui.refactoring.gettersandsetters;
|
||||||
|
|
||||||
import org.eclipse.core.resources.IFile;
|
|
||||||
import org.eclipse.jface.viewers.ISelection;
|
import org.eclipse.jface.viewers.ISelection;
|
||||||
import org.eclipse.jface.window.IShellProvider;
|
import org.eclipse.jface.window.IShellProvider;
|
||||||
import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation;
|
import org.eclipse.ui.IEditorPart;
|
||||||
import org.eclipse.ui.PlatformUI;
|
import org.eclipse.ui.PlatformUI;
|
||||||
import org.eclipse.ui.texteditor.ITextEditor;
|
import org.eclipse.ui.texteditor.ITextEditor;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.model.ICElement;
|
import org.eclipse.cdt.core.model.ICElement;
|
||||||
import org.eclipse.cdt.core.model.ICProject;
|
import org.eclipse.cdt.core.model.ICProject;
|
||||||
|
|
||||||
import org.eclipse.cdt.internal.ui.refactoring.RefactoringRunner;
|
import org.eclipse.cdt.internal.ui.refactoring.RefactoringRunner2;
|
||||||
|
import org.eclipse.cdt.internal.ui.refactoring.RefactoringASTCache;
|
||||||
|
import org.eclipse.cdt.internal.ui.refactoring.RefactoringSaveHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Thomas Corbat
|
* @author Thomas Corbat
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class GenerateGettersAndSettersRefactoringRunner extends RefactoringRunner {
|
public class GenerateGettersAndSettersRefactoringRunner extends RefactoringRunner2 {
|
||||||
|
|
||||||
public GenerateGettersAndSettersRefactoringRunner(IFile file, ISelection selection,
|
public GenerateGettersAndSettersRefactoringRunner(ICElement element, ISelection selection,
|
||||||
ICElement elem, IShellProvider shellProvider, ICProject cProject) {
|
IShellProvider shellProvider, ICProject cProject) {
|
||||||
super(file, selection, elem, shellProvider, cProject);
|
super(element, selection, shellProvider, cProject);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run(RefactoringASTCache astCache) {
|
||||||
if (PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor() instanceof ITextEditor) {
|
if (getActiveEditor() instanceof ITextEditor) {
|
||||||
GenerateGettersAndSettersRefactoring refactoring = new GenerateGettersAndSettersRefactoring(file, selection, celement, project);
|
GenerateGettersAndSettersRefactoring refactoring =
|
||||||
GenerateGettersAndSettersRefactoringWizard wizard = new GenerateGettersAndSettersRefactoringWizard(refactoring);
|
new GenerateGettersAndSettersRefactoring(element, selection, project, astCache);
|
||||||
RefactoringWizardOpenOperation operator = new RefactoringWizardOpenOperation(wizard);
|
GenerateGettersAndSettersRefactoringWizard wizard =
|
||||||
|
new GenerateGettersAndSettersRefactoringWizard(refactoring);
|
||||||
|
starter.activate(wizard, shellProvider.getShell(), refactoring.getName(),
|
||||||
|
RefactoringSaveHelper.SAVE_REFACTORING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
private IEditorPart getActiveEditor() {
|
||||||
operator.run(shellProvider.getShell(), refactoring.getName());
|
return PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();
|
||||||
} catch (InterruptedException e) {
|
|
||||||
//initial condition checking got canceled by the user.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2008, 2011 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
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Institute for Software - initial API and implementation
|
||||||
|
* Sergey Prigogin (Google)
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.internal.ui.refactoring.implementmethod;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
|
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is returned when using the find method of the MethodDefinitionInsertLocationFinder.
|
||||||
|
* Contains all the information needed to insert at the correct position.
|
||||||
|
* This class is intended as a replacement for InsertLocation.
|
||||||
|
*
|
||||||
|
* @author Lukas Felber
|
||||||
|
*/
|
||||||
|
public class InsertLocation2 {
|
||||||
|
private IASTNode nodeToInsertAfter;
|
||||||
|
private IASTNode nodeToInsertBefore;
|
||||||
|
private IASTNode parentNode;
|
||||||
|
private ITranslationUnit tu;
|
||||||
|
|
||||||
|
public InsertLocation2() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasAnyNode() {
|
||||||
|
return nodeToInsertAfter != null || nodeToInsertBefore != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTNode getNodeToInsertBefore() {
|
||||||
|
return nodeToInsertBefore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTNode getParentOfNodeToInsertBefore() throws CoreException {
|
||||||
|
IASTNode node = nodeToInsertBefore != null ? nodeToInsertBefore : nodeToInsertAfter;
|
||||||
|
return node != null ? node.getParent() : parentNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITranslationUnit getTranslationUnit() {
|
||||||
|
return tu;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IFile getFile() {
|
||||||
|
return tu != null ? (IFile) tu.getResource() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getInsertPosition() {
|
||||||
|
if (nodeToInsertBefore != null) {
|
||||||
|
return nodeToInsertBefore.getFileLocation().getNodeOffset();
|
||||||
|
} else if (nodeToInsertAfter != null) {
|
||||||
|
return nodeToInsertAfter.getFileLocation().getNodeOffset() +
|
||||||
|
nodeToInsertAfter.getFileLocation().getNodeLength();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNodeToInsertAfter(IASTNode nodeToInsertAfter, ITranslationUnit tu) {
|
||||||
|
this.nodeToInsertAfter = nodeToInsertAfter;
|
||||||
|
this.tu = tu;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNodeToInsertBefore(IASTNode nodeToInsertBefore, ITranslationUnit tu) {
|
||||||
|
this.nodeToInsertBefore = nodeToInsertBefore;
|
||||||
|
this.tu = tu;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParentNode(IASTNode parentNode, ITranslationUnit tu) {
|
||||||
|
this.parentNode = parentNode;
|
||||||
|
this.tu = tu;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,129 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2008, 2011 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
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Institute for Software - initial API and implementation
|
||||||
|
* Sergey Prigogin (Google)
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.internal.ui.refactoring.implementmethod;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.ui.refactoring.RefactoringASTCache;
|
||||||
|
import org.eclipse.cdt.internal.ui.refactoring.utils.ASTNameInContext;
|
||||||
|
import org.eclipse.cdt.internal.ui.refactoring.utils.DefinitionFinder2;
|
||||||
|
import org.eclipse.cdt.internal.ui.refactoring.utils.NodeHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the information that are needed to tell where a method definition of a certain
|
||||||
|
* method declaration should be inserted.
|
||||||
|
* This class is intended as a replacement for MethodDefinitionInsertLocationFinder.
|
||||||
|
*
|
||||||
|
* @author Mirko Stocker, Lukas Felber
|
||||||
|
*/
|
||||||
|
public class MethodDefinitionInsertLocationFinder2 {
|
||||||
|
|
||||||
|
private static IASTNode findFunctionDefinitionInParents(IASTNode node) {
|
||||||
|
if (node == null) {
|
||||||
|
return null;
|
||||||
|
} else if (node instanceof IASTFunctionDefinition) {
|
||||||
|
if (node.getParent() instanceof ICPPASTTemplateDeclaration) {
|
||||||
|
node = node.getParent();
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
return findFunctionDefinitionInParents(node.getParent());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IASTNode findFirstSurroundingParentFunctionNode(IASTNode definition) {
|
||||||
|
IASTNode functionDefinitionInParents = findFunctionDefinitionInParents(definition);
|
||||||
|
if (functionDefinitionInParents == null ||
|
||||||
|
functionDefinitionInParents.getNodeLocations().length == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return functionDefinitionInParents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InsertLocation2 find(IASTFileLocation methodDeclarationLocation, IASTNode parent,
|
||||||
|
RefactoringASTCache astCache) throws CoreException {
|
||||||
|
IASTDeclaration[] declarations = NodeHelper.getDeclarations(parent);
|
||||||
|
InsertLocation2 insertLocation = new InsertLocation2();
|
||||||
|
|
||||||
|
for (IASTSimpleDeclaration simpleDeclaration : getAllPreviousSimpleDeclarationsFromClassInReverseOrder(
|
||||||
|
declarations, methodDeclarationLocation)) {
|
||||||
|
ASTNameInContext definition = DefinitionFinder2.getDefinition(simpleDeclaration, astCache);
|
||||||
|
if (definition != null) {
|
||||||
|
insertLocation.setNodeToInsertAfter(findFirstSurroundingParentFunctionNode(
|
||||||
|
definition.getName()), definition.getTranslationUnit());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (IASTSimpleDeclaration simpleDeclaration : getAllFollowingSimpleDeclarationsFromClass(
|
||||||
|
declarations, methodDeclarationLocation)) {
|
||||||
|
ASTNameInContext definition = DefinitionFinder2.getDefinition(simpleDeclaration, astCache);
|
||||||
|
if (definition != null) {
|
||||||
|
insertLocation.setNodeToInsertBefore(findFirstSurroundingParentFunctionNode(
|
||||||
|
definition.getName()), definition.getTranslationUnit());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return insertLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches the given class for all IASTSimpleDeclarations occurring before 'method'
|
||||||
|
* and returns them in reverse order.
|
||||||
|
*
|
||||||
|
* @param declarations to be searched
|
||||||
|
* @param methodPosition on which the search aborts
|
||||||
|
* @return all declarations, sorted in reverse order
|
||||||
|
*/
|
||||||
|
private static Collection<IASTSimpleDeclaration> getAllPreviousSimpleDeclarationsFromClassInReverseOrder(
|
||||||
|
IASTDeclaration[] declarations, IASTFileLocation methodPosition) {
|
||||||
|
ArrayList<IASTSimpleDeclaration> allIASTSimpleDeclarations = new ArrayList<IASTSimpleDeclaration>();
|
||||||
|
for (IASTDeclaration decl : declarations) {
|
||||||
|
if (decl.getFileLocation().getStartingLineNumber() >= methodPosition.getStartingLineNumber()) {
|
||||||
|
return allIASTSimpleDeclarations;
|
||||||
|
}
|
||||||
|
if (isMemberFunctionDeclaration(decl)) {
|
||||||
|
allIASTSimpleDeclarations.add(0, (IASTSimpleDeclaration) decl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allIASTSimpleDeclarations;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Collection<IASTSimpleDeclaration> getAllFollowingSimpleDeclarationsFromClass(
|
||||||
|
IASTDeclaration[] declarations, IASTFileLocation methodPosition) {
|
||||||
|
ArrayList<IASTSimpleDeclaration> allIASTSimpleDeclarations = new ArrayList<IASTSimpleDeclaration>();
|
||||||
|
|
||||||
|
for (IASTDeclaration decl : declarations) {
|
||||||
|
if (isMemberFunctionDeclaration(decl) &&
|
||||||
|
decl.getFileLocation().getStartingLineNumber() > methodPosition.getStartingLineNumber() ) {
|
||||||
|
allIASTSimpleDeclarations.add((IASTSimpleDeclaration) decl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allIASTSimpleDeclarations;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isMemberFunctionDeclaration(IASTDeclaration decl) {
|
||||||
|
return decl instanceof IASTSimpleDeclaration &&
|
||||||
|
((IASTSimpleDeclaration) decl).getDeclarators().length > 0 &&
|
||||||
|
((IASTSimpleDeclaration) decl).getDeclarators()[0] instanceof IASTFunctionDeclarator;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011 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.utils;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||||
|
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates an IASTName and the ITranslationUnit it belongs to.
|
||||||
|
*/
|
||||||
|
public class ASTNameInContext {
|
||||||
|
private final IASTName name;
|
||||||
|
private final ITranslationUnit tu;
|
||||||
|
|
||||||
|
ASTNameInContext(IASTName name, ITranslationUnit tu) {
|
||||||
|
this.name = name;
|
||||||
|
this.tu = tu;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTName getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITranslationUnit getTranslationUnit() {
|
||||||
|
return tu;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011 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.utils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.OperationCanceledException;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.IName;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
|
import org.eclipse.cdt.core.index.IIndexName;
|
||||||
|
import org.eclipse.cdt.core.model.CoreModelUtil;
|
||||||
|
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||||
|
import org.eclipse.cdt.ui.CUIPlugin;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.ui.refactoring.RefactoringASTCache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class to find definitions. This class is intended as a replacement for DefinitionFinder.
|
||||||
|
*/
|
||||||
|
public class DefinitionFinder2 {
|
||||||
|
|
||||||
|
public static ASTNameInContext getDefinition(IASTSimpleDeclaration simpleDeclaration,
|
||||||
|
RefactoringASTCache astCache) throws CoreException {
|
||||||
|
IASTDeclarator declarator = simpleDeclaration.getDeclarators()[0];
|
||||||
|
IBinding binding = declarator.getName().resolveBinding();
|
||||||
|
return getDefinition(binding, astCache);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ASTNameInContext getDefinition(IBinding binding, RefactoringASTCache astCache)
|
||||||
|
throws CoreException {
|
||||||
|
Set<String> searchedFiles = new HashSet<String>();
|
||||||
|
ITranslationUnit[] workingCopies = CUIPlugin.getSharedWorkingCopies();
|
||||||
|
List<ASTNameInContext> definitions = new ArrayList<ASTNameInContext>();
|
||||||
|
for (ITranslationUnit tu : workingCopies) {
|
||||||
|
findDefinitionsInTranslationUnit(binding, tu, astCache, definitions, null);
|
||||||
|
searchedFiles.add(tu.getLocation().toOSString());
|
||||||
|
}
|
||||||
|
|
||||||
|
IIndexName[] definitionsFromIndex = astCache.getIndex().findDefinitions(binding);
|
||||||
|
|
||||||
|
if (definitionsFromIndex.length > 0) {
|
||||||
|
for (IIndexName name : definitionsFromIndex) {
|
||||||
|
ITranslationUnit tu = CoreModelUtil.findTranslationUnitForLocation(
|
||||||
|
name.getFile().getLocation(), null);
|
||||||
|
if (searchedFiles.add(tu.getLocation().toOSString())) {
|
||||||
|
findDefinitionsInTranslationUnit(binding, tu, astCache, definitions, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (definitions.size() != 1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return definitions.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void findDefinitionsInTranslationUnit(IBinding binding, ITranslationUnit tu,
|
||||||
|
RefactoringASTCache astCache, List<ASTNameInContext> definitions, IProgressMonitor pm)
|
||||||
|
throws OperationCanceledException, CoreException {
|
||||||
|
IASTTranslationUnit ast = astCache.getAST(tu, pm);
|
||||||
|
findDefinitionsInAST(binding, ast, tu, definitions);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void findDefinitionsInAST(IBinding binding, IASTTranslationUnit ast,
|
||||||
|
ITranslationUnit tu, List<ASTNameInContext> definitions) {
|
||||||
|
for (IName definition : ast.getDefinitions(binding)) {
|
||||||
|
if (definition instanceof IASTName) {
|
||||||
|
definitions.add(new ASTNameInContext((IASTName) definition, tu));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2008, 2009 Institute for Software, HSR Hochschule fuer Technik
|
* Copyright (c) 2008, 2011 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,6 +8,7 @@
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Institute for Software - initial API and implementation
|
* Institute for Software - initial API and implementation
|
||||||
|
* Sergey Prigogin (Google)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.ui.refactoring.actions;
|
package org.eclipse.cdt.ui.refactoring.actions;
|
||||||
|
|
||||||
|
@ -33,35 +34,35 @@ public class GettersAndSettersAction extends RefactoringAction {
|
||||||
|
|
||||||
public GettersAndSettersAction() {
|
public GettersAndSettersAction() {
|
||||||
super(Messages.GettersAndSetters_label);
|
super(Messages.GettersAndSetters_label);
|
||||||
|
setSaveRequired(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 5.1
|
* @since 5.1
|
||||||
*/
|
*/
|
||||||
public GettersAndSettersAction(IEditorPart editor) {
|
public GettersAndSettersAction(IEditorPart editor) {
|
||||||
super(Messages.GettersAndSetters_label);
|
this();
|
||||||
setEditor(editor);
|
setEditor(editor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(IShellProvider shellProvider, ICElement elem) {
|
public void run(IShellProvider shellProvider, ICElement elem) {
|
||||||
new GenerateGettersAndSettersRefactoringRunner(null, null, elem, shellProvider, elem.getCProject()).run();
|
new GenerateGettersAndSettersRefactoringRunner(elem, null, shellProvider, elem.getCProject()).run();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(IShellProvider shellProvider, IWorkingCopy wc, ITextSelection s) {
|
public void run(IShellProvider shellProvider, IWorkingCopy wc, ITextSelection s) {
|
||||||
IResource res= wc.getResource();
|
IResource res= wc.getResource();
|
||||||
if (res instanceof IFile) {
|
if (res instanceof IFile) {
|
||||||
new GenerateGettersAndSettersRefactoringRunner((IFile) res, s, null, shellProvider, wc.getCProject()).run();
|
new GenerateGettersAndSettersRefactoringRunner(wc, s, shellProvider, wc.getCProject()).run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateSelection(ICElement elem) {
|
public void updateSelection(ICElement elem) {
|
||||||
super.updateSelection(elem);
|
super.updateSelection(elem);
|
||||||
if (elem instanceof IField == false
|
if (!(elem instanceof IField) || !(elem instanceof ISourceReference) ||
|
||||||
|| elem instanceof ISourceReference == false
|
!(((ISourceReference) elem).getTranslationUnit().getResource() instanceof IFile)) {
|
||||||
|| ((ISourceReference) elem).getTranslationUnit().getResource() instanceof IFile == false) {
|
|
||||||
setEnabled(false);
|
setEnabled(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue