diff --git a/README.md b/README.md index ac77e740c..2ee8ddb4f 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,10 @@ selected suggestion. > (Temporary limitation) > > Suggestions of user-defined words may not comprise symbols that are -> defined in some sections of the data division. +> defined in the communication, report, or screen section of the data +> division. Although user-defined words that occur in [configured +> copybooks](#editing-an-existing-project) are also suggested, +> preprocessor-related variables or phrases are not. ## Navigation features @@ -146,6 +149,13 @@ select  `Go to Definition` (or press F12). ![Go to Definition](./assets/superbol-goto-definition.gif) +> [!NOTE] +> (Temporary limitation) +> +> At the moment, definitions that belong to communication, report, or +> screen sections of the data division are ignored by the extension. +> They will be covered by the first stable release. + ### Peek Definition To only have a peek at where such a data item defined, you can @@ -169,9 +179,25 @@ every reference to this item. > [!NOTE] > (Temporary limitation) > -> At the moment, definitions that belong to *some* sections of the -> data division, and some references to data items, are ignored by the -> extension. They will be covered by the first stable release. +> In addition to limitations mentioned in [Go to +> Definition](#go-to-definition), references that occur in +> `EXEC`/`END-EXEC` blocks are also not taken into account yet. + +### Reference Information + +The extension shows inline reference information above definitons of +data items and elements of the procedure division. +The same limitations as for [Go to Definition](#go-to-definition) +apply. + +![Reference Information](./assets/superbol-reference-information.png) + +> [!TIP] +> +> This feature can be turned on or off by tuning the +> `"editor.codeLens"` configuration setting (you can type +> Ctrl+, and then `codelens` to change this +> setting). ### Hover to Show Copybooks @@ -191,6 +217,50 @@ replacement by a `REPLACE` directive in the same way. ![Hover over replacement](./assets/superbol-hover-replacement.gif) +## Editing + +### Rename Data Items, Sections, and Paragraphs + +You can rename any data item by pressing F2 while your +cursor is positioned on one of its references. The extension will +warn you if a reference to the renamed item appears in a copybook (in +which case the renaming of every reference is not performed). + +![Rename Symbol](./assets/superbol-rename-symbol.gif) + +![Rename Symbol in Copybook](./assets/superbol-rename-symbol-in-copybook.gif) + +Sections and paragraphs of the procedure division can also be renamed +in the same way. +The same limitations as for [Go to References](#go-to-references) +apply to this feature. + +## Exploring the Control-flow + +Navigating a graphical representation of a COBOL program's +control-flow proves invaluable when it comes to decipher its overall +logic. To do this, open the command palette (or type +Ctrl+Shift+P), and select `SuperBOL: +Show Control-flow` (you can also right click and select `Show +Control-flow` in the menu). You are then presented with a list of +portions of program to consider (either the entire program, or +individiual sections): select one element to see the corresponding +CFG. + +![CFG Explorer](./assets/superbol-cfg-explorer.gif) + +Various settings are provided to tune the rendering of CFGs. + +![CFG Explorer Collapse Fallthrough](./assets/superbol-cfg-explorer-collapse-fallthrough.gif) + +### CFG as an arc diagram + +A rendering of CFGs as arc diagrams is also available. In this +representation, named sections and paragraphs are laid out vertically, +and arcs show the direction of control-flow between them. + +![CFG Explorer as Arc Diagram](./assets/superbol-cfg-explorer-arc.gif) + ## Debugging In order to debug a COBOL program, you first need to run a *build @@ -248,9 +318,9 @@ whenever you start a debugging session, *e.g* with F5). Save the `tasks.json` as shown. Definitions for this task notably include a `for-debug` flag, that instructs the compiler to insert -debug annotations into generated executable files, as well as -`extra-args`, that can be edited to pass additional arguments to the -`cobc` compiler. +debug annotations into generated executable files (this effectively +passes flags `-ftraceall` and `-g` to `cobc`). The `extra-args` +setting can be edited to pass additional arguments to `cobc`. ![`tasks.json` for debug](./assets/superbol-tasks.json.png) @@ -259,8 +329,9 @@ debug annotations into generated executable files, as well as GnuCOBOL can instrument your programs so they can generate coverage information at runtime. To enable this feature, you can set the `for-coverage` setting to `true` in the `Superbol: build (debug)` task -in your `tasks.json` file (see [Section Customizing Build -Tasks](#customizing-build-tasks)). +in your `tasks.json` file (see [Customizing Build +Tasks](#customizing-build-tasks)). This flag instructs the extension +to pass the `--coverage` flag to the `cobc` compiler. ### Coverage Information @@ -275,11 +346,13 @@ Coverage data can be shown after the execution of a program that was compiled to generate this information terminates. SuperBOL will display coverage on a line-by-line basis, by highlighting the lines of your source code using colors that represent their coverage status. -To enable coverage highlighting, you can open the command palette -(or type Ctrl+Shift+P), and select -`SuperBOL: Show Coverage`. -You can also hide the highlighting with the command `SuperBOL: Hide Coverage`, -and update it after re-executing your program with `SuperBOL: Update Coverage`. +To enable coverage highlighting, you can open the command palette (or +type Ctrl+Shift+P), and select +`SuperBOL: Show Coverage`. You can also hide the highlighting with +the command `SuperBOL: Hide Coverage`, and update it after +re-executing your program with `SuperBOL: Update Coverage`. + +![Show Coverage](./assets/superbol-show-coverage.png) diff --git a/assets/superbol-cfg-explorer-arc.gif b/assets/superbol-cfg-explorer-arc.gif new file mode 100644 index 000000000..3db0d600d Binary files /dev/null and b/assets/superbol-cfg-explorer-arc.gif differ diff --git a/assets/superbol-cfg-explorer-collapse-fallthrough.gif b/assets/superbol-cfg-explorer-collapse-fallthrough.gif new file mode 100644 index 000000000..bed531de6 Binary files /dev/null and b/assets/superbol-cfg-explorer-collapse-fallthrough.gif differ diff --git a/assets/superbol-cfg-explorer.gif b/assets/superbol-cfg-explorer.gif new file mode 100644 index 000000000..779aa08e0 Binary files /dev/null and b/assets/superbol-cfg-explorer.gif differ diff --git a/assets/superbol-reference-information.png b/assets/superbol-reference-information.png new file mode 100644 index 000000000..7a73a2778 Binary files /dev/null and b/assets/superbol-reference-information.png differ diff --git a/assets/superbol-rename-symbol-in-copybook.gif b/assets/superbol-rename-symbol-in-copybook.gif new file mode 100644 index 000000000..595f503d7 Binary files /dev/null and b/assets/superbol-rename-symbol-in-copybook.gif differ diff --git a/assets/superbol-rename-symbol.gif b/assets/superbol-rename-symbol.gif new file mode 100644 index 000000000..4ac429532 Binary files /dev/null and b/assets/superbol-rename-symbol.gif differ diff --git a/assets/superbol-show-coverage.png b/assets/superbol-show-coverage.png new file mode 100644 index 000000000..89004f361 Binary files /dev/null and b/assets/superbol-show-coverage.png differ diff --git a/package.json b/package.json index 79e69f195..52a0e0a72 100644 --- a/package.json +++ b/package.json @@ -41,12 +41,12 @@ }, { "command": "superbol.cfg.open", - "title": "Show control-flow", + "title": "Show Control-flow", "category": "SuperBOL" }, { "command": "superbol.cfg.open.arc", - "title": "Show control-flow as an arc-diagram", + "title": "Show Control-flow as an Arc-diagram", "category": "SuperBOL" } ], diff --git a/src/lsp/cobol_lsp/lsp_request.ml b/src/lsp/cobol_lsp/lsp_request.ml index ee2ff8296..d4965e66b 100644 --- a/src/lsp/cobol_lsp/lsp_request.ml +++ b/src/lsp/cobol_lsp/lsp_request.ml @@ -753,34 +753,38 @@ let handle_codelens registry ({ textDocument; _ }: CodeLensParams.t) = (** { Rename } *) -let handle_rename ?(ignore_when_copybook=false) +let handle_rename + ?(abort_when_in_copybook = true) registry ({ textDocument; position; newName = newText; _ }: RenameParams.t) = + Option.value ~default:(WorkspaceEdit.create ()) @@ try_with_main_document_data registry textDocument ~f:begin fun ~doc checked_doc -> let rootdir = Lsp_project.(string_of_rootdir @@ rootdir doc.project) in - let locations = Option.value ~default:[] @@ + let locations = let context = ReferenceContext.create ~includeDeclaration:true in - let params = ReferenceParams.create - ~context ~position ~textDocument () in - lookup_references_in_doc ~rootdir params checked_doc in - let changes, is_copybook = - List.fold_left begin fun (map, is_copybook) ({ range; uri }: Location.t) -> + Option.value ~default:[] @@ + lookup_references_in_doc ~rootdir + (ReferenceParams.create () ~context ~position ~textDocument ) + checked_doc + in + let changes, in_copybook = + List.fold_left begin fun (map, in_copybook) Location.{ range; uri } -> URIMap.add_to_list uri (TextEdit.create ~newText ~range) map, - is_copybook || DocumentUri.compare uri textDocument.uri <> 0 - end (URIMap.empty, false) locations in - let changes = List.of_seq @@ URIMap.to_seq changes in - if is_copybook && ignore_when_copybook - then begin Lsp_io.notify_info - "Ignored renaming of a reference that occurs in a copybook"; - Some ( WorkspaceEdit.create () ) end - else - begin if is_copybook - then Lsp_io.notify_warn - "Proceeded to rename of a reference that occurs in a copybook"; - Some ( WorkspaceEdit.create ~changes () ) end + in_copybook || DocumentUri.compare uri textDocument.uri <> 0 + end (URIMap.empty, false) locations + in + if in_copybook && abort_when_in_copybook + then begin + Lsp_io.notify_error "Reference occurs in a copybook: not renaming"; + None + end else begin + if in_copybook then + Lsp_io.notify_warn "Renamed reference that occurs in a copybook"; + let changes = List.of_seq @@ URIMap.to_seq changes in + Some (WorkspaceEdit.create ~changes ()) + end end - |> Option.get (** {3 Generic handling} *) diff --git a/src/lsp/cobol_lsp/lsp_request.mli b/src/lsp/cobol_lsp/lsp_request.mli index 592cdef4a..72520bd14 100644 --- a/src/lsp/cobol_lsp/lsp_request.mli +++ b/src/lsp/cobol_lsp/lsp_request.mli @@ -46,7 +46,7 @@ module INTERNAL: sig -> Lsp.Types.CodeLensParams.t -> Lsp.Types.CodeLens.t list val rename - : ?ignore_when_copybook:bool + : ?abort_when_in_copybook:bool -> Lsp_server.t -> Lsp.Types.RenameParams.t -> Lsp.Types.WorkspaceEdit.t diff --git a/src/lsp/superbol_free_lib/vscode_extension.ml b/src/lsp/superbol_free_lib/vscode_extension.ml index a1b1bd5fa..6a94643ba 100644 --- a/src/lsp/superbol_free_lib/vscode_extension.ml +++ b/src/lsp/superbol_free_lib/vscode_extension.ml @@ -585,11 +585,11 @@ let contributes = ~category:"SuperBOL"; Manifest.command () ~command:"superbol.cfg.open" - ~title:"Show control-flow" + ~title:"Show Control-flow" ~category:"SuperBOL"; Manifest.command () ~command:"superbol.cfg.open.arc" - ~title:"Show control-flow as an arc-diagram" + ~title:"Show Control-flow as an Arc-diagram" ~category:"SuperBOL"; ] ~tomlValidation: [ diff --git a/src/vscode/superbol-vscode-platform/superbol_tasks.ml b/src/vscode/superbol-vscode-platform/superbol_tasks.ml index 1f5a206d4..a64d58361 100644 --- a/src/vscode/superbol-vscode-platform/superbol_tasks.ml +++ b/src/vscode/superbol-vscode-platform/superbol_tasks.ml @@ -134,7 +134,7 @@ let cobc_execution ?config attributes = config_string "cobol.source-format" ~config ~append:(fun f -> List.cons ("-fformat=" ^ f)) |> attr_bool_flag "for-debug" ~attributes - ~ok:(List.append ["-fsource-location"; "-ftraceall"; "-g"]) |> + ~ok:(List.append ["-ftraceall"; "-g"]) |> attr_bool_flag "for-coverage" ~attributes ~ok:(List.cons "--coverage") |> attr_bool_flag "executable" ~attributes diff --git a/test/lsp/lsp_rename.ml b/test/lsp/lsp_rename.ml index c20f31ca3..9d522a945 100644 --- a/test/lsp/lsp_rename.ml +++ b/test/lsp/lsp_rename.ml @@ -29,19 +29,23 @@ let pp_assoc_elem ppf ((uri, edits): DocumentUri.t * TextEdit.t list) = let count l = List.fold_left begin fun acc (_, t) -> acc + List.length t end 0 l -let rename_positions ?(ignore_when_copybook=false) ?(copybooks=[]) (doc, positions) : string -> unit = +let rename_positions ?(abort_when_in_copybook = false) ?(copybooks = []) + (doc, positions) : string -> unit = let { end_with_postproc; projdir }, server = make_lsp_project () in - let server = List.fold_left begin fun server (name, document) -> - add_cobol_doc server ~projdir name document - |> fst - end server copybooks in + let server = + List.fold_left begin fun server (name, document) -> + fst @@ add_cobol_doc server ~projdir name document + end server copybooks + in let server, prog = add_cobol_doc server ~projdir "prog.cob" doc in let rename_at_position ?key (position: Position.t) = - let params = RenameParams.create ~newName:"aNewName" ~position ~textDocument:prog () in + let params = + RenameParams.create ~newName:"aNewName" ~position ~textDocument:prog () + in Pretty.out "%a(line %d, character %d):\n" Fmt.(option ~none:nop (string ++ sp)) key position.line position.character; - match LSP.Request.rename ~ignore_when_copybook server params with + match LSP.Request.rename ~abort_when_in_copybook server params with | { changes = None; _ } -> Pretty.out "No renames@." | { changes = Some assoc; _ } -> @@ -181,7 +185,7 @@ let%expect_test "rename-with-a-ref-in-a-copybook" = {"params":{"message":"file://__rootdir__/lib.cpy appears to be a copybook","type":4},"method":"window/logMessage","jsonrpc":"2.0"} {"params":{"diagnostics":[],"uri":"file://__rootdir__/lib.cpy"},"method":"textDocument/publishDiagnostics","jsonrpc":"2.0"} {"params":{"diagnostics":[],"uri":"file://__rootdir__/prog.cob"},"method":"textDocument/publishDiagnostics","jsonrpc":"2.0"} - {"params":{"message":"Proceeded to rename of a reference that occurs in a copybook","type":2},"method":"window/showMessage","jsonrpc":"2.0"} + {"params":{"message":"Renamed reference that occurs in a copybook","type":2},"method":"window/showMessage","jsonrpc":"2.0"} (line 7, character 21): 2 rename entries: aNewName at __rootdir__/lib.cpy:2.11-2.21: @@ -202,7 +206,7 @@ let%expect_test "rename-with-a-ignored-ref-in-a-copybook" = ("lib.cpy", {cobol| 01 copied-var pic 9.|cobol}) ] in - let end_with_postproc = rename_positions ~ignore_when_copybook:true ~copybooks + let end_with_postproc = rename_positions ~abort_when_in_copybook:true ~copybooks @@ extract_position_markers {cobol| IDENTIFICATION DIVISION. PROGRAM-ID. prog. @@ -219,7 +223,7 @@ let%expect_test "rename-with-a-ignored-ref-in-a-copybook" = {"params":{"message":"file://__rootdir__/lib.cpy appears to be a copybook","type":4},"method":"window/logMessage","jsonrpc":"2.0"} {"params":{"diagnostics":[],"uri":"file://__rootdir__/lib.cpy"},"method":"textDocument/publishDiagnostics","jsonrpc":"2.0"} {"params":{"diagnostics":[],"uri":"file://__rootdir__/prog.cob"},"method":"textDocument/publishDiagnostics","jsonrpc":"2.0"} - {"params":{"message":"Ignored renaming of a reference that occurs in a copybook","type":3},"method":"window/showMessage","jsonrpc":"2.0"} + {"params":{"message":"Reference occurs in a copybook: not renaming","type":1},"method":"window/showMessage","jsonrpc":"2.0"} (line 7, character 21): No renames |}] @@ -347,4 +351,3 @@ let%expect_test "rename-procedure" = ---- ^^^ 6 PERFORM sec. 7 GO para. |}] -