How to get the Path of current selected file in Eclipse? - eclipse

I want to get the path of current selected file in Eclipse workspace but my project is a simple view plug-in project.
I just want to display the name/path of the file selected as soon as user opens the view.

You get the current selection as mentioned by #Danail Nachev. See http://www.eclipse.org/articles/Article-WorkbenchSelections/article.html for information on working with the selection service.
Once you have the selection, the most common pattern is:
if (selection instanceof IStructuredSelection) {
IStructuredSelection ssel = (IStructuredSelection) selection;
Object obj = ssel.getFirstElement();
IFile file = (IFile) Platform.getAdapterManager().getAdapter(obj,
IFile.class);
if (file == null) {
if (obj instanceof IAdaptable) {
file = (IFile) ((IAdaptable) obj).getAdapter(IFile.class);
}
}
if (file != null) {
// do something
}
}
Edit:
Usually you get an InputStream from the IFile and process it that way. Using some FileSystemProviders or EFS implementations, there might not be a local path to the file.
PW

You can retrieve the current workbench selection using two methods with the following code:
through the Workbench SelectionService
getViewSite().getSelectionProvider().getSelection()
getViewSite().getWorkbenchWindow().getSelectionService()
You can find more information in this article.
Using the global workbench selection is the better approach, because it enables your view to get selection from everywhere, which is something the user might expect (I at least do). Also, almost all of the views in Eclipse (and I don't know exceptions to this rule) are using this approach.
If you absolutely must to tie your view to another view, then you can get all IWorkbenchPage iterate over them and search for the view by its ID and when you find the view, you call get its SelectionProvider to get the selection.
Only by reading this explanation, makes my hair go straight up. Considering that there might be multiple instances of the same view, you can end up with a selection from a random view. I'm not sure whether the user will make sense of how things work, unless you have some clear rules, which exactly view you need. It is up to you.
`

Related

Visual Studio Extension: Project context is applied to every opened file except the first one

I have a Visual Studio extension package where I am applying C++ syntax settings to custom file extensions. This is done in the Visual Studio's Text Editor options. Those files are plain text and I mean to have them behave as code files in the IDE (IntelliSense, find matching braces, etc...)
It's mostly working fine, but there is one problem. The C++ syntax context is not applied to whichever is the first file I open in a given Visual Studio session. I will launch Visual Studio, open one of our custom projects, and open one file. The IDE opens a document window and the file is opened, can be edited and saved, no problem in appearance. But the file behaves as a plain text and not a C++ source. Now, whenever I open a second file in the IDE, or any further file, the C++ settings do get applied successfully. I can close all document tabs, and open new ones, and all those tabs are fine. Even re-opening the first file in a new tab, or after re-loading the project or the solution, is fine. Only the first document opened in a Visual Studio session has the issue.
For the following segment, I will refer to the Microsoft documentation on using their standard editor: https ://msdn.microsoft.com/en-us/library/bb166504.aspx
To implement the OpenItem method with a standard editor
1.Call IVsRunningDocumentTable (RDT_EditLock) to determine whether the document data object file is already open.
2.If the file is already open, resurface the file by calling the IsDocumentOpen method, specifying a value of IDO_ActivateIfOpen for the grfIDO parameter.
If the file is open and the document is owned by a different project than the calling project, your project receives a warning that the editor being opened is from another project. The file window is then surfaced.
3.If the document is not open or not in the running document table, call the OpenStandardEditor method (OSE_ChooseBestStdEditor) to open a standard editor for the file.
When you call the method, the IDE performs the following tasks:
a.The IDE scans the Editors/{guidEditorType}/Extensions subkey in the registry to determine which editor can open the file and has the highest priority for doing this.
b.After the IDE has determined which editor can open the file, the IDE calls CreateEditorInstance. The editor's implementation of this method returns information that is required for the IDE to call CreateDocumentWindow and site the newly opened document.
c.Finally, the IDE loads the document by using the usual persistence interface, such as IVsPersistDocData2.
d.If the IDE has previously determined that the hierarchy or hierarchy item is available, the IDE calls GetItemContext method on the project to get a project-level context IServiceProvider pointer to pass back in with the CreateDocumentWindow method call.
4.Return an IServiceProvider pointer to the IDE when the IDE calls GetItemContext on your project if you want to let the editor get context from your project.
Performing this step lets the project offer additional services to the editor.
If the document view or document view object was successfully sited in a window frame, the object is initialized with its data by calling LoadDocData.
It definitely seems to me that I need to hit element (D) from the above instructions. I have debuged through my extension code, and I do see where my implementation of GetItemContext() comes into play. When I open most files, the code path does effectively go through this method, however it does not when I open the first file of a Visual Studio session.
Call stack from OpenStandardEditor
GetItemContext is invoked by the Microsoft assemblies and I do not know what is the condition that triggers whether it is called or not. I can only trace up to my call to the method OpenStandardEditor(), in FileDocumentManager.cs, then I don't know what happens beyond that. The above screenshot is the call stack when GetItemContext is successfully invoked, but when I'm opening the first file I'm totally in the dark as to what OpenStandardEditor is doing. I do know that in both cases, when the context is loaded and when it is not, the exact same parameter values are passed to OpenStandardEditor. So here's my code where this method is invoked, if that can be of some help:
My override of class DocumentManager:
private int Open(bool newFile, bool openWith, uint editorFlags, ref Guid editorType, string physicalView, ref Guid logicalView, IntPtr docDataExisting, out IVsWindowFrame windowFrame, WindowFrameShowAction windowFrameAction)
{
windowFrame = null;
if (this.Node == null || this.Node.ProjectMgr == null || this.Node.ProjectMgr.IsClosed)
{
return VSConstants.E_FAIL;
}
int returnValue = VSConstants.S_OK;
string caption = this.GetOwnerCaption();
string fullPath = this.GetFullPathForDocument();
// Make sure that the file is on disk before we open the editor and display message if not found
if (!((FileNode)this.Node).IsFileOnDisk(true))
{
// Inform clients that we have an invalid item (wrong icon)
this.Node.OnInvalidateItems(this.Node.Parent);
// Bail since we are not able to open the item
return VSConstants.E_FAIL;
}
IVsUIShellOpenDocument uiShellOpenDocument = this.Node.ProjectMgr.Site.GetService(typeof(SVsUIShellOpenDocument)) as IVsUIShellOpenDocument;
IOleServiceProvider serviceProvider = this.Node.ProjectMgr.Site.GetService(typeof(IOleServiceProvider)) as IOleServiceProvider;
try
{
int result = VSConstants.E_FAIL;
if (openWith)
{
result = uiShellOpenDocument.OpenStandardEditor((uint)__VSOSEFLAGS.OSE_UseOpenWithDialog, fullPath, ref logicalView, caption, this.Node.ProjectMgr, this.Node.ID, docDataExisting, serviceProvider, out windowFrame);
}
else
{
__VSOSEFLAGS openFlags = 0;
if (newFile)
{
openFlags |= __VSOSEFLAGS.OSE_OpenAsNewFile;
}
//NOTE: we MUST pass the IVsProject in pVsUIHierarchy and the itemid
// of the node being opened, otherwise the debugger doesn't work.
if (editorType != Guid.Empty)
{
result = uiShellOpenDocument.OpenSpecificEditor(editorFlags, fullPath, ref editorType, physicalView, ref logicalView, caption, this.Node.ProjectMgr, this.Node.ID, docDataExisting, serviceProvider, out windowFrame);
}
else
{
openFlags |= __VSOSEFLAGS.OSE_ChooseBestStdEditor;
// THIS IS THE CALL THAT I'M ALWAYS INVOKING. PARAMS ARE ALWAYS THE SAME, BUT ITEM CONTEXT IS NOT ACTIVATED FOR FIRST FILE OF A SESSION.
result = uiShellOpenDocument.OpenStandardEditor((uint)openFlags, fullPath, ref logicalView, caption, this.Node.ProjectMgr, this.Node.ID, docDataExisting, serviceProvider, out windowFrame);
}
}
if (result != VSConstants.S_OK && result != VSConstants.S_FALSE && result != VSConstants.OLE_E_PROMPTSAVECANCELLED)
{
ErrorHandler.ThrowOnFailure(result);
}
if (windowFrame != null)
{
object var;
if (newFile)
{
ErrorHandler.ThrowOnFailure(windowFrame.GetProperty((int)__VSFPROPID.VSFPROPID_DocData, out var));
IVsPersistDocData persistDocData = (IVsPersistDocData)var;
ErrorHandler.ThrowOnFailure(persistDocData.SetUntitledDocPath(fullPath));
}
var = null;
ErrorHandler.ThrowOnFailure(windowFrame.GetProperty((int)__VSFPROPID.VSFPROPID_DocCookie, out var));
this.Node.DocCookie = (uint)(int)var;
if (windowFrameAction == WindowFrameShowAction.Show)
{
ErrorHandler.ThrowOnFailure(windowFrame.Show());
}
else if (windowFrameAction == WindowFrameShowAction.ShowNoActivate)
{
ErrorHandler.ThrowOnFailure(windowFrame.ShowNoActivate());
}
else if (windowFrameAction == WindowFrameShowAction.Hide)
{
ErrorHandler.ThrowOnFailure(windowFrame.Hide());
}
}
}
catch (COMException e)
{
Trace.WriteLine("Exception e:" + e.Message);
returnValue = e.ErrorCode;
this.CloseWindowFrame(ref windowFrame);
}
return returnValue;
}
I have also tried an alternative. In the call stack where I perform DoDefaultAction on my FileNode (extends HierarchyNode), I normally call an instance of my DocumentManager.Open() directly. I have changed that to try OpenDocumentViaProject() instead. Now, the MSENV assembly turns out to call my GetItemContext, then goes out to my implementation of DocumentManager.Open I quoted above.
Call stack from OpenDocumentViaProject
Sounds promising... but no. Beyond the screenshot above, once I call OpenStandardEditor the exact same behavior happens. No project context is applied to the first document opened in a session, and the context is applied to every further file. The call to GetItemContext() that is done by OpenDocumentViaProject() does not seem to matter in the slightest. Only when OpenStandardEditor() also ends up calling GetItemContext() somewhere downstream does the project settings I want get applied.
I don't see where I would be doing something fundamentally wrong. It seems to me that I am following the Mimcrosoft instructions on opening standard editors. Would you have a clue as to how my GetItemContext implementation is not invoked when I'm opening the first file of a VS session? Thanks

Delete a particular IMarker in builder

I am currently into Eclipse plugin development. I am in the need of using IMarker for a custom builder. I am creating project marker through org.eclipse.core.resources.IMarker and I am using IMarker.PROBLEM for two different situations.
How to delete and refresh a particular IMarker without deleting all the iMarker in the project resource.
I tried delete() method in the IMarker implementation. But it is not helping me out. And I found only the method deleteMarkers() in the project that actually deletes all the markers that are available in the project resource.
iProject.deleteMarkers(IMarker.PROBLEM, true,
IProject.DEPTH_INFINITE);
iProject.refreshLocal(IProject.DEPTH_INFINITE, null);
Please help me through this, I want to delete only a particular IMarker at the specified situation. I could not delete individual markers. Are there any source or reference you can point me to ? Thanks.
Basically, you have either store or find your specific markers. You can look for a marker in a selected resource (not on a project, but the current resource):
IMarker[] problems = null;
int depth = IResource.DEPTH_INFINITE;
try {
problems = resource.findMarkers(IMarker.PROBLEM, true, depth);
} catch (CoreException e) {
// something went wrong
}
When you have the correct marker, you can 1) update it by setting its properties, or 2) delete it using IMarker.delete().
The code snippet used here comes from the Mark My Words tutorial.

Suppress Errors in JavaScript validation

I'm currently developing an eclipse plugin. This plugin contains a project nature which depends on the javaScript nature of jsdt.
Now at a few details the JavaScripts that the projects of my nature can contain are somewhat special.
They can contain "compiler hints" which are basicly statements beginning with #
They can contain return statements outside of functions
But at this two points the standard validation of jsdt come in and marks them as errors (which is normally right). I already managed to get this errors filtered out in the properties of the JavaScript validator (manually).
My question is, how can i exclude these errors from the validation of jsdt automatically for the projects with my nature?
JSDT uses concrete syntax parser which generates syntax errors.
You can't disable this. Only semantics error or warnings can be configured.
However you can disable entire validation of JSDT.
Below solution will suppress errors ands warnings which are generated while we save some changes on java script files. (Auto Build, Build)
Open Properties Dialog of Your Project.
Choose Builders item.
Uncheck "JavaScript Validator". And Press OK button.
Remove current errors and warnings from Problems View
This solution can't eliminate error or warning annotations in editor while you edit. They will show up on editor temporarily only when you edit it.
After a lot of research, hours of deleting markers and debugging i finally managed to delete the errors i wanted. In a bad bad way of course but i've come to a point where i just wanted this to work no matter how it's done.
If you ever want to delete existing problems that had been created during the validation process of jsdt you need to do the following (and you must not ommit anything):
Create a class extending org.eclipse.wst.jsdt.core.compiler.ValidationParticipant
Override isActive(), buildStarting() and reconcile() methods.
So there are two things you basicly have to care about.
The actual problem markers that will be created or had already been created at the end of the validation process.
The Problems created by the validation process. They are of the type CategorizedProblem and can be obtained by the ReconcileContext object that is passed to the reconcile() method.
It seems to me that the CategorizedProblems will be translated to problem markers after the validation process.
So what you need to do is:
Delete all unwanted problem markers of all files in buildStarting (this removes problem markers from all files in your project that are about to be validated)
Iterate the CategorizedProblem objects of the ReconcileContext (getProblems())
Create a new Array containing only the CategorizedProblems you want to keep
Set this new Array to the ReconcileContext with putProblems()
Delete the unwanted markers again for that file (i don't know why this is needed, please don't ask, i don't care anymore :-/)
An example implementation of such a validationParticipant could look like this: (this one will filter out problems complaining about return statements outside of methods:
[...ommited imports ...]
public class MyValidationParticipant extends org.eclipse.wst.jsdt.core.compiler.ValidationParticipant{
#Override
public boolean isActive(IJavaScriptProject project) {
return true;
}
#Override
public void buildStarting(BuildContext[] files, boolean isBatch) {
super.buildStarting(files, isBatch);
for(BuildContext context : files){
IFile file = context.getFile();
deleteUnwantedMarkers(file);
}
}
#Override
public void reconcile(ReconcileContext context) {
IResource resource = context.getWorkingCopy().getResource();
CategorizedProblem[] newProblems = new CategorizedProblem[0];
ArrayList<CategorizedProblem> newProblemList = new ArrayList<CategorizedProblem>();
CategorizedProblem[] probs = context.getProblems("org.eclipse.wst.jsdt.core.problem");
if(probs != null){
for(CategorizedProblem p : probs){
if(!(p.getMessage().equals("Cannot return from outside a function or method."))){
newProblemList.add(p);
}
}
}
}
context.putProblems("org.eclipse.wst.jsdt.core.problem", newProblemList.toArray(newProblems));
deleteUnwantedMarkers(resource);
}
public static void deleteUnwantedMarkers(IResource resource){
if(resource.isSynchronized(IResource.DEPTH_INFINITE)){
try {
IMarker[] markers = resource.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE);
if(markers != null && markers.length > 0){
for(IMarker m : markers){
Object message = m.getAttribute(IMarker.MESSAGE);
if(message.equals("Cannot return from outside a function or method.")){
m.delete();
}
}
}
}catch (CoreException e) {
e.printStackTrace();
}
}
}
}
As i said, this is kind of a bad solution since the code relies on the String of the error message. There should be better ways to identify the problems you don't want to have.
Don't forget to add a proper extension in your plugin.xml for the ValidationParticipant.

Eclipse RCP - project selected (Package Explorer)

How do I retrieve the name and path of the project selected? (Package Explorer)
example: c:\project\test\projectName
someone has some code that explains how to complete I get the project name or full path of a particular project in my workspace?
Eclipse defines an extension point
"org.eclipse.ui.navigator.linkHelper"
If you contribute a class to these EP you have to implement ILinkHelper
The ILInkHelper interface notifies you, when something was selected in the explorer
public void activateEditor(IWorkbenchPage aPage, IStructuredSelection aSelection)
You can check the type of the selection
if (aSelection.getFirstElement() instanceof IFile) {
// Do something
}
Old memories but maybe useful for you. I guess package explorer provides its selection, so you can get the current selection in your code by calling:
ISelectionService service = getSite().getWorkbenchWindow().getSelectionService()
than you can get the package explorer view by its id (plugin.xml for more details):
IStructuredSelection selection = (IStructuredSelection) service.getSelection("org.eclipse.jdt.ui.PackageExplorer");
Please note AFAIK you can always safely cast ISelection to IStructuredSelection. Then call structured.getFirstElement() and I think the first element will be an IFile object. I hope my "pseudo code" whould be enough for you. And IFile has lots of usefule methods for your convenience

Eclipse - Export/Save Search Results

Eclipse's Search results view is quite handy with its tree-like structure. Is there any way to export these results to a readable text format or save them to a file for later use?
I've tried using copy & paste but the resulting text format is far from readable.
You can change the mode from tree to list by click 'upper-right corner triangle' ->'show in list', then just copy all the files in the list , it will be a perfect list of search result
I'm using Eclipse Search CSV Export.
No I don't think there is a possibility to export the results yet. (Update: Now there's a suitable plugin available). But you should be able to use the eclipse search framework programmatically an export the entries by yourself.
I did not test the following snipped but implemeted a custom search that way once (using the RetrieverAction class). You should be able to listen to search result changes without the action as well:
TextSearchQueryProvider provider= TextSearchQueryProvider.getPreferred();
// your input (you'll have to implement that one I think...)
TextSearchInput input = new TextSearchQueryProvider.TextSearchInput();
ISearchQuery query= provider.createQuery(input);
ISearchResult result = query.getSearchResult();
result.addListener(new ISearchResultListener() {
public void searchResultChanged(SearchResultEvent e) {
// -> export result
}
});
// run the query
NewSearchUI.runQueryInBackground(query);
Again: I did not test that at all and don't know if there is a better approach as well..