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 * 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;

View file

@ -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;
} }
} // namespace Personal
int main(int argc, char **argv) { 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_

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 * 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
@ -7,7 +7,8 @@
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* 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,16 +25,17 @@ 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);
initializeConfiguration(files); initializeConfiguration(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) {

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 * 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
@ -7,12 +7,14 @@
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* 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,60 +54,53 @@ 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) {
@ -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);
} }
} }
} }

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 * 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
@ -7,14 +7,14 @@
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* 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;

View file

@ -7,7 +7,8 @@
# http://www.eclipse.org/legal/epl-v10.html # http://www.eclipse.org/legal/epl-v10.html
# #
# 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.

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 * 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
@ -7,18 +7,18 @@
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* 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 { finalStatus = super.checkFinalConditions(pm);
lockIndex(); if (!context.isImplementationInHeader()) {
finalStatus = super.checkFinalConditions(pm); definitionInsertLocation = findInsertLocation();
if (!context.isImplementationInHeader()) { if (definitionInsertLocation == null || tu.equals(definitionInsertLocation.getTranslationUnit())) {
definitionInsertLocation = findInsertLocation(); finalStatus.addInfo(Messages.GenerateGettersAndSettersRefactoring_NoImplFile);
if (file.equals(definitionInsertLocation.getInsertFile())) {
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,10 +187,8 @@ 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);
}
} }
} }
} }
@ -214,38 +208,32 @@ 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>(); for (GetterSetterInsertEditProvider currentProvider : context.selectedFunctions) {
ArrayList<IASTFunctionDefinition> definitions = new ArrayList<IASTFunctionDefinition>(); if (context.isImplementationInHeader()) {
for (GetterSetterInsertEditProvider currentProvider : context.selectedFunctions) { getterAndSetters.add(currentProvider.getFunctionDefinition(false));
if (context.isImplementationInHeader()) { } else {
getterAndSetters.add(currentProvider.getFunctionDefinition(false)); getterAndSetters.add(currentProvider.getFunctionDeclaration());
} else { definitions.add(currentProvider.getFunctionDefinition(true));
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 { 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,20 +246,15 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring {
return context; return context;
} }
public Region getRegion() { private InsertLocation2 findInsertLocation() throws CoreException {
return region; IASTSimpleDeclaration decl = context.existingFields.get(0);
} InsertLocation2 insertLocation = MethodDefinitionInsertLocationFinder2.find(
decl.getFileLocation(), decl.getParent(), astCache);
private InsertLocation findInsertLocation() throws CoreException {
IASTSimpleDeclaration decl = context.existingFields.get(0);
InsertLocation insertLocation = MethodDefinitionInsertLocationFinder.find(decl.getFileLocation(),
decl.getParent(), file);
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;
} }

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 * 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
@ -7,45 +7,47 @@
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* 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);
try { starter.activate(wizard, shellProvider.getShell(), refactoring.getName(),
operator.run(shellProvider.getShell(), refactoring.getName()); RefactoringSaveHelper.SAVE_REFACTORING);
} catch (InterruptedException e) {
//initial condition checking got canceled by the user.
}
} }
} }
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,13 +1,14 @@
/******************************************************************************* /*******************************************************************************
* 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
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* 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;
@ -30,38 +31,38 @@ import org.eclipse.cdt.internal.ui.refactoring.gettersandsetters.GenerateGetters
* @noextend This class is not intended to be subclassed by clients. * @noextend This class is not intended to be subclassed by clients.
*/ */
public class GettersAndSettersAction extends RefactoringAction { 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);
} }
} }