mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-25 01:45:33 +02:00
partial fix for 113063 from Janees and Vivian
This commit is contained in:
parent
778c379f88
commit
1eceeb0258
2 changed files with 280 additions and 2 deletions
|
@ -63,7 +63,7 @@ public class AddIncludesOperation implements IWorkspaceRunnable {
|
|||
fTranslationUnit = tu;
|
||||
}
|
||||
|
||||
public void executeInludes(IProgressMonitor monitor) throws CoreException {
|
||||
public void executeIncludes(IProgressMonitor monitor) throws CoreException {
|
||||
// Sanity
|
||||
if (fIncludes == null || fIncludes.length == 0) {
|
||||
return;
|
||||
|
@ -199,7 +199,7 @@ public class AddIncludesOperation implements IWorkspaceRunnable {
|
|||
}
|
||||
try {
|
||||
executeUsings(monitor);
|
||||
executeInludes(monitor);
|
||||
executeIncludes(monitor);
|
||||
} finally {
|
||||
monitor.done();
|
||||
}
|
||||
|
|
|
@ -13,8 +13,31 @@ package org.eclipse.cdt.internal.ui.editor;
|
|||
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.browser.IQualifiedTypeName;
|
||||
import org.eclipse.cdt.core.browser.PathUtil;
|
||||
import org.eclipse.cdt.core.browser.QualifiedTypeName;
|
||||
import org.eclipse.cdt.core.dom.IPDOMManager;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IEnumeration;
|
||||
import org.eclipse.cdt.core.dom.ast.IFunction;
|
||||
import org.eclipse.cdt.core.dom.ast.ITypedef;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding;
|
||||
import org.eclipse.cdt.core.model.CModelException;
|
||||
import org.eclipse.cdt.core.model.CoreModel;
|
||||
import org.eclipse.cdt.core.model.ICProject;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
import org.eclipse.cdt.core.parser.IScannerInfo;
|
||||
import org.eclipse.cdt.core.parser.IScannerInfoProvider;
|
||||
import org.eclipse.cdt.internal.core.pdom.PDOM;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMMemberOwner;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMName;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
|
||||
import org.eclipse.cdt.internal.ui.CHelpProviderManager;
|
||||
import org.eclipse.cdt.internal.ui.ICHelpContextIds;
|
||||
import org.eclipse.cdt.internal.ui.actions.WorkbenchRunnableAdapter;
|
||||
|
@ -24,9 +47,14 @@ import org.eclipse.cdt.internal.ui.util.ExceptionHandler;
|
|||
import org.eclipse.cdt.ui.CUIPlugin;
|
||||
import org.eclipse.cdt.ui.IFunctionSummary;
|
||||
import org.eclipse.cdt.ui.IRequiredInclude;
|
||||
import org.eclipse.cdt.ui.browser.typeinfo.TypeInfoLabelProvider;
|
||||
import org.eclipse.cdt.ui.text.ICHelpInvocationContext;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.IProjectDescription;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
import org.eclipse.jface.action.Action;
|
||||
import org.eclipse.jface.dialogs.MessageDialog;
|
||||
import org.eclipse.jface.operation.IRunnableWithProgress;
|
||||
|
@ -35,9 +63,11 @@ import org.eclipse.jface.text.IDocument;
|
|||
import org.eclipse.jface.text.IRegion;
|
||||
import org.eclipse.jface.text.ITextSelection;
|
||||
import org.eclipse.jface.viewers.ISelection;
|
||||
import org.eclipse.jface.window.Window;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
import org.eclipse.ui.IEditorInput;
|
||||
import org.eclipse.ui.PlatformUI;
|
||||
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
|
||||
import org.eclipse.ui.texteditor.ITextEditor;
|
||||
import org.eclipse.ui.texteditor.IUpdate;
|
||||
|
||||
|
@ -123,6 +153,42 @@ public class AddIncludeOnSelectionAction extends Action implements IUpdate {
|
|||
fUsings = null;
|
||||
fRequiredIncludes = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* To be used by ElementListSelectionDialog for user to choose which declarations/
|
||||
* definitions for "add include" when there are more than one to choose from.
|
||||
*/
|
||||
private class DisplayName extends Object
|
||||
{
|
||||
private PDOMName name;
|
||||
|
||||
public DisplayName(PDOMName name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
try {
|
||||
PDOMBinding binding = (PDOMBinding) name.resolveBinding();
|
||||
if (binding != null)
|
||||
{
|
||||
return getBindingQualifiedName(binding) + " - " + name.getFileName(); //$NON-NLS-1$
|
||||
}
|
||||
else
|
||||
return null;
|
||||
} catch (CoreException e) {
|
||||
CCorePlugin.log(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public PDOMName getPDOMName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract the includes for the given selection. This can be both used to perform
|
||||
|
@ -162,6 +228,144 @@ public class AddIncludeOnSelectionAction extends Action implements IUpdate {
|
|||
}
|
||||
}
|
||||
|
||||
IPDOMManager pdomManager = CCorePlugin.getPDOMManager();
|
||||
try {
|
||||
ITranslationUnit unit = getTranslationUnit();
|
||||
//get all referenced projects
|
||||
if (unit != null)
|
||||
{
|
||||
ICProject cProj = unit.getCProject();
|
||||
if (cProj != null)
|
||||
{
|
||||
IProject proj = cProj.getProject();
|
||||
if (proj != null)
|
||||
{
|
||||
IProjectDescription projectDescription = proj.getDescription();
|
||||
if (projectDescription != null)
|
||||
{
|
||||
IProject[] projects = projectDescription.getReferencedProjects();
|
||||
List cProjectsToSearch = new ArrayList();
|
||||
//get all the ICProjects for the referenced projects
|
||||
for(int i = 0; i < projects.length; i++)
|
||||
{
|
||||
IProject project = projects[i];
|
||||
try {
|
||||
ICProject[] cProjects = CoreModel.getDefault().getCModel().getCProjects();
|
||||
if (cProjects != null) {
|
||||
for (int j = 0; j < cProjects.length; j++) {
|
||||
ICProject cProject = cProjects[j];
|
||||
if (project.equals(cProjects[j].getProject()))
|
||||
cProjectsToSearch.add(cProject);
|
||||
}
|
||||
}
|
||||
} catch (CModelException e) {
|
||||
}
|
||||
}
|
||||
|
||||
cProjectsToSearch.add(cProj); //current project
|
||||
Pattern pattern = Pattern.compile(name);
|
||||
List pdomBindings = new ArrayList();
|
||||
//search the projects and get name matching bindings
|
||||
for (int n = 0; n < cProjectsToSearch.size(); n++)
|
||||
{
|
||||
PDOM pdom = (PDOM)pdomManager.getPDOM((ICProject) cProjectsToSearch.get(n));
|
||||
IBinding[] bindings = pdom.findBindings(pattern);
|
||||
|
||||
for (int i = 0; i < bindings.length; ++i) {
|
||||
PDOMBinding binding = (PDOMBinding)bindings[i];
|
||||
PDOMBinding pdomBinding = pdom.getLinkage(getTranslationUnit().getLanguage()).adaptBinding(binding);
|
||||
pdomBindings.add(pdomBinding);
|
||||
}
|
||||
}
|
||||
|
||||
List pdomNames = new ArrayList();
|
||||
|
||||
//get all the declarations/definitions of the pdomBindings found
|
||||
for (int i = 0; i < pdomBindings.size(); ++i)
|
||||
{
|
||||
PDOMBinding pdomBinding = (PDOMBinding) pdomBindings.get(i);
|
||||
|
||||
if (pdomBinding instanceof PDOMMemberOwner //class or struct
|
||||
|| pdomBinding instanceof IEnumeration)
|
||||
{
|
||||
PDOMName currentDef = pdomBinding.getFirstDefinition();
|
||||
while(currentDef != null) //get all the definitions of the file to include
|
||||
{
|
||||
pdomNames.add(new DisplayName(currentDef));
|
||||
currentDef = currentDef.getNextInBinding();
|
||||
}
|
||||
}
|
||||
if (pdomBinding instanceof ITypedef || pdomBinding instanceof IFunction)
|
||||
{
|
||||
PDOMName currentDec = pdomBinding.getFirstDeclaration();
|
||||
while(currentDec != null) //get all the declarations of the file to include
|
||||
{
|
||||
pdomNames.add(new DisplayName(currentDec));
|
||||
currentDec = currentDec.getNextInBinding();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pdomNames.size() > 1)
|
||||
{
|
||||
ElementListSelectionDialog dialog= new ElementListSelectionDialog(getShell(), new TypeInfoLabelProvider(TypeInfoLabelProvider.SHOW_TYPE_ONLY));
|
||||
dialog.setElements(pdomNames.toArray());
|
||||
dialog.setTitle(CEditorMessages.getString("AddIncludeOnSelection.label")); //$NON-NLS-1$
|
||||
dialog.setMessage(CEditorMessages.getString("AddIncludeOnSelection.description")); //$NON-NLS-1$
|
||||
if (dialog.open() == Window.OK) {
|
||||
//get selection
|
||||
Object[] selects = dialog.getResult();
|
||||
|
||||
fRequiredIncludes = new IRequiredInclude[selects.length];
|
||||
List usings = new ArrayList(selects.length);
|
||||
for (int i = 0; i < fRequiredIncludes.length; i++) {
|
||||
IRequiredInclude include = getRequiredInclude(((DisplayName)selects[i]).getPDOMName().getFileName(), getTranslationUnit());
|
||||
if (include != null) {
|
||||
fRequiredIncludes[i] = include;
|
||||
PDOMBinding pdomBinding = ((PDOMBinding)(((DisplayName)selects[i]).getPDOMName().resolveBinding()));
|
||||
if (pdomBinding instanceof ICPPBinding)
|
||||
{
|
||||
//find the enclosing namespace, if there's one
|
||||
IQualifiedTypeName qualifiedName = new QualifiedTypeName(getBindingQualifiedName(pdomBinding));
|
||||
String qualifiedEnclosingName = (new QualifiedTypeName(qualifiedName.getEnclosingNames())).getFullyQualifiedName();
|
||||
if (!qualifiedEnclosingName.equals("")) //$NON-NLS-1$
|
||||
usings.add(qualifiedEnclosingName);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(usings.size() > 0)
|
||||
{
|
||||
fUsings = new String[usings.size()];
|
||||
for (int i = 0; i < usings.size(); i++)
|
||||
{
|
||||
fUsings[i] = (String) usings.get(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pdomNames.size() == 1)
|
||||
{
|
||||
String fileName = ((DisplayName)pdomNames.get(0)).getPDOMName().getFileName();
|
||||
fRequiredIncludes = new IRequiredInclude[] {getRequiredInclude(fileName, getTranslationUnit())};
|
||||
PDOMBinding pdomBinding = (PDOMBinding) ((DisplayName)pdomNames.get(0)).getPDOMName().resolveBinding();
|
||||
|
||||
if (pdomBinding instanceof ICPPBinding)
|
||||
{
|
||||
//find the enclosing namespace, if there's one
|
||||
IQualifiedTypeName qualifiedName = new QualifiedTypeName(getBindingQualifiedName(pdomBinding));
|
||||
String qualifiedEnclosingName = new QualifiedTypeName(qualifiedName.getEnclosingNames()).getFullyQualifiedName();
|
||||
if (!qualifiedEnclosingName.equals("")) //$NON-NLS-1$
|
||||
fUsings = new String[] {qualifiedEnclosingName};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// Try the type caching.
|
||||
if (fRequiredIncludes == null && fUsings == null) {
|
||||
}
|
||||
|
@ -214,6 +418,80 @@ public class AddIncludeOnSelectionAction extends Action implements IUpdate {
|
|||
public void update() {
|
||||
setEnabled(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the RequiredInclude object to be added to the include list
|
||||
* @param path - the full path of the file to include
|
||||
* @param tu - the translation unit which requires the include
|
||||
* @return the required include
|
||||
*/
|
||||
private IRequiredInclude getRequiredInclude(String path, ITranslationUnit tu) {
|
||||
if (path != null) {
|
||||
IPath typeLocation = new Path(path);
|
||||
IProject project = tu.getCProject().getProject();
|
||||
IPath projectLocation = project.getLocation();
|
||||
IPath workspaceLocation = project.getWorkspace().getRoot().getLocation();
|
||||
IPath headerLocation = tu.getResource().getLocation();
|
||||
boolean isSystemIncludePath = false;
|
||||
|
||||
IPath includePath = makeRelativePathToProjectIncludes(typeLocation, tu);
|
||||
if (includePath != null && !projectLocation.isPrefixOf(typeLocation)) {
|
||||
isSystemIncludePath = true;
|
||||
}
|
||||
//create a relative path - the include file is in the same project as the file we're currently at
|
||||
else if (projectLocation.isPrefixOf(typeLocation)
|
||||
&& projectLocation.isPrefixOf(headerLocation)) {
|
||||
includePath = PathUtil.makeRelativePath(typeLocation, headerLocation.removeLastSegments(1));
|
||||
}
|
||||
//create a relative path - the include file is in the same workspace as the file we're currently at
|
||||
else if (workspaceLocation.isPrefixOf(typeLocation))
|
||||
{
|
||||
includePath = PathUtil.makeRelativePath(typeLocation, projectLocation);
|
||||
}
|
||||
if (includePath == null)
|
||||
includePath = typeLocation; //the full path
|
||||
return new RequiredIncludes(includePath.toString(), isSystemIncludePath);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a relative path to the project includes.
|
||||
* @param fullPath the full path to the project
|
||||
* @param tu a translation unit in the project
|
||||
* @return IPath corresponding to a relative path to the project includes
|
||||
*/
|
||||
private static IPath makeRelativePathToProjectIncludes(IPath fullPath, ITranslationUnit tu) {
|
||||
IScannerInfoProvider provider = CCorePlugin.getDefault().getScannerInfoProvider(tu.getCProject().getProject());
|
||||
if (provider != null) {
|
||||
IScannerInfo info = provider.getScannerInformation(tu.getResource());
|
||||
if (info != null) {
|
||||
return PathUtil.makeRelativePathToIncludes(fullPath, info.getIncludePaths());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fully qualified name for a given PDOMBinding
|
||||
* @param pdomBinding
|
||||
* @return binding's fully qualified name
|
||||
* @throws CoreException
|
||||
*/
|
||||
private String getBindingQualifiedName(PDOMBinding pdomBinding) throws CoreException
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(pdomBinding.getName());
|
||||
PDOMNode parent = pdomBinding.getParentNode();
|
||||
while (parent != null)
|
||||
{
|
||||
if (parent instanceof PDOMBinding)
|
||||
{
|
||||
buf.insert(0, ((PDOMBinding)parent).getName() + "::"); //$NON-NLS-1$
|
||||
}
|
||||
parent = parent.getParentNode();
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue