4

Inside an Eclipse plugin, I'd like to open a file in editor.

I know the full package and class name

How can I determine the path of the .java file from this?

Lii
  • 11,553
  • 8
  • 64
  • 88
Cedric Reichenbach
  • 8,970
  • 6
  • 54
  • 89

3 Answers3

5

Take a look at IJavaProject.findType( name ) method. Once you have an IType, you can use getPath or getResource methods to locate the file. This method searches across a project and everything visible from that project.

To search the whole workspace, iterate through all the Java projects in the workspace, calling the findType method on each in turn.

Lii
  • 11,553
  • 8
  • 64
  • 88
Konstantin Komissarchik
  • 28,879
  • 6
  • 61
  • 61
  • Arrghh! Right after I had implemented it in my head-crushing way... -.- Hmm, but one thing: I only have Java Projects in my workspace, but programmatically, they seem to be just Projects (I cannot cast them). – Cedric Reichenbach Aug 03 '12 at 20:48
  • JavaCore.create( IProject ) is the API that you are looking for. – Konstantin Komissarchik Aug 03 '12 at 20:56
  • Okay, one more question: I tried this, and it's pretty cleaner than my way, but not working correctly: The IType returned by `IJavaProject.findType()` seems only to know compiled binary files, but I need the source file (i.e. java file). Or is there such a method I did not see? – Cedric Reichenbach Aug 04 '12 at 12:07
  • The findType() method will located either a source or a binary type, but it can only find types in .java files if they are located in project's Java Source folder. – Konstantin Komissarchik Aug 06 '12 at 14:02
  • Yeah, I guess your solution is much cleaner, but it seems to return class file paths for types that are in the project source folder, so mine works better for me. I'll add my solution to your post and then mark it as solved. – Cedric Reichenbach Aug 06 '12 at 18:25
  • I'd be curious to know what usecase involves .java files that are in a project, but aren't in a source folder (so not treated by Eclipse as Java source). – Konstantin Komissarchik Aug 06 '12 at 18:28
  • DoodleDebug. An eclipse plugin to, similarly to System.out.println(), visualize objects, but graphically. And a feature is that you can render exceptions (i.e. stack traces) too, **and** they remain clickable as in the eclipse console. Btw, did you delete my addition to your post?? – Cedric Reichenbach Aug 07 '12 at 12:49
  • No. Didn't delete anything. Didn't see any additions. – Konstantin Komissarchik Aug 08 '12 at 05:09
1

You also need to know the source folder.

IProject prj = ResourcePlugin.getWorkspace().getRoot().getProject("project-name");
IFile theFile = prj.getFile(sourceFolder + packageName.replace('.','/') + className + ".java");

Generally you specify the file for an editor with an IFile. You can also ask an IFile for variants of the file's path.

Chris Gerken
  • 16,221
  • 6
  • 44
  • 59
  • Okay, but the problem is that I don't know the project name (could be any). I managed to do it now using some kind of a brute-force URLClassloader I had used before and calling classloader.findResource(classname). – Cedric Reichenbach Aug 03 '12 at 19:44
  • Is this class on a Java project's class path? – Chris Gerken Aug 03 '12 at 19:50
  • Not necessarily. I'm implementing something similar to the clickability of text like `(Main.java:12)` in the console (e.g. in a stack trace). – Cedric Reichenbach Aug 03 '12 at 20:07
  • OK. In that case you'd have to scan the entire workspace. It's similar to the code above, but instead of getting a single project by name you use getProjects() to get all of the projects. For each project, check the project description for nature "org.eclipse.jdt.core.javanature" to see if it's a java project. Scan the .classpath file in the project for classpathentry elements of type "src" to get all of the source folders and then see if the source folder has a file matching the fully qualified name. You may get multiple matches so use a dialog to let the user choose the right file. – Chris Gerken Aug 03 '12 at 20:16
  • That's exacltly what I did when building the classloader. :D I thought it was brutal, but it seems to work in useful time (if I don't instantiate it every time again). And because I know the package, I do something like `package.split("\\.")` and check for every part if `url.toExternalForm().contains(part)`. This way it's very unlikely to still have a collision (impossible with intelligent package names). – Cedric Reichenbach Aug 03 '12 at 20:37
1

I know this is a bit old but I had the same need and I had a look at how eclipse does it for stack trace elements (they have a hyperlink on them). The code is in org.eclipse.jdt.internal.debug.ui.console.JavaStackTraceHyperlink (the link is "lazy" so the editor to open is resolved only when you click on it).

What it does is it first searches for the type in the context of the launched application, then for in the whole workspace (method startSourceSearch) :

IType result = OpenTypeAction.findTypeInWorkspace(typeName, false);

And then opens the associated editor (method processSearchResult, source is the type retrieved above) :

protected void processSearchResult(Object source, String typeName, int lineNumber) {
    IDebugModelPresentation presentation = JDIDebugUIPlugin.getDefault().getModelPresentation();
    IEditorInput editorInput = presentation.getEditorInput(source);
    if (editorInput != null) {
        String editorId = presentation.getEditorId(editorInput, source);
        if (editorId != null) {
            try { 
                IEditorPart editorPart = JDIDebugUIPlugin.getActivePage().openEditor(editorInput, editorId);
                if (editorPart instanceof ITextEditor && lineNumber >= 0) {
                    ITextEditor textEditor = (ITextEditor)editorPart;
                    IDocumentProvider provider = textEditor.getDocumentProvider();
                    provider.connect(editorInput);
                    IDocument document = provider.getDocument(editorInput);
                    try {
                        IRegion line = document.getLineInformation(lineNumber);
                        textEditor.selectAndReveal(line.getOffset(), line.getLength());
                    } catch (BadLocationException e) {
                        MessageDialog.openInformation(JDIDebugUIPlugin.getActiveWorkbenchShell(), ConsoleMessages.JavaStackTraceHyperlink_0, NLS.bind("{0}{1}{2}", new String[] {(lineNumber+1)+"", ConsoleMessages.JavaStackTraceHyperlink_1, typeName}));  //$NON-NLS-2$ //$NON-NLS-1$
                    }
                    provider.disconnect(editorInput);
                }
            } catch (CoreException e) {
                JDIDebugUIPlugin.statusDialog(e.getStatus()); 
            }
        }
    }       
}

Code has copyright from eclipse. Hopfully I'm allowed to reproduced it if this is mentionned.

yannick1976
  • 10,171
  • 2
  • 19
  • 27