mirror of
https://github.com/lune-org/lune.git
synced 2024-12-12 13:00:37 +00:00
Implement docs file generation & docs in the luau type definitions file
This commit is contained in:
parent
ee5b67bf3a
commit
0657e05cc0
13 changed files with 1175 additions and 105 deletions
10
.github/workflows/release.yaml
vendored
10
.github/workflows/release.yaml
vendored
|
@ -79,6 +79,16 @@ jobs:
|
||||||
asset_name: luneTypes.d.luau
|
asset_name: luneTypes.d.luau
|
||||||
asset_content_type: application/x-luau
|
asset_content_type: application/x-luau
|
||||||
|
|
||||||
|
- name: Upload documentation file to release
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ needs.create-release.outputs.upload_url }}
|
||||||
|
asset_path: luneDocs.json
|
||||||
|
asset_name: luneDocs.json
|
||||||
|
asset_content_type: application/json
|
||||||
|
|
||||||
release:
|
release:
|
||||||
needs: ["init", "create-release"]
|
needs: ["init", "create-release"]
|
||||||
strategy:
|
strategy:
|
||||||
|
|
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
|
@ -3,6 +3,7 @@
|
||||||
"luau-lsp.sourcemap.enabled": false,
|
"luau-lsp.sourcemap.enabled": false,
|
||||||
"luau-lsp.types.roblox": false,
|
"luau-lsp.types.roblox": false,
|
||||||
"luau-lsp.types.definitionFiles": ["luneTypes.d.luau"],
|
"luau-lsp.types.definitionFiles": ["luneTypes.d.luau"],
|
||||||
|
"luau-lsp.types.documentationFiles": ["luneDocs.json"],
|
||||||
"luau-lsp.require.mode": "relativeToFile",
|
"luau-lsp.require.mode": "relativeToFile",
|
||||||
// Rust
|
// Rust
|
||||||
"rust-analyzer.check.command": "clippy",
|
"rust-analyzer.check.command": "clippy",
|
||||||
|
|
181
Cargo.lock
generated
181
Cargo.lock
generated
|
@ -8,6 +8,15 @@ version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "0.7.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.68"
|
version = "1.0.68"
|
||||||
|
@ -135,6 +144,12 @@ version = "0.13.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "beef"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
|
@ -170,6 +185,12 @@ version = "3.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
|
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytecount"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "be0fdd54b507df8f22012890aadd099979befdba27713c767993f8380112ca7c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.78"
|
version = "1.0.78"
|
||||||
|
@ -228,6 +249,12 @@ dependencies = [
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "convert_case"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crc32fast"
|
name = "crc32fast"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
|
@ -246,6 +273,19 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "derive_more"
|
||||||
|
version = "0.99.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
|
||||||
|
dependencies = [
|
||||||
|
"convert_case",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rustc_version",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "erased-serde"
|
name = "erased-serde"
|
||||||
version = "0.3.24"
|
version = "0.3.24"
|
||||||
|
@ -301,6 +341,12 @@ dependencies = [
|
||||||
"miniz_oxide",
|
"miniz_oxide",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fnv"
|
||||||
|
version = "1.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "form_urlencoded"
|
name = "form_urlencoded"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
@ -310,6 +356,34 @@ dependencies = [
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "full_moon"
|
||||||
|
version = "0.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d58cb343df2e63e8a496de3e344e5f2b97f010bc1359e994be38a99586888f5"
|
||||||
|
dependencies = [
|
||||||
|
"bytecount",
|
||||||
|
"cfg-if",
|
||||||
|
"derive_more",
|
||||||
|
"full_moon_derive",
|
||||||
|
"logos",
|
||||||
|
"paste",
|
||||||
|
"serde",
|
||||||
|
"smol_str",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "full_moon_derive"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "99b4bd12ce56927d1dc5478d21528ea8c4b93ca85ff8f8043b6a5351a2a3c6f7"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-core"
|
name = "futures-core"
|
||||||
version = "0.3.25"
|
version = "0.3.25"
|
||||||
|
@ -368,6 +442,12 @@ dependencies = [
|
||||||
"slab",
|
"slab",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
@ -393,6 +473,16 @@ dependencies = [
|
||||||
"unicode-normalization",
|
"unicode-normalization",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "1.9.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "instant"
|
name = "instant"
|
||||||
version = "0.1.12"
|
version = "0.1.12"
|
||||||
|
@ -460,6 +550,29 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "logos"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bf8b031682c67a8e3d5446840f9573eb7fe26efe7ec8d195c9ac4c0647c502f1"
|
||||||
|
dependencies = [
|
||||||
|
"logos-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "logos-derive"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a1d849148dbaf9661a6151d1ca82b13bb4c4c128146a88d05253b38d4e2f496c"
|
||||||
|
dependencies = [
|
||||||
|
"beef",
|
||||||
|
"fnv",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"regex-syntax",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "luau0-src"
|
name = "luau0-src"
|
||||||
version = "0.5.1+luau558"
|
version = "0.5.1+luau558"
|
||||||
|
@ -475,8 +588,10 @@ version = "0.1.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
|
"full_moon",
|
||||||
"mlua",
|
"mlua",
|
||||||
"os_str_bytes",
|
"os_str_bytes",
|
||||||
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"smol",
|
"smol",
|
||||||
|
@ -548,6 +663,25 @@ version = "2.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
|
checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "paste"
|
||||||
|
version = "0.1.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880"
|
||||||
|
dependencies = [
|
||||||
|
"paste-impl",
|
||||||
|
"proc-macro-hack",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "paste-impl"
|
||||||
|
version = "0.1.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-hack",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.2.0"
|
version = "2.2.0"
|
||||||
|
@ -610,6 +744,12 @@ dependencies = [
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-hack"
|
||||||
|
version = "0.5.20+deprecated"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.50"
|
version = "1.0.50"
|
||||||
|
@ -628,6 +768,23 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.6.28"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ring"
|
name = "ring"
|
||||||
version = "0.16.20"
|
version = "0.16.20"
|
||||||
|
@ -649,6 +806,15 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc_version"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
||||||
|
dependencies = [
|
||||||
|
"semver",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.36.7"
|
version = "0.36.7"
|
||||||
|
@ -691,6 +857,12 @@ dependencies = [
|
||||||
"untrusted",
|
"untrusted",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver"
|
||||||
|
version = "1.0.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.152"
|
version = "1.0.152"
|
||||||
|
@ -767,6 +939,15 @@ dependencies = [
|
||||||
"futures-lite",
|
"futures-lite",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smol_str"
|
||||||
|
version = "0.1.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7475118a28b7e3a2e157ce0131ba8c5526ea96e90ee601d9f6bb2e286a35ab44"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.4.7"
|
version = "0.4.7"
|
||||||
|
|
|
@ -26,10 +26,12 @@ panic = "abort" # Remove extra panic info
|
||||||
|
|
||||||
anyhow = "1.0.68"
|
anyhow = "1.0.68"
|
||||||
os_str_bytes = "6.4.1"
|
os_str_bytes = "6.4.1"
|
||||||
|
regex = "1.7.1"
|
||||||
serde_json = "1.0.91"
|
serde_json = "1.0.91"
|
||||||
smol = "1.3.0"
|
smol = "1.3.0"
|
||||||
ureq = "2.6.2"
|
ureq = "2.6.2"
|
||||||
|
|
||||||
clap = { version = "4.1.1", features = ["derive"] }
|
clap = { version = "4.1.1", features = ["derive"] }
|
||||||
|
full_moon = { version = "0.17.0", features = ["roblox"] }
|
||||||
mlua = { version = "0.8.7", features = ["luau", "async", "serialize"] }
|
mlua = { version = "0.8.7", features = ["luau", "async", "serialize"] }
|
||||||
serde = { version = "1.0.152", features = ["derive"] }
|
serde = { version = "1.0.152", features = ["derive"] }
|
||||||
|
|
110
README.md
110
README.md
|
@ -33,102 +33,15 @@ Check out the examples on how to write a script in the [.lune](.lune) folder ! <
|
||||||
A great starting point and walkthrough of Lune can be found in the [Hello, Lune](.lune/hello_lune.luau) example.
|
A great starting point and walkthrough of Lune can be found in the [Hello, Lune](.lune/hello_lune.luau) example.
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary><b>🔎 Full list of APIs</b></summary>
|
<summary><b>🔎 List of APIs</b></summary>
|
||||||
|
|
||||||
<details>
|
`console` - Logging & formatting <br />
|
||||||
<summary><b>console</b> - Logging & formatting</summary>
|
`fs` - Filesystem <br />
|
||||||
|
`net` - Networking <br />
|
||||||
|
`process` - Current process & child processes <br />
|
||||||
|
`task` - Task scheduler & thread spawning <br />
|
||||||
|
|
||||||
```lua
|
Documentation for individual members and types can be found using your editor of choice and [Luau LSP](https://github.com/JohnnyMorganz/luau-lsp).
|
||||||
type console = {
|
|
||||||
resetColor: () -> (),
|
|
||||||
setColor: (color: "black" | "red" | "green" | "yellow" | "blue" | "purple" | "cyan" | "white") -> (),
|
|
||||||
resetStyle: () -> (),
|
|
||||||
setStyle: (color: "bold" | "dim") -> (),
|
|
||||||
format: (...any) -> (string),
|
|
||||||
log: (...any) -> (),
|
|
||||||
info: (...any) -> (),
|
|
||||||
warn: (...any) -> (),
|
|
||||||
error: (...any) -> (),
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary><b>fs</b> - Filesystem</summary>
|
|
||||||
|
|
||||||
```lua
|
|
||||||
type fs = {
|
|
||||||
readFile: (path: string) -> string,
|
|
||||||
readDir: (path: string) -> { string },
|
|
||||||
writeFile: (path: string, contents: string) -> (),
|
|
||||||
writeDir: (path: string) -> (),
|
|
||||||
removeFile: (path: string) -> (),
|
|
||||||
removeDir: (path: string) -> (),
|
|
||||||
isFile: (path: string) -> boolean,
|
|
||||||
isDir: (path: string) -> boolean,
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary><b>net</b> - Networking</summary>
|
|
||||||
|
|
||||||
```lua
|
|
||||||
type net = {
|
|
||||||
request: (config: string | {
|
|
||||||
url: string,
|
|
||||||
method: ("GET" | "POST" | "PUT" | "DELETE" | "HEAD" | "OPTIONS" | "PATCH")?,
|
|
||||||
headers: { [string]: string }?,
|
|
||||||
body: string?,
|
|
||||||
}) -> {
|
|
||||||
ok: boolean,
|
|
||||||
statusCode: number,
|
|
||||||
statusMessage: string,
|
|
||||||
headers: { [string]: string },
|
|
||||||
body: string,
|
|
||||||
},
|
|
||||||
jsonEncode: (value: any, pretty: boolean?) -> string,
|
|
||||||
jsonDecode: (encoded: string) -> any,
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary><b>process</b> - Current process & child processes</summary>
|
|
||||||
|
|
||||||
```lua
|
|
||||||
type process = {
|
|
||||||
args: { string },
|
|
||||||
env: { [string]: string? },
|
|
||||||
exit: (code: number?) -> (),
|
|
||||||
spawn: (program: string, params: { string }?) -> {
|
|
||||||
ok: boolean,
|
|
||||||
code: number,
|
|
||||||
stdout: string,
|
|
||||||
stderr: string,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary><b>task</b> - Task scheduler & thread spawning</summary>
|
|
||||||
|
|
||||||
```lua
|
|
||||||
type task = {
|
|
||||||
cancel: (thread: thread) -> (),
|
|
||||||
defer: <T...>(functionOrThread: thread | (T...) -> (...any), T...) -> thread,
|
|
||||||
delay: <T...>(duration: number?, functionOrThread: thread | (T...) -> (...any), T...) -> thread,
|
|
||||||
spawn: <T...>(functionOrThread: thread | (T...) -> (...any), T...) -> thread,
|
|
||||||
wait: (duration: number?) -> (number),
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
@ -174,9 +87,12 @@ Lune puts developer experience first, and as such provides type definitions and
|
||||||
<details>
|
<details>
|
||||||
<summary>Luau LSP</summary>
|
<summary>Luau LSP</summary>
|
||||||
|
|
||||||
1. Use `lune --download-luau-types` to download Luau types (`luneTypes.d.luau`) to the current directory
|
1. Set the require mode setting to `relativeToFile`
|
||||||
2. Set your definition files setting to include `luneTypes.d.luau`
|
2. Use `lune --download-luau-types` to download Luau types (`luneTypes.d.luau`) to the current directory
|
||||||
3. Set the require mode setting to `relativeToFile`
|
3. Set your definition files setting to include `luneTypes.d.luau`
|
||||||
|
4. Generate the documentation file using `lune --generate-docs-file`
|
||||||
|
- NOTE: This is a temporary solution and a docs file separate from type definitions will not be necessary in the future
|
||||||
|
5. Set your documentation files setting to include `luneDocs.json`
|
||||||
|
|
||||||
An example of these settings can be found in the [.vscode](.vscode) folder in this repository
|
An example of these settings can be found in the [.vscode](.vscode) folder in this repository
|
||||||
|
|
||||||
|
|
305
luneDocs.json
Normal file
305
luneDocs.json
Normal file
|
@ -0,0 +1,305 @@
|
||||||
|
{
|
||||||
|
"@roblox/global/console": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Logging & formatting",
|
||||||
|
"keys": {
|
||||||
|
"console": "@roblox/global/console.console"
|
||||||
|
},
|
||||||
|
"learn_more_link": ""
|
||||||
|
},
|
||||||
|
"@roblox/global/console.error": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Prints arguments as a human-readable string with syntax highlighting for tables to stderr.\n\nThis will also prepend an [ERROR] tag at the beginning of the message.\n\nUsing this function will automatically set the exit code of the process\nto 1, unless it gets manually specified afterwards using `process.exit`.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [],
|
||||||
|
"returns": []
|
||||||
|
},
|
||||||
|
"@roblox/global/console.format": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Formats arguments into a human-readable string with syntax highlighting for tables.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [],
|
||||||
|
"returns": []
|
||||||
|
},
|
||||||
|
"@roblox/global/console.info": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Prints arguments as a human-readable string with syntax highlighting for tables to stdout.\n\nThis will also prepend an [INFO] tag at the beginning of the message.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [],
|
||||||
|
"returns": []
|
||||||
|
},
|
||||||
|
"@roblox/global/console.log": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Prints arguments as a human-readable string with syntax highlighting for tables to stdout.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [],
|
||||||
|
"returns": []
|
||||||
|
},
|
||||||
|
"@roblox/global/console.resetColor": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Resets the current persistent output color.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [],
|
||||||
|
"returns": []
|
||||||
|
},
|
||||||
|
"@roblox/global/console.resetStyle": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Resets the current persistent output style.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [],
|
||||||
|
"returns": []
|
||||||
|
},
|
||||||
|
"@roblox/global/console.setColor": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Sets the current persistent output color.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [],
|
||||||
|
"returns": []
|
||||||
|
},
|
||||||
|
"@roblox/global/console.setStyle": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Sets the current persistent output style.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [],
|
||||||
|
"returns": []
|
||||||
|
},
|
||||||
|
"@roblox/global/console.warn": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Prints arguments as a human-readable string with syntax highlighting for tables to stdout.\n\nThis will also prepend an [INFO] tag at the beginning of the message.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [],
|
||||||
|
"returns": []
|
||||||
|
},
|
||||||
|
"@roblox/global/fs": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Filesystem",
|
||||||
|
"keys": {
|
||||||
|
"fs": "@roblox/global/fs.fs"
|
||||||
|
},
|
||||||
|
"learn_more_link": ""
|
||||||
|
},
|
||||||
|
"@roblox/global/fs.isDir": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Checks if a given path is a directory.\n\nAn error will be thrown in the following situations:\n\n* The current process lacks permissions to read at `path`.\n* Some other I/O error occurred.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [],
|
||||||
|
"returns": []
|
||||||
|
},
|
||||||
|
"@roblox/global/fs.isFile": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Checks if a given path is a file.\n\nAn error will be thrown in the following situations:\n\n* The current process lacks permissions to read at `path`.\n* Some other I/O error occurred.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [],
|
||||||
|
"returns": []
|
||||||
|
},
|
||||||
|
"@roblox/global/fs.readDir": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Reads entries in a directory at `path`.\n\nAn error will be thrown in the following situations:\n\n* `path` does not point to an existing directory.\n* The current process lacks permissions to read the contents of the directory.\n* Some other I/O error occurred.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [],
|
||||||
|
"returns": []
|
||||||
|
},
|
||||||
|
"@roblox/global/fs.readFile": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Reads a file at `path`.\n\nAn error will be thrown in the following situations:\n\n* `path` does not point to an existing file.\n* The current process lacks permissions to read the file.\n* The contents of the file cannot be read as a UTF-8 string.\n* Some other I/O error occurred.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [],
|
||||||
|
"returns": []
|
||||||
|
},
|
||||||
|
"@roblox/global/fs.removeDir": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Removes a directory and all of its contents.\n\nAn error will be thrown in the following situations:\n\n* `path` is not an existing and empty directory.\n* The current process lacks permissions to remove the directory.\n* Some other I/O error occurred.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [],
|
||||||
|
"returns": []
|
||||||
|
},
|
||||||
|
"@roblox/global/fs.removeFile": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Removes a file.\n\nAn error will be thrown in the following situations:\n\n* `path` does not point to an existing file.\n* The current process lacks permissions to remove the file.\n* Some other I/O error occurred.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [],
|
||||||
|
"returns": []
|
||||||
|
},
|
||||||
|
"@roblox/global/fs.writeDir": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Creates a directory and its parent directories if they are missing.\n\nAn error will be thrown in the following situations:\n\n* `path` already points to an existing file or directory.\n* The current process lacks permissions to create the directory or its missing parents.\n* Some other I/O error occurred.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [],
|
||||||
|
"returns": []
|
||||||
|
},
|
||||||
|
"@roblox/global/fs.writeFile": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Writes to a file at `path`.\n\nAn error will be thrown in the following situations:\n\n* The file's parent directory does not exist.\n* The current process lacks permissions to write to the file.\n* Some other I/O error occurred.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [],
|
||||||
|
"returns": []
|
||||||
|
},
|
||||||
|
"@roblox/global/net": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Networking",
|
||||||
|
"keys": {
|
||||||
|
"net": "@roblox/global/net.net"
|
||||||
|
},
|
||||||
|
"learn_more_link": ""
|
||||||
|
},
|
||||||
|
"@roblox/global/net.jsonDecode": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Decodes the given JSON string into a lua value.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [],
|
||||||
|
"returns": []
|
||||||
|
},
|
||||||
|
"@roblox/global/net.jsonEncode": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Encodes the given value as JSON.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [],
|
||||||
|
"returns": []
|
||||||
|
},
|
||||||
|
"@roblox/global/net.request": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Sends an HTTP request using the given url and / or parameters, and returns a dictionary that describes the response received.\n\nOnly throws an error if a miscellaneous network or I/O error occurs, never for unsuccessful status codes.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [],
|
||||||
|
"returns": []
|
||||||
|
},
|
||||||
|
"@roblox/global/process": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Current process & child processes",
|
||||||
|
"keys": {
|
||||||
|
"process": "@roblox/global/process.process"
|
||||||
|
},
|
||||||
|
"learn_more_link": ""
|
||||||
|
},
|
||||||
|
"@roblox/global/process.args": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "The arguments given when running the Lune script.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [],
|
||||||
|
"returns": []
|
||||||
|
},
|
||||||
|
"@roblox/global/process.env": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Current environment variables for this process.\n\nSetting a value on this table will set the corresponding environment variable.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [],
|
||||||
|
"returns": []
|
||||||
|
},
|
||||||
|
"@roblox/global/process.exit": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Exits the currently running script as soon as possible with the given exit code.\n\nExit code 0 is treated as a successful exit, any other value is treated as an error.\n\nSetting the exit code using this function will override any otherwise automatic exit code.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [],
|
||||||
|
"returns": []
|
||||||
|
},
|
||||||
|
"@roblox/global/process.spawn": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Spawns a child process that will run the program `program` with the given `params` as arguments, and returns a dictionary that describes the final status and ouput of the child process.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [],
|
||||||
|
"returns": []
|
||||||
|
},
|
||||||
|
"@roblox/global/task": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Task scheduler & thread spawning",
|
||||||
|
"keys": {
|
||||||
|
"task": "@roblox/global/task.task"
|
||||||
|
},
|
||||||
|
"learn_more_link": ""
|
||||||
|
},
|
||||||
|
"@roblox/global/task.cancel": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Stops a currently scheduled thread from resuming.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"documentation": "@roblox/global/task.cancel/param/0",
|
||||||
|
"name": "thread"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"returns": []
|
||||||
|
},
|
||||||
|
"@roblox/global/task.cancel/param/0": {
|
||||||
|
"documentation": "The thread to cancel"
|
||||||
|
},
|
||||||
|
"@roblox/global/task.defer": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Defers a thread or function to run at the end of the current task queue.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"documentation": "@roblox/global/task.defer/param/0",
|
||||||
|
"name": "functionOrThread"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"returns": [
|
||||||
|
"@roblox/global/task.defer/return/0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"@roblox/global/task.defer/param/0": {
|
||||||
|
"documentation": "The function or thread to defer"
|
||||||
|
},
|
||||||
|
"@roblox/global/task.defer/return/0": {
|
||||||
|
"documentation": "The thread that will be deferred"
|
||||||
|
},
|
||||||
|
"@roblox/global/task.delay": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Delays a thread or function to run after `duration` seconds.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"documentation": "@roblox/global/task.delay/param/0",
|
||||||
|
"name": "functionOrThread"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"returns": [
|
||||||
|
"@roblox/global/task.delay/return/0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"@roblox/global/task.delay/param/0": {
|
||||||
|
"documentation": "The function or thread to delay"
|
||||||
|
},
|
||||||
|
"@roblox/global/task.delay/return/0": {
|
||||||
|
"documentation": "The thread that will be delayed"
|
||||||
|
},
|
||||||
|
"@roblox/global/task.spawn": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Instantly runs a thread or function.\n\nIf the spawned task yields, the thread that spawned the task\nwill resume, letting the spawned task run in the background.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"documentation": "@roblox/global/task.spawn/param/0",
|
||||||
|
"name": "functionOrThread"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"returns": [
|
||||||
|
"@roblox/global/task.spawn/return/0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"@roblox/global/task.spawn/param/0": {
|
||||||
|
"documentation": "The function or thread to spawn"
|
||||||
|
},
|
||||||
|
"@roblox/global/task.spawn/return/0": {
|
||||||
|
"documentation": "The thread that was spawned"
|
||||||
|
},
|
||||||
|
"@roblox/global/task.wait": {
|
||||||
|
"code_sample": "",
|
||||||
|
"documentation": "Waits for the given duration, with a minimum wait time of 10 milliseconds.",
|
||||||
|
"learn_more_link": "",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"documentation": "@roblox/global/task.wait/param/0",
|
||||||
|
"name": "duration"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"returns": [
|
||||||
|
"@roblox/global/task.wait/return/0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"@roblox/global/task.wait/param/0": {
|
||||||
|
"documentation": "The amount of time to wait"
|
||||||
|
},
|
||||||
|
"@roblox/global/task.wait/return/0": {
|
||||||
|
"documentation": "The exact amount of time waited"
|
||||||
|
}
|
||||||
|
}
|
251
luneTypes.d.luau
251
luneTypes.d.luau
|
@ -1,29 +1,192 @@
|
||||||
-- Lune v0.1.3
|
-- Lune v0.1.3
|
||||||
|
|
||||||
|
--[=[
|
||||||
|
@class console
|
||||||
|
|
||||||
|
Logging & formatting
|
||||||
|
]=]
|
||||||
declare console: {
|
declare console: {
|
||||||
|
--[=[
|
||||||
|
@within console
|
||||||
|
|
||||||
|
Resets the current persistent output color.
|
||||||
|
]=]
|
||||||
resetColor: () -> (),
|
resetColor: () -> (),
|
||||||
|
--[=[
|
||||||
|
@within console
|
||||||
|
|
||||||
|
Sets the current persistent output color.
|
||||||
|
]=]
|
||||||
setColor: (color: "black" | "red" | "green" | "yellow" | "blue" | "purple" | "cyan" | "white") -> (),
|
setColor: (color: "black" | "red" | "green" | "yellow" | "blue" | "purple" | "cyan" | "white") -> (),
|
||||||
|
--[=[
|
||||||
|
@within console
|
||||||
|
|
||||||
|
Resets the current persistent output style.
|
||||||
|
]=]
|
||||||
resetStyle: () -> (),
|
resetStyle: () -> (),
|
||||||
|
--[=[
|
||||||
|
@within console
|
||||||
|
|
||||||
|
Sets the current persistent output style.
|
||||||
|
]=]
|
||||||
setStyle: (style: "bold" | "dim") -> (),
|
setStyle: (style: "bold" | "dim") -> (),
|
||||||
|
--[=[
|
||||||
|
@within console
|
||||||
|
|
||||||
|
Formats arguments into a human-readable string with syntax highlighting for tables.
|
||||||
|
]=]
|
||||||
format: (...any) -> (string),
|
format: (...any) -> (string),
|
||||||
|
--[=[
|
||||||
|
@within console
|
||||||
|
|
||||||
|
Prints arguments as a human-readable string with syntax highlighting for tables to stdout.
|
||||||
|
]=]
|
||||||
log: (...any) -> (),
|
log: (...any) -> (),
|
||||||
|
--[=[
|
||||||
|
@within console
|
||||||
|
|
||||||
|
Prints arguments as a human-readable string with syntax highlighting for tables to stdout.
|
||||||
|
|
||||||
|
This will also prepend an [INFO] tag at the beginning of the message.
|
||||||
|
]=]
|
||||||
info: (...any) -> (),
|
info: (...any) -> (),
|
||||||
|
--[=[
|
||||||
|
@within console
|
||||||
|
|
||||||
|
Prints arguments as a human-readable string with syntax highlighting for tables to stdout.
|
||||||
|
|
||||||
|
This will also prepend an [INFO] tag at the beginning of the message.
|
||||||
|
]=]
|
||||||
warn: (...any) -> (),
|
warn: (...any) -> (),
|
||||||
|
--[=[
|
||||||
|
@within console
|
||||||
|
|
||||||
|
Prints arguments as a human-readable string with syntax highlighting for tables to stderr.
|
||||||
|
|
||||||
|
This will also prepend an [ERROR] tag at the beginning of the message.
|
||||||
|
|
||||||
|
Using this function will automatically set the exit code of the process
|
||||||
|
to 1, unless it gets manually specified afterwards using `process.exit`.
|
||||||
|
]=]
|
||||||
error: (...any) -> (),
|
error: (...any) -> (),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--[=[
|
||||||
|
@class fs
|
||||||
|
|
||||||
|
Filesystem
|
||||||
|
]=]
|
||||||
declare fs: {
|
declare fs: {
|
||||||
|
--[=[
|
||||||
|
@within fs
|
||||||
|
|
||||||
|
Reads a file at `path`.
|
||||||
|
|
||||||
|
An error will be thrown in the following situations:
|
||||||
|
|
||||||
|
* `path` does not point to an existing file.
|
||||||
|
* The current process lacks permissions to read the file.
|
||||||
|
* The contents of the file cannot be read as a UTF-8 string.
|
||||||
|
* Some other I/O error occurred.
|
||||||
|
]=]
|
||||||
readFile: (path: string) -> string,
|
readFile: (path: string) -> string,
|
||||||
|
--[=[
|
||||||
|
@within fs
|
||||||
|
|
||||||
|
Reads entries in a directory at `path`.
|
||||||
|
|
||||||
|
An error will be thrown in the following situations:
|
||||||
|
|
||||||
|
* `path` does not point to an existing directory.
|
||||||
|
* The current process lacks permissions to read the contents of the directory.
|
||||||
|
* Some other I/O error occurred.
|
||||||
|
]=]
|
||||||
readDir: (path: string) -> { string },
|
readDir: (path: string) -> { string },
|
||||||
|
--[=[
|
||||||
|
@within fs
|
||||||
|
|
||||||
|
Writes to a file at `path`.
|
||||||
|
|
||||||
|
An error will be thrown in the following situations:
|
||||||
|
|
||||||
|
* The file's parent directory does not exist.
|
||||||
|
* The current process lacks permissions to write to the file.
|
||||||
|
* Some other I/O error occurred.
|
||||||
|
]=]
|
||||||
writeFile: (path: string, contents: string) -> (),
|
writeFile: (path: string, contents: string) -> (),
|
||||||
|
--[=[
|
||||||
|
@within fs
|
||||||
|
|
||||||
|
Creates a directory and its parent directories if they are missing.
|
||||||
|
|
||||||
|
An error will be thrown in the following situations:
|
||||||
|
|
||||||
|
* `path` already points to an existing file or directory.
|
||||||
|
* The current process lacks permissions to create the directory or its missing parents.
|
||||||
|
* Some other I/O error occurred.
|
||||||
|
]=]
|
||||||
writeDir: (path: string) -> (),
|
writeDir: (path: string) -> (),
|
||||||
|
--[=[
|
||||||
|
@within fs
|
||||||
|
|
||||||
|
Removes a file.
|
||||||
|
|
||||||
|
An error will be thrown in the following situations:
|
||||||
|
|
||||||
|
* `path` does not point to an existing file.
|
||||||
|
* The current process lacks permissions to remove the file.
|
||||||
|
* Some other I/O error occurred.
|
||||||
|
]=]
|
||||||
removeFile: (path: string) -> (),
|
removeFile: (path: string) -> (),
|
||||||
|
--[=[
|
||||||
|
@within fs
|
||||||
|
|
||||||
|
Removes a directory and all of its contents.
|
||||||
|
|
||||||
|
An error will be thrown in the following situations:
|
||||||
|
|
||||||
|
* `path` is not an existing and empty directory.
|
||||||
|
* The current process lacks permissions to remove the directory.
|
||||||
|
* Some other I/O error occurred.
|
||||||
|
]=]
|
||||||
removeDir: (path: string) -> (),
|
removeDir: (path: string) -> (),
|
||||||
|
--[=[
|
||||||
|
@within fs
|
||||||
|
|
||||||
|
Checks if a given path is a file.
|
||||||
|
|
||||||
|
An error will be thrown in the following situations:
|
||||||
|
|
||||||
|
* The current process lacks permissions to read at `path`.
|
||||||
|
* Some other I/O error occurred.
|
||||||
|
]=]
|
||||||
isFile: (path: string) -> boolean,
|
isFile: (path: string) -> boolean,
|
||||||
|
--[=[
|
||||||
|
@within fs
|
||||||
|
|
||||||
|
Checks if a given path is a directory.
|
||||||
|
|
||||||
|
An error will be thrown in the following situations:
|
||||||
|
|
||||||
|
* The current process lacks permissions to read at `path`.
|
||||||
|
* Some other I/O error occurred.
|
||||||
|
]=]
|
||||||
isDir: (path: string) -> boolean,
|
isDir: (path: string) -> boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--[=[
|
||||||
|
@class net
|
||||||
|
|
||||||
|
Networking
|
||||||
|
]=]
|
||||||
declare net: {
|
declare net: {
|
||||||
|
--[=[
|
||||||
|
@within net
|
||||||
|
|
||||||
|
Sends an HTTP request using the given url and / or parameters, and returns a dictionary that describes the response received.
|
||||||
|
|
||||||
|
Only throws an error if a miscellaneous network or I/O error occurs, never for unsuccessful status codes.
|
||||||
|
]=]
|
||||||
request: (config: string | {
|
request: (config: string | {
|
||||||
url: string,
|
url: string,
|
||||||
method: ("GET" | "POST" | "PUT" | "DELETE" | "HEAD" | "OPTIONS" | "PATCH")?,
|
method: ("GET" | "POST" | "PUT" | "DELETE" | "HEAD" | "OPTIONS" | "PATCH")?,
|
||||||
|
@ -36,14 +199,55 @@ declare net: {
|
||||||
headers: { [string]: string },
|
headers: { [string]: string },
|
||||||
body: string,
|
body: string,
|
||||||
},
|
},
|
||||||
|
--[=[
|
||||||
|
@within net
|
||||||
|
|
||||||
|
Encodes the given value as JSON.
|
||||||
|
]=]
|
||||||
jsonEncode: (value: any, pretty: boolean?) -> string,
|
jsonEncode: (value: any, pretty: boolean?) -> string,
|
||||||
|
--[=[
|
||||||
|
@within net
|
||||||
|
|
||||||
|
Decodes the given JSON string into a lua value.
|
||||||
|
]=]
|
||||||
jsonDecode: (encoded: string) -> any,
|
jsonDecode: (encoded: string) -> any,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--[=[
|
||||||
|
@class process
|
||||||
|
|
||||||
|
Current process & child processes
|
||||||
|
]=]
|
||||||
declare process: {
|
declare process: {
|
||||||
|
--[=[
|
||||||
|
@within process
|
||||||
|
|
||||||
|
The arguments given when running the Lune script.
|
||||||
|
]=]
|
||||||
args: { string },
|
args: { string },
|
||||||
|
--[=[
|
||||||
|
@within process
|
||||||
|
|
||||||
|
Current environment variables for this process.
|
||||||
|
|
||||||
|
Setting a value on this table will set the corresponding environment variable.
|
||||||
|
]=]
|
||||||
env: { [string]: string? },
|
env: { [string]: string? },
|
||||||
|
--[=[
|
||||||
|
@within process
|
||||||
|
|
||||||
|
Exits the currently running script as soon as possible with the given exit code.
|
||||||
|
|
||||||
|
Exit code 0 is treated as a successful exit, any other value is treated as an error.
|
||||||
|
|
||||||
|
Setting the exit code using this function will override any otherwise automatic exit code.
|
||||||
|
]=]
|
||||||
exit: (code: number?) -> (),
|
exit: (code: number?) -> (),
|
||||||
|
--[=[
|
||||||
|
@within process
|
||||||
|
|
||||||
|
Spawns a child process that will run the program `program` with the given `params` as arguments, and returns a dictionary that describes the final status and ouput of the child process.
|
||||||
|
]=]
|
||||||
spawn: (program: string, params: { string }?) -> {
|
spawn: (program: string, params: { string }?) -> {
|
||||||
ok: boolean,
|
ok: boolean,
|
||||||
code: number,
|
code: number,
|
||||||
|
@ -52,10 +256,57 @@ declare process: {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--[=[
|
||||||
|
@class task
|
||||||
|
|
||||||
|
Task scheduler & thread spawning
|
||||||
|
]=]
|
||||||
declare task: {
|
declare task: {
|
||||||
|
--[=[
|
||||||
|
@within task
|
||||||
|
|
||||||
|
Stops a currently scheduled thread from resuming.
|
||||||
|
|
||||||
|
@param thread The thread to cancel
|
||||||
|
]=]
|
||||||
cancel: (thread: thread) -> (),
|
cancel: (thread: thread) -> (),
|
||||||
|
--[=[
|
||||||
|
@within task
|
||||||
|
|
||||||
|
Defers a thread or function to run at the end of the current task queue.
|
||||||
|
|
||||||
|
@param functionOrThread The function or thread to defer
|
||||||
|
@return The thread that will be deferred
|
||||||
|
]=]
|
||||||
defer: <T...>(functionOrThread: thread | (T...) -> (...any), T...) -> thread,
|
defer: <T...>(functionOrThread: thread | (T...) -> (...any), T...) -> thread,
|
||||||
|
--[=[
|
||||||
|
@within task
|
||||||
|
|
||||||
|
Delays a thread or function to run after `duration` seconds.
|
||||||
|
|
||||||
|
@param functionOrThread The function or thread to delay
|
||||||
|
@return The thread that will be delayed
|
||||||
|
]=]
|
||||||
delay: <T...>(duration: number?, functionOrThread: thread | (T...) -> (...any), T...) -> thread,
|
delay: <T...>(duration: number?, functionOrThread: thread | (T...) -> (...any), T...) -> thread,
|
||||||
|
--[=[
|
||||||
|
@within task
|
||||||
|
|
||||||
|
Instantly runs a thread or function.
|
||||||
|
|
||||||
|
If the spawned task yields, the thread that spawned the task
|
||||||
|
will resume, letting the spawned task run in the background.
|
||||||
|
|
||||||
|
@param functionOrThread The function or thread to spawn
|
||||||
|
@return The thread that was spawned
|
||||||
|
]=]
|
||||||
spawn: <T...>(functionOrThread: thread | (T...) -> (...any), T...) -> thread,
|
spawn: <T...>(functionOrThread: thread | (T...) -> (...any), T...) -> thread,
|
||||||
|
--[=[
|
||||||
|
@within task
|
||||||
|
|
||||||
|
Waits for the given duration, with a minimum wait time of 10 milliseconds.
|
||||||
|
|
||||||
|
@param duration The amount of time to wait
|
||||||
|
@return The exact amount of time waited
|
||||||
|
]=]
|
||||||
wait: (duration: number?) -> (number),
|
wait: (duration: number?) -> (number),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,28 @@
|
||||||
use std::{fs::read_to_string, process::ExitCode};
|
use std::process::ExitCode;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::{CommandFactory, Parser};
|
use clap::{CommandFactory, Parser};
|
||||||
|
|
||||||
use lune::Lune;
|
use lune::Lune;
|
||||||
|
use smol::fs::{read_to_string, write};
|
||||||
|
|
||||||
use crate::utils::{
|
use crate::{
|
||||||
|
gen::generate_docs_json_from_definitions,
|
||||||
|
utils::{
|
||||||
files::find_parse_file_path,
|
files::find_parse_file_path,
|
||||||
github::Client as GithubClient,
|
github::Client as GithubClient,
|
||||||
listing::{find_lune_scripts, print_lune_scripts, sort_lune_scripts},
|
listing::{find_lune_scripts, print_lune_scripts, sort_lune_scripts},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const LUNE_SELENE_FILE_NAME: &str = "lune.yml";
|
const LUNE_SELENE_FILE_NAME: &str = "lune.yml";
|
||||||
const LUNE_LUAU_FILE_NAME: &str = "luneTypes.d.luau";
|
const LUNE_LUAU_FILE_NAME: &str = "luneTypes.d.luau";
|
||||||
|
const LUNE_DOCS_FILE_NAME: &str = "luneDocs.json";
|
||||||
|
|
||||||
/// Lune CLI
|
/// Lune CLI
|
||||||
#[derive(Parser, Debug, Default)]
|
#[derive(Parser, Debug, Default)]
|
||||||
#[command(author, version, about, long_about = None)]
|
#[command(author, version, about, long_about = None)]
|
||||||
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
pub struct Cli {
|
pub struct Cli {
|
||||||
/// Path to the file to run, or the name
|
/// Path to the file to run, or the name
|
||||||
/// of a luau file in a lune directory
|
/// of a luau file in a lune directory
|
||||||
|
@ -37,6 +43,10 @@ pub struct Cli {
|
||||||
/// definitions file to the current directory
|
/// definitions file to the current directory
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
download_luau_types: bool,
|
download_luau_types: bool,
|
||||||
|
/// Pass this flag to generate the Lune documentation file
|
||||||
|
/// from a luau type definitions file in the current directory
|
||||||
|
#[clap(long)]
|
||||||
|
generate_docs_file: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -123,10 +133,18 @@ impl Cli {
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Generate docs file, if wanted
|
||||||
|
if self.generate_docs_file {
|
||||||
|
let defs_contents = read_to_string(LUNE_LUAU_FILE_NAME).await?;
|
||||||
|
let docs_root = generate_docs_json_from_definitions(&defs_contents, "roblox/global")?;
|
||||||
|
let docs_contents = serde_json::to_string_pretty(&docs_root)?;
|
||||||
|
write(LUNE_DOCS_FILE_NAME, &docs_contents).await?;
|
||||||
|
}
|
||||||
if self.script_path.is_none() {
|
if self.script_path.is_none() {
|
||||||
// Only downloading types without running a script is completely
|
// Only downloading types without running a script is completely
|
||||||
// fine, and we should just exit the program normally afterwards
|
// fine, and we should just exit the program normally afterwards
|
||||||
if download_types_requested {
|
// Same thing goes for generating the docs file
|
||||||
|
if download_types_requested || self.generate_docs_file {
|
||||||
return Ok(ExitCode::SUCCESS);
|
return Ok(ExitCode::SUCCESS);
|
||||||
}
|
}
|
||||||
// HACK: We know that we didn't get any arguments here but since
|
// HACK: We know that we didn't get any arguments here but since
|
||||||
|
@ -138,7 +156,7 @@ impl Cli {
|
||||||
}
|
}
|
||||||
// Parse and read the wanted file
|
// Parse and read the wanted file
|
||||||
let file_path = find_parse_file_path(&self.script_path.unwrap())?;
|
let file_path = find_parse_file_path(&self.script_path.unwrap())?;
|
||||||
let file_contents = read_to_string(&file_path)?;
|
let file_contents = read_to_string(&file_path).await?;
|
||||||
// Display the file path relative to cwd with no extensions in stack traces
|
// Display the file path relative to cwd with no extensions in stack traces
|
||||||
let file_display_name = file_path.with_extension("").display().to_string();
|
let file_display_name = file_path.with_extension("").display().to_string();
|
||||||
// Create a new lune object with all globals & run the script
|
// Create a new lune object with all globals & run the script
|
||||||
|
|
46
src/cli/gen/doc.rs
Normal file
46
src/cli/gen/doc.rs
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Default, Debug)]
|
||||||
|
pub struct DocsGlobal {
|
||||||
|
pub documentation: String,
|
||||||
|
pub keys: HashMap<String, String>,
|
||||||
|
pub learn_more_link: String,
|
||||||
|
pub code_sample: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Default, Debug)]
|
||||||
|
pub struct DocsFunctionParamLink {
|
||||||
|
pub name: String,
|
||||||
|
pub documentation: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Default, Debug)]
|
||||||
|
pub struct DocsFunction {
|
||||||
|
#[serde(skip)]
|
||||||
|
pub global_name: String,
|
||||||
|
pub documentation: String,
|
||||||
|
pub params: Vec<DocsFunctionParamLink>,
|
||||||
|
pub returns: Vec<String>,
|
||||||
|
pub learn_more_link: String,
|
||||||
|
pub code_sample: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Default, Debug)]
|
||||||
|
pub struct DocsParam {
|
||||||
|
#[serde(skip)]
|
||||||
|
pub global_name: String,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub function_name: String,
|
||||||
|
pub documentation: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Default, Debug)]
|
||||||
|
pub struct DocsReturn {
|
||||||
|
#[serde(skip)]
|
||||||
|
pub global_name: String,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub function_name: String,
|
||||||
|
pub documentation: String,
|
||||||
|
}
|
83
src/cli/gen/mod.rs
Normal file
83
src/cli/gen/mod.rs
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use regex::Regex;
|
||||||
|
use serde_json::{Map, Value};
|
||||||
|
|
||||||
|
use full_moon::{parse as parse_luau_ast, visitors::Visitor};
|
||||||
|
|
||||||
|
mod doc;
|
||||||
|
mod tag;
|
||||||
|
mod visitor;
|
||||||
|
|
||||||
|
use self::{doc::DocsFunctionParamLink, visitor::DocumentationVisitor};
|
||||||
|
|
||||||
|
fn parse_definitions(contents: &str) -> Result<DocumentationVisitor> {
|
||||||
|
let (regex, replacement) = (
|
||||||
|
Regex::new(r#"declare (?P<n>\w+): \{"#).unwrap(),
|
||||||
|
r#"export type $n = {"#,
|
||||||
|
);
|
||||||
|
let defs_ast = parse_luau_ast(®ex.replace_all(contents, replacement))?;
|
||||||
|
let mut visitor = DocumentationVisitor::new();
|
||||||
|
visitor.visit_ast(&defs_ast);
|
||||||
|
Ok(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_docs_json_from_definitions(contents: &str, namespace: &str) -> Result<Value> {
|
||||||
|
let visitor = parse_definitions(contents)?;
|
||||||
|
/*
|
||||||
|
Extract globals, functions, params, returns from the visitor
|
||||||
|
Here we will also convert the plain names into proper namespaced names according to the spec at
|
||||||
|
https://raw.githubusercontent.com/MaximumADHD/Roblox-Client-Tracker/roblox/api-docs/en-us.json
|
||||||
|
*/
|
||||||
|
let mut map = Map::new();
|
||||||
|
for (name, mut doc) in visitor.globals {
|
||||||
|
doc.keys = doc
|
||||||
|
.keys
|
||||||
|
.iter()
|
||||||
|
.map(|(key, value)| (key.clone(), format!("@{namespace}/{name}.{value}")))
|
||||||
|
.collect::<HashMap<String, String>>();
|
||||||
|
map.insert(format!("@{namespace}/{name}"), serde_json::to_value(doc)?);
|
||||||
|
}
|
||||||
|
for (name, mut doc) in visitor.functions {
|
||||||
|
doc.params = doc
|
||||||
|
.params
|
||||||
|
.iter()
|
||||||
|
.map(|param| DocsFunctionParamLink {
|
||||||
|
name: param.name.clone(),
|
||||||
|
documentation: format!(
|
||||||
|
"@{namespace}/{}.{name}/param/{}",
|
||||||
|
doc.global_name, param.documentation
|
||||||
|
),
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
doc.returns = doc
|
||||||
|
.returns
|
||||||
|
.iter()
|
||||||
|
.map(|ret| format!("@{namespace}/{}.{name}/return/{ret}", doc.global_name))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
map.insert(
|
||||||
|
format!("@{namespace}/{}.{name}", doc.global_name),
|
||||||
|
serde_json::to_value(doc)?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
for (name, doc) in visitor.params {
|
||||||
|
map.insert(
|
||||||
|
format!(
|
||||||
|
"@{namespace}/{}.{}/param/{name}",
|
||||||
|
doc.global_name, doc.function_name
|
||||||
|
),
|
||||||
|
serde_json::to_value(doc)?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
for (name, doc) in visitor.returns {
|
||||||
|
map.insert(
|
||||||
|
format!(
|
||||||
|
"@{namespace}/{}.{}/return/{name}",
|
||||||
|
doc.global_name, doc.function_name
|
||||||
|
),
|
||||||
|
serde_json::to_value(doc)?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Ok(Value::Object(map))
|
||||||
|
}
|
64
src/cli/gen/tag.rs
Normal file
64
src/cli/gen/tag.rs
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
use anyhow::{bail, Result};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub enum DocsTagKind {
|
||||||
|
Class,
|
||||||
|
Within,
|
||||||
|
Param,
|
||||||
|
Return,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DocsTagKind {
|
||||||
|
pub fn parse(s: &str) -> Result<Self> {
|
||||||
|
match s.trim().to_ascii_lowercase().as_ref() {
|
||||||
|
"class" => Ok(Self::Class),
|
||||||
|
"within" => Ok(Self::Within),
|
||||||
|
"param" => Ok(Self::Param),
|
||||||
|
"return" => Ok(Self::Return),
|
||||||
|
s => bail!("Unknown docs tag: '{}'", s),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct DocsTag {
|
||||||
|
pub kind: DocsTagKind,
|
||||||
|
pub name: String,
|
||||||
|
pub contents: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct DocsTagList {
|
||||||
|
tags: Vec<DocsTag>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DocsTagList {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self { tags: vec![] }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push(&mut self, tag: DocsTag) {
|
||||||
|
self.tags.push(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn contains(&mut self, kind: DocsTagKind) -> bool {
|
||||||
|
self.tags.iter().any(|tag| tag.kind == kind)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find(&mut self, kind: DocsTagKind) -> Option<&DocsTag> {
|
||||||
|
self.tags.iter().find(|tag| tag.kind == kind)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.tags.is_empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoIterator for DocsTagList {
|
||||||
|
type Item = DocsTag;
|
||||||
|
type IntoIter = std::vec::IntoIter<Self::Item>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.tags.into_iter()
|
||||||
|
}
|
||||||
|
}
|
188
src/cli/gen/visitor.rs
Normal file
188
src/cli/gen/visitor.rs
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
use full_moon::{
|
||||||
|
ast::types::{ExportedTypeDeclaration, TypeField, TypeFieldKey},
|
||||||
|
tokenizer::{Token, TokenType},
|
||||||
|
visitors::Visitor,
|
||||||
|
};
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
doc::{DocsFunction, DocsFunctionParamLink, DocsGlobal, DocsParam, DocsReturn},
|
||||||
|
tag::{DocsTag, DocsTagKind, DocsTagList},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct DocumentationVisitor {
|
||||||
|
pub globals: Vec<(String, DocsGlobal)>,
|
||||||
|
pub functions: Vec<(String, DocsFunction)>,
|
||||||
|
pub params: Vec<(String, DocsParam)>,
|
||||||
|
pub returns: Vec<(String, DocsReturn)>,
|
||||||
|
tag_regex: Regex,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DocumentationVisitor {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let tag_regex = Regex::new(r#"^@(\w+)\s+(\w+)(.*)$"#).unwrap();
|
||||||
|
Self {
|
||||||
|
globals: vec![],
|
||||||
|
functions: vec![],
|
||||||
|
params: vec![],
|
||||||
|
returns: vec![],
|
||||||
|
tag_regex,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_moonwave_style_tag(&self, line: &str) -> Option<DocsTag> {
|
||||||
|
if self.tag_regex.is_match(line) {
|
||||||
|
let captures = self.tag_regex.captures(line).unwrap();
|
||||||
|
let tag_kind = captures.get(1).unwrap().as_str();
|
||||||
|
let tag_name = captures.get(2).unwrap().as_str();
|
||||||
|
let tag_contents = captures.get(3).unwrap().as_str();
|
||||||
|
Some(DocsTag {
|
||||||
|
kind: DocsTagKind::parse(tag_kind).unwrap(),
|
||||||
|
name: tag_name.to_string(),
|
||||||
|
contents: tag_contents.to_string(),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_moonwave_style_comment(&self, comment: &str) -> (String, DocsTagList) {
|
||||||
|
let lines = comment.lines().map(str::trim).collect::<Vec<_>>();
|
||||||
|
let indent_len = lines.iter().fold(usize::MAX, |acc, line| {
|
||||||
|
let first = line.chars().enumerate().find_map(|(idx, ch)| {
|
||||||
|
if ch.is_alphanumeric() {
|
||||||
|
Some(idx)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if let Some(first_alphanumeric) = first {
|
||||||
|
if first_alphanumeric > 0 {
|
||||||
|
acc.min(first_alphanumeric - 1)
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
acc
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let unindented_lines = lines.iter().map(|line| &line[indent_len..]);
|
||||||
|
let mut doc_lines = Vec::new();
|
||||||
|
let mut doc_tags = DocsTagList::new();
|
||||||
|
for line in unindented_lines {
|
||||||
|
if let Some(tag) = self.parse_moonwave_style_tag(line) {
|
||||||
|
doc_tags.push(tag);
|
||||||
|
} else {
|
||||||
|
doc_lines.push(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(doc_lines.join("\n").trim().to_owned(), doc_tags)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extract_moonwave_comment(&mut self, token: &Token) -> Option<(String, DocsTagList)> {
|
||||||
|
if let TokenType::MultiLineComment { comment, .. } = token.token_type() {
|
||||||
|
let (doc, tags) = self.parse_moonwave_style_comment(comment);
|
||||||
|
if doc.is_empty() && tags.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some((doc, tags))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Visitor for DocumentationVisitor {
|
||||||
|
fn visit_exported_type_declaration(&mut self, node: &ExportedTypeDeclaration) {
|
||||||
|
for token in node.export_token().leading_trivia() {
|
||||||
|
if let Some((doc, mut tags)) = self.extract_moonwave_comment(token) {
|
||||||
|
if tags.contains(DocsTagKind::Class) {
|
||||||
|
self.globals.push((
|
||||||
|
node.type_declaration().type_name().token().to_string(),
|
||||||
|
DocsGlobal {
|
||||||
|
documentation: doc,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_type_field(&mut self, node: &TypeField) {
|
||||||
|
// Parse out names, moonwave comments from the ast
|
||||||
|
let mut parsed_data = Vec::new();
|
||||||
|
if let TypeFieldKey::Name(name) = node.key() {
|
||||||
|
for token in name.leading_trivia() {
|
||||||
|
if let Some((doc, mut tags)) = self.extract_moonwave_comment(token) {
|
||||||
|
if let Some(within) = tags.find(DocsTagKind::Within).map(ToOwned::to_owned) {
|
||||||
|
parsed_data.push((within.name, name, doc, tags));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (global_name, name, doc, tags) in parsed_data {
|
||||||
|
// Find the global definition, which is guaranteed to
|
||||||
|
// be visited and parsed before its inner members, and
|
||||||
|
// add a ref to the found function / member to it
|
||||||
|
let name = name.token().to_string();
|
||||||
|
for (name, global) in &mut self.globals {
|
||||||
|
if name == &global_name {
|
||||||
|
global.keys.insert(name.clone(), name.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Look through tags to find and create doc params and returns
|
||||||
|
let mut param_links = Vec::new();
|
||||||
|
let mut return_links = Vec::new();
|
||||||
|
for tag in tags {
|
||||||
|
match tag.kind {
|
||||||
|
DocsTagKind::Param => {
|
||||||
|
let idx_string = param_links.len().to_string();
|
||||||
|
self.params.push((
|
||||||
|
idx_string.clone(),
|
||||||
|
DocsParam {
|
||||||
|
global_name: global_name.clone(),
|
||||||
|
function_name: name.clone(),
|
||||||
|
documentation: tag.contents.trim().to_owned(),
|
||||||
|
},
|
||||||
|
));
|
||||||
|
param_links.push(DocsFunctionParamLink {
|
||||||
|
name: tag.name.clone(),
|
||||||
|
documentation: idx_string.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
DocsTagKind::Return => {
|
||||||
|
// NOTE: Returns don't have names but we still parse
|
||||||
|
// them as such, so we should concat name & contents
|
||||||
|
let doc = format!("{} {}", tag.name.trim(), tag.contents.trim());
|
||||||
|
let idx_string = return_links.len().to_string();
|
||||||
|
self.returns.push((
|
||||||
|
idx_string.clone(),
|
||||||
|
DocsReturn {
|
||||||
|
global_name: global_name.clone(),
|
||||||
|
function_name: name.clone(),
|
||||||
|
documentation: doc,
|
||||||
|
},
|
||||||
|
));
|
||||||
|
return_links.push(idx_string.clone());
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Finally, add our complete doc
|
||||||
|
// function with links into the list
|
||||||
|
self.functions.push((
|
||||||
|
name,
|
||||||
|
DocsFunction {
|
||||||
|
global_name,
|
||||||
|
documentation: doc,
|
||||||
|
params: param_links,
|
||||||
|
returns: return_links,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,10 @@
|
||||||
#![deny(clippy::all)]
|
#![deny(clippy::all)]
|
||||||
#![warn(clippy::cargo, clippy::pedantic)]
|
#![warn(clippy::cargo, clippy::pedantic)]
|
||||||
#![allow(clippy::needless_pass_by_value, clippy::match_bool)]
|
#![allow(
|
||||||
|
clippy::needless_pass_by_value,
|
||||||
|
clippy::match_bool,
|
||||||
|
clippy::module_name_repetitions
|
||||||
|
)]
|
||||||
|
|
||||||
use std::process::ExitCode;
|
use std::process::ExitCode;
|
||||||
|
|
||||||
|
@ -8,6 +12,7 @@ use anyhow::Result;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
mod cli;
|
mod cli;
|
||||||
|
mod gen;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use cli::Cli;
|
use cli::Cli;
|
||||||
|
|
Loading…
Reference in a new issue