Skip to content

Commit

Permalink
Merge remote-tracking branch 'dk/master' into db
Browse files Browse the repository at this point in the history
  • Loading branch information
fblanqui committed Jun 24, 2024
2 parents f58c24f + 2cb70da commit 4b4bcf7
Show file tree
Hide file tree
Showing 11 changed files with 130 additions and 73 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
strategy:
fail-fast: false
matrix:
ocaml-version: [5.1.1, 5.0.0, 4.14.1, 4.13.1, 4.12.1, 4.11.2, 4.10.2, 4.09.1, 4.08.1]
ocaml-version: [5.2.0, 5.1.1, 5.0.0, 4.14.1, 4.13.1, 4.12.1, 4.11.2, 4.10.2, 4.09.1, 4.08.1]
runs-on: ubuntu-latest
steps:
- name: checking out lambdapi repo ...
Expand Down Expand Up @@ -48,12 +48,12 @@ jobs:
- name: generate-vscode-extension
run: |
npm install -g @types/vscode
npm install -g vsce
npm install -g @vscode/vsce
make build-vscode-extension
make publish-vscode-extension
env:
PAT: ${{secrets.VSCODE_PAT}}
- name: publish vscode extension
PAT: ${{ secrets.VSCODE_PAT }}
- name: upload vscode extension
uses: actions/upload-artifact@v4
with:
name: assets-for-download
Expand Down
15 changes: 15 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -182,12 +182,27 @@ JQ = $(shell which jq)
ifneq ($(VSCE),)
ifneq ($(JQ),)
EXT = $(shell vsce show --json deducteam.lambdapi 2>/dev/null | jq '.versions[0]' | jq '.version')

.PHONY: publish-vscode-extension
publish-vscode-extension:
ifeq ($(EXT), $(shell cat editors/vscode/package.json | jq '.version'))
echo "extension already exists. Skip"
else
ifeq ($(PAT),)
# Note, when pushing code from a fork of the Lambdapi repository, PAT secret is not "reachable".
# The extension is only published when merge occurs.
echo "The \"PAT\" secret is not set. Please check a PAT exists with permissions to publish to Vscode market"
else
ifeq ("$(GITHUB_REF_NAME)", "master")
# The extension is only published when code is pushed to master to avoid publishing from feature branches
cd editors/vscode && vsce publish -p ${PAT}
else
echo "Env Variable \"GITHUB_REF_NAME\" is set to \"$(GITHUB_REF_NAME)\"."
echo "Extension will only be published when pushing to master."
echo "If used manualy, please set Variable \"GITHUB_REF_NAME\" to \"master\" to force publishing the extension"
endif
endif
endif

endif
endif
7 changes: 5 additions & 2 deletions editors/vscode/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/),
and this project adheres to [Semantic Versioning](https://semver.org/).

## [Unreleased]
## [0.2.2]
- code refactoring of the client for maintenability.
- fix the bug that causes the proof navigation to malfunction when the Goals panel is closed by the user. Now the panel is recreated whenever needed.
- fix the bug that causes the proof navigation to malfunction when the `Goals` panel is closed by the user. Now the panel is recreated whenever needed. If focus is taken away frol the `Goals` panel, focus is given back to it when user starts navigating proofs again.
- fix bug related to navigating sub-goals : navigating next subgoal stops before `{` instead of after it so that next subgoal is correctly shown in the `Goals` panel.
- change navigation with ``navigate until cursor`` : Navigation includes the command if the cursor is whithin its range instead of the line above.
- first command is no more systematically navigated. If the current command is the first one, navigating the previous command results in no command being navigated.

## [0.1.2] - 2020-12-10
- use vscode configuration for lambdapi.path to call the lambdapi LSP server
Expand Down
4 changes: 2 additions & 2 deletions editors/vscode/RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ TODO list for a new release on the VSCode Marketplace

The github DICD pipeline detects the existance of a new version of the Lambdapi extension for Vscode based on the `version` field in the `editors/vscode/package.json` file and publishes it on the Marketplace.

Please note that a valid Azure Personal Access Token (PAT) is required for this operation. This PAT must be saved in the `PAT` environment variable as described [here](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions).
Please note that a valid Azure Personal Access Token (PAT) is required for this operation. This PAT must be saved in the `VSCODE_PAT` environment variable as described [here](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions).

If the pipeline fails at publishing the extension, it may be due to the PAT being expired.
Please generate a new one on [Azure](https://dev.azure.com/lambdapi/) and update the `PAT` env variable value as described in the link above.
Please generate a new one on [Azure](https://dev.azure.com/lambdapi/) and update the `VSCODE_PAT` env variable value as described in the link above.

**manual release**

Expand Down
2 changes: 1 addition & 1 deletion editors/vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"François Lefoulon <[email protected]>",
"Ashish Barnawal <[email protected]>"
],
"version": "0.2.1",
"version": "0.2.2",
"publisher": "Deducteam",
"engines": {
"vscode": "^1.82.0"
Expand Down
58 changes: 51 additions & 7 deletions editors/vscode/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,34 @@ function checkProofBackward(context: ExtensionContext) {

function checkProofUntilCursor(context: ExtensionContext) {

function previousCaracterSkippingSpaces(document: TextDocument, currentPos: Position) {
const index = document.offsetAt(currentPos)
const slicedText = document.getText().slice(0, index);

// Match the last letter before a series of spaces and tabulations
const regex =/(\S)(?=[ \t]*$)/;

// Find the last letter before spaces
let myMatch = slicedText.match(regex);

// return the last letter if found
return myMatch ? myMatch[1] : null;
}

function nextCaracterSkippingSpaces(document: TextDocument, currentPos: Position) {
const index = document.offsetAt(currentPos)
const slicedText = document.getText().slice(index);

// Match the last letter after spaces and tabulations
const regex = /(\S)(?=[ \t]*$)/;

// Find the last letter after spaces
let myMatch = slicedText.split(/\r?\n/)[0].match(regex);

// return the last letter if found
return myMatch ? myMatch[0] : null;
}

//Checking workspace
const openEditor: TextEditor | undefined = window.activeTextEditor;
if (!openEditor)
Expand All @@ -178,13 +206,16 @@ function checkProofUntilCursor(context: ExtensionContext) {

//The current position of the cursor
let cursorPosition: Position = openEditor.selection.active;
if (proofState.line == cursorPosition.line)
return;

//To simplify the code, proof states are always at the beggining of the highlighted line
//So must be the cursor position since it is the new proof state
if (cursorPosition.character != 0)
cursorPosition = new Position(cursorPosition.line, 0);
const cursorIsAtEndOfCommand = previousCaracterSkippingSpaces(openEditor.document, cursorPosition) === ";";
const commandExistsAfterCursorinSameLine = nextCaracterSkippingSpaces(openEditor.document, cursorPosition) != null;

// If the cursor is at the begining or in the middle of a command or there are more commands in the same line,
// then do not move the green zone further.
// Else, stop at the current position
if(!cursorIsAtEndOfCommand || commandExistsAfterCursorinSameLine) {
cursorPosition = stepCommand(openEditor.document, cursorPosition, true);
}

context.workspaceState.update('proofState', cursorPosition); //proof state is set to the cursor position

Expand Down Expand Up @@ -509,7 +540,11 @@ function stepCommand(document: TextDocument, currentPos: Position, forward: bool
const termRegex = new RegExp(terminators.join("|"), 'gi');

let termPositions = [...document.getText().matchAll(termRegex)]
.map(rm => rm.index ? rm.index + rm[0].length : undefined)
.map(rm => {
if (rm[0] === ";") {
return rm.index ? rm.index + rm[0].length : undefined
}
else return rm.index ? rm.index : undefined })
.filter((x): x is number => x !== undefined) // remove undefined
.map(x => document.positionAt(x));

Expand Down Expand Up @@ -664,6 +699,15 @@ function sendGoalsRequest(position: Position, panel: WebviewPanel, docUri: Uri,
let cursor = { textDocument: doc, position: position };
const req = new RequestType<ParamsGoals, GoalResp, void>("proof/goals");
client.sendRequest(req, cursor).then((goals) => {
// If uri is not a lambdapi/dedukti file, do nothing
if(goals.goals == null){
return;
}
// Take focus back if the goal panel lost it.
window.showErrorMessage("Going through Goals");
if(!panel.active) {
panel.reveal(2, false);
}

updateTerminalText(goals.logs);

Expand Down
42 changes: 18 additions & 24 deletions src/lsp/lp_doc.ml
Original file line number Diff line number Diff line change
Expand Up @@ -164,35 +164,29 @@ let dummy_loc =

let check_text ~doc =
let uri, version = doc.uri, doc.version in
let cmds, error = Pure.parse_text ~fname:uri doc.text in
let root =
match doc.root with
| Some(ss) -> ss
| Some ss -> ss
| None ->
raise(Error.fatal_no_pos "Root state is missing
probably because new_doc has raised exception")
raise(Error.fatal_no_pos "Root state is missing probably because \
new_doc raised an exception")
in
try
let cmds =
let (cmds, root) = Pure.parse_text root ~fname:uri doc.text in
(* One shot state update after parsing. *)
doc.root <- Some(root); doc.final <- Some(root); cmds
in

(* compute rangemap *)
let map = Pure.rangemap cmds in

let nodes, final, diag, logs =
List.fold_left (process_cmd uri) ([],root,[],[]) cmds in
let logs = List.rev logs in
let doc = { doc with nodes; final=Some(final); map; logs } in
doc,
LSP.mk_diagnostics ~uri ~version @@
let nodes, final, diags, logs =
List.fold_left (process_cmd uri) ([],root,[],[]) cmds in
let logs = List.rev logs
and diags = (* filter out diagnostics with no position *)
List.fold_left (fun acc (pos,lvl,msg,goal) ->
match pos with
| None -> acc
| Some pos -> (pos,lvl,msg,goal) :: acc
) [] diag
with
| Pure.Parse_error(loc, msg) ->
let logs = [((1, msg), Some loc)] in
{doc with logs}, mk_error ~doc loc msg
) [] diags
in
let logs, diags =
match error with
| None -> logs, diags
| Some(pos,msg) -> logs @ [((1, msg), Some pos)], diags @ [pos,1,msg,None]
in
let map = Pure.rangemap cmds in
let doc = { doc with nodes; final=Some(final); map; logs } in
doc, LSP.mk_diagnostics ~uri ~version diags
13 changes: 10 additions & 3 deletions src/lsp/lp_lsp.ml
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ let get_node_at_pos doc line pos =
let rec get_goals ~doc ~line ~pos =
let node = get_node_at_pos doc line pos in
let goals = match node with
| None -> None
| None -> Some([], None)
| Some n ->
closest_before (line+1, pos) n.goals in
match goals with
Expand Down Expand Up @@ -294,7 +294,7 @@ let get_logs ~doc ~line ~pos : string =
(fun ((_,msg),loc) ->
match loc with
| Some Pos.{start_line; start_col; _}
when compare (start_line,start_col) end_limit <= 0 -> Some msg
when compare (start_line,start_col) end_limit < 0 -> Some msg
| _ -> None)
doc.Lp_doc.logs
in
Expand Down Expand Up @@ -526,7 +526,14 @@ let process_input ofmt (com : J.t) =
| exn ->
let bt = Printexc.get_backtrace () in
LIO.log_error "[BT]" bt;
LIO.log_error "process_input" (Printexc.to_string exn)
LIO.log_error "process_input" (Printexc.to_string exn);
(*Send an "empty" answer with Null goals when exception occurs*)
let id = oint_field "id" (U.to_assoc com) in
let goals = None in
let logs = "" in
let result = LSP.json_of_goals goals ~logs in
let msg = LSP.mk_reply ~id ~result in
LIO.send_json ofmt msg

let main std log_file =

Expand Down
5 changes: 4 additions & 1 deletion src/parsing/lpLexer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,10 @@ and comment next i lb =
(** [token buf] is a lexing function on buffer [buf] that can be passed to
a parser. *)
let token : lexbuf -> unit -> token * Lexing.position * Lexing.position =
with_tokenizer token
fun lb () -> try with_tokenizer token lb () with
| Sedlexing.MalFormed -> fail lb "Not Utf8 encoded file"
| Sedlexing.InvalidCodepoint k ->
fail lb ("Invalid Utf8 code point " ^ string_of_int k)

let token =
let r = ref (EOF, Lexing.dummy_pos, Lexing.dummy_pos) in fun lb () ->
Expand Down
35 changes: 14 additions & 21 deletions src/pure/pure.ml
Original file line number Diff line number Diff line change
Expand Up @@ -58,30 +58,23 @@ end
type state = Time.t * Sig_state.t

(** Exception raised by [parse_text] on error. *)
exception Parse_error of Pos.pos * string

let parse_text : state -> fname:string -> string -> Command.t list * state =
fun (t,st) ~fname s ->
let dk_syntax = Filename.check_suffix fname dk_src_extension in
let parse_text :
fname:string -> string -> Command.t list * (Pos.pos * string) option =
fun ~fname s ->
let parse_string =
if Filename.check_suffix fname dk_src_extension then
Parser.Dk.parse_string
else Parser.parse_string
in
let cmds = Stdlib.ref [] in
try
LibMeta.reset_meta_counter();
Time.restore t;
let ast =
let strm =
if dk_syntax then Parser.Dk.parse_string fname s
else Parser.parse_string fname s
in
(* NOTE this processing could be avoided with a parser for a list of
commands. Such a parser is not trivially done. *)
let cmds = Stdlib.ref [] in
Stream.iter (fun c -> Stdlib.(cmds := c :: !cmds)) strm;
List.rev Stdlib.(!cmds)
in
(ast, (Time.save (), st))
Stream.iter (fun c -> Stdlib.(cmds := c :: !cmds)) (parse_string fname s);
List.rev Stdlib.(!cmds), None
with
| Fatal(Some(Some(pos)), msg) -> raise (Parse_error(pos, msg))
| Fatal(Some(None) , _ ) -> assert false (* Should not produce. *)
| Fatal(None , _ ) -> assert false (* Should not produce. *)
| Fatal(Some(Some(pos)), msg) -> List.rev Stdlib.(!cmds), Some(pos, msg)
| Fatal(Some(None) , _ ) -> assert false
| Fatal(None , _ ) -> assert false

type proof_finalizer = Sig_state.t -> Proof.proof_state -> Sig_state.t

Expand Down
14 changes: 6 additions & 8 deletions src/pure/pure.mli
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,12 @@ type state
(** Representation of the state when in a proof. *)
type proof_state

(** Exception raised by [parse_text]. *)
exception Parse_error of Pos.pos * string

(** [parse_text st ~fname contents] runs the parser on the string [contents]
as if it were a file named [fname]. The action takes place in the state
[st], and an updated state is returned. The function may raise
[Parse_error]. *)
val parse_text : state -> fname:string -> string -> Command.t list * state
(** [parse_text ~fname contents] runs the parser on the string [contents] as
if it were a file named [fname]. It returns the list of commands it could
parse and, either [None] if it could parse all commands, or some position
and error message otherwise. *)
val parse_text :
fname:string -> string -> Command.t list * (Pos.pos * string) option

(** A goal is given by a list of assumptions and a conclusion. Each assumption
has a name and a type. *)
Expand Down

0 comments on commit 4b4bcf7

Please sign in to comment.