This repository was archived by the owner on Dec 27, 2025. It is now read-only.
sync#2
Open
cheesycod wants to merge 661 commits into
Open
Conversation
Adds and uses `assert.that(value: unknown, msg: string?): Failure?` in lieu of places we have `assert.eq(_, true)` We considered naming this `assert.true` and `assert.truthy`, but agreed on `assert.that` since it's the [new (suggested) API for NUnit](https://docs.nunit.org/articles/nunit/writing-tests/assertions/assertion-models/constraint.html)
) We've defined a version string in CMake, which gets turned into a header that C++ commands can consume. However, the code in lute uses a hardcoded version of this string. We need to expose this information to the cli commands so that they can use the correct version when setting up new projects or generating type definition files. This PR sets up a global table called `version` with shape: `{version: string, versionFull : string, versionSuffix : string}` for consumption _exclusively_ by the CLI commands. User code and code loaded by various lute apis in the tests cannot use this global (as those are sandboxed environments).
Fix #643 `TOML` `deserialization` of quoted keys containing dots, which were incorrectly split into separate keys. Adds quote-aware path splitting for `deserialization` and key quoting for `serialization` so round-trips preserve structure. Now we can run this code: ```luau local pp = require("@batteries/pp") local toml = require("@batteries/toml") local content = [=[ [assets.package] assetId = "120786139379662" [images."icon.png"] assetId = "95124518202499" hash = "fac185770cf5e824d4c0a9b59e547df42dc10011c5ad139bfc2c7e1507eef631" ]=] local deserialized = toml.deserialize(content) local serialized = toml.serialize(deserialized) print("\nDeserialized:") print(pp(deserialized)) print("\nSerialized:") print(serialized) ``` and get: ```console Deserialized: { assets = { package = { assetId = "120786139379662", }, }, images = { ["icon.png"] = { assetId = "95124518202499", hash = "fac185770cf5e824d4c0a9b59e547df42dc10011c5ad139bfc2c7e1507eef631", }, }, } Serialized: [assets.package] assetId = "120786139379662" [images."icon.png"] hash = "fac185770cf5e824d4c0a9b59e547df42dc10011c5ad139bfc2c7e1507eef631" assetId = "95124518202499" ```
updating path types and query to PascalCase
Right now, users have to write something like this to get `require` calls([example](https://github.com/luau-lang/lute/blob/e0faf05ee8d274be25c9e686e95c88af42d9589c/examples/query.luau#L7)): ```luau local requireCalls = query .findallfromroot(ast, utils.isExprCall) :filter(function(call) local calledFunc = call.func return calledFunc.tag == "global" and calledFunc.name.text == "require" end) ``` writing their own `helpers`([example](https://github.com/luau-lang/lute/blob/e0faf05ee8d274be25c9e686e95c88af42d9589c/lute/cli/commands/lint/rules/unused_variable.luau#L19)): ```luau local function isRequireCall(expr: syntax.AstExpr) return expr.tag == "call" and expr.func.tag == "global" and expr.func.name.text == "require" end ``` It would be nice if `utils` had `utils.isRequireCall`. Then it would be simplified to: ```luau local requireCalls = query.findallfromroot(ast, utils.isRequireCall) ``` Thanks to @Vighnesh-V for [highlighting](https://github.com/luau-lang/lute/pull/878/changes#r2934146238) the issue and @skberkeley for the `API` [suggestion](https://github.com/luau-lang/lute/pull/878/changes#r2934155678). --------- Co-authored-by: Vighnesh Vijay <vvijay@roblox.com>
If you try to run the `process` example, an error throws: ``` 0 Hello, lute! @std/task.luau:60: attempt to index number with 'success' stacktrace: @std/task.luau:60 function awaitall ./examples/process.luau:15 ``` This occurs as we iterate over `tasks`, which is equal to a `table.pack` return value. This means `tasks` has an `n` property and is not entirely array-like. We can use `ipairs` when iterating over `tasks` to avoid the bug
…ed by `@lute/time` (#900) We've had a long-standing split between `@std/time` and `@lute/time` where the former provided an entirely userland implementation of duration, but the latter provided both durations and instants from C++. In the interest of getting the standard library generally into shape and avoiding these confusing duplications (with differences!) between the runtime and the standard library, this PR eliminates the `@std/time` that already exists, and replaces it with one that re-exports the runtime functionality. Making this a proper replacement required both implementing `__mul` and `__div`, as well as fixing a number of smaller bugs that were scattered throughout the runtime implementation of duration.
Adds explicit `jumpToAlias` implementations to support FileVfs handling unprefixed relative paths in configuration files. Earlier, we were able to get away with reusing the same `resetToPath` function for both resetting to a path (such as when initializing FileVfs to point to the project entry point script) and for jumping to aliases. We now need to split these back into two different implementations (although, there is a good amount of logic reused) because the "reset" path requires us to resolve relative paths from the current working directory, but the "jumpToAlias" path requires us to resolve them relative to the .luaurc/.config.luau in which they were defined. This must be done here and not in Luau.Require, as Luau.Require relies on prefixes to determine path type. The absence of a prefix in this case means that the embedder (Lute) must be responsible for path resolution.
…heck` (#862) This PR ensures that `lute check` correctly resolves and uses embedded source code for the `@std`, `@lute`, and `@batteries` namespaces during static analysis. Previously, `lute check` used a basic file resolver that only searched the physical disk. Since Lute's standard library and runtime definitions are embedded directly into the executable, `require` calls to these namespaces would fail to resolve. This caused Luau to treat standard modules as `any`, effectively disabling typechecking for code that relied on Lute's built-in APIs. - **Refactored `resolveRequire`**: Updated the core resolution logic in `lute/luau/src/resolverequire.cpp` to support both physical disk and virtual embedded paths. - **Implemented `readSourceFromVfs`**: Added a utility to retrieve source code directly from Lute's internal memory buffers when an `@` alias is used. - **Updated Resolvers**: Integrated the new resolution and reading logic into `LuteModuleResolver` and `LuteFileResolver`. - **Build System Integration**: Updated `lute/luau/CMakeLists.txt` to link the analysis library against `Lute.Std`, `Lute.Lute`, and `Lute.Batteries`, ensuring the embedded sources are available at compile time. - **Improved Global Registry**: Ensured the `require` function is correctly recognized as a built-in global during the analysis phase. Fixes #773 --------- Co-authored-by: Master Oogway <ActualMasterOogway@users.noreply.github.com> Co-authored-by: Vighnesh Vijay <vvijay@roblox.com>
This PR adds documentation that summarizes a) how to write tests, b) how to run tests, c) how to organize your tests using suites. I've also explicitly called out testing as part of the cool developer tooling we've built, and linked it in the CLI reference. The plan for the Developer Tooling section is to extend it with blurbs about `lute lint`, `lute check`, and `lute compile` (and any others that we add).
When working on cleaning up `lute doc` with `typeofmodule` API integration, I noticed that function type serialization was missing the `argNames` fields, so we weren't preserving the argument names of the parameters in function types. This makes it hard for users (aka the `lute doc` command) to use the type serialization on function types because our output would be missing the argument names and only have the types, which isn't very useful to understand the function signature. Before this change, using the type serializer to generate docs would result in (the wip) `fs.link` serialization appearing as: ```luau fs.link (string, string) -> () ``` But after this change, we have: ```luau fs.link (src: string, dest: string) -> () ``` which better matches the actual function signature of of fs.link, which is ```luau function fs.link(src: string, dest: string): () ``` Pls see more examples of this specific change's additions (in my [WIP branch](https://github.com/luau-lang/lute/compare/annietang/lute_doc_integration_with_typeofmodule) of `lute doc`) if curious: 9488009
…ssert.throwsWith` (#905) following naming convention from [NUnit](https://docs.nunit.org/articles/nunit/writing-tests/assertions/classic-assertions/Assert.Throws.html) `assert.errors` renamed to `assert.throws<...T>: function, ...T` `assert.errorseq` renamed to `assert.throwsWith<...T> : (with : any, function, ...T)`
**Luau**: Updated from `0.713` to `0.714` **Release Notes:** https://github.com/luau-lang/luau/releases/tag/0.714 --- *This PR was automatically created by the [Update Luau workflow](https://github.com/luau-lang/lute/actions/workflows/update-prs.yml)* Co-authored-by: aatxe <744293+aatxe@users.noreply.github.com> Co-authored-by: Sora Kanosue <kanosuesora@gmail.com>
**Lute**: Updated from `0.1.0-nightly.20260320` to `0.1.0-nightly.20260327` **Release Notes:** https://github.com/luau-lang/lute/releases/tag/0.1.0-nightly.20260327 --- *This PR was automatically created by the [Update Luau workflow](https://github.com/luau-lang/lute/actions/workflows/update-prs.yml)* Co-authored-by: aatxe <744293+aatxe@users.noreply.github.com>
Achieved via a combination of refactoring, casts, and annotations. The remaining ones should be addressed/addressable when we bump Luau to 0.716.
Part of a larger refactor of the AST types
The typechecker was flagging an actual error in the luau code, which is that the table we were creating to represent filtered test suites was missing properties. Although the testing framework never uses these properties (as they are index metatable methods that are used to register test cases), they are in fact missing, which can cause errors if they are accesses down the road. This PR just table.clones these testsuites and updates their test cases explicitly to the list of filtered test cases.
Moved the `profiler options` from the `CLI` directly into the `profiler`. Currently, the sampling `frequency` in Hz duplicates its default value in two places: [here](https://github.com/luau-lang/lute/blob/6ed3142c96d109a7ac94ec7c9a7d8dc86a56ac69/lute/cli/src/profiler.cpp#L53) and [here](https://github.com/luau-lang/lute/blob/6ed3142c96d109a7ac94ec7c9a7d8dc86a56ac69/lute/cli/include/lute/climain.h#L13). It has no impact at the moment, but having a single source will help avoid potential bugs in the future. Originally a minor change in PR #911, this has been moved to a separate PR for better clarity. Besides, in PR #911 the main logic of `runBytecode` was moved from `CLI` to `Runtime`, so we don't need the `profiler` dependency in the `CLI` at all.
Part of a larger refactor of AST types where we want property names to be camelCased
Part of a larger refactor of AST types so that property names are camelCased
Part of a larger refactor of AST types so property names are camelCased
…ableeq` and `buffereq` (#904) Updates `assert.eq` to perform structural equality, calling `assert.tableeq` and `assert.buffereq` to simplify user experience for the assertion library. We also unexpose `tableeq`, `buffereq` so users only need to use `assert.eq` to test equality Updates tests and snapshots to reflect changes
…#906) This PR exposes the `task` library methods in `@std` as wrappers around the task methods in `@lute`. I've left in the previous implementations of `task.await/awaitAll/create` for now, because we're still exposing the superset that users would expect of the roblox api.
isAbsolute is now camelCased per #919
- camelCases the members of the stringext library.
- `local stringext = require("@std/stringext') -> local stringExt =
require("@std/stringext")` - not strictly required, but I just feel like
it's better.
camelCased functions for #919
camelCased relevant functions for #919
Refactor for #919
Summary - Make lute pkg install read the existing loom.lock.luau before resolving. If the lockfile satisfies the current manifest and path dependencies haven't changed, skip resolution entirely. - When re-resolution is needed, the solver prefers previously-locked registry versions to minimize version churn - Add --locked flag that errors if the lockfile is missing or doesn't match the manifest
The CLI battery's `help` method was showing empty parens if an option didn't have any aliases. I added a check not to emit it if there is no alias, and snapshot tests documenting it.
Title is self-explanatory. I feel like I've ended up implementing bespoke versions of these quite often in side projects, so I think they'd be useful to have. Open to name-change ideas --------- Co-authored-by: ariel <aweiss@hey.com> Co-authored-by: ariel <arielweiss@roblox.com>
Updates all the lint messages that begin with "XYZ detected". Slightly changes some wording to read better. --------- Co-authored-by: Sora Kanosue <kanosuesora@gmail.com> Co-authored-by: ariel <aweiss@hey.com>
Adds a non-default lint to flag on reassignment of parameters in functions.
…1181) As part of introducing AST types to Lute, we would like AST types to subtype structurally against CST types. However, the AST returned by the Luau parser provides no way to distinguish between table type properties that are bracketed and those that aren't. This means that the eventual Lute AST will have a single type for bracketed and non-bracketed table type properties, so the Lute CST should too.
Fixes #1172. On Windows, `io.input()` returned the line with its trailing terminator still attached. That meant a path read from input would fail in `fs.open()` with "no such file or directory" even when the file was right there. The cause is that `io.input()` just returned `io.read()` directly. `io.read()` is the raw read primitive, so it returns the bytes from stdin as-is, including the line terminator (`\r\n` on Windows, `\n` on Unix). I fixed it in `io.input()` instead of `io.read()` so the raw read keeps returning exactly what it read, while the line-oriented helper hands back a clean string you can pass straight to filesystem APIs. It strips a single trailing terminator and leaves interior and leading whitespace alone. I added `IoInputSuite` to `tests/std/io.test.luau`. Each case pipes a value into a small script so the platform's own terminator gets appended (`\r\n` on Windows, which is the case in #1172, and `\n` on Unix), then checks that `io.input()` returns the clean string. The cases cover a basic value, a path with separators, and preserving interior whitespace. I verified this locally on Windows with the MSVC (VS 2022) build. The new suite passes and the rest of the test suite is unaffected.
**Lute**: Updated from `1.0.1-nightly.20260701` to `1.0.1-nightly.20260710` **Release Notes:** https://github.com/luau-lang/lute/releases/tag/v1.0.1-nightly.20260710 --- *This PR was automatically created by the [Update Luau workflow](https://github.com/luau-lang/lute/actions/workflows/update-prs.yml)* Co-authored-by: aatxe <744293+aatxe@users.noreply.github.com>
**Luau**: Updated from `0.728` to `0.729` **Release Notes:** https://github.com/luau-lang/luau/releases/tag/0.729 --- *This PR was automatically created by the [Update Luau workflow](https://github.com/luau-lang/lute/actions/workflows/update-prs.yml)* Co-authored-by: aatxe <744293+aatxe@users.noreply.github.com>
- Add overrides support to loom, allowing projects to force specific
versions or sources for any transitive dependency (similar to npm/pnpm
overrides)
- Two override modes: version pin (force an exact registry version) and
source redirect (replace a registry package with a local path or github
source)
- Lockfile version bumps to 4 only when overrides are present; projects
without overrides stay on version 3
Overrides are declared at the project root in loom.config.luau:
```
return {
package = { ... },
overrides = {
-- Pin a transitive dependency to an exact version
citrus = { sourceKind = "registry", source = "citrus", version = "3.0.0" },
-- Or redirect to a local fork
citrus = { sourceKind = "path", source = "./citrus-fork" },
},
}
```
The resolver removes conflicting constraints for overridden packages,
builds a modified universe respecting the pins, and stitches
source-redirected packages back into the dependency graph after solving.
The lockfile records a fingerprint of
active overrides so changes trigger re-resolution.
Recent changes to the Luau type solver have reduced the number of code too complex errors being emitted, meaning we can remove some any casts.
Adds a `lute self` subcommand for installing, updating, and uninstalling lute from a well-known system location (~/.lute/bin). This gives users a first-class way to bootstrap and maintain their lute installation without relying on external toolchain managers. ### Subcommands - `lute self install`: Copies the running lute binary to `~/.lute/bin` and adds it to PATH via shell profile modifications (Unix) or the user registry (Windows) - `lute self update`: Queries the latest GitHub release (or a specific `--version`) and replaces the installed binary - `lute self uninstall`: Removes the binary directory and strips PATH entries from all known shell profiles. Supports `--remove-data` to also delete cached type definitions under `~/.lute` --------- Co-authored-by: Ariel Weiss <arielweiss@roblox.com>
After #1205 was merged, I noticed the documentation has the wrong casing for `Self` instead of `self` (see https://lute.luau.org/cli/self.html)
This PR makes breakpoints actually functional but in order to do we need to add many features under the hood * as mentioned here #1202 (review), we need to run the child debuggee process in a separate VM. * as a side effect of the above change, we need to instead schedule operations (such as adding and removing breakpoints) onto the child VM, which effectively makes them async * we add some callbacks when breakpoints are installed or un-installed, and when program execution terminates, and when a breakpoint is hit * we add a `continue()` to resume program execution Caveats: * most of this code relies on the debugged script (`exit` and `continue`) being single coroutine. Multi-coroutines execution will be handled in future PRs.
Pretty straightforward, implements a `--nightly` flag to update to the latest nightly build as opposed to the latest official release which is currently at `1.0.0`: https://api.github.com/repos/luau-lang/lute/releases/latest --------- Co-authored-by: ariel <aweiss@hey.com>
The `resolve` function has gotten a little big. This PR just breaks out the functionality to individual functions
**Lute**: Updated from `1.0.1-nightly.20260710` to `1.0.1-nightly.20260717` **Release Notes:** https://github.com/luau-lang/lute/releases/tag/v1.0.1-nightly.20260717 --- *This PR was automatically created by the [Update Luau workflow](https://github.com/luau-lang/lute/actions/workflows/update-prs.yml)* Co-authored-by: aatxe <744293+aatxe@users.noreply.github.com>
**Luau**: Updated from `0.729` to `0.730` **Release Notes:** https://github.com/luau-lang/luau/releases/tag/0.730 --- *This PR was automatically created by the [Update Luau workflow](https://github.com/luau-lang/lute/actions/workflows/update-prs.yml)* Co-authored-by: aatxe <744293+aatxe@users.noreply.github.com>
This adds a minimal DAP adapter, which is not currently callable by the `lute` CLI * we handle I/O and JSON parsing correctly (and add some tests for this) * add some minimal implementations for the debugger startup/terminate events If we modify Mandolin, we can connect it to VSCode <img width="1236" height="817" alt="Screenshot 2026-07-10 at 2 11 11 PM" src="https://github.com/user-attachments/assets/d9d280f3-bc67-4a6d-a21a-b2ad9bb341ef" />
While reviewing feedback for my attribute parsing PR, I realized we're missing query tests and query visitor suppressions for some node types. This PR adds a unit test for querying each CST node type and any needed fixes.
Remove print statements since they're polluting test output. We'll need to introduce some sort of logging library with different modes that we can disable for tests.
I noticed lute was still using `.luaurc` and had a stray `lint.config.luau` so I merged the two
## Summary
Adds support for user-specified type definition files in `lute check`.
Definition files (`.d.luau`) declare globals and types that are injected
into the type checker's global scope, allowing user code to reference
them without explicit imports.
## Configuration
Definition files are specified in `.config.luau` under lute.definitions
as a map:
```luau
return {
lute = {
definitions = {
roblox = "./types/roblox.d.luau",
custom = "./types/custom-globals.d.luau",
},
},
}
```
Run `clang-format` (v22.1.8) on `runtime` as a part of splitting #1233 into three.
`@std/syntax/visitor` was missing methods for `visitStat`, `visitType`, and `visitTypePack`.
Previously, we used `resumeTokens` to do pausing in the debugger. This is unsustainable for multi-coroutine applications. Instead, we introduce a`debugMode` to `Runtime` that enables pausing all coroutines at once. We also add a `pauseProcess` method in the debugger itself that can be called outside of breakpoints. The pausing pathway is now: 1. Trigger the presently queued running coroutine to break out of execution. The easiest way to do this is to set a callback in the VM and then call `lua_break` 2. Use the runtime's `stopDebug()` to actually stop queuing of further coroutines.
Added some additional testing to breakpoints + resolved one potential timing issue in `setBreakpoint`
Create initial bindings for `lute/debug` to Luau, which primarily focuses on breakpoint behavior. - Add some basic Luau tests - A definitions file for the library for type checking - Renames `debugger.cpp` to `debuginternals.cpp` to more clearly separate out the bindings from internal implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.