@@ -277,6 +277,9 @@ Unless overridden by a more specific face association."
277277Faces to use for semantic token modifiers if
278278`lsp-semantic-tokens-apply-modifiers' is non-nil." )
279279
280+ (defconst lsp--semantic-tokens-font-lock-keywords
281+ '((lsp--semantic-tokens-fontify)))
282+
280283(defun lsp--semantic-tokens-capabilities ()
281284 `((semanticTokens
282285 . ((dynamicRegistration . t )
@@ -354,7 +357,7 @@ When non-nil, `lsp--semantic-tokens-cache' should adhere to the
354357following lsp-interface:
355358`(_SemanticTokensCache
356359 (:_documentVersion)
357- (:response :_region :_truncated ))'." )
360+ (:response :_region))'." )
358361
359362(defsubst lsp--semantic-tokens-putcache (k v )
360363 " Set key K of `lsp--semantic-tokens-cache' to V."
@@ -446,7 +449,7 @@ If FONTIFY-IMMEDIATELY is non-nil, fontification will be performed immediately
446449 (lsp--semantic-tokens-putcache :_documentVersion lsp--cur-version)
447450 (lsp--semantic-tokens-putcache :_region final-region)
448451 (funcall response-handler response)
449- (when ( or fontify-immediately ( plist-get lsp--semantic-tokens-cache :_truncated )) (font-lock-flush )))
452+ (when fontify-immediately (font-lock-flush )))
450453 :error-handler ; ; buffer is not captured in `error-handler' , it is in `callback'
451454 (let ((buf (current-buffer )))
452455 (lambda (&rest _ )
@@ -470,45 +473,19 @@ given workspace/language-server combination.
470473This cache should be flushed every time any modifier
471474configuration changes." )
472475
473- (defun lsp-semantic-tokens--fontify (old-fontify-region beg-orig end-orig &optional loudly )
474- " Apply fonts to retrieved semantic tokens.
475- OLD-FONTIFY-REGION is the underlying region fontification function,
476- e.g., `font-lock-fontify-region' .
477- BEG-ORIG and END-ORIG deliminate the requested fontification region and maybe
478- modified by OLD-FONTIFY-REGION.
479- LOUDLY will be forwarded to OLD-FONTIFY-REGION as-is."
476+ (defun lsp--semantic-tokens-fontify (end )
477+ " Apply semantic tokens from point to END."
480478 ; ; TODO: support multiple language servers per buffer?
481479 (let ((faces (seq-some #'lsp--workspace-semantic-tokens-faces lsp--buffer-workspaces))
482480 (modifier-faces
483481 (when lsp-semantic-tokens-apply-modifiers
484- (seq-some #'lsp--workspace-semantic-tokens-modifier-faces lsp--buffer-workspaces)))
485- old-bounds
486- beg end)
487- (cond
488- ((or (eq nil faces)
489- (eq nil lsp--semantic-tokens-cache)
490- (eq nil (plist-get lsp--semantic-tokens-cache :response )))
491- ; ; default to non-semantic highlighting until first response has arrived
492- (funcall old-fontify-region beg-orig end-orig loudly))
493- ((not (= lsp--cur-version (plist-get lsp--semantic-tokens-cache :_documentVersion )))
494- ; ; delay fontification until we have fresh tokens
495- '(jit-lock-bounds 0 . 0 ))
496- (t
497- (setq old-bounds (funcall old-fontify-region beg-orig end-orig loudly))
498- ; ; this is to prevent flickering when semantic token highlighting
499- ; ; is layered on top of, e.g., tree-sitter-hl, or clojure-mode's syntax highlighting.
500- (setq beg (min beg-orig (cadr old-bounds))
501- end (max end-orig (cddr old-bounds)))
502- ; ; if we're using the response to a ranged request, we'll only be able to fontify within
503- ; ; that range (and hence shouldn't clear any highlights outside of that range)
504- (let ((token-region (plist-get lsp--semantic-tokens-cache :_region )))
505- (if token-region
506- (progn
507- (lsp--semantic-tokens-putcache :_truncated (or (< beg (car token-region))
508- (> end (cdr token-region))))
509- (setq beg (max beg (car token-region)))
510- (setq end (min end (cdr token-region))))
511- (lsp--semantic-tokens-putcache :_truncated nil )))
482+ (seq-some #'lsp--workspace-semantic-tokens-modifier-faces lsp--buffer-workspaces))))
483+ (unless (or (eq nil faces)
484+ (eq nil lsp--semantic-tokens-cache)
485+ (eq nil (plist-get lsp--semantic-tokens-cache :response ))
486+ ; ; NOTE: perhaps we'd rather have stale highlights than temporarily dropping them altogether?
487+ (not (= lsp--cur-version (plist-get lsp--semantic-tokens-cache :_documentVersion ))))
488+
512489 (-let* ((inhibit-field-text-motion t )
513490 (data (lsp-get (plist-get lsp--semantic-tokens-cache :response ) :data ))
514491 (i0 0 )
@@ -517,44 +494,40 @@ LOUDLY will be forwarded to OLD-FONTIFY-REGION as-is."
517494 (line-delta)
518495 (column 0 )
519496 (face)
497+ (beg)
520498 (line-start-pos)
521499 (line-min)
522- (line-max-inclusive)
523500 (text-property-beg)
524501 (text-property-end))
525- (save-mark-and-excursion
526- (save-restriction
527- (widen )
528- (goto-char beg)
529- (goto-char (line-beginning-position ))
530- (setq line-min (line-number-at-pos ))
531- (with-silent-modifications
532- (goto-char end)
533- (goto-char (line-end-position ))
534- (setq line-max-inclusive (line-number-at-pos ))
535- (forward-line (- line-min line-max-inclusive))
536- (let ((skip-lines (- line-min current-line)))
537- (while (and (<= i0 i-max) (< (aref data i0) skip-lines))
538- (setq skip-lines (- skip-lines (aref data i0)))
539- (setq i0 (+ i0 5 )))
540- (setq current-line (- line-min skip-lines)))
541- (forward-line (- current-line line-min))
542- (setq line-start-pos (point ))
543- (cl-loop
544- for i from i0 to i-max by 5 do
545- (setq line-delta (aref data i))
546- (unless (= line-delta 0 )
547- (forward-line line-delta)
548- (setq line-start-pos (point ))
549- (setq column 0 )
550- (setq current-line (+ current-line line-delta)))
551- (setq column (+ column (aref data (1+ i))))
552- (setq face (aref faces (aref data (+ i 3 ))))
553- (setq text-property-beg (+ line-start-pos column))
554- (setq text-property-end
555- (min (if lsp-semantic-tokens-enable-multiline-token-support
556- (point-max ) (line-end-position ))
557- (+ text-property-beg (aref data (+ i 2 )))))
502+ ; ; TODO: do we need to save mark and excursion within function-type font-lock keywords?
503+ (save-restriction
504+ (widen )
505+ (setq line-min (line-number-at-pos ))
506+ (setq beg (point ))
507+ (with-silent-modifications
508+ (let ((skip-lines (- line-min current-line)))
509+ (while (and (<= i0 i-max) (< (aref data i0) skip-lines))
510+ (setq skip-lines (- skip-lines (aref data i0)))
511+ (setq i0 (+ i0 5 )))
512+ (setq current-line (- line-min skip-lines)))
513+ (forward-line (- current-line line-min))
514+ (setq line-start-pos (point ))
515+ (cl-loop
516+ for i from i0 to i-max by 5 do
517+ (setq line-delta (aref data i))
518+ (unless (= line-delta 0 )
519+ (forward-line line-delta)
520+ (setq line-start-pos (point ))
521+ (setq column 0 )
522+ (setq current-line (+ current-line line-delta)))
523+ (setq column (+ column (aref data (1+ i))))
524+ (setq face (aref faces (aref data (+ i 3 ))))
525+ (setq text-property-beg (+ line-start-pos column))
526+ (setq text-property-end
527+ (min (if lsp-semantic-tokens-enable-multiline-token-support
528+ (point-max ) (line-end-position ))
529+ (+ text-property-beg (aref data (+ i 2 )))))
530+ (unless (< text-property-beg beg)
558531 (when face
559532 (put-text-property text-property-beg text-property-end 'face face))
560533 ; ; Deal with modifiers. We cache common combinations of
@@ -569,9 +542,8 @@ LOUDLY will be forwarded to OLD-FONTIFY-REGION as-is."
569542 (push (aref modifier-faces j) faces-to-apply)))
570543 (puthash modifier-code faces-to-apply semantic-token-modifier-cache))
571544 (dolist (face faces-to-apply)
572- (add-face-text-property text-property-beg text-property-end face)))
573- when (> current-line line-max-inclusive) return nil )))))
574- `(jit-lock-bounds , beg . , end )))))
545+ (add-face-text-property text-property-beg text-property-end face))))
546+ when (>= (point ) end) return nil )))))))
575547
576548(defun lsp-semantic-tokens--request-update ()
577549 " Request semantic-tokens update."
@@ -670,28 +642,18 @@ Please adapt your config to prevent unnecessary mode reinitialization in the fut
670642(defun lsp--semantic-tokens-initialize-buffer ()
671643 " Initialize the buffer for semantic tokens.
672644IS-RANGE-PROVIDER is non-nil when server supports range requests."
673- (let* ((old-extend-region-functions font-lock-extend-region-functions)
674- ; ; make sure font-lock always fontifies entire lines (TODO: do we also have
675- ; ; to change some jit-lock-...-region functions/variables?)
676- (new-extend-region-functions
677- (if (memq 'font-lock-extend-region-wholelines old-extend-region-functions)
678- old-extend-region-functions
679- (cons 'font-lock-extend-region-wholelines old-extend-region-functions)))
680- (buffer (current-buffer )))
645+ (let* ((buffer (current-buffer )))
681646 (setq lsp--semantic-tokens-cache nil )
682- (setq font-lock-extend-region-functions new-extend-region-functions)
683- (add-function :around (local 'font-lock-fontify-region-function ) #'lsp-semantic-tokens--fontify )
684647 (add-hook 'lsp-on-change-hook #'lsp-semantic-tokens--request-update nil t )
685648 (lsp-semantic-tokens--request-update)
686649 (setq lsp--semantic-tokens-teardown
687650 (lambda ()
651+ (font-lock-remove-keywords nil lsp--semantic-tokens-font-lock-keywords)
688652 (setq lsp--semantic-tokens-pending-full-token-requests
689653 (--remove (eq buffer (car it)) lsp--semantic-tokens-pending-full-token-requests))
690- (setq font-lock-extend-region-functions old-extend-region-functions)
691654 (setq lsp--semantic-tokens-cache nil )
692- (remove-function (local 'font-lock-fontify-region-function )
693- #'lsp-semantic-tokens--fontify )
694- (remove-hook 'lsp-on-change-hook #'lsp-semantic-tokens--request-update t )))))
655+ (remove-hook 'lsp-on-change-hook #'lsp-semantic-tokens--request-update t )))
656+ (font-lock-add-keywords nil lsp--semantic-tokens-font-lock-keywords)))
695657
696658(defun lsp--semantic-tokens-build-face-map (identifiers faces category varname )
697659 " Build map of FACES for IDENTIFIERS using CATEGORY and VARNAME."
@@ -859,8 +821,8 @@ This is a debugging tool, and may incur significant performance penalties."
859821
860822 (defun lsp-log-full-response (response )
861823 (setq lsp-semantic-tokens--prev-response `(:request-type " full"
862- :response , response
863- :version , lsp--cur-version )))
824+ :response , response
825+ :version , lsp--cur-version )))
864826 (advice-add 'lsp--semantic-tokens-ingest-full-response :before 'lsp-log-full-response )
865827
866828 (defun lsp-log-range-response (response )
0 commit comments