Skip to content

Commit

Permalink
Merge pull request #582 from ejgallego/selectionRange
Browse files Browse the repository at this point in the history
[lsp] Implement `textDocument/selectionRange`.
  • Loading branch information
ejgallego authored Oct 25, 2023
2 parents 78811e0 + ef9c87a commit 7d63e35
Show file tree
Hide file tree
Showing 11 changed files with 102 additions and 4 deletions.
6 changes: 6 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@
- New `pretac` field for preprocessing of goals with a tactic using
speculative execution, this is experimental for now (@amblafont,
@ejgallego, #573, helps with #558)
- Implement `textDocument/selectionRange` request, that will return
the range of the Coq sentence underlying the cursor. In VSCode,
this is triggered by the "Expand Selection" command. The
implementation is partial: we only take into account the first
position, and we only return a single range (Coq sentence) without
parents. (@ejgallego, #582)

# coq-lsp 0.1.7: Just-in-time
-----------------------------
Expand Down
30 changes: 27 additions & 3 deletions controller/lsp_core.ml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ module U = Yojson.Safe.Util

let field name dict = List.(assoc name dict)
let int_field name dict = U.to_int (field name dict)
let dict_field name dict = U.to_assoc (field name dict)
let list_field name dict = U.to_list (field name dict)
let string_field name dict = U.to_string (field name dict)
let ofield name dict = List.(assoc_opt name dict)
Expand Down Expand Up @@ -70,10 +69,18 @@ module Helpers = struct
let Lsp.Doc.VersionedTextDocumentIdentifier.{ uri; version } = document in
(uri, version)

let get_position params =
let pos = dict_field "position" params in
let lsp_position_to_tuple (pos : J.t) =
let pos = U.to_assoc pos in
let line, character = (int_field "line" pos, int_field "character" pos) in
(line, character)

let get_position params =
let pos = field "position" params in
lsp_position_to_tuple pos

let get_position_array params =
let pos_list = list_field "positions" params in
List.map lsp_position_to_tuple pos_list
end

(** LSP loop internal state: mainly the data needed to create a new document. In
Expand Down Expand Up @@ -276,8 +283,24 @@ let do_position_request ~postpone ~params ~handler =
Rq.Action.Data
(Request.Data.PosRequest { uri; handler; point; version; postpone })

(* For now we only pick the first item *)
let do_position_list_request ~postpone ~params ~handler =
let uri, version = Helpers.get_uri_oversion params in
let points = Helpers.get_position_array params in
match points with
| [] ->
let point, handler = ((0, 0), Request.empty) in
Rq.Action.Data
(Request.Data.PosRequest { uri; handler; point; version; postpone })
| point :: _ ->
Rq.Action.Data
(Request.Data.PosRequest { uri; handler; point; version; postpone })

let do_hover = do_position_request ~postpone:false ~handler:Rq_hover.hover

let do_selectionRange =
do_position_list_request ~postpone:false ~handler:Rq_selectionRange.request

(* We get the format from the params *)
let get_pp_format_from_config () =
match !Fleche.Config.v.pp_type with
Expand Down Expand Up @@ -423,6 +446,7 @@ let dispatch_request ~method_ ~params : Rq.Action.t =
| "textDocument/documentSymbol" -> do_symbols ~params
| "textDocument/hover" -> do_hover ~params
| "textDocument/codeLens" -> do_lens ~params
| "textDocument/selectionRange" -> do_selectionRange ~params
(* Proof-specific stuff *)
| "proof/goals" -> do_goals ~params
(* Proof-specific stuff *)
Expand Down
2 changes: 2 additions & 0 deletions controller/request.ml
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,5 @@ module Data = struct
| PosRequest { uri = _; point; version = _; postpone = _; handler } ->
handler ~point ~doc
end

let empty ~doc:_ ~point:_ = Ok (`List [])
2 changes: 2 additions & 0 deletions controller/request.mli
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,5 @@ module Data : sig
val dm_request : t -> Fleche.Theory.Request.request
val serve : doc:Fleche.Doc.t -> t -> R.t
end

val empty : position
2 changes: 1 addition & 1 deletion controller/rq_hover.ml
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ module type HoverProvider = sig
end

module Loc_info : HoverProvider = struct
let enabled = false
let enabled = true

let h ~contents:_ ~point:_ ~node =
match node with
Expand Down
1 change: 1 addition & 0 deletions controller/rq_init.ml
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ let do_initialize ~params =
] )
; ("definitionProvider", `Bool true)
; ("codeLensProvider", `Assoc [])
; ("selectionRangeProvider", `Bool true)
; ( "workspace"
, `Assoc
[ ( "workspaceFolders"
Expand Down
26 changes: 26 additions & 0 deletions controller/rq_selectionRange.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
(************************************************************************)
(* * The Coq Proof Assistant / The Coq Development Team *)
(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
(* <O___,, * (see CREDITS file for the list of authors) *)
(* \VV/ **************************************************************)
(* // * This file is distributed under the terms of the *)
(* * GNU Lesser General Public License Version 2.1 *)
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)

(************************************************************************)
(* Coq Language Server Protocol *)
(* Copyright 2019 MINES ParisTech -- Dual License LGPL 2.1 / GPL3+ *)
(* Copyright 2019-2023 Inria -- Dual License LGPL 2.1 / GPL3+ *)
(* Written by: Emilio J. Gallego Arias *)
(************************************************************************)

let request ~doc ~point =
let approx = Fleche.Info.Exact in
match Fleche.Info.LC.node ~doc ~point approx with
| None -> Ok `Null
| Some node ->
let range = Fleche.Doc.Node.range node in
let parent = None in
let answer = Lsp.Core.SelectionRange.({ range; parent } |> to_yojson) in
Ok (`List [ answer ])
18 changes: 18 additions & 0 deletions controller/rq_selectionRange.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
(************************************************************************)
(* * The Coq Proof Assistant / The Coq Development Team *)
(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
(* <O___,, * (see CREDITS file for the list of authors) *)
(* \VV/ **************************************************************)
(* // * This file is distributed under the terms of the *)
(* * GNU Lesser General Public License Version 2.1 *)
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)

(************************************************************************)
(* Coq Language Server Protocol *)
(* Copyright 2019 MINES ParisTech -- Dual License LGPL 2.1 / GPL3+ *)
(* Copyright 2019-2023 Inria -- Dual License LGPL 2.1 / GPL3+ *)
(* Written by: Emilio J. Gallego Arias *)
(************************************************************************)

val request : Request.position
1 change: 1 addition & 0 deletions etc/doc/PROTOCOL.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ If a feature doesn't appear here it usually means it is not planned in the short
| `textDocument/publishDiagnostics` | Yes | |
| `textDocument/diagnostic` | No | Planned, issue #49 |
| `textDocument/codeAction` | No | Planned |
| `textDocument/selectionRange` | Partial | We only take into account the first selection; no parents |
|---------------------------------------|---------|------------------------------------------------------------|
| `workspace/workspaceFolders` | Yes | Each folder should have a `_CoqProject` file at the root. |
| `workspace/didChangeWorkspaceFolders` | Yes | |
Expand Down
9 changes: 9 additions & 0 deletions lsp/core.ml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,15 @@ module CodeLens = struct
[@@deriving yojson]
end

(** SelectionRange *)
module SelectionRange = struct
type t =
{ range : Lang.Range.t
; parent : t option [@default None]
}
[@@deriving yojson]
end

(** Pull Diagnostics *)
module DocumentDiagnosticParams = struct
type t =
Expand Down
9 changes: 9 additions & 0 deletions lsp/core.mli
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ module CodeLens : sig
[@@deriving yojson]
end

(** SelectionRange *)
module SelectionRange : sig
type t =
{ range : Lang.Range.t
; parent : t option [@default None]
}
[@@deriving yojson]
end

(** Pull Diagnostics *)
module DocumentDiagnosticParams : sig
type t =
Expand Down

0 comments on commit 7d63e35

Please sign in to comment.