Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 320439

Summary: Add support for rich hovers in editor (like JDT)
Product: [Modeling] TMF Reporter: Christoph Kulla <christophkulla>
Component: XtextAssignee: Project Inbox <tmf.xtext-inbox>
Status: CLOSED FIXED QA Contact:
Severity: enhancement    
Priority: P3 CC: b.kolb, jan, sebastian.zarnekow, sven.efftinge, thsoft, tmf.xtext-inbox
Version: unspecifiedFlags: sebastian.zarnekow: indigo+
Target Milestone: M4   
Hardware: PC   
OS: Mac OS X - Carbon (unsup.)   
Whiteboard:
Bug Depends on:    
Bug Blocks: 320818    
Attachments:
Description Flags
Patch for the hover
none
hover without focus
none
hover with focus
none
hover after following link to "String".
none
Hover with quickfixes
none
Patch for the hover (version 2)
none
Patch adapted to HEAD
none
Hover patch, refactored according to review, added tests sven.efftinge: iplog+

Description Christoph Kulla CLA 2010-07-20 16:03:20 EDT
Build Identifier: 1.0.0

The attached patch contains an initial implementation of a generic html based text hover for
 EObjects in Xtext (XtextHtmlHover). The text hover is a clone of JDT's javadoc hover.  
 The hover content is made by an IHtmlHoverContentProvider, which returns the html content 
 for a given model element. The hover  supports linking to other model elements 
 (see XtextElementLinks), navigating forward  and backward  and open declaration. 
 All classes related to the html hover can be found in the org.eclipse.xtext.ui.editor.hover.html package. 
I've attached a couple of screen shots which show the hover in action in the domainmodel example. 

The hover content can be build in arbitrary ways. To mimic javadoc style one has to extract
 the content of multi line comments in front of model elements. The class 
 MultiLineDocumentationProvider does exactly this task. Note: The comment  has to start with /** to 
 be recognized as a documentation  comment (look at DomainmodelHoverContentProvider or 
 DefaultHtmlHoverContentProvider).

Issues:

(1) Think about a reasonable default hover (see DefaultHtmlHoverContentProvider, or should the hover 
be turned off by default?)

(2) Review AbstractXtextEditorHover.getXtextElementAt() method. I'm not sure that the implemenation 
is correct.

(3) Add support for showing the icon of a model element (from the label provider). Not easy
as the image itself can not be displayed (must be a link to a file embedded in html, JDT offers an 
implementation for converting ImageDescriptions to files). 

(4) Remove hard coded reference to "org.eclipse.jdt.ui.javadocfont"

(5) Potential clean-up: Remove XtextTextHover, remove AbstractHover, derive ProblemHover 
from AbstractXtextEditorHover

Possible Future Improvements:

(6) Add an Xtextdoc view (like javadoc view)

(7) Add the hover to completion proposals for cross references.

(8) Enhance problem hover, show available quickfixes as JDT does.

(9) Handle the case where no browser is available (fallback to styled text, 
convert html to styledtext, see JDT).

(10) Add support for displaying arbitrary hovers for certain elements (e.g. display the original JDT hover 
for references to java classes (JDTTypes)).


Reproducible: Always
Comment 1 Christoph Kulla CLA 2010-07-20 16:04:47 EDT
Created attachment 174786 [details]
Patch for the hover
Comment 2 Christoph Kulla CLA 2010-07-20 16:11:17 EDT
Created attachment 174788 [details]
hover without focus
Comment 3 Christoph Kulla CLA 2010-07-20 16:12:22 EDT
Created attachment 174789 [details]
hover with focus
Comment 4 Christoph Kulla CLA 2010-07-20 16:13:26 EDT
Created attachment 174790 [details]
hover after following link to "String".
Comment 5 Sebastian Zarnekow CLA 2010-07-22 08:23:38 EDT
*** Bug 284943 has been marked as a duplicate of this bug. ***
Comment 6 Christoph Kulla CLA 2010-08-18 08:54:20 EDT
Created attachment 176886 [details]
Hover with quickfixes
Comment 7 Christoph Kulla CLA 2010-08-18 09:04:38 EDT
Created attachment 176887 [details]
Patch for the hover (version 2)

Attached a new version of the patch. Contains now an problem hover showing available quick fixes. This patch does also contains the java doc hover from https://bugs.eclipse.org/bugs/show_bug.cgi?id=320818 (https://bugs.eclipse.org/bugs/show_bug.cgi?id=320818 is now obsolete).
Comment 8 Christoph Kulla CLA 2010-08-18 09:29:57 EDT
This patch introduces the class DelegatingHover, which let's you register a number of hovers with a guice multibinder.  I could get the multibinder working only with the non AOP guice version. With the regular guice version I get the following exception:

java.lang.IllegalAccessError: tried to access class com.google.inject.multibindings.Multibinder$RealMultibinder from class $com.google.inject.multibindings.Multibinder$RealMultibinder$$FastClassByGuice$$94efefc8
	at $com.google.inject.multibindings.Multibinder$RealMultibinder$$FastClassByGuice$$94efefc8.invoke(<generated>)
	at com.google.inject.internal.cglib.reflect.FastMethod.invoke(FastMethod.java:53)
	at com.google.inject.SingleMethodInjector$1.invoke(SingleMethodInjector.java:59)
	at com.google.inject.SingleMethodInjector.inject(SingleMethodInjector.java:91)
	at com.google.inject.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:99)
	at com.google.inject.MembersInjectorImpl$1.call(MembersInjectorImpl.java:76)
	at com.google.inject.MembersInjectorImpl$1.call(MembersInjectorImpl.java:74)
	at com.google.inject.InjectorImpl.callInContext(InjectorImpl.java:804)
	at com.google.inject.MembersInjectorImpl.injectAndNotify(MembersInjectorImpl.java:74)
	at com.google.inject.Initializer$InjectableReference.get(Initializer.java:145)
	at com.google.inject.Initializer.injectAll(Initializer.java:92)
	at com.google.inject.InjectorBuilder.injectDynamically(InjectorBuilder.java:171)
	at com.google.inject.InjectorBuilder.build(InjectorBuilder.java:113)
	at com.google.inject.Guice.createInjector(Guice.java:92)

You can reproduce this by adding a multibinder like this:

	public void configureAdditionalHover(com.google.inject.Binder binder) {
		Multibinder<org.eclipse.jface.text.ITextHover> hoverBinder = Multibinder.newSetBinder(binder, org.eclipse.jface.text.ITextHover.class);
		hoverBinder.addBinding().to(org.eclipse.xtext.common.types.xtext.ui.JdtHover.class);
		//binder.bind(org.eclipse.jface.text.ITextHover.class).annotatedWith(com.google.inject.name.Names.named(org.eclipse.xtext.ui.editor.hover.DelegatingHover.ADDITIONAL_HOVER)).to(org.eclipse.xtext.common.types.xtext.ui.JdtHover.class);
	}

I guess this is the first time someone tried to use a multibinder within Xtext.
Comment 9 Sven Efftinge CLA 2010-08-18 13:52:20 EDT
(In reply to comment #8)
> I guess this is the first time someone tried to use a multibinder within Xtext.

We have tried them but I like the current approach more, because with that I can override (remove) an addition to a multibinding in submodules again. It's not optimal to inject the injector, but as it is pretty much encapsulated it's not such a big problem.

Btw.: Thanks for the contribution. This is a nice feature. We'll add it as soon as the SR1 is out and we have migrated to git.
Comment 10 Christoph Kulla CLA 2010-08-18 14:28:30 EDT
> Btw.: Thanks for the contribution. This is a nice feature. We'll add it as soon
> as the SR1 is out and we have migrated to git.

Thx, Sven. Just let me know if you have any issues with this patch I can help with.
Comment 11 Christoph Kulla CLA 2010-08-18 14:33:00 EDT
*** Bug 320818 has been marked as a duplicate of this bug. ***
Comment 12 Sven Efftinge CLA 2010-09-21 16:27:34 EDT
postponed to M3
Comment 13 Jan Koehnlein CLA 2010-09-28 11:34:57 EDT
Created attachment 179760 [details]
Patch adapted to HEAD

Adapted the patch to HEAD. Will be revised shortly.
Comment 14 Jan Koehnlein CLA 2010-09-29 09:03:19 EDT
I've finished revising your patch. Very impressive work, thank you! I am sure I've missed a lot of points, but I have a few (as it is a big patch quite a few) observations, which I put in the end of this comment. 

After all, it's a huge patch, covering multiple new features at once. I'd suggest to split it up into several smaller bugs, add a few tests :-), and discuss the individual issues in separately, e.g. EObject documentation, Hover delegation, HTML hovers, JDT hover integration, etc. Could you do that?

Here are my observations on the existing patch:

1) DelegatingHover:
I wouldn't add hovers using multibinding as you cannot specify their order. I'd rather provide a method in which the list of hovers is filled, such that the user can override it. I'd also skip the notions of default/priority hovers, as users might want to change that. Maybe we should skip the binding part for hovers for the sake of simplicity and inject instances by their concrete classes instead, e.g.

DelegatingHover {
  @Inject SomeHoverClass hover0;
  @Inject OtherHoverClass hover1;
   …

  protected List<ITextHover> createHovers() {
	List<ITextHover> hovers = Lists.newArrayList();
	hovers.add(hover0);
	hovers.add(hover1);
	return hovers;
  }
...


2) You should not pass EObjects/AbstractNodes as a result of an IUnitOfWork, e.g. in AbstractXtextEditorHover.getXtextElementAt(ITextViewer, int) as these could change concurrently thus becoming invalid. You have to put all calculation on these inside the unit. If you just need offset and length, consider using a (Text)Region. 

3) I'd expect AbstractXtextEditorHover (maybe better named AbstractTextHover) to inherit form AbstractHover. If there is nothing in common, we should rename AbstractHover or eliminate it.

4) AnnotationWithQuickFixesHover
Please document what is copied and what is changed. 

5) AbstractHtmlHoverContentProvider
I don't understand the delegation mechanism. Do you use it? If not, skip it in the first place. 

6) IHtmlHoverContentProvider:
Can there be non-EObject's ? If not, this interface looks pretty much like the IEObjectDocumentationProvider. 

7) XtextBrowserInformationControlInput:
Please don't use internal API.

8) TypesGeneratorFragment
Class name should be JdtHover, not JDTHover.

9) How about some tests? :-)
Comment 15 Christoph Kulla CLA 2010-10-13 03:33:24 EDT
(In reply to comment #14)

> I've finished revising your patch. Very impressive work, thank you! I am sure
> I've missed a lot of points, but I have a few (as it is a big patch quite a
> few) observations, which I put in the end of this comment. 

Jan, thanks for looking at the patch and providing your comments.
 
> After all, it's a huge patch, covering multiple new features at once. I'd
> suggest to split it up into several smaller bugs, add a few tests :-), and
> discuss the individual issues in separately, e.g. EObject documentation, Hover
> delegation, HTML hovers, JDT hover integration, etc. Could you do that?

Yep, good idea. Sven also proposed this some time ago. Don't know how fast I can provide those individual patches. What about creating an xtext clone on github where we can work on the hover stuff in separation instead of juggling with a lot of patches?
 
> Here are my observations on the existing patch:
> 
> 1) DelegatingHover:
> I wouldn't add hovers using multibinding as you cannot specify their order. I'd
> rather provide a method in which the list of hovers is filled, such that the
> user can override it. I'd also skip the notions of default/priority hovers, as
> users might want to change that. Maybe we should skip the binding part for
> hovers for the sake of simplicity and inject instances by their concrete
> classes instead, e.g.
> 
> DelegatingHover {
>   @Inject SomeHoverClass hover0;
>   @Inject OtherHoverClass hover1;
>    �
> 
>   protected List<ITextHover> createHovers() {
>     List<ITextHover> hovers = Lists.newArrayList();
>     hovers.add(hover0);
>     hovers.add(hover1);
>     return hovers;
>   }
> ...


The idea is to have the configuration decentralized and allow different generator fragments to contribute hovers. E.g. the TypesGeneratorFragment should be able to add the JdtHover. Not sure if this is still possible with the centralized method.
 
> 2) You should not pass EObjects/AbstractNodes as a result of an IUnitOfWork,
> e.g. in AbstractXtextEditorHover.getXtextElementAt(ITextViewer, int) as these
> could change concurrently thus becoming invalid. You have to put all
> calculation on these inside the unit. If you just need offset and length,
> consider using a (Text)Region. 

Ok, I'll have to look at this.
 
> 3) I'd expect AbstractXtextEditorHover (maybe better named AbstractTextHover)
> to inherit form AbstractHover. If there is nothing in common, we should rename
> AbstractHover or eliminate it.

Yep. See initial comment (5).  Potential clean-up: Remove XtextTextHover, remove AbstractHover, derive ProblemHover from AbstractXtextEditorHover

I think this should be postponed until all changes on the hover stuff are completed. Then the clean up should happen.

> 4) AnnotationWithQuickFixesHover
> Please document what is copied and what is changed. 

Can do.
 
> 5) AbstractHtmlHoverContentProvider
> I don't understand the delegation mechanism. Do you use it? If not, skip it in
> the first place. 

Just copied from AbstractLabelProvider, can be removed.
 
> 6) IHtmlHoverContentProvider:
> Can there be non-EObject's ? If not, this interface looks pretty much like the
> IEObjectDocumentationProvider. 

The IEObjectDocumentationProvider provides the raw text documentation for EObjects. The IHtmlHoverContentProvider returns html content for an object and may transform the result from the IEObjectDocumentationProvider into html. 

You are correct, that the HtmlHoverContentProvider deals only with EObjects by default. A possible scenario where objects are used, is when following special links in the html content, which may lead to objects insted of eobjects. Have to look at this in more detail.

> 
> 7) XtextBrowserInformationControlInput:
> Please don't use internal API.

Not sure how to solve this without using internal API. JDT's JavadocBrowserInformationControlInput is doing it the same way. Same problem at XtextHtmlHover. Any ideas?
 
> 8) TypesGeneratorFragment
> Class name should be JdtHover, not JDTHover.


Yep, will change

 
> 9) How about some tests? :-)

Will make a lot of sense.
Comment 16 Sven Efftinge CLA 2010-10-13 04:25:50 EDT
(In reply to comment #15)
> Yep, good idea. Sven also proposed this some time ago. Don't know how fast I
> can provide those individual patches. What about creating an xtext clone on
> github where we can work on the hover stuff in separation instead of juggling
> with a lot of patches?

Yes, let's do it. 
When the contribution is finished, it has to go through the IP process (because of its size).
Comment 17 Christoph Kulla CLA 2010-10-16 06:12:41 EDT
> Yes, let's do it. 
> When the contribution is finished, it has to go through the IP process (because
> of its size).

Setup an xtext clone at http://github.com/ckulla/xtext-hover/. There are two branches, master and hover. Master is a clone of the xtext repositroy, hover will provide changes regarding to this bug. This let's us update the master with changes from the regular xtext repository independent of changes in the hover branch. I applied the updated patch from Jan to the hover branch. Will do some changes according to Jan's comments in the near future.
Comment 18 Christoph Kulla CLA 2010-10-24 07:17:16 EDT
Issues 1)-6), 8) are fixed on http://github.com/ckulla/xtext-hover/commits/hover . Thanks for the review comments, the code is now much more concise.

 I don't see a solution for Issue 7)  unless changing the jface code to make the package org.eclipse.jface.internal.text.html public available. The JDT code faces the same issue (see JavadocBrowserInformationControlInput). 

Tests are still missing, hope to add some in the next days.
Comment 19 Christoph Kulla CLA 2010-11-21 05:29:02 EST
Created attachment 183535 [details]
Hover patch, refactored according to review, added tests

Added the result from refactoring according to Jan's comments. Please let me know if anything should be changed, if not this is the final version of the patch.
Comment 20 Sven Efftinge CLA 2010-11-22 14:16:48 EST
Thanks, will look into it tomorrow.
Comment 21 Sven Efftinge CLA 2010-11-23 07:26:22 EST
I've filed a CQ for the patch (http://dev.eclipse.org/ipzilla/show_bug.cgi?id=4658)
Comment 22 Christoph Kulla CLA 2010-11-24 04:41:06 EST
I authored 100% of the content (minus the reuse of Eclipse JDT source)
I have the rights to contribute the content to Eclipse
I contribute the content under the EPL
Comment 23 Christoph Kulla CLA 2010-11-24 08:19:47 EST
Please note that the patch contains a commit history from https://github.com/ckulla/xtext-hover/tree/hover. I created a branch from the xtext repository and developed the patch there. The first commit message on that branch is from Jan Koehnlein. Jan did a review of my initial patch[1] and modified it only slightly [2]. I then started from there to resolve all review comments. The result is in [3].

[1] https://bugs.eclipse.org/bugs/attachment.cgi?id=174786
[2] https://bugs.eclipse.org/bugs/attachment.cgi?id=179760
[3] https://bugs.eclipse.org/bugs/attachment.cgi?id=183535
Comment 24 Sven Efftinge CLA 2010-11-29 08:39:12 EST
pushed the patch, made implementation use and lookup language specific hover providers.
Comment 25 Karsten Thoms CLA 2017-09-19 17:57:02 EDT
Closing all bugs that were set to RESOLVED before Neon.0
Comment 26 Karsten Thoms CLA 2017-09-19 18:07:49 EDT
Closing all bugs that were set to RESOLVED before Neon.0