-
Notifications
You must be signed in to change notification settings - Fork 109
Plugins #1088
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
JohnnyMorganz
wants to merge
9
commits into
main
Choose a base branch
from
plugins
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Plugins #1088
Conversation
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
Introduces a plugin system that allows Luau scripts to transform source code before type checking, with automatic position mapping for LSP features. Key components: - PluginRuntime: Sandboxed Luau VM execution with timeout support - SourceMapping: Bidirectional position mapping from text edits - PluginTextDocument: TextDocument subclass with transparent position mapping - PluginManager: Orchestrates multiple plugins with overlap detection Features: - Plugins return text edits (not transformed source) for simpler API - Multiple plugins receive original source; edits are combined - Overlapping edits from different plugins are rejected with error - transformSource is optional - plugins can load without implementing it - Wall-clock timeout using Luau::TimeTrace::getClock() - VS Code extension settings for plugin configuration 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
6a7f253 to
50e54a8
Compare
Deploying luau-lsp with
|
| Latest commit: |
61d9c8c
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://c86c3057.luau-lsp.pages.dev |
| Branch Preview URL: | https://plugins.luau-lsp.pages.dev |
Introduces a sandboxed filesystem API that allows plugins to read files within the workspace: - lsp.workspace.getRootUri() - get workspace root as Uri - lsp.fs.readFile(uri) - read file contents (workspace-only) - lsp.Uri.parse(str) / lsp.Uri.file(path) - create Uri objects - Uri userdata with properties (scheme, path, fsPath) and methods (joinPath, toString) Security: Only files within the workspace can be accessed. Controlled by luau-lsp.plugins.fileSystem.enabled setting (default: false). Also fixes lua_resume -> lua_pcall for transformSource calls to prevent crashes when plugins error. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
Exposes lsp.client.sendLogMessage(type, message) to plugins for sending
log messages to the LSP client. Message types are strings: "error",
"warning", "info", "log".
Also overrides the global print() function to redirect output to
sendLogMessage with "info" level, allowing familiar debugging patterns.
All messages are automatically prefixed with [Plugin {path}] for easy
identification in logs.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Adds lsp.json.deserialize(string) function that parses JSON strings and returns the corresponding Lua values. Supports all JSON types: null, boolean, number, string, arrays (1-indexed), and objects. Parse errors throw Lua errors with descriptive messages. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
Register an LSPPlugin environment that provides type information for the plugin Lua API (lsp.fs, lsp.client, lsp.workspace, lsp.json, Uri). This enables autocomplete and type checking when developing plugins. Key changes: - Add PluginDefinitions with embedded type definitions using 'declare extern type' syntax for Uri userdata - Register LSPPlugin environment via registerBuiltinDefinition and applyBuiltinDefinitionToEnvironment pattern - Implement getEnvironmentForModule to return LSPPlugin for plugin files - Store plugin Uri (resolved) instead of string path for correct path comparison regardless of relative/absolute paths in settings - Store definitionsSourceModule for documentation lookup 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
Owner
Author
|
Sample plugin implementation of #976 in its current state: type SourcemapNode = {
name: string,
className: string,
filePaths: { string }?,
children: SourcemapNode
}
local function startsWith(str: string, prefix: string)
return str:sub(1, #prefix) == prefix
end
local function endsWith(str: string, suffix: string)
return str:sub(-#suffix) == suffix
end
local REQUIRE_PATTERN = [[require%("(%w+)"%)]]
local root = lsp.workspace.getRootUri()
local sourcemapContents = lsp.fs.readFile(root:joinPath("sourcemap.json"))
local sourcemap = lsp.json.deserialize(sourcemapContents) :: SourcemapNode
local function getScriptFilePath(node: SourcemapNode): string?
if not node.filePaths then
return nil
end
for _, path in node.filePaths do
if endsWith(path, ".luau") or endsWith(path, ".lua") then
return path
end
end
return nil
end
-- Populate module names to file paths map
local moduleNamesToFilePaths = {}
local queue = {sourcemap}
while #queue > 0 do
local node = table.remove(queue, 1)
assert(node ~= nil)
local filepath = getScriptFilePath(node)
if filepath then
moduleNamesToFilePaths[node.name] = root:joinPath(filepath)
end
if node.children then
for _, child in node.children do
table.insert(queue, child)
end
end
end
return {
transformSource = function(source: string, context: PluginContext): { TextEdit }?
local edits = {}
local lines = string.split(source, '\n')
for i, lineContents in lines do
local lineNumber = i - 1
-- Comment out the require override to prevent it from impacting intellisense
if startsWith(lineContents, "local require = ") then
table.insert(edits, {
range = {
start = { line = lineNumber, column = 0 },
["end"] = { line = lineNumber, column = 0},
},
newText = "-- "
})
else
local startIndex, endIndex = string.find(lineContents, REQUIRE_PATTERN)
if startIndex then
local REQUIRE_START_LEN = string.len('require("')
local REQUIRE_END_LEN = string.len('")')
local nameStartIndex = startIndex + REQUIRE_START_LEN
local nameEndIndex = endIndex - REQUIRE_END_LEN
local requireName = lineContents:sub(nameStartIndex, nameEndIndex)
if moduleNamesToFilePaths[requireName] then
table.insert(edits, {
range = {
-- column is 0 indexed
start = { line = lineNumber, column = nameStartIndex - 1 },
["end"] = { line = lineNumber, column = nameEndIndex },
},
newText = moduleNamesToFilePaths[requireName].fsPath
})
end
end
end
end
return edits
end,
} |
Use lua_Integer instead of int64_t when pushing integers to avoid C4244 warning about narrowing conversion on Windows. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
Adds a new LSP request `luau-lsp/debug/viewInternalSource` that returns the internal source representation of a document after plugin transformations have been applied. This helps plugin developers debug how their plugins modify source code before type checking. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.