From 0db32ad4c4f83855f1b700c0e6f43fac794e224b Mon Sep 17 00:00:00 2001 From: Filip Tibell Date: Sun, 14 May 2023 22:01:44 +0200 Subject: [PATCH] Actually, lets just not process the typedefs at all --- docs/typedefs/FS.luau | 28 ++++-- docs/typedefs/Net.luau | 30 ++++-- docs/typedefs/Process.luau | 18 ++-- docs/typedefs/Roblox.luau | 18 ++-- docs/typedefs/Serde.luau | 10 +- docs/typedefs/Stdio.luau | 70 ++++++++------ docs/typedefs/Task.luau | 26 +++-- packages/cli/src/gen/mod.rs | 20 +++- packages/cli/src/gen/typedef_files.rs | 132 +------------------------- 9 files changed, 153 insertions(+), 199 deletions(-) diff --git a/docs/typedefs/FS.luau b/docs/typedefs/FS.luau index f15d9e1..6d249f3 100644 --- a/docs/typedefs/FS.luau +++ b/docs/typedefs/FS.luau @@ -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, } diff --git a/docs/typedefs/Net.luau b/docs/typedefs/Net.luau index 04558e5..2869a92 100644 --- a/docs/typedefs/Net.luau +++ b/docs/typedefs/Net.luau @@ -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, } diff --git a/docs/typedefs/Process.luau b/docs/typedefs/Process.luau index 0fbadb8..6b82c32 100644 --- a/docs/typedefs/Process.luau +++ b/docs/typedefs/Process.luau @@ -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, } diff --git a/docs/typedefs/Roblox.luau b/docs/typedefs/Roblox.luau index af10b61..c7b288b 100644 --- a/docs/typedefs/Roblox.luau +++ b/docs/typedefs/Roblox.luau @@ -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, } diff --git a/docs/typedefs/Serde.luau b/docs/typedefs/Serde.luau index ddc7694..8ca0a2b 100644 --- a/docs/typedefs/Serde.luau +++ b/docs/typedefs/Serde.luau @@ -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, } diff --git a/docs/typedefs/Stdio.luau b/docs/typedefs/Stdio.luau index 37f4dd7..fbd7134 100644 --- a/docs/typedefs/Stdio.luau +++ b/docs/typedefs/Stdio.luau @@ -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, } diff --git a/docs/typedefs/Task.luau b/docs/typedefs/Task.luau index 42ff92c..d902568 100644 --- a/docs/typedefs/Task.luau +++ b/docs/typedefs/Task.luau @@ -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: (functionOrThread: thread | (T...) -> ...any, T...) -> thread, + defer = function(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: (duration: number?, functionOrThread: thread | (T...) -> ...any, T...) -> thread, + delay = function( + 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: (functionOrThread: thread | (T...) -> ...any, T...) -> thread, + spawn = function(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, } diff --git a/packages/cli/src/gen/mod.rs b/packages/cli/src/gen/mod.rs index a0acfa0..a68e262 100644 --- a/packages/cli/src/gen/mod.rs +++ b/packages/cli/src/gen/mod.rs @@ -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> { - 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> { + 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> { diff --git a/packages/cli/src/gen/typedef_files.rs b/packages/cli/src/gen/typedef_files.rs index 12f847c..33cc305 100644 --- a/packages/cli/src/gen/typedef_files.rs +++ b/packages/cli/src/gen/typedef_files.rs @@ -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, + typedef_files: HashMap>, ) -> Result> { 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::>()) } - -fn make_return_table_item(item: &DefinitionsItem) -> Result { - 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::>() - .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::>(); - 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(()) -}