From a8231cbf3d07df11468a2470c291e05a4fd56bd1 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Sun, 26 Nov 2023 00:02:01 -0300 Subject: [PATCH 01/12] move tools to ocaml code --- .github/workflows/ci.yml | 45 +++++--- .gitignore | 11 +- analysis/.ocamlformat => .ocamlformat | 0 .ocamlformat-ignore | 2 + .vscode/settings.json | 4 +- CONTRIBUTING.md | 31 ++++-- Makefile | 15 +-- .../rescript-vscode.opam => analysis.opam | 7 +- analysis/.ocamlformat-ignore | 2 - analysis/.vscode/settings.json | 11 -- analysis/.vscode/tasks.json | 5 - analysis/Makefile | 23 +--- analysis/README.md | 7 +- analysis/bin/dune | 6 ++ analysis/{src/Cli.ml => bin/main.ml} | 2 + analysis/dune | 2 +- analysis/src/dune | 8 +- analysis/tests/test.sh | 4 +- analysis/dune-project => dune-project | 23 ++-- server/src/constants.ts | 1 - tools.opam | 28 +++++ tools/bin/dune | 9 ++ tools/bin/main.ml | 54 ++++++++++ .../{analysis_binaries => binaries}/.gitkeep | 0 tools/dune | 1 + tools/package-lock.json | 17 +-- tools/package.json | 8 +- tools/rescript.json | 2 +- tools/src/Cli.res | 102 ------------------ tools/src/Cli.resi | 1 - tools/src/cli.js | 23 ++++ 31 files changed, 242 insertions(+), 212 deletions(-) rename analysis/.ocamlformat => .ocamlformat (100%) create mode 100644 .ocamlformat-ignore rename analysis/rescript-vscode.opam => analysis.opam (78%) delete mode 100644 analysis/.ocamlformat-ignore delete mode 100644 analysis/.vscode/settings.json delete mode 100644 analysis/.vscode/tasks.json create mode 100644 analysis/bin/dune rename analysis/{src/Cli.ml => bin/main.ml} (99%) rename analysis/dune-project => dune-project (52%) create mode 100644 tools.opam create mode 100644 tools/bin/dune create mode 100644 tools/bin/main.ml rename tools/{analysis_binaries => binaries}/.gitkeep (100%) create mode 100644 tools/dune delete mode 100644 tools/src/Cli.res delete mode 100644 tools/src/Cli.resi create mode 100755 tools/src/cli.js diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 195a08734..b020facec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,23 +68,25 @@ jobs: # - run: opam pin add rescript-editor-analysis.dev . --no-action # - run: opam install . --deps-only --with-doc --with-test - - name: Build and test + - name: Build + run: opam exec -- make + + - name: Test run: opam exec -- make test - working-directory: analysis # Also avoids artifacts upload permission loss: # https://github.com/actions/upload-artifact/tree/ee69f02b3dfdecd58bb31b4d133da38ba6fe3700#permission-loss - name: Compress files run: | - cd analysis mkdir ${{matrix.artifact-folder}} mv rescript-editor-analysis.exe ${{matrix.artifact-folder}} + mv rescript-tools.exe ${{matrix.artifact-folder}} tar -cvf binary.tar ${{matrix.artifact-folder}} - uses: actions/upload-artifact@v3 with: name: ${{matrix.os}} - path: analysis/binary.tar + path: binary.tar package: needs: test @@ -106,37 +108,51 @@ jobs: uses: actions/download-artifact@v3 with: name: macos-latest - path: ./server/analysis_binaries + path: binaries - run: tar -xvf binary.tar - working-directory: ./server/analysis_binaries + working-directory: binaries - name: Download MacOS ARM binary uses: actions/download-artifact@v3 with: name: macos-arm - path: ./server/analysis_binaries + path: binaries - run: tar -xvf binary.tar - working-directory: ./server/analysis_binaries + working-directory: binaries - name: Download Linux binary uses: actions/download-artifact@v3 with: name: ubuntu-20.04 - path: ./server/analysis_binaries + path: binaries - run: tar -xvf binary.tar - working-directory: ./server/analysis_binaries + working-directory: binaries - name: Download Windows binary uses: actions/download-artifact@v3 with: name: windows-latest - path: ./server/analysis_binaries + path: binaries - run: tar -xvf binary.tar - working-directory: ./server/analysis_binaries + working-directory: binaries - name: Cleanup tar file run: rm binary.tar - working-directory: ./server/analysis_binaries + working-directory: binaries + + - name: Move binaries to folders + run: | + declare -a platforms=("darwin" "darwinarm64" "linux" "win32") + + for platform in "${platforms[@]}"; do + mkdir server/analysis_binaries/"$platform" + mv binaries/"$platform"/rescript-editor-analysis.exe server/analysis_binaries/"$platform" + done + + for platform in "${platforms[@]}"; do + mkdir tools/binaries/"$platform" + mv binaries/"$platform"/rescript-tools.exe tools/binaries/"$platform" + done - name: Store short commit SHA for filename id: vars @@ -221,9 +237,6 @@ jobs: env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - - name: Copy analysis binaries to tools folder - run: cp -r server/analysis_binaries/* tools/analysis_binaries - - name: Build @rescript/tools package working-directory: tools run: | diff --git a/.gitignore b/.gitignore index eec4dd08d..2e774067e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,12 +2,17 @@ out node_modules examples/*/lib + analysis/tests/lib analysis/tests/.bsb.lock -analysis/_build analysis/tests/.merlin -analysis/rescript-editor-analysis.exe -analysis/_opam + tools/node_modules tools/lib tools/**/*.bs.js + +rescript-editor-analysis.exe +rescript-tools.exe + +_opam/ +_build/ diff --git a/analysis/.ocamlformat b/.ocamlformat similarity index 100% rename from analysis/.ocamlformat rename to .ocamlformat diff --git a/.ocamlformat-ignore b/.ocamlformat-ignore new file mode 100644 index 000000000..a0940f84d --- /dev/null +++ b/.ocamlformat-ignore @@ -0,0 +1,2 @@ +analysis/vendor/compiler-libs-406/* +analysis/vendor/res_outcome_printer/* diff --git a/.vscode/settings.json b/.vscode/settings.json index 11909bf1d..c7e28bd31 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,6 +8,6 @@ }, "ocaml.sandbox": { "kind": "opam", - "switch": "${workspaceFolder:rescript-vscode}/analysis" + "switch": "${workspaceFolder:rescript-vscode}" } -} \ No newline at end of file +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 21824c676..cdfe7b9f8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,14 +10,21 @@ Thanks for your interest. Below is an informal spec of how the plugin's server c │ └── src │ └── extension.ts // Language Client entry point ├── analysis // Native binary powering hover, autocomplete, etc. -│ ├── src -│ └── rescript-editor-analysis.exe // Dev-time analysis binary +│ ├── src // Analysis library +│ ├── bin // Analysis binary ├── package.json // The extension manifest -└── server // Language Server. Usable standalone - ├── src - │ ├── server.ts // Language Server Module - │ ├── cli.ts // LSP CLI - └── analysis_binaries // Prod-time platform-specific analysis binaries +├── server // Language Server. Usable standalone +│ ├── src +│ │ ├── server.ts // Language Server Module +│ │ ├── cli.ts // LSP CLI +│ └── analysis_binaries // Prod-time platform-specific analysis binaries +│ ├── darwin +│ ├── linux +│ └── win32 +└── tools // ReScript Tools + ├── bin // OCaml Binary + ├── src // ReScript Tools library + └── binaries // Prod-time platform-specific binaries ├── darwin ├── linux └── win32 @@ -27,9 +34,11 @@ Thanks for your interest. Below is an informal spec of how the plugin's server c - Run `npm install` at the root. This will also install the npm modules for both the `client` and `server` folders. -## Analysis Binary +## OCaml Code + +This is needed for the `analysis` and `tools` folder, which is native code. -This is needed for the `analysis` folder, which is native code. +At the root: ```sh # If you haven't created the switch, do it. OPAM(https://opam.ocaml.org) @@ -45,7 +54,7 @@ opam install ocaml-lsp-server ## Build & Run - `npm run compile`. You don't need this if you're developing this repo in VSCode. The compilation happens automatically in the background. -- `cd analysis && make`. +- `make`. ## Test @@ -214,4 +223,4 @@ For beta releases, ask folks to use the pre-release version installable from the ## Releasing the `@rescript/tools` package -The tools package is released by bumping the version in `tools/package.json`, running `npm i` in the `tools/` folder, and then pushing those changes with the commit message `publish tools`. +The tools package is released by bumping the version in `tools/package.json` and `tools/bin/main/ml`, running `npm i` in the `tools/` folder, and then pushing those changes with the commit message `publish tools`. diff --git a/Makefile b/Makefile index dd56cd9b3..4519c3874 100644 --- a/Makefile +++ b/Makefile @@ -1,19 +1,22 @@ SHELL = /bin/bash build: - make -C analysis build - -clean: - make -C analysis clean + dune build + cp _build/install/default/bin/rescript-editor-analysis rescript-editor-analysis.exe + cp _build/install/default/bin/rescript-tools rescript-tools.exe test: make -C analysis test +clean: + dune clean + make -C analysis clean + format: - make -C analysis format + dune build @fmt --auto-promote checkformat: - make -C analysis checkformat + dune build @fmt .DEFAULT_GOAL := build diff --git a/analysis/rescript-vscode.opam b/analysis.opam similarity index 78% rename from analysis/rescript-vscode.opam rename to analysis.opam index 1645dea53..f016255c4 100644 --- a/analysis/rescript-vscode.opam +++ b/analysis.opam @@ -1,15 +1,14 @@ # This file is generated by dune, edit dune-project instead opam-version: "2.0" -synopsis: "ReScript vscode support" -maintainer: ["Cristiano Calcagno"] -authors: ["Cristiano Calcagno"] +synopsis: "ReScript Analysis" +maintainer: ["ReScript Team"] +authors: ["ReScript Team"] homepage: "https://github.com/rescript-lang/rescript-vscode" bug-reports: "https://github.com/rescript-lang/rescript-vscode/issues" depends: [ "ocaml" {>= "4.10"} "ocamlformat" {= "0.22.4"} "cppo" {= "1.6.9"} - "reanalyze" {= "2.23.0"} "dune" ] build: [ diff --git a/analysis/.ocamlformat-ignore b/analysis/.ocamlformat-ignore deleted file mode 100644 index 841c7c180..000000000 --- a/analysis/.ocamlformat-ignore +++ /dev/null @@ -1,2 +0,0 @@ -vendor/compiler-libs-406/* -vendor/res_outcome_printer/* diff --git a/analysis/.vscode/settings.json b/analysis/.vscode/settings.json deleted file mode 100644 index 290cb9031..000000000 --- a/analysis/.vscode/settings.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "editor.formatOnSave": false, - "git.ignoreLimitWarning": true, - "git.enabled": true, - "editor.codeLens": true, - "editor.tabSize": 2, - "workbench.settings.editor": "json", - "ocaml.sandbox": { - "kind": "global" - } -} diff --git a/analysis/.vscode/tasks.json b/analysis/.vscode/tasks.json deleted file mode 100644 index 462911f2c..000000000 --- a/analysis/.vscode/tasks.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - ] -} \ No newline at end of file diff --git a/analysis/Makefile b/analysis/Makefile index 069dbbbe4..a29bdbd81 100644 --- a/analysis/Makefile +++ b/analysis/Makefile @@ -1,41 +1,26 @@ SHELL = /bin/bash -build-analysis-binary: - rm -f rescript-editor-analysis.exe - dune build - cp _build/install/default/bin/rescript-editor-analysis rescript-editor-analysis.exe - build-tests: make -C tests build build-reanalyze: make -C reanalyze build -build: build-analysis-binary build-reanalyze build-tests +build: build-reanalyze build-tests dce: build-analysis-binary opam exec reanalyze.exe -- -dce-cmt _build -suppress vendor -format: - dune build @fmt --auto-promote - -test-analysis-binary: build-analysis-binary +test-analysis-binary: make -C tests test -test-reanalyze: build-analysis-binary +test-reanalyze: make -C reanalyze test test: test-analysis-binary test-reanalyze clean: - rm -f rescript-editor-analysis.exe - dune clean make -C tests clean make -C reanalyze clean -checkformat: - dune build @fmt - -.DEFAULT_GOAL := build - -.PHONY: build-analysis-binary build-reanalyze build-tests dce clean format test +.PHONY: build-reanalyze build-tests dce clean test diff --git a/analysis/README.md b/analysis/README.md index 73e453e26..2ce1bf5a2 100644 --- a/analysis/README.md +++ b/analysis/README.md @@ -1,4 +1,4 @@ -# Analysis Binary +# Analysis Library and Binary This subfolder builds a private command line binary used by the plugin to power a few functionalities such as jump to definition, hover and autocomplete. @@ -12,8 +12,13 @@ See main CONTRIBUTING.md's repo structure. Additionally, `examples/` is a conven ## Usage +At root: ```sh ./rescript-editor-analysis.exe --help + +# or + +dune exec -- rescript-editor-analysis --help ``` ## History diff --git a/analysis/bin/dune b/analysis/bin/dune new file mode 100644 index 000000000..94665f5d1 --- /dev/null +++ b/analysis/bin/dune @@ -0,0 +1,6 @@ +(executable + (public_name rescript-editor-analysis) + (package analysis) + (modes byte exe) + (name main) + (libraries analysis)) diff --git a/analysis/src/Cli.ml b/analysis/bin/main.ml similarity index 99% rename from analysis/src/Cli.ml rename to analysis/bin/main.ml index a7529b705..fa026ac8d 100644 --- a/analysis/src/Cli.ml +++ b/analysis/bin/main.ml @@ -1,3 +1,5 @@ +open Analysis + let help = {| **Private CLI For rescript-vscode usage only** diff --git a/analysis/dune b/analysis/dune index 5ce956be5..6b297d2e5 100644 --- a/analysis/dune +++ b/analysis/dune @@ -1,4 +1,4 @@ -(dirs src reanalyze vendor) +(dirs bin src reanalyze vendor) (env (dev diff --git a/analysis/src/dune b/analysis/src/dune index bc16552c3..c1bd828c1 100644 --- a/analysis/src/dune +++ b/analysis/src/dune @@ -1,9 +1,5 @@ -(executable - (public_name rescript-editor-analysis) - (modes byte exe) - ; The main module that will become the binary. - (name Cli) +(library + (name analysis) (flags (-w "+6+26+27+32+33+39")) - ; Depends on: (libraries unix str ext ml jsonlib syntax reanalyze)) diff --git a/analysis/tests/test.sh b/analysis/tests/test.sh index e511a49ec..71a43c26e 100755 --- a/analysis/tests/test.sh +++ b/analysis/tests/test.sh @@ -1,6 +1,6 @@ for file in src/*.{res,resi}; do output="$(dirname $file)/expected/$(basename $file).txt" - ../rescript-editor-analysis.exe test $file &> $output + ../../rescript-editor-analysis.exe test $file &> $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 @@ -9,7 +9,7 @@ done for file in not_compiled/*.{res,resi}; do output="$(dirname $file)/expected/$(basename $file).txt" - ../rescript-editor-analysis.exe test $file &> $output + ../../rescript-editor-analysis.exe test $file &> $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/dune-project b/dune-project similarity index 52% rename from analysis/dune-project rename to dune-project index 47a122217..027fee0bc 100644 --- a/analysis/dune-project +++ b/dune-project @@ -2,17 +2,17 @@ (generate_opam_files true) -(authors "Cristiano Calcagno") +(authors "ReScript Team") -(maintainers "Cristiano Calcagno") +(maintainers "ReScript Team") (homepage "https://github.com/rescript-lang/rescript-vscode") (bug_reports "https://github.com/rescript-lang/rescript-vscode/issues") (package - (name rescript-vscode) - (synopsis "ReScript vscode support") + (name analysis) + (synopsis "ReScript Analysis") (depends (ocaml (>= 4.10)) @@ -20,6 +20,17 @@ (= 0.22.4)) (cppo (= 1.6.9)) - (reanalyze - (= 2.23.0)) + dune)) + +(package + (name tools) + (synopsis "ReScript Tools") + (depends + (ocaml + (>= 4.10)) + (ocamlformat + (= 0.22.4)) + (cppo + (= 1.6.9)) + analysis dune)) diff --git a/server/src/constants.ts b/server/src/constants.ts index 8fc2a1214..fd6e29472 100644 --- a/server/src/constants.ts +++ b/server/src/constants.ts @@ -18,7 +18,6 @@ export let bscNativeReScriptPartialPath = path.join( export let analysisDevPath = path.join( path.dirname(__dirname), "..", - "analysis", "rescript-editor-analysis.exe" ); export let analysisProdPath = path.join( diff --git a/tools.opam b/tools.opam new file mode 100644 index 000000000..87aa770c7 --- /dev/null +++ b/tools.opam @@ -0,0 +1,28 @@ +# This file is generated by dune, edit dune-project instead +opam-version: "2.0" +synopsis: "ReScript Tools" +maintainer: ["ReScript Team"] +authors: ["ReScript Team"] +homepage: "https://github.com/rescript-lang/rescript-vscode" +bug-reports: "https://github.com/rescript-lang/rescript-vscode/issues" +depends: [ + "ocaml" {>= "4.10"} + "ocamlformat" {= "0.22.4"} + "cppo" {= "1.6.9"} + "analysis" + "dune" +] +build: [ + ["dune" "subst"] {pinned} + [ + "dune" + "build" + "-p" + name + "-j" + jobs + "@install" + "@runtest" {with-test} + "@doc" {with-doc} + ] +] diff --git a/tools/bin/dune b/tools/bin/dune new file mode 100644 index 000000000..f13369a47 --- /dev/null +++ b/tools/bin/dune @@ -0,0 +1,9 @@ +(executable + (public_name rescript-tools) + (package tools) + (modes byte exe) + ; The main module that will become the binary. + (name main) + (libraries analysis) + (flags + (-w "+6+26+27+32+33+39"))) diff --git a/tools/bin/main.ml b/tools/bin/main.ml new file mode 100644 index 000000000..ce53d3517 --- /dev/null +++ b/tools/bin/main.ml @@ -0,0 +1,54 @@ +(* Update here and package.json *) +let version = "0.1.1" + +let docHelp = + {|ReScript Tools + +Output documentation to standard output + +Usage: rescript-tools doc + +Example: rescript-tools doc ./path/to/EntryPointLib.res|} + +let help = + {|ReScript Tools + +Usage: rescript-tools [command] + +Commands: + +doc Generate documentation +reanalyze Reanalyze +-v, --version Print version +-h, --help Print help|} + +type exitCode = [`Ok | `Error] + +let logAndExit ~log ~code = + print_endline log |> ignore; + let code = + match code with + | `Ok -> 0 + | `Error -> 1 + in + exit code + +let main () = + match Sys.argv |> Array.to_list |> List.tl with + | "doc" :: rest -> ( + match rest with + | ["-h"] | ["--help"] -> logAndExit ~log:docHelp ~code:`Ok + | [path] -> Analysis.DocExtraction.extractDocs ~path ~debug:false + | _ -> logAndExit ~log:docHelp ~code:`Error) + | "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 ~log:help ~code:`Ok + | ["-v"] | ["--version"] -> logAndExit ~log:version ~code:`Ok + | _ -> logAndExit ~log:help ~code:`Error + +let () = main () diff --git a/tools/analysis_binaries/.gitkeep b/tools/binaries/.gitkeep similarity index 100% rename from tools/analysis_binaries/.gitkeep rename to tools/binaries/.gitkeep diff --git a/tools/dune b/tools/dune new file mode 100644 index 000000000..c3308ddde --- /dev/null +++ b/tools/dune @@ -0,0 +1 @@ +(dirs bin) diff --git a/tools/package-lock.json b/tools/package-lock.json index 788f84642..5c5993631 100644 --- a/tools/package-lock.json +++ b/tools/package-lock.json @@ -7,21 +7,22 @@ "": { "name": "@rescript/tools", "version": "0.1.1", + "hasInstallScript": true, "license": "MIT", "dependencies": { - "rescript": "^11.0.0-rc.4" + "rescript": "^11.0.0-rc.6" }, "bin": { - "rescript-tools": "src/Cli.bs.js" + "rescript-tools": "bin/rescript-tools" }, "engines": { "node": "*" } }, "node_modules/rescript": { - "version": "11.0.0-rc.4", - "resolved": "https://registry.npmjs.org/rescript/-/rescript-11.0.0-rc.4.tgz", - "integrity": "sha512-yh82o30J2/B/IwyPZjM+mc82FdyPkXRjXxlsUVEoyc5Z/snlq3Za2PhJhlfacwk+ui5lcOZsH8SndWPiI21vXg==", + "version": "11.0.0-rc.6", + "resolved": "https://registry.npmjs.org/rescript/-/rescript-11.0.0-rc.6.tgz", + "integrity": "sha512-2nqdpQxLgQGNp0Rb8AFn5cM3kwRTd54zLvchqCsK3iLOe1CJwdVW5nEF7lsJbFTqihl8W6Va1y7SbFxY3FNxOQ==", "hasInstallScript": true, "bin": { "bsc": "bsc", @@ -35,9 +36,9 @@ }, "dependencies": { "rescript": { - "version": "11.0.0-rc.4", - "resolved": "https://registry.npmjs.org/rescript/-/rescript-11.0.0-rc.4.tgz", - "integrity": "sha512-yh82o30J2/B/IwyPZjM+mc82FdyPkXRjXxlsUVEoyc5Z/snlq3Za2PhJhlfacwk+ui5lcOZsH8SndWPiI21vXg==" + "version": "11.0.0-rc.6", + "resolved": "https://registry.npmjs.org/rescript/-/rescript-11.0.0-rc.6.tgz", + "integrity": "sha512-2nqdpQxLgQGNp0Rb8AFn5cM3kwRTd54zLvchqCsK3iLOe1CJwdVW5nEF7lsJbFTqihl8W6Va1y7SbFxY3FNxOQ==" } } } diff --git a/tools/package.json b/tools/package.json index 5d9fe76ea..3f2b189ae 100644 --- a/tools/package.json +++ b/tools/package.json @@ -5,7 +5,7 @@ "author": "ReScript Team", "license": "MIT", "bin": { - "rescript-tools": "./src/Cli.bs.js" + "rescript-tools": "src/cli.js" }, "keywords": [ "ReScript", @@ -13,10 +13,10 @@ "Docgen" ], "files": [ - "src/Cli.bs.js", + "src/cli.js", "src/*.res", "src/*.resi", - "analysis_binaries/", + "binaries", "rescript.json", "README.md" ], @@ -36,6 +36,6 @@ "build": "rescript build" }, "dependencies": { - "rescript": "^11.0.0-rc.4" + "rescript": "^11.0.0-rc.6" } } diff --git a/tools/rescript.json b/tools/rescript.json index e064756bd..f7e4fb10b 100644 --- a/tools/rescript.json +++ b/tools/rescript.json @@ -1,6 +1,6 @@ { "name": "@rescript/tools", - "version": "0.1.0", + "version": "0.1.1", "sources": [ { "dir": "src" diff --git a/tools/src/Cli.res b/tools/src/Cli.res deleted file mode 100644 index d4d72b4dd..000000000 --- a/tools/src/Cli.res +++ /dev/null @@ -1,102 +0,0 @@ -@@directive("#!/usr/bin/env node") - -@module("fs") external readFileSync: string => string = "readFileSync" -@variadic @module("path") external join: array => string = "join" -@module("path") external dirname: string => string = "dirname" -@val external __dirname: string = "__dirname" - -module Buffer = { - type t - - @send external toString: t => string = "toString" -} - -type spawnSyncResult = { - stdout: Buffer.t, - stderr: Buffer.t, - status: Js.Null.t, -} -@module("child_process") -external spawnSync: (string, array) => spawnSyncResult = "spawnSync" - -@val @scope("process") -external exit: int => unit = "exit" - -@val -external process: {"arch": string, "platform": string, "argv": array} = "process" - -let argv = process["argv"] - -let args = argv->Js.Array2.slice(~start=2, ~end_=Js.Array2.length(argv)) - -let platformDir = - process["arch"] === "arm64" ? process["platform"] ++ process["arch"] : process["platform"] - -let analysisProdPath = join([ - dirname(__dirname), - "analysis_binaries", - platformDir, - "rescript-editor-analysis.exe", -]) - -let docHelp = `ReScript Tools - -Output documentation to standard output - -Usage: rescript-tools doc - -Example: rescript-tools doc ./path/to/EntryPointLib.res` - -let help = `ReScript Tools - -Usage: rescript-tools [command] - -Commands: - -doc Generate documentation -reanalyze Reanalyze --v, --version Print version --h, --help Print help` - -let logAndExit = (~log, ~code) => { - Js.log(log) - exit(code) -} - -switch args->Belt.List.fromArray { -| list{"doc", ...rest} => - switch rest { - | list{"-h" | "--help"} => logAndExit(~log=docHelp, ~code=0) - | list{filePath} => - let spawn = spawnSync(analysisProdPath, ["extractDocs", filePath]) - - switch spawn.status->Js.Null.toOption { - | Some(code) if code !== 0 => logAndExit(~log=spawn.stderr->Buffer.toString, ~code) - | Some(code) => logAndExit(~log=spawn.stdout->Buffer.toString, ~code) - | None => logAndExit(~log=`error: unexpected error to extract docs for ${filePath}`, ~code=1) - } - | _ => logAndExit(~log=docHelp, ~code=1) - } -| list{"reanalyze", ...rest} => - let args = ["reanalyze"]->Js.Array2.concat(Belt.List.toArray(rest)) - let spawn = spawnSync(analysisProdPath, args) - - switch spawn.status->Js.Null.toOption { - | Some(code) if code !== 0 => logAndExit(~log=spawn.stderr->Buffer.toString, ~code) - | Some(code) => logAndExit(~log=spawn.stdout->Buffer.toString, ~code) - | None => - logAndExit( - ~log=`error: unexpected error to run reanalyze with arguments: ${args->Js.Array2.joinWith( - " ", - )}`, - ~code=1, - ) - } -| list{"-h" | "--help"} => logAndExit(~log=help, ~code=0) -| list{"-v" | "--version"} => - switch readFileSync("./package.json")->Js.Json.parseExn->Js.Json.decodeObject { - | None => logAndExit(~log="error: failed to find version in package.json", ~code=1) - | Some(dict) => logAndExit(~log=dict->Js.Dict.unsafeGet("version"), ~code=0) - } -| _ => logAndExit(~log=help, ~code=1) -} diff --git a/tools/src/Cli.resi b/tools/src/Cli.resi deleted file mode 100644 index 8b1378917..000000000 --- a/tools/src/Cli.resi +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tools/src/cli.js b/tools/src/cli.js new file mode 100755 index 000000000..3815c897c --- /dev/null +++ b/tools/src/cli.js @@ -0,0 +1,23 @@ +#!/usr/bin/env node +//@ts-check +"use strict"; + +const child_process = require("child_process"); +const path = require("path"); + +const platformArch = + process.arch === "x64" ? process.platform : process.platform + process.arch; + +const binPath = path.join(__dirname, "..", "binaries", platformArch, "rescript-tools.exe"); + +const args = process.argv.slice(2); + +const spawn = child_process.spawnSync(binPath, args); + +if (spawn.status !== 0) { + console.log(spawn.stderr.toString().trim()); + process.exit(spawn.status || 1); +} else { + console.log(spawn.stdout.toString().trim()); + process.exit(0) +} From b60b56d3db9f395eef6a53707945a40a05f6be37 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Sun, 26 Nov 2023 00:46:34 -0300 Subject: [PATCH 02/12] update .vscodeignore --- .vscodeignore | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.vscodeignore b/.vscodeignore index aa75b64a6..8e6c65bd1 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -8,3 +8,9 @@ contributing.md server/node_modules/.bin node_modules/.bin analysis/ +tools/ +dune-project +analysis.opam +tools.opam +.ocamlformat +.ocamlformat-ignore From 05b87407adb859d378f889886634c238a24e06c7 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Mon, 18 Dec 2023 21:13:29 -0300 Subject: [PATCH 03/12] add script update version --- CONTRIBUTING.md | 2 +- analysis/bin/main.ml | 8 +------- scripts/updateVersion.js | 24 ++++++++++++++++++++++++ tools/bin/main.ml | 12 +++++++++--- tools/bin/version.ml | 1 + tools/rescript.json | 4 ++-- tools/src/cli.js | 10 +++------- 7 files changed, 41 insertions(+), 20 deletions(-) create mode 100644 scripts/updateVersion.js create mode 100644 tools/bin/version.ml diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cdfe7b9f8..d17ea2363 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -223,4 +223,4 @@ For beta releases, ask folks to use the pre-release version installable from the ## Releasing the `@rescript/tools` package -The tools package is released by bumping the version in `tools/package.json` and `tools/bin/main/ml`, running `npm i` in the `tools/` folder, and then pushing those changes with the commit message `publish tools`. +The tools package is released by bumping the version in `tools/package.json` and run `node scripts/updateVersion.js`, running `npm i` in the `tools/` folder, and then pushing those changes with the commit message `publish tools`. diff --git a/analysis/bin/main.ml b/analysis/bin/main.ml index 94a9b51db..6674d5c8e 100644 --- a/analysis/bin/main.ml +++ b/analysis/bin/main.ml @@ -145,13 +145,7 @@ let main () = ~pos:(int_of_string line_start, int_of_string line_end) ~maxLength ~debug | [_; "codeLens"; path] -> Commands.codeLens ~path ~debug - | [_; "extractDocs"; path] -> - - let () = match Sys.getenv_opt "FROM_COMPILER" with - | Some("true") -> Cfg.isDocGenFromCompiler := true - | _ -> () in - - DocExtraction.extractDocs ~path ~debug + | [_; "extractDocs"; path] -> DocExtraction.extractDocs ~path ~debug | [_; "codeAction"; path; startLine; startCol; endLine; endCol; currentFile] -> Commands.codeAction ~path diff --git a/scripts/updateVersion.js b/scripts/updateVersion.js new file mode 100644 index 000000000..3f9f69bc6 --- /dev/null +++ b/scripts/updateVersion.js @@ -0,0 +1,24 @@ +//@ts-check +// This file is used only in dev time +// Bump version in package.json and this script will update version in ml file +// and rescript.json + +const fs = require("fs"); +const path = require("path"); + +const toolsPkgDir = path.join(__dirname, "..", "tools"); + +const { version } = JSON.parse( + fs.readFileSync(path.join(toolsPkgDir, "package.json"), "utf8"), +); + +const rescriptJsonPath = path.join(toolsPkgDir, "rescript.json"); + +const rescriptJson = JSON.parse(fs.readFileSync(rescriptJsonPath, "utf8")); +rescriptJson.version = version; +fs.writeFileSync(rescriptJsonPath, JSON.stringify(rescriptJson, null, 2)); + +fs.writeFileSync( + path.join(toolsPkgDir, "bin", "version.ml"), + `let version = "${version}"`, +); diff --git a/tools/bin/main.ml b/tools/bin/main.ml index ce53d3517..3ef3a0712 100644 --- a/tools/bin/main.ml +++ b/tools/bin/main.ml @@ -1,6 +1,4 @@ (* Update here and package.json *) -let version = "0.1.1" - let docHelp = {|ReScript Tools @@ -33,12 +31,20 @@ let logAndExit ~log ~code = in exit code +let version = Version.version + let main () = match Sys.argv |> Array.to_list |> List.tl with | "doc" :: rest -> ( match rest with | ["-h"] | ["--help"] -> logAndExit ~log:docHelp ~code:`Ok - | [path] -> Analysis.DocExtraction.extractDocs ~path ~debug:false + | [path] -> ( + (* NOTE: Internal use to generate docs from compiler *) + let () = match Sys.getenv_opt "FROM_COMPILER" with + | Some("true") -> Analysis.Cfg.isDocGenFromCompiler := true + | _ -> () in + Analysis.DocExtraction.extractDocs ~path ~debug:false + ) | _ -> logAndExit ~log:docHelp ~code:`Error) | "reanalyze" :: _ -> let len = Array.length Sys.argv in diff --git a/tools/bin/version.ml b/tools/bin/version.ml new file mode 100644 index 000000000..36ca949bb --- /dev/null +++ b/tools/bin/version.ml @@ -0,0 +1 @@ +let version = "0.3.0" \ No newline at end of file diff --git a/tools/rescript.json b/tools/rescript.json index 3673429fe..3b5361df8 100644 --- a/tools/rescript.json +++ b/tools/rescript.json @@ -1,6 +1,6 @@ { "name": "@rescript/tools", - "version": "0.2.0", + "version": "0.3.0", "sources": [ { "dir": "src" @@ -11,4 +11,4 @@ "module": "commonjs", "in-source": true } -} +} \ No newline at end of file diff --git a/tools/src/cli.js b/tools/src/cli.js index 3815c897c..7f3dc4312 100755 --- a/tools/src/cli.js +++ b/tools/src/cli.js @@ -12,12 +12,8 @@ const binPath = path.join(__dirname, "..", "binaries", platformArch, "rescript-t const args = process.argv.slice(2); -const spawn = child_process.spawnSync(binPath, args); +const spawn = child_process.spawnSync(binPath, args, { stdio: "inherit" }); -if (spawn.status !== 0) { - console.log(spawn.stderr.toString().trim()); - process.exit(spawn.status || 1); -} else { - console.log(spawn.stdout.toString().trim()); - process.exit(0) +if (spawn.status != null) { + process.exit(spawn.status) } From ad547b4f674b10783d2aa4a1511aa14c9a4fcf71 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Mon, 18 Dec 2023 21:23:45 -0300 Subject: [PATCH 04/12] more updates --- .vscodeignore | 1 + CHANGELOG.md | 4 ++++ CONTRIBUTING.md | 9 ++++----- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.vscodeignore b/.vscodeignore index 8e6c65bd1..a2ba46c12 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -9,6 +9,7 @@ server/node_modules/.bin node_modules/.bin analysis/ tools/ +scripts/ dune-project analysis.opam tools.opam diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b8691cd1..ad185099f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ ## master +#### :house: Internal + +- Move `rescript-tools` to OCaml code and make `analysis` an library. https://github.com/rescript-lang/rescript-vscode/pull/855 + ## 1.30.0 #### :rocket: New Feature diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d17ea2363..02aa947ba 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -76,7 +76,7 @@ opam install ocaml-lsp-server image -- For the native analysis binary tests: `cd analysis && make test`. +- For the native analysis binary tests: `make test`. ## Change the Grammar @@ -105,7 +105,7 @@ We call a few binaries and it's tricky to call them properly cross-platform. Her ## General Coding Guidance -- `server/` is a standalone folder that can be vendored by e.g. Vim and Sublime Text. Keep it light, don't add deps unless absolutely necessarily, and don't accidentally use a runtime dep from the top level `package.json`. +- `server/` is a standalone LSP server. Keep it light, don't add deps unless absolutely necessarily, and don't accidentally use a runtime dep from the top level `package.json`. - This codebase stayed alive by not trying to babysit long-living processes. Be fast, call a binary and shut down. ## Rough Description Of How The Plugin Works @@ -206,9 +206,8 @@ We're happy to gather more resources over time here, including more in-depth get _This below will automatically release the LSP package as well._ 1. Bump the version to an _even minor_ version number in `package.json` and `server/package.json` and their lockfiles. It's very important that it's an even minor like `1.8.0`, and not `1.7.0`. This is because even minors are reserved for actual releases, and uneven minors for pre-releases. Commit and push the version bump. -2. Make sure @ryyppy is aware of your changes. He needs to sync them over to the vim plugin. -3. Let CI build your version bump commit. -4. Tag the commit with the version number (e.g. `git tag 1.6.0`) and push the tag (e.g. `git push origin 1.6.0`). Another build will trigger, which should automatically: +2. Let CI build your version bump commit. +3. Tag the commit with the version number (e.g. `git tag 1.6.0`) and push the tag (e.g. `git push origin 1.6.0`). Another build will trigger, which should automatically: - create a `rescript-vscode-.vsix` file - publish that extension version to the VSCode marketplace - create an automatic release on GitHub From bff2928d79d4fb70dcf6aea220b5195f9247d19f Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Sat, 23 Dec 2023 18:25:41 -0300 Subject: [PATCH 05/12] remove ocamlformat dep --- analysis.opam | 1 - dune-project | 4 ---- tools.opam | 1 - 3 files changed, 6 deletions(-) diff --git a/analysis.opam b/analysis.opam index f016255c4..8a6978820 100644 --- a/analysis.opam +++ b/analysis.opam @@ -7,7 +7,6 @@ homepage: "https://github.com/rescript-lang/rescript-vscode" bug-reports: "https://github.com/rescript-lang/rescript-vscode/issues" depends: [ "ocaml" {>= "4.10"} - "ocamlformat" {= "0.22.4"} "cppo" {= "1.6.9"} "dune" ] diff --git a/dune-project b/dune-project index 027fee0bc..e3e04789b 100644 --- a/dune-project +++ b/dune-project @@ -16,8 +16,6 @@ (depends (ocaml (>= 4.10)) - (ocamlformat - (= 0.22.4)) (cppo (= 1.6.9)) dune)) @@ -28,8 +26,6 @@ (depends (ocaml (>= 4.10)) - (ocamlformat - (= 0.22.4)) (cppo (= 1.6.9)) analysis diff --git a/tools.opam b/tools.opam index 87aa770c7..3dbdc6f1d 100644 --- a/tools.opam +++ b/tools.opam @@ -7,7 +7,6 @@ homepage: "https://github.com/rescript-lang/rescript-vscode" bug-reports: "https://github.com/rescript-lang/rescript-vscode/issues" depends: [ "ocaml" {>= "4.10"} - "ocamlformat" {= "0.22.4"} "cppo" {= "1.6.9"} "analysis" "dune" From 233c664cb6e9e22f9a1e93b4b02078722c87f0e3 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Wed, 10 Jan 2024 19:48:29 -0300 Subject: [PATCH 06/12] add tests --- .gitignore | 4 +- Makefile | 2 + analysis.opam | 1 - analysis/bin/main.ml | 8 - analysis/src/Commands.ml | 3 - dune-project | 2 - tools/Makefile | 17 + tools/bin/dune | 2 +- tools/bin/main.ml | 13 +- tools/dune | 1 - tools/npm/RescriptTools.bs.js | 8 + tools/{src => npm}/RescriptTools.res | 0 tools/npm/Tools_Docgen.bs.js | 440 ++++++++++++++++++ tools/{src => npm}/Tools_Docgen.res | 0 tools/{src => npm}/Tools_Docgen.resi | 0 tools/{src => npm}/cli.js | 0 tools/package-lock.json | 2 +- tools/package.json | 8 +- tools/rescript.json | 4 +- tools/src/Cli.res | 92 ---- tools/src/dune | 5 + .../DocExtraction.ml => tools/src/tools.ml | 9 +- tools/tests/README.md | 23 + tools/tests/package-lock.json | 92 ++++ tools/tests/package.json | 18 + tools/tests/rescript.json | 13 + .../tests/src/DocExtraction2.res | 0 .../tests/src/DocExtraction2.resi | 0 .../tests/src/DocExtractionRes.res | 0 .../src/expected/DocExtraction2.res.json | 40 ++ .../src/expected/DocExtraction2.resi.json | 40 ++ .../src/expected/DocExtractionRes.res.json | 167 +++++++ tools/tests/test.sh | 21 + 33 files changed, 910 insertions(+), 125 deletions(-) create mode 100644 tools/Makefile delete mode 100644 tools/dune create mode 100644 tools/npm/RescriptTools.bs.js rename tools/{src => npm}/RescriptTools.res (100%) create mode 100644 tools/npm/Tools_Docgen.bs.js rename tools/{src => npm}/Tools_Docgen.res (100%) rename tools/{src => npm}/Tools_Docgen.resi (100%) rename tools/{src => npm}/cli.js (100%) delete mode 100644 tools/src/Cli.res create mode 100644 tools/src/dune rename analysis/src/DocExtraction.ml => tools/src/tools.ml (97%) create mode 100644 tools/tests/README.md create mode 100644 tools/tests/package-lock.json create mode 100644 tools/tests/package.json create mode 100644 tools/tests/rescript.json rename {analysis => tools}/tests/src/DocExtraction2.res (100%) rename {analysis => tools}/tests/src/DocExtraction2.resi (100%) rename {analysis => tools}/tests/src/DocExtractionRes.res (100%) create mode 100644 tools/tests/src/expected/DocExtraction2.res.json create mode 100644 tools/tests/src/expected/DocExtraction2.resi.json create mode 100644 tools/tests/src/expected/DocExtractionRes.res.json create mode 100755 tools/tests/test.sh diff --git a/.gitignore b/.gitignore index 2e774067e..be3459b4b 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,9 @@ analysis/tests/.merlin tools/node_modules tools/lib -tools/**/*.bs.js +tools/**/*.res.js +tools/tests/node_modules +tools/tests/lib rescript-editor-analysis.exe rescript-tools.exe diff --git a/Makefile b/Makefile index 4519c3874..5c904753c 100644 --- a/Makefile +++ b/Makefile @@ -7,10 +7,12 @@ build: test: make -C analysis test + make -C tools test clean: dune clean make -C analysis clean + make -C tools clean format: dune build @fmt --auto-promote diff --git a/analysis.opam b/analysis.opam index f6da17149..8a6978820 100644 --- a/analysis.opam +++ b/analysis.opam @@ -7,7 +7,6 @@ homepage: "https://github.com/rescript-lang/rescript-vscode" bug-reports: "https://github.com/rescript-lang/rescript-vscode/issues" depends: [ "ocaml" {>= "4.10"} - "ocamlformat" {= "0.26.1"} "cppo" {= "1.6.9"} "dune" ] diff --git a/analysis/bin/main.ml b/analysis/bin/main.ml index 21b49d858..9d44434b4 100644 --- a/analysis/bin/main.ml +++ b/analysis/bin/main.ml @@ -145,14 +145,6 @@ let main () = ~pos:(int_of_string line_start, int_of_string line_end) ~maxLength ~debug | [_; "codeLens"; path] -> Commands.codeLens ~path ~debug - | [_; "extractDocs"; path] -> - let () = - match Sys.getenv_opt "FROM_COMPILER" with - | Some "true" -> Cfg.isDocGenFromCompiler := true - | _ -> () - in - - DocExtraction.extractDocs ~path ~debug | [_; "codeAction"; path; startLine; startCol; endLine; endCol; currentFile] -> Commands.codeAction ~path diff --git a/analysis/src/Commands.ml b/analysis/src/Commands.ml index 3a91151cc..bfb9dc3c2 100644 --- a/analysis/src/Commands.ml +++ b/analysis/src/Commands.ml @@ -347,9 +347,6 @@ let test ~path = let currentFile = createCurrentFile () in signatureHelp ~path ~pos:(line, col) ~currentFile ~debug:true; Sys.remove currentFile - | "dex" -> - print_endline ("Documentation extraction " ^ path); - DocExtraction.extractDocs ~path ~debug:true | "int" -> print_endline ("Create Interface " ^ path); let cmiFile = diff --git a/dune-project b/dune-project index 950779dc9..e3e04789b 100644 --- a/dune-project +++ b/dune-project @@ -16,8 +16,6 @@ (depends (ocaml (>= 4.10)) - (ocamlformat - (= 0.26.1)) (cppo (= 1.6.9)) dune)) diff --git a/tools/Makefile b/tools/Makefile new file mode 100644 index 000000000..c7a225691 --- /dev/null +++ b/tools/Makefile @@ -0,0 +1,17 @@ +SHELL = /bin/bash + +node_modules/.bin/rescript: + npm install + +build: node_modules/.bin/rescript + node_modules/.bin/rescript + +test: build + cd tests && ./test.sh + +clean: + rm -r node_modules lib + +.DEFAULT_GOAL := test + +.PHONY: clean test diff --git a/tools/bin/dune b/tools/bin/dune index f13369a47..d498e0675 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 analysis) + (libraries tools) (flags (-w "+6+26+27+32+33+39"))) diff --git a/tools/bin/main.ml b/tools/bin/main.ml index 3ef3a0712..83eb24ddb 100644 --- a/tools/bin/main.ml +++ b/tools/bin/main.ml @@ -38,13 +38,14 @@ let main () = | "doc" :: rest -> ( match rest with | ["-h"] | ["--help"] -> logAndExit ~log:docHelp ~code:`Ok - | [path] -> ( + | [path] -> (* NOTE: Internal use to generate docs from compiler *) - let () = match Sys.getenv_opt "FROM_COMPILER" with - | Some("true") -> Analysis.Cfg.isDocGenFromCompiler := true - | _ -> () in - Analysis.DocExtraction.extractDocs ~path ~debug:false - ) + let () = + match Sys.getenv_opt "FROM_COMPILER" with + | Some "true" -> Analysis.Cfg.isDocGenFromCompiler := true + | _ -> () + in + Tools.extractDocs ~path ~debug:false | _ -> logAndExit ~log:docHelp ~code:`Error) | "reanalyze" :: _ -> let len = Array.length Sys.argv in diff --git a/tools/dune b/tools/dune deleted file mode 100644 index c3308ddde..000000000 --- a/tools/dune +++ /dev/null @@ -1 +0,0 @@ -(dirs bin) diff --git a/tools/npm/RescriptTools.bs.js b/tools/npm/RescriptTools.bs.js new file mode 100644 index 000000000..281db50e0 --- /dev/null +++ b/tools/npm/RescriptTools.bs.js @@ -0,0 +1,8 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE +'use strict'; + + +var Docgen; + +exports.Docgen = Docgen; +/* No side effect */ diff --git a/tools/src/RescriptTools.res b/tools/npm/RescriptTools.res similarity index 100% rename from tools/src/RescriptTools.res rename to tools/npm/RescriptTools.res diff --git a/tools/npm/Tools_Docgen.bs.js b/tools/npm/Tools_Docgen.bs.js new file mode 100644 index 000000000..ed123cd7a --- /dev/null +++ b/tools/npm/Tools_Docgen.bs.js @@ -0,0 +1,440 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE +'use strict'; + +var Js_dict = require("rescript/lib/js/js_dict.js"); + +function decodeDocstrings(item) { + var match = Js_dict.get(item, "docstrings"); + if (match !== undefined) { + if (!Array.isArray(match) && (match === null || typeof match !== "object") && typeof match !== "number" && typeof match !== "string" && typeof match !== "boolean") { + return []; + } else if (Array.isArray(match)) { + return match.map(function (s) { + if (!Array.isArray(s) && (s === null || typeof s !== "object") && typeof s !== "number" && typeof s !== "string" && typeof s !== "boolean") { + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "Tools_Docgen.res", + 64, + 13 + ], + Error: new Error() + }; + } + if (typeof s === "string") { + return s; + } + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "Tools_Docgen.res", + 64, + 13 + ], + Error: new Error() + }; + }); + } else { + return []; + } + } else { + return []; + } +} + +function decodeStringByField(item, field) { + var match = Js_dict.get(item, field); + if (match !== undefined && !(!Array.isArray(match) && (match === null || typeof match !== "object") && typeof match !== "number" && typeof match !== "string" && typeof match !== "boolean") && typeof match === "string") { + return match; + } + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "Tools_Docgen.res", + 75, + 9 + ], + Error: new Error() + }; +} + +function decodeDepreacted(item) { + var match = Js_dict.get(item, "deprecated"); + if (match !== undefined && !(!Array.isArray(match) && (match === null || typeof match !== "object") && typeof match !== "number" && typeof match !== "string" && typeof match !== "boolean" || typeof match !== "string")) { + return match; + } + +} + +function decodeDetail(detail) { + if (!Array.isArray(detail) && (detail === null || typeof detail !== "object") && typeof detail !== "number" && typeof detail !== "string" && typeof detail !== "boolean") { + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "Tools_Docgen.res", + 144, + 9 + ], + Error: new Error() + }; + } + if (typeof detail === "object" && !Array.isArray(detail)) { + var match = Js_dict.get(detail, "kind"); + var match$1 = Js_dict.get(detail, "items"); + if (match !== undefined && !(!Array.isArray(match) && (match === null || typeof match !== "object") && typeof match !== "number" && typeof match !== "string" && typeof match !== "boolean") && typeof match === "string" && match$1 !== undefined && !(!Array.isArray(match$1) && (match$1 === null || typeof match$1 !== "object") && typeof match$1 !== "number" && typeof match$1 !== "string" && typeof match$1 !== "boolean") && Array.isArray(match$1)) { + switch (match) { + case "record" : + var items = match$1.map(function (field) { + if (!Array.isArray(field) && (field === null || typeof field !== "object") && typeof field !== "number" && typeof field !== "string" && typeof field !== "boolean") { + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "Tools_Docgen.res", + 104, + 11 + ], + Error: new Error() + }; + } + if (typeof field === "object" && !Array.isArray(field)) { + var name = decodeStringByField(field, "name"); + var docstrings = decodeDocstrings(field); + var signature = decodeStringByField(field, "signature"); + var deprecated = decodeDepreacted(field); + var match = Js_dict.get(field, "optional"); + var optional; + var exit = 0; + if (match !== undefined && !(!Array.isArray(match) && (match === null || typeof match !== "object") && typeof match !== "number" && typeof match !== "string" && typeof match !== "boolean" || typeof match !== "boolean")) { + optional = match; + } else { + exit = 1; + } + if (exit === 1) { + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "Tools_Docgen.res", + 98, + 15 + ], + Error: new Error() + }; + } + return { + name: name, + docstrings: docstrings, + signature: signature, + optional: optional, + deprecated: deprecated + }; + } + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "Tools_Docgen.res", + 104, + 11 + ], + Error: new Error() + }; + }); + return { + kind: "record", + items: items + }; + case "variant" : + var items$1 = match$1.map(function (field) { + if (!Array.isArray(field) && (field === null || typeof field !== "object") && typeof field !== "number" && typeof field !== "string" && typeof field !== "boolean") { + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "Tools_Docgen.res", + 123, + 11 + ], + Error: new Error() + }; + } + if (typeof field === "object" && !Array.isArray(field)) { + var name = decodeStringByField(field, "name"); + var docstrings = decodeDocstrings(field); + var signature = decodeStringByField(field, "signature"); + var deprecated = decodeDepreacted(field); + return { + name: name, + docstrings: docstrings, + signature: signature, + deprecated: deprecated + }; + } + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "Tools_Docgen.res", + 123, + 11 + ], + Error: new Error() + }; + }); + return { + kind: "variant", + items: items$1 + }; + default: + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "Tools_Docgen.res", + 139, + 13 + ], + Error: new Error() + }; + } + } + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "Tools_Docgen.res", + 141, + 11 + ], + Error: new Error() + }; + } + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "Tools_Docgen.res", + 144, + 9 + ], + Error: new Error() + }; +} + +function decodeValue(item) { + var id = decodeStringByField(item, "id"); + var signature = decodeStringByField(item, "signature"); + var name = decodeStringByField(item, "name"); + var deprecated = decodeDepreacted(item); + var docstrings = decodeDocstrings(item); + return { + kind: "value", + id: id, + docstrings: docstrings, + signature: signature, + name: name, + deprecated: deprecated + }; +} + +function decodeType(item) { + var id = decodeStringByField(item, "id"); + var signature = decodeStringByField(item, "signature"); + var name = decodeStringByField(item, "name"); + var deprecated = decodeDepreacted(item); + var docstrings = decodeDocstrings(item); + var field = Js_dict.get(item, "detail"); + var detail = field !== undefined ? decodeDetail(field) : undefined; + return { + kind: "type", + id: id, + docstrings: docstrings, + signature: signature, + name: name, + deprecated: deprecated, + detail: detail + }; +} + +function decodeModuleAlias(item) { + var id = decodeStringByField(item, "id"); + var name = decodeStringByField(item, "name"); + var docstrings = decodeDocstrings(item); + var match = Js_dict.get(item, "items"); + var items; + var exit = 0; + if (match !== undefined && !(!Array.isArray(match) && (match === null || typeof match !== "object") && typeof match !== "number" && typeof match !== "string" && typeof match !== "boolean" || !Array.isArray(match))) { + items = match.map(function (item) { + return decodeItem(item); + }); + } else { + exit = 1; + } + if (exit === 1) { + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "Tools_Docgen.res", + 175, + 9 + ], + Error: new Error() + }; + } + return { + kind: "moduleAlias", + id: id, + docstrings: docstrings, + name: name, + items: items + }; +} + +function decodeModule(item) { + var id = decodeStringByField(item, "id"); + var name = decodeStringByField(item, "name"); + var deprecated = decodeDepreacted(item); + var docstrings = decodeDocstrings(item); + var match = Js_dict.get(item, "items"); + var items; + var exit = 0; + if (match !== undefined && !(!Array.isArray(match) && (match === null || typeof match !== "object") && typeof match !== "number" && typeof match !== "string" && typeof match !== "boolean" || !Array.isArray(match))) { + items = match.map(function (item) { + return decodeItem(item); + }); + } else { + exit = 1; + } + if (exit === 1) { + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "Tools_Docgen.res", + 187, + 9 + ], + Error: new Error() + }; + } + return { + kind: "module", + id: id, + docstrings: docstrings, + deprecated: deprecated, + name: name, + items: items + }; +} + +function decodeItem(item) { + if (!Array.isArray(item) && (item === null || typeof item !== "object") && typeof item !== "number" && typeof item !== "string" && typeof item !== "boolean") { + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "Tools_Docgen.res", + 206, + 9 + ], + Error: new Error() + }; + } + if (typeof item === "object" && !Array.isArray(item)) { + var match = Js_dict.get(item, "kind"); + if (match !== undefined && !(!Array.isArray(match) && (match === null || typeof match !== "object") && typeof match !== "number" && typeof match !== "string" && typeof match !== "boolean") && typeof match === "string") { + switch (match) { + case "module" : + return decodeModule(item); + case "moduleAlias" : + return decodeModuleAlias(item); + case "type" : + return decodeType(item); + case "value" : + return decodeValue(item); + default: + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "Tools_Docgen.res", + 202, + 13 + ], + Error: new Error() + }; + } + } + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "Tools_Docgen.res", + 204, + 11 + ], + Error: new Error() + }; + } + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "Tools_Docgen.res", + 206, + 9 + ], + Error: new Error() + }; +} + +function decodeFromJson(json) { + if (!Array.isArray(json) && (json === null || typeof json !== "object") && typeof json !== "number" && typeof json !== "string" && typeof json !== "boolean") { + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "Tools_Docgen.res", + 236, + 9 + ], + Error: new Error() + }; + } + if (typeof json === "object" && !Array.isArray(json)) { + var name = decodeStringByField(json, "name"); + var deprecated = decodeDepreacted(json); + var docstrings = decodeDocstrings(json); + var match = Js_dict.get(json, "items"); + var items; + var exit = 0; + if (match !== undefined && !(!Array.isArray(match) && (match === null || typeof match !== "object") && typeof match !== "number" && typeof match !== "string" && typeof match !== "boolean" || !Array.isArray(match))) { + items = match.map(function (item) { + return decodeItem(item); + }); + } else { + exit = 1; + } + if (exit === 1) { + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "Tools_Docgen.res", + 230, + 13 + ], + Error: new Error() + }; + } + return { + name: name, + deprecated: deprecated, + docstrings: docstrings, + items: items + }; + } + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "Tools_Docgen.res", + 236, + 9 + ], + Error: new Error() + }; +} + +exports.decodeValue = decodeValue; +exports.decodeType = decodeType; +exports.decodeModule = decodeModule; +exports.decodeModuleAlias = decodeModuleAlias; +exports.decodeItem = decodeItem; +exports.decodeFromJson = decodeFromJson; +/* No side effect */ diff --git a/tools/src/Tools_Docgen.res b/tools/npm/Tools_Docgen.res similarity index 100% rename from tools/src/Tools_Docgen.res rename to tools/npm/Tools_Docgen.res diff --git a/tools/src/Tools_Docgen.resi b/tools/npm/Tools_Docgen.resi similarity index 100% rename from tools/src/Tools_Docgen.resi rename to tools/npm/Tools_Docgen.resi diff --git a/tools/src/cli.js b/tools/npm/cli.js similarity index 100% rename from tools/src/cli.js rename to tools/npm/cli.js diff --git a/tools/package-lock.json b/tools/package-lock.json index 0cf61f051..c56dd869f 100644 --- a/tools/package-lock.json +++ b/tools/package-lock.json @@ -12,7 +12,7 @@ "rescript": "^11.0.0-rc.7" }, "bin": { - "rescript-tools": "bin/rescript-tools" + "rescript-tools": "npm/cli.js" }, "engines": { "node": "*" diff --git a/tools/package.json b/tools/package.json index f3a486e5a..1cc59028f 100644 --- a/tools/package.json +++ b/tools/package.json @@ -5,7 +5,7 @@ "author": "ReScript Team", "license": "MIT", "bin": { - "rescript-tools": "src/cli.js" + "rescript-tools": "npm/cli.js" }, "keywords": [ "ReScript", @@ -13,9 +13,9 @@ "Docgen" ], "files": [ - "src/cli.js", - "src/*.res", - "src/*.resi", + "npm/cli.js", + "npm/*.res", + "npm/*.resi", "binaries", "rescript.json", "README.md" diff --git a/tools/rescript.json b/tools/rescript.json index 3b5361df8..8917b16ec 100644 --- a/tools/rescript.json +++ b/tools/rescript.json @@ -3,7 +3,7 @@ "version": "0.3.0", "sources": [ { - "dir": "src" + "dir": "npm" } ], "suffix": ".bs.js", @@ -11,4 +11,4 @@ "module": "commonjs", "in-source": true } -} \ No newline at end of file +} diff --git a/tools/src/Cli.res b/tools/src/Cli.res deleted file mode 100644 index 6e17a0851..000000000 --- a/tools/src/Cli.res +++ /dev/null @@ -1,92 +0,0 @@ -@@directive("#!/usr/bin/env node") - -@module("fs") external readFileSync: string => string = "readFileSync" -@variadic @module("path") external join: array => string = "join" -@module("path") external dirname: string => string = "dirname" -@val external __dirname: string = "__dirname" - -type processEnvOptions = {stdio?: string} -type spawnSyncResult = {status: Js.Null.t} - -@module("child_process") -external spawnSync: (string, array, option) => spawnSyncResult = - "spawnSync" - -@val @scope("process") -external exit: int => unit = "exit" - -@val -external process: {"arch": string, "platform": string, "argv": array} = "process" - -let argv = process["argv"] - -let args = argv->Js.Array2.slice(~start=2, ~end_=Js.Array2.length(argv)) - -let platformDir = - process["arch"] === "arm64" ? process["platform"] ++ process["arch"] : process["platform"] - -let analysisProdPath = join([ - dirname(__dirname), - "analysis_binaries", - platformDir, - "rescript-editor-analysis.exe", -]) - -let docHelp = `ReScript Tools - -Output documentation to standard output - -Usage: rescript-tools doc - -Example: rescript-tools doc ./path/to/EntryPointLib.res` - -let help = `ReScript Tools - -Usage: rescript-tools [command] - -Commands: - -doc Generate documentation -reanalyze Reanalyze --v, --version Print version --h, --help Print help` - -let logAndExit = (~log, ~code) => { - Js.log(log) - exit(code) -} - -switch args->Belt.List.fromArray { -| list{"doc", ...rest} => - switch rest { - | list{"-h" | "--help"} => logAndExit(~log=docHelp, ~code=0) - | list{filePath} => - let spawn = spawnSync(analysisProdPath, ["extractDocs", filePath], Some({stdio: "inherit"})) - - switch spawn.status->Js.Null.toOption { - | Some(code) => exit(code) - | None => () - } - | _ => logAndExit(~log=docHelp, ~code=1) - } -| list{"reanalyze", ...rest} => - let args = ["reanalyze"]->Js.Array2.concat(Belt.List.toArray(rest)) - let spawn = spawnSync(analysisProdPath, args, Some({stdio: "inherit"})) - - switch spawn.status->Js.Null.toOption { - | Some(code) => exit(code) - | None => () - } -| list{"-h" | "--help"} => logAndExit(~log=help, ~code=0) -| list{"-v" | "--version"} => - let packageJson = join([__dirname, "..", "package.json"]) - switch readFileSync(packageJson)->Js.Json.parseExn->Js.Json.decodeObject { - | None => logAndExit(~log="error: failed to find version in package.json", ~code=1) - | Some(dict) => - switch dict->Js.Dict.get("version") { - | Some(version) => logAndExit(~log=version, ~code=0) - | None => logAndExit(~log="error: failed to find version in package.json", ~code=1) - } - } -| _ => logAndExit(~log=help, ~code=1) -} diff --git a/tools/src/dune b/tools/src/dune new file mode 100644 index 000000000..f124a3737 --- /dev/null +++ b/tools/src/dune @@ -0,0 +1,5 @@ +(library + (name tools) + (flags + (-w "+6+26+27+32+33+39")) + (libraries analysis)) diff --git a/analysis/src/DocExtraction.ml b/tools/src/tools.ml similarity index 97% rename from analysis/src/DocExtraction.ml rename to tools/src/tools.ml index d646bd175..08f17ac49 100644 --- a/analysis/src/DocExtraction.ml +++ b/tools/src/tools.ml @@ -1,3 +1,5 @@ +open Analysis + type fieldDoc = { fieldName: string; docstrings: string list; @@ -117,8 +119,7 @@ let rec stringifyDocItem ?(indentation = 0) ~originalEnv (item : docItem) = match deprecated with | Some d -> Some (wrapInQuotes d) | None -> None ); - ( "signature", - Some (signature |> String.trim |> wrapInQuotes) ); + ("signature", Some (signature |> String.trim |> wrapInQuotes)); ("docstrings", Some (stringifyDocstrings docstring)); ] | Type {id; docstring; signature; name; deprecated; detail} -> @@ -312,7 +313,9 @@ let extractDocs ~path ~debug = id; name = item.name; items; - docstring = item.docstring @ internalDocstrings |> List.map String.trim; + docstring = + item.docstring @ internalDocstrings + |> List.map String.trim; }) | Module (Structure m) -> (* module Whatever = {} in res or module Whatever: {} in resi. *) diff --git a/tools/tests/README.md b/tools/tests/README.md new file mode 100644 index 000000000..b18cb385c --- /dev/null +++ b/tools/tests/README.md @@ -0,0 +1,23 @@ +# ReScript Project Template + +- [Installation](../../README.md) + +Official ReScript starter template. + +## Installation + +```sh +npm install +``` + +## Build + +- Build: `npm run res:build` +- Clean: `npm run res:clean` +- Build & watch: `npm run res:dev` + +## Run + +```sh +node src/Demo.res.js +``` diff --git a/tools/tests/package-lock.json b/tools/tests/package-lock.json new file mode 100644 index 000000000..41294271a --- /dev/null +++ b/tools/tests/package-lock.json @@ -0,0 +1,92 @@ +{ + "name": "docstrings-test", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "docstrings-test", + "version": "0.0.0", + "license": "MIT", + "dependencies": { + "@rescript/react": "^0.12.0-alpha.3", + "rescript": "^11.0.0" + } + }, + "node_modules/@rescript/react": { + "version": "0.12.0-alpha.3", + "resolved": "https://registry.npmjs.org/@rescript/react/-/react-0.12.0-alpha.3.tgz", + "integrity": "sha512-/S1uj77RPDzuLg3Ofb8KKU3Vppqy97/vF6bBdBZ+saIO9bpHVlsmmJyJG8QXjGZKE+aMynrrR3Tj4+9+5OzLdw==", + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "peer": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "peer": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/rescript": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/rescript/-/rescript-11.0.0.tgz", + "integrity": "sha512-uIUwDZZmDUb7ymGkBiiGioxMg8hXh1mze/2k/qhYQcZGgi7PrLHQIW9AksM7gb9WnpjCAvFsA8U2VgC0nA468w==", + "hasInstallScript": true, + "bin": { + "bsc": "bsc", + "bstracing": "lib/bstracing", + "rescript": "rescript" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + } + } + } +} diff --git a/tools/tests/package.json b/tools/tests/package.json new file mode 100644 index 000000000..e8b109e4a --- /dev/null +++ b/tools/tests/package.json @@ -0,0 +1,18 @@ +{ + "name": "docstrings-test", + "version": "0.0.0", + "scripts": { + "res:build": "rescript", + "res:clean": "rescript clean", + "res:dev": "rescript -w" + }, + "keywords": [ + "rescript" + ], + "author": "", + "license": "MIT", + "dependencies": { + "@rescript/react": "^0.12.0-alpha.3", + "rescript": "^11.0.0" + } +} diff --git a/tools/tests/rescript.json b/tools/tests/rescript.json new file mode 100644 index 000000000..c7968f1bf --- /dev/null +++ b/tools/tests/rescript.json @@ -0,0 +1,13 @@ +{ + "name": "docstrings-test", + "sources": { + "dir": "src", + "subdirs": true + }, + "package-specs": { + "module": "commonjs", + "in-source": true + }, + "suffix": ".res.js", + "bs-dependencies": ["@rescript/react"] +} diff --git a/analysis/tests/src/DocExtraction2.res b/tools/tests/src/DocExtraction2.res similarity index 100% rename from analysis/tests/src/DocExtraction2.res rename to tools/tests/src/DocExtraction2.res diff --git a/analysis/tests/src/DocExtraction2.resi b/tools/tests/src/DocExtraction2.resi similarity index 100% rename from analysis/tests/src/DocExtraction2.resi rename to tools/tests/src/DocExtraction2.resi diff --git a/analysis/tests/src/DocExtractionRes.res b/tools/tests/src/DocExtractionRes.res similarity index 100% rename from analysis/tests/src/DocExtractionRes.res rename to tools/tests/src/DocExtractionRes.res diff --git a/tools/tests/src/expected/DocExtraction2.res.json b/tools/tests/src/expected/DocExtraction2.res.json new file mode 100644 index 000000000..214e0cacb --- /dev/null +++ b/tools/tests/src/expected/DocExtraction2.res.json @@ -0,0 +1,40 @@ + +{ + "name": "DocExtraction2", + "docstrings": ["Module level doc here."], + "items": [ + { + "id": "DocExtraction2.t", + "kind": "type", + "name": "t", + "signature": "type t", + "docstrings": ["Type t is pretty cool."] + }, + { + "id": "DocExtraction2.make", + "kind": "value", + "name": "make", + "signature": "let make: (. unit) => t", + "docstrings": ["Makerz of stuffz."] + }, + { + "id": "DocExtraction2.InnerModule", + "name": "InnerModule", + "kind": "module", + "items": [ + { + "id": "DocExtraction2.InnerModule.t", + "kind": "type", + "name": "t", + "signature": "type t", + "docstrings": ["This type is also t."] + }, + { + "id": "DocExtraction2.InnerModule.make", + "kind": "value", + "name": "make", + "signature": "let make: (. unit) => t", + "docstrings": ["Maker of tea."] + }] + }] +} diff --git a/tools/tests/src/expected/DocExtraction2.resi.json b/tools/tests/src/expected/DocExtraction2.resi.json new file mode 100644 index 000000000..214e0cacb --- /dev/null +++ b/tools/tests/src/expected/DocExtraction2.resi.json @@ -0,0 +1,40 @@ + +{ + "name": "DocExtraction2", + "docstrings": ["Module level doc here."], + "items": [ + { + "id": "DocExtraction2.t", + "kind": "type", + "name": "t", + "signature": "type t", + "docstrings": ["Type t is pretty cool."] + }, + { + "id": "DocExtraction2.make", + "kind": "value", + "name": "make", + "signature": "let make: (. unit) => t", + "docstrings": ["Makerz of stuffz."] + }, + { + "id": "DocExtraction2.InnerModule", + "name": "InnerModule", + "kind": "module", + "items": [ + { + "id": "DocExtraction2.InnerModule.t", + "kind": "type", + "name": "t", + "signature": "type t", + "docstrings": ["This type is also t."] + }, + { + "id": "DocExtraction2.InnerModule.make", + "kind": "value", + "name": "make", + "signature": "let make: (. unit) => t", + "docstrings": ["Maker of tea."] + }] + }] +} diff --git a/tools/tests/src/expected/DocExtractionRes.res.json b/tools/tests/src/expected/DocExtractionRes.res.json new file mode 100644 index 000000000..8e716c0b3 --- /dev/null +++ b/tools/tests/src/expected/DocExtractionRes.res.json @@ -0,0 +1,167 @@ + +{ + "name": "DocExtractionRes", + "docstrings": ["Module level documentation goes here."], + "items": [ + { + "id": "DocExtractionRes.t", + "kind": "type", + "name": "t", + "signature": "type t = {name: string, online: bool}", + "docstrings": ["This type represents stuff."], + "detail": + { + "kind": "record", + "items": [{ + "name": "name", + "optional": false, + "docstrings": ["The name of the stuff."], + "signature": "string" + }, { + "name": "online", + "optional": false, + "docstrings": ["Whether stuff is online."], + "signature": "bool" + }] + } + }, + { + "id": "DocExtractionRes.make", + "kind": "value", + "name": "make", + "signature": "let make: (. string) => t", + "docstrings": ["Create stuff.\n\n```rescript example\nlet stuff = make(\"My name\")\n```"] + }, + { + "id": "DocExtractionRes.asOffline", + "kind": "value", + "name": "asOffline", + "signature": "let asOffline: (. t) => t", + "docstrings": ["Stuff goes offline."] + }, + { + "id": "DocExtractionRes.SomeConstant\\", + "kind": "value", + "name": "SomeConstant\\", + "signature": "let SomeConstant\\: int", + "docstrings": ["exotic identifier"] + }, + { + "id": "DocExtractionRes.SomeInnerModule", + "name": "SomeInnerModule", + "kind": "module", + "items": [ + { + "id": "DocExtractionRes.SomeInnerModule.status", + "kind": "type", + "name": "status", + "signature": "type status = Started(t) | Stopped | Idle", + "docstrings": [], + "detail": + { + "kind": "variant", + "items": [ + { + "name": "Started", + "docstrings": ["If this is started or not"], + "signature": "Started(t)" + }, + { + "name": "Stopped", + "docstrings": ["Stopped?"], + "signature": "Stopped" + }, + { + "name": "Idle", + "docstrings": ["Now idle."], + "signature": "Idle" + }] + } + }, + { + "id": "DocExtractionRes.SomeInnerModule.validInputs", + "kind": "type", + "name": "validInputs", + "signature": "type validInputs = [\n | #\"needs-escaping\"\n | #something\n | #status(status)\n | #withPayload(int)\n]", + "docstrings": ["These are all the valid inputs."] + }, + { + "id": "DocExtractionRes.SomeInnerModule.callback", + "kind": "type", + "name": "callback", + "signature": "type callback = (. t, ~status: status) => unit", + "docstrings": [] + }] + }, + { + "id": "DocExtractionRes.AnotherModule", + "name": "AnotherModule", + "kind": "module", + "items": [ + { + "id": "DocExtractionRes.LinkedModule", + "kind": "moduleAlias", + "name": "LinkedModule", + "docstrings": ["This links another module. Neat."], + "items": [] + }, + { + "id": "DocExtractionRes.AnotherModule.callback", + "kind": "type", + "name": "callback", + "signature": "type callback = (. SomeInnerModule.status) => unit", + "docstrings": ["Testing what this looks like."] + }, + { + "id": "DocExtractionRes.AnotherModule.isGoodStatus", + "kind": "value", + "name": "isGoodStatus", + "signature": "let isGoodStatus: (. SomeInnerModule.status) => bool", + "docstrings": [] + }, + { + "id": "DocExtractionRes.AnotherModule.someVariantWithInlineRecords", + "kind": "type", + "name": "someVariantWithInlineRecords", + "signature": "type someVariantWithInlineRecords =\n | SomeStuff({offline: bool})", + "docstrings": ["Trying how it looks with an inline record in a variant."], + "detail": + { + "kind": "variant", + "items": [ + { + "name": "SomeStuff", + "docstrings": ["This has inline records..."], + "signature": "SomeStuff" + }] + } + }, + { + "id": "DocExtractionRes.AnotherModule.domRoot", + "kind": "type", + "name": "domRoot", + "signature": "type domRoot = (. unit) => ReactDOM.Client.Root.t", + "docstrings": ["Callback to get the DOM root..."] + }] + }, + { + "id": "DocExtractionRes.ModuleWithThingsThatShouldNotBeExported", + "name": "ModuleWithThingsThatShouldNotBeExported", + "kind": "module", + "items": [ + { + "id": "DocExtractionRes.ModuleWithThingsThatShouldNotBeExported.t", + "kind": "type", + "name": "t", + "signature": "type t", + "docstrings": ["The type t is stuff."] + }, + { + "id": "DocExtractionRes.ModuleWithThingsThatShouldNotBeExported.make", + "kind": "value", + "name": "make", + "signature": "let make: (. unit) => t", + "docstrings": ["The maker of stuff!"] + }] + }] +} diff --git a/tools/tests/test.sh b/tools/tests/test.sh new file mode 100755 index 000000000..4a002d8f1 --- /dev/null +++ b/tools/tests/test.sh @@ -0,0 +1,21 @@ +for file in src/*.{res,resi}; do + output="$(dirname $file)/expected/$(basename $file).json" + dune exec --no-print-directory -- rescript-tools doc $file > $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 + fi +done + +warningYellow='\033[0;33m' +successGreen='\033[0;32m' +reset='\033[0m' + +diff=$(git ls-files --modified src/expected) +if [[ $diff = "" ]]; then + printf "${successGreen}✅ No unstaged tests difference.${reset}\n" +else + printf "${warningYellow}⚠️ There are unstaged differences in tests/! Did you break a test?\n${diff}\n${reset}" + git --no-pager diff src/expected + exit 1 +fi From a187e44c532a3007476ecd91a8afb6afc6d79220 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Wed, 10 Jan 2024 20:02:44 -0300 Subject: [PATCH 07/12] fix tests --- Makefile | 4 ++-- tools/bin/main.ml | 1 - tools/{ => tests}/Makefile | 2 +- tools/tests/README.md | 23 ----------------------- 4 files changed, 3 insertions(+), 27 deletions(-) rename tools/{ => tests}/Makefile (90%) delete mode 100644 tools/tests/README.md diff --git a/Makefile b/Makefile index 5c904753c..e693761a0 100644 --- a/Makefile +++ b/Makefile @@ -7,12 +7,12 @@ build: test: make -C analysis test - make -C tools test + make -C tools/tests test clean: dune clean make -C analysis clean - make -C tools clean + make -C tools/tests clean format: dune build @fmt --auto-promote diff --git a/tools/bin/main.ml b/tools/bin/main.ml index 83eb24ddb..6e7de372a 100644 --- a/tools/bin/main.ml +++ b/tools/bin/main.ml @@ -1,4 +1,3 @@ -(* Update here and package.json *) let docHelp = {|ReScript Tools diff --git a/tools/Makefile b/tools/tests/Makefile similarity index 90% rename from tools/Makefile rename to tools/tests/Makefile index c7a225691..5084c67ab 100644 --- a/tools/Makefile +++ b/tools/tests/Makefile @@ -7,7 +7,7 @@ build: node_modules/.bin/rescript node_modules/.bin/rescript test: build - cd tests && ./test.sh + ./test.sh clean: rm -r node_modules lib diff --git a/tools/tests/README.md b/tools/tests/README.md deleted file mode 100644 index b18cb385c..000000000 --- a/tools/tests/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# ReScript Project Template - -- [Installation](../../README.md) - -Official ReScript starter template. - -## Installation - -```sh -npm install -``` - -## Build - -- Build: `npm run res:build` -- Clean: `npm run res:clean` -- Build & watch: `npm run res:dev` - -## Run - -```sh -node src/Demo.res.js -``` From 60e0f13a29c75e7f460e816d79f90f0b9dc39333 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Wed, 10 Jan 2024 20:45:02 -0300 Subject: [PATCH 08/12] some refactor --- tools/bin/main.ml | 29 +++--- tools/src/tools.ml | 228 ++++++++++++++++++++++++--------------------- 2 files changed, 133 insertions(+), 124 deletions(-) diff --git a/tools/bin/main.ml b/tools/bin/main.ml index 6e7de372a..f1dc157b1 100644 --- a/tools/bin/main.ml +++ b/tools/bin/main.ml @@ -19,16 +19,13 @@ reanalyze Reanalyze -v, --version Print version -h, --help Print help|} -type exitCode = [`Ok | `Error] - -let logAndExit ~log ~code = - print_endline log |> ignore; - let code = - match code with - | `Ok -> 0 - | `Error -> 1 - in - exit code +let logAndExit = function + | Ok log -> + Printf.printf "%s\n" log; + exit 0 + | Error log -> + Printf.eprintf "%s\n" log; + exit 1 let version = Version.version @@ -36,7 +33,7 @@ let main () = match Sys.argv |> Array.to_list |> List.tl with | "doc" :: rest -> ( match rest with - | ["-h"] | ["--help"] -> logAndExit ~log:docHelp ~code:`Ok + | ["-h"] | ["--help"] -> logAndExit (Ok docHelp) | [path] -> (* NOTE: Internal use to generate docs from compiler *) let () = @@ -44,8 +41,8 @@ let main () = | Some "true" -> Analysis.Cfg.isDocGenFromCompiler := true | _ -> () in - Tools.extractDocs ~path ~debug:false - | _ -> logAndExit ~log:docHelp ~code:`Error) + logAndExit (Tools.extractDocs ~path ~debug:false) + | _ -> logAndExit (Error docHelp)) | "reanalyze" :: _ -> let len = Array.length Sys.argv in for i = 1 to len - 2 do @@ -53,8 +50,8 @@ let main () = done; Sys.argv.(len - 1) <- ""; Reanalyze.cli () - | ["-h"] | ["--help"] -> logAndExit ~log:help ~code:`Ok - | ["-v"] | ["--version"] -> logAndExit ~log:version ~code:`Ok - | _ -> logAndExit ~log:help ~code:`Error + | ["-h"] | ["--help"] -> logAndExit (Ok help) + | ["-v"] | ["--version"] -> logAndExit (Ok version) + | _ -> logAndExit (Error help) let () = main () diff --git a/tools/src/tools.ml b/tools/src/tools.ml index 08f17ac49..97c080c8e 100644 --- a/tools/src/tools.ml +++ b/tools/src/tools.ml @@ -225,113 +225,125 @@ let makeId modulePath ~identifier = let extractDocs ~path ~debug = if debug then Printf.printf "extracting docs for %s\n" path; - if - FindFiles.isImplementation path = false - && FindFiles.isInterface path = false - then ( - Printf.eprintf "error: failed to read %s, expected an .res or .resi file\n" - path; - exit 1); - let path = - if FindFiles.isImplementation path then - let pathAsResi = - (path |> Filename.dirname) ^ "/" - ^ (path |> Filename.basename |> Filename.chop_extension) - ^ ".resi" + let result = + match + FindFiles.isImplementation path = false + && FindFiles.isInterface path = false + with + | false -> ( + let path = + if FindFiles.isImplementation path then + let pathAsResi = + (path |> Filename.dirname) ^ "/" + ^ (path |> Filename.basename |> Filename.chop_extension) + ^ ".resi" + in + if Sys.file_exists pathAsResi then ( + if debug then + Printf.printf "preferring found resi file for impl: %s\n" + pathAsResi; + pathAsResi) + else path + else path in - if Sys.file_exists pathAsResi then ( - if debug then - Printf.printf "preferring found resi file for impl: %s\n" pathAsResi; - pathAsResi) - else path - else path - in - match Cmt.loadFullCmtFromPath ~path with - | None -> - Printf.eprintf - "error: failed to generate doc for %s, try to build the project\n" path; - exit 1 - | Some full -> - let file = full.file in - let structure = file.structure in - let open SharedTypes in - let env = QueryEnv.fromFile file in - let rec extractDocsForModule ?(modulePath = [env.file.moduleName]) - (structure : Module.structure) = - { - id = modulePath |> List.rev |> ident; - docstring = structure.docstring |> List.map String.trim; - name = structure.name; - deprecated = structure.deprecated; - items = - structure.items - |> List.filter_map (fun (item : Module.item) -> - match item.kind with - | Value typ -> - Some - (Value - { - id = modulePath |> makeId ~identifier:item.name; - docstring = item.docstring |> List.map String.trim; - signature = - "let " ^ item.name ^ ": " ^ Shared.typeToString typ; - name = item.name; - deprecated = item.deprecated; - }) - | Type (typ, _) -> - Some - (Type - { - id = modulePath |> makeId ~identifier:item.name; - docstring = item.docstring |> List.map String.trim; - signature = typ.decl |> Shared.declToString item.name; - name = item.name; - deprecated = item.deprecated; - detail = typeDetail typ ~full ~env; - }) - | Module (Ident p) -> - (* module Whatever = OtherModule *) - let aliasToModule = p |> pathIdentToString in - let id = - (modulePath |> List.rev |> List.hd) ^ "." ^ item.name - in - let items, internalDocstrings = - match - ProcessCmt.fileForModule ~package:full.package - aliasToModule - with - | None -> ([], []) - | Some file -> - let docs = - extractDocsForModule ~modulePath:[id] file.structure + match Cmt.loadFullCmtFromPath ~path with + | None -> + Error + (Printf.sprintf + "error: failed to generate doc for %s, try to build the project" + path) + | Some full -> + let file = full.file in + let structure = file.structure in + let open SharedTypes in + let env = QueryEnv.fromFile file in + let rec extractDocsForModule ?(modulePath = [env.file.moduleName]) + (structure : Module.structure) = + { + id = modulePath |> List.rev |> ident; + docstring = structure.docstring |> List.map String.trim; + name = structure.name; + deprecated = structure.deprecated; + items = + structure.items + |> List.filter_map (fun (item : Module.item) -> + match item.kind with + | Value typ -> + Some + (Value + { + id = modulePath |> makeId ~identifier:item.name; + docstring = item.docstring |> List.map String.trim; + signature = + "let " ^ item.name ^ ": " + ^ Shared.typeToString typ; + name = item.name; + deprecated = item.deprecated; + }) + | Type (typ, _) -> + Some + (Type + { + id = modulePath |> makeId ~identifier:item.name; + docstring = item.docstring |> List.map String.trim; + signature = + typ.decl |> Shared.declToString item.name; + name = item.name; + deprecated = item.deprecated; + detail = typeDetail typ ~full ~env; + }) + | Module (Ident p) -> + (* module Whatever = OtherModule *) + let aliasToModule = p |> pathIdentToString in + let id = + (modulePath |> List.rev |> List.hd) ^ "." ^ item.name + in + let items, internalDocstrings = + match + ProcessCmt.fileForModule ~package:full.package + aliasToModule + with + | None -> ([], []) + | Some file -> + let docs = + extractDocsForModule ~modulePath:[id] + file.structure + in + (docs.items, docs.docstring) in - (docs.items, docs.docstring) - in - Some - (ModuleAlias - { - id; - name = item.name; - items; - docstring = - item.docstring @ internalDocstrings - |> List.map String.trim; - }) - | Module (Structure m) -> - (* module Whatever = {} in res or module Whatever: {} in resi. *) - Some - (Module - (extractDocsForModule ~modulePath:(m.name :: modulePath) - m)) - | Module (Constraint (Structure _impl, Structure interface)) -> - (* module Whatever: { } = { }. Prefer the interface. *) - Some - (Module - (extractDocsForModule - ~modulePath:(interface.name :: modulePath) - interface)) - | _ -> None); - } - in - let docs = extractDocsForModule structure in - print_endline (stringifyDocsForModule ~originalEnv:env docs) + Some + (ModuleAlias + { + id; + name = item.name; + items; + docstring = + item.docstring @ internalDocstrings + |> List.map String.trim; + }) + | Module (Structure m) -> + (* module Whatever = {} in res or module Whatever: {} in resi. *) + Some + (Module + (extractDocsForModule + ~modulePath:(m.name :: modulePath) m)) + | Module + (Constraint (Structure _impl, Structure interface)) -> + (* module Whatever: { } = { }. Prefer the interface. *) + Some + (Module + (extractDocsForModule + ~modulePath:(interface.name :: modulePath) + interface)) + | _ -> None); + } + in + let docs = extractDocsForModule structure in + Ok (stringifyDocsForModule ~originalEnv:env docs)) + | true -> + Error + (Printf.sprintf + "error: failed to read %s, expected an .res or .resi file" path) + in + + result From 24d2946698887e54b0ea76bc9eace8e8e05bccc6 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Wed, 10 Jan 2024 21:10:15 -0300 Subject: [PATCH 09/12] delete .bs.js files --- tools/npm/RescriptTools.bs.js | 8 - tools/npm/Tools_Docgen.bs.js | 440 ---------------------------------- 2 files changed, 448 deletions(-) delete mode 100644 tools/npm/RescriptTools.bs.js delete mode 100644 tools/npm/Tools_Docgen.bs.js diff --git a/tools/npm/RescriptTools.bs.js b/tools/npm/RescriptTools.bs.js deleted file mode 100644 index 281db50e0..000000000 --- a/tools/npm/RescriptTools.bs.js +++ /dev/null @@ -1,8 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE -'use strict'; - - -var Docgen; - -exports.Docgen = Docgen; -/* No side effect */ diff --git a/tools/npm/Tools_Docgen.bs.js b/tools/npm/Tools_Docgen.bs.js deleted file mode 100644 index ed123cd7a..000000000 --- a/tools/npm/Tools_Docgen.bs.js +++ /dev/null @@ -1,440 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE -'use strict'; - -var Js_dict = require("rescript/lib/js/js_dict.js"); - -function decodeDocstrings(item) { - var match = Js_dict.get(item, "docstrings"); - if (match !== undefined) { - if (!Array.isArray(match) && (match === null || typeof match !== "object") && typeof match !== "number" && typeof match !== "string" && typeof match !== "boolean") { - return []; - } else if (Array.isArray(match)) { - return match.map(function (s) { - if (!Array.isArray(s) && (s === null || typeof s !== "object") && typeof s !== "number" && typeof s !== "string" && typeof s !== "boolean") { - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "Tools_Docgen.res", - 64, - 13 - ], - Error: new Error() - }; - } - if (typeof s === "string") { - return s; - } - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "Tools_Docgen.res", - 64, - 13 - ], - Error: new Error() - }; - }); - } else { - return []; - } - } else { - return []; - } -} - -function decodeStringByField(item, field) { - var match = Js_dict.get(item, field); - if (match !== undefined && !(!Array.isArray(match) && (match === null || typeof match !== "object") && typeof match !== "number" && typeof match !== "string" && typeof match !== "boolean") && typeof match === "string") { - return match; - } - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "Tools_Docgen.res", - 75, - 9 - ], - Error: new Error() - }; -} - -function decodeDepreacted(item) { - var match = Js_dict.get(item, "deprecated"); - if (match !== undefined && !(!Array.isArray(match) && (match === null || typeof match !== "object") && typeof match !== "number" && typeof match !== "string" && typeof match !== "boolean" || typeof match !== "string")) { - return match; - } - -} - -function decodeDetail(detail) { - if (!Array.isArray(detail) && (detail === null || typeof detail !== "object") && typeof detail !== "number" && typeof detail !== "string" && typeof detail !== "boolean") { - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "Tools_Docgen.res", - 144, - 9 - ], - Error: new Error() - }; - } - if (typeof detail === "object" && !Array.isArray(detail)) { - var match = Js_dict.get(detail, "kind"); - var match$1 = Js_dict.get(detail, "items"); - if (match !== undefined && !(!Array.isArray(match) && (match === null || typeof match !== "object") && typeof match !== "number" && typeof match !== "string" && typeof match !== "boolean") && typeof match === "string" && match$1 !== undefined && !(!Array.isArray(match$1) && (match$1 === null || typeof match$1 !== "object") && typeof match$1 !== "number" && typeof match$1 !== "string" && typeof match$1 !== "boolean") && Array.isArray(match$1)) { - switch (match) { - case "record" : - var items = match$1.map(function (field) { - if (!Array.isArray(field) && (field === null || typeof field !== "object") && typeof field !== "number" && typeof field !== "string" && typeof field !== "boolean") { - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "Tools_Docgen.res", - 104, - 11 - ], - Error: new Error() - }; - } - if (typeof field === "object" && !Array.isArray(field)) { - var name = decodeStringByField(field, "name"); - var docstrings = decodeDocstrings(field); - var signature = decodeStringByField(field, "signature"); - var deprecated = decodeDepreacted(field); - var match = Js_dict.get(field, "optional"); - var optional; - var exit = 0; - if (match !== undefined && !(!Array.isArray(match) && (match === null || typeof match !== "object") && typeof match !== "number" && typeof match !== "string" && typeof match !== "boolean" || typeof match !== "boolean")) { - optional = match; - } else { - exit = 1; - } - if (exit === 1) { - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "Tools_Docgen.res", - 98, - 15 - ], - Error: new Error() - }; - } - return { - name: name, - docstrings: docstrings, - signature: signature, - optional: optional, - deprecated: deprecated - }; - } - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "Tools_Docgen.res", - 104, - 11 - ], - Error: new Error() - }; - }); - return { - kind: "record", - items: items - }; - case "variant" : - var items$1 = match$1.map(function (field) { - if (!Array.isArray(field) && (field === null || typeof field !== "object") && typeof field !== "number" && typeof field !== "string" && typeof field !== "boolean") { - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "Tools_Docgen.res", - 123, - 11 - ], - Error: new Error() - }; - } - if (typeof field === "object" && !Array.isArray(field)) { - var name = decodeStringByField(field, "name"); - var docstrings = decodeDocstrings(field); - var signature = decodeStringByField(field, "signature"); - var deprecated = decodeDepreacted(field); - return { - name: name, - docstrings: docstrings, - signature: signature, - deprecated: deprecated - }; - } - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "Tools_Docgen.res", - 123, - 11 - ], - Error: new Error() - }; - }); - return { - kind: "variant", - items: items$1 - }; - default: - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "Tools_Docgen.res", - 139, - 13 - ], - Error: new Error() - }; - } - } - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "Tools_Docgen.res", - 141, - 11 - ], - Error: new Error() - }; - } - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "Tools_Docgen.res", - 144, - 9 - ], - Error: new Error() - }; -} - -function decodeValue(item) { - var id = decodeStringByField(item, "id"); - var signature = decodeStringByField(item, "signature"); - var name = decodeStringByField(item, "name"); - var deprecated = decodeDepreacted(item); - var docstrings = decodeDocstrings(item); - return { - kind: "value", - id: id, - docstrings: docstrings, - signature: signature, - name: name, - deprecated: deprecated - }; -} - -function decodeType(item) { - var id = decodeStringByField(item, "id"); - var signature = decodeStringByField(item, "signature"); - var name = decodeStringByField(item, "name"); - var deprecated = decodeDepreacted(item); - var docstrings = decodeDocstrings(item); - var field = Js_dict.get(item, "detail"); - var detail = field !== undefined ? decodeDetail(field) : undefined; - return { - kind: "type", - id: id, - docstrings: docstrings, - signature: signature, - name: name, - deprecated: deprecated, - detail: detail - }; -} - -function decodeModuleAlias(item) { - var id = decodeStringByField(item, "id"); - var name = decodeStringByField(item, "name"); - var docstrings = decodeDocstrings(item); - var match = Js_dict.get(item, "items"); - var items; - var exit = 0; - if (match !== undefined && !(!Array.isArray(match) && (match === null || typeof match !== "object") && typeof match !== "number" && typeof match !== "string" && typeof match !== "boolean" || !Array.isArray(match))) { - items = match.map(function (item) { - return decodeItem(item); - }); - } else { - exit = 1; - } - if (exit === 1) { - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "Tools_Docgen.res", - 175, - 9 - ], - Error: new Error() - }; - } - return { - kind: "moduleAlias", - id: id, - docstrings: docstrings, - name: name, - items: items - }; -} - -function decodeModule(item) { - var id = decodeStringByField(item, "id"); - var name = decodeStringByField(item, "name"); - var deprecated = decodeDepreacted(item); - var docstrings = decodeDocstrings(item); - var match = Js_dict.get(item, "items"); - var items; - var exit = 0; - if (match !== undefined && !(!Array.isArray(match) && (match === null || typeof match !== "object") && typeof match !== "number" && typeof match !== "string" && typeof match !== "boolean" || !Array.isArray(match))) { - items = match.map(function (item) { - return decodeItem(item); - }); - } else { - exit = 1; - } - if (exit === 1) { - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "Tools_Docgen.res", - 187, - 9 - ], - Error: new Error() - }; - } - return { - kind: "module", - id: id, - docstrings: docstrings, - deprecated: deprecated, - name: name, - items: items - }; -} - -function decodeItem(item) { - if (!Array.isArray(item) && (item === null || typeof item !== "object") && typeof item !== "number" && typeof item !== "string" && typeof item !== "boolean") { - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "Tools_Docgen.res", - 206, - 9 - ], - Error: new Error() - }; - } - if (typeof item === "object" && !Array.isArray(item)) { - var match = Js_dict.get(item, "kind"); - if (match !== undefined && !(!Array.isArray(match) && (match === null || typeof match !== "object") && typeof match !== "number" && typeof match !== "string" && typeof match !== "boolean") && typeof match === "string") { - switch (match) { - case "module" : - return decodeModule(item); - case "moduleAlias" : - return decodeModuleAlias(item); - case "type" : - return decodeType(item); - case "value" : - return decodeValue(item); - default: - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "Tools_Docgen.res", - 202, - 13 - ], - Error: new Error() - }; - } - } - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "Tools_Docgen.res", - 204, - 11 - ], - Error: new Error() - }; - } - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "Tools_Docgen.res", - 206, - 9 - ], - Error: new Error() - }; -} - -function decodeFromJson(json) { - if (!Array.isArray(json) && (json === null || typeof json !== "object") && typeof json !== "number" && typeof json !== "string" && typeof json !== "boolean") { - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "Tools_Docgen.res", - 236, - 9 - ], - Error: new Error() - }; - } - if (typeof json === "object" && !Array.isArray(json)) { - var name = decodeStringByField(json, "name"); - var deprecated = decodeDepreacted(json); - var docstrings = decodeDocstrings(json); - var match = Js_dict.get(json, "items"); - var items; - var exit = 0; - if (match !== undefined && !(!Array.isArray(match) && (match === null || typeof match !== "object") && typeof match !== "number" && typeof match !== "string" && typeof match !== "boolean" || !Array.isArray(match))) { - items = match.map(function (item) { - return decodeItem(item); - }); - } else { - exit = 1; - } - if (exit === 1) { - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "Tools_Docgen.res", - 230, - 13 - ], - Error: new Error() - }; - } - return { - name: name, - deprecated: deprecated, - docstrings: docstrings, - items: items - }; - } - throw { - RE_EXN_ID: "Assert_failure", - _1: [ - "Tools_Docgen.res", - 236, - 9 - ], - Error: new Error() - }; -} - -exports.decodeValue = decodeValue; -exports.decodeType = decodeType; -exports.decodeModule = decodeModule; -exports.decodeModuleAlias = decodeModuleAlias; -exports.decodeItem = decodeItem; -exports.decodeFromJson = decodeFromJson; -/* No side effect */ From dd1d3f0e850be79d24139806f1d7059f28b82d33 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Wed, 10 Jan 2024 21:49:19 -0300 Subject: [PATCH 10/12] update npm install and contributing.md --- CONTRIBUTING.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 02aa947ba..6be7c9d51 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -76,7 +76,7 @@ opam install ocaml-lsp-server image -- For the native analysis binary tests: `make test`. +- For the native analysis and tools binary tests: `make test`. ## Change the Grammar diff --git a/package.json b/package.json index a65328a51..c20c78223 100644 --- a/package.json +++ b/package.json @@ -218,7 +218,7 @@ "vscode:prepublish": "npm run clean && npm run compile", "compile": "tsc -b", "watch": "tsc -b -w", - "postinstall": "cd server && npm i && cd ../client && npm i && cd ../analysis/tests && npm i && cd ../reanalyze/examples/deadcode && npm i && cd ../termination && npm i" + "postinstall": "cd server && npm i && cd ../client && npm i && cd ../tools && npm i && cd ../tools/tests && npm i && cd ../../analysis/tests && npm i && cd ../reanalyze/examples/deadcode && npm i && cd ../termination && npm i" }, "devDependencies": { "@types/node": "^14.14.41", From 12cdae3d9a942f3cb1e799d486c75038c1e597d0 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Thu, 11 Jan 2024 23:22:44 -0300 Subject: [PATCH 11/12] update tests --- .../src/expected/DocExtraction2.res.json | 1 + .../src/expected/DocExtraction2.resi.json | 1 + .../src/expected/DocExtractionRes.res.json | 21 +++++++++++++++++-- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/tools/tests/src/expected/DocExtraction2.res.json b/tools/tests/src/expected/DocExtraction2.res.json index 214e0cacb..06467b54c 100644 --- a/tools/tests/src/expected/DocExtraction2.res.json +++ b/tools/tests/src/expected/DocExtraction2.res.json @@ -21,6 +21,7 @@ "id": "DocExtraction2.InnerModule", "name": "InnerModule", "kind": "module", + "docstrings": [], "items": [ { "id": "DocExtraction2.InnerModule.t", diff --git a/tools/tests/src/expected/DocExtraction2.resi.json b/tools/tests/src/expected/DocExtraction2.resi.json index 214e0cacb..06467b54c 100644 --- a/tools/tests/src/expected/DocExtraction2.resi.json +++ b/tools/tests/src/expected/DocExtraction2.resi.json @@ -21,6 +21,7 @@ "id": "DocExtraction2.InnerModule", "name": "InnerModule", "kind": "module", + "docstrings": [], "items": [ { "id": "DocExtraction2.InnerModule.t", diff --git a/tools/tests/src/expected/DocExtractionRes.res.json b/tools/tests/src/expected/DocExtractionRes.res.json index 8e716c0b3..c31159024 100644 --- a/tools/tests/src/expected/DocExtractionRes.res.json +++ b/tools/tests/src/expected/DocExtractionRes.res.json @@ -50,6 +50,7 @@ "id": "DocExtractionRes.SomeInnerModule", "name": "SomeInnerModule", "kind": "module", + "docstrings": ["Another module level docstring here."], "items": [ { "id": "DocExtractionRes.SomeInnerModule.status", @@ -97,6 +98,7 @@ "id": "DocExtractionRes.AnotherModule", "name": "AnotherModule", "kind": "module", + "docstrings": ["Mighty fine module here too!"], "items": [ { "id": "DocExtractionRes.LinkedModule", @@ -123,7 +125,7 @@ "id": "DocExtractionRes.AnotherModule.someVariantWithInlineRecords", "kind": "type", "name": "someVariantWithInlineRecords", - "signature": "type someVariantWithInlineRecords =\n | SomeStuff({offline: bool})", + "signature": "type someVariantWithInlineRecords =\n | SomeStuff({offline: bool, online?: bool})", "docstrings": ["Trying how it looks with an inline record in a variant."], "detail": { @@ -132,7 +134,21 @@ { "name": "SomeStuff", "docstrings": ["This has inline records..."], - "signature": "SomeStuff" + "signature": "SomeStuff({offline: bool, online?: bool})", + "payload": { + "kind": "inlineRecord", + "fields": [{ + "name": "offline", + "optional": false, + "docstrings": [], + "signature": "bool" + }, { + "name": "online", + "optional": true, + "docstrings": ["Is the user online?"], + "signature": "option" + }] + } }] } }, @@ -148,6 +164,7 @@ "id": "DocExtractionRes.ModuleWithThingsThatShouldNotBeExported", "name": "ModuleWithThingsThatShouldNotBeExported", "kind": "module", + "docstrings": [], "items": [ { "id": "DocExtractionRes.ModuleWithThingsThatShouldNotBeExported.t", From 546b7ca49728d5b61e193ada833dfad20cbe7201 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Thu, 11 Jan 2024 23:50:33 -0300 Subject: [PATCH 12/12] [skip ci]: update CONTRIBUTING.md --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6be7c9d51..1a7a0668c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -47,8 +47,8 @@ opam switch 4.14.0 # can also create local switch with opam switch create . 4.14 # Install dev dependencies from OPAM opam install . --deps-only -# For IDE support, install the OCaml language server -opam install ocaml-lsp-server +# For IDE support, install the OCaml language server and OCaml Formatter +opam install ocaml-lsp-server ocamlformat ``` ## Build & Run