@@ -4,7 +4,11 @@ import * as lsProtocol from 'vscode-languageserver-protocol';
44import { FreeTooltip } from '../free_tooltip' ;
55import { DefaultMap , getModifierState , until_ready } from '../utils' ;
66import { PositionConverter } from '../converter' ;
7- import { CompletionTriggerKind , diagnosticSeverityNames } from '../lsp' ;
7+ import {
8+ CompletionTriggerKind ,
9+ diagnosticSeverityNames ,
10+ documentHighlightKindNames
11+ } from '../lsp' ;
812import { VirtualEditor } from '../virtual/editor' ;
913import { VirtualDocument } from '../virtual/document' ;
1014import {
@@ -20,10 +24,17 @@ export type KeyModifier = 'Alt' | 'Control' | 'Shift' | 'Meta' | 'AltGraph';
2024const hover_modifier : KeyModifier = 'Control' ;
2125const default_severity = 2 ;
2226
27+ interface IEditorRange {
28+ start : IEditorPosition ;
29+ end : IEditorPosition ;
30+ editor : CodeMirror . Editor ;
31+ }
32+
2333export class CodeMirrorAdapterExtension extends CodeMirrorAdapter {
2434 public connection : LSPConnection ;
2535 public editor : VirtualEditor ;
2636
37+ protected highlight_markers : CodeMirror . TextMarker [ ] = [ ] ;
2738 private marked_diagnostics : Map < string , CodeMirror . TextMarker > = new Map ( ) ;
2839 private _tooltip : FreeTooltip ;
2940 private show_next_tooltip : boolean ;
@@ -80,6 +91,9 @@ export class CodeMirrorAdapterExtension extends CodeMirrorAdapter {
8091 }
8192 } ) ;
8293
94+ this . editor . off ( 'cursorActivity' , listeners . cursorActivity ) ;
95+ this . editor . on ( 'cursorActivity' , this . onCursorActivity . bind ( this ) ) ;
96+
8397 this . editor . off ( 'change' , listeners . changeListener ) ;
8498 // due to an unknown reason the default listener (as defined in the base class) is not invoked on file editors
8599 // the workaround - setting it at doc instead - works, thus the original one is first disabled (above) and a new
@@ -185,7 +199,11 @@ export class CodeMirrorAdapterExtension extends CodeMirrorAdapter {
185199 return ;
186200 }
187201
188- this . highlight_range ( response . range , 'cm-lp-hover-available' ) ;
202+ // @ts -ignore
203+ this . hoverMarker = this . highlight_range (
204+ this . editor_range_for_hover ( response . range ) ,
205+ 'cm-lsp-hover-available'
206+ ) ;
189207
190208 if ( ! this . show_next_tooltip ) {
191209 this . last_hover_response = response ;
@@ -352,55 +370,103 @@ export class CodeMirrorAdapterExtension extends CodeMirrorAdapter {
352370 this . last_change = change ;
353371 }
354372
355- protected highlight_range ( range : lsProtocol . Range , class_name : string ) {
356- let hover_character = this . hover_character ;
373+ public handleHighlight ( items : lsProtocol . DocumentHighlight [ ] ) {
374+ for ( let marker of this . highlight_markers ) {
375+ marker . clear ( ) ;
376+ }
377+ this . highlight_markers = [ ] ;
357378
358- let start : IVirtualPosition ;
359- let end : IVirtualPosition ;
379+ if ( ! items ) {
380+ return ;
381+ }
360382
361- let start_in_editor : any ;
362- let end_in_editor : any ;
383+ for ( let item of items ) {
384+ let range = this . range_to_editor_range ( item . range ) ;
385+ let kind_class = item . kind
386+ ? 'cm-lsp-highlight-' + documentHighlightKindNames [ item . kind ]
387+ : '' ;
388+ let marker = this . highlight_range (
389+ range ,
390+ 'cm-lsp-highlight ' + kind_class
391+ ) ;
392+ this . highlight_markers . push ( marker ) ;
393+ }
394+ }
363395
364- let cm_editor : any ;
365- // NOTE: foreign document ranges are checked before the request is sent,
366- // no need to to this again here.
396+ protected onCursorActivity ( ) {
397+ let root_position = this . editor
398+ . getDoc ( )
399+ . getCursor ( 'start' ) as IRootPosition ;
400+ let document = this . editor . document_at_root_position ( root_position ) ;
401+ if ( document !== this . virtual_document ) {
402+ return ;
403+ }
404+ let virtual_position = this . editor . root_position_to_virtual_position (
405+ root_position
406+ ) ;
407+ this . connection . getDocumentHighlights ( virtual_position ) ;
408+ }
367409
368- if ( range ) {
369- start = PositionConverter . lsp_to_cm ( range . start ) as IVirtualPosition ;
370- end = PositionConverter . lsp_to_cm ( range . end ) as IVirtualPosition ;
410+ protected range_to_editor_range (
411+ range : lsProtocol . Range ,
412+ cm_editor ?: CodeMirror . Editor
413+ ) : IEditorRange {
414+ let start = PositionConverter . lsp_to_cm ( range . start ) as IVirtualPosition ;
415+ let end = PositionConverter . lsp_to_cm ( range . end ) as IVirtualPosition ;
371416
372- start_in_editor = this . virtual_document . transform_virtual_to_editor (
417+ if ( typeof cm_editor === 'undefined' ) {
418+ let start_in_root = this . transform_virtual_position_to_root_position (
373419 start
374420 ) ;
375- end_in_editor = this . virtual_document . transform_virtual_to_editor ( end ) ;
421+ cm_editor = this . editor . get_editor_at_root_position ( start_in_root ) ;
422+ }
423+
424+ return {
425+ start : this . virtual_document . transform_virtual_to_editor ( start ) ,
426+ end : this . virtual_document . transform_virtual_to_editor ( end ) ,
427+ editor : cm_editor
428+ } ;
429+ }
376430
377- cm_editor = this . editor . get_editor_at_root_position ( hover_character ) ;
431+ protected editor_range_for_hover ( range : lsProtocol . Range ) : IEditorRange {
432+ let character = this . hover_character ;
433+ // NOTE: foreign document ranges are checked before the request is sent,
434+ // no need to to this again here.
435+
436+ if ( range ) {
437+ let cm_editor = this . editor . get_editor_at_root_position ( character ) ;
438+ return this . range_to_editor_range ( range , cm_editor ) ;
378439 } else {
379440 // construct range manually using the token information
380- cm_editor = this . virtual_document . root . get_editor_at_source_line (
381- hover_character
441+ let cm_editor = this . virtual_document . root . get_editor_at_source_line (
442+ character
382443 ) ;
383- let token = this . editor . getTokenAt ( hover_character ) ;
444+ let token = this . editor . getTokenAt ( character ) ;
384445
385446 let start_in_root = {
386- line : hover_character . line ,
447+ line : character . line ,
387448 ch : token . start
388449 } as IRootPosition ;
389450 let end_in_root = {
390- line : hover_character . line ,
451+ line : character . line ,
391452 ch : token . end
392453 } as IRootPosition ;
393454
394- start_in_editor = this . editor . root_position_to_editor_position (
395- start_in_root
396- ) ;
397- end_in_editor = this . editor . root_position_to_editor_position ( end_in_root ) ;
455+ return {
456+ start : this . editor . root_position_to_editor_position ( start_in_root ) ,
457+ end : this . editor . root_position_to_editor_position ( end_in_root ) ,
458+ editor : cm_editor
459+ } ;
398460 }
461+ }
399462
400- // @ts -ignore
401- this . hoverMarker = cm_editor
463+ protected highlight_range (
464+ range : IEditorRange ,
465+ class_name : string
466+ ) : CodeMirror . TextMarker {
467+ return range . editor
402468 . getDoc ( )
403- . markText ( start_in_editor , end_in_editor , { className : class_name } ) ;
469+ . markText ( range . start , range . end , { className : class_name } ) ;
404470 }
405471
406472 protected position_from_mouse ( ev : MouseEvent ) : IRootPosition {
@@ -418,7 +484,6 @@ export class CodeMirrorAdapterExtension extends CodeMirrorAdapter {
418484 // TODO || token.type.length === 0? (sometimes the underline is shown on meaningless tokens)
419485 }
420486
421- // @ts -ignore
422487 public _handleMouseOver ( event : MouseEvent ) {
423488 // currently the events are coming from notebook panel; ideally these would be connected to individual cells,
424489 // (only cells with code) instead, but this is more complex to implement right. In any case filtering
@@ -481,7 +546,7 @@ export class CodeMirrorAdapterExtension extends CodeMirrorAdapter {
481546 protected collapse_overlapping_diagnostics (
482547 diagnostics : lsProtocol . Diagnostic [ ]
483548 ) : Map < lsProtocol . Range , lsProtocol . Diagnostic [ ] > {
484- // because Range is not a primitive types , the equality of the objects having
549+ // because Range is not a primitive type , the equality of the objects having
485550 // the same parameters won't be compared (thus considered equal) in Map.
486551
487552 // instead, a intermediate step of mapping through a stringified representation of Range is needed:
0 commit comments