LuaLS / LuaLS/lua-language-server

[Library] A native Luals parser

未关闭
#2,910 9 条评论 10 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

rust
主要语言
Lua
星标
4.4k
派生
442
PR 合并指标
30 天内没有已合并 PR

描述

I have completed most of the work, but there may still be many bugs in the details that I will gradually fix in future use. I will implement a new language server based on this. If you are interested, you can continue to follow my progress.

the library: https://crates.io/crates/emmylua_parser

a simple example:

let code = r#"
    local a = 1
    local b = 2
    local function foo(x)
        return x + 1
    end
    function f()
    end
    local c = foo(a + b)
    if c > 2 then
        print(c)
    elseif c == 2 then
    else
        print("c is not greater than 2")
    end
    for i = 1, 10 do
        print(i)
    end
    for i, v in ipairs({1, 2, 3}) do
        print(i, v)
    end
    while c < 10 do
        c = c + 1
    end
    repeat
        c = c - 1
    until c == 0
    ::ll::
    goto ll
    local a = c["string"]
"#;
let tree = LuaParser::parse(code, ParserConfig::default());
let chunk = tree.get_chunk_node();
for node in chunk.descendants::<LuaAst>() {
    match node {
        LuaAst::LuaChunk(lua_chunk) => {
            assert!(lua_chunk.get_block().is_some());
        }
        LuaAst::LuaBlock(lua_block) => {
            assert!(lua_block.get_stats().next().is_some());
        }
        LuaAst::LuaAssignStat(lua_assign_stat) => {
            let (var_list, expr_list) = lua_assign_stat.get_var_and_expr_list();
            assert!(var_list.len() > 0);
            assert!(expr_list.len() > 0);
        }
        LuaAst::LuaLocalStat(lua_local_stat) => {
            let mut name_list = lua_local_stat.get_local_name_list();
            let local_name = name_list.next().unwrap();
            assert!(local_name.get_name_token().is_some());
            let mut expr_list = lua_local_stat.get_value_exprs();
            assert!(expr_list.next().is_some());
        }
        LuaAst::LuaCallExprStat(lua_call_expr_stat) => {
            assert!(lua_call_expr_stat.get_call_expr().is_some());
        }
        LuaAst::LuaLabelStat(lua_label_stat) => {
            assert!(lua_label_stat.get_label_name_token().is_some());
            assert_eq!(
                lua_label_stat
                    .get_label_name_token()
                    .unwrap()
                    .get_name_text(),
                "ll"
            );
        }
        LuaAst::LuaGotoStat(lua_goto_stat) => {
            assert!(lua_goto_stat.get_label_name_token().is_some());
            assert_eq!(
                lua_goto_stat
                    .get_label_name_token()
                    .unwrap()
                    .get_name_text(),
                "ll"
            );
        }
        LuaAst::LuaDoStat(lua_do_stat) => {
            assert!(lua_do_stat.get_block().is_some());
        }
        LuaAst::LuaWhileStat(lua_while_stat) => {
            assert!(lua_while_stat.get_condition_expr().is_some());
            assert!(lua_while_stat.get_block().is_some());
        }
        LuaAst::LuaRepeatStat(lua_repeat_stat) => {
            assert!(lua_repeat_stat.get_block().is_some());
            assert!(lua_repeat_stat.get_condition_expr().is_some());
        }
        LuaAst::LuaIfStat(lua_if_stat) => {
            assert!(lua_if_stat.get_condition_expr().is_some());
            assert!(lua_if_stat.get_block().is_some());
            assert!(lua_if_stat.get_else_if_clause_list().next().is_some());
            assert!(lua_if_stat.get_else_clause().is_some());
        }
        LuaAst::LuaForStat(lua_for_stat) => {
            assert!(lua_for_stat.get_var_name().is_some());
            assert!(lua_for_stat.get_block().is_some());
            assert_eq!(lua_for_stat.get_iter_expr().count(), 2);
        }
        LuaAst::LuaForRangeStat(lua_for_range_stat) => {
            assert_eq!(lua_for_range_stat.get_var_name_list().count(), 2);
            assert!(lua_for_range_stat.get_block().is_some());
            assert!(lua_for_range_stat.get_expr_list().next().is_some());
        }
        LuaAst::LuaFuncStat(lua_func_stat) => {
            assert!(lua_func_stat.get_func_name().is_some());
            assert!(lua_func_stat.get_closure().is_some());
        }
        LuaAst::LuaLocalFuncStat(lua_local_func_stat) => {
            assert!(lua_local_func_stat.get_local_name().is_some());
            assert!(lua_local_func_stat.get_closure().is_some());
        }
        LuaAst::LuaReturnStat(lua_return_stat) => {
            assert!(lua_return_stat.get_expr_list().next().is_some());
        }
        LuaAst::LuaNameExpr(lua_name_expr) => {
            assert!(lua_name_expr.get_name_token().is_some());
        }
        LuaAst::LuaIndexExpr(lua_index_expr) => {
            assert!(lua_index_expr.get_prefix_expr().is_some());
            assert!(lua_index_expr.get_indexed_expr().is_some());
        }
        LuaAst::LuaTableExpr(lua_table_expr) => {
            assert!(lua_table_expr.is_array());
        }
        _ => {}
    }
}

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

从链接的 emmylua_parser crate 和使用 LuaParser::parse 与 get_chunk_node() 的示例开始,然后将其 AST 覆盖范围与 language server repository 进行比较。该 issue 未指明 repository 文件、测试、集成点或验收标准,因此 definition of done 仍不明确。

由索引模型根据 Issue 内容生成。

评估

技术栈
lua, rust
领域
compilers, devtools
Issue 类型
功能
难度
5/5
预计耗时
一周以上
活跃度
停滞
描述清晰度
需要澄清
新手友好度
18/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。