1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 22:52:11 +02:00

Bug 337040 - MethodDefinitionInsertLocationFinder2 does not find implementation file when no definition already present. Patch by Marc-Andre Laperle.

This commit is contained in:
Sergey Prigogin 2011-02-19 21:38:56 +00:00
parent 29552b6bcf
commit 3715cdbbe8
8 changed files with 544 additions and 309 deletions

View file

@ -26,11 +26,13 @@ import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.testplugin.CProjectHelper;
import org.eclipse.cdt.core.testplugin.FileManager;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
/**
@ -42,13 +44,13 @@ abstract public class BaseTestFramework extends TestCase {
static protected IProject project;
static protected ICProject cproject;
static protected FileManager fileManager;
static protected boolean indexDisabled=false;
static protected boolean indexDisabled= false;
static void initProject() {
if (project != null) {
return;
}
if( CCorePlugin.getDefault() != null && CCorePlugin.getDefault().getCoreModel() != null){
if (CCorePlugin.getDefault() != null && CCorePlugin.getDefault().getCoreModel() != null) {
//(CCorePlugin.getDefault().getCoreModel().getIndexManager()).reset();
monitor = new NullProgressMonitor();
@ -59,14 +61,11 @@ abstract public class BaseTestFramework extends TestCase {
project = cproject.getProject();
/*project.setSessionProperty(SourceIndexer.activationKey, Boolean.FALSE );
/*project.setSessionProperty(SourceIndexer.activationKey, Boolean.FALSE);
//Set the id of the source indexer extension point as a session property to allow
//index manager to instantiate it
project.setSessionProperty(IndexManager.indexerIDKey, sourceIndexerID);*/
} catch ( CoreException e ) {
} catch (CoreException e) {
/*boo*/
}
if (project == null)
@ -77,22 +76,21 @@ abstract public class BaseTestFramework extends TestCase {
}
}
public BaseTestFramework()
{
public BaseTestFramework() {
super();
}
/**
* @param name
*/
public BaseTestFramework(String name)
{
public BaseTestFramework(String name) {
super(name);
}
public void cleanupProject() throws Exception {
try{
project.delete( true, false, monitor );
} catch( Throwable e ){
project.delete(true, false, monitor);
} catch (Throwable e) {
/*boo*/
} finally {
project= null;
@ -106,36 +104,50 @@ abstract public class BaseTestFramework extends TestCase {
}
protected void tearDown() throws Exception {
if( project == null || !project.exists() )
if (project == null || !project.exists())
return;
IResource [] members = project.members();
for( int i = 0; i < members.length; i++ ){
if( members[i].getName().equals( ".project" ) || members[i].getName().equals( ".cproject" ) ) //$NON-NLS-1$ //$NON-NLS-2$
for (int i = 0; i < members.length; i++) {
if (members[i].getName().equals(".project") || members[i].getName().equals(".cproject")) //$NON-NLS-1$ //$NON-NLS-2$
continue;
if (members[i].getName().equals(".settings"))
continue;
try{
members[i].delete( false, monitor );
} catch( Throwable e ){
try {
members[i].delete(false, monitor);
} catch (Throwable e) {
/*boo*/
}
}
}
protected IFile importFile(String fileName, String contents ) throws Exception{
//Obtain file handle
protected IFile importFile(String fileName, String contents) throws Exception {
// Obtain file handle
IFile file = project.getProject().getFile(fileName);
InputStream stream = new ByteArrayInputStream( contents.getBytes() );
//Create file input stream
if( file.exists() )
file.setContents( stream, false, false, monitor );
else
file.create( stream, false, monitor );
InputStream stream = new ByteArrayInputStream(contents.getBytes());
// Create file input stream
if (file.exists()) {
file.setContents(stream, false, false, monitor);
} else {
IPath path = file.getLocation();
path = path.makeRelativeTo(project.getLocation());
if (path.segmentCount() > 1) {
path = path.removeLastSegments(1);
for (int i = path.segmentCount() - 1; i >= 0; i--) {
IPath currentPath = path.removeLastSegments(i);
IFolder folder = project.getFolder(currentPath);
if (!folder.exists()) {
folder.create(false, true, null);
}
}
}
file.create(stream, false, monitor);
}
fileManager.addFile(file);
return file;
}
}

View file

@ -1458,6 +1458,7 @@ namespace foo
}
}
//=
#include "Test.h"
@ -1478,3 +1479,103 @@ namespace foo
}
}
//!Bug 337040 - Insert definition in empty implementation file (.cxx)
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
//@.config
filename=Test.h
getters=testField
setters=testField
//@Test.h
#ifndef TEST_H_
#define TEST_H_
class Test
{
int /*$*/testField/*$$*/;
};
#endif
//=
#ifndef TEST_H_
#define TEST_H_
class Test
{
int testField;
public:
int getTestField() const;
void setTestField(int testField);
};
#endif
//@Test.cxx
//=
int Test::getTestField() const
{
return testField;
}
void Test::setTestField(int testField)
{
this->testField = testField;
}
//!Bug 337040 - Insert definition in empty implementation file in complex directory structure
//#org.eclipse.cdt.ui.tests.refactoring.gettersandsetters.GenerateGettersAndSettersTest
//@.config
filename=component_b/public_headers/Test.h
getters=testField
setters=testField
//@component_b/public_headers/Test.h
#ifndef TEST_H_
#define TEST_H_
class Test
{
int /*$*/testField/*$$*/;
};
#endif
//=
#ifndef TEST_H_
#define TEST_H_
class Test
{
int testField;
public:
int getTestField() const;
void setTestField(int testField);
};
#endif
//@component_b/implementation/Test.cpp
//=
int Test::getTestField() const
{
return testField;
}
void Test::setTestField(int testField)
{
this->testField = testField;
}
//@component_a/public_headers/Test.h
//=
//@component_a/implementation/Test.cpp
//=

View file

@ -811,3 +811,25 @@ void n1::n2::A::B::testmethod2()
//!Bug 337040 - Insert definition in empty implementation file (.cxx)
//#org.eclipse.cdt.ui.tests.refactoring.implementmethod.ImplementMethodRefactoringTest
//@.config
filename=A.h
//@A.h
class TestClass {
public:
/*$*/void foo();/*$$*/
};
//@A.cxx
//=
void TestClass::foo()
{
}

View file

@ -0,0 +1,355 @@
/*******************************************************************************
* Copyright (c) 2007, 2011 Wind River Systems, 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:
* Anton Leherbauer (Wind River Systems) - initial API and implementation
* Markus Schorn (Wind River Systems)
* Marc-Andre Laperle - Extracted Util class from ToggleSourceHeaderAction
*******************************************************************************/
package org.eclipse.cdt.internal.ui.editor;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceProxy;
import org.eclipse.core.resources.IResourceProxyVisitor;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.core.runtime.content.IContentTypeManager;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexName;
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.ui.CUIPlugin;
import org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable;
import org.eclipse.cdt.internal.ui.refactoring.RefactoringASTCache;
/**
* A collection of static methods for finding the source file corresponding to a header
* and vice versa.
*/
public final class SourceHeaderPartnerFinder {
private static class Counter {
public int fCount;
}
private SourceHeaderPartnerFinder() {
}
/**
* Compute the partner file for a translation unit.
* The partner file is the corresponding source or header file
* based on heuristics.
*
* @since 4.0
*/
private static class PartnerFileComputer implements ASTRunnable {
PartnerFileVisitor fVisitor = null;
public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) {
if (ast != null && ast.getIndex() != null) {
fVisitor = new PartnerFileVisitor();
ast.accept(fVisitor);
}
return Status.OK_STATUS;
}
public IPath getPartnerFileLocation() {
if(fVisitor != null) {
return fVisitor.getPartnerFileLocation();
}
return null;
}
}
private static class PartnerFileVisitor extends ASTVisitor {
/**
* When this many times the same partner file is hit,
* we are confident enough to take it.
*/
private static final int CONFIDENCE_LIMIT = 15;
/**
* When this many times no match was found in the index,
* we suspect that we won't get a good partner.
*/
private static final int SUSPECT_LIMIT = 15;
private IIndex fIndex;
private IPath fFilePath;
private Map<IPath, Counter> fMap;
/** The confidence level == number of hits */
private int fConfidence;
/** Suspect level == number of no index matches */
private int fSuspect;
/** The current favorite partner file */
private IPath fFavoriteLocation;
{
shouldVisitDeclarators= true;
shouldVisitTranslationUnit = true;
}
public PartnerFileVisitor() {
fMap= new HashMap<IPath, Counter>();
}
@Override
public int visit(IASTTranslationUnit tu) {
fIndex= tu.getIndex();
if(fIndex == null) {
return PROCESS_ABORT;
}
fFilePath= Path.fromOSString(tu.getFilePath());
return super.visit(tu);
}
public IPath getPartnerFileLocation() {
return fFavoriteLocation;
}
/*
* @see org.eclipse.cdt.core.dom.ast.ASTVisitor#visit(org.eclipse.cdt.core.dom.ast.IASTDeclarator)
*/
@Override
public int visit(IASTDeclarator declarator) {
if (declarator instanceof IASTFunctionDeclarator) {
IASTName name= declarator.getName();
if (name != null && declarator.getNestedDeclarator() == null) {
IBinding binding= name.resolveBinding();
if (binding != null && !(binding instanceof IProblemBinding)) {
boolean isDefinition= name.isDefinition();
final IIndexName[] partnerNames;
try {
if (isDefinition) {
partnerNames= fIndex.findNames(binding,
IIndex.FIND_DECLARATIONS | IIndex.SEARCH_ACROSS_LANGUAGE_BOUNDARIES);
} else {
partnerNames= fIndex.findNames(binding,
IIndex.FIND_DEFINITIONS | IIndex.SEARCH_ACROSS_LANGUAGE_BOUNDARIES);
}
if (partnerNames.length == 0) {
++fSuspect;
if (fSuspect == SUSPECT_LIMIT) {
fFavoriteLocation= null;
return PROCESS_ABORT;
}
}
for (int i= 0; i < partnerNames.length; i++) {
IIndexName partnerName= partnerNames[i];
IASTFileLocation partnerLocation= partnerName.getFileLocation();
if (partnerLocation != null) {
IPath partnerFileLocation= Path.fromOSString(partnerLocation.getFileName());
if (!fFilePath.equals(partnerFileLocation)) {
addPotentialPartnerFileLocation(partnerFileLocation);
if (fConfidence == CONFIDENCE_LIMIT) {
return PROCESS_ABORT;
}
}
}
}
} catch (CoreException exc) {
CUIPlugin.log(exc.getStatus());
}
}
}
}
return PROCESS_SKIP;
}
private void addPotentialPartnerFileLocation(IPath partnerFileLocation) {
Counter counter= fMap.get(partnerFileLocation);
if (counter == null) {
counter= new Counter();
fMap.put(partnerFileLocation, counter);
}
++counter.fCount;
if (counter.fCount > fConfidence) {
fConfidence= counter.fCount;
fFavoriteLocation= partnerFileLocation;
}
}
}
/**
* Finds a file in the given resource container for the given basename.
*
* @param container
* @param basename
* @return a matching {@link IFile} or <code>null</code>, if no matching file was found
*/
private static IFile findInContainer(IContainer container, final String basename) {
final IFile[] result= { null };
IResourceProxyVisitor visitor= new IResourceProxyVisitor() {
public boolean visit(IResourceProxy proxy) throws CoreException {
if (result[0] != null) {
return false;
}
if (!proxy.isAccessible()) {
return false;
}
if (proxy.getType() == IResource.FILE && proxy.getName().equals(basename)) {
result[0]= (IFile)proxy.requestResource();
return false;
}
return true;
}};
try {
container.accept(visitor, 0);
} catch (CoreException exc) {
// ignore
}
return result[0];
}
private static IContentType[] getPartnerContentTypes(String contentTypeId) {
IContentTypeManager mgr= Platform.getContentTypeManager();
if (contentTypeId.equals(CCorePlugin.CONTENT_TYPE_CHEADER)) {
return new IContentType[] {
mgr.getContentType(CCorePlugin.CONTENT_TYPE_CSOURCE),
mgr.getContentType(CCorePlugin.CONTENT_TYPE_CXXSOURCE)
};
}
if (contentTypeId.equals(CCorePlugin.CONTENT_TYPE_CSOURCE)) {
return new IContentType[] {
mgr.getContentType(CCorePlugin.CONTENT_TYPE_CHEADER),
mgr.getContentType(CCorePlugin.CONTENT_TYPE_CXXHEADER)
};
}
if (contentTypeId.equals(CCorePlugin.CONTENT_TYPE_CXXHEADER)) {
return new IContentType[] {
mgr.getContentType(CCorePlugin.CONTENT_TYPE_CXXSOURCE),
mgr.getContentType(CCorePlugin.CONTENT_TYPE_CSOURCE)
};
}
if (contentTypeId.equals(CCorePlugin.CONTENT_TYPE_CXXSOURCE)) {
return new IContentType[] {
mgr.getContentType(CCorePlugin.CONTENT_TYPE_CXXHEADER),
mgr.getContentType(CCorePlugin.CONTENT_TYPE_CHEADER)
};
}
return new IContentType[0];
}
/**
* Finds a partner translation unit based on filename/extension matching.
*
* @param a partner translation unit or <code>null</code>
*/
private static ITranslationUnit getPartnerFileFromFilename(ITranslationUnit tu) {
IPath sourceFileLocation= tu.getLocation();
if (sourceFileLocation == null) {
return null;
}
IPath partnerBasePath= sourceFileLocation.removeFileExtension();
IContentType[] contentTypes= getPartnerContentTypes(tu.getContentTypeId());
HashSet<String> extensionsTried= new HashSet<String>();
for (int j = 0; j < contentTypes.length; j++) {
IContentType contentType= contentTypes[j];
String[] partnerExtensions;
partnerExtensions= contentType.getFileSpecs(IContentType.FILE_EXTENSION_SPEC);
for (int i= 0; i < partnerExtensions.length; i++) {
String ext= partnerExtensions[i];
if (extensionsTried.add(ext)) {
String partnerFileBasename= partnerBasePath.addFileExtension(ext).lastSegment();
IFile partnerFile= null;
IContainer container = tu.getResource().getParent();
while (container != null && partnerFile == null && !(container instanceof IWorkspaceRoot)) {
partnerFile= findInContainer(container, partnerFileBasename);
container = container.getParent();
}
if (partnerFile != null) {
ITranslationUnit partnerUnit= (ITranslationUnit) CoreModel.getDefault().create(partnerFile);
if (partnerUnit != null) {
return partnerUnit;
}
}
// External translation unit - try in same directory
if (tu.getResource() == null) {
IPath partnerFileLoation= partnerBasePath.removeLastSegments(1).append(partnerFileBasename);
ITranslationUnit partnerUnit= CoreModel.getDefault().createTranslationUnitFrom(
tu.getCProject(), partnerFileLoation);
if (partnerUnit != null) {
return partnerUnit;
}
}
}
}
}
return null;
}
public static ITranslationUnit getPartnerTranslationUnit(ITranslationUnit tu) {
ITranslationUnit partnerUnit= getPartnerFileFromFilename(tu);
if (partnerUnit == null) {
// Search partner file based on definition/declaration association
IProgressMonitor monitor= new NullProgressMonitor();
PartnerFileComputer computer= new PartnerFileComputer();
ASTProvider.getASTProvider().runOnAST(tu, ASTProvider.WAIT_ACTIVE_ONLY, monitor, computer);
partnerUnit = createTranslationUnit(computer.getPartnerFileLocation(), tu.getCProject());
}
return partnerUnit;
}
public static ITranslationUnit getPartnerTranslationUnit(ITranslationUnit tu,
RefactoringASTCache astCache) throws CoreException {
ITranslationUnit partnerUnit= getPartnerFileFromFilename(tu);
if (partnerUnit == null) {
// Search partner file based on definition/declaration association
IProgressMonitor monitor= new NullProgressMonitor();
IASTTranslationUnit ast = astCache.getAST(tu, monitor);
PartnerFileVisitor visitor = new PartnerFileVisitor();
ast.accept(visitor);
partnerUnit = createTranslationUnit(visitor.getPartnerFileLocation(), tu.getCProject());
}
return partnerUnit;
}
private static ITranslationUnit createTranslationUnit(IPath partnerFileLoation, ICProject cProject) {
ITranslationUnit partnerUnit = null;
if (partnerFileLoation != null) {
partnerUnit= (ITranslationUnit) CoreModel.getDefault().create(partnerFileLoation);
if (partnerUnit == null) {
partnerUnit= CoreModel.getDefault().createTranslationUnitFrom(cProject.getCProject(),
partnerFileLoation);
}
}
return partnerUnit;
}
}

View file

@ -12,53 +12,20 @@
package org.eclipse.cdt.internal.ui.editor;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.ResourceBundle;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceProxy;
import org.eclipse.core.resources.IResourceProxyVisitor;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.core.runtime.content.IContentTypeManager;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.ui.texteditor.TextEditorAction;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.model.IWorkingCopy;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.IWorkingCopyManager;
import org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable;
import org.eclipse.cdt.internal.ui.util.EditorUtility;
/**
@ -68,119 +35,6 @@ import org.eclipse.cdt.internal.ui.util.EditorUtility;
*/
public class ToggleSourceAndHeaderAction extends TextEditorAction {
private static class Counter {
public int fCount;
}
/**
* Compute the partner file for a translation unit.
* The partner file is the corresponding source or header file
* based on heuristics.
*
* @since 4.0
*/
private static class PartnerFileComputer extends ASTVisitor implements ASTRunnable {
/**
* When this many times the same partner file is hit,
* we are confident enough to take it.
*/
private static final int CONFIDENCE_LIMIT = 15;
/**
* When this many times no match was found in the index,
* we suspect that we won't get a good partner.
*/
private static final int SUSPECT_LIMIT = 15;
private IIndex fIndex;
private IPath fFilePath;
private Map<IPath, Counter> fMap;
/** The confidence level == number of hits */
private int fConfidence;
/** Suspect level == number of no index matches */
private int fSuspect;
/** The current favorite partner file */
private IPath fFavoriteLocation;
{
shouldVisitDeclarators= true;
}
public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) {
if (ast != null) {
fIndex= ast.getIndex();
fFilePath= Path.fromOSString(ast.getFilePath());
fMap= new HashMap<IPath, Counter>();
if (fIndex != null) {
ast.accept(this);
}
}
return Status.OK_STATUS;
}
public IPath getPartnerFileLocation() {
return fFavoriteLocation;
}
/*
* @see org.eclipse.cdt.core.dom.ast.ASTVisitor#visit(org.eclipse.cdt.core.dom.ast.IASTDeclarator)
*/
@Override
public int visit(IASTDeclarator declarator) {
if (declarator instanceof IASTFunctionDeclarator) {
IASTName name= declarator.getName();
if (name != null && declarator.getNestedDeclarator() == null) {
IBinding binding= name.resolveBinding();
if (binding != null && !(binding instanceof IProblemBinding)) {
boolean isDefinition= name.isDefinition();
final IIndexName[] partnerNames;
try {
if (isDefinition) {
partnerNames= fIndex.findNames(binding, IIndex.FIND_DECLARATIONS | IIndex.SEARCH_ACROSS_LANGUAGE_BOUNDARIES);
} else {
partnerNames= fIndex.findNames(binding, IIndex.FIND_DEFINITIONS | IIndex.SEARCH_ACROSS_LANGUAGE_BOUNDARIES);
}
if (partnerNames.length == 0) {
++fSuspect;
if (fSuspect == SUSPECT_LIMIT) {
fFavoriteLocation= null;
return PROCESS_ABORT;
}
}
for (int i= 0; i < partnerNames.length; i++) {
IIndexName partnerName= partnerNames[i];
IASTFileLocation partnerLocation= partnerName.getFileLocation();
if (partnerLocation != null) {
IPath partnerFileLocation= Path.fromOSString(partnerLocation.getFileName());
if (!fFilePath.equals(partnerFileLocation)) {
addPotentialPartnerFileLocation(partnerFileLocation);
if (fConfidence == CONFIDENCE_LIMIT) {
return PROCESS_ABORT;
}
}
}
}
} catch (CoreException exc) {
CUIPlugin.log(exc.getStatus());
}
}
}
}
return PROCESS_SKIP;
}
private void addPotentialPartnerFileLocation(IPath partnerFileLocation) {
Counter counter= fMap.get(partnerFileLocation);
if (counter == null) {
counter= new Counter();
fMap.put(partnerFileLocation, counter);
}
++counter.fCount;
if (counter.fCount > fConfidence) {
fConfidence= counter.fCount;
fFavoriteLocation= partnerFileLocation;
}
}
}
private static ITranslationUnit fgLastPartnerUnit;
private static ITranslationUnit fgLastSourceUnit;
@ -261,130 +115,6 @@ public class ToggleSourceAndHeaderAction extends TextEditorAction {
}
// search partner file based on filename/extension
ITranslationUnit partnerUnit= getPartnerFileFromFilename(tUnit);
if (partnerUnit == null) {
// search partner file based on definition/declaration association
IProgressMonitor monitor= new NullProgressMonitor();
PartnerFileComputer computer= new PartnerFileComputer();
ASTProvider.getASTProvider().runOnAST(tUnit, ASTProvider.WAIT_ACTIVE_ONLY, monitor, computer);
IPath partnerFileLoation= computer.getPartnerFileLocation();
if (partnerFileLoation != null) {
partnerUnit= (ITranslationUnit) CoreModel.getDefault().create(partnerFileLoation);
if (partnerUnit == null) {
partnerUnit= CoreModel.getDefault().createTranslationUnitFrom(tUnit.getCProject(), partnerFileLoation);
}
}
}
return partnerUnit;
}
/**
* Find a partner translation unit based on filename/extension matching.
*
* @param a partner translation unit or <code>null</code>
*/
private ITranslationUnit getPartnerFileFromFilename(ITranslationUnit tUnit) {
IPath sourceFileLocation= tUnit.getLocation();
if (sourceFileLocation == null) {
return null;
}
IPath partnerBasePath= sourceFileLocation.removeFileExtension();
IContentType[] contentTypes= getPartnerContentTypes(tUnit.getContentTypeId());
HashSet<String> extensionsTried= new HashSet<String>();
for (int j = 0; j < contentTypes.length; j++) {
IContentType contentType= contentTypes[j];
String[] partnerExtensions;
partnerExtensions= contentType.getFileSpecs(IContentType.FILE_EXTENSION_SPEC);
for (int i= 0; i < partnerExtensions.length; i++) {
String ext= partnerExtensions[i];
if (extensionsTried.add(ext)) {
String partnerFileBasename= partnerBasePath.addFileExtension(ext).lastSegment();
IFile partnerFile= null;
if (tUnit.getResource() != null) {
partnerFile= findInContainer(tUnit.getResource().getParent(), partnerFileBasename);
}
if (partnerFile == null) {
partnerFile= findInContainer(tUnit.getCProject().getProject(), partnerFileBasename);
}
if (partnerFile != null) {
ITranslationUnit partnerUnit= (ITranslationUnit) CoreModel.getDefault().create(partnerFile);
if (partnerUnit != null) {
return partnerUnit;
}
}
// external tanslation unit - try in same directory
if (tUnit.getResource() == null) {
IPath partnerFileLoation= partnerBasePath.removeLastSegments(1).append(partnerFileBasename);
ITranslationUnit partnerUnit= CoreModel.getDefault().createTranslationUnitFrom(tUnit.getCProject(), partnerFileLoation);
if (partnerUnit != null) {
return partnerUnit;
}
}
}
}
}
return null;
}
/**
* Find a file in the given resource container for the given basename.
*
* @param container
* @param basename
* @return a matching {@link IFile} or <code>null</code>, if no matching file was found
*/
private IFile findInContainer(IContainer container, final String basename) {
final IFile[] result= { null };
IResourceProxyVisitor visitor= new IResourceProxyVisitor() {
public boolean visit(IResourceProxy proxy) throws CoreException {
if (result[0] != null) {
return false;
}
if (!proxy.isAccessible()) {
return false;
}
if (proxy.getType() == IResource.FILE && proxy.getName().equals(basename)) {
result[0]= (IFile)proxy.requestResource();
return false;
}
return true;
}};
try {
container.accept(visitor, 0);
} catch (CoreException exc) {
// ignore
}
return result[0];
}
private IContentType[] getPartnerContentTypes(String contentTypeId) {
IContentTypeManager mgr= Platform.getContentTypeManager();
if (contentTypeId.equals(CCorePlugin.CONTENT_TYPE_CHEADER)) {
return new IContentType[] {
mgr.getContentType(CCorePlugin.CONTENT_TYPE_CSOURCE),
mgr.getContentType(CCorePlugin.CONTENT_TYPE_CXXSOURCE)
};
}
if (contentTypeId.equals(CCorePlugin.CONTENT_TYPE_CSOURCE)) {
return new IContentType[] {
mgr.getContentType(CCorePlugin.CONTENT_TYPE_CHEADER),
mgr.getContentType(CCorePlugin.CONTENT_TYPE_CXXHEADER)
};
}
if (contentTypeId.equals(CCorePlugin.CONTENT_TYPE_CXXHEADER)) {
return new IContentType[] {
mgr.getContentType(CCorePlugin.CONTENT_TYPE_CXXSOURCE),
mgr.getContentType(CCorePlugin.CONTENT_TYPE_CSOURCE)
};
}
if (contentTypeId.equals(CCorePlugin.CONTENT_TYPE_CXXSOURCE)) {
return new IContentType[] {
mgr.getContentType(CCorePlugin.CONTENT_TYPE_CXXHEADER),
mgr.getContentType(CCorePlugin.CONTENT_TYPE_CHEADER)
};
}
return new IContentType[0];
return SourceHeaderPartnerFinder.getPartnerTranslationUnit(tUnit);
}
}

View file

@ -272,7 +272,7 @@ public class GenerateGettersAndSettersRefactoring extends CRefactoring2 {
IASTSimpleDeclaration decl = context.existingFields.get(0);
InsertLocation2 location = MethodDefinitionInsertLocationFinder2.find(
decl.getFileLocation(), decl.getParent(), astCache);
tu, decl.getFileLocation(), decl.getParent(), astCache);
if (location.getFile() == null || NodeHelper.isContainedInTemplateDeclaration(decl)) {
location.setNodeToInsertAfter(NodeHelper.findTopLevelParent(decl), tu);

View file

@ -15,10 +15,9 @@ import java.util.ArrayList;
import java.util.Collection;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
@ -27,7 +26,11 @@ import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.internal.core.resources.ResourceLookup;
import org.eclipse.cdt.internal.ui.editor.SourceHeaderPartnerFinder;
import org.eclipse.cdt.internal.ui.refactoring.utils.DefinitionFinder;
import org.eclipse.cdt.internal.ui.refactoring.utils.FileHelper;
import org.eclipse.cdt.internal.ui.refactoring.utils.NodeHelper;
@ -85,12 +88,15 @@ public class MethodDefinitionInsertLocationFinder {
}
}
IPath path = file.getLocation().removeFileExtension().addFileExtension("cpp"); //$NON-NLS-1$
IFile fileForLocation = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(path);
if (fileForLocation != null && fileForLocation.exists()) {
result.setInsertFile(fileForLocation);
ITranslationUnit tu = (ITranslationUnit) CCorePlugin.getDefault().getCoreModel().create(file);
ITranslationUnit partner = SourceHeaderPartnerFinder.getPartnerTranslationUnit(tu);
if (partner != null) {
IFile fileForLocation = ResourceLookup.selectFileForLocation(partner.getLocation(), file.getProject());
if (fileForLocation != null && fileForLocation.exists()) {
result.setInsertFile(fileForLocation);
}
}
return result;
}

View file

@ -24,7 +24,9 @@ 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.core.model.ITranslationUnit;
import org.eclipse.cdt.internal.ui.editor.SourceHeaderPartnerFinder;
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;
@ -60,7 +62,7 @@ public class MethodDefinitionInsertLocationFinder2 {
return functionDefinitionInParents;
}
public static InsertLocation2 find(IASTFileLocation methodDeclarationLocation, IASTNode parent,
public static InsertLocation2 find(ITranslationUnit declarationTu, IASTFileLocation methodDeclarationLocation, IASTNode parent,
RefactoringASTCache astCache) throws CoreException {
IASTDeclaration[] declarations = NodeHelper.getDeclarations(parent);
InsertLocation2 insertLocation = new InsertLocation2();
@ -82,6 +84,13 @@ public class MethodDefinitionInsertLocationFinder2 {
definition.getName()), definition.getTranslationUnit());
}
}
if (insertLocation.getTranslationUnit() == null) {
ITranslationUnit partner = SourceHeaderPartnerFinder.getPartnerTranslationUnit(declarationTu, astCache);
if (partner != null) {
insertLocation.setParentNode(astCache.getAST(partner, null), partner);
}
}
return insertLocation;
}