# Get line numbers from \`xref\_called/3\`

**URL:** <https://swi-prolog.discourse.group/t/get-line-numbers-from-xref-called-3/448>\
**Category:** Help!\
**Created:** [March 26, 2019, 5:02pm UTC](https://swi-prolog.discourse.group/t/get-line-numbers-from-xref-called-3/448 "2019-03-26T17:02:55Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![jamesnvc](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jamesnvc/32/14_2.png) [@jamesnvc](https://swi-prolog.discourse.group/u/jamesnvc)\
**Post date:** [March 26, 2019, 5:02pm UTC](https://swi-prolog.discourse.group/t/get-line-numbers-from-xref-called-3/448/1 "2019-03-26T17:02:55Z")

</div>

I’m working on making [a language server for Prolog](https://github.com/jamesnvc/prolog-lsp), for nice IDE-like integrations in Emacs & any other editors that can act as clients. While the `xref` library is proving very useful thus far, a challenge I’ve run in to is that `xref_called/3` doesn’t give the line number that the predicate was called from, just the containing predicate.

I’ve tried finding where the containing predicate was defined and was going to try searching from there for the sub-term, but that doesn’t always work, because the definition of the calling predicate could be broken up over multiple clauses. Is there a way to either get _all_ of the definitions of a predicate so I can do the walking myself or (hopefully) to get xref to report the line number?

Essentially, given code like below, how can I find that `other_term/1` is called on line 4?

```auto
1 caller(X) :- false.
2 caller(X) :- 
3 true,
4 other_term(X).
5 
6 other_term(A).

```

My current approach looks like [this](https://github.com/jamesnvc/prolog-lsp/blob/ae4719abea38fedd2c6164129d130cfc2da6224e/prolog/server.pl#L199), which just reports the first line of the caller, which is not great when there are a bunch of definitions for `caller`.

---

<div class="post-metadata">

**Author:** ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)\
**Post date:** [March 26, 2019, 7:49pm UTC](https://swi-prolog.discourse.group/t/get-line-numbers-from-xref-called-3/448/2 "2019-03-26T19:49:32Z")

</div>

Hi James,

I wrote an lsp server for SWI-Prolog (in a few days, so it is far from complete and not bug free) I have used it for weeks now with neovim, and it works fine. It is missing many features and has some bugs, but it can really jump start your work since it is a working server. You can use the code as you wish. [This](https://paste.fedoraproject.org/paste/DdxgQ4FOizH0IyWjK~G2eA) is the link.

It uses stdio for the JSON exchange, so you just have to configure the server within the editor.

Hope it helps.

```auto

```

---

<div class="post-metadata">

**Author:** ![jamesnvc](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jamesnvc/32/14_2.png) [@jamesnvc](https://swi-prolog.discourse.group/u/jamesnvc)\
**Post date:** [March 26, 2019, 7:53pm UTC](https://swi-prolog.discourse.group/t/get-line-numbers-from-xref-called-3/448/3 "2019-03-26T19:53:07Z")

</div>

Oh, thanks a lot! Mine seems to be working well enough in Emacs now, but I’ll have a look over how you’re doing things & see which features you have that I don’t 😁.

---

<div class="post-metadata">

**Author:** ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)\
**Post date:** [March 26, 2019, 7:56pm UTC](https://swi-prolog.discourse.group/t/get-line-numbers-from-xref-called-3/448/4 "2019-03-26T19:56:35Z")

</div>

BTW, I use the SWI-Prolog compiler itself to give all the messages/errors/etc. See `load_source_code/2`.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [March 26, 2019, 7:58pm UTC](https://swi-prolog.discourse.group/t/get-line-numbers-from-xref-called-3/448/5 "2019-03-26T19:58:38Z")

</div>

Great initiative! As is, I’m afraid this isn’t supported. A lot of the prerequisites are in the prolog\_xref, prolog\_clause and prolog\_codewalk libraries. A ready made solution is lacking though.

We could consider to extend prolog\_xref to keep track of all call locations using the line number of the clause. The proloag\_clause primitives can than be used to find the real location. I’m into too many projects to provide this shortly, but I’m happy to give some pointers and handle pull requests. Call locations are indeed quite nice to have …

---

<div class="post-metadata">

**Author:** ![jamesnvc](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jamesnvc/32/14_2.png) [@jamesnvc](https://swi-prolog.discourse.group/u/jamesnvc)\
**Post date:** [March 27, 2019, 9:27pm UTC](https://swi-prolog.discourse.group/t/get-line-numbers-from-xref-called-3/448/6 "2019-03-27T21:27:57Z")

</div>

I created a PR [here](https://github.com/SWI-Prolog/swipl-devel/pull/451). This gives information about the line the calling clause begins on; not the exact line number of the calling, but it works for my purposes.

I think the complete solution will involve passing subterm positions in to the various processing goals & move down through that structure in sync with moving through the term…as mentioned in the PR, I was kind of concerned that would be changing a lot of code though.

---

<div class="post-metadata">

**Author:** ![jamesnvc](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jamesnvc/32/14_2.png) [@jamesnvc](https://swi-prolog.discourse.group/u/jamesnvc)\
**Post date:** [March 27, 2019, 11:38pm UTC](https://swi-prolog.discourse.group/t/get-line-numbers-from-xref-called-3/448/7 "2019-03-27T23:38:54Z")

</div>

If I can plug my own thing too, even the minimal LSP thing I have working now was actually pretty helpful for making the change! I was able to have the cursor on the call to `xref_called/4` in my code, press `M-.`, and get taken right to its definition in `prolog_xref.pl` 😁 Also very helpful for jumping around in the file itself, being able to get live docs & see the callers, etc.

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [March 28, 2019, 2:56am UTC](https://swi-prolog.discourse.group/t/get-line-numbers-from-xref-called-3/448/8 "2019-03-28T02:56:44Z")

</div>

Sicstus Prolog has a “layout” option for its reads – there’s an example here: [https://sicstus.sics.se/sicstus/docs/latest3/html/sicstus/Term-I\_002fO.html](https://sicstus.sics.se/sicstus/docs/latest3/html/sicstus/Term-I_002fO.html)

Quintus Prolog has a subterm\_positions option – see page 1255 of [https://quintus.sics.se/isl/quintus/pdf/quintus.pdf](https://quintus.sics.se/isl/quintus/pdf/quintus.pdf)

And I think that IBM Prolog had something similar, but I can’t find an online copy of the manual.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [March 28, 2019, 7:51am UTC](https://swi-prolog.discourse.group/t/get-line-numbers-from-xref-called-3/448/9 "2019-03-28T07:51:18Z")

</div>

Great! I’ll have a look at the PR. Using the start line should be enough. The logic in library(prolog\_clause) can be reused to find the real line and character position on demand. That probably requires a bit of additional hacking as this library relies on an actual clause, but most of the stuff should be there. Doing it on demand probably requires less changes and reduces the resources needed for the cross-referencing step.

@peter.ludemann SWI-Prolog has the Quintus `subterm_positions` in `read_term/3`, although with some extensions over the years. How else would the source level debugger work …
