diff --git a/core/org.eclipse.cdt.core.tests/regression/org/eclipse/cdt/core/tests/BaseTestFramework.java b/core/org.eclipse.cdt.core.tests/regression/org/eclipse/cdt/core/tests/BaseTestFramework.java index ce9d176d471..2e3c268a080 100644 --- a/core/org.eclipse.cdt.core.tests/regression/org/eclipse/cdt/core/tests/BaseTestFramework.java +++ b/core/org.eclipse.cdt.core.tests/regression/org/eclipse/cdt/core/tests/BaseTestFramework.java @@ -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; } - } diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/GenerateGettersAndSetters.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/GenerateGettersAndSetters.rts index 1fdc5ece39d..1ef8de22f39 100644 --- a/core/org.eclipse.cdt.ui.tests/resources/refactoring/GenerateGettersAndSetters.rts +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/GenerateGettersAndSetters.rts @@ -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 + +//= diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ImplementMethod.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ImplementMethod.rts index b37756e99be..893f5d31ca3 100644 --- a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ImplementMethod.rts +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ImplementMethod.rts @@ -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() +{ +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SourceHeaderPartnerFinder.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SourceHeaderPartnerFinder.java new file mode 100644 index 00000000000..74ffad6da3e --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SourceHeaderPartnerFinder.java @@ -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 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(); + } + + @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 null, 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 null + */ + 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 extensionsTried= new HashSet(); + 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; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ToggleSourceAndHeaderAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ToggleSourceAndHeaderAction.java index 9a4261ab0cb..beafb9ea386 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ToggleSourceAndHeaderAction.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ToggleSourceAndHeaderAction.java @@ -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 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(); - 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 null - */ - private ITranslationUnit getPartnerFileFromFilename(ITranslationUnit tUnit) { - IPath sourceFileLocation= tUnit.getLocation(); - if (sourceFileLocation == null) { - return null; - } - IPath partnerBasePath= sourceFileLocation.removeFileExtension(); - IContentType[] contentTypes= getPartnerContentTypes(tUnit.getContentTypeId()); - HashSet extensionsTried= new HashSet(); - 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 null, 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); } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoring.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoring.java index 90560156329..85d096b457a 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoring.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GenerateGettersAndSettersRefactoring.java @@ -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); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/implementmethod/MethodDefinitionInsertLocationFinder.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/implementmethod/MethodDefinitionInsertLocationFinder.java index d285309f06c..a1841644739 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/implementmethod/MethodDefinitionInsertLocationFinder.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/implementmethod/MethodDefinitionInsertLocationFinder.java @@ -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; } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/implementmethod/MethodDefinitionInsertLocationFinder2.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/implementmethod/MethodDefinitionInsertLocationFinder2.java index aa513697d1e..fb917ed84d1 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/implementmethod/MethodDefinitionInsertLocationFinder2.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/implementmethod/MethodDefinitionInsertLocationFinder2.java @@ -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; }