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),
(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"
(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)