diff --git a/net.sf.eclipsefp.haskell.buildwrapper/src/net/sf/eclipsefp/haskell/buildwrapper/types/Location.java b/net.sf.eclipsefp.haskell.buildwrapper/src/net/sf/eclipsefp/haskell/buildwrapper/types/Location.java index 78dc188f4..04d3f6052 100644 --- a/net.sf.eclipsefp.haskell.buildwrapper/src/net/sf/eclipsefp/haskell/buildwrapper/types/Location.java +++ b/net.sf.eclipsefp.haskell.buildwrapper/src/net/sf/eclipsefp/haskell/buildwrapper/types/Location.java @@ -131,8 +131,9 @@ public Location(IProject project, String fileName, int startLin, int startCol, i if (lineTracker != null) { try { //System.err.println("Initial span: "+startLine+":"+startColumn+" to "+endLine+":"+endColumn); + String delimiter = lineTracker.getLineDelimiter(startLine-1); // apparently this can return null int lineLength = lineTracker.getLineLength(startLine-1 /*LineTracker is 0 based*/ ) - - lineTracker.getLineDelimiter(startLine-1).length(); // subtract the delimiter length + - (delimiter == null ? 0 : delimiter.length()); // subtract the delimiter length if (startLine==endLine && startColumn==endColumn) { // span is empty if (startColumn < lineLength) { // not past the last character, so we can extend to the right. endColumn += 1; diff --git a/net.sf.eclipsefp.haskell.ui/plugin.xml b/net.sf.eclipsefp.haskell.ui/plugin.xml index aa1ae2124..d86c85520 100644 --- a/net.sf.eclipsefp.haskell.ui/plugin.xml +++ b/net.sf.eclipsefp.haskell.ui/plugin.xml @@ -906,6 +906,10 @@ + + + diff --git a/net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/editors/haskell/HaskellInformationControl.java b/net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/editors/haskell/HaskellInformationControl.java index 25ea3a6ed..a0232ecf9 100644 --- a/net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/editors/haskell/HaskellInformationControl.java +++ b/net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/editors/haskell/HaskellInformationControl.java @@ -6,6 +6,8 @@ import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.text.AbstractInformationControl; +import org.eclipse.jface.text.IInformationControl; +import org.eclipse.jface.text.IInformationControlCreator; import org.eclipse.jface.util.Geometry; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.Browser; @@ -20,9 +22,11 @@ * @author Alejandro Serrano * */ -@Deprecated public class HaskellInformationControl extends AbstractInformationControl { + private static final int HOVER_WIDTH = 600; // size of the tooltip for + private static final int HOVER_HEIGHT = 80; // type info and errors/warnings + private Browser doc; private boolean hasContents = false; @@ -40,16 +44,16 @@ public void setInformation( final String content ) { protected void createContent( final Composite parent ) { doc = new Browser( parent, SWT.NONE ); - //doc.setForeground( parent.getForeground() ); - //doc.setBackground( parent.getBackground() ); + // These have no effect, so we set the colors with css. + // Unfortunately, the background remains white, which is sometimes visible when scrolling doc.setForeground( parent.getDisplay().getSystemColor( SWT.COLOR_INFO_FOREGROUND ) ); - doc.setBackground( parent.getDisplay().getSystemColor( SWT.COLOR_INFO_BACKGROUND ) ); - doc.setFont( JFaceResources.getDialogFont() ); + doc.setBackground( parent.getDisplay().getSystemColor( SWT.COLOR_YELLOW ) ); + doc.setFont( JFaceResources.getTextFont() ); } public void setDocumentation( final String content ) { hasContents = content.length() > 0; - doc.setText( content ); + doc.setText( ""+content+"" ); } /* @@ -64,6 +68,7 @@ public void setVisible( final boolean visible ) { /* * @see IInformationControl#computeSizeHint() */ + /* @Override public Point computeSizeHint() { // see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=117602 @@ -75,6 +80,18 @@ public Point computeSizeHint() { return getShell().computeSize( widthHint, SWT.DEFAULT, true ); } +For some reason, the method above causes a very large tooltip to be generated, which is +briefly visible before it shrinks to its normal size. Unfortunately, this doesn't happen +on test runs, but only when the plug-in is deployed, making it extremely difficult to debug. +The problem doesn't seem to occur in Eclipse Juno. + +For some other reason, everything works fine if we specify the size with computeSizeConstraints. +*/ + @Override + public Point computeSizeConstraints(final int widthInChars, final int heightInChars) { + return new Point(HOVER_WIDTH,HOVER_HEIGHT); + } + /* * @see org.eclipse.jface.text.AbstractInformationControl#computeTrim() */ @@ -116,4 +133,22 @@ public void setFocus() { doc.setFocus(); } + // Without this, the hover text disappears immediately on a mouse move. + /* + * @see org.eclipse.jface.text.IInformationControlExtension5#getInformationPresenterControlCreator() + * @since 3.4 + */ + @Override + public IInformationControlCreator getInformationPresenterControlCreator() { + return new IInformationControlCreator() { + /* + * @see org.eclipse.jface.text.IInformationControlCreator#createInformationControl(org.eclipse.swt.widgets.Shell) + */ + @Override + public IInformationControl createInformationControl(final Shell parent) { + return new HaskellInformationControl(parent); + } + }; + } + } diff --git a/net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/editors/haskell/HaskellTextHover.java b/net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/editors/haskell/HaskellTextHover.java index 89138d573..5fbefbd8e 100644 --- a/net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/editors/haskell/HaskellTextHover.java +++ b/net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/editors/haskell/HaskellTextHover.java @@ -11,10 +11,10 @@ import net.sf.eclipsefp.haskell.buildwrapper.types.ThingAtPoint; import net.sf.eclipsefp.haskell.ui.HaskellUIPlugin; import net.sf.eclipsefp.haskell.ui.internal.editors.haskell.imports.ImportsManager; +import net.sf.eclipsefp.haskell.ui.internal.preferences.editor.IEditorPreferenceNames; import net.sf.eclipsefp.haskell.ui.internal.util.UITexts; import org.eclipse.core.resources.IFile; import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.DefaultInformationControl; import org.eclipse.jface.text.DefaultTextHover; import org.eclipse.jface.text.IInformationControl; import org.eclipse.jface.text.IInformationControlCreator; @@ -51,11 +51,11 @@ public String getHoverInfo( final ITextViewer textViewer, final IRegion hoverRegion ) { // TODO TtC this method does not get called when hovering over a string literal // which leads to potential problem annotation hovers not appearing - String hoverInfo = computeProblemInfo( textViewer, hoverRegion,fMarkerAnnotationAccess ); - if (hoverInfo != null) { - return hoverInfo; - } - return computeThingAtPoint( textViewer, hoverRegion,false ); + String hoverInfo = computeProblemInfo( textViewer, hoverRegion,fMarkerAnnotationAccess); + if (hoverInfo != null) { + return hoverInfo; + } + return computeThingAtPoint( textViewer, hoverRegion,false ); } /* (non-Javadoc) @@ -64,7 +64,7 @@ public String getHoverInfo( final ITextViewer textViewer, @Override public Object getHoverInfo2( final ITextViewer textViewer, final IRegion hoverRegion) { - String hoverInfo = computeProblemInfo( textViewer, hoverRegion,fMarkerAnnotationAccess ); + String hoverInfo = computeProblemInfo( textViewer, hoverRegion,fMarkerAnnotationAccess); if (hoverInfo != null) { return hoverInfo; } @@ -80,8 +80,8 @@ public IInformationControlCreator getHoverControlCreator() { @Override public IInformationControl createInformationControl( final Shell parent ) { - //return new HaskellInformationControl(parent,editor.getFont()); - return new DefaultInformationControl( parent, false ); + return new HaskellInformationControl(parent); + //return new DefaultInformationControl( parent, false ); // for bold-only tooltips } } ; } @@ -100,7 +100,9 @@ public static String computeProblemInfo( final ITextViewer textViewer, final IRe fMarkerAnnotationAccess.isSubtype( type, WARNING_ANNOTATION_TYPE )) { Position p = annotationModel.getPosition( a ); if (p.overlapsWith( hoverRegion.getOffset(), hoverRegion.getLength() )) { - return a.getText(); + return "
" + + a.getText() + + "
"; } } } @@ -123,26 +125,36 @@ protected String computeThingAtPoint( final ITextViewer textViewer, final IRegio ThingAtPoint tap=f.getThingAtPoint(file,location); if (tap!=null){ StringBuilder sb=new StringBuilder(); + + + sb.append(html ? "
" : ""); sb.append(tap.getName()); + String moduleColor = HaskellUIPlugin.getDefault().getPreferenceStore().getString( IEditorPreferenceNames.EDITOR_CON_COLOR ); + if (tap.getType()!=null){ sb.append(" :: "); + sb.append(html ? "" : ""); sb.append(tap.getType()); + sb.append(html ? "" : ""); } - if(html){ - sb.insert( 0, "" ); - sb.append( "" ); + if (tap.getModule()!=null){ + sb.append(html ? "
" : "\n"); + sb.append(html ? "module: " : ""); + sb.append(tap.getModule()); + sb.append(html ? "" : ""); } + sb.append(html ? "
" : ""); ImportsManager im=editor.getImportsManager(); Documented d=im.getDeclarations().get( tap.getName() ); if (d!=null && d.getDoc()!=null && d.getDoc().length()>0){ - if(html){ - sb.append( "
" ); - } else { - sb.append("\n"); - } + sb.append(html ? "
" : "\n"); + sb.append(html ? "
" : ""); sb.append(d.getDoc()); + sb.append(html ? "
" : ""); + } + return sb.toString(); } //} finally { diff --git a/net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/editors/haskell/imports/AnImport.java b/net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/editors/haskell/imports/AnImport.java index fb1359f34..7a70183de 100644 --- a/net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/editors/haskell/imports/AnImport.java +++ b/net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/editors/haskell/imports/AnImport.java @@ -270,7 +270,11 @@ private static List getDeclarationsFromOutlineResult( final IFil outlineToBrowser( def,null,file,decls ); } for (ExportDef ed:or.getExportDefs()){ - if (ed.getType().equals( ImportExportType.IEModule )){ + if (ed.getType().equals( ImportExportType.IEModule ) + && !file.getName().equals(ed.getName()+".hs") // Hacky workaround for bug that causes a loop when the export list contains the module itself. + // This hack can probably still fail in case of hi-boot import cycles, + // so it's better to keep track of visited modules. + ){ decls.addAll( getDeclarationsFromFile( ed.getName(), file.getProject() ) ); } }