diff --git a/CHANGELOG.md b/CHANGELOG.md index fa551ea5..fff26196 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,10 @@ ## [0.1.4] Next release ### Added +- Support for Symbol Renaming command [#351](https://github.com/OCamlPro/superbol-studio-oss/pull/351) - Show documentation comments on hover information [#350](https://github.com/OCamlPro/superbol-studio-oss/pull/350) - Completion for more grammar constructs [#322](https://github.com/OCamlPro/superbol-studio-oss/pull/322) -- Support for LSP request `textDocument/codeLens` [#349](https://github.com/OCamlPro/superbol-studio-oss/pull/349) +- Support for CodeLens [#349](https://github.com/OCamlPro/superbol-studio-oss/pull/349) - Show display example of `NUMERIC-EDITED` data on hover [#337](https://github.com/OCamlPro/superbol-studio-oss/pull/337) - Support for dump and listing files, along with a task attribute for outputting the latter [#347](https://github.com/OCamlPro/superbol-studio-oss/pull/347) - Improved information shown on completion [#336](https://github.com/OCamlPro/superbol-studio-oss/pull/336) diff --git a/src/lsp/cobol_lsp/lsp_capabilities.ml b/src/lsp/cobol_lsp/lsp_capabilities.ml index 933d8ebf..2e851f2b 100644 --- a/src/lsp/cobol_lsp/lsp_capabilities.ml +++ b/src/lsp/cobol_lsp/lsp_capabilities.ml @@ -46,8 +46,7 @@ let reply (_: ClientCapabilities.t) = in ServerCapabilities.create_workspace () ~workspaceFolders - in - let codeLensProvider = CodeLensOptions.create () in + and codeLensProvider = CodeLensOptions.create () in ServerCapabilities.create () ~textDocumentSync:(`TextDocumentSyncOptions sync) ~definitionProvider:(`Bool true) @@ -61,3 +60,4 @@ let reply (_: ClientCapabilities.t) = ~workspace ~documentSymbolProvider:(`Bool true) ~codeLensProvider + ~renameProvider:(`Bool true) diff --git a/src/lsp/cobol_lsp/lsp_imports.ml b/src/lsp/cobol_lsp/lsp_imports.ml index 591b4fe2..1eea715c 100644 --- a/src/lsp/cobol_lsp/lsp_imports.ml +++ b/src/lsp/cobol_lsp/lsp_imports.ml @@ -15,4 +15,10 @@ module CUs = Cobol_unit.Collections.SET module CUMap = Cobol_unit.Collections.MAP -module URIMap = Map.Make (Lsp.Uri) +module URIMap = struct + include Map.Make (Lsp.Uri) + + let add_to_list x data m = + let add = function None -> Some [data] | Some l -> Some (data :: l) in + update x add m +end diff --git a/src/lsp/cobol_lsp/lsp_request.ml b/src/lsp/cobol_lsp/lsp_request.ml index 8875feb8..05ff4c06 100644 --- a/src/lsp/cobol_lsp/lsp_request.ml +++ b/src/lsp/cobol_lsp/lsp_request.ml @@ -605,7 +605,7 @@ let handle_folding_range registry (params: FoldingRangeParams.t) = let handle_document_symbol registry (params: DocumentSymbolParams.t) = try_with_main_document_data registry params.textDocument - ~f:begin fun ~doc { ptree; _ }-> + ~f:begin fun ~doc { ptree; _ } -> let uri = Lsp.Text_document.documentUri doc.textdoc in let symbols = Lsp_document_symbol.from_ptree_at ~uri ptree in Some (`DocumentSymbol symbols) @@ -702,6 +702,38 @@ let handle_codelens registry ({ textDocument; _ }: CodeLensParams.t) = end |> Option.value ~default:[] +(** { Rename } *) + +let handle_rename ?(ignore_when_copybook=false) + registry + ({ textDocument; position; newName = newText; _ }: RenameParams.t) = + 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 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) -> + 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 + end + |> Option.get + + (** {3 Generic handling} *) let shutdown: state -> unit = function @@ -747,17 +779,18 @@ let on_request Ok (handle_folding_range registry params, state) | Shutdown -> Ok (handle_shutdown registry, ShuttingDown) - | DocumentSymbol (* DocumentSymbolParams.t.t *) params -> + | DocumentSymbol params -> Ok (handle_document_symbol registry params, state) | TextDocumentCodeLens (* CodeLensParams.t.t *) params -> Ok (handle_codelens registry params, state) + | TextDocumentRename params -> + Ok (handle_rename registry params, state) | TextDocumentDeclaration (* TextDocumentPositionParams.t.t *) _ | TextDocumentTypeDefinition (* TypeDefinitionParams.t.t *) _ | TextDocumentImplementation (* ImplementationParams.t.t *) _ | TextDocumentCodeLensResolve (* CodeLens.t.t *) _ | TextDocumentPrepareCallHierarchy (* CallHierarchyPrepareParams.t.t *) _ | TextDocumentPrepareRename (* PrepareRenameParams.t.t *) _ - | TextDocumentRename (* RenameParams.t.t *) _ | TextDocumentLink (* DocumentLinkParams.t.t *) _ | TextDocumentLinkResolve (* DocumentLink.t.t *) _ | TextDocumentMoniker (* MonikerParams.t.t *) _ @@ -825,4 +858,5 @@ module INTERNAL = struct let codelens = handle_codelens let document_symbol = handle_document_symbol let formatting = handle_formatting + let rename = handle_rename end diff --git a/src/lsp/cobol_lsp/lsp_request.mli b/src/lsp/cobol_lsp/lsp_request.mli index 026acb85..592cdef4 100644 --- a/src/lsp/cobol_lsp/lsp_request.mli +++ b/src/lsp/cobol_lsp/lsp_request.mli @@ -45,4 +45,9 @@ module INTERNAL: sig : Lsp_server.t -> Lsp.Types.CodeLensParams.t -> Lsp.Types.CodeLens.t list + val rename + : ?ignore_when_copybook:bool + -> Lsp_server.t + -> Lsp.Types.RenameParams.t + -> Lsp.Types.WorkspaceEdit.t end diff --git a/src/lsp/cobol_typeck/typeck_outputs.ml b/src/lsp/cobol_typeck/typeck_outputs.ml index ef55f7b8..c26adcf9 100644 --- a/src/lsp/cobol_typeck/typeck_outputs.ml +++ b/src/lsp/cobol_typeck/typeck_outputs.ml @@ -20,6 +20,12 @@ type references_in_unit = data_refs: qualrefmap; proc_refs: qualrefmap; (* TODO: const_refs, prog_refs?, others... *) + (* TODO atm data_refs and proc_refs contains BOTH direct references and indirect references + e.g.: DISPLAY B IN A result in + - a direct reference to B + - a indirect reference to A + In the future we may need/want to split those 2 kind of references + *) } type references_in_group = references_in_unit Cobol_unit.Collections.MAP.t diff --git a/src/lsp/cobol_typeck/typeck_procedure.ml b/src/lsp/cobol_typeck/typeck_procedure.ml index fac082df..e201afc6 100644 --- a/src/lsp/cobol_typeck/typeck_procedure.ml +++ b/src/lsp/cobol_typeck/typeck_procedure.ml @@ -187,7 +187,7 @@ let references ~(data_definitions: Cobol_unit.Types.data_definitions) procedure method! fold_qualname qn acc = (* TODO: data_name' instead *) let loc = baseloc_of_qualname qn in - Visitor.skip_children @@ + Visitor.do_children @@ (* match Qualmap.find qn data_definitions.data_items.named with *) (* | Data_field { def; _ } -> *) (* { acc with *) @@ -226,18 +226,28 @@ let references ~(data_definitions: Cobol_unit.Types.data_definitions) procedure Cobol_ptree.Proc_division_visitor.fold_paragraph' v paragraph acc - method! fold_procedure_name' ({ loc; _ } as qn) + method! fold_procedure_name' qn ({ current_section = in_section; _ } as acc) = - Visitor.skip_children @@ - match Cobol_unit.Procedure.find ~&qn ?in_section procedure with - | block -> + let register ?in_section qn acc = + let loc = baseloc_of_qualname ~&qn in + match Cobol_unit.Procedure.find ~&qn ?in_section procedure with + | block -> { acc with refs = Typeck_outputs.register_procedure_ref ~loc block acc.refs } - | exception Not_found -> + | exception Not_found -> error acc @@ Unknown_proc_name qn - | exception Qualmap.Ambiguous (lazy matching_qualnames) -> + | exception Qualmap.Ambiguous (lazy matching_qualnames) -> error acc @@ Ambiguous_proc_name { given_qualname = qn; matching_qualnames } + in + let acc = register ?in_section qn acc in + let acc = match ~&qn with + | Name _ -> acc + | Qual (_, section_qn) -> + let loc = baseloc_of_qualname section_qn in + register (section_qn &@ loc) acc + in + Visitor.skip_children acc end in diff --git a/test/lsp/lsp_codelens.ml b/test/lsp/lsp_codelens.ml index ebf6c865..7385c66b 100644 --- a/test/lsp/lsp_codelens.ml +++ b/test/lsp/lsp_codelens.ml @@ -47,6 +47,7 @@ let%expect_test "codelens" = 88 YYcond value "a". PROCEDURE DIVISION. MOVE aa TO aA. + DISPLAY BB IN AA. STOP RUN. |cobol} in end_with_postproc [%expect.output]; @@ -60,7 +61,7 @@ let%expect_test "codelens" = ---- ^ 7 02 BB PIC X. 8 02 BBprime REDEFINES BB PIC 9. - 3 references + 4 references __rootdir__/prog.cob:7.13: 4 DATA DIVISION. 5 WORKING-STORAGE SECTION. @@ -69,7 +70,7 @@ let%expect_test "codelens" = ---- ^ 8 02 BBprime REDEFINES BB PIC 9. 9 02 CC PIC X. 02 DD PIC X. - 3 references + 4 references __rootdir__/prog.cob:8.13: 5 WORKING-STORAGE SECTION. 6 01 AA. @@ -154,7 +155,7 @@ let%expect_test "codelens-procedure" = CC. DD SECTION. PERFORM AA. - PERFORM BB. + PERFORM BB IN AA. GO DD. STOP RUN. |cobol} in @@ -169,7 +170,7 @@ let%expect_test "codelens-procedure" = ---- ^ 6 BB. 7 PERFORM BB. - 2 references + 3 references __rootdir__/prog.cob:6.12: 3 PROGRAM-ID. prog. 4 PROCEDURE DIVISION. @@ -195,5 +196,5 @@ let%expect_test "codelens-procedure" = 9 > DD SECTION. ---- ^ 10 PERFORM AA. - 11 PERFORM BB. + 11 PERFORM BB IN AA. 2 references |}];; diff --git a/test/lsp/lsp_definition.ml b/test/lsp/lsp_definition.ml index 93fdb616..23ebb706 100644 --- a/test/lsp/lsp_definition.ml +++ b/test/lsp/lsp_definition.ml @@ -638,11 +638,11 @@ let%expect_test "definition-index" = SET _|3-i|_I IN V-TAB TO 0 SET _|4-j|_J IN w TO 0 SET _|5-k|_K IN W-TAB IN W TO 0 - SET _|6-missing|_L IN w-tab IN W TO 0 + SET _|6-missing|_L IN w-tab IN W TO 0. |cobol}; end_with_postproc [%expect.output]; [%expect {| - {"params":{"diagnostics":[{"message":"Missing .","range":{"end":{"character":35,"line":11},"start":{"character":35,"line":11}},"severity":4}],"uri":"file://__rootdir__/prog.cob"},"method":"textDocument/publishDiagnostics","jsonrpc":"2.0"} + {"params":{"diagnostics":[],"uri":"file://__rootdir__/prog.cob"},"method":"textDocument/publishDiagnostics","jsonrpc":"2.0"} 1-j (line 4, character 41): __rootdir__/prog.cob:5.41-5.42: 2 PROGRAM-ID. prog. diff --git a/test/lsp/lsp_references.ml b/test/lsp/lsp_references.ml index e04c59a1..0813ef5a 100644 --- a/test/lsp/lsp_references.ml +++ b/test/lsp/lsp_references.ml @@ -302,3 +302,173 @@ let%expect_test "references-requests-filler" = ---- ^ 14 STOP RUN. 15 |}] + +let%expect_test "references-requests-group-var" = + let { end_with_postproc; projdir }, server = make_lsp_project () in + print_references ~projdir server @@ extract_position_markers {cobol| + IDENTIFICATION DIVISION. + PROGRAM-ID. prog. + DATA DIVISION. + WORKING-STORAGE SECTION. + 01 _|parent-in-def|_A. + 05 _|child-in-def|_B PIC 9. + PROCEDURE DIVISION. + DISPLAY _|parent-alone|_A. + DISPLAY _|child-alone|_B. + DISPLAY _|child-in-parent|_B IN _|parent-of-child|_A. + MOVE 1 TO X. + STOP RUN. + |cobol}; + end_with_postproc [%expect.output]; + [%expect {| + {"params":{"diagnostics":[],"uri":"file://__rootdir__/prog.cob"},"method":"textDocument/publishDiagnostics","jsonrpc":"2.0"} + child-alone (line 9, character 18): + __rootdir__/prog.cob:7.13-7.14: + 4 DATA DIVISION. + 5 WORKING-STORAGE SECTION. + 6 01 A. + 7 > 05 B PIC 9. + ---- ^ + 8 PROCEDURE DIVISION. + 9 DISPLAY A. + __rootdir__/prog.cob:10.18-10.19: + 7 05 B PIC 9. + 8 PROCEDURE DIVISION. + 9 DISPLAY A. + 10 > DISPLAY B. + ---- ^ + 11 DISPLAY B IN A. + 12 MOVE 1 TO X. + __rootdir__/prog.cob:11.18-11.19: + 8 PROCEDURE DIVISION. + 9 DISPLAY A. + 10 DISPLAY B. + 11 > DISPLAY B IN A. + ---- ^ + 12 MOVE 1 TO X. + 13 STOP RUN. + child-in-def (line 6, character 13): + __rootdir__/prog.cob:7.13-7.14: + 4 DATA DIVISION. + 5 WORKING-STORAGE SECTION. + 6 01 A. + 7 > 05 B PIC 9. + ---- ^ + 8 PROCEDURE DIVISION. + 9 DISPLAY A. + __rootdir__/prog.cob:10.18-10.19: + 7 05 B PIC 9. + 8 PROCEDURE DIVISION. + 9 DISPLAY A. + 10 > DISPLAY B. + ---- ^ + 11 DISPLAY B IN A. + 12 MOVE 1 TO X. + __rootdir__/prog.cob:11.18-11.19: + 8 PROCEDURE DIVISION. + 9 DISPLAY A. + 10 DISPLAY B. + 11 > DISPLAY B IN A. + ---- ^ + 12 MOVE 1 TO X. + 13 STOP RUN. + child-in-parent (line 10, character 18): + __rootdir__/prog.cob:7.13-7.14: + 4 DATA DIVISION. + 5 WORKING-STORAGE SECTION. + 6 01 A. + 7 > 05 B PIC 9. + ---- ^ + 8 PROCEDURE DIVISION. + 9 DISPLAY A. + __rootdir__/prog.cob:10.18-10.19: + 7 05 B PIC 9. + 8 PROCEDURE DIVISION. + 9 DISPLAY A. + 10 > DISPLAY B. + ---- ^ + 11 DISPLAY B IN A. + 12 MOVE 1 TO X. + __rootdir__/prog.cob:11.18-11.19: + 8 PROCEDURE DIVISION. + 9 DISPLAY A. + 10 DISPLAY B. + 11 > DISPLAY B IN A. + ---- ^ + 12 MOVE 1 TO X. + 13 STOP RUN. + parent-alone (line 8, character 18): + __rootdir__/prog.cob:6.11-6.12: + 3 PROGRAM-ID. prog. + 4 DATA DIVISION. + 5 WORKING-STORAGE SECTION. + 6 > 01 A. + ---- ^ + 7 05 B PIC 9. + 8 PROCEDURE DIVISION. + __rootdir__/prog.cob:9.18-9.19: + 6 01 A. + 7 05 B PIC 9. + 8 PROCEDURE DIVISION. + 9 > DISPLAY A. + ---- ^ + 10 DISPLAY B. + 11 DISPLAY B IN A. + __rootdir__/prog.cob:11.23-11.24: + 8 PROCEDURE DIVISION. + 9 DISPLAY A. + 10 DISPLAY B. + 11 > DISPLAY B IN A. + ---- ^ + 12 MOVE 1 TO X. + 13 STOP RUN. + parent-in-def (line 5, character 11): + __rootdir__/prog.cob:6.11-6.12: + 3 PROGRAM-ID. prog. + 4 DATA DIVISION. + 5 WORKING-STORAGE SECTION. + 6 > 01 A. + ---- ^ + 7 05 B PIC 9. + 8 PROCEDURE DIVISION. + __rootdir__/prog.cob:9.18-9.19: + 6 01 A. + 7 05 B PIC 9. + 8 PROCEDURE DIVISION. + 9 > DISPLAY A. + ---- ^ + 10 DISPLAY B. + 11 DISPLAY B IN A. + __rootdir__/prog.cob:11.23-11.24: + 8 PROCEDURE DIVISION. + 9 DISPLAY A. + 10 DISPLAY B. + 11 > DISPLAY B IN A. + ---- ^ + 12 MOVE 1 TO X. + 13 STOP RUN. + parent-of-child (line 10, character 23): + __rootdir__/prog.cob:6.11-6.12: + 3 PROGRAM-ID. prog. + 4 DATA DIVISION. + 5 WORKING-STORAGE SECTION. + 6 > 01 A. + ---- ^ + 7 05 B PIC 9. + 8 PROCEDURE DIVISION. + __rootdir__/prog.cob:9.18-9.19: + 6 01 A. + 7 05 B PIC 9. + 8 PROCEDURE DIVISION. + 9 > DISPLAY A. + ---- ^ + 10 DISPLAY B. + 11 DISPLAY B IN A. + __rootdir__/prog.cob:11.23-11.24: + 8 PROCEDURE DIVISION. + 9 DISPLAY A. + 10 DISPLAY B. + 11 > DISPLAY B IN A. + ---- ^ + 12 MOVE 1 TO X. + 13 STOP RUN. |}] diff --git a/test/lsp/lsp_rename.ml b/test/lsp/lsp_rename.ml new file mode 100644 index 00000000..c7c147c0 --- /dev/null +++ b/test/lsp/lsp_rename.ml @@ -0,0 +1,348 @@ +(**************************************************************************) +(* *) +(* SuperBOL OSS Studio *) +(* *) +(* Copyright (c) 2022-2023 OCamlPro SAS *) +(* *) +(* All rights reserved. *) +(* This source code is licensed under the GNU Affero General Public *) +(* License version 3 found in the LICENSE.md file in the root directory *) +(* of this source tree. *) +(* *) +(**************************************************************************) + +open EzCompat (* StringMap *) +open Lsp.Types +open Lsp_testing + +let pp_assoc_elem ppf ((uri, edits): DocumentUri.t * TextEdit.t list) = + let pp_range ppf range = + let location_as_srcloc = new srcloc_resuscitator_cache in + location_as_srcloc#pp ppf @@ Location.create ~range ~uri + in + let pp_edit ppf (edit: TextEdit.t) = + Fmt.pf ppf "%s at " edit.newText; + pp_range ppf edit.range + in + Fmt.(list pp_edit) ppf edits + +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 { 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, 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 + 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 + | { changes = None; _ } -> + Pretty.out "No renames@." + | { changes = Some assoc; _ } -> + Pretty.out "@.@[%d rename entries:@;%a@]@\n" + (count assoc) + (Fmt.list ~sep:Fmt.sp pp_assoc_elem) assoc + in + StringMap.iter (fun n p -> rename_at_position ~key:n p) positions.pos_map; + List.iter (fun p -> rename_at_position p) positions.pos_anonymous; + end_with_postproc + +let%expect_test "rename" = + let end_with_postproc = rename_positions @@ extract_position_markers {cobol| + IDENTIFICATION DIVISION. + PROGRAM-ID. prog. + DATA DIVISION. + WORKING-STORAGE SECTION. + 01 O_|_LD PIC 9. + PROCEDURE DIVISION. + MOVE 1 TO old_|_. + S_|_TOP RUN. + |cobol} + in + end_with_postproc [%expect.output]; + [%expect {| + {"params":{"diagnostics":[],"uri":"file://__rootdir__/prog.cob"},"method":"textDocument/publishDiagnostics","jsonrpc":"2.0"} + (line 5, character 12): + 2 rename entries: + aNewName at __rootdir__/prog.cob:8.20-8.23: + 5 WORKING-STORAGE SECTION. + 6 01 OLD PIC 9. + 7 PROCEDURE DIVISION. + 8 > MOVE 1 TO old. + ---- ^^^ + 9 STOP RUN. + 10 + aNewName at __rootdir__/prog.cob:6.11-6.14: + 3 PROGRAM-ID. prog. + 4 DATA DIVISION. + 5 WORKING-STORAGE SECTION. + 6 > 01 OLD PIC 9. + ---- ^^^ + 7 PROCEDURE DIVISION. + 8 MOVE 1 TO old. + (line 7, character 23): + 2 rename entries: + aNewName at __rootdir__/prog.cob:8.20-8.23: + 5 WORKING-STORAGE SECTION. + 6 01 OLD PIC 9. + 7 PROCEDURE DIVISION. + 8 > MOVE 1 TO old. + ---- ^^^ + 9 STOP RUN. + 10 + aNewName at __rootdir__/prog.cob:6.11-6.14: + 3 PROGRAM-ID. prog. + 4 DATA DIVISION. + 5 WORKING-STORAGE SECTION. + 6 > 01 OLD PIC 9. + ---- ^^^ + 7 PROCEDURE DIVISION. + 8 MOVE 1 TO old. + (line 8, character 11): + 0 rename entries: |}] + +let%expect_test "rename-group" = + let end_with_postproc = rename_positions @@ extract_position_markers {cobol| + IDENTIFICATION DIVISION. + PROGRAM-ID. prog. + DATA DIVISION. + WORKING-STORAGE SECTION. + 01 OLD. + 02 CHILD PIC 9. + PROCEDURE DIVISION. + DISPLAY _|_child in old_|_. + STOP RUN. + |cobol} + in + end_with_postproc [%expect.output]; + [%expect {| + {"params":{"diagnostics":[],"uri":"file://__rootdir__/prog.cob"},"method":"textDocument/publishDiagnostics","jsonrpc":"2.0"} + (line 8, character 18): + 2 rename entries: + aNewName at __rootdir__/prog.cob:9.18-9.23: + 6 01 OLD. + 7 02 CHILD PIC 9. + 8 PROCEDURE DIVISION. + 9 > DISPLAY child in old. + ---- ^^^^^ + 10 STOP RUN. + 11 + aNewName at __rootdir__/prog.cob:7.13-7.18: + 4 DATA DIVISION. + 5 WORKING-STORAGE SECTION. + 6 01 OLD. + 7 > 02 CHILD PIC 9. + ---- ^^^^^ + 8 PROCEDURE DIVISION. + 9 DISPLAY child in old. + (line 8, character 30): + 2 rename entries: + aNewName at __rootdir__/prog.cob:9.27-9.30: + 6 01 OLD. + 7 02 CHILD PIC 9. + 8 PROCEDURE DIVISION. + 9 > DISPLAY child in old. + ---- ^^^ + 10 STOP RUN. + 11 + aNewName at __rootdir__/prog.cob:6.11-6.14: + 3 PROGRAM-ID. prog. + 4 DATA DIVISION. + 5 WORKING-STORAGE SECTION. + 6 > 01 OLD. + ---- ^^^ + 7 02 CHILD PIC 9. + 8 PROCEDURE DIVISION. |}] + +let%expect_test "rename-with-a-ref-in-a-copybook" = + let copybooks = [ + ("lib.cpy", {cobol| + 01 copied-var pic 9.|cobol}) + ] in + let end_with_postproc = rename_positions ~copybooks @@ extract_position_markers {cobol| + IDENTIFICATION DIVISION. + PROGRAM-ID. prog. + DATA DIVISION. + WORKING-STORAGE SECTION. + COPY "lib.cpy". + PROCEDURE DIVISION. + MOVE 1 TO c_|_opied-var. + STOP RUN. + |cobol} + in + end_with_postproc [%expect.output]; + [%expect {| + {"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"} + (line 7, character 21): + 2 rename entries: + aNewName at __rootdir__/lib.cpy:2.11-2.21: + 1 + 2 > 01 copied-var pic 9. + ---- ^^^^^^^^^^ + aNewName at __rootdir__/prog.cob:8.20-8.30: + 5 WORKING-STORAGE SECTION. + 6 COPY "lib.cpy". + 7 PROCEDURE DIVISION. + 8 > MOVE 1 TO copied-var. + ---- ^^^^^^^^^^ + 9 STOP RUN. + 10 |}] + +let%expect_test "rename-with-a-ignored-ref-in-a-copybook" = + let copybooks = [ + ("lib.cpy", {cobol| + 01 copied-var pic 9.|cobol}) + ] in + let end_with_postproc = rename_positions ~ignore_when_copybook:true ~copybooks + @@ extract_position_markers {cobol| + IDENTIFICATION DIVISION. + PROGRAM-ID. prog. + DATA DIVISION. + WORKING-STORAGE SECTION. + COPY "lib.cpy". + PROCEDURE DIVISION. + MOVE 1 TO c_|_opied-var. + STOP RUN. + |cobol} + in + end_with_postproc [%expect.output]; + [%expect {| + {"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"} + (line 7, character 21): + No renames |}] + +let%expect_test "rename-procedure" = + let end_with_postproc = rename_positions @@ extract_position_markers {cobol| + IDENTIFICATION DIVISION. + PROGRAM-ID. prog. + PROCEDURE DIVISION. + s_|sec-simple|_ec SECTION. + PERFORM sec. + GO par_|para-simple|_a. + para. + PERFORM _|para-in-sec|_PARA IN _|sec-of-para|_SEC + STOP RUN. + |cobol} + in + end_with_postproc [%expect.output]; + [%expect {| + {"params":{"diagnostics":[],"uri":"file://__rootdir__/prog.cob"},"method":"textDocument/publishDiagnostics","jsonrpc":"2.0"} + para-in-sec + (line 8, character 18): + 3 rename entries: + aNewName at __rootdir__/prog.cob:9.18-9.22: + 6 PERFORM sec. + 7 GO para. + 8 para. + 9 > PERFORM PARA IN SEC + ---- ^^^^ + 10 STOP RUN. + 11 + aNewName at __rootdir__/prog.cob:7.13-7.17: + 4 PROCEDURE DIVISION. + 5 sec SECTION. + 6 PERFORM sec. + 7 > GO para. + ---- ^^^^ + 8 para. + 9 PERFORM PARA IN SEC + aNewName at __rootdir__/prog.cob:8.10-8.14: + 5 sec SECTION. + 6 PERFORM sec. + 7 GO para. + 8 > para. + ---- ^^^^ + 9 PERFORM PARA IN SEC + 10 STOP RUN. + para-simple + (line 6, character 16): + 3 rename entries: + aNewName at __rootdir__/prog.cob:9.18-9.22: + 6 PERFORM sec. + 7 GO para. + 8 para. + 9 > PERFORM PARA IN SEC + ---- ^^^^ + 10 STOP RUN. + 11 + aNewName at __rootdir__/prog.cob:7.13-7.17: + 4 PROCEDURE DIVISION. + 5 sec SECTION. + 6 PERFORM sec. + 7 > GO para. + ---- ^^^^ + 8 para. + 9 PERFORM PARA IN SEC + aNewName at __rootdir__/prog.cob:8.10-8.14: + 5 sec SECTION. + 6 PERFORM sec. + 7 GO para. + 8 > para. + ---- ^^^^ + 9 PERFORM PARA IN SEC + 10 STOP RUN. + sec-of-para + (line 8, character 26): + 3 rename entries: + aNewName at __rootdir__/prog.cob:9.26-9.29: + 6 PERFORM sec. + 7 GO para. + 8 para. + 9 > PERFORM PARA IN SEC + ---- ^^^ + 10 STOP RUN. + 11 + aNewName at __rootdir__/prog.cob:6.18-6.21: + 3 PROGRAM-ID. prog. + 4 PROCEDURE DIVISION. + 5 sec SECTION. + 6 > PERFORM sec. + ---- ^^^ + 7 GO para. + 8 para. + aNewName at __rootdir__/prog.cob:5.10-5.13: + 2 IDENTIFICATION DIVISION. + 3 PROGRAM-ID. prog. + 4 PROCEDURE DIVISION. + 5 > sec SECTION. + ---- ^^^ + 6 PERFORM sec. + 7 GO para. + sec-simple + (line 4, character 11): + 3 rename entries: + aNewName at __rootdir__/prog.cob:9.26-9.29: + 6 PERFORM sec. + 7 GO para. + 8 para. + 9 > PERFORM PARA IN SEC + ---- ^^^ + 10 STOP RUN. + 11 + aNewName at __rootdir__/prog.cob:6.18-6.21: + 3 PROGRAM-ID. prog. + 4 PROCEDURE DIVISION. + 5 sec SECTION. + 6 > PERFORM sec. + ---- ^^^ + 7 GO para. + 8 para. + aNewName at __rootdir__/prog.cob:5.10-5.13: + 2 IDENTIFICATION DIVISION. + 3 PROGRAM-ID. prog. + 4 PROCEDURE DIVISION. + 5 > sec SECTION. + ---- ^^^ + 6 PERFORM sec. + 7 GO para. |}] +