LuaLS / LuaLS/lua-language-server
Feature Request: Typestate / Self-Type Refinement for Method Calls
还没有人认领这个 Issue。
- 主要语言
- Lua
- 星标
- 4.4k
- 派生
- 442
- PR 合并指标
- 30 天内没有已合并 PR
描述
Problem
Lua is a highly dynamic language, and many real-world Lua frameworks mutate object capabilities at runtime.
This pattern is especially common in:
- game engines
- UI frameworks
- ECS architectures
- builder APIs
- runtime mixin systems
- userdata bindings from native engines
Currently, LuaLS/LuaCats cannot properly express:
"after calling this method,
selfnow has additional capabilities/methods"
This becomes a major DX limitation for frameworks that dynamically extend objects.
Real-world Example
Consider a UI framework where all elements start as a generic UIElement.
---@class UIElement
local UIElement = {}
Calling:
element:setupUIImage()
injects image-related functionality into the element at runtime:
element:setImage(...)
However, LuaLS still sees element as only UIElement.
The only current workaround is manual casting:
element:setupUIImage()
---@cast element UIImage
element:setImage(material)
This works technically, but becomes repetitive and hurts DX significantly in large codebases.
Comparison to TypeScript
TypeScript supports type refinement after method calls through assertion signatures such as:
asserts this is SomeType
This allows APIs to safely refine object types after capability-changing methods.
A good real-world example is discord.js, where Interaction objects can be refined into subtypes through methods like:
interaction.isButton()
interaction.isChatInputCommand()
After refinement, TypeScript understands the new subtype automatically.
Lua frameworks often use similar runtime patterns, but LuaLS currently cannot model them.
Proposed Solution
Introduce a LuaCats annotation for self-type refinement / capability injection.
Possible syntax examples:
---@injects UIImage
function UIElement:setupUIImage() end
or:
---@mutates self UIImage
function UIElement:setupUIImage() end
or:
---@becomes UIImage
function UIElement:setupUIImage() end
Expected Behavior
After:
element:setupUIImage()
LuaLS would understand:
element :: UIElement & UIImage
allowing:
element:setImage(...)
without requiring manual casts.
Why This Matters
This would greatly improve support for:
- dynamic Lua architectures
- runtime capability injection
- engine bindings
- UI frameworks
- builder APIs
- fluent APIs
- mixin systems
while keeping Lua's dynamic nature intact.
This feature would also reduce:
- repetitive
---@cast - noisy annotations
- inaccurate supersets in base classes
- degraded autocomplete quality
Additional Notes
This feature does not need to become full typestate analysis or advanced dependent typing.
Even a pragmatic flow-sensitive refinement system limited to:
- direct method calls
- current scope
- explicit annotations only
would already provide massive DX improvements.
Example Use Case
---@class UIImage
---@field setImage fun(self: UIImage, material: string)
---@class UIElement
---@injects UIImage
function UIElement:setupUIImage() end
local element = UIElement.new()
element:setupUIImage()
element:setImage("icon")
Expected:
- autocomplete works
- diagnostics recognize
setImage - no manual cast required
Thanks for all the amazing work on LuaLS and LuaCats.
This would significantly improve tooling support for dynamic Lua patterns commonly used in real-world frameworks and game engines.
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
调研方向
该 issue 没有指明实现文件或测试。首先查看 LuaLS 当前如何处理显式的 ---@cast 和方法调用,然后评估所提议的细化范围:直接调用、当前作用域和显式注解。完成的标准是确定注解设计,并且无需手动 cast,基于流的 capability 细化、自动补全和诊断都能正常工作。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- lua
- 领域
- devtools
- Issue 类型
- 功能
- 难度
- 5/5
- 预计耗时
- 一周以上
- 活跃度
- 冷清
- 描述清晰度
- 基本清楚
- 新手友好度
- 45/100