From 76c7ef46524d4d46dd88ebd566785883600f29af Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Sat, 3 Feb 2024 16:52:15 -0300 Subject: [PATCH 01/11] use cmdliner --- analysis/reanalyze/src/Reanalyze.ml | 4 + tools/bin/dune | 2 +- tools/bin/main.ml | 332 ++++++++++++++++++++++++---- 3 files changed, 290 insertions(+), 48 deletions(-) diff --git a/analysis/reanalyze/src/Reanalyze.ml b/analysis/reanalyze/src/Reanalyze.ml index 0355c9cb7..3e40452e2 100644 --- a/analysis/reanalyze/src/Reanalyze.ml +++ b/analysis/reanalyze/src/Reanalyze.ml @@ -220,3 +220,7 @@ let cli () = module RunConfig = RunConfig module Log_ = Log_ +module Version = Version +module Common = Common +module Paths = Paths +module DeadCommon = DeadCommon diff --git a/tools/bin/dune b/tools/bin/dune index d498e0675..1f80896de 100644 --- a/tools/bin/dune +++ b/tools/bin/dune @@ -4,6 +4,6 @@ (modes byte exe) ; The main module that will become the binary. (name main) - (libraries tools) + (libraries tools analysis cmdliner) (flags (-w "+6+26+27+32+33+39"))) diff --git a/tools/bin/main.ml b/tools/bin/main.ml index d9b4f2ae4..746dfd81f 100644 --- a/tools/bin/main.ml +++ b/tools/bin/main.ml @@ -1,57 +1,295 @@ -let docHelp = - {|ReScript Tools +open Cmdliner -Output documentation to standard output +let version = Version.version -Usage: rescript-tools doc +module Docgen = struct + let run file = + let () = + match Sys.getenv_opt "FROM_COMPILER" with + | Some "true" -> Analysis.Cfg.isDocGenFromCompiler := true + | _ -> () + in + match Tools.extractDocs ~entryPointFile:file ~debug:false with + | Ok s -> `Ok (Printf.printf "%s\n" s) + | Error e -> `Error (true, e) -Example: rescript-tools doc ./path/to/EntryPointLib.res|} + let docgen_file = + let env = + let doc = + "Internal usage: `true` to generate documentation from \ + rescript-compiler repo: \ + https://github.com/rescript-lang/rescript-compiler" + in + Cmd.Env.info "FROM_COMPILER" ~doc + in + let doc = "Path to ReScript file" in + Arg.(required & (pos 0) (some string) None & info [] ~doc ~env ~docv:"PATH") -let help = - {|ReScript Tools + let cmd = + let doc = "Generate JSON Documentation. Output to standard output" in + let info = Cmd.info "doc" ~version ~doc in + Cmd.v info Term.(ret (const run $ docgen_file)) +end -Usage: rescript-tools [command] +module Reanalyze = struct + type dir = Suppress of string list | Unsuppress of string list + type analysis = All | DCE | Termination | Exception -Commands: + type args = { + analysis: analysis; + ci: bool; + config: bool; + debug: bool; + exclude_paths: string list option; + experimental: bool; + externals: bool; + json: bool; + live_names: string list option; + live_paths: string list option; + cmt_path: string option; + write: bool; + suppress_unsuppress: dir option; + } -doc Generate documentation -reanalyze Reanalyze --v, --version Print version --h, --help Print help|} + let run + { + analysis; + ci; + config; + debug; + exclude_paths; + experimental; + externals; + json; + live_names; + live_paths; + cmt_path; + write; + suppress_unsuppress; + } = + let open Reanalyze in + (* Set kind of analysis *) + (match analysis with + | All -> RunConfig.all () + | DCE -> RunConfig.dce () + | Termination -> RunConfig.termination () + | Exception -> RunConfig.exception_ ()); -let logAndExit = function - | Ok log -> - Printf.printf "%s\n" log; - exit 0 - | Error log -> - Printf.eprintf "%s\n" log; - exit 1 + if config then Paths.Config.processBsconfig (); -let version = Version.version + let () = + let open Common in + Cli.debug := debug; + Cli.ci := ci; + Cli.experimental := experimental; + Cli.json := json; + Cli.write := write; + (Cli.liveNames := + match live_names with + | None -> [] + | Some l -> l); + (Cli.livePaths := + match live_paths with + | None -> [] + | Some l -> l); + Cli.excludePaths := + match exclude_paths with + | None -> [] + | Some l -> l + in + + DeadCommon.Config.analyzeExternals := externals; + + (match suppress_unsuppress with + | Some kind -> ( + match kind with + | Suppress dirs -> Common.runConfig.suppress <- dirs + | Unsuppress dirs -> Common.runConfig.unsuppress <- dirs) + | None -> ()); + + runAnalysisAndReport ~cmtRoot:cmt_path + + let cmd = + let doc = + "Experimental analyses for ReScript and OCaml: globally dead \ + values/types, exception analysis, and termination analysis." + in + let version = Reanalyze.Version.version in + let info = Cmd.info "reanalyze" ~version ~doc in + + let analysis = + let all = + let doc = "Run all the analyses: DCE, Exception and Termination" in + (All, Arg.info ["all"] ~doc ~absent:"Reanalyze run all analysis") + in + let dce = + let doc = + "Enable experimental DCE. The dead code analysis reports on globally \ + dead values, redundant optional arguments, dead modules, dead types \ + (records and variants)." + in + (DCE, Arg.info ["dce"] ~doc) + in + let termination = + let doc = "Experimental termination analysis" in + (Termination, Arg.info ["termination"] ~doc) + in + let exception_ = + let doc = + "Experimental exception analysis. The exception analysis is designed \ + to keep track statically of the exceptions that might be raised at \ + runtime. It works by issuing warnings and recognizing annotations" + in + (Exception, Arg.info ["exception"] ~doc) + in + + Arg.(last & vflag_all [All] [all; dce; termination; exception_]) + in + + let ci = + let doc = "Internal flag for use in CI" in + Arg.(value & flag & info ["ci"] ~doc) + in + + let config = + let doc = "Read the analysis mode from rescript.json or bsconfig.json" in + Arg.(value & flag & info ["config"] ~doc) + in + + let debug = + let doc = "Print debug information" in + Arg.(value & flag & info ["debug"] ~doc) + in + + let exclude_paths = + let doc = + "Exclude from analysis files whose path has a prefix in the list" + in + Arg.( + value + & opt (some (list ~sep:',' string)) None + & info ["exclude-paths"] ~doc ~docv:"PATHS") + in + + let experimental = + let doc = + "Turn on experimental analyses. This option is currently unused" + in + Arg.(value & flag & info ["experimental"] ~doc) + in + + let externals = + let doc = "Report on externals in dead code analysis" in + Arg.(value & flag & info ["externals"] ~doc) + in + + let json = + let doc = "Print reports in JSON Format" in + Arg.(value & flag & info ["json"] ~doc) + in + + let live_names = + let doc = + "Consider all values with the given name as live. This automatically \ + annotates @live all the items in list" + in + Arg.( + value + & opt (some (list ~sep:',' string)) None + & info ["live-names"] ~doc ~docv:"PATHS") + in + + let live_paths = + let doc = + "Consider all values whose path has a prefix in the list as live. This \ + automatically annotates @live all the items on list" + in + Arg.( + value + & opt (some (list ~sep:',' string)) None + & info ["live-paths"] ~doc ~docv:"PATHS") + in + + let suppress_unsuppress_exclusive = + let open Cmdliner.Term in + let exclusive_msg = + "The options --suppress and --unsuppress are mutually exclusive." + in + + let suppress = + let doc = + "Don't report on files whose path has a prefix in the list. \ + Comma-separated-path-prefixes" + in + Arg.( + value + & opt (some (list ~sep:',' string)) None + & info ["suppress"] ~doc ~docv:"PATHS") + in + + let unsuppress = + let doc = + "Report on files whose path has a prefix in the list. \ + comma-separated-path-prefixes" + in + Arg.( + value + & opt (some (list ~sep:',' string)) None + & info ["unsuppress"] ~doc ~docv:"PATHS") + in + + let suppress_unsuppress suppress unsuppress = + match (suppress, unsuppress) with + | None, None -> `Ok None + | Some s, None -> `Ok (Some (Suppress s)) + | None, Some s -> `Ok (Some (Unsuppress s)) + | _ -> `Error (true, exclusive_msg) + in + ret (const suppress_unsuppress $ suppress $ unsuppress) + in + + let cmt_path = + let doc = "Path to .cmt files" in + Arg.(value & opt (some string) None & info ["cmt-path"] ~doc ~docv:"PATH") + in + + let write = + let doc = "Write @dead annotations directly in the source files" in + Arg.(value & flag & info ["write"] ~doc) + in + + let parse analysis externals live_names live_paths cmt_path exclude_paths + suppress_unsuppress experimental config ci write json debug = + { + analysis; + ci; + config; + debug; + exclude_paths; + experimental; + externals; + json; + live_names; + live_paths; + write; + cmt_path; + suppress_unsuppress; + } + in + + let cmd = + Term.( + const parse $ analysis $ externals $ live_names $ live_paths $ cmt_path + $ exclude_paths $ suppress_unsuppress_exclusive $ experimental $ config + $ ci $ write $ json $ debug) + in + + Cmd.v info Term.(const run $ cmd) +end + +let cmd = + let doc = "ReScript Tools" in + let info = Cmd.info "rescript-tools" ~version ~doc in + Cmd.group info [Docgen.cmd; Reanalyze.cmd] -let main () = - match Sys.argv |> Array.to_list |> List.tl with - | "doc" :: rest -> ( - match rest with - | ["-h"] | ["--help"] -> logAndExit (Ok docHelp) - | [path] -> - (* NOTE: Internal use to generate docs from compiler *) - let () = - match Sys.getenv_opt "FROM_COMPILER" with - | Some "true" -> Analysis.Cfg.isDocGenFromCompiler := true - | _ -> () - in - logAndExit (Tools.extractDocs ~entryPointFile:path ~debug:false) - | _ -> logAndExit (Error docHelp)) - | "reanalyze" :: _ -> - let len = Array.length Sys.argv in - for i = 1 to len - 2 do - Sys.argv.(i) <- Sys.argv.(i + 1) - done; - Sys.argv.(len - 1) <- ""; - Reanalyze.cli () - | ["-h"] | ["--help"] -> logAndExit (Ok help) - | ["-v"] | ["--version"] -> logAndExit (Ok version) - | _ -> logAndExit (Error help) - -let () = main () +let () = exit (Cmd.eval cmd) From 1d4becf68791f770cdeac88d47131267f9f867b6 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Sat, 3 Feb 2024 17:28:16 -0300 Subject: [PATCH 02/11] add cmdliner dep --- dune-project | 2 ++ tools.opam | 1 + 2 files changed, 3 insertions(+) diff --git a/dune-project b/dune-project index e3e04789b..bccbfe348 100644 --- a/dune-project +++ b/dune-project @@ -28,5 +28,7 @@ (>= 4.10)) (cppo (= 1.6.9)) + (cmdliner + (>= 1.2)) analysis dune)) diff --git a/tools.opam b/tools.opam index 3dbdc6f1d..6e123e55c 100644 --- a/tools.opam +++ b/tools.opam @@ -8,6 +8,7 @@ bug-reports: "https://github.com/rescript-lang/rescript-vscode/issues" depends: [ "ocaml" {>= "4.10"} "cppo" {= "1.6.9"} + "cmdliner" {>= "1.2"} "analysis" "dune" ] From dcd65a57e462efcc508670372a2bd6221019a245 Mon Sep 17 00:00:00 2001 From: Christoph Knittel Date: Mon, 5 Feb 2024 07:49:19 +0100 Subject: [PATCH 03/11] Use Github-hosted macos arm runner (macos-14) --- .github/workflows/ci.yml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 41099b87d..ac7ec1bd3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,13 +18,18 @@ jobs: matrix: # Stay on the oldest Ubuntu version that's still supported by Github Actions # to avoid glibc incompatibilities as far as possible. - os: [macos-latest, macos-arm, ubuntu-20.04, windows-latest] + os: [ + macos-13, # x64 + macos-14, # ARM + ubuntu-20.04, + windows-latest, + ] # syntax explanation: # https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#example-including-additional-values-into-combinations include: - - os: macos-latest + - os: macos-13 artifact-folder: darwin - - os: macos-arm + - os: macos-14 artifact-folder: darwinarm64 - os: ubuntu-20.04 artifact-folder: linux @@ -107,7 +112,7 @@ jobs: - name: Download MacOS binary uses: actions/download-artifact@v3 with: - name: macos-latest + name: macos-13 path: binaries - run: tar -xvf binary.tar working-directory: binaries @@ -115,7 +120,7 @@ jobs: - name: Download MacOS ARM binary uses: actions/download-artifact@v3 with: - name: macos-arm + name: macos-14 path: binaries - run: tar -xvf binary.tar working-directory: binaries From 49c11b9c98dce6f0044c7decc76d4d1c24b1ddf0 Mon Sep 17 00:00:00 2001 From: Christoph Knittel Date: Mon, 5 Feb 2024 07:56:20 +0100 Subject: [PATCH 04/11] Use latest setup-ocaml again --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ac7ec1bd3..ff125b8a2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,7 +54,7 @@ jobs: key: ${{matrix.os}}-rescript-vscode-v4 - name: Use OCaml - uses: ocaml/setup-ocaml@v2.1.7 + uses: ocaml/setup-ocaml@v2 with: ocaml-compiler: 4.14.x From 1e29e8834ff2e4e0dc29bfbf70e74c4e0a482930 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Sun, 11 Feb 2024 16:07:45 -0300 Subject: [PATCH 05/11] refactor --- tools/bin/main.ml | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/tools/bin/main.ml b/tools/bin/main.ml index 746dfd81f..906384699 100644 --- a/tools/bin/main.ml +++ b/tools/bin/main.ml @@ -84,18 +84,9 @@ module Reanalyze = struct Cli.experimental := experimental; Cli.json := json; Cli.write := write; - (Cli.liveNames := - match live_names with - | None -> [] - | Some l -> l); - (Cli.livePaths := - match live_paths with - | None -> [] - | Some l -> l); - Cli.excludePaths := - match exclude_paths with - | None -> [] - | Some l -> l + Cli.liveNames := live_names |> Option.value ~default:[]; + Cli.livePaths := live_paths |> Option.value ~default:[]; + Cli.excludePaths := exclude_paths |> Option.value ~default:[] in DeadCommon.Config.analyzeExternals := externals; From fce82af1f9c2a87f89f7185a628788fbbd506569 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Sun, 11 Feb 2024 17:56:05 -0300 Subject: [PATCH 06/11] dont make suppress and unsuppress mututually exclusive --- .../examples/deadcode/expected/deadcode.txt | 1 - .../examples/deadcode/expected/exception.txt | 1 - analysis/reanalyze/examples/deadcode/test.sh | 4 +- .../termination/expected/termination.txt | 1 - .../reanalyze/examples/termination/test.sh | 2 +- tools/bin/main.ml | 78 +++++++------------ 6 files changed, 33 insertions(+), 54 deletions(-) diff --git a/analysis/reanalyze/examples/deadcode/expected/deadcode.txt b/analysis/reanalyze/examples/deadcode/expected/deadcode.txt index 9296b5944..9cec65dfd 100644 --- a/analysis/reanalyze/examples/deadcode/expected/deadcode.txt +++ b/analysis/reanalyze/examples/deadcode/expected/deadcode.txt @@ -1,4 +1,3 @@ - Scanning AutoAnnotate.cmt Source:AutoAnnotate.res addVariantCaseDeclaration R AutoAnnotate.res:1:15 path:+AutoAnnotate.variant addRecordLabelDeclaration variant AutoAnnotate.res:4:15 path:+AutoAnnotate.record diff --git a/analysis/reanalyze/examples/deadcode/expected/exception.txt b/analysis/reanalyze/examples/deadcode/expected/exception.txt index 171a11501..e64a79905 100644 --- a/analysis/reanalyze/examples/deadcode/expected/exception.txt +++ b/analysis/reanalyze/examples/deadcode/expected/exception.txt @@ -1,5 +1,4 @@ - Exception Analysis Exn.res:1:5-10 raises might raise Not_found (Exn.res:1:19) and is not annotated with @raises(Not_found) diff --git a/analysis/reanalyze/examples/deadcode/test.sh b/analysis/reanalyze/examples/deadcode/test.sh index ea28ad778..913620b66 100755 --- a/analysis/reanalyze/examples/deadcode/test.sh +++ b/analysis/reanalyze/examples/deadcode/test.sh @@ -6,7 +6,7 @@ else exclude_dirs="src/exception" suppress="src/ToSuppress.res" fi -dune exec rescript-editor-analysis -- reanalyze -config -debug -ci -exclude-paths $exclude_dirs -live-names globallyLive1 -live-names globallyLive2,globallyLive3 -suppress $suppress > $output +dune exec -- rescript-tools reanalyze --dce --config --debug --ci --exclude-paths $exclude_dirs --live-names globallyLive1,globallyLive2,globallyLive3 --suppress $suppress > $output # CI. We use LF, and the CI OCaml fork prints CRLF. Convert. if [ "$RUNNER_OS" == "Windows" ]; then perl -pi -e 's/\r\n/\n/g' -- $output @@ -18,7 +18,7 @@ if [ "$RUNNER_OS" == "Windows" ]; then else unsuppress_dirs="src/exception" fi -dune exec rescript-editor-analysis -- reanalyze -exception -ci -suppress src -unsuppress $unsuppress_dirs > $output +dune exec -- rescript-tools reanalyze --exception --ci --suppress src --unsuppress $unsuppress_dirs > $output # CI. We use LF, and the CI OCaml fork prints CRLF. Convert. if [ "$RUNNER_OS" == "Windows" ]; then perl -pi -e 's/\r\n/\n/g' -- $output diff --git a/analysis/reanalyze/examples/termination/expected/termination.txt b/analysis/reanalyze/examples/termination/expected/termination.txt index 063f51b6d..50144280b 100644 --- a/analysis/reanalyze/examples/termination/expected/termination.txt +++ b/analysis/reanalyze/examples/termination/expected/termination.txt @@ -1,4 +1,3 @@ - Scanning TestCyberTruck.cmt Source:TestCyberTruck.res Function Table diff --git a/analysis/reanalyze/examples/termination/test.sh b/analysis/reanalyze/examples/termination/test.sh index 3897ae695..c85424ae5 100755 --- a/analysis/reanalyze/examples/termination/test.sh +++ b/analysis/reanalyze/examples/termination/test.sh @@ -1,5 +1,5 @@ output="expected/termination.txt" -dune exec rescript-editor-analysis -- reanalyze -config -ci -debug > $output +dune exec -- rescript-tools reanalyze --termination --config --ci --debug > $output # CI. We use LF, and the CI OCaml fork prints CRLF. Convert. if [ "$RUNNER_OS" == "Windows" ]; then perl -pi -e 's/\r\n/\n/g' -- $output diff --git a/tools/bin/main.ml b/tools/bin/main.ml index 906384699..0041006ab 100644 --- a/tools/bin/main.ml +++ b/tools/bin/main.ml @@ -32,7 +32,6 @@ module Docgen = struct end module Reanalyze = struct - type dir = Suppress of string list | Unsuppress of string list type analysis = All | DCE | Termination | Exception type args = { @@ -48,7 +47,8 @@ module Reanalyze = struct live_paths: string list option; cmt_path: string option; write: bool; - suppress_unsuppress: dir option; + suppress: string list option; + unsuppress: string list option; } let run @@ -65,7 +65,8 @@ module Reanalyze = struct live_paths; cmt_path; write; - suppress_unsuppress; + suppress; + unsuppress; } = let open Reanalyze in (* Set kind of analysis *) @@ -86,18 +87,13 @@ module Reanalyze = struct Cli.write := write; Cli.liveNames := live_names |> Option.value ~default:[]; Cli.livePaths := live_paths |> Option.value ~default:[]; - Cli.excludePaths := exclude_paths |> Option.value ~default:[] + Cli.excludePaths := exclude_paths |> Option.value ~default:[]; + runConfig.unsuppress <- unsuppress |> Option.value ~default:[]; + runConfig.suppress <- suppress |> Option.value ~default:[] in DeadCommon.Config.analyzeExternals := externals; - (match suppress_unsuppress with - | Some kind -> ( - match kind with - | Suppress dirs -> Common.runConfig.suppress <- dirs - | Unsuppress dirs -> Common.runConfig.unsuppress <- dirs) - | None -> ()); - runAnalysisAndReport ~cmtRoot:cmt_path let cmd = @@ -201,42 +197,27 @@ module Reanalyze = struct & info ["live-paths"] ~doc ~docv:"PATHS") in - let suppress_unsuppress_exclusive = - let open Cmdliner.Term in - let exclusive_msg = - "The options --suppress and --unsuppress are mutually exclusive." - in - - let suppress = - let doc = - "Don't report on files whose path has a prefix in the list. \ - Comma-separated-path-prefixes" - in - Arg.( - value - & opt (some (list ~sep:',' string)) None - & info ["suppress"] ~doc ~docv:"PATHS") - in - - let unsuppress = - let doc = - "Report on files whose path has a prefix in the list. \ - comma-separated-path-prefixes" - in - Arg.( - value - & opt (some (list ~sep:',' string)) None - & info ["unsuppress"] ~doc ~docv:"PATHS") + let unsuppress = + let doc = + "Report on files whose path has a prefix in the list. overriding \ + --suppress (no-op if --suppress is not specified)\n\ + \ comma-separated-path-prefixes" in + Arg.( + value + & opt (some (list ~sep:',' string)) None + & info ["unsuppress"] ~doc ~docv:"PATHS") + in - let suppress_unsuppress suppress unsuppress = - match (suppress, unsuppress) with - | None, None -> `Ok None - | Some s, None -> `Ok (Some (Suppress s)) - | None, Some s -> `Ok (Some (Unsuppress s)) - | _ -> `Error (true, exclusive_msg) + let suppress = + let doc = + "Don't report on files whose path has a prefix in the list. \ + Comma-separated-path-prefixes" in - ret (const suppress_unsuppress $ suppress $ unsuppress) + Arg.( + value + & opt (some (list ~sep:',' string)) None + & info ["suppress"] ~doc ~docv:"PATHS") in let cmt_path = @@ -250,7 +231,7 @@ module Reanalyze = struct in let parse analysis externals live_names live_paths cmt_path exclude_paths - suppress_unsuppress experimental config ci write json debug = + suppress unsuppress experimental config ci write json debug = { analysis; ci; @@ -264,15 +245,16 @@ module Reanalyze = struct live_paths; write; cmt_path; - suppress_unsuppress; + suppress; + unsuppress; } in let cmd = Term.( const parse $ analysis $ externals $ live_names $ live_paths $ cmt_path - $ exclude_paths $ suppress_unsuppress_exclusive $ experimental $ config - $ ci $ write $ json $ debug) + $ exclude_paths $ suppress $ unsuppress $ experimental $ config $ ci + $ write $ json $ debug) in Cmd.v info Term.(const run $ cmd) From 70aa3d9b362eb2be0435660e81f4f33dd3dec43e Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Sun, 11 Feb 2024 17:57:15 -0300 Subject: [PATCH 07/11] update ci --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ff125b8a2..39a78c116 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,7 +65,7 @@ jobs: registry-url: 'https://registry.npmjs.org' - run: npm ci - - run: opam install dune cppo + - run: opam install . --deps-only --with-doc --with-test - run: npm run compile # These 2 runs (or just the second?) are for when you have opam dependencies. We don't. From 5ca3fe0d503dd57a9eace3e75d5228f01dba2760 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Sun, 11 Feb 2024 18:47:45 -0300 Subject: [PATCH 08/11] fix ci --- .github/workflows/ci.yml | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 39a78c116..b76d7c0bb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,7 +65,25 @@ jobs: registry-url: 'https://registry.npmjs.org' - run: npm ci - - run: opam install . --deps-only --with-doc --with-test + + - name: Use OCaml ${{matrix.ocaml_compiler}} + uses: ocaml/setup-ocaml@v2 + if: matrix.os != 'windows-latest' + with: + ocaml-compiler: ${{matrix.ocaml_compiler}} + + - name: Use OCaml ${{matrix.ocaml_compiler}} (Win) + uses: ocaml/setup-ocaml@v2 + if: matrix.os == 'windows-latest' + with: + ocaml-compiler: ${{ matrix.ocaml-compiler }} + opam-repositories: | + sunset: https://github.com/ocaml-opam/opam-repository-mingw.git#sunset + default: https://github.com/ocaml/opam-repository.git + + - name: Install opam deps + run: opam install . --deps-only --with-doc --with-test + - run: npm run compile # These 2 runs (or just the second?) are for when you have opam dependencies. We don't. From b70106a794ad58959c114c04d0a83a92f504a9da Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Sun, 11 Feb 2024 18:52:31 -0300 Subject: [PATCH 09/11] fix ci --- .github/workflows/ci.yml | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b76d7c0bb..6ec33863f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -53,37 +53,29 @@ jobs: path: ~/.opam key: ${{matrix.os}}-rescript-vscode-v4 - - name: Use OCaml - uses: ocaml/setup-ocaml@v2 - with: - ocaml-compiler: 4.14.x - - - name: Use Node.js - uses: actions/setup-node@v3 - with: - node-version: 16 - registry-url: 'https://registry.npmjs.org' - - - run: npm ci - - name: Use OCaml ${{matrix.ocaml_compiler}} uses: ocaml/setup-ocaml@v2 if: matrix.os != 'windows-latest' with: - ocaml-compiler: ${{matrix.ocaml_compiler}} + ocaml-compiler: 4.14.x - name: Use OCaml ${{matrix.ocaml_compiler}} (Win) uses: ocaml/setup-ocaml@v2 if: matrix.os == 'windows-latest' with: - ocaml-compiler: ${{ matrix.ocaml-compiler }} + ocaml-compiler: 4.14.x opam-repositories: | sunset: https://github.com/ocaml-opam/opam-repository-mingw.git#sunset default: https://github.com/ocaml/opam-repository.git - - name: Install opam deps - run: opam install . --deps-only --with-doc --with-test + - name: Use Node.js + uses: actions/setup-node@v3 + with: + node-version: 16 + registry-url: 'https://registry.npmjs.org' + - run: npm ci + - run: opam install . --deps-only --with-doc --with-test - run: npm run compile # These 2 runs (or just the second?) are for when you have opam dependencies. We don't. From 64747063db2e9ecabb37d5765c729b99f3c794c5 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Mon, 12 Feb 2024 18:12:13 -0300 Subject: [PATCH 10/11] remove --all flag --- tools/bin/main.ml | 130 +++++++++++++++++++++++++--------------------- 1 file changed, 70 insertions(+), 60 deletions(-) diff --git a/tools/bin/main.ml b/tools/bin/main.ml index 0041006ab..ad8993210 100644 --- a/tools/bin/main.ml +++ b/tools/bin/main.ml @@ -32,10 +32,10 @@ module Docgen = struct end module Reanalyze = struct - type analysis = All | DCE | Termination | Exception - type args = { - analysis: analysis; + dce: bool; + termination: bool; + exception_: bool; ci: bool; config: bool; debug: bool; @@ -53,7 +53,9 @@ module Reanalyze = struct let run { - analysis; + dce; + termination; + exception_; ci; config; debug; @@ -69,31 +71,29 @@ module Reanalyze = struct unsuppress; } = let open Reanalyze in - (* Set kind of analysis *) - (match analysis with - | All -> RunConfig.all () - | DCE -> RunConfig.dce () - | Termination -> RunConfig.termination () - | Exception -> RunConfig.exception_ ()); - - if config then Paths.Config.processBsconfig (); - - let () = - let open Common in - Cli.debug := debug; - Cli.ci := ci; - Cli.experimental := experimental; - Cli.json := json; - Cli.write := write; - Cli.liveNames := live_names |> Option.value ~default:[]; - Cli.livePaths := live_paths |> Option.value ~default:[]; - Cli.excludePaths := exclude_paths |> Option.value ~default:[]; - runConfig.unsuppress <- unsuppress |> Option.value ~default:[]; - runConfig.suppress <- suppress |> Option.value ~default:[] - in + if dce then RunConfig.dce (); + if termination then RunConfig.termination (); + if exception_ then RunConfig.exception_ (); + + (* Enable all analysis if dce, termination and exception_ is false *) + if (not dce) && (not termination) && not exception_ then RunConfig.all (); + + let open Common in + Cli.debug := debug; + Cli.ci := ci; + Cli.experimental := experimental; + Cli.json := json; + Cli.write := write; + Cli.liveNames := live_names |> Option.value ~default:[]; + Cli.livePaths := live_paths |> Option.value ~default:[]; + Cli.excludePaths := exclude_paths |> Option.value ~default:[]; + runConfig.unsuppress <- unsuppress |> Option.value ~default:[]; + runConfig.suppress <- suppress |> Option.value ~default:[]; DeadCommon.Config.analyzeExternals := externals; + if config then Paths.Config.processBsconfig (); + runAnalysisAndReport ~cmtRoot:cmt_path let cmd = @@ -102,35 +102,42 @@ module Reanalyze = struct values/types, exception analysis, and termination analysis." in let version = Reanalyze.Version.version in - let info = Cmd.info "reanalyze" ~version ~doc in + let man = + [ + `S Manpage.s_description; + `P + "Reanalyze will report all kind of analysis, dead code, exception \ + and termination"; + `S Manpage.s_examples; + `I + ( "rescript-tools reanalyze", + "Report all analysis (dead code, exception and termination)" ); + `I ("rescript-tools reanalyze --dce", "Report only dead code"); + ] + in + let info = Cmd.info "reanalyze" ~version ~doc ~man in - let analysis = - let all = - let doc = "Run all the analyses: DCE, Exception and Termination" in - (All, Arg.info ["all"] ~doc ~absent:"Reanalyze run all analysis") - in - let dce = - let doc = - "Enable experimental DCE. The dead code analysis reports on globally \ - dead values, redundant optional arguments, dead modules, dead types \ - (records and variants)." - in - (DCE, Arg.info ["dce"] ~doc) - in - let termination = - let doc = "Experimental termination analysis" in - (Termination, Arg.info ["termination"] ~doc) - in - let exception_ = - let doc = - "Experimental exception analysis. The exception analysis is designed \ - to keep track statically of the exceptions that might be raised at \ - runtime. It works by issuing warnings and recognizing annotations" - in - (Exception, Arg.info ["exception"] ~doc) + let exception_ = + let doc = + "Experimental exception analysis. The exception analysis is designed \ + to keep track statically of the exceptions that might be raised at \ + runtime. It works by issuing warnings and recognizing annotations" in + Arg.(value & flag & info ["exception"] ~doc) + in - Arg.(last & vflag_all [All] [all; dce; termination; exception_]) + let termination = + let doc = "Experimental termination analysis" in + Arg.(value & flag & info ["termination"] ~doc) + in + + let dce = + let doc = + "Enable experimental DCE. The dead code analysis reports on globally \ + dead values, redundant optional arguments, dead modules, dead types \ + (records and variants)." + in + Arg.(value & flag & info ["dce"] ~doc) in let ci = @@ -183,7 +190,7 @@ module Reanalyze = struct Arg.( value & opt (some (list ~sep:',' string)) None - & info ["live-names"] ~doc ~docv:"PATHS") + & info ["live-names"] ~doc ~docv:"NAMES") in let live_paths = @@ -194,7 +201,7 @@ module Reanalyze = struct Arg.( value & opt (some (list ~sep:',' string)) None - & info ["live-paths"] ~doc ~docv:"PATHS") + & info ["live-paths"] ~doc ~docv:"NAMES") in let unsuppress = @@ -230,10 +237,13 @@ module Reanalyze = struct Arg.(value & flag & info ["write"] ~doc) in - let parse analysis externals live_names live_paths cmt_path exclude_paths - suppress unsuppress experimental config ci write json debug = + let parse dce termination exception_ externals live_names live_paths + cmt_path exclude_paths suppress unsuppress experimental config ci write + json debug = { - analysis; + dce; + termination; + exception_; ci; config; debug; @@ -252,9 +262,9 @@ module Reanalyze = struct let cmd = Term.( - const parse $ analysis $ externals $ live_names $ live_paths $ cmt_path - $ exclude_paths $ suppress $ unsuppress $ experimental $ config $ ci - $ write $ json $ debug) + const parse $ dce $ termination $ exception_ $ externals $ live_names + $ live_paths $ cmt_path $ exclude_paths $ suppress $ unsuppress + $ experimental $ config $ ci $ write $ json $ debug) in Cmd.v info Term.(const run $ cmd) From f31703adbff24d9250d7c7086273e92a50eab1b3 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Mon, 12 Feb 2024 18:56:44 -0300 Subject: [PATCH 11/11] update tools/CHANGELOG.md --- analysis/reanalyze/src/Reanalyze.ml | 1 - tools/CHANGELOG.md | 7 +++++++ tools/bin/main.ml | 7 +++---- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/analysis/reanalyze/src/Reanalyze.ml b/analysis/reanalyze/src/Reanalyze.ml index 3e40452e2..a8a4fbb4b 100644 --- a/analysis/reanalyze/src/Reanalyze.ml +++ b/analysis/reanalyze/src/Reanalyze.ml @@ -220,7 +220,6 @@ let cli () = module RunConfig = RunConfig module Log_ = Log_ -module Version = Version module Common = Common module Paths = Paths module DeadCommon = DeadCommon diff --git a/tools/CHANGELOG.md b/tools/CHANGELOG.md index 22872f017..fa43de001 100644 --- a/tools/CHANGELOG.md +++ b/tools/CHANGELOG.md @@ -12,6 +12,13 @@ ## master +## 0.6.0 + +#### :boom: Breaking Change + +- Reanalyze subcommand arguments now starts with two dash `--`. Some commands removed. https://github.com/rescript-lang/rescript-vscode/pull/910 +- ReScript Tools command now generate man pages following GNU conventions. https://github.com/rescript-lang/rescript-vscode/pull/910 + ## 0.5.0 #### :rocket: New Feature diff --git a/tools/bin/main.ml b/tools/bin/main.ml index ad8993210..6ef24db00 100644 --- a/tools/bin/main.ml +++ b/tools/bin/main.ml @@ -101,13 +101,12 @@ module Reanalyze = struct "Experimental analyses for ReScript and OCaml: globally dead \ values/types, exception analysis, and termination analysis." in - let version = Reanalyze.Version.version in let man = [ `S Manpage.s_description; `P - "Reanalyze will report all kind of analysis, dead code, exception \ - and termination"; + "Reanalyze command will report all kinds of analysis, dead code \ + (dce), exception and termination"; `S Manpage.s_examples; `I ( "rescript-tools reanalyze", @@ -115,7 +114,7 @@ module Reanalyze = struct `I ("rescript-tools reanalyze --dce", "Report only dead code"); ] in - let info = Cmd.info "reanalyze" ~version ~doc ~man in + let info = Cmd.info "reanalyze" ~doc ~man in let exception_ = let doc =