Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
NEW: Re: [cdt-patch] OpenInclude - Search Local Includes

OK, I'm sending a new patch.  This patch is rapidly becoming an uber
patch ... but it is addressing:

PR 52128: Where duplicate editors are opened for external include files
PR 46263: Where local headers residing in the current directory are
          not found.
PR 51355: Performance in searching a large project in the absence of
          proper include information is poor.

Thanks,
 Thomas


Thomas Fletcher <thomasf@xxxxxxx> said:

> 
> Folks,
> 
>   This is an updated patch for the OpenIncludeAction which hangs
> off of the Outline View.  Unlike last time this one tries to stick
> to the "your project should be configured properly" consistancy
> rules =;-)
> 
>   The current version will not search the directory location of the
> current file for local "" include files.  This patch always searches
> the local directory, but has a provision for doing the correct thing
> when I figure out what the correct way to get an Include from an
> ICElement (see post in cdt-dev/core) =;-)
> 
>   Additionally this patch still includes the more efficient search 
> of the local project for when there is no scanner information provided.
> This will all get rolled into the scanner class so that we all have
> a common location for getting at these things, but for now this is a
> small patch to address PR 51355.
> 
> For the ChangeLog
> 
> - Add the local directory as part of the include paths for local 
>   include statements.  PR 51355
> 
> 
> 
> 



-- 



Index: src/org/eclipse/cdt/internal/ui/editor/OpenIncludeAction.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/OpenIncludeAction.java,v
retrieving revision 1.7
diff -u -r1.7 OpenIncludeAction.java
--- src/org/eclipse/cdt/internal/ui/editor/OpenIncludeAction.java	28 Aug 2003 19:47:01 -0000	1.7
+++ src/org/eclipse/cdt/internal/ui/editor/OpenIncludeAction.java	16 Feb 2004 10:55:21 -0000
@@ -23,6 +23,8 @@
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceProxy;
+import org.eclipse.core.resources.IResourceProxyVisitor;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
@@ -35,22 +37,29 @@
 import org.eclipse.jface.viewers.LabelProvider;
 import org.eclipse.jface.window.Window;
 import org.eclipse.ui.IEditorDescriptor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IEditorReference;
 import org.eclipse.ui.IEditorRegistry;
+import org.eclipse.ui.IStorageEditorInput;
 import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.internal.UIPlugin;
 
 
 public class OpenIncludeAction extends Action {
-
-
 	private static final String PREFIX= "OpenIncludeAction.";
 	
 	private static final String DIALOG_TITLE= PREFIX + "dialog.title";
 	private static final String DIALOG_MESSAGE= PREFIX + "dialog.message";
 	
 	private ISelectionProvider fSelectionProvider;
-
+	private IResource		   fBaseResource;
 
 	public OpenIncludeAction(ISelectionProvider provider) {
+		this(provider, null);
+	}
+
+	public OpenIncludeAction(ISelectionProvider provider, IResource baseResource) {
 		super(CUIPlugin.getResourceString(PREFIX + "label"));
 		setDescription(CUIPlugin.getResourceString(PREFIX + "description"));
 		setToolTipText(CUIPlugin.getResourceString(PREFIX + "tooltip"));
@@ -58,6 +67,28 @@
 		CPluginImages.setImageDescriptors(this, CPluginImages.T_LCL, CPluginImages.IMG_MENU_OPEN_INCLUDE);
 		
 		fSelectionProvider= provider;
+		fBaseResource = baseResource;
+	}
+	
+	/**
+	 * Sets the base resource which will be used as a reference to extract out include
+	 * path information if the selected element does not already contain resource 
+	 * reference information.
+	 * 
+	 * @param resource IResource used as a reference to extract include path information or null not to have one
+	 */
+	public void setBaseResource(IResource resource) {
+		fBaseResource = resource;
+	}
+
+	/**
+	 * Returns the base resource currently used as a reference to extract out include
+	 * path information.
+	 * 
+	 * @param resource IResource used to extract the information or null if there is no base resource
+	 */
+	public IResource getBaseResource() {
+		return fBaseResource;
 	}
 			
 	public void run() {
@@ -65,9 +96,20 @@
 		if (include == null) {
 			return;
 		}
+
+		/* FIXME 
+		 * The information about whether this is a local include file or not
+		 * a local include file is in the Include specific ICElement.  Unfortunately
+		 * while we know that, it isn't part of the public interface.  For now we
+		 * just assume that every header has the possibility of being local.
+		 */
+		boolean isLocal = true;
 		
 		try {
 			IResource res = include.getUnderlyingResource();
+			if(res == null) {
+				res = fBaseResource;
+			}
 			ArrayList filesFound= new ArrayList(4);
 			if (res != null) {
 				IProject proj = res.getProject();
@@ -81,10 +123,18 @@
 						info = provider.getScannerInformation(proj);
 					}
 					if (info != null) {
+						//If the header is local, then look in the current location first
 						String[] includePaths = info.getIncludePaths();
+
+						if(isLocal) {		//Prepend our path at the start of this array
+							String [] newIncludePaths = new String[includePaths.length + 1];
+							newIncludePaths[0] = res.getLocation().removeLastSegments(1).toOSString();
+							System.arraycopy(includePaths, 0, newIncludePaths, 1, includePaths.length);			
+							includePaths = newIncludePaths;
+						}
+						
 						findFile(includePaths, includeName, filesFound);
 					} else {
-						// Fall back and search the project
 						findFile(proj, new Path(includeName), filesFound);
 					}
 				}
@@ -103,7 +153,7 @@
 				IFile file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(fileToOpen);
 				if (file != null) {
 					EditorUtility.openInEditor(file);
-				}  else {
+				}  else if(activateExistingOpenedExternalFile(fileToOpen) == false){
 					FileStorage storage = new FileStorage(null, fileToOpen);
 					EditorUtility.openInEditor(storage);
 				}
@@ -114,28 +164,107 @@
 			CUIPlugin.getDefault().log(e.getStatus());
 		}
 	}
+	
+	/**
+	 * Check to see if this file has already been opened in another editor using an 
+	 * external file storage mechanism
+	 * @param path IPath with the path of the external file which is being edited.
+	 * @return true if an editor was found and activated, false otherwise
+	 */
+	private boolean activateExistingOpenedExternalFile(IPath path) {
+		IEditorReference [] editorRefs;
+		editorRefs = UIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage().getEditorReferences();
+		
+		for(int i = 0; i < editorRefs.length; i++) {
+			IEditorPart editor = editorRefs[i].getEditor(true);
+			IEditorInput input = editor.getEditorInput();
+			if(input instanceof IStorageEditorInput) {
+				IPath editorPath;
+				try {
+					editorPath = ((IStorageEditorInput)input).getStorage().getFullPath();
+				} catch(Exception ex) {
+					editorPath = null;
+				}
+				if(editorPath != null && editorPath.equals(path)) {
+					UIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage().activate(editor);
+					return true;
+				}
+			}
+		}
+		
+		return false;
+	}
 
-	private void findFile(String[] includePaths,  String name, ArrayList list)  throws CoreException {
+	private void findFile(String[] includePaths, String name, ArrayList list)  throws CoreException {		
 		for (int i = 0; i < includePaths.length; i++) {
 			IPath path = new Path(includePaths[i] + "/" + name);
 			File file = path.toFile();
-			if (file.exists()) {
+			if (file.exists() && !list.contains(path)) {
 				list.add(path);
 			} 
 		}
 	}
 
-	private void findFile(IContainer parent, IPath name, ArrayList list) throws CoreException {
-		IResource found= parent.findMember(name);
-		if (found != null && found.getType() == IResource.FILE) {
-			list.add(found.getLocation());
+	private void findFile(IContainer parent, IPath name, final ArrayList list) throws CoreException {
+		final String lastSegment = name.lastSegment();
+		if(lastSegment == null) {
+			return;
 		}
-		IResource[] children= parent.members();
-		for (int i= 0; i < children.length; i++) {
-			if (children[i] instanceof IContainer) {
-				findFile((IContainer)children[i], name, list);
+
+		final IPath pathSegments = name.removeLastSegments(1);
+		
+		//We use the lastSegment as a fast key, but then make sure that we can match
+		//the rest of the segments (if they exist) so a path like:
+		//#include "subsystem/includefile.h" won't match with "a/b/c/includefile.h"
+		IResourceProxyVisitor visitor = new IResourceProxyVisitor() {
+			private boolean checkSegments(IPath sourceSegments, IPath targetSegments) {
+				if(sourceSegments == null) {
+					return true;
+				}
+				if(targetSegments == null) {
+					return false;
+				}
+				
+				int segmentCount = sourceSegments.segmentCount();
+				int targetCount = targetSegments.segmentCount();
+				if(segmentCount > targetCount) {
+					return false;
+				}
+				
+				for(int i = segmentCount - 1; i >= 0; i--) {
+					if(!sourceSegments.segment(i).equals(targetSegments.segment(--targetCount))) {
+						return false;
+					}	
+				}
+				
+				return true;
+			}
+			
+			public boolean visit(IResourceProxy proxy) throws CoreException {
+				String resourceName = proxy.getName();
+				if(resourceName.equals(lastSegment)) {
+					IResource res = proxy.requestResource();
+					if(!res.exists()) {
+						return true;
+					}
+					
+					IPath location = res.getLocation();
+					if(list.contains(location)) {
+						return true;
+					}
+
+					//Check segment match criteria to make sure we really match this entry
+					if(checkSegments(pathSegments, location.removeLastSegments(1)) != true) {
+						return true;
+					} 
+					
+					list.add(location);
+				}
+				return true;
 			}
-		}		
+		};
+		
+		parent.accept(visitor, IResource.NONE);		
 	}
 

Back to the top