]> git.eshelyaron.com Git - dict.git/commitdiff
ENHANCED: provide exact buffer positions for cross references
authorEshel Yaron <me@eshelyaron.com>
Wed, 1 Feb 2023 16:28:09 +0000 (18:28 +0200)
committerEshel Yaron <me@eshelyaron.com>
Wed, 1 Feb 2023 16:28:09 +0000 (18:28 +0200)
* sweep.pl (reference_span/5): new predicate.
(sweep_predicate_references/2): use it to find exact character offset of
predicate references.
* sweeprolog.el (xref-backend-references): adapt accordingly.

sweep.pl
sweeprolog-tests.el
sweeprolog.el

index 0a02caf452ccc1a3ba1fcbdbb756a176319f5135..48a8c0dc0a23c13aeed2b5551c26da27109ddf56 100644 (file)
--- a/sweep.pl
+++ b/sweep.pl
@@ -316,20 +316,39 @@ sweep_module_description([M0|P], [M|[P]]) :- atom_string(M0, M).
 sweep_predicate_references(MFN, Refs) :-
     term_string(M:F/N, MFN),
     pi_head(F/N, H),
-    findall([B,Path|Line],
+    findall([B, Path, From, Len],
             (xref_called(Path0, H, B0, _, Line),
              pi_head(B1, B0),
              term_string(B1, B),
-             atom_string(Path0, Path)),
+             atom_string(Path0, Path),
+             reference_span(Path0, Line, H, From, Len)),
             Refs,
             Tail),
-    findall([B,Path|Line],
+    findall([B, Path, From, Len],
             (xref_called(Path0, M:H, B0, _, Line),
              pi_head(B1, B0),
              term_string(B1, B),
-             atom_string(Path0, Path)),
+             atom_string(Path0, Path),
+             reference_span(Path0, Line, H, From, Len)),
             Tail).
 
+:- dynamic current_reference_span/2.
+
+reference_span(Path, Line, Head, From, Len) :-
+    retractall(current_reference_span(_, _)),
+    setup_call_cleanup(prolog_open_source(Path, Stream),
+                       (   prolog_source:seek_to_line(Stream, Line),
+                           prolog_colourise_term(Stream, Path, reference_span_(Head), [])
+                       ),
+                       prolog_close_source(Stream)),
+    !,
+    current_reference_span(From, Len).
+
+reference_span_(Head, goal_term(_, Goal), Beg0, Len) :-
+    \+ \+ Head = Goal,
+    Beg is Beg0 + 1,
+    assertz(current_reference_span(Beg, Len)).
+reference_span_(_, _, _, _) :- true.
 
 sweep_predicate_location(MFN, [Path|Line]) :-
     term_string(M:F/N, MFN),
index b766af1eafdc3a9ce6507a5ca74f4f7afb2360d1..9dad8f45607d3d7660df8634f8b41a23af7030c4 100644 (file)
@@ -302,6 +302,28 @@ foo(Foo) :- bar.
     (should (string= (buffer-string)
                      "foo(Baz,Bar) :- spam(Bar,Baz)."))))
 
+(ert-deftest find-references ()
+  "Tests `sweeprolog-predicate-references'."
+  (let ((temp (make-temp-file "sweeprolog-test"
+                              nil
+                              ".pl"
+                              ":- module(test_sweep_find_references, [caller/0]).
+
+caller :- callee, baz, callee.
+caller :- baz, callee, baz.
+
+callee.
+
+baz.
+"
+                              )))
+    (find-file-literally temp)
+    (sweeprolog-mode)
+    (should (equal (sweeprolog-predicate-references "test_sweep_find_references:callee/0")
+                   (list (list "caller/0" temp 63 6)
+                         (list "caller/0" temp 76 6)
+                         (list "caller/0" temp 99 6))))))
+
 (ert-deftest forward-many-holes ()
   "Tests jumping over holes with `sweeprolog-forward-hole'."
   (let ((temp (make-temp-file "sweeprolog-test"
index 33655612dd55f321c882cebe712286d169950a3f..1f283d76f0517e461067d2cee24f17b158eab135 100644 (file)
@@ -4516,10 +4516,14 @@ accordingly."
 (cl-defmethod xref-backend-references ((_backend (eql sweeprolog)) mfn)
   (let ((refs (sweeprolog-predicate-references mfn)))
     (seq-map (lambda (loc)
-               (let ((by (car loc))
-                     (path (cadr loc))
-                     (line (or (cddr loc) 1)))
-                 (xref-make by (xref-make-file-location path line 0))))
+               (let* ((by   (nth 0 loc))
+                      (file (nth 1 loc))
+                      (beg  (nth 2 loc))
+                      (buf (find-file-noselect file t)))
+                 (xref-make (format "Call from %s at line %s" by
+                                    (with-current-buffer buf
+                                      (line-number-at-pos beg t)))
+                            (xref-make-buffer-location buf beg))))
              refs)))
 
 (cl-defmethod xref-backend-apropos ((_backend (eql sweeprolog)) pattern)