diff --git a/sample/.githooks/README.md b/sample/.githooks/README.md new file mode 100644 index 0000000..61c0ad6 --- /dev/null +++ b/sample/.githooks/README.md @@ -0,0 +1,21 @@ +# Git Hooks + +## Pre-commit Hook + +This pre-commit hook performs automatic checks before finalizing your commit. + +### Usage Instructions + +To use this pre-commit hook: + +1. Make the hook executable if it isn't already: + ```bash + chmod +x .githooks/pre-commit + ``` + +2. Configure Git to use the hooks in the .githooks directory: + ```bash + git config core.hooksPath .githooks + ``` + +3. The hook will automatically run when you execute `git commit` diff --git a/sample/.githooks/pre-commit b/sample/.githooks/pre-commit new file mode 100755 index 0000000..e2a32b0 --- /dev/null +++ b/sample/.githooks/pre-commit @@ -0,0 +1,3 @@ +#!/bin/sh + +moon check \ No newline at end of file diff --git a/sample/.github/workflows/copilot-setup-steps.yml b/sample/.github/workflows/copilot-setup-steps.yml new file mode 100644 index 0000000..6f8811a --- /dev/null +++ b/sample/.github/workflows/copilot-setup-steps.yml @@ -0,0 +1,41 @@ +# Reference: https://docs.github.com/en/copilot/how-tos/use-copilot-agents/coding-agent/customize-the-agent-environment +name: "Copilot Setup Steps" + +# Automatically run the setup steps when they are changed to allow for easy validation, and +# allow manual testing through the repository's "Actions" tab +on: + workflow_dispatch: + push: + paths: + - .github/workflows/copilot-setup-steps.yml + pull_request: + paths: + - .github/workflows/copilot-setup-steps.yml + +jobs: + # The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot. + copilot-setup-steps: + runs-on: ubuntu-latest + + # Set the permissions to the lowest permissions possible needed for your steps. + # Copilot will be given its own token for its operations. + permissions: + # If you want to clone the repository as part of your setup steps, for example to install dependencies, you'll need the `contents: read` permission. If you don't clone the repository in your setup steps, Copilot will do this for you automatically after the steps complete. + contents: read + + # You can define any steps you want, and they will run before the agent starts. + # If you do not check out your code, Copilot will do this for you. + steps: + - name: Checkout code + uses: actions/checkout@v5 + + - name: Set up MoonBit + run: | + curl -fsSL https://cli.moonbitlang.com/install/unix.sh | bash + echo "$HOME/.moon/bin" >> $GITHUB_PATH + + - name: Update MoonBit dependencies + run: | + moon version --all + moon update + diff --git a/sample/.gitignore b/sample/.gitignore new file mode 100644 index 0000000..2cc4b64 --- /dev/null +++ b/sample/.gitignore @@ -0,0 +1,4 @@ +.DS_Store +_build/ +.mooncakes/ +.moonagent/ \ No newline at end of file diff --git a/sample/AGENTS.md b/sample/AGENTS.md new file mode 100644 index 0000000..7a491d8 --- /dev/null +++ b/sample/AGENTS.md @@ -0,0 +1,51 @@ +# Project Agents.md Guide + +This is a [MoonBit](https://docs.moonbitlang.com) project. + +You can browse and install extra skills here: + + +## Project Structure + +- MoonBit packages are organized per directory; each directory contains a + `moon.pkg` file listing its dependencies. Each package has its files and + blackbox test files (ending in `_test.mbt`) and whitebox test files (ending in + `_wbtest.mbt`). + +- In the toplevel directory, there is a `moon.mod.json` file listing module + metadata. + +## Coding convention + +- MoonBit code is organized in block style, each block is separated by `///|`, + the order of each block is irrelevant. In some refactorings, you can process + block by block independently. + +- Try to keep deprecated blocks in file called `deprecated.mbt` in each + directory. + +## Tooling + +- `moon fmt` is used to format your code properly. + +- `moon ide` provides project navigation helpers like `peek-def`, `outline`, and + `find-references`. See $moonbit-agent-guide for details. + +- `moon info` is used to update the generated interface of the package, each + package has a generated interface file `.mbti`, it is a brief formal + description of the package. If nothing in `.mbti` changes, this means your + change does not bring the visible changes to the external package users, it is + typically a safe refactoring. + +- In the last step, run `moon info && moon fmt` to update the interface and + format the code. Check the diffs of `.mbti` file to see if the changes are + expected. + +- Run `moon test` to check tests pass. MoonBit supports snapshot testing; when + changes affect outputs, run `moon test --update` to refresh snapshots. + +- Prefer `assert_eq` or `assert_true(pattern is Pattern(...))` for results that + are stable or very unlikely to change. Use snapshot tests to record current + behavior. For solid, well-defined results (e.g. scientific computations), + prefer assertion tests. You can use `moon coverage analyze > uncovered.log` to + see which parts of your code are not covered by tests. diff --git a/sample/LICENSE b/sample/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/sample/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/sample/README.mbt.md b/sample/README.mbt.md new file mode 100644 index 0000000..9eafa25 --- /dev/null +++ b/sample/README.mbt.md @@ -0,0 +1 @@ +# bzy-debug/sample \ No newline at end of file diff --git a/sample/README.md b/sample/README.md new file mode 120000 index 0000000..7ae1db3 --- /dev/null +++ b/sample/README.md @@ -0,0 +1 @@ +README.mbt.md \ No newline at end of file diff --git a/sample/cmd/main/main.mbt b/sample/cmd/main/main.mbt new file mode 100644 index 0000000..e31b62c --- /dev/null +++ b/sample/cmd/main/main.mbt @@ -0,0 +1,7 @@ +///| +/// Entry point for the CLI or runnable program in this template. +/// Keep main focused; move logic into the library package. +/// Run with `moon run cmd/main` from the project root. +fn main { + println("Hello") +} diff --git a/sample/cmd/main/moon.pkg b/sample/cmd/main/moon.pkg new file mode 100644 index 0000000..7639d7c --- /dev/null +++ b/sample/cmd/main/moon.pkg @@ -0,0 +1,7 @@ +// import { +// "bzy-debug/sample" @lib, +// } + +options( + "is-main": true, +) diff --git a/sample/dune b/sample/dune new file mode 100644 index 0000000..7b2fa28 --- /dev/null +++ b/sample/dune @@ -0,0 +1,3 @@ +(cram + (deps + (source_tree .))) diff --git a/sample/generated_find_references.t b/sample/generated_find_references.t new file mode 100644 index 0000000..8368cf6 --- /dev/null +++ b/sample/generated_find_references.t @@ -0,0 +1,847 @@ + $ export MOON_HOME="${MOON_HOME:-$HOME/.moon}" + $ export BUILD_PATH_PREFIX_MAP="\$MOON_HOME=$MOON_HOME:$BUILD_PATH_PREFIX_MAP" + $ moon ide find-references Item --loc 'sample.mbt:3:10' + Error: could not find references for symbol 'Item' at sample.mbt:3:10 + [1] + $ moon ide find-references Worker --loc 'sample.mbt:5:11' + Found 3 references for symbol 'Worker': + $TESTCASE_ROOT/sample.mbt:5:11-5:17: + | /// Sample source used by testgen. + | pub type Item = Int + | + 5 | pub trait Worker { + | ^^^^^^ + | run(Self, Int) -> Int + | } + + $TESTCASE_ROOT/sample.mbt:21:6-21:12: + | Int::abs(-n) + | } + | + 21 | impl Worker for Int with run(self, delta) { + | ^^^^^^ + | self + delta + | } + + $TESTCASE_ROOT/sample.mbt:27:22-27:28: + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + 27 | let worker_value = Worker::run(x, item) + | ^^^^^^ + | worker_value + use_features() + | } + + $ moon ide find-references run --loc 'sample.mbt:6:3' + Found 3 references for symbol 'run': + $TESTCASE_ROOT/sample.mbt:6:3-6:6: + | pub type Item = Int + | + | pub trait Worker { + 6 | run(Self, Int) -> Int + | ^^^ + | } + | + + $TESTCASE_ROOT/sample.mbt:21:26-21:29: + | Int::abs(-n) + | } + | + 21 | impl Worker for Int with run(self, delta) { + | ^^^ + | self + delta + | } + + $TESTCASE_ROOT/sample.mbt:27:30-27:33: + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + 27 | let worker_value = Worker::run(x, item) + | ^^^ + | worker_value + use_features() + | } + + $ moon ide find-references make_item --loc 'sample.mbt:9:8' + Found 2 references for symbol 'make_item': + $TESTCASE_ROOT/sample.mbt:9:8-9:17: + | run(Self, Int) -> Int + | } + | + 9 | pub fn make_item(x : Int) -> Item { + | ^^^^^^^^^ + | x + | } + + $TESTCASE_ROOT/sample.mbt:26:14-26:23: + | } + | + | pub fn demo_call(x : Int) -> Int { + 26 | let item = make_item(default_item) + | ^^^^^^^^^ + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + + $ moon ide find-references x --loc 'sample.mbt:9:18' + Found 2 references for symbol 'x': + $TESTCASE_ROOT/sample.mbt:9:18-9:19: + | run(Self, Int) -> Int + | } + | + 9 | pub fn make_item(x : Int) -> Item { + | ^ + | x + | } + + $TESTCASE_ROOT/sample.mbt:10:3-10:4: + | } + | + | pub fn make_item(x : Int) -> Item { + 10 | x + | ^ + | } + | + + $ moon ide find-references Item --loc 'sample.mbt:9:30' + Error: could not find references for symbol 'Item' at sample.mbt:9:30 + [1] + $ moon ide find-references x --loc 'sample.mbt:10:3' + Found 2 references for symbol 'x': + $TESTCASE_ROOT/sample.mbt:9:18-9:19: + | run(Self, Int) -> Int + | } + | + 9 | pub fn make_item(x : Int) -> Item { + | ^ + | x + | } + + $TESTCASE_ROOT/sample.mbt:10:3-10:4: + | } + | + | pub fn make_item(x : Int) -> Item { + 10 | x + | ^ + | } + | + + $ moon ide find-references default_item --loc 'sample.mbt:13:9' + Found 2 references for symbol 'default_item': + $TESTCASE_ROOT/sample.mbt:13:9-13:21: + | x + | } + | + 13 | pub let default_item : Item = 1 + | ^^^^^^^^^^^^ + | + | pub fn use_features() -> Int { + + $TESTCASE_ROOT/sample.mbt:26:24-26:36: + | } + | + | pub fn demo_call(x : Int) -> Int { + 26 | let item = make_item(default_item) + | ^^^^^^^^^^^^ + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + + $ moon ide find-references Item --loc 'sample.mbt:13:24' + Error: could not find references for symbol 'Item' at sample.mbt:13:24 + [1] + $ moon ide find-references use_features --loc 'sample.mbt:15:8' + Found 2 references for symbol 'use_features': + $TESTCASE_ROOT/sample.mbt:15:8-15:20: + | + | pub let default_item : Item = 1 + | + 15 | pub fn use_features() -> Int { + | ^^^^^^^^^^^^ + | let xs = [1, 2, 3] + | let n = xs.length() + + $TESTCASE_ROOT/sample.mbt:28:18-28:30: + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + 28 | worker_value + use_features() + | ^^^^^^^^^^^^ + | } + + $ moon ide find-references xs --loc 'sample.mbt:16:7' + Found 2 references for symbol 'xs': + $TESTCASE_ROOT/sample.mbt:16:7-16:9: + | pub let default_item : Item = 1 + | + | pub fn use_features() -> Int { + 16 | let xs = [1, 2, 3] + | ^^ + | let n = xs.length() + | Int::abs(-n) + + $TESTCASE_ROOT/sample.mbt:17:11-17:13: + | + | pub fn use_features() -> Int { + | let xs = [1, 2, 3] + 17 | let n = xs.length() + | ^^ + | Int::abs(-n) + | } + + $ moon ide find-references n --loc 'sample.mbt:17:7' + Found 2 references for symbol 'n': + $TESTCASE_ROOT/sample.mbt:17:7-17:8: + | + | pub fn use_features() -> Int { + | let xs = [1, 2, 3] + 17 | let n = xs.length() + | ^ + | Int::abs(-n) + | } + + $TESTCASE_ROOT/sample.mbt:18:13-18:14: + | pub fn use_features() -> Int { + | let xs = [1, 2, 3] + | let n = xs.length() + 18 | Int::abs(-n) + | ^ + | } + | + + $ moon ide find-references length --loc 'sample.mbt:17:14' + Found 2 references for symbol 'length': + $MOON_HOME/lib/core/builtin/arraycore_nonjs.mbt:81:18-81:24: + | /// } + | /// ``` + | #intrinsic("%array.length") + 81 | pub fn[T] Array::length(self : Array[T]) -> Int { + | ^^^^^^ + | self.len + | } + + $TESTCASE_ROOT/sample.mbt:17:14-17:20: + | + | pub fn use_features() -> Int { + | let xs = [1, 2, 3] + 17 | let n = xs.length() + | ^^^^^^ + | Int::abs(-n) + | } + + $ moon ide find-references xs --loc 'sample.mbt:17:11' + Found 2 references for symbol 'xs': + $TESTCASE_ROOT/sample.mbt:16:7-16:9: + | pub let default_item : Item = 1 + | + | pub fn use_features() -> Int { + 16 | let xs = [1, 2, 3] + | ^^ + | let n = xs.length() + | Int::abs(-n) + + $TESTCASE_ROOT/sample.mbt:17:11-17:13: + | + | pub fn use_features() -> Int { + | let xs = [1, 2, 3] + 17 | let n = xs.length() + | ^^ + | Int::abs(-n) + | } + + $ moon ide find-references abs --loc 'sample.mbt:18:8' + Found 2 references for symbol 'abs': + $MOON_HOME/lib/core/builtin/int.mbt:176:13-176:16: + | /// inspect(Int::abs(0), content="0") + | /// } + | /// ``` + 176 | pub fn Int::abs(self : Int) -> Int { + | ^^^ + | if self < 0 { + | -self + + $TESTCASE_ROOT/sample.mbt:18:8-18:11: + | pub fn use_features() -> Int { + | let xs = [1, 2, 3] + | let n = xs.length() + 18 | Int::abs(-n) + | ^^^ + | } + | + + $ moon ide find-references n --loc 'sample.mbt:18:13' + Found 2 references for symbol 'n': + $TESTCASE_ROOT/sample.mbt:17:7-17:8: + | + | pub fn use_features() -> Int { + | let xs = [1, 2, 3] + 17 | let n = xs.length() + | ^ + | Int::abs(-n) + | } + + $TESTCASE_ROOT/sample.mbt:18:13-18:14: + | pub fn use_features() -> Int { + | let xs = [1, 2, 3] + | let n = xs.length() + 18 | Int::abs(-n) + | ^ + | } + | + + $ moon ide find-references Worker --loc 'sample.mbt:21:6' + Found 3 references for symbol 'Worker': + $TESTCASE_ROOT/sample.mbt:5:11-5:17: + | /// Sample source used by testgen. + | pub type Item = Int + | + 5 | pub trait Worker { + | ^^^^^^ + | run(Self, Int) -> Int + | } + + $TESTCASE_ROOT/sample.mbt:21:6-21:12: + | Int::abs(-n) + | } + | + 21 | impl Worker for Int with run(self, delta) { + | ^^^^^^ + | self + delta + | } + + $TESTCASE_ROOT/sample.mbt:27:22-27:28: + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + 27 | let worker_value = Worker::run(x, item) + | ^^^^^^ + | worker_value + use_features() + | } + + $ moon ide find-references run --loc 'sample.mbt:21:26' + Found 2 references for symbol 'run': + $TESTCASE_ROOT/sample.mbt:21:26-21:29: + | Int::abs(-n) + | } + | + 21 | impl Worker for Int with run(self, delta) { + | ^^^ + | self + delta + | } + + $TESTCASE_ROOT/sample.mbt:27:22-27:33: + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + 27 | let worker_value = Worker::run(x, item) + | ^^^^^^^^^^^ + | worker_value + use_features() + | } + + $ moon ide find-references self --loc 'sample.mbt:21:30' + Found 2 references for symbol 'self': + $TESTCASE_ROOT/sample.mbt:21:30-21:34: + | Int::abs(-n) + | } + | + 21 | impl Worker for Int with run(self, delta) { + | ^^^^ + | self + delta + | } + + $TESTCASE_ROOT/sample.mbt:22:3-22:7: + | } + | + | impl Worker for Int with run(self, delta) { + 22 | self + delta + | ^^^^ + | } + | + + $ moon ide find-references delta --loc 'sample.mbt:21:36' + Found 2 references for symbol 'delta': + $TESTCASE_ROOT/sample.mbt:21:36-21:41: + | Int::abs(-n) + | } + | + 21 | impl Worker for Int with run(self, delta) { + | ^^^^^ + | self + delta + | } + + $TESTCASE_ROOT/sample.mbt:22:10-22:15: + | } + | + | impl Worker for Int with run(self, delta) { + 22 | self + delta + | ^^^^^ + | } + | + + $ moon ide find-references self --loc 'sample.mbt:22:3' + Found 2 references for symbol 'self': + $TESTCASE_ROOT/sample.mbt:21:30-21:34: + | Int::abs(-n) + | } + | + 21 | impl Worker for Int with run(self, delta) { + | ^^^^ + | self + delta + | } + + $TESTCASE_ROOT/sample.mbt:22:3-22:7: + | } + | + | impl Worker for Int with run(self, delta) { + 22 | self + delta + | ^^^^ + | } + | + + $ moon ide find-references delta --loc 'sample.mbt:22:10' + Found 2 references for symbol 'delta': + $TESTCASE_ROOT/sample.mbt:21:36-21:41: + | Int::abs(-n) + | } + | + 21 | impl Worker for Int with run(self, delta) { + | ^^^^^ + | self + delta + | } + + $TESTCASE_ROOT/sample.mbt:22:10-22:15: + | } + | + | impl Worker for Int with run(self, delta) { + 22 | self + delta + | ^^^^^ + | } + | + + $ moon ide find-references demo_call --loc 'sample.mbt:25:8' + Found 2 references for symbol 'demo_call': + $TESTCASE_ROOT/sample.mbt:25:8-25:17: + | self + delta + | } + | + 25 | pub fn demo_call(x : Int) -> Int { + | ^^^^^^^^^ + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + + $TESTCASE_ROOT/sample_test.mbt:7:11-7:20: + | + | ///| + | test "demo_call" { + 7 | inspect(demo_call(2), content="6") + | ^^^^^^^^^ + | } + + $ moon ide find-references x --loc 'sample.mbt:25:18' + Found 2 references for symbol 'x': + $TESTCASE_ROOT/sample.mbt:25:18-25:19: + | self + delta + | } + | + 25 | pub fn demo_call(x : Int) -> Int { + | ^ + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + + $TESTCASE_ROOT/sample.mbt:27:34-27:35: + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + 27 | let worker_value = Worker::run(x, item) + | ^ + | worker_value + use_features() + | } + + $ moon ide find-references item --loc 'sample.mbt:26:7' + Found 2 references for symbol 'item': + $TESTCASE_ROOT/sample.mbt:26:7-26:11: + | } + | + | pub fn demo_call(x : Int) -> Int { + 26 | let item = make_item(default_item) + | ^^^^ + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + + $TESTCASE_ROOT/sample.mbt:27:37-27:41: + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + 27 | let worker_value = Worker::run(x, item) + | ^^^^ + | worker_value + use_features() + | } + + $ moon ide find-references make_item --loc 'sample.mbt:26:14' + Found 2 references for symbol 'make_item': + $TESTCASE_ROOT/sample.mbt:9:8-9:17: + | run(Self, Int) -> Int + | } + | + 9 | pub fn make_item(x : Int) -> Item { + | ^^^^^^^^^ + | x + | } + + $TESTCASE_ROOT/sample.mbt:26:14-26:23: + | } + | + | pub fn demo_call(x : Int) -> Int { + 26 | let item = make_item(default_item) + | ^^^^^^^^^ + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + + $ moon ide find-references default_item --loc 'sample.mbt:26:24' + Found 2 references for symbol 'default_item': + $TESTCASE_ROOT/sample.mbt:13:9-13:21: + | x + | } + | + 13 | pub let default_item : Item = 1 + | ^^^^^^^^^^^^ + | + | pub fn use_features() -> Int { + + $TESTCASE_ROOT/sample.mbt:26:24-26:36: + | } + | + | pub fn demo_call(x : Int) -> Int { + 26 | let item = make_item(default_item) + | ^^^^^^^^^^^^ + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + + $ moon ide find-references worker_value --loc 'sample.mbt:27:7' + Found 2 references for symbol 'worker_value': + $TESTCASE_ROOT/sample.mbt:27:7-27:19: + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + 27 | let worker_value = Worker::run(x, item) + | ^^^^^^^^^^^^ + | worker_value + use_features() + | } + + $TESTCASE_ROOT/sample.mbt:28:3-28:15: + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + 28 | worker_value + use_features() + | ^^^^^^^^^^^^ + | } + + $ moon ide find-references Worker --loc 'sample.mbt:27:22' + Found 3 references for symbol 'Worker': + $TESTCASE_ROOT/sample.mbt:5:11-5:17: + | /// Sample source used by testgen. + | pub type Item = Int + | + 5 | pub trait Worker { + | ^^^^^^ + | run(Self, Int) -> Int + | } + + $TESTCASE_ROOT/sample.mbt:21:6-21:12: + | Int::abs(-n) + | } + | + 21 | impl Worker for Int with run(self, delta) { + | ^^^^^^ + | self + delta + | } + + $TESTCASE_ROOT/sample.mbt:27:22-27:28: + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + 27 | let worker_value = Worker::run(x, item) + | ^^^^^^ + | worker_value + use_features() + | } + + $ moon ide find-references run --loc 'sample.mbt:27:30' + Found 2 references for symbol 'run': + $TESTCASE_ROOT/sample.mbt:21:26-21:29: + | Int::abs(-n) + | } + | + 21 | impl Worker for Int with run(self, delta) { + | ^^^ + | self + delta + | } + + $TESTCASE_ROOT/sample.mbt:27:22-27:33: + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + 27 | let worker_value = Worker::run(x, item) + | ^^^^^^^^^^^ + | worker_value + use_features() + | } + + $ moon ide find-references x --loc 'sample.mbt:27:34' + Found 2 references for symbol 'x': + $TESTCASE_ROOT/sample.mbt:25:18-25:19: + | self + delta + | } + | + 25 | pub fn demo_call(x : Int) -> Int { + | ^ + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + + $TESTCASE_ROOT/sample.mbt:27:34-27:35: + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + 27 | let worker_value = Worker::run(x, item) + | ^ + | worker_value + use_features() + | } + + $ moon ide find-references item --loc 'sample.mbt:27:37' + Found 2 references for symbol 'item': + $TESTCASE_ROOT/sample.mbt:26:7-26:11: + | } + | + | pub fn demo_call(x : Int) -> Int { + 26 | let item = make_item(default_item) + | ^^^^ + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + + $TESTCASE_ROOT/sample.mbt:27:37-27:41: + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + 27 | let worker_value = Worker::run(x, item) + | ^^^^ + | worker_value + use_features() + | } + + $ moon ide find-references worker_value --loc 'sample.mbt:28:3' + Found 2 references for symbol 'worker_value': + $TESTCASE_ROOT/sample.mbt:27:7-27:19: + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + 27 | let worker_value = Worker::run(x, item) + | ^^^^^^^^^^^^ + | worker_value + use_features() + | } + + $TESTCASE_ROOT/sample.mbt:28:3-28:15: + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + 28 | worker_value + use_features() + | ^^^^^^^^^^^^ + | } + + $ moon ide find-references use_features --loc 'sample.mbt:28:18' + Found 2 references for symbol 'use_features': + $TESTCASE_ROOT/sample.mbt:15:8-15:20: + | + | pub let default_item : Item = 1 + | + 15 | pub fn use_features() -> Int { + | ^^^^^^^^^^^^ + | let xs = [1, 2, 3] + | let n = xs.length() + + $TESTCASE_ROOT/sample.mbt:28:18-28:30: + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + 28 | worker_value + use_features() + | ^^^^^^^^^^^^ + | } + + $ moon ide find-references demo_call --loc 'sample_test.mbt:7:11' + Found 2 references for symbol 'demo_call': + $TESTCASE_ROOT/sample.mbt:25:8-25:17: + | self + delta + | } + | + 25 | pub fn demo_call(x : Int) -> Int { + | ^^^^^^^^^ + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + + $TESTCASE_ROOT/sample_test.mbt:7:11-7:20: + | + | ///| + | test "demo_call" { + 7 | inspect(demo_call(2), content="6") + | ^^^^^^^^^ + | } + + $ moon ide find-references 'Item' + `pub type alias Item` in package bzy-debug/sample at $TESTCASE_ROOT/sample.mbt:1-3 + 1 | ///| + | /// Sample source used by testgen. + | pub type Item = Int + + Found 0 references for symbol 'Item': + $ moon ide find-references 'Worker' + `pub trait Worker` in package bzy-debug/sample at $TESTCASE_ROOT/sample.mbt:5-7 + 5 | pub trait Worker { + | run(Self, Int) -> Int + | } + + Found 3 references for symbol 'Worker': + $TESTCASE_ROOT/sample.mbt:5:11-5:17: + | /// Sample source used by testgen. + | pub type Item = Int + | + 5 | pub trait Worker { + | ^^^^^^ + | run(Self, Int) -> Int + | } + + $TESTCASE_ROOT/sample.mbt:21:6-21:12: + | Int::abs(-n) + | } + | + 21 | impl Worker for Int with run(self, delta) { + | ^^^^^^ + | self + delta + | } + + $TESTCASE_ROOT/sample.mbt:27:22-27:28: + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + 27 | let worker_value = Worker::run(x, item) + | ^^^^^^ + | worker_value + use_features() + | } + + $ moon ide find-references 'make_item' + `pub fn make_item` in package bzy-debug/sample at $TESTCASE_ROOT/sample.mbt:9-11 + 9 | pub fn make_item(x : Int) -> Item { + | x + | } + + Found 2 references for symbol 'make_item': + $TESTCASE_ROOT/sample.mbt:9:8-9:17: + | run(Self, Int) -> Int + | } + | + 9 | pub fn make_item(x : Int) -> Item { + | ^^^^^^^^^ + | x + | } + + $TESTCASE_ROOT/sample.mbt:26:14-26:23: + | } + | + | pub fn demo_call(x : Int) -> Int { + 26 | let item = make_item(default_item) + | ^^^^^^^^^ + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + + $ moon ide find-references 'default_item' + `pub let default_item` in package bzy-debug/sample at $TESTCASE_ROOT/sample.mbt:13-13 + 13 | pub let default_item : Item = 1 + + Found 2 references for symbol 'default_item': + $TESTCASE_ROOT/sample.mbt:13:9-13:21: + | x + | } + | + 13 | pub let default_item : Item = 1 + | ^^^^^^^^^^^^ + | + | pub fn use_features() -> Int { + + $TESTCASE_ROOT/sample.mbt:26:24-26:36: + | } + | + | pub fn demo_call(x : Int) -> Int { + 26 | let item = make_item(default_item) + | ^^^^^^^^^^^^ + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + + $ moon ide find-references 'use_features' + `pub fn use_features` in package bzy-debug/sample at $TESTCASE_ROOT/sample.mbt:15-19 + 15 | pub fn use_features() -> Int { + | let xs = [1, 2, 3] + | let n = xs.length() + | Int::abs(-n) + | } + + Found 2 references for symbol 'use_features': + $TESTCASE_ROOT/sample.mbt:15:8-15:20: + | + | pub let default_item : Item = 1 + | + 15 | pub fn use_features() -> Int { + | ^^^^^^^^^^^^ + | let xs = [1, 2, 3] + | let n = xs.length() + + $TESTCASE_ROOT/sample.mbt:28:18-28:30: + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + 28 | worker_value + use_features() + | ^^^^^^^^^^^^ + | } + + $ moon ide find-references 'Worker::run for Int' + `impl Worker::run for Int` in package bzy-debug/sample at $TESTCASE_ROOT/sample.mbt:21-23 + 21 | impl Worker for Int with run(self, delta) { + | self + delta + | } + + Found 2 references for symbol 'Worker::run for Int': + $TESTCASE_ROOT/sample.mbt:21:26-21:29: + | Int::abs(-n) + | } + | + 21 | impl Worker for Int with run(self, delta) { + | ^^^ + | self + delta + | } + + $TESTCASE_ROOT/sample.mbt:27:22-27:33: + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + 27 | let worker_value = Worker::run(x, item) + | ^^^^^^^^^^^ + | worker_value + use_features() + | } + + $ moon ide find-references 'demo_call' + `pub fn demo_call` in package bzy-debug/sample at $TESTCASE_ROOT/sample.mbt:25-29 + 25 | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + | } + + Found 2 references for symbol 'demo_call': + $TESTCASE_ROOT/sample.mbt:25:8-25:17: + | self + delta + | } + | + 25 | pub fn demo_call(x : Int) -> Int { + | ^^^^^^^^^ + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + + $TESTCASE_ROOT/sample_test.mbt:7:11-7:20: + | + | ///| + | test "demo_call" { + 7 | inspect(demo_call(2), content="6") + | ^^^^^^^^^ + | } + diff --git a/sample/generated_hover.t b/sample/generated_hover.t new file mode 100644 index 0000000..f75604b --- /dev/null +++ b/sample/generated_hover.t @@ -0,0 +1,411 @@ + $ export MOON_HOME="${MOON_HOME:-$HOME/.moon}" + $ export BUILD_PATH_PREFIX_MAP="\$MOON_HOME=$MOON_HOME:$BUILD_PATH_PREFIX_MAP" + $ moon ide hover Item --loc 'sample.mbt:3:10' + No hover information found for symbol 'Item' at sample.mbt:3:10 + [1] + $ moon ide hover Worker --loc 'sample.mbt:5:11' + /// Sample source used by testgen. + pub type Item = Int + + pub trait Worker { + ^^^^^^ + ```moonbit + trait Worker { + run(Self, Int) -> Int + } + ``` + run(Self, Int) -> Int + } + $ moon ide hover run --loc 'sample.mbt:6:3' + pub type Item = Int + + pub trait Worker { + run(Self, Int) -> Int + ^^^ + ```moonbit + (Self, Int) -> Int + ``` + } + + $ moon ide hover make_item --loc 'sample.mbt:9:8' + run(Self, Int) -> Int + } + + pub fn make_item(x : Int) -> Item { + ^^^^^^^^^ + ```moonbit + fn make_item(x : Int) -> Int + ``` + x + } + $ moon ide hover x --loc 'sample.mbt:9:18' + run(Self, Int) -> Int + } + + pub fn make_item(x : Int) -> Item { + ^ + ```moonbit + Int + ``` + x + } + $ moon ide hover Item --loc 'sample.mbt:9:30' + run(Self, Int) -> Int + } + + pub fn make_item(x : Int) -> Item { + ^^^^ + ```moonbit + Int + ``` + x + } + $ moon ide hover x --loc 'sample.mbt:10:3' + } + + pub fn make_item(x : Int) -> Item { + x + ^ + ```moonbit + Int + ``` + } + + $ moon ide hover default_item --loc 'sample.mbt:13:9' + x + } + + pub let default_item : Item = 1 + ^^^^^^^^^^^^ + ```moonbit + Int + ``` + + pub fn use_features() -> Int { + $ moon ide hover Item --loc 'sample.mbt:13:24' + x + } + + pub let default_item : Item = 1 + ^^^^ + ```moonbit + Int + ``` + + pub fn use_features() -> Int { + $ moon ide hover use_features --loc 'sample.mbt:15:8' + pub let default_item : Item = 1 + + pub fn use_features() -> Int { + ^^^^^^^^^^^^ + ```moonbit + fn use_features() -> Int + ``` + let xs = [1, 2, 3] + let n = xs.length() + $ moon ide hover xs --loc 'sample.mbt:16:7' + pub let default_item : Item = 1 + + pub fn use_features() -> Int { + let xs = [1, 2, 3] + ^^ + ```moonbit + Array[Int] + ``` + let n = xs.length() + Int::abs(-n) + $ moon ide hover n --loc 'sample.mbt:17:7' + pub fn use_features() -> Int { + let xs = [1, 2, 3] + let n = xs.length() + ^ + ```moonbit + Int + ``` + Int::abs(-n) + } + $ moon ide hover length --loc 'sample.mbt:17:14' + pub fn use_features() -> Int { + let xs = [1, 2, 3] + let n = xs.length() + ^^^^^^ + ```moonbit + fn[T] Array::length(self : Array[T]) -> Int + ``` + --- + + Returns the number of elements in the array. + + Parameters: + + * `array` : The array whose length is to be determined. + + Returns the number of elements in the array as an integer. + + Example: + + ```mbt check + test { + let arr = [1, 2, 3] + inspect(arr.length(), content="3") + let empty : Array[Int] = [] + inspect(empty.length(), content="0") + } + ``` + Int::abs(-n) + } + $ moon ide hover xs --loc 'sample.mbt:17:11' + pub fn use_features() -> Int { + let xs = [1, 2, 3] + let n = xs.length() + ^^ + ```moonbit + Array[Int] + ``` + Int::abs(-n) + } + $ moon ide hover abs --loc 'sample.mbt:18:8' + pub fn use_features() -> Int { + let xs = [1, 2, 3] + let n = xs.length() + Int::abs(-n) + ^^^ + ```moonbit + fn Int::abs(self : Int) -> Int + ``` + --- + + Computes the absolute value of an integer. + + Parameters: + + * `self` : The integer whose absolute value is to be computed. + + Returns the absolute value of the integer. + + Example: + + ```mbt check + test { + inspect(Int::abs(42), content="42") + inspect(Int::abs(-42), content="42") + inspect(Int::abs(0), content="0") + } + ``` + } + + $ moon ide hover n --loc 'sample.mbt:18:13' + pub fn use_features() -> Int { + let xs = [1, 2, 3] + let n = xs.length() + Int::abs(-n) + ^ + ```moonbit + Int + ``` + } + + $ moon ide hover Worker --loc 'sample.mbt:21:6' + Int::abs(-n) + } + + impl Worker for Int with run(self, delta) { + ^^^^^^ + ```moonbit + trait Worker { + run(Self, Int) -> Int + } + ``` + self + delta + } + $ moon ide hover run --loc 'sample.mbt:21:26' + Int::abs(-n) + } + + impl Worker for Int with run(self, delta) { + ^^^ + ```moonbit + fn Worker::run(self : Int, delta : Int) -> Int + ``` + self + delta + } + $ moon ide hover self --loc 'sample.mbt:21:30' + Int::abs(-n) + } + + impl Worker for Int with run(self, delta) { + ^^^^ + ```moonbit + Int + ``` + self + delta + } + $ moon ide hover delta --loc 'sample.mbt:21:36' + Int::abs(-n) + } + + impl Worker for Int with run(self, delta) { + ^^^^^ + ```moonbit + Int + ``` + self + delta + } + $ moon ide hover self --loc 'sample.mbt:22:3' + } + + impl Worker for Int with run(self, delta) { + self + delta + ^^^^ + ```moonbit + Int + ``` + } + + $ moon ide hover delta --loc 'sample.mbt:22:10' + } + + impl Worker for Int with run(self, delta) { + self + delta + ^^^^^ + ```moonbit + Int + ``` + } + + $ moon ide hover demo_call --loc 'sample.mbt:25:8' + self + delta + } + + pub fn demo_call(x : Int) -> Int { + ^^^^^^^^^ + ```moonbit + fn demo_call(x : Int) -> Int + ``` + let item = make_item(default_item) + let worker_value = Worker::run(x, item) + $ moon ide hover x --loc 'sample.mbt:25:18' + self + delta + } + + pub fn demo_call(x : Int) -> Int { + ^ + ```moonbit + Int + ``` + let item = make_item(default_item) + let worker_value = Worker::run(x, item) + $ moon ide hover item --loc 'sample.mbt:26:7' + } + + pub fn demo_call(x : Int) -> Int { + let item = make_item(default_item) + ^^^^ + ```moonbit + Int + ``` + let worker_value = Worker::run(x, item) + worker_value + use_features() + $ moon ide hover make_item --loc 'sample.mbt:26:14' + } + + pub fn demo_call(x : Int) -> Int { + let item = make_item(default_item) + ^^^^^^^^^ + ```moonbit + fn make_item(x : Int) -> Int + ``` + let worker_value = Worker::run(x, item) + worker_value + use_features() + $ moon ide hover default_item --loc 'sample.mbt:26:24' + } + + pub fn demo_call(x : Int) -> Int { + let item = make_item(default_item) + ^^^^^^^^^^^^ + ```moonbit + let default_item : Int + ``` + let worker_value = Worker::run(x, item) + worker_value + use_features() + $ moon ide hover worker_value --loc 'sample.mbt:27:7' + pub fn demo_call(x : Int) -> Int { + let item = make_item(default_item) + let worker_value = Worker::run(x, item) + ^^^^^^^^^^^^ + ```moonbit + Int + ``` + worker_value + use_features() + } + $ moon ide hover Worker --loc 'sample.mbt:27:22' + pub fn demo_call(x : Int) -> Int { + let item = make_item(default_item) + let worker_value = Worker::run(x, item) + ^^^^^^ + ```moonbit + trait Worker { + run(Self, Int) -> Int + } + ``` + worker_value + use_features() + } + $ moon ide hover run --loc 'sample.mbt:27:30' + pub fn demo_call(x : Int) -> Int { + let item = make_item(default_item) + let worker_value = Worker::run(x, item) + ^^^^^^^^^^^ + ```moonbit + (self : Int, delta : Int) -> Int + ``` + worker_value + use_features() + } + $ moon ide hover x --loc 'sample.mbt:27:34' + pub fn demo_call(x : Int) -> Int { + let item = make_item(default_item) + let worker_value = Worker::run(x, item) + ^ + ```moonbit + Int + ``` + worker_value + use_features() + } + $ moon ide hover item --loc 'sample.mbt:27:37' + pub fn demo_call(x : Int) -> Int { + let item = make_item(default_item) + let worker_value = Worker::run(x, item) + ^^^^ + ```moonbit + Int + ``` + worker_value + use_features() + } + $ moon ide hover worker_value --loc 'sample.mbt:28:3' + pub fn demo_call(x : Int) -> Int { + let item = make_item(default_item) + let worker_value = Worker::run(x, item) + worker_value + use_features() + ^^^^^^^^^^^^ + ```moonbit + Int + ``` + } + $ moon ide hover use_features --loc 'sample.mbt:28:18' + pub fn demo_call(x : Int) -> Int { + let item = make_item(default_item) + let worker_value = Worker::run(x, item) + worker_value + use_features() + ^^^^^^^^^^^^ + ```moonbit + fn use_features() -> Int + ``` + } + $ moon ide hover demo_call --loc 'sample_test.mbt:7:11' + ///| + test "demo_call" { + inspect(demo_call(2), content="6") + ^^^^^^^^^ + ```moonbit + fn @bzy-debug/sample.demo_call(x : Int) -> Int + ``` + } diff --git a/sample/generated_outline.t b/sample/generated_outline.t new file mode 100644 index 0000000..bc7ca97 --- /dev/null +++ b/sample/generated_outline.t @@ -0,0 +1,28 @@ + $ export MOON_HOME="${MOON_HOME:-$HOME/.moon}" + $ export BUILD_PATH_PREFIX_MAP="\$MOON_HOME=$MOON_HOME:$BUILD_PATH_PREFIX_MAP" + $ moon ide outline 'cmd/main/main.mbt' + L5 | fn main { + ... + + $ moon ide outline 'sample.mbt' + L03 | pub type Item = Int + ... + L05 | pub trait Worker { + ... + L09 | pub fn make_item(x : Int) -> Item { + ... + L13 | pub let default_item : Item = 1 + ... + L15 | pub fn use_features() -> Int { + ... + L21 | impl Worker for Int with run(self, delta) { + ... + L25 | pub fn demo_call(x : Int) -> Int { + ... + + $ moon ide outline 'sample_test.mbt' + L6 | test "demo_call" { + ... + + $ moon ide outline 'sample_wbtest.mbt' + No symbols found. diff --git a/sample/generated_peek_def.t b/sample/generated_peek_def.t new file mode 100644 index 0000000..1f39925 --- /dev/null +++ b/sample/generated_peek_def.t @@ -0,0 +1,665 @@ + $ export MOON_HOME="${MOON_HOME:-$HOME/.moon}" + $ export BUILD_PATH_PREFIX_MAP="\$MOON_HOME=$MOON_HOME:$BUILD_PATH_PREFIX_MAP" + $ moon ide peek-def Item --loc 'sample.mbt:3:10' + Error: could not find definition for symbol 'Item' at sample.mbt:3:10 + [1] + $ moon ide peek-def Worker --loc 'sample.mbt:5:11' + Definition found at file $TESTCASE_ROOT/sample.mbt + | ///| + | /// Sample source used by testgen. + | pub type Item = Int + | + 5 | pub trait Worker { + | ^ + | run(Self, Int) -> Int + | } + | + | pub fn make_item(x : Int) -> Item { + | x + | } + | + | pub let default_item : Item = 1 + | + | pub fn use_features() -> Int { + | let xs = [1, 2, 3] + | let n = xs.length() + | Int::abs(-n) + | } + | + | impl Worker for Int with run(self, delta) { + $ moon ide peek-def run --loc 'sample.mbt:6:3' + Definition found at file $TESTCASE_ROOT/sample.mbt + | ///| + | /// Sample source used by testgen. + | pub type Item = Int + | + | pub trait Worker { + 6 | run(Self, Int) -> Int + | ^^^^^^^^^^^^^^^^^^^^^ + | } + | + | pub fn make_item(x : Int) -> Item { + | x + | } + | + | pub let default_item : Item = 1 + | + | pub fn use_features() -> Int { + | let xs = [1, 2, 3] + | let n = xs.length() + | Int::abs(-n) + | } + | + $ moon ide peek-def make_item --loc 'sample.mbt:9:8' + Definition found at file $TESTCASE_ROOT/sample.mbt + | + | pub trait Worker { + | run(Self, Int) -> Int + | } + | + 9 | pub fn make_item(x : Int) -> Item { + | ^^^^^^^^^ + | x + | } + | + | pub let default_item : Item = 1 + | + | pub fn use_features() -> Int { + | let xs = [1, 2, 3] + | let n = xs.length() + | Int::abs(-n) + | } + | + | impl Worker for Int with run(self, delta) { + | self + delta + | } + $ moon ide peek-def x --loc 'sample.mbt:9:18' + Definition found at file $TESTCASE_ROOT/sample.mbt + | + | pub trait Worker { + | run(Self, Int) -> Int + | } + | + 9 | pub fn make_item(x : Int) -> Item { + | ^ + | x + | } + | + | pub let default_item : Item = 1 + | + | pub fn use_features() -> Int { + | let xs = [1, 2, 3] + | let n = xs.length() + | Int::abs(-n) + | } + | + | impl Worker for Int with run(self, delta) { + | self + delta + | } + $ moon ide peek-def Item --loc 'sample.mbt:9:30' + Error: could not find definition for symbol 'Item' at sample.mbt:9:30 + [1] + $ moon ide peek-def x --loc 'sample.mbt:10:3' + Definition found at file $TESTCASE_ROOT/sample.mbt + | + | pub trait Worker { + | run(Self, Int) -> Int + | } + | + 9 | pub fn make_item(x : Int) -> Item { + | ^ + | x + | } + | + | pub let default_item : Item = 1 + | + | pub fn use_features() -> Int { + | let xs = [1, 2, 3] + | let n = xs.length() + | Int::abs(-n) + | } + | + | impl Worker for Int with run(self, delta) { + | self + delta + | } + $ moon ide peek-def default_item --loc 'sample.mbt:13:9' + Definition found at file $TESTCASE_ROOT/sample.mbt + | + | pub fn make_item(x : Int) -> Item { + | x + | } + | + 13 | pub let default_item : Item = 1 + | ^^^^^^^^^^^^ + | + | pub fn use_features() -> Int { + | let xs = [1, 2, 3] + | let n = xs.length() + | Int::abs(-n) + | } + | + | impl Worker for Int with run(self, delta) { + | self + delta + | } + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + $ moon ide peek-def Item --loc 'sample.mbt:13:24' + Error: could not find definition for symbol 'Item' at sample.mbt:13:24 + [1] + $ moon ide peek-def use_features --loc 'sample.mbt:15:8' + Definition found at file $TESTCASE_ROOT/sample.mbt + | x + | } + | + | pub let default_item : Item = 1 + | + 15 | pub fn use_features() -> Int { + | ^^^^^^^^^^^^ + | let xs = [1, 2, 3] + | let n = xs.length() + | Int::abs(-n) + | } + | + | impl Worker for Int with run(self, delta) { + | self + delta + | } + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + | } + $ moon ide peek-def xs --loc 'sample.mbt:16:7' + Definition found at file $TESTCASE_ROOT/sample.mbt + | } + | + | pub let default_item : Item = 1 + | + | pub fn use_features() -> Int { + 16 | let xs = [1, 2, 3] + | ^^ + | let n = xs.length() + | Int::abs(-n) + | } + | + | impl Worker for Int with run(self, delta) { + | self + delta + | } + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + | } + $ moon ide peek-def n --loc 'sample.mbt:17:7' + Definition found at file $TESTCASE_ROOT/sample.mbt + | + | pub let default_item : Item = 1 + | + | pub fn use_features() -> Int { + | let xs = [1, 2, 3] + 17 | let n = xs.length() + | ^ + | Int::abs(-n) + | } + | + | impl Worker for Int with run(self, delta) { + | self + delta + | } + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + | } + $ moon ide peek-def length --loc 'sample.mbt:17:14' + Definition found at file $MOON_HOME/lib/core/builtin/arraycore_nonjs.mbt + | /// let empty : Array[Int] = [] + | /// inspect(empty.length(), content="0") + | /// } + | /// ``` + | #intrinsic("%array.length") + 81 | pub fn[T] Array::length(self : Array[T]) -> Int { + | ^^^^^^ + | self.len + | } + | + | ///| + | /// Truncates the array to the specified length. This function is marked as + | /// `unsafe` because it directly manipulates the internal buffer of the array, + | /// which can lead to undefined behavior if not used carefully. + | /// + | /// # Parameters + | /// + | /// - `self` : The array to be truncated. + | /// - `new_len` : The new length to which the array should be truncated. Must be + | /// less than or equal to the current length of the array. + | /// + $ moon ide peek-def xs --loc 'sample.mbt:17:11' + Definition found at file $TESTCASE_ROOT/sample.mbt + | } + | + | pub let default_item : Item = 1 + | + | pub fn use_features() -> Int { + 16 | let xs = [1, 2, 3] + | ^^ + | let n = xs.length() + | Int::abs(-n) + | } + | + | impl Worker for Int with run(self, delta) { + | self + delta + | } + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + | } + $ moon ide peek-def abs --loc 'sample.mbt:18:8' + Definition found at file $MOON_HOME/lib/core/builtin/int.mbt + | /// inspect(Int::abs(42), content="42") + | /// inspect(Int::abs(-42), content="42") + | /// inspect(Int::abs(0), content="0") + | /// } + | /// ``` + 176 | pub fn Int::abs(self : Int) -> Int { + | ^^^ + | if self < 0 { + | -self + | } else { + | self + | } + | } + $ moon ide peek-def n --loc 'sample.mbt:18:13' + Definition found at file $TESTCASE_ROOT/sample.mbt + | + | pub let default_item : Item = 1 + | + | pub fn use_features() -> Int { + | let xs = [1, 2, 3] + 17 | let n = xs.length() + | ^ + | Int::abs(-n) + | } + | + | impl Worker for Int with run(self, delta) { + | self + delta + | } + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + | } + $ moon ide peek-def Worker --loc 'sample.mbt:21:6' + Definition found at file $TESTCASE_ROOT/sample.mbt + | ///| + | /// Sample source used by testgen. + | pub type Item = Int + | + 5 | pub trait Worker { + | ^ + | run(Self, Int) -> Int + | } + | + | pub fn make_item(x : Int) -> Item { + | x + | } + | + | pub let default_item : Item = 1 + | + | pub fn use_features() -> Int { + | let xs = [1, 2, 3] + | let n = xs.length() + | Int::abs(-n) + | } + | + | impl Worker for Int with run(self, delta) { + $ moon ide peek-def run --loc 'sample.mbt:21:26' + Definition found at file $TESTCASE_ROOT/sample.mbt + | let xs = [1, 2, 3] + | let n = xs.length() + | Int::abs(-n) + | } + | + 21 | impl Worker for Int with run(self, delta) { + | ^^^ + | self + delta + | } + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + | } + $ moon ide peek-def self --loc 'sample.mbt:21:30' + Definition found at file $TESTCASE_ROOT/sample.mbt + | let xs = [1, 2, 3] + | let n = xs.length() + | Int::abs(-n) + | } + | + 21 | impl Worker for Int with run(self, delta) { + | ^^^^ + | self + delta + | } + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + | } + $ moon ide peek-def delta --loc 'sample.mbt:21:36' + Definition found at file $TESTCASE_ROOT/sample.mbt + | let xs = [1, 2, 3] + | let n = xs.length() + | Int::abs(-n) + | } + | + 21 | impl Worker for Int with run(self, delta) { + | ^^^^^ + | self + delta + | } + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + | } + $ moon ide peek-def self --loc 'sample.mbt:22:3' + Definition found at file $TESTCASE_ROOT/sample.mbt + | let xs = [1, 2, 3] + | let n = xs.length() + | Int::abs(-n) + | } + | + 21 | impl Worker for Int with run(self, delta) { + | ^^^^ + | self + delta + | } + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + | } + $ moon ide peek-def delta --loc 'sample.mbt:22:10' + Definition found at file $TESTCASE_ROOT/sample.mbt + | let xs = [1, 2, 3] + | let n = xs.length() + | Int::abs(-n) + | } + | + 21 | impl Worker for Int with run(self, delta) { + | ^^^^^ + | self + delta + | } + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + | } + $ moon ide peek-def demo_call --loc 'sample.mbt:25:8' + Definition found at file $TESTCASE_ROOT/sample.mbt + | + | impl Worker for Int with run(self, delta) { + | self + delta + | } + | + 25 | pub fn demo_call(x : Int) -> Int { + | ^^^^^^^^^ + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + | } + $ moon ide peek-def x --loc 'sample.mbt:25:18' + Definition found at file $TESTCASE_ROOT/sample.mbt + | + | impl Worker for Int with run(self, delta) { + | self + delta + | } + | + 25 | pub fn demo_call(x : Int) -> Int { + | ^ + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + | } + $ moon ide peek-def item --loc 'sample.mbt:26:7' + Definition found at file $TESTCASE_ROOT/sample.mbt + | impl Worker for Int with run(self, delta) { + | self + delta + | } + | + | pub fn demo_call(x : Int) -> Int { + 26 | let item = make_item(default_item) + | ^^^^ + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + | } + $ moon ide peek-def make_item --loc 'sample.mbt:26:14' + Definition found at file $TESTCASE_ROOT/sample.mbt + | + | pub trait Worker { + | run(Self, Int) -> Int + | } + | + 9 | pub fn make_item(x : Int) -> Item { + | ^^^^^^^^^ + | x + | } + | + | pub let default_item : Item = 1 + | + | pub fn use_features() -> Int { + | let xs = [1, 2, 3] + | let n = xs.length() + | Int::abs(-n) + | } + | + | impl Worker for Int with run(self, delta) { + | self + delta + | } + $ moon ide peek-def default_item --loc 'sample.mbt:26:24' + Definition found at file $TESTCASE_ROOT/sample.mbt + | + | pub fn make_item(x : Int) -> Item { + | x + | } + | + 13 | pub let default_item : Item = 1 + | ^^^^^^^^^^^^ + | + | pub fn use_features() -> Int { + | let xs = [1, 2, 3] + | let n = xs.length() + | Int::abs(-n) + | } + | + | impl Worker for Int with run(self, delta) { + | self + delta + | } + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + $ moon ide peek-def worker_value --loc 'sample.mbt:27:7' + Definition found at file $TESTCASE_ROOT/sample.mbt + | self + delta + | } + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + 27 | let worker_value = Worker::run(x, item) + | ^^^^^^^^^^^^ + | worker_value + use_features() + | } + $ moon ide peek-def Worker --loc 'sample.mbt:27:22' + Definition found at file $TESTCASE_ROOT/sample.mbt + | ///| + | /// Sample source used by testgen. + | pub type Item = Int + | + 5 | pub trait Worker { + | ^ + | run(Self, Int) -> Int + | } + | + | pub fn make_item(x : Int) -> Item { + | x + | } + | + | pub let default_item : Item = 1 + | + | pub fn use_features() -> Int { + | let xs = [1, 2, 3] + | let n = xs.length() + | Int::abs(-n) + | } + | + | impl Worker for Int with run(self, delta) { + $ moon ide peek-def run --loc 'sample.mbt:27:30' + Definition found at file $TESTCASE_ROOT/sample.mbt + | let xs = [1, 2, 3] + | let n = xs.length() + | Int::abs(-n) + | } + | + 21 | impl Worker for Int with run(self, delta) { + | ^^^ + | self + delta + | } + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + | } + $ moon ide peek-def x --loc 'sample.mbt:27:34' + Definition found at file $TESTCASE_ROOT/sample.mbt + | + | impl Worker for Int with run(self, delta) { + | self + delta + | } + | + 25 | pub fn demo_call(x : Int) -> Int { + | ^ + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + | } + $ moon ide peek-def item --loc 'sample.mbt:27:37' + Definition found at file $TESTCASE_ROOT/sample.mbt + | impl Worker for Int with run(self, delta) { + | self + delta + | } + | + | pub fn demo_call(x : Int) -> Int { + 26 | let item = make_item(default_item) + | ^^^^ + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + | } + $ moon ide peek-def worker_value --loc 'sample.mbt:28:3' + Definition found at file $TESTCASE_ROOT/sample.mbt + | self + delta + | } + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + 27 | let worker_value = Worker::run(x, item) + | ^^^^^^^^^^^^ + | worker_value + use_features() + | } + $ moon ide peek-def use_features --loc 'sample.mbt:28:18' + Definition found at file $TESTCASE_ROOT/sample.mbt + | x + | } + | + | pub let default_item : Item = 1 + | + 15 | pub fn use_features() -> Int { + | ^^^^^^^^^^^^ + | let xs = [1, 2, 3] + | let n = xs.length() + | Int::abs(-n) + | } + | + | impl Worker for Int with run(self, delta) { + | self + delta + | } + | + | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + | } + $ moon ide peek-def demo_call --loc 'sample_test.mbt:7:11' + Definition found at file $TESTCASE_ROOT/sample.mbt + | + | impl Worker for Int with run(self, delta) { + | self + delta + | } + | + 25 | pub fn demo_call(x : Int) -> Int { + | ^^^^^^^^^ + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + | } + $ moon ide peek-def 'Item' + Found 1 symbols matching 'Item': + + `pub type alias Item` in package bzy-debug/sample at $TESTCASE_ROOT/sample.mbt:1-3 + 1 | ///| + | /// Sample source used by testgen. + | pub type Item = Int + $ moon ide peek-def 'Worker' + Found 1 symbols matching 'Worker': + + `pub trait Worker` in package bzy-debug/sample at $TESTCASE_ROOT/sample.mbt:5-7 + 5 | pub trait Worker { + | run(Self, Int) -> Int + | } + $ moon ide peek-def 'make_item' + Found 1 symbols matching 'make_item': + + `pub fn make_item` in package bzy-debug/sample at $TESTCASE_ROOT/sample.mbt:9-11 + 9 | pub fn make_item(x : Int) -> Item { + | x + | } + $ moon ide peek-def 'default_item' + Found 1 symbols matching 'default_item': + + `pub let default_item` in package bzy-debug/sample at $TESTCASE_ROOT/sample.mbt:13-13 + 13 | pub let default_item : Item = 1 + $ moon ide peek-def 'use_features' + Found 1 symbols matching 'use_features': + + `pub fn use_features` in package bzy-debug/sample at $TESTCASE_ROOT/sample.mbt:15-19 + 15 | pub fn use_features() -> Int { + | let xs = [1, 2, 3] + | let n = xs.length() + | Int::abs(-n) + | } + $ moon ide peek-def 'Worker::run for Int' + Found 1 symbols matching 'Worker::run for Int': + + `impl Worker::run for Int` in package bzy-debug/sample at $TESTCASE_ROOT/sample.mbt:21-23 + 21 | impl Worker for Int with run(self, delta) { + | self + delta + | } + $ moon ide peek-def 'demo_call' + Found 1 symbols matching 'demo_call': + + `pub fn demo_call` in package bzy-debug/sample at $TESTCASE_ROOT/sample.mbt:25-29 + 25 | pub fn demo_call(x : Int) -> Int { + | let item = make_item(default_item) + | let worker_value = Worker::run(x, item) + | worker_value + use_features() + | } diff --git a/sample/generated_rename.t b/sample/generated_rename.t new file mode 100644 index 0000000..d6157a9 --- /dev/null +++ b/sample/generated_rename.t @@ -0,0 +1,769 @@ + $ export MOON_HOME="${MOON_HOME:-$HOME/.moon}" + $ export BUILD_PATH_PREFIX_MAP="\$MOON_HOME=$MOON_HOME:$BUILD_PATH_PREFIX_MAP" + $ moon ide rename Item ItemRenamed --loc 'sample.mbt:3:10' + Error: could not find references for symbol 'Item' at sample.mbt:3:10 + [1] + $ moon ide rename Worker WorkerRenamed --loc 'sample.mbt:5:11' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + /// Sample source used by testgen. + pub type Item = Int + + -pub trait Worker { + +pub trait WorkerRenamed { + run(Self, Int) -> Int + } + + @@ + Int::abs(-n) + } + + -impl Worker for Int with run(self, delta) { + +impl WorkerRenamed for Int with run(self, delta) { + self + delta + } + + pub fn demo_call(x : Int) -> Int { + let item = make_item(default_item) + - let worker_value = Worker::run(x, item) + + let worker_value = WorkerRenamed::run(x, item) + worker_value + use_features() + } + *** End Patch + + $ moon ide rename run run_renamed --loc 'sample.mbt:6:3' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + pub type Item = Int + + pub trait Worker { + - run(Self, Int) -> Int + + run_renamed(Self, Int) -> Int + } + + pub fn make_item(x : Int) -> Item { + @@ + Int::abs(-n) + } + + -impl Worker for Int with run(self, delta) { + +impl Worker for Int with run_renamed(self, delta) { + self + delta + } + + pub fn demo_call(x : Int) -> Int { + let item = make_item(default_item) + - let worker_value = Worker::run(x, item) + + let worker_value = Worker::run_renamed(x, item) + worker_value + use_features() + } + *** End Patch + + $ moon ide rename make_item make_item_renamed --loc 'sample.mbt:9:8' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + run(Self, Int) -> Int + } + + -pub fn make_item(x : Int) -> Item { + +pub fn make_item_renamed(x : Int) -> Item { + x + } + + @@ + } + + pub fn demo_call(x : Int) -> Int { + - let item = make_item(default_item) + + let item = make_item_renamed(default_item) + let worker_value = Worker::run(x, item) + worker_value + use_features() + } + *** End Patch + + $ moon ide rename x x_renamed --loc 'sample.mbt:9:18' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + run(Self, Int) -> Int + } + + -pub fn make_item(x : Int) -> Item { + +pub fn make_item(x_renamed : Int) -> Item { + - x + + x_renamed + } + + pub let default_item : Item = 1 + *** End Patch + + $ moon ide rename Item ItemRenamed --loc 'sample.mbt:9:30' + Error: could not find references for symbol 'Item' at sample.mbt:9:30 + [1] + $ moon ide rename x x_renamed --loc 'sample.mbt:10:3' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + run(Self, Int) -> Int + } + + -pub fn make_item(x : Int) -> Item { + +pub fn make_item(x_renamed : Int) -> Item { + - x + + x_renamed + } + + pub let default_item : Item = 1 + *** End Patch + + $ moon ide rename default_item default_item_renamed --loc 'sample.mbt:13:9' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + x + } + + -pub let default_item : Item = 1 + +pub let default_item_renamed : Item = 1 + + pub fn use_features() -> Int { + let xs = [1, 2, 3] + @@ + } + + pub fn demo_call(x : Int) -> Int { + - let item = make_item(default_item) + + let item = make_item(default_item_renamed) + let worker_value = Worker::run(x, item) + worker_value + use_features() + } + *** End Patch + + $ moon ide rename Item ItemRenamed --loc 'sample.mbt:13:24' + Error: could not find references for symbol 'Item' at sample.mbt:13:24 + [1] + $ moon ide rename use_features use_features_renamed --loc 'sample.mbt:15:8' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + + pub let default_item : Item = 1 + + -pub fn use_features() -> Int { + +pub fn use_features_renamed() -> Int { + let xs = [1, 2, 3] + let n = xs.length() + Int::abs(-n) + @@ + pub fn demo_call(x : Int) -> Int { + let item = make_item(default_item) + let worker_value = Worker::run(x, item) + - worker_value + use_features() + + worker_value + use_features_renamed() + } + *** End Patch + + $ moon ide rename xs xs_renamed --loc 'sample.mbt:16:7' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + pub let default_item : Item = 1 + + pub fn use_features() -> Int { + - let xs = [1, 2, 3] + + let xs_renamed = [1, 2, 3] + - let n = xs.length() + + let n = xs_renamed.length() + Int::abs(-n) + } + + *** End Patch + + $ moon ide rename n n_renamed --loc 'sample.mbt:17:7' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + + pub fn use_features() -> Int { + let xs = [1, 2, 3] + - let n = xs.length() + + let n_renamed = xs.length() + - Int::abs(-n) + + Int::abs(-n_renamed) + } + + impl Worker for Int with run(self, delta) { + *** End Patch + + $ moon ide rename length length_renamed --loc 'sample.mbt:17:14' + Error: cannot rename symbol 'length' in package 'moonbitlang/core/builtin' outside of module 'bzy-debug/sample' + [1] + $ moon ide rename xs xs_renamed --loc 'sample.mbt:17:11' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + pub let default_item : Item = 1 + + pub fn use_features() -> Int { + - let xs = [1, 2, 3] + + let xs_renamed = [1, 2, 3] + - let n = xs.length() + + let n = xs_renamed.length() + Int::abs(-n) + } + + *** End Patch + + $ moon ide rename abs abs_renamed --loc 'sample.mbt:18:8' + Error: cannot rename symbol 'abs' in package 'moonbitlang/core/builtin' outside of module 'bzy-debug/sample' + [1] + $ moon ide rename n n_renamed --loc 'sample.mbt:18:13' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + + pub fn use_features() -> Int { + let xs = [1, 2, 3] + - let n = xs.length() + + let n_renamed = xs.length() + - Int::abs(-n) + + Int::abs(-n_renamed) + } + + impl Worker for Int with run(self, delta) { + *** End Patch + + $ moon ide rename Worker WorkerRenamed --loc 'sample.mbt:21:6' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + /// Sample source used by testgen. + pub type Item = Int + + -pub trait Worker { + +pub trait WorkerRenamed { + run(Self, Int) -> Int + } + + @@ + Int::abs(-n) + } + + -impl Worker for Int with run(self, delta) { + +impl WorkerRenamed for Int with run(self, delta) { + self + delta + } + + pub fn demo_call(x : Int) -> Int { + let item = make_item(default_item) + - let worker_value = Worker::run(x, item) + + let worker_value = WorkerRenamed::run(x, item) + worker_value + use_features() + } + *** End Patch + + $ moon ide rename run run_renamed --loc 'sample.mbt:21:26' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + pub type Item = Int + + pub trait Worker { + - run(Self, Int) -> Int + + run_renamed(Self, Int) -> Int + } + + pub fn make_item(x : Int) -> Item { + @@ + Int::abs(-n) + } + + -impl Worker for Int with run(self, delta) { + +impl Worker for Int with run_renamed(self, delta) { + self + delta + } + + pub fn demo_call(x : Int) -> Int { + let item = make_item(default_item) + - let worker_value = Worker::run(x, item) + + let worker_value = Worker::run_renamed(x, item) + worker_value + use_features() + } + *** End Patch + + $ moon ide rename self self_renamed --loc 'sample.mbt:21:30' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + Int::abs(-n) + } + + -impl Worker for Int with run(self, delta) { + +impl Worker for Int with run(self_renamed, delta) { + - self + delta + + self_renamed + delta + } + + pub fn demo_call(x : Int) -> Int { + *** End Patch + + $ moon ide rename delta delta_renamed --loc 'sample.mbt:21:36' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + Int::abs(-n) + } + + -impl Worker for Int with run(self, delta) { + +impl Worker for Int with run(self, delta_renamed) { + - self + delta + + self + delta_renamed + } + + pub fn demo_call(x : Int) -> Int { + *** End Patch + + $ moon ide rename self self_renamed --loc 'sample.mbt:22:3' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + Int::abs(-n) + } + + -impl Worker for Int with run(self, delta) { + +impl Worker for Int with run(self_renamed, delta) { + - self + delta + + self_renamed + delta + } + + pub fn demo_call(x : Int) -> Int { + *** End Patch + + $ moon ide rename delta delta_renamed --loc 'sample.mbt:22:10' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + Int::abs(-n) + } + + -impl Worker for Int with run(self, delta) { + +impl Worker for Int with run(self, delta_renamed) { + - self + delta + + self + delta_renamed + } + + pub fn demo_call(x : Int) -> Int { + *** End Patch + + $ moon ide rename demo_call demo_call_renamed --loc 'sample.mbt:25:8' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + self + delta + } + + -pub fn demo_call(x : Int) -> Int { + +pub fn demo_call_renamed(x : Int) -> Int { + let item = make_item(default_item) + let worker_value = Worker::run(x, item) + worker_value + use_features() + *** Update File: $TESTCASE_ROOT/sample_test.mbt + @@ + + ///| + test "demo_call" { + - inspect(demo_call(2), content="6") + + inspect(demo_call_renamed(2), content="6") + } + *** End Patch + + $ moon ide rename x x_renamed --loc 'sample.mbt:25:18' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + self + delta + } + + -pub fn demo_call(x : Int) -> Int { + +pub fn demo_call(x_renamed : Int) -> Int { + let item = make_item(default_item) + - let worker_value = Worker::run(x, item) + + let worker_value = Worker::run(x_renamed, item) + worker_value + use_features() + } + *** End Patch + + $ moon ide rename item item_renamed --loc 'sample.mbt:26:7' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + } + + pub fn demo_call(x : Int) -> Int { + - let item = make_item(default_item) + + let item_renamed = make_item(default_item) + - let worker_value = Worker::run(x, item) + + let worker_value = Worker::run(x, item_renamed) + worker_value + use_features() + } + *** End Patch + + $ moon ide rename make_item make_item_renamed --loc 'sample.mbt:26:14' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + run(Self, Int) -> Int + } + + -pub fn make_item(x : Int) -> Item { + +pub fn make_item_renamed(x : Int) -> Item { + x + } + + @@ + } + + pub fn demo_call(x : Int) -> Int { + - let item = make_item(default_item) + + let item = make_item_renamed(default_item) + let worker_value = Worker::run(x, item) + worker_value + use_features() + } + *** End Patch + + $ moon ide rename default_item default_item_renamed --loc 'sample.mbt:26:24' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + x + } + + -pub let default_item : Item = 1 + +pub let default_item_renamed : Item = 1 + + pub fn use_features() -> Int { + let xs = [1, 2, 3] + @@ + } + + pub fn demo_call(x : Int) -> Int { + - let item = make_item(default_item) + + let item = make_item(default_item_renamed) + let worker_value = Worker::run(x, item) + worker_value + use_features() + } + *** End Patch + + $ moon ide rename worker_value worker_value_renamed --loc 'sample.mbt:27:7' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + + pub fn demo_call(x : Int) -> Int { + let item = make_item(default_item) + - let worker_value = Worker::run(x, item) + + let worker_value_renamed = Worker::run(x, item) + - worker_value + use_features() + + worker_value_renamed + use_features() + } + *** End Patch + + $ moon ide rename Worker WorkerRenamed --loc 'sample.mbt:27:22' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + /// Sample source used by testgen. + pub type Item = Int + + -pub trait Worker { + +pub trait WorkerRenamed { + run(Self, Int) -> Int + } + + @@ + Int::abs(-n) + } + + -impl Worker for Int with run(self, delta) { + +impl WorkerRenamed for Int with run(self, delta) { + self + delta + } + + pub fn demo_call(x : Int) -> Int { + let item = make_item(default_item) + - let worker_value = Worker::run(x, item) + + let worker_value = WorkerRenamed::run(x, item) + worker_value + use_features() + } + *** End Patch + + $ moon ide rename run run_renamed --loc 'sample.mbt:27:30' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + pub type Item = Int + + pub trait Worker { + - run(Self, Int) -> Int + + run_renamed(Self, Int) -> Int + } + + pub fn make_item(x : Int) -> Item { + @@ + Int::abs(-n) + } + + -impl Worker for Int with run(self, delta) { + +impl Worker for Int with run_renamed(self, delta) { + self + delta + } + + pub fn demo_call(x : Int) -> Int { + let item = make_item(default_item) + - let worker_value = Worker::run(x, item) + + let worker_value = Worker::run_renamed(x, item) + worker_value + use_features() + } + *** End Patch + + $ moon ide rename x x_renamed --loc 'sample.mbt:27:34' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + self + delta + } + + -pub fn demo_call(x : Int) -> Int { + +pub fn demo_call(x_renamed : Int) -> Int { + let item = make_item(default_item) + - let worker_value = Worker::run(x, item) + + let worker_value = Worker::run(x_renamed, item) + worker_value + use_features() + } + *** End Patch + + $ moon ide rename item item_renamed --loc 'sample.mbt:27:37' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + } + + pub fn demo_call(x : Int) -> Int { + - let item = make_item(default_item) + + let item_renamed = make_item(default_item) + - let worker_value = Worker::run(x, item) + + let worker_value = Worker::run(x, item_renamed) + worker_value + use_features() + } + *** End Patch + + $ moon ide rename worker_value worker_value_renamed --loc 'sample.mbt:28:3' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + + pub fn demo_call(x : Int) -> Int { + let item = make_item(default_item) + - let worker_value = Worker::run(x, item) + + let worker_value_renamed = Worker::run(x, item) + - worker_value + use_features() + + worker_value_renamed + use_features() + } + *** End Patch + + $ moon ide rename use_features use_features_renamed --loc 'sample.mbt:28:18' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + + pub let default_item : Item = 1 + + -pub fn use_features() -> Int { + +pub fn use_features_renamed() -> Int { + let xs = [1, 2, 3] + let n = xs.length() + Int::abs(-n) + @@ + pub fn demo_call(x : Int) -> Int { + let item = make_item(default_item) + let worker_value = Worker::run(x, item) + - worker_value + use_features() + + worker_value + use_features_renamed() + } + *** End Patch + + $ moon ide rename demo_call demo_call_renamed --loc 'sample_test.mbt:7:11' + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + self + delta + } + + -pub fn demo_call(x : Int) -> Int { + +pub fn demo_call_renamed(x : Int) -> Int { + let item = make_item(default_item) + let worker_value = Worker::run(x, item) + worker_value + use_features() + *** Update File: $TESTCASE_ROOT/sample_test.mbt + @@ + + ///| + test "demo_call" { + - inspect(demo_call(2), content="6") + + inspect(demo_call_renamed(2), content="6") + } + *** End Patch + + $ moon ide rename 'Item' ItemRenamed + No references found for symbol 'Item' + [1] + $ moon ide rename 'Worker' WorkerRenamed + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + /// Sample source used by testgen. + pub type Item = Int + + -pub trait Worker { + +pub trait WorkerRenamed { + run(Self, Int) -> Int + } + + @@ + Int::abs(-n) + } + + -impl Worker for Int with run(self, delta) { + +impl WorkerRenamed for Int with run(self, delta) { + self + delta + } + + pub fn demo_call(x : Int) -> Int { + let item = make_item(default_item) + - let worker_value = Worker::run(x, item) + + let worker_value = WorkerRenamed::run(x, item) + worker_value + use_features() + } + *** End Patch + + $ moon ide rename 'make_item' make_item_renamed + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + run(Self, Int) -> Int + } + + -pub fn make_item(x : Int) -> Item { + +pub fn make_item_renamed(x : Int) -> Item { + x + } + + @@ + } + + pub fn demo_call(x : Int) -> Int { + - let item = make_item(default_item) + + let item = make_item_renamed(default_item) + let worker_value = Worker::run(x, item) + worker_value + use_features() + } + *** End Patch + + $ moon ide rename 'default_item' default_item_renamed + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + x + } + + -pub let default_item : Item = 1 + +pub let default_item_renamed : Item = 1 + + pub fn use_features() -> Int { + let xs = [1, 2, 3] + @@ + } + + pub fn demo_call(x : Int) -> Int { + - let item = make_item(default_item) + + let item = make_item(default_item_renamed) + let worker_value = Worker::run(x, item) + worker_value + use_features() + } + *** End Patch + + $ moon ide rename 'use_features' use_features_renamed + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + + pub let default_item : Item = 1 + + -pub fn use_features() -> Int { + +pub fn use_features_renamed() -> Int { + let xs = [1, 2, 3] + let n = xs.length() + Int::abs(-n) + @@ + pub fn demo_call(x : Int) -> Int { + let item = make_item(default_item) + let worker_value = Worker::run(x, item) + - worker_value + use_features() + + worker_value + use_features_renamed() + } + *** End Patch + + $ moon ide rename 'Worker::run for Int' run_renamed + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + pub type Item = Int + + pub trait Worker { + - run(Self, Int) -> Int + + run_renamed(Self, Int) -> Int + } + + pub fn make_item(x : Int) -> Item { + @@ + Int::abs(-n) + } + + -impl Worker for Int with run(self, delta) { + +impl Worker for Int with run_renamed(self, delta) { + self + delta + } + + pub fn demo_call(x : Int) -> Int { + let item = make_item(default_item) + - let worker_value = Worker::run(x, item) + + let worker_value = Worker::run_renamed(x, item) + worker_value + use_features() + } + *** End Patch + + $ moon ide rename 'demo_call' demo_call_renamed + *** Begin Patch + *** Update File: $TESTCASE_ROOT/sample.mbt + @@ + self + delta + } + + -pub fn demo_call(x : Int) -> Int { + +pub fn demo_call_renamed(x : Int) -> Int { + let item = make_item(default_item) + let worker_value = Worker::run(x, item) + worker_value + use_features() + *** Update File: $TESTCASE_ROOT/sample_test.mbt + @@ + + ///| + test "demo_call" { + - inspect(demo_call(2), content="6") + + inspect(demo_call_renamed(2), content="6") + } + *** End Patch + diff --git a/sample/moon.mod.json b/sample/moon.mod.json new file mode 100644 index 0000000..28a8be9 --- /dev/null +++ b/sample/moon.mod.json @@ -0,0 +1,9 @@ +{ + "name": "bzy-debug/sample", + "version": "0.1.0", + "readme": "README.mbt.md", + "repository": "", + "license": "Apache-2.0", + "keywords": [], + "description": "" +} \ No newline at end of file diff --git a/sample/moon.pkg b/sample/moon.pkg new file mode 100644 index 0000000..e69de29 diff --git a/sample/sample.mbt b/sample/sample.mbt new file mode 100644 index 0000000..6fbf3d4 --- /dev/null +++ b/sample/sample.mbt @@ -0,0 +1,29 @@ +///| +/// Sample source used by testgen. +pub type Item = Int + +pub trait Worker { + run(Self, Int) -> Int +} + +pub fn make_item(x : Int) -> Item { + x +} + +pub let default_item : Item = 1 + +pub fn use_features() -> Int { + let xs = [1, 2, 3] + let n = xs.length() + Int::abs(-n) +} + +impl Worker for Int with run(self, delta) { + self + delta +} + +pub fn demo_call(x : Int) -> Int { + let item = make_item(default_item) + let worker_value = Worker::run(x, item) + worker_value + use_features() +} diff --git a/sample/sample_test.mbt b/sample/sample_test.mbt new file mode 100644 index 0000000..2bc7c6f --- /dev/null +++ b/sample/sample_test.mbt @@ -0,0 +1,8 @@ +// Blackbox tests run against the package's public API. Use `@sample` to import. +// Prefer high-level behaviors over implementation details. +// Run `moon test` to execute and `moon test --update` to refresh snapshots. + +///| +test "demo_call" { + inspect(demo_call(2), content="6") +} diff --git a/sample/sample_wbtest.mbt b/sample/sample_wbtest.mbt new file mode 100644 index 0000000..10fda4f --- /dev/null +++ b/sample/sample_wbtest.mbt @@ -0,0 +1,3 @@ +// Whitebox tests run within the package scope. +// Use them to validate internal helpers or invariants. +// Keep them focused; public behavior belongs in `_test.mbt`. diff --git a/testgen/.gitignore b/testgen/.gitignore new file mode 100644 index 0000000..efa2da1 --- /dev/null +++ b/testgen/.gitignore @@ -0,0 +1,6 @@ +.DS_Store +_build/ +target/ +target +.mooncakes/ +.moonagent/ \ No newline at end of file diff --git a/testgen/LICENSE b/testgen/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/testgen/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/testgen/README.mbt.md b/testgen/README.mbt.md new file mode 100644 index 0000000..7fb5596 --- /dev/null +++ b/testgen/README.mbt.md @@ -0,0 +1,48 @@ +# testgen + +`testgen` generates cram `.t` snapshots for `moon ide` from a MoonBit project. + +Generated suites: +- `generated_outline.t` +- `generated_hover.t` +- `generated_peek_def.t` +- `generated_find_references.t` +- `generated_rename.t` + +All generated files are written to the target project's root directory. + +## Usage + +Run from this repository root: + +```sh +moon -C testgen run . -- tests/example +``` + +## Options + +- `[project]`: project root to scan (default: current directory) +- `--max-per-file `: max collected AST locations with `--loc` per source file (default: `50`) +- `--help`: print help + +## Notes + +- The tool scans `.mbt` files recursively under project root. +- `_build`, `target`, and `node_modules` are skipped. +- Symbol collection is AST-based (`moonbitlang/parser/syntax` visitor), not string scanning. +- `hover` uses only location-based nodes (`--loc`). +- `peek-def`, `find-references`, and `rename` use location-based nodes first, then toplevel queries without `--loc`. +- Toplevel queries are generated by symbol kind: + - `sym` for value/function/type/trait targets. + - `T::sym` for method-style targets. + - `Trait::meth for Type` for trait impl methods. +- `main` function symbols are excluded from collection. +- Legacy alias syntaxes (`fnalias`/`typealias`/`traitalias`) are not included in toplevel symbol collection. +- `outline` is generated per `.mbt` file and does not depend on parser output. +- Every generated `.t` file begins with: + - ` $ export MOON_HOME="${MOON_HOME:-$HOME/.moon}"` + - ` $ export BUILD_PATH_PREFIX_MAP="\$MOON_HOME=$MOON_HOME:$BUILD_PATH_PREFIX_MAP"` +- If the target project root has no `dune` file, `testgen` creates one with: + - `(cram` + - ` (deps` + - ` (source_tree .)))` diff --git a/testgen/collect.mbt b/testgen/collect.mbt new file mode 100644 index 0000000..67f6a1e --- /dev/null +++ b/testgen/collect.mbt @@ -0,0 +1,582 @@ +///| +fn should_keep_symbol(sym : String) -> Bool { + if not(sym lexmatch? "[A-Za-z_][A-Za-z0-9_]*") { + false + } else { + // Keep in sync with prelude/builtin symbols that should not become ide test targets. + match sym { + "main" + | "Self" + // Prelude values + | "abort" + | "assert_eq" + | "assert_false" + | "assert_not_eq" + | "assert_true" + | "debug" + | "debug_inspect" + | "dump" + | "fail" + | "ignore" + | "inspect" + | "json_inspect" + | "not" + | "null" + | "panic" + | "physical_equal" + | "println" + | "repr" + | "tap" + | "then" + // Prelude types + | "ArgsLoc" + | "Array" + | "ArrayView" + | "BigInt" + | "Failure" + | "Hasher" + | "InspectError" + | "Iter" + | "Iter2" + | "IterResult" + | "Iterator" + | "Iterator2" + | "Json" + | "Map" + | "MutArrayView" + | "Repr" + | "Set" + | "SnapshotError" + | "SourceLoc" + | "StringBuilder" + | "UninitializedArray" + // Prelude traits + | "Add" + | "BitAnd" + | "BitOr" + | "BitXOr" + | "Compare" + | "Debug" + | "Default" + | "Div" + | "Eq" + | "FromJson" + | "Hash" + | "Logger" + | "Mod" + | "Mul" + | "Neg" + | "Shl" + | "Show" + | "Shr" + | "Sub" + | "ToJson" + // Compiler builtins and constructors + | "Unit" + | "Bool" + | "Char" + | "Byte" + | "Int16" + | "UInt16" + | "Int" + | "Int64" + | "UInt" + | "UInt64" + | "Float" + | "Double" + | "String" + | "Bytes" + | "Ref" + | "FixedArray" + | "ReadonlyArray" + | "MaybeUninit" + | "FuncRef" + | "StringView" + | "BytesView" + | "Option" + | "Result" + | "Error" + | "Some" + | "None" + | "Ok" + | "Err" => false + _ => true + } + } +} + +///| +priv struct HoverCollector { + file : String + max_per_file : Int + out : Array[TestCase] + seen : @hashset.HashSet[TestCase] + count : Ref[Int] +} + +///| +fn HoverCollector::append_symbol( + self : HoverCollector, + sym : String, + line : Int, + col : Int, +) -> Unit { + if not(should_keep_symbol(sym)) { + return + } + if self.count.val >= self.max_per_file { + return + } + let normalized_col = if col <= 0 { 1 } else { col } + let test_case = TestCase::{ file: self.file, line, col: normalized_col, sym } + if self.seen.contains(test_case) { + return + } + self.seen.add(test_case) + self.out.push(test_case) + self.count.val = self.count.val + 1 +} + +///| +fn HoverCollector::append_from_loc( + self : HoverCollector, + sym : String, + loc : @basic.Location, +) -> Unit { + let line = loc.start.lnum + let col = loc.start.column() + self.append_symbol(sym, line, col) +} + +///| +fn HoverCollector::append_from_long_ident( + self : HoverCollector, + long_ident : @syntax.LongIdent, + loc : @basic.Location, +) -> Unit { + match long_ident { + @syntax.LongIdent::Ident(name~) => self.append_from_loc(name, loc) + @syntax.LongIdent::Dot(pkg~, id~) => { + ignore(pkg) + let line = loc.end.lnum + let col = loc.end.column() - id.length() + self.append_symbol(id, line, col) + } + } +} + +///| +impl @syntax.IterVisitor for HoverCollector + +///| +impl @syntax.IterVisitor for HoverCollector with visit_Binder(env, binder) { + env.append_from_loc(binder.name, binder.loc) +} + +///| +impl @syntax.IterVisitor for HoverCollector with visit_FieldName( + env, + field_name, +) { + env.append_from_loc(field_name.label, field_name.loc) +} + +///| +impl @syntax.IterVisitor for HoverCollector with visit_Label(env, label) { + env.append_from_loc(label.name, label.loc) +} + +///| +impl @syntax.IterVisitor for HoverCollector with visit_TypeDeclBinder( + env, + type_decl_binder, +) { + if type_decl_binder.name is Some(name) { + env.append_from_loc(name, type_decl_binder.loc) + } +} + +///| +impl @syntax.IterVisitor for HoverCollector with visit_TypeDecl(env, type_decl) { + env.append_from_loc(type_decl.tycon, type_decl.tycon_loc) + type_decl.params.each(x => env.visit_TypeDeclBinder(x)) + env.visit_TypeDesc(type_decl.components) + type_decl.deriving.each(x => env.visit_DerivingDirective(x)) + env.visit_Visibility(type_decl.type_vis) +} + +///| +impl @syntax.IterVisitor for HoverCollector with visit_Var(env, var_) { + env.append_from_long_ident(var_.name, var_.loc) +} + +///| +impl @syntax.IterVisitor for HoverCollector with visit_TypeName(env, type_name) { + env.append_from_long_ident(type_name.name, type_name.loc) +} + +///| +impl @syntax.IterVisitor for HoverCollector with visit_ConstrId(env, constr_id) { + env.append_from_long_ident(constr_id.id, constr_id.loc) +} + +///| +impl @syntax.IterVisitor for HoverCollector with visit_ConstrDecl( + env, + constr_decl, +) { + env.append_from_loc(constr_decl.name.name, constr_decl.name.loc) + match constr_decl.args { + Some(args) => args.each(arg => env.visit_ConstrParam(arg)) + None => () + } +} + +///| +impl @syntax.IterVisitor for HoverCollector with visit_Constructor( + env, + constructor_, +) { + env.append_from_loc(constructor_.name.name, constructor_.name.loc) + env.visit_ConstructorExtraInfo(constructor_.extra_info) +} + +///| +impl @syntax.IterVisitor for HoverCollector with visit_Accessor_Label( + env, + label, +) { + env.append_from_loc(label.name, label.loc) +} + +///| +impl @syntax.IterVisitor for HoverCollector with visit_Expr_DotApply( + env, + self~, + method_name~, + args~, + return_self~, + attr~, + loc~, +) { + ignore(return_self) + ignore(loc) + env.append_from_loc(method_name.name, method_name.loc) + env.visit_Expr(self) + args.each(arg => env.visit_Argument(arg)) + env.visit_ApplyAttr(attr) +} + +///| +fn long_ident_tail(long_ident : @syntax.LongIdent) -> String { + match long_ident { + @syntax.LongIdent::Ident(name~) => name + @syntax.LongIdent::Dot(pkg~, id~) => { + ignore(pkg) + id + } + } +} + +///| +fn type_to_query(ty : @syntax.Type) -> String? { + match ty { + @syntax.Type::Any(..) | @syntax.Type::Arrow(..) => None + @syntax.Type::Tuple(tys~, ..) => { + let parts = Array::new() + for item in tys { + match type_to_query(item) { + Some(part) => parts.push(part) + None => return None + } + } + let joined = parts.join(", ") + Some("(\{joined})") + } + @syntax.Type::Name(constr_id~, tys~, ..) => { + let base = long_ident_tail(constr_id.id) + if tys.is_empty() { + Some(base) + } else { + let args = Array::new() + for item in tys { + match type_to_query(item) { + Some(part) => args.push(part) + None => return None + } + } + let joined = args.join(", ") + Some("\{base}[\{joined}]") + } + } + @syntax.Type::Option(ty~, ..) => + match type_to_query(ty) { + Some(name) => Some("\{name}?") + None => None + } + @syntax.Type::Object(constr_id) => Some(long_ident_tail(constr_id.id)) + } +} + +///| +fn make_toplevel_case( + file : String, + query : String, + rename_sym : String, + loc : @basic.Location, +) -> ToplevelCase { + let col = loc.start.column() + let normalized_col = if col <= 0 { 1 } else { col } + ToplevelCase::{ + file, + line: loc.start.lnum, + col: normalized_col, + query, + rename_sym, + } +} + +///| +fn render_toplevel_cases( + file : String, + impl_ : @syntax.Impl, +) -> Array[ToplevelCase] { + let queries = Array::new() + match impl_ { + @syntax.Impl::TopTypeDef(type_decl) => + queries.push( + make_toplevel_case( + file, + type_decl.tycon, + type_decl.tycon, + type_decl.tycon_loc, + ), + ) + @syntax.Impl::TopFuncDef(fun_decl~, ..) => { + let func_name = fun_decl.name.name + match fun_decl.type_name { + Some(type_name) => + queries.push( + make_toplevel_case( + file, + "\{long_ident_tail(type_name.name)}::\{func_name}", + func_name, + fun_decl.name.loc, + ), + ) + None => + queries.push( + make_toplevel_case(file, func_name, func_name, fun_decl.name.loc), + ) + } + } + @syntax.Impl::TopLetDef(binder~, ..) => + queries.push( + make_toplevel_case(file, binder.name, binder.name, binder.loc), + ) + @syntax.Impl::TopTrait(trait_decl) => + queries.push( + make_toplevel_case( + file, + trait_decl.name.name, + trait_decl.name.name, + trait_decl.name.loc, + ), + ) + @syntax.Impl::TopImpl(self_ty~, trait_~, method_name~, ..) => { + let trait_name = long_ident_tail(trait_.name) + let meth = method_name.name + match self_ty { + None => + queries.push( + make_toplevel_case( + file, + "\{trait_name}::\{meth}", + meth, + method_name.loc, + ), + ) + Some(ty) => + match type_to_query(ty) { + Some(type_name) => + queries.push( + make_toplevel_case( + file, + "\{trait_name}::\{meth} for \{type_name}", + meth, + method_name.loc, + ), + ) + None => () + } + } + } + @syntax.Impl::TopView(view_type_name~, view_type_loc~, view_func_name~, ..) => { + queries.push( + make_toplevel_case(file, view_type_name, view_type_name, view_type_loc), + ) + queries.push( + make_toplevel_case( + file, + view_func_name.name, + view_func_name.name, + view_func_name.loc, + ), + ) + } + @syntax.Impl::TopUsing(names~, ..) => + for pair in names { + let binder = pair.0.binder + queries.push( + make_toplevel_case(file, binder.name, binder.name, binder.loc), + ) + } + _ => () + } + queries +} + +///| +fn collect_toplevel_symbols( + file : String, + impls : @syntax.Impls, +) -> Array[ToplevelCase] { + let symbols = Array::new() + let seen : @hashset.HashSet[ToplevelCase] = @hashset.HashSet::new() + for impl_ in impls { + for test_case in render_toplevel_cases(file, impl_) { + if test_case.query is "" { + continue + } + if not(should_keep_symbol(test_case.rename_sym)) { + continue + } + if seen.contains(test_case) { + continue + } + seen.add(test_case) + symbols.push(test_case) + } + } + symbols +} + +///| +fn collect_hover_cases( + file : String, + impls : @syntax.Impls, + max_per_file : Int, +) -> Array[TestCase] { + let cases = Array::new() + let seen : @hashset.HashSet[TestCase] = @hashset.HashSet::new() + let collector = HoverCollector::{ + file, + max_per_file, + out: cases, + seen, + count: Ref::new(0), + } + for impl_ in impls { + collector.visit_Impl(impl_) + } + cases +} + +///| +fn collect_cases_for_text( + file : String, + text : String, + max_per_file : Int, +) -> CollectResult { + let (impls, reports) = @parser.parse_string(text, name=file) + ignore(reports) + let hover_cases = collect_hover_cases(file, impls, max_per_file) + let toplevel_symbols = collect_toplevel_symbols(file, impls) + CollectResult::{ source_files: [file], hover_cases, toplevel_symbols } +} + +///| +fn should_skip_dir(name : String) -> Bool { + match name { + "_build" + | "target" + | "node_modules" + | ".mooncakes" + | ".moonagent" + | ".repo" + | ".git" => true + _ => false + } +} + +///| +fn walk_dir(abs_dir : String, rel_dir : String, out : Array[String]) -> Unit { + let entries = try @fs.read_dir(abs_dir) catch { + _ => [] + } noraise { + values => values + } + entries.sort() + for name in entries { + let abs_path = @path.Path::join(abs_dir, name).to_string() + let rel_path = if rel_dir is "" { + name + } else { + @path.Path::join(rel_dir, name).to_string() + } + let is_dir = try @fs.is_dir(abs_path) catch { + _ => false + } noraise { + value => value + } + if is_dir { + if not(should_skip_dir(name)) { + walk_dir(abs_path, rel_path, out) + } + continue + } + let is_file = try @fs.is_file(abs_path) catch { + _ => false + } noraise { + value => value + } + if is_file && name.has_suffix(".mbt") { + out.push(rel_path) + } + } +} + +///| +fn collect_files(project_root : String) -> Array[String] { + let files = Array::new() + walk_dir(project_root, "", files) + files +} + +///| +fn collect_cases(project_root : String, max_per_file : Int) -> CollectResult { + let source_files = collect_files(project_root) + let hover_cases = Array::new() + let toplevel_symbols = Array::new() + for rel_path in source_files { + let abs_path = @path.Path::join(project_root, rel_path).to_string() + let maybe_text = try @fs.read_file_to_string(abs_path) catch { + _ => None + } noraise { + text => Some(text) + } + match maybe_text { + Some(text) => { + let result = collect_cases_for_text(rel_path, text, max_per_file) + for test_case in result.hover_cases { + hover_cases.push(test_case) + } + for test_case in result.toplevel_symbols { + toplevel_symbols.push(test_case) + } + } + None => () + } + } + CollectResult::{ source_files, hover_cases, toplevel_symbols } +} diff --git a/testgen/main.mbt b/testgen/main.mbt new file mode 100644 index 0000000..fa545ce --- /dev/null +++ b/testgen/main.mbt @@ -0,0 +1,118 @@ +///| +priv struct Args { + project_root : String + max_per_file : Int +} + +///| +fn fatal(message : String) -> Unit { + println("Error: \{message}") + @sys.exit(1) +} + +///| +fn write_generated_file_or_exit(path : String, content : String) -> Unit { + @fs.write_string_to_file(path, content) catch { + err => fatal("failed to write \{path}: \{err}") + } + println("generated \{path}") +} + +///| +fn write_cram_files(project_root : String, files : Array[CramFile]) -> Unit { + for file in files { + let path = @path.Path::join(project_root, file.name).to_string() + write_generated_file_or_exit(path, file.content) + } +} + +///| +fn without_program_name(args : Array[String]) -> Array[String] { + let start = if args.length() == 0 { 0 } else { 1 } + args[start:].to_array() +} + +///| +fn parse_args(args : Array[String]) -> Args { + let project_root = match @env.current_dir() { + Some(dir) => dir + None => "." + } + let max_per_file_raw : Ref[String] = Ref::new("50") + let project_arg : Ref[String?] = Ref::new(None) + let spec = [ + ( + "--max-per-file", + "-m", + @arg_parser.Spec::Set_string(max_per_file_raw), + "Cap collected AST locations with --loc per source file (default: 50)", + ), + ] + @arg_parser.parse( + spec, + arg => { + if arg.has_prefix("-") { + fatal("unknown flag: \{arg}") + } + match project_arg.val { + None => project_arg.val = Some(arg) + Some(_) => fatal("unexpected positional argument: \{arg}") + } + }, + "Usage: testgen [options] [project]", + args, + ) catch { + @arg_parser.ErrorMsg(message) => fatal(message) + err => fatal("\{err}") + } + let max_per_file = @strconv.parse_int(max_per_file_raw.val) catch { + _ => { + fatal("invalid --max-per-file value: \{max_per_file_raw.val}") + 0 + } + } + Args::{ + project_root: match project_arg.val { + Some(root) => root + None => project_root + }, + max_per_file, + } +} + +///| +fn ensure_dune_file(project_root : String) -> Unit { + let dune_path = @path.Path::join(project_root, "dune").to_string() + if @fs.path_exists(dune_path) { + let is_file = @fs.is_file(dune_path) catch { + err => { + fatal("failed to check \{dune_path}: \{err}") + false + } + } + if not(is_file) { + fatal("\{dune_path} exists but is not a file") + } + } else { + let dune_content = + #|(cram + #| (deps + #| (source_tree .))) + #| + write_generated_file_or_exit(dune_path, dune_content) + } +} + +///| +fn run(args : Array[String]) -> Unit { + let config = parse_args(args) + ensure_dune_file(config.project_root) + let result = collect_cases(config.project_root, config.max_per_file) + let files = render_cram_files(result) + write_cram_files(config.project_root, files) +} + +///| +fn main { + run(without_program_name(@env.args())) +} diff --git a/testgen/model.mbt b/testgen/model.mbt new file mode 100644 index 0000000..a9e8c58 --- /dev/null +++ b/testgen/model.mbt @@ -0,0 +1,33 @@ +///| +priv struct TestCase { + file : String + line : Int + col : Int + sym : String +} derive(Eq, Hash, Debug) + +///| +priv struct ToplevelCase { + file : String + line : Int + col : Int + query : String + rename_sym : String +} derive(Eq, Hash, Debug) + +///| + +///| +#warnings("-unused_value") +priv struct CollectResult { + source_files : Array[String] + hover_cases : Array[TestCase] + toplevel_symbols : Array[ToplevelCase] +} derive(Debug) + +///| +#warnings("-unused_value") +priv struct CramFile { + name : String + content : String +} derive(Debug) diff --git a/testgen/moon.mod.json b/testgen/moon.mod.json new file mode 100644 index 0000000..d8e4083 --- /dev/null +++ b/testgen/moon.mod.json @@ -0,0 +1,14 @@ +{ + "name": "username/testgen", + "version": "0.1.0", + "deps": { + "moonbitlang/parser": "0.1.17", + "moonbitlang/x": "0.4.38", + "Yoorkin/ArgParser": "0.2.1" + }, + "repository": "", + "license": "Apache-2.0", + "keywords": [], + "description": "", + "preferred-target": "native" +} \ No newline at end of file diff --git a/testgen/moon.pkg b/testgen/moon.pkg new file mode 100644 index 0000000..b80fc39 --- /dev/null +++ b/testgen/moon.pkg @@ -0,0 +1,16 @@ +import { + "Yoorkin/ArgParser" @arg_parser, + "moonbitlang/core/env", + "moonbitlang/core/hashset" @hashset, + "moonbitlang/core/strconv", + "moonbitlang/parser" @parser, + "moonbitlang/parser/basic" @basic, + "moonbitlang/parser/syntax" @syntax, + "moonbitlang/x/fs" @fs, + "moonbitlang/x/path" @path, + "moonbitlang/x/sys" @sys, +} + +options( + "is-main": true, +) diff --git a/testgen/render.mbt b/testgen/render.mbt new file mode 100644 index 0000000..bac11ad --- /dev/null +++ b/testgen/render.mbt @@ -0,0 +1,222 @@ +///| +fn append_line(sb : StringBuilder, line : String) -> Unit { + sb.write_string(line) + sb.write_char('\n') +} + +///| +fn append_fixed_header(sb : StringBuilder) -> Unit { + append_line(sb, " $ export MOON_HOME=\"${MOON_HOME:-$HOME/.moon}\"") + append_line( + sb, " $ export BUILD_PATH_PREFIX_MAP=\"\\$MOON_HOME=$MOON_HOME:$BUILD_PATH_PREFIX_MAP\"", + ) +} + +///| +fn location(test_case : TestCase) -> String { + "\{test_case.file}:\{test_case.line}:\{test_case.col}" +} + +///| +fn quoted_location(test_case : TestCase) -> String { + shell_quote(location(test_case)) +} + +///| +fn append_unique_command( + sb : StringBuilder, + seen : @hashset.HashSet[String], + command : String, +) -> Bool { + if seen.contains(command) { + false + } else { + seen.add(command) + append_line(sb, command) + true + } +} + +///| +fn append_case_commands( + sb : StringBuilder, + seen : @hashset.HashSet[String], + cases : Array[TestCase], + to_command : (TestCase) -> String, +) -> Bool { + let mut has_command = false + for test_case in cases { + if append_unique_command(sb, seen, to_command(test_case)) { + has_command = true + } + } + has_command +} + +///| +fn append_toplevel_commands( + sb : StringBuilder, + seen : @hashset.HashSet[String], + cases : Array[ToplevelCase], + to_command : (ToplevelCase) -> String, +) -> Bool { + let mut has_command = false + for test_case in cases { + if append_unique_command(sb, seen, to_command(test_case)) { + has_command = true + } + } + has_command +} + +///| +fn shell_quote(arg : String) -> String { + let escaped = arg.replace(old="'", new="'\\''") + "'\{escaped}'" +} + +///| +fn render_outline_file(source_files : Array[String]) -> CramFile? { + let sb = StringBuilder::new() + append_fixed_header(sb) + let seen : @hashset.HashSet[String] = @hashset.HashSet::new() + let mut has_command = false + for file in source_files { + if append_unique_command( + sb, + seen, + " $ moon ide outline \{shell_quote(file)}", + ) { + has_command = true + } + } + if has_command { + Some(CramFile::{ name: "generated_outline.t", content: sb.to_string() }) + } else { + None + } +} + +///| +fn render_symbol_file( + name : String, + hover_cases : Array[TestCase], + toplevel_symbols : Array[ToplevelCase], + hover_command : (TestCase) -> String, + toplevel_command : (ToplevelCase) -> String, +) -> CramFile? { + let sb = StringBuilder::new() + append_fixed_header(sb) + let seen : @hashset.HashSet[String] = @hashset.HashSet::new() + let hover_has_command = append_case_commands( + sb, seen, hover_cases, hover_command, + ) + let toplevel_has_command = append_toplevel_commands( + sb, seen, toplevel_symbols, toplevel_command, + ) + if hover_has_command || toplevel_has_command { + Some(CramFile::{ name, content: sb.to_string() }) + } else { + None + } +} + +///| +fn render_hover_file(cases : Array[TestCase]) -> CramFile? { + render_symbol_file( + "generated_hover.t", + cases, + [], + test_case => { + " $ moon ide hover \{test_case.sym} --loc \{quoted_location(test_case)}" + }, + _ => "", + ) +} + +///| +fn render_peek_file( + hover_cases : Array[TestCase], + toplevel_symbols : Array[ToplevelCase], +) -> CramFile? { + render_symbol_file( + "generated_peek_def.t", + hover_cases, + toplevel_symbols, + test_case => { + " $ moon ide peek-def \{test_case.sym} --loc \{quoted_location(test_case)}" + }, + test_case => " $ moon ide peek-def \{shell_quote(test_case.query)}", + ) +} + +///| +fn render_refs_file( + hover_cases : Array[TestCase], + toplevel_symbols : Array[ToplevelCase], +) -> CramFile? { + render_symbol_file( + "generated_find_references.t", + hover_cases, + toplevel_symbols, + test_case => { + " $ moon ide find-references \{test_case.sym} --loc \{quoted_location(test_case)}" + }, + test_case => " $ moon ide find-references \{shell_quote(test_case.query)}", + ) +} + +///| +fn rename_target(symbol : String) -> String { + if symbol.length() > 0 && symbol[0] >= 'A' && symbol[0] <= 'Z' { + "\{symbol}Renamed" + } else { + "\{symbol}_renamed" + } +} + +///| +fn render_rename_file( + hover_cases : Array[TestCase], + toplevel_symbols : Array[ToplevelCase], +) -> CramFile? { + render_symbol_file( + "generated_rename.t", + hover_cases, + toplevel_symbols, + test_case => { + " $ moon ide rename \{test_case.sym} \{rename_target(test_case.sym)} --loc \{quoted_location(test_case)}" + }, + test_case => { + " $ moon ide rename \{shell_quote(test_case.query)} \{rename_target(test_case.rename_sym)}" + }, + ) +} + +///| +fn append_if_some(files : Array[CramFile], maybe_file : CramFile?) -> Unit { + match maybe_file { + Some(file) => files.push(file) + None => () + } +} + +///| +fn render_cram_files(result : CollectResult) -> Array[CramFile] { + let files = Array::new() + append_if_some(files, render_outline_file(result.source_files)) + append_if_some(files, render_hover_file(result.hover_cases)) + append_if_some( + files, + render_peek_file(result.hover_cases, result.toplevel_symbols), + ) + append_if_some( + files, + render_refs_file(result.hover_cases, result.toplevel_symbols), + ) + append_if_some( + files, + render_rename_file(result.hover_cases, result.toplevel_symbols), + ) + files +} diff --git a/testgen/testgen_wbtest.mbt b/testgen/testgen_wbtest.mbt new file mode 100644 index 0000000..d47ddd0 --- /dev/null +++ b/testgen/testgen_wbtest.mbt @@ -0,0 +1,260 @@ +///| +test "parse_args accepts positional project argument" { + let config = parse_args(["core_test/test_project", "--max-per-file", "7"]) + inspect(config.project_root, content="core_test/test_project") + inspect(config.max_per_file, content="7") +} + +///| +test "parse_args defaults project to current dir when omitted" { + let config = parse_args(["--max-per-file", "9"]) + let expected_root = match @env.current_dir() { + Some(dir) => dir + None => "." + } + inspect(config.project_root, content=expected_root) + inspect(config.max_per_file, content="9") +} + +///| +test "should_skip_dir covers dependency and vcs dirs" { + debug_inspect( + [ + should_skip_dir("_build"), + should_skip_dir("target"), + should_skip_dir("node_modules"), + should_skip_dir(".mooncakes"), + should_skip_dir(".moonagent"), + should_skip_dir(".repo"), + should_skip_dir(".git"), + should_skip_dir("src"), + ], + content="[true, true, true, true, true, true, true, false]", + ) +} + +///| +test "collect_cases_for_text uses ast nodes" { + let text = + #|fn f() { + #| let x = 1 + #| x.dotcall() + #| Other::method + #| @pkg.dotvalue + #| @pkg.PkgType + #|} + let result = collect_cases_for_text("a.mbt", text, 50) + debug_inspect( + result, + content=( + #|{ + #| source_files: ["a.mbt"], + #| hover_cases: [ + #| { file: "a.mbt", line: 1, col: 4, sym: "f" }, + #| { file: "a.mbt", line: 2, col: 7, sym: "x" }, + #| { file: "a.mbt", line: 3, col: 5, sym: "dotcall" }, + #| { file: "a.mbt", line: 3, col: 3, sym: "x" }, + #| { file: "a.mbt", line: 4, col: 3, sym: "Other" }, + #| { file: "a.mbt", line: 4, col: 10, sym: "method" }, + #| { file: "a.mbt", line: 5, col: 8, sym: "dotvalue" }, + #| { file: "a.mbt", line: 6, col: 8, sym: "PkgType" }, + #| ], + #| toplevel_symbols: [{ file: "a.mbt", line: 1, col: 4, query: "f", rename_sym: "f" }], + #|} + ), + ) +} + +///| +test "collect_cases_for_text enforces max_per_file for loc nodes" { + let text = + #|fn f() { + #| let x = 1 + #| x.dotcall() + #| Other::method + #|} + let result = collect_cases_for_text("a.mbt", text, 2) + debug_inspect( + result, + content=( + #|{ + #| source_files: ["a.mbt"], + #| hover_cases: [ + #| { file: "a.mbt", line: 1, col: 4, sym: "f" }, + #| { file: "a.mbt", line: 2, col: 7, sym: "x" }, + #| ], + #| toplevel_symbols: [{ file: "a.mbt", line: 1, col: 4, query: "f", rename_sym: "f" }], + #|} + ), + ) +} + +///| +test "collect_cases_for_text includes toplevel symbols" { + let text = + #|type T = Int + #|fn f() { () } + #|let x = 1 + #|trait Tr { + #| g(Self) -> Unit = _ + #|} + #|impl Tr for Int with g(self) { () } + #|using @pkg {func as func2} + #| + let result = collect_cases_for_text("a.mbt", text, 50) + debug_inspect( + result, + content=( + #|{ + #| source_files: ["a.mbt"], + #| hover_cases: [ + #| { file: "a.mbt", line: 1, col: 6, sym: "T" }, + #| { file: "a.mbt", line: 2, col: 4, sym: "f" }, + #| { file: "a.mbt", line: 3, col: 5, sym: "x" }, + #| { file: "a.mbt", line: 4, col: 7, sym: "Tr" }, + #| { file: "a.mbt", line: 5, col: 3, sym: "g" }, + #| { file: "a.mbt", line: 7, col: 6, sym: "Tr" }, + #| { file: "a.mbt", line: 7, col: 22, sym: "g" }, + #| { file: "a.mbt", line: 7, col: 24, sym: "self" }, + #| { file: "a.mbt", line: 8, col: 7, sym: "pkg" }, + #| { file: "a.mbt", line: 8, col: 21, sym: "func2" }, + #| ], + #| toplevel_symbols: [ + #| { file: "a.mbt", line: 1, col: 6, query: "T", rename_sym: "T" }, + #| { file: "a.mbt", line: 2, col: 4, query: "f", rename_sym: "f" }, + #| { file: "a.mbt", line: 3, col: 5, query: "x", rename_sym: "x" }, + #| { file: "a.mbt", line: 4, col: 7, query: "Tr", rename_sym: "Tr" }, + #| { + #| file: "a.mbt", + #| line: 7, + #| col: 22, + #| query: "Tr::g for Int", + #| rename_sym: "g", + #| }, + #| { + #| file: "a.mbt", + #| line: 8, + #| col: 21, + #| query: "func2", + #| rename_sym: "func2", + #| }, + #| ], + #|} + ), + ) +} + +///| +test "collect_cases_for_text renders generic impl self type in query" { + let text = + #|trait Tr { + #| g(Self) -> Unit = _ + #|} + #|impl Tr for Array[Int] with g(self) { () } + #| + let result = collect_cases_for_text("a.mbt", text, 50) + debug_inspect( + result.toplevel_symbols, + content=( + #|[ + #| { file: "a.mbt", line: 1, col: 7, query: "Tr", rename_sym: "Tr" }, + #| { + #| file: "a.mbt", + #| line: 4, + #| col: 29, + #| query: "Tr::g for Array[Int]", + #| rename_sym: "g", + #| }, + #|] + ), + ) +} + +///| +test "collect_cases_for_text renders type function query" { + let text = + #|fn Int::local_abs(self : Int) -> Int { self } + #| + let result = collect_cases_for_text("a.mbt", text, 50) + debug_inspect( + result.toplevel_symbols, + content=( + #|[ + #| { + #| file: "a.mbt", + #| line: 1, + #| col: 9, + #| query: "Int::local_abs", + #| rename_sym: "local_abs", + #| }, + #|] + ), + ) +} + +///| +test "collect_cases_for_text excludes Self type symbol" { + let text = + #|trait Tr { + #| g(Self) -> Unit = _ + #|} + let result = collect_cases_for_text("a.mbt", text, 50) + debug_inspect( + result, + content=( + #|{ + #| source_files: ["a.mbt"], + #| hover_cases: [ + #| { file: "a.mbt", line: 1, col: 7, sym: "Tr" }, + #| { file: "a.mbt", line: 2, col: 3, sym: "g" }, + #| ], + #| toplevel_symbols: [{ file: "a.mbt", line: 1, col: 7, query: "Tr", rename_sym: "Tr" }], + #|} + ), + ) +} + +///| +test "collect_cases_for_text excludes operator symbols" { + let text = + #|fn f(x : Int) -> Int { + #| let n = Int::abs(-x) + #| n + 1 + #|} + let result = collect_cases_for_text("a.mbt", text, 50) + debug_inspect( + result, + content=( + #|{ + #| source_files: ["a.mbt"], + #| hover_cases: [ + #| { file: "a.mbt", line: 1, col: 4, sym: "f" }, + #| { file: "a.mbt", line: 1, col: 6, sym: "x" }, + #| { file: "a.mbt", line: 2, col: 7, sym: "n" }, + #| { file: "a.mbt", line: 2, col: 16, sym: "abs" }, + #| { file: "a.mbt", line: 2, col: 21, sym: "x" }, + #| { file: "a.mbt", line: 3, col: 3, sym: "n" }, + #| ], + #| toplevel_symbols: [{ file: "a.mbt", line: 1, col: 4, query: "f", rename_sym: "f" }], + #|} + ), + ) +} + +///| +test "collect_cases_for_text excludes main function" { + let text = + #|fn main() { () } + #|fn f() { main() } + let result = collect_cases_for_text("a.mbt", text, 50) + debug_inspect( + result, + content=( + #|{ + #| source_files: ["a.mbt"], + #| hover_cases: [{ file: "a.mbt", line: 2, col: 4, sym: "f" }], + #| toplevel_symbols: [{ file: "a.mbt", line: 2, col: 4, query: "f", rename_sym: "f" }], + #|} + ), + ) +}