Actually, lets just not process the typedefs at all

This commit is contained in:
Filip Tibell 2023-05-14 22:01:44 +02:00
parent 75c79e15e8
commit 0db32ad4c4
No known key found for this signature in database
9 changed files with 153 additions and 199 deletions

View file

@ -35,7 +35,7 @@ export type WriteOptions = {
end
```
]=]
export type FS = {
return {
--[=[
@within FS
@must_use
@ -52,7 +52,9 @@ export type FS = {
@param path The path to the file to read
@return The contents of the file
]=]
readFile: (path: string) -> string,
readFile = function(path: string): string
return nil :: any
end,
--[=[
@within FS
@must_use
@ -68,7 +70,9 @@ export type FS = {
@param path The directory path to search in
@return A list of files & directories found
]=]
readDir: (path: string) -> { string },
readDir = function(path: string): { string }
return {}
end,
--[=[
@within FS
@ -83,7 +87,7 @@ export type FS = {
@param path The path of the file
@param contents The contents of the file
]=]
writeFile: (path: string, contents: string) -> (),
writeFile = function(path: string, contents: string) end,
--[=[
@within FS
@ -97,7 +101,7 @@ export type FS = {
@param path The directory to create
]=]
writeDir: (path: string) -> (),
writeDir = function(path: string) end,
--[=[
@within FS
@ -111,7 +115,7 @@ export type FS = {
@param path The file to remove
]=]
removeFile: (path: string) -> (),
removeFile = function(path: string) end,
--[=[
@within FS
@ -125,7 +129,7 @@ export type FS = {
@param path The directory to remove
]=]
removeDir: (path: string) -> (),
removeDir = function(path: string) end,
--[=[
@within FS
@must_use
@ -140,7 +144,9 @@ export type FS = {
@param path The file path to check
@return If the path is a file or not
]=]
isFile: (path: string) -> boolean,
isFile = function(path: string): boolean
return nil :: any
end,
--[=[
@within FS
@must_use
@ -155,7 +161,9 @@ export type FS = {
@param path The directory path to check
@return If the path is a directory or not
]=]
isDir: (path: string) -> boolean,
isDir = function(path: string): boolean
return nil :: any
end,
--[=[
@within FS
@ -175,5 +183,5 @@ export type FS = {
@param to The path to move to
@param overwriteOrOptions Options for the target path, such as if should be overwritten if it already exists
]=]
move: (from: string, to: string, overwriteOrOptions: (boolean | WriteOptions)?) -> (),
move = function(from: string, to: string, overwriteOrOptions: (boolean | WriteOptions)?) end,
}

View file

@ -180,7 +180,7 @@ export type WebSocket = {
end)
```
]=]
export type Net = {
return {
--[=[
@within Net
@ -191,7 +191,9 @@ export type Net = {
@param config The URL or request config to use
@return A dictionary representing the response for the request
]=]
request: (config: string | FetchParams) -> FetchResponse,
request = function(config: string | FetchParams): FetchResponse
return nil :: any
end,
--[=[
@within Net
@must_use
@ -204,7 +206,9 @@ export type Net = {
@param url The URL to connect to
@return A web socket handle
]=]
socket: (url: string) -> WebSocket,
socket = function(url: string): WebSocket
return nil :: any
end,
--[=[
@within Net
@ -216,7 +220,9 @@ export type Net = {
@param port The port to use for the server
@param handlerOrConfig The handler function or config to use for the server
]=]
serve: (port: number, handlerOrConfig: ServeHttpHandler | ServeConfig) -> ServeHandle,
serve = function(port: number, handlerOrConfig: ServeHttpHandler | ServeConfig): ServeHandle
return nil :: any
end,
--[=[
@within Net
@must_use
@ -227,7 +233,9 @@ export type Net = {
@param pretty If the encoded JSON string should include newlines and spaces. Defaults to false
@return The encoded JSON string
]=]
jsonEncode: (value: any, pretty: boolean?) -> string,
jsonEncode = function(value: any, pretty: boolean?): string
return nil :: any
end,
--[=[
@within Net
@must_use
@ -237,7 +245,9 @@ export type Net = {
@param encoded The JSON string to decode
@return The decoded lua value
]=]
jsonDecode: (encoded: string) -> any,
jsonDecode = function(encoded: string): any
return nil :: any
end,
--[=[
@within Net
@must_use
@ -248,7 +258,9 @@ export type Net = {
@param binary If the string should be treated as binary data and/or is not valid utf-8. Defaults to false
@return The encoded string
]=]
urlEncode: (s: string, binary: boolean?) -> string,
urlEncode = function(s: string, binary: boolean?): string
return nil :: any
end,
--[=[
@within Net
@must_use
@ -259,5 +271,7 @@ export type Net = {
@param binary If the string should be treated as binary data and/or is not valid utf-8. Defaults to false
@return The decoded string
]=]
urlDecode: (s: string, binary: boolean?) -> string,
urlDecode = function(s: string, binary: boolean?): string
return nil :: any
end,
}

View file

@ -78,7 +78,7 @@ export type SpawnResult = {
end
```
]=]
export type Process = {
return {
--[=[
@within Process
@read_only
@ -91,7 +91,7 @@ export type Process = {
* `"macos"`
* `"windows"`
]=]
os: OS,
os = (nil :: any) :: OS,
--[=[
@within Process
@read_only
@ -103,21 +103,21 @@ export type Process = {
* `"x86_64"`
* `"aarch64"`
]=]
arch: Arch,
arch = (nil :: any) :: Arch,
--[=[
@within Process
@read_only
The arguments given when running the Lune script.
]=]
args: { string },
args = (nil :: any) :: { string },
--[=[
@within Process
@read_only
The current working directory in which the Lune script is running.
]=]
cwd: string,
cwd = (nil :: any) :: string,
--[=[
@within Process
@read_write
@ -126,7 +126,7 @@ export type Process = {
Setting a value on this table will set the corresponding environment variable.
]=]
env: { [string]: string? },
env = (nil :: any) :: { [string]: string? },
--[=[
@within Process
@ -138,7 +138,7 @@ export type Process = {
@param code The exit code to set
]=]
exit: (code: number?) -> (),
exit = function(code: number?) end,
--[=[
@within Process
@ -154,5 +154,7 @@ export type Process = {
@param options A dictionary of options for the child process
@return A dictionary representing the result of the child process
]=]
spawn: (program: string, params: { string }?, options: SpawnOptions?) -> SpawnResult,
spawn = function(program: string, params: { string }?, options: SpawnOptions?): SpawnResult
return nil :: any
end,
}

View file

@ -21,7 +21,7 @@ export type Instance = {}
roblox.writePlaceFile("myPlaceFile.rbxl", game)
```
]=]
export type Roblox = {
return {
--[=[
@within Roblox
@must_use
@ -37,7 +37,9 @@ export type Roblox = {
@param filePath The file path to read from
]=]
readPlaceFile: (filePath: string) -> Instance,
readPlaceFile = function(filePath: string): Instance
return nil :: any
end,
--[=[
@within Roblox
@must_use
@ -53,7 +55,9 @@ export type Roblox = {
@param filePath The file path to read from
]=]
readModelFile: (filePath: string) -> { Instance },
readModelFile = function(filePath: string): { Instance }
return nil :: any
end,
--[=[
@within Roblox
@ -69,7 +73,7 @@ export type Roblox = {
@param filePath The file path to write to
@param dataModel The DataModel to write to the file
]=]
writePlaceFile: (filePath: string, dataModel: Instance) -> (),
writePlaceFile = function(filePath: string, dataModel: Instance) end,
--[=[
@within Roblox
@ -85,7 +89,7 @@ export type Roblox = {
@param filePath The file path to write to
@param instances The array of instances to write to the file
]=]
writeModelFile: (filePath: string, instances: { Instance }) -> (),
writeModelFile = function(filePath: string, instances: { Instance }) end,
--[=[
@within Roblox
@must_use
@ -122,5 +126,7 @@ export type Roblox = {
@param raw If the cookie should be returned as a pure value or not. Defaults to false
]=]
getAuthCookie: (raw: boolean?) -> string?,
getAuthCookie = function(raw: boolean?): string?
return nil :: any
end,
}

View file

@ -22,7 +22,7 @@ export type EncodeDecodeFormat = "json" | "yaml" | "toml"
fs.writeFile("myFile.yaml", serde.encode("yaml", someYaml))
```
]=]
export type Serde = {
return {
--[=[
@within Serde
@must_use
@ -34,7 +34,9 @@ export type Serde = {
@param pretty If the encoded string should be human-readable, including things such as newlines and spaces. Only supported for json and toml formats, and defaults to false
@return The encoded string
]=]
encode: (format: EncodeDecodeFormat, value: any, pretty: boolean?) -> string,
encode = function(format: EncodeDecodeFormat, value: any, pretty: boolean?): string
return nil :: any
end,
--[=[
@within Serde
@must_use
@ -45,5 +47,7 @@ export type Serde = {
@param encoded The string to decode
@return The decoded lua value
]=]
decode: (format: EncodeDecodeFormat, encoded: string) -> any,
decode = function(format: EncodeDecodeFormat, encoded: string): any
return nil :: any
end,
}

View file

@ -10,6 +10,34 @@ export type Color =
| "white"
export type Style = "reset" | "bold" | "dim"
type PromptFn = (
(() -> string)
& ((kind: "text", message: string?, defaultOrOptions: string?) -> string)
& ((kind: "confirm", message: string, defaultOrOptions: boolean?) -> boolean)
& ((kind: "select", message: string?, defaultOrOptions: { string }) -> number?)
& ((kind: "multiselect", message: string?, defaultOrOptions: { string }) -> { number }?)
)
--[=[
@within Stdio
@must_use
Prompts for user input using the wanted kind of prompt:
* `"text"` - Prompts for a plain text string from the user
* `"confirm"` - Prompts the user to confirm with y / n (yes / no)
* `"select"` - Prompts the user to select *one* value from a list
* `"multiselect"` - Prompts the user to select *one or more* values from a list
* `nil` - Equivalent to `"text"` with no extra arguments
@param kind The kind of prompt to use
@param message The message to show the user
@param defaultOrOptions The default value for the prompt, or options to choose from for selection prompts
]=]
local prompt: PromptFn = function(kind: any, message: any, defaultOrOptions: any)
return nil :: any
end
--[=[
@class Stdio
@ -31,7 +59,7 @@ export type Style = "reset" | "bold" | "dim"
stdio.ewrite("\nAnd some error text, too")
```
]=]
export type Stdio = {
return {
--[=[
@within Stdio
@must_use
@ -52,7 +80,9 @@ export type Stdio = {
@param color The color to use
@return A printable ANSI string
]=]
color: (color: Color) -> string,
color = function(color: Color): string
return nil :: any
end,
--[=[
@within Stdio
@must_use
@ -73,7 +103,9 @@ export type Stdio = {
@param style The style to use
@return A printable ANSI string
]=]
style: (style: Style) -> string,
style = function(style: Style): string
return nil :: any
end,
--[=[
@within Stdio
@must_use
@ -83,7 +115,9 @@ export type Stdio = {
@param ... The values to format
@return The formatted string
]=]
format: (...any) -> string,
format = function(...: any): string
return nil :: any
end,
--[=[
@within Stdio
@ -91,7 +125,7 @@ export type Stdio = {
@param s The string to write to stdout
]=]
write: (s: string) -> (),
write = function(s: string) end,
--[=[
@within Stdio
@ -99,28 +133,6 @@ export type Stdio = {
@param s The string to write to stderr
]=]
ewrite: (s: string) -> (),
--[=[
@within Stdio
@must_use
Prompts for user input using the wanted kind of prompt:
* `"text"` - Prompts for a plain text string from the user
* `"confirm"` - Prompts the user to confirm with y / n (yes / no)
* `"select"` - Prompts the user to select *one* value from a list
* `"multiselect"` - Prompts the user to select *one or more* values from a list
* `nil` - Equivalent to `"text"` with no extra arguments
@param kind The kind of prompt to use
@param message The message to show the user
@param defaultOrOptions The default value for the prompt, or options to choose from for selection prompts
]=]
prompt: (
(() -> string)
& ((kind: "text", message: string?, defaultOrOptions: string?) -> string)
& ((kind: "confirm", message: string, defaultOrOptions: boolean?) -> boolean)
& ((kind: "select", message: string?, defaultOrOptions: { string }) -> number?)
& ((kind: "multiselect", message: string?, defaultOrOptions: { string }) -> { number }?)
),
ewrite = function(s: string) end,
prompt = prompt,
}

View file

@ -27,7 +27,7 @@
print("Running after task.spawn yields")
```
]=]
export type Task = {
return {
--[=[
@within Task
@ -35,7 +35,7 @@ export type Task = {
@param thread The thread to cancel
]=]
cancel: (thread: thread) -> (),
cancel = function(thread: thread) end,
--[=[
@within Task
@ -44,16 +44,26 @@ export type Task = {
@param functionOrThread The function or thread to defer
@return The thread that will be deferred
]=]
defer: <T...>(functionOrThread: thread | (T...) -> ...any, T...) -> thread,
defer = function<T...>(functionOrThread: thread | (T...) -> ...any, ...: T...): thread
return nil :: any
end,
--[=[
@within Task
Delays a thread or function to run after `duration` seconds.
If no `duration` is given, this will wait for the minimum amount of time possible.
@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 = function<T...>(
duration: number?,
functionOrThread: thread | (T...) -> ...any,
...: T...
): thread
return nil :: any
end,
--[=[
@within Task
@ -65,7 +75,9 @@ export type Task = {
@param functionOrThread The function or thread to spawn
@return The thread that was spawned
]=]
spawn: <T...>(functionOrThread: thread | (T...) -> ...any, T...) -> thread,
spawn = function<T...>(functionOrThread: thread | (T...) -> ...any, ...: T...): thread
return nil :: any
end,
--[=[
@within Task
@ -77,5 +89,7 @@ export type Task = {
@param duration The amount of time to wait
@return The exact amount of time waited
]=]
wait: (duration: number?) -> number,
wait = function(duration: number?): number
return nil :: any
end,
}

View file

@ -18,8 +18,24 @@ pub async fn generate_gitbook_dir_from_definitions(dir: &Dir<'_>) -> Result<()>
pub async fn generate_typedef_files_from_definitions(
dir: &Dir<'_>,
) -> Result<HashMap<String, PathBuf>> {
let definitions = read_typedefs_dir(dir)?;
typedef_files::generate_from_type_definitions(definitions).await
let contents = read_typedefs_dir_contents(dir);
typedef_files::generate_from_type_definitions(contents).await
}
fn read_typedefs_dir_contents(dir: &Dir<'_>) -> HashMap<String, Vec<u8>> {
let mut definitions = HashMap::new();
for entry in dir.find("*.luau").unwrap() {
let entry_file = entry.as_file().unwrap();
let entry_name = entry_file.path().file_name().unwrap().to_string_lossy();
let typedef_name = entry_name.trim_end_matches(".luau");
let typedef_contents = entry_file.contents().to_vec();
definitions.insert(typedef_name.to_string(), typedef_contents);
}
definitions
}
fn read_typedefs_dir(dir: &Dir<'_>) -> Result<HashMap<String, DefinitionsTree>> {

View file

@ -1,4 +1,4 @@
use std::{collections::HashMap, fmt::Write, path::PathBuf};
use std::{collections::HashMap, path::PathBuf};
use anyhow::{Context, Result};
use directories::UserDirs;
@ -6,13 +6,9 @@ use directories::UserDirs;
use futures_util::future::try_join_all;
use tokio::fs::{create_dir_all, write};
use super::definitions::{DefinitionsItem, DefinitionsTree};
const GENERATED_COMMENT_TAG: &str = "--!strict";
#[allow(clippy::too_many_lines)]
pub async fn generate_from_type_definitions(
api_reference: HashMap<String, DefinitionsTree>,
typedef_files: HashMap<String, Vec<u8>>,
) -> Result<HashMap<String, PathBuf>> {
let mut dirs_to_write = Vec::new();
let mut files_to_write = Vec::new();
@ -25,19 +21,11 @@ pub async fn generate_from_type_definitions(
.join(env!("CARGO_PKG_VERSION"));
dirs_to_write.push(cache_dir.clone());
// Make typedef files
for (category_name, category_tree) in api_reference {
for (builtin_name, builtin_typedef) in typedef_files {
let path = cache_dir
.join(category_name.to_ascii_lowercase())
.join(builtin_name.to_ascii_lowercase())
.with_extension("luau");
let mut contents = String::new();
write!(
contents,
"{GENERATED_COMMENT_TAG}\n-- @lune/{} {}\n",
category_name.to_lowercase(),
env!("CARGO_PKG_VERSION")
)?;
write_tree(&mut contents, category_name.to_string(), category_tree)?;
files_to_write.push((category_name.to_lowercase(), path, contents));
files_to_write.push((builtin_name.to_lowercase(), path, builtin_typedef));
}
// Write all dirs and files only when we know generation was successful
let futs_dirs = dirs_to_write
@ -55,113 +43,3 @@ pub async fn generate_from_type_definitions(
.map(|(name, path, _)| (name, path))
.collect::<HashMap<_, _>>())
}
fn make_return_table_item(item: &DefinitionsItem) -> Result<String> {
let mut description = String::new();
if let Some(desc) = item.children().iter().find(|child| child.is_description()) {
write!(description, "\n{}\n", desc.get_value().unwrap().trim())?;
for tag in item.children().iter().filter(|child| child.is_tag()) {
let tag_name = tag.get_name().unwrap();
if tag_name == "param" {
write!(
description,
"\n@param {} {}",
tag.get_meta().unwrap(),
tag.get_value().unwrap()
)?;
} else if tag_name == "return" {
write!(description, "\n@return {}", tag.get_value().unwrap())?;
}
}
}
let mut contents = String::new();
if item.is_function() {
let args = item
.args()
.iter()
.map(|arg| format!("{}: {}", arg.name.trim(), arg.typedef.trim()))
.collect::<Vec<_>>()
.join(", ");
// HACK: We should probably handle vararg and generics properly but this works for now...
let args = args
.replace("_: ...any", "...: any")
.replace("_: T...", "...: any")
.replace("(T...)", "(...any)");
write!(contents, "function({args})")?;
write!(contents, "\n\treturn nil :: any")?;
write!(contents, "\nend,")?;
} else if item.is_property() {
write!(contents, "(nil :: any) :: {},", item.get_type().unwrap())?;
}
Ok(format!(
"\n--[=[{}\n]=]\n{} = {}",
description.trim_end().replace('\n', "\n\t"),
item.get_name().unwrap_or("_"),
contents
))
}
fn write_tree(contents: &mut String, name: String, root: DefinitionsTree) -> Result<()> {
let main = root
.children()
.iter()
.find(|c| matches!(c.get_name(), Some(s) if s.to_lowercase() == name.to_lowercase()))
.expect("Failed to find main export for generating typedef file");
let mut description = String::new();
if let Some(desc) = main.children().iter().find(|child| child.is_description()) {
write!(description, "\n{}\n", desc.get_value().unwrap().trim())?;
}
let children = root
.children()
.iter()
.filter(|child| child != &main)
.collect::<Vec<_>>();
for child in children {
if child.is_type() || child.is_table() || child.is_function() || child.is_property() {
let mut child_description = String::new();
if let Some(desc) = child.children().iter().find(|child| child.is_description()) {
write!(
child_description,
"\n{}\n",
desc.get_value().unwrap().trim()
)?;
write!(
contents,
"\n--[=[{}\n]=]",
child_description.trim_end().replace('\n', "\n\t"),
)?;
}
if child.is_exported() {
write!(contents, "\nexport ")?;
}
writeln!(
contents,
"type {} = {}",
child.get_name().unwrap(),
child.get_type().unwrap()
)?;
}
}
let mut ret_table = String::new();
for child in main
.children()
.iter()
.filter(|child| child.is_function() || child.is_property())
{
write!(ret_table, "{}", make_return_table_item(child)?)?;
}
write!(
contents,
"\n--[=[{}\n]=]\nreturn {{\n{}\n}}\n",
description.trim_end().replace('\n', "\n\t"),
ret_table.trim_end().replace('\n', "\n\t")
)?;
Ok(())
}