Bug 528419 - [code mining] Provide extension point for CodeMining
Summary: [code mining] Provide extension point for CodeMining
Status: RESOLVED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: Text (show other bugs)
Version: 4.8   Edit
Hardware: All All
: P3 enhancement (vote)
Target Milestone: 4.8 M5   Edit
Assignee: Angelo ZERR CLA
QA Contact:
URL:
Whiteboard:
Keywords: Documentation, noteworthy
Depends on: 527515
Blocks: 526969 528728
  Show dependency tree
 
Reported: 2017-12-11 08:42 EST by Angelo ZERR CLA
Modified: 2018-04-05 17:31 EDT (History)
2 users (show)

See Also:


Attachments
Demo with CodeMining & dotproject GenericEditor (236.66 KB, image/gif)
2017-12-14 06:30 EST, Angelo ZERR CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Angelo ZERR CLA 2017-12-11 08:42:57 EST
An extension point should be provided to register ICodeMiningProviders for a given text editor (JDT Editor, GenericEditor).

Here how we could register codemining providers for JDT to support 2 codemining providers:

 * codemining for references/implementations/main (run debug) :
 * codemining for JUnit test (run debug) :

-----------------------------------------------------------------------------
<extension
      point="org.eclipse.ui.workbench.texteditor.codeMiningProviders">
   <codeMiningProvider
         id="java"
         activate="true"
         class="JavaCodeMiningProvider"
         name="Java CodeMining"
         targetId="java.codeminings.target">
   </codeMiningProvider>
</extension>

<extension
      point="org.eclipse.ui.workbench.texteditor.codeMiningProviders">
   <codeMiningProvider
         id="junit"
         activate="true"
         class="JUnitCodeMiningProvider"
         name="JUnit CodeMining"
         targetId="java.codeminings.target">
   </codeMiningProvider>
</extension>

<extension
      point="org.eclipse.ui.workbench.texteditor.codeMiningProviderTargets">
   <target
         id="java.codeminings.target"
         name="Java Editor">
   </target>
</extension>
-----------------------------------------------------------------------------

Each codemining providers are linked to a target id "java.codeminings.target" that JDT Java Editor should register. It works exactly like hyperlink extension point.
Comment 1 Angelo ZERR CLA 2017-12-11 18:38:21 EST
An another proposition is to provide one extension point "org.eclipse.ui.workbench.texteditor.codeMinings" (1) instead of 2 extension point "org.eclipse.ui.workbench.texteditor.codeMiningProviders" & "org.eclipse.ui.workbench.texteditor.codeMiningProviderTargets"(2) like:

-----------------------------------------------------------------------------
<extension
      point="org.eclipse.ui.workbench.texteditor.codeMinings">
   <provider
         id="java"
         activate="true"
         class="JavaCodeMiningProvider"
         name="Java CodeMining"
         targetId="java.codeminings.target">
   </provider>
   <provider
         id="junit"
         activate="true"
         class="JUnitCodeMiningProvider"
         name="JUnit CodeMining"
         targetId="java.codeminings.target">
   </provider>
   <target
         id="java.codeminings.target"
         name="Java Editor">
   </target>
</extension>
-----------------------------------------------------------------------------

What do you prefer? (1) or (2) ?
Comment 2 Mickael Istria CLA 2017-12-12 03:24:01 EST
I'm not a big fan of this `target` pattern in general.
I prefer activation/enablement based on content-type or enabledWhen/activeWhen expression that give much more flexibility. Do you think an approach based on enabledWhen is doable here?
Comment 3 Angelo ZERR CLA 2017-12-12 03:38:37 EST
> I'm not a big fan of this `target` pattern in general.

Me too:) But I though to keep the same logic than hyperlink.

> I prefer activation/enablement based on content-type or enabledWhen/activeWhen expression that give much more flexibility.

Is it a good idea to use content type? For instance with lsp codelens, the condition is not about content type but with support of codelens language server. My first idea was to manage that with a property test class that you imlement as you wish.

What do you think about that?
Comment 4 Mickael Istria CLA 2017-12-12 03:42:45 EST
(In reply to Angelo ZERR from comment #3)
> Is it a good idea to use content type?

Content-type may not be enough, but it'd be nice if we could include this as a condition on an enableWhen or such.
That said, I don't think we do need it at the moment

> For instance with lsp codelens, the
> condition is not about content type but with support of codelens language
> server. My first idea was to manage that with a property test class that you
> imlement as you wish.
> What do you think about that?

I think it's good. Moreover, activeWhen/enableWhen interpreters can very well handle thos property test class, so it seems like the most flexible and powerful approach.
Comment 5 Angelo ZERR CLA 2017-12-12 04:13:50 EST
@Mickael, have you a sample code with activeWhen/enableWhen interpreters (extension point declaration and Java code which load this extension point)?
Comment 6 Mickael Istria CLA 2017-12-12 04:21:03 EST
    IConfigurationElement activeWhen = activeWhenElements[0];
    IConfigurationElement[] activeWhenChildren = activeWhen.getChildren();
    if (activeWhenChildren.length == 1) {
      try {
        Expression expression = this.expressionConverter.perform(activeWhen.getChildren()[0]);
        EvaluationContext context = new EvaluationContext(null, defaultEvaluationObject);
        isActive = expression.evaluate(context).equals(EvaluationResult.TRUE);
     }
   }

The hardest part is to properly create the EvaluationContext with relevant data.
Comment 7 Mickael Istria CLA 2017-12-12 04:23:02 EST
(In reply to Mickael Istria from comment #6)
> [...]

With 
   this.expressionConverter = new ExpressionConverter(new ElementHandler[] {
      ElementHandler.getDefault(),
      // other custom element handlers that can make sense here
   });
Comment 8 Angelo ZERR CLA 2017-12-12 04:27:23 EST
Thanks @Mickael for your feedback. I have never done that, I must study it. I don't know how many  time I could do that. If it's so hard for me, perhaps I could create a gerrit patch without enableWhen at first?
Comment 9 Mickael Istria CLA 2017-12-12 04:48:57 EST
Ok.
However, I'd rather avoid introducing the "target" in the extension point if we plan to replace it with something better. A first iteration should skip it.
Also, I don't get what's the "activate" attibute. Can you please explain?
Comment 10 Angelo ZERR CLA 2017-12-12 06:23:37 EST
> However, I'd rather avoid introducing the "target" in the extension point if we plan to replace it with something better. A first iteration should skip it.

Yes sure.

> Also, I don't get what's the "activate" attibute. Can you please explain?

It's like hyperlink, activate - an attribute that tells whether to activate the contributing plug-in when hyperlink detection takes place in the given target (not sure we need it?)
Comment 11 Mickael Istria CLA 2017-12-12 06:41:24 EST
(In reply to Angelo ZERR from comment #10)
> It's like hyperlink, activate - an attribute that tells whether to activate
> the contributing plug-in when hyperlink detection takes place in the given
> target (not sure we need it?)

No, I don't think we need it. We should use the typical rule of extension: plugin loads automatically when contributed class is loaded. If we need some earlier loading, we'll add it later; but as the vast majority of extension do work well without such `activate`, I don't see why we need it here more than anywhere else.
Comment 12 Angelo ZERR CLA 2017-12-12 08:11:47 EST
> The hardest part is to properly create the EvaluationContext with relevant data.

I think I understand more what you mean. The data that I can have is ISourceViewer (because I'm in TextSourceViewerConfiguration to retrieve ICodeMiningProvider extension point). 

For LSP it will work since LanguageServiceAccessor.getLSPDocumentInfosFor works with a IDocument. 

But what about with other case? I think other editors will need IResource or ITextEditor, but it's not possible to get in TextSourceViewerConfiguration.

Hyperlink works in other editor because they register their editor in their context by overriding #getHyperlinkDetectorTargets (like GenericEditor does).

Have you an idea @Mickael how I could do it? Is IsourceViewer data is enough?
Comment 13 Mickael Istria CLA 2017-12-12 09:22:45 EST
Having an ISourceViewer may be enough, because from the viewer we should be able to get document, and from the document the content-type... I believe there may be some issues about the initialization sequence which may make that from the first call, the viewer won't contain reference to the document and is not so useful. What you can do to work around that is to initiatilize the codeMiningProviders as part of the documentChanged(...) in the TextEditor.
Comment 14 Angelo ZERR CLA 2017-12-12 10:32:09 EST
All features (content assist,hyperlink, etc) are initialized in SourceViewer#configure(SourceViewerConfiguration configuration) but at this step document is null.

So if we wish to use enableWhen, we should do that in other place (like documentChanged for instance). I could do that but it will differ from other features. Is it not annoying?
Comment 15 Mickael Istria CLA 2017-12-12 10:34:42 EST
(In reply to Angelo ZERR from comment #14)
> Is it not annoying?

Not to me, especially if it works better and give much more powerful enablement possibilities.
Comment 16 Angelo ZERR CLA 2017-12-12 10:37:33 EST
> Not to me, especially if it works better and give much more powerful enablement possibilities.

Perhaps initialize of CodeMining should be done with a CompletableFuture in order to avoid freezing the editor. I think about lsp which can take time to initialize language server. No?
Comment 17 Mickael Istria CLA 2017-12-12 14:48:18 EST
(In reply to Angelo ZERR from comment #16)
> Perhaps initialize of CodeMining should be done with a CompletableFuture in
> order to avoid freezing the editor. I think about lsp which can take time to
> initialize language server. No?

I don't think it's necessary. At this point, I think it's up to the provider to make the initialization fast and deal with it.
For example, LSP4E would contribute the codemining provider anyway, and this codemining provider would simply not return anything until the LS is started, so the delay to start server happens later (during the computation of codemining)
Comment 18 Eclipse Genie CLA 2017-12-13 10:03:13 EST
New Gerrit change created: https://git.eclipse.org/r/113331
Comment 19 Angelo ZERR CLA 2017-12-13 10:12:05 EST
@Mickael, please see my gerrit patch https://git.eclipse.org/r/#/c/113331/ which provides codemining provider extension point with <enabledWhen>. You can see a sample with the codeMiningProviders.exsd:

-----------------------------------------------------
   <extension
         point="org.eclipse.ui.workbench.texteditor.codeMiningProviders">
      <codeMiningProvider
         class="org.eclipse.jdt.internal.ui.codemining.JavaReferencesCodeMiningProvider"
         id="org.eclipse.jdt.ui.codemining.references"
         label="Java References">
         <enabledWhen>
            <with variable="editor">
               <instanceof value="org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor"/>
            </with>
         </enabledWhen>
      </codeMiningProvider>
   </extension>
-----------------------------------------------------

Here 2 important information (I don't know how to set it, in exsd?):

- enabledWhen : available variables are "editor" & "viewer" and default variable is the editor. I tell me if "editor" should be enough, because we can retrieve the viewer from the editor, no?
- the extension point don't update codeminings, it just register ICodeMiningProviders. Where can I add this information?
 - in other words, the update is not done, developer must call SourceViewer#updateCodeMinings() in a reconciler or other things. My question is about update on focus ? Perhaps AbstractTextEditor#setFocus should update codeminings? I think about this case when a java editor changes some content and when you go at in an another editor, codeminings should be updated.
Comment 20 Angelo ZERR CLA 2017-12-14 04:07:16 EST
@Mickael I would like to provide a sample with CodeMining extension point. My proposition is to display number of referenced project inside .project by using the org.eclipse.ui.genericeditor.examples which supports .project editor with GenericEditor. Take a sample with a "test" project and a "test2" project which references "test" project. When you will open .project you will see that:

 * test/.project

-----------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
        1 reference
	<name>test</name>
...
-----------------------------------------

 * test2/.project

-----------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
        0 reference
	<name>test2</name>
...
-----------------------------------------

Do you like this idea?
Comment 21 Mickael Istria CLA 2017-12-14 04:15:55 EST
(In reply to Angelo ZERR from comment #20)
> My proposition is to display number of referenced project inside .project
> [...]
> Do you like this idea?

Yes, a lot!
Comment 22 Angelo ZERR CLA 2017-12-14 06:30:22 EST
Created attachment 271909 [details]
Demo with CodeMining & dotproject GenericEditor

Here a demo that I have done for .project inside org.eclipse.ui.genericeditor.examples

Because of this demo, I have added "editorInput" in the expression context to check content type (see <with variable="editorInput">):

--------------------------------------------------
<extension
      point="org.eclipse.ui.workbench.texteditor.codeMiningProviders">
      <codeMiningProvider
           class="org.eclipse.ui.genericeditor.examples.dotproject.codemining.ProjectReferencesCodeMiningProvider"
           id="org.eclipse.ui.genericeditor.examples.dotproject.codemining.references"
           label="Project references">
           <enabledWhen>
           	  <with variable="editorInput">
                 <adapt type="org.eclipse.core.resources.IFile">
                   <test property="org.eclipse.core.resources.contentTypeId" value="org.eclipse.ui.genericeditor.examples.dotproject" />
                 </adapt>
           	  </with>
           </enabledWhen>
      </codeMiningProvider>
   </extension>
--------------------------------------------------

In other words, today we have 2 variables "editor", "editorInput" and "viewer".

A problem that I have seen with this demo, is that minings is not updated when editor takes focus. (it's annoying if you change project references in project2 (remove project1 as reference) and you go at .project of project1.

So I tell me, if minings should be updated on focus (in AbstractTextEditor#setFocus)

An another things that I have seen is that AbstractCodeMiningProvider is not helpfull. Perhaps we should remove it?
Comment 23 Mickael Istria CLA 2017-12-14 09:45:55 EST
All that seems really great! Being able to use the editor input is incredibly practical and powerful! That looks like, once again, a great piece of work!
Before merging the patch, I'd like to be able to look at the example you implemented. Would you mind pushing another Gerrit with the example to ease review?
Comment 24 Eclipse Genie CLA 2017-12-14 12:22:30 EST
New Gerrit change created: https://git.eclipse.org/r/113429
Comment 25 Angelo ZERR CLA 2017-12-14 12:25:27 EST
> All that seems really great! 

Cool!!!

> Being able to use the editor input is incredibly practical and powerful! That looks like, once again, a great piece of work!

Wow, thanks! But it was your idea to provide "enabledWhen" which was a so great idea:)

> Before merging the patch, I'd like to be able to look at the example you implemented. Would you mind pushing another Gerrit with the example to ease review?

done with https://git.eclipse.org/r/113429

Please note that I have added a comment at https://git.eclipse.org/r/#/c/113429/1/org.eclipse.ui.genericeditor.examples/src/org/eclipse/ui/genericeditor/examples/dotproject/codemining/ProjectCodeMiningStrategy.java about focus.
Comment 27 Eclipse Genie CLA 2017-12-15 14:45:43 EST
New Gerrit change created: https://git.eclipse.org/r/113502
Comment 28 Angelo ZERR CLA 2017-12-15 14:46:16 EST
@Mickael please review my gerrit patch https://git.eclipse.org/r/#/c/113502/ for N&N. Thanks!