1
0
Fork 0
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:
Sergey Prigogin 2011-01-10 03:59:38 +00:00
parent 0823fc1277
commit c12a4d8b9b
16 changed files with 937 additions and 167 deletions

View file

@ -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
* are made available under the terms of the Eclipse Public License v1.0
* 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.IEnumeration;
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.IFunctionType;
import org.eclipse.cdt.core.dom.ast.ILabel;
@ -1409,12 +1410,26 @@ public class CPPVisitor extends ASTQueries {
if (nameBinding.equals(binding)) {
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 (ArrayUtil.contains(((ICPPUsingDeclaration) nameBinding).getDelegates(), binding)) {
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;

View file

@ -914,32 +914,35 @@ getters=name
//@C.cpp
#include "C.h"
int Person::SocSecNo(){
namespace Personal {
int Person::SocSecNo() {
return socSecNo;
}
int main(int argc, char **argv) {
} // namespace Personal
int main(int argc, char **argv) {
}
//=
#include "C.h"
int Person::SocSecNo(){
namespace Personal {
char *Person::getName() const
{
return name;
}
int Person::SocSecNo() {
return socSecNo;
}
} // namespace Personal
int main(int argc, char **argv) {
}
char *Person::getName() const
{
return name;
}
//@C.h
#ifndef C_H_
#define C_H_

View file

@ -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
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@ -7,7 +7,8 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* 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;
@ -24,15 +25,16 @@ import org.eclipse.cdt.core.dom.IPDOMManager;
import org.eclipse.cdt.core.index.IIndexManager;
import org.eclipse.cdt.ui.testplugin.CTestPlugin;
import org.eclipse.cdt.internal.ui.refactoring.RefactoringASTCache;
/**
* @author Emanuel Graf
*
*/
public abstract class RefactoringTest extends RefactoringBaseTest {
private static final String CONFIG_FILE_NAME = ".config"; //$NON-NLS-1$
protected String fileName;
protected RefactoringASTCache astCache;
public RefactoringTest(String name, Vector<TestSourceFile> files) {
super(name, files);
@ -52,6 +54,13 @@ public abstract class RefactoringTest extends RefactoringBaseTest {
CCorePlugin.getIndexManager().reindex(cproject);
boolean joined = CCorePlugin.getIndexManager().joinIndexer(IIndexManager.FOREVER, NULL_PROGRESS_MONITOR);
assertTrue(joined);
astCache = new RefactoringASTCache();
}
@Override
protected void tearDown() throws Exception {
astCache.dispose();
super.tearDown();
}
private void initializeConfiguration(Vector<TestSourceFile> files) {
@ -76,7 +85,6 @@ public abstract class RefactoringTest extends RefactoringBaseTest {
initCommonFields(refactoringProperties);
configureRefactoring(refactoringProperties);
files.remove(configFile);
}
private void initCommonFields(Properties refactoringProperties) {
@ -84,8 +92,8 @@ public abstract class RefactoringTest extends RefactoringBaseTest {
}
protected void assertConditionsOk(RefactoringStatus conditions) {
assertTrue(conditions.isOK() ? "OK" : "Error or Warning in Conditions: " + conditions.getEntries()[0].getMessage() //$NON-NLS-1$ //$NON-NLS-2$
, conditions.isOK());
assertTrue(conditions.isOK() ? "OK" : "Error or Warning in Conditions: " + conditions.getEntries()[0].getMessage(), //$NON-NLS-1$ //$NON-NLS-2$
conditions.isOK());
}
protected void assertConditionsWarning(RefactoringStatus conditions, int number) {

View file

@ -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
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@ -7,12 +7,14 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Emanuel Graf & Leo Buettiker - initial API and implementation
* Thomas Corbat - implementation
* Emanuel Graf & Leo Buettiker - initial API and implementation
* Thomas Corbat - implementation
* Sergey Prigogin (Google)
******************************************************************************/
package org.eclipse.cdt.ui.tests.refactoring.gettersandsetters;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
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.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.TestSourceFile;
@ -30,19 +34,16 @@ import org.eclipse.cdt.internal.ui.refactoring.gettersandsetters.GetterAndSetter
/**
* @author Thomas Corbat
*
*/
public class GenerateGettersAndSettersTest extends RefactoringTest {
protected boolean fatalError;
private int warnings;
private ArrayList<String> selectedGetters;
private ArrayList<String> selectedSetters;
private List<String> selectedGetters;
private List<String> selectedSetters;
private GenerateGettersAndSettersRefactoring refactoring;
private boolean keepInHeader;
private int infos;
/**
* @param name
* @param files
@ -53,61 +54,54 @@ public class GenerateGettersAndSettersTest extends RefactoringTest {
@Override
protected void runTest() throws Throwable {
IFile refFile = project.getFile(fileName);
refactoring = new GenerateGettersAndSettersRefactoring(refFile, selection, null, cproject);
IFile file = project.getFile(fileName);
ICElement element = CoreModel.getDefault().create(file);
refactoring = new GenerateGettersAndSettersRefactoring(element, selection, cproject, astCache);
RefactoringStatus initialConditions = refactoring.checkInitialConditions(NULL_PROGRESS_MONITOR);
if(fatalError){
if (fatalError) {
assertConditionsFatalError(initialConditions);
return;
}
else{
} else {
assertConditionsOk(initialConditions);
executeRefactoring();
}
}
private void executeRefactoring() throws CoreException, Exception {
selectFields();
refactoring.getContext().setImplementationInHeader(keepInHeader);
RefactoringStatus finalConditions = refactoring.checkFinalConditions(NULL_PROGRESS_MONITOR);
Change createChange = refactoring.createChange(NULL_PROGRESS_MONITOR);
if(warnings > 0){
if (warnings > 0) {
assertConditionsWarning(finalConditions, warnings);
}else if(infos >0) {
} else if (infos > 0) {
assertConditionsInfo(finalConditions, infos);
}
else{
} else {
assertConditionsOk(finalConditions);
}
createChange.perform(NULL_PROGRESS_MONITOR);
compareFiles(fileMap);
}
private void selectFields() {
GetterAndSetterContext context = refactoring.getContext();
for(IASTSimpleDeclaration currentDecl : context.existingFields){
for (IASTSimpleDeclaration currentDecl : context.existingFields) {
String name = currentDecl.getDeclarators()[0].getName().getRawSignature();
if(selectedGetters.contains(name) ){
if (selectedGetters.contains(name)) {
selectedGetters.remove(name);
context.selectedFunctions.add(context.createGetterInserter(currentDecl));
}
if(selectedSetters.contains(name) ){
if (selectedSetters.contains(name)) {
selectedSetters.remove(name);
context.selectedFunctions.add(context.createSetterInserter(currentDecl));
}
}
}
@Override
protected void configureRefactoring(Properties refactoringProperties) {
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"));
selectedGetters = new ArrayList<String>();
for(String getterName : getters.split(",")){ //$NON-NLS-1$
for (String getterName : getters.split(",")) { //$NON-NLS-1$
selectedGetters.add(getterName);
}
selectedSetters = new ArrayList<String>();
for(String setterName : setters.split(",")){ //$NON-NLS-1$
for (String setterName : setters.split(",")) { //$NON-NLS-1$
selectedSetters.add(setterName);
}
}
}

View file

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

View file

@ -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
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@ -7,14 +7,14 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* 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;
import org.eclipse.osgi.util.NLS;
public final class Messages extends NLS {
public static String DeleteFileChange_0;
public static String DeleteFileChange_1;
public static String Refactoring_name;
@ -33,6 +33,7 @@ public final class Messages extends NLS {
public static String Refactoring_SelectionNotValid;
public static String Refactoring_CantLoadTU;
public static String Refactoring_Ambiguity;
public static String Refactoring_ParsingError;
public static String NodeContainer_Name;
public static String NO_FILE;
public static String RefactoringSaveHelper_unexpected_exception;

View file

@ -7,7 +7,8 @@
# http://www.eclipse.org/legal/epl-v10.html
#
# Contributors:
# Institute for Software - initial API and implementation
# Institute for Software - initial API and implementation
# Sergey Prigogin (Google)
###############################################################################
DeleteFileChange_0=Delete File
DeleteFileChange_1=File doesn't exist.
@ -18,7 +19,7 @@ Refactoring_PM_InitRef=Initialize Refactoring
Refactoring_PM_ParseTU=Parse Translation Unit
Refactoring_PM_MergeComments=Merge Comments
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}.
CreateFileChange_CreateFile=Create file: {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_CantLoadTU=Can not load translation unit.
Refactoring_Ambiguity=Translation unit is ambiguous.
Refactoring_ParsingError=Unable to parse {0}.
NO_FILE=File not found.
NodeContainer_Name=name:
RefactoringSaveHelper_unexpected_exception=An unexpected exception occurred. See the error log for more details.

View file

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

View file

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

View file

@ -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
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@ -7,18 +7,18 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* 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;
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.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
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.ui.refactoring.CRefactoring2;
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.ModificationCollector;
import org.eclipse.cdt.internal.ui.refactoring.implementmethod.InsertLocation;
import org.eclipse.cdt.internal.ui.refactoring.implementmethod.MethodDefinitionInsertLocationFinder;
import org.eclipse.cdt.internal.ui.refactoring.RefactoringASTCache;
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.SelectionHelper;
import org.eclipse.cdt.internal.ui.refactoring.utils.VisibilityEnum;
/**
* @author Thomas Corbat
*/
public class GenerateGettersAndSettersRefactoring extends CRefactoring {
public class GenerateGettersAndSettersRefactoring extends CRefactoring2 {
private final class CompositeTypeSpecFinder extends ASTVisitor {
private final int start;
@ -74,7 +74,7 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring {
public int visit(IASTDeclSpecifier declSpec) {
if (declSpec instanceof IASTCompositeTypeSpecifier) {
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);
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 final GetterAndSetterContext context = new GetterAndSetterContext();
private InsertLocation definitionInsertLocation;
private final GetterAndSetterContext context;
private InsertLocation2 definitionInsertLocation;
public GenerateGettersAndSettersRefactoring(IFile file, ISelection selection, ICElement element,
ICProject project) {
super(file, selection, element, project);
public GenerateGettersAndSettersRefactoring(ICElement element, ISelection selection,
ICProject project, RefactoringASTCache astCache) {
super(element, selection, project, astCache);
context = new GetterAndSetterContext();
}
@Override
@ -105,7 +106,7 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring {
if (!initStatus.hasFatalError()) {
initRefactoring(pm);
if (context.existingFields.size() == 0) {
if (context.existingFields.isEmpty()) {
initStatus.addFatalError(Messages.GenerateGettersAndSettersRefactoring_NoFields);
}
}
@ -116,30 +117,24 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring {
public RefactoringStatus checkFinalConditions(IProgressMonitor pm)
throws CoreException, OperationCanceledException {
RefactoringStatus finalStatus = null;
try {
lockIndex();
finalStatus = super.checkFinalConditions(pm);
if (!context.isImplementationInHeader()) {
definitionInsertLocation = findInsertLocation();
if (file.equals(definitionInsertLocation.getInsertFile())) {
finalStatus.addInfo(Messages.GenerateGettersAndSettersRefactoring_NoImplFile);
}
finalStatus = super.checkFinalConditions(pm);
if (!context.isImplementationInHeader()) {
definitionInsertLocation = findInsertLocation();
if (definitionInsertLocation == null || tu.equals(definitionInsertLocation.getTranslationUnit())) {
finalStatus.addInfo(Messages.GenerateGettersAndSettersRefactoring_NoImplFile);
}
} catch (InterruptedException e) {
} finally {
unlockIndex();
}
return finalStatus;
}
private void initRefactoring(IProgressMonitor pm) {
loadTranslationUnit(initStatus, pm);
context.selectedName = getSelectedName();
private void initRefactoring(IProgressMonitor pm) throws OperationCanceledException, CoreException {
IASTTranslationUnit ast = astCache.getAST(tu, null);
context.selectedName = getSelectedName(ast);
IASTCompositeTypeSpecifier compositeTypeSpecifier = null;
if (context.selectedName != null) {
compositeTypeSpecifier = getCompositeTypeSpecifier(context.selectedName);
} else {
compositeTypeSpecifier = findCurrentCompositeTypeSpecifier();
compositeTypeSpecifier = findCurrentCompositeTypeSpecifier(ast);
}
if (compositeTypeSpecifier != null) {
findDeclarations(compositeTypeSpecifier);
@ -148,8 +143,9 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring {
}
}
private IASTCompositeTypeSpecifier findCurrentCompositeTypeSpecifier() {
final int start = region.getOffset();
private IASTCompositeTypeSpecifier findCurrentCompositeTypeSpecifier(IASTTranslationUnit ast)
throws OperationCanceledException, CoreException {
final int start = selectedRegion.getOffset();
Container<IASTCompositeTypeSpecifier> container = new Container<IASTCompositeTypeSpecifier>();
ast.accept(new CompositeTypeSpecFinder(start, container));
return container.getObject();
@ -163,12 +159,12 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring {
return (IASTCompositeTypeSpecifier) node;
}
private IASTName getSelectedName() {
ArrayList<IASTName> names = findAllMarkedNames();
private IASTName getSelectedName(IASTTranslationUnit ast) {
List<IASTName> names = findAllMarkedNames(ast);
if (names.size() < 1) {
return null;
}
return names.get(names.size()-1);
return names.get(names.size() - 1);
}
protected void findDeclarations(IASTCompositeTypeSpecifier compositeTypeSpecifier) {
@ -191,10 +187,8 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring {
}
if ((innermostDeclarator instanceof IASTFunctionDeclarator)) {
context.existingFunctionDeclarations.add(fieldDeclaration);
} else {
if (SelectionHelper.isInSameFile(fieldDeclaration, file)) {
context.existingFields.add(fieldDeclaration);
}
} else if (fieldDeclaration.isPartOfTranslationUnitFile()) {
context.existingFields.add(fieldDeclaration);
}
}
}
@ -214,38 +208,32 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring {
@Override
protected void collectModifications(IProgressMonitor pm,ModificationCollector collector)
throws CoreException, OperationCanceledException {
try {
lockIndex();
ArrayList<IASTNode> getterAndSetters = new ArrayList<IASTNode>();
ArrayList<IASTFunctionDefinition> definitions = new ArrayList<IASTFunctionDefinition>();
for (GetterSetterInsertEditProvider currentProvider : context.selectedFunctions) {
if (context.isImplementationInHeader()) {
getterAndSetters.add(currentProvider.getFunctionDefinition(false));
} else {
getterAndSetters.add(currentProvider.getFunctionDeclaration());
definitions.add(currentProvider.getFunctionDefinition(true));
}
List<IASTNode> getterAndSetters = new ArrayList<IASTNode>();
List<IASTFunctionDefinition> definitions = new ArrayList<IASTFunctionDefinition>();
for (GetterSetterInsertEditProvider currentProvider : context.selectedFunctions) {
if (context.isImplementationInHeader()) {
getterAndSetters.add(currentProvider.getFunctionDefinition(false));
} else {
getterAndSetters.add(currentProvider.getFunctionDeclaration());
definitions.add(currentProvider.getFunctionDefinition(true));
}
if (!context.isImplementationInHeader()) {
addDefinition(collector, definitions);
}
ICPPASTCompositeTypeSpecifier classDefinition =
(ICPPASTCompositeTypeSpecifier) context.existingFields.get(context.existingFields.size() - 1).getParent();
AddDeclarationNodeToClassChange.createChange(classDefinition, VisibilityEnum.v_public,
getterAndSetters, false, collector);
} catch (InterruptedException e) {
} finally {
unlockIndex();
}
if (!context.isImplementationInHeader()) {
addDefinition(collector, definitions);
}
ICPPASTCompositeTypeSpecifier classDefinition =
(ICPPASTCompositeTypeSpecifier) context.existingFields.get(context.existingFields.size() - 1).getParent();
AddDeclarationNodeToClassChange.createChange(classDefinition, VisibilityEnum.v_public,
getterAndSetters, false, collector);
}
private void addDefinition(ModificationCollector collector, ArrayList<IASTFunctionDefinition> definitions)
private void addDefinition(ModificationCollector collector, List<IASTFunctionDefinition> definitions)
throws CoreException {
InsertLocation location = findInsertLocation();
IASTTranslationUnit targetUnit = location.getTargetTranslationUnit();
IASTNode parent = location.getPartenOfNodeToInsertBefore();
ASTRewrite rewrite = collector.rewriterForTranslationUnit(targetUnit);
InsertLocation2 location = findInsertLocation();
IASTNode parent = location.getParentOfNodeToInsertBefore();
IASTTranslationUnit ast = parent.getTranslationUnit();
ASTRewrite rewrite = collector.rewriterForTranslationUnit(ast);
IASTNode nodeToInsertBefore = location.getNodeToInsertBefore();
ContainerNode cont = new ContainerNode();
for (IASTFunctionDefinition functionDefinition : definitions) {
@ -258,18 +246,13 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring {
return context;
}
public Region getRegion() {
return region;
}
private InsertLocation findInsertLocation() throws CoreException {
private InsertLocation2 findInsertLocation() throws CoreException {
IASTSimpleDeclaration decl = context.existingFields.get(0);
InsertLocation insertLocation = MethodDefinitionInsertLocationFinder.find(decl.getFileLocation(),
decl.getParent(), file);
InsertLocation2 insertLocation = MethodDefinitionInsertLocationFinder2.find(
decl.getFileLocation(), decl.getParent(), astCache);
if (!insertLocation.hasFile() || NodeHelper.isContainedInTemplateDeclaration(decl)) {
insertLocation.setInsertFile(file);
insertLocation.setNodeToInsertAfter(NodeHelper.findTopLevelParent(decl));
if (insertLocation.getFile() == null || NodeHelper.isContainedInTemplateDeclaration(decl)) {
insertLocation.setNodeToInsertAfter(NodeHelper.findTopLevelParent(decl), tu);
}
return insertLocation;

View file

@ -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
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@ -7,45 +7,47 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* 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;
import org.eclipse.core.resources.IFile;
import org.eclipse.jface.viewers.ISelection;
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.texteditor.ITextEditor;
import org.eclipse.cdt.core.model.ICElement;
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
*
*/
public class GenerateGettersAndSettersRefactoringRunner extends RefactoringRunner {
public class GenerateGettersAndSettersRefactoringRunner extends RefactoringRunner2 {
public GenerateGettersAndSettersRefactoringRunner(IFile file, ISelection selection,
ICElement elem, IShellProvider shellProvider, ICProject cProject) {
super(file, selection, elem, shellProvider, cProject);
public GenerateGettersAndSettersRefactoringRunner(ICElement element, ISelection selection,
IShellProvider shellProvider, ICProject cProject) {
super(element, selection, shellProvider, cProject);
}
@Override
public void run() {
if (PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor() instanceof ITextEditor) {
GenerateGettersAndSettersRefactoring refactoring = new GenerateGettersAndSettersRefactoring(file, selection, celement, project);
GenerateGettersAndSettersRefactoringWizard wizard = new GenerateGettersAndSettersRefactoringWizard(refactoring);
RefactoringWizardOpenOperation operator = new RefactoringWizardOpenOperation(wizard);
try {
operator.run(shellProvider.getShell(), refactoring.getName());
} catch (InterruptedException e) {
//initial condition checking got canceled by the user.
}
public void run(RefactoringASTCache astCache) {
if (getActiveEditor() instanceof ITextEditor) {
GenerateGettersAndSettersRefactoring refactoring =
new GenerateGettersAndSettersRefactoring(element, selection, project, astCache);
GenerateGettersAndSettersRefactoringWizard wizard =
new GenerateGettersAndSettersRefactoringWizard(refactoring);
starter.activate(wizard, shellProvider.getShell(), refactoring.getName(),
RefactoringSaveHelper.SAVE_REFACTORING);
}
}
private IEditorPart getActiveEditor() {
return PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();
}
}

View file

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

View file

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

View file

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

View file

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

View file

@ -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
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@ -7,7 +7,8 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* 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;
@ -33,35 +34,35 @@ public class GettersAndSettersAction extends RefactoringAction {
public GettersAndSettersAction() {
super(Messages.GettersAndSetters_label);
setSaveRequired(false);
}
/**
* @since 5.1
*/
public GettersAndSettersAction(IEditorPart editor) {
super(Messages.GettersAndSetters_label);
this();
setEditor(editor);
}
@Override
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
public void run(IShellProvider shellProvider, IWorkingCopy wc, ITextSelection s) {
IResource res= wc.getResource();
if (res instanceof IFile) {
new GenerateGettersAndSettersRefactoringRunner((IFile) res, s, null, shellProvider, wc.getCProject()).run();
new GenerateGettersAndSettersRefactoringRunner(wc, s, shellProvider, wc.getCProject()).run();
}
}
@Override
public void updateSelection(ICElement elem) {
super.updateSelection(elem);
if (elem instanceof IField == false
|| elem instanceof ISourceReference == false
|| ((ISourceReference) elem).getTranslationUnit().getResource() instanceof IFile == false) {
if (!(elem instanceof IField) || !(elem instanceof ISourceReference) ||
!(((ISourceReference) elem).getTranslationUnit().getResource() instanceof IFile)) {
setEnabled(false);
}
}