Skip to content

Commit 877c38d

Browse files
committed
update
1 parent f677fc6 commit 877c38d

16 files changed

Lines changed: 181 additions & 30 deletions

File tree

CHANGELOG.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,58 @@
22

33
*All notable changes to the EmmyLua Analyzer Rust project will be documented in this file.*
44

5+
## [0.20.0] - 2026-1-30
6+
### ✨ Added
7+
- **Support .emmyrc.lua configuration file**: The language server and emmylua_check now support loading configuration from `.emmyrc.lua` in addition to `.emmyrc.json` and `.luarc.json`. Lua configuration is parsed using the [luars](https://github.com/CppCXY/lua-rs) library. A basic config looks like:
8+
```lua
9+
local diagnostics = {
10+
disable = { "undefined-global" },
11+
}
12+
13+
return {
14+
diagnostics = diagnostics,
15+
}
16+
```
17+
You can use standard libraries such as os, table, utf8, string to write more complex configuration logic. `print` can be used for debugging; its output is redirected to the language server log.
18+
19+
Note: The current `.emmyrc.lua` does not have dedicated code completions; this will be added in a future release.
20+
Note2: The `luars` project was developed by me with AI assistance. It is an almost-complete Lua 5.5 implementation but is still experimental and contains many bugs. Use with caution.
21+
22+
### 🔧 Changed
23+
- **Enhance workspace.library**: `workspace.library` now supports per-entry ignore configuration, for example:
24+
```json
25+
{
26+
"workspace": {
27+
"library": [
28+
{
29+
"path": "/path/to/lib1",
30+
"ignoreGlobs": [ "**/test/**" ],
31+
"ignoreDir": ["docs"]
32+
}
33+
]
34+
}
35+
}
36+
```
37+
Additionally, `workspace.library` can now point directly to a single file instead of a directory:
38+
```json
39+
{
40+
"workspace": {
41+
"library": [
42+
"/path/to/single/file.lua"
43+
]
44+
}
45+
}
46+
```
47+
48+
- **Improve type narrowing for 'and'/'or'**: Improved type narrowing for the `and` and `or` operators when used with nullable types and table/literal expressions.
49+
50+
### 🐛 Fixed
51+
- Fixed preferred_local_alias diagnostic
52+
- Fixed some type checking issues
53+
- Fixed recursive behavior in reference computation
54+
- Optimized generic-related computations
55+
56+
557
## [0.19.0] - 2025-12-25
658

759
### ✨ Added

Cargo.lock

Lines changed: 20 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ members = [
77

88
[workspace.dependencies]
99
# local
10-
emmylua_code_analysis = { path = "crates/emmylua_code_analysis", version = "0.19.0" }
11-
emmylua_parser = { path = "crates/emmylua_parser", version = "0.21.0" }
12-
emmylua_parser_desc = { path = "crates/emmylua_parser_desc", version = "0.21.0" }
10+
emmylua_code_analysis = { path = "crates/emmylua_code_analysis", version = "0.20.0" }
11+
emmylua_parser = { path = "crates/emmylua_parser", version = "0.22.0" }
12+
emmylua_parser_desc = { path = "crates/emmylua_parser_desc", version = "0.22.0" }
1313
emmylua_diagnostic_macro = { path = "crates/emmylua_diagnostic_macro", version = "0.5.0" }
1414

1515
# external
@@ -53,6 +53,7 @@ num-traits = { version = "0.2", features = ["std"] }
5353
mimalloc = "0.1.48"
5454
googletest = "0.14.2"
5555
unicode-general-category = "1.0.0"
56+
luars = { version = "0.1.0", features = ["serde"] }
5657

5758
# Lint configuration for the entire workspace
5859
[workspace.lints.clippy]

crates/emmylua_check/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "emmylua_check"
3-
version = "0.19.0"
3+
version = "0.20.0"
44
edition = "2024"
55
authors = ["CppCXY"]
66
description = "A command-line tool for checking lua code."

crates/emmylua_check/src/cmd_args.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::path::PathBuf;
99
#[cfg_attr(feature = "cli", command(version))]
1010
pub struct CmdArgs {
1111
/// Configuration file paths.
12-
/// If not provided, both ".emmyrc.json" and ".luarc.json" will be searched in the workspace
12+
/// If not provided, both ".emmyrc.json" ".emmyrc.lua" and ".luarc.json" will be searched in the workspace
1313
/// directory
1414
#[cfg_attr(feature = "cli", arg(short, long, value_delimiter = ','))]
1515
pub config: Option<Vec<PathBuf>>,

crates/emmylua_code_analysis/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "emmylua_code_analysis"
3-
version = "0.19.0"
3+
version = "0.20.0"
44
edition = "2024"
55
authors = ["CppCXY"]
66
description = "A library for analyzing lua code."
@@ -49,6 +49,7 @@ serde_with.workspace = true
4949
include_dir.workspace = true
5050
emmylua_codestyle.workspace = true
5151
itertools.workspace = true
52+
luars.workspace = true
5253

5354
[package.metadata.i18n]
5455
available-locales = ["en", "zh_CN", "zh_HK"]

crates/emmylua_code_analysis/src/config/config_loader.rs

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::{collections::HashSet, path::PathBuf};
22

33
use serde_json::Value;
44

5-
use crate::read_file_with_encoding;
5+
use crate::{config::lua_loader::load_lua_config, read_file_with_encoding};
66

77
use super::{Emmyrc, flatten_config::FlattenConfigObject};
88

@@ -11,8 +11,8 @@ pub fn load_configs_raw(config_files: Vec<PathBuf>, partial_emmyrcs: Option<Vec<
1111

1212
for config_file in config_files {
1313
log::info!("Loading config file: {:?}", config_file);
14-
let config_json_str = match read_file_with_encoding(&config_file, "utf-8") {
15-
Some(json_str) => json_str,
14+
let config_content = match read_file_with_encoding(&config_file, "utf-8") {
15+
Some(content) => content,
1616
None => {
1717
log::error!(
1818
"Failed to read config file: {:?}, error: File not found or unreadable",
@@ -22,19 +22,33 @@ pub fn load_configs_raw(config_files: Vec<PathBuf>, partial_emmyrcs: Option<Vec<
2222
}
2323
};
2424

25-
let config_json: Value = match serde_json::from_str(&config_json_str) {
26-
Ok(json) => json,
27-
Err(e) => {
28-
log::error!(
29-
"Failed to parse config file: {:?}, error: {:?}",
30-
&config_file,
31-
e
32-
);
33-
continue;
25+
let config_value = if config_file.extension().and_then(|s| s.to_str()) == Some("lua") {
26+
match load_lua_config(&config_content) {
27+
Ok(value) => value,
28+
Err(e) => {
29+
log::error!(
30+
"Failed to parse lua config file: {:?}, error: {:?}",
31+
&config_file,
32+
e
33+
);
34+
continue;
35+
}
36+
}
37+
} else {
38+
match serde_json::from_str(&config_content) {
39+
Ok(json) => json,
40+
Err(e) => {
41+
log::error!(
42+
"Failed to parse config file: {:?}, error: {:?}",
43+
&config_file,
44+
e
45+
);
46+
continue;
47+
}
3448
}
3549
};
3650

37-
config_jsons.push(config_json);
51+
config_jsons.push(config_value);
3852
}
3953

4054
if let Some(partial_emmyrcs) = partial_emmyrcs {
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
use luars::{
2+
LuaResult, LuaVM, LuaValue,
3+
lua_vm::{LuaState, SafeOption},
4+
};
5+
use serde_json::Value;
6+
7+
pub fn load_lua_config(content: &str) -> Result<Value, String> {
8+
let mut lua = LuaVM::new(SafeOption {
9+
max_call_depth: 64,
10+
max_stack_size: 256,
11+
max_memory_limit: 100 * 1024 * 1024, // 100 MB
12+
});
13+
14+
let _ = lua.open_stdlib(luars::Stdlib::Package);
15+
let _ = lua.open_stdlib(luars::Stdlib::Basic);
16+
let _ = lua.open_stdlib(luars::Stdlib::Table);
17+
let _ = lua.open_stdlib(luars::Stdlib::String);
18+
let _ = lua.open_stdlib(luars::Stdlib::Math);
19+
let _ = lua.open_stdlib(luars::Stdlib::Os);
20+
let _ = lua.open_stdlib(luars::Stdlib::Utf8);
21+
let _ = lua.set_global("print", LuaValue::cfunction(ls_println));
22+
23+
let values = match lua.execute_string(content) {
24+
Ok(v) => v,
25+
Err(e) => {
26+
let err_msg = lua.main_state().get_error_msg(e);
27+
return Err(format!("Failed to execute lua config: {:?}", err_msg));
28+
}
29+
};
30+
31+
if values.is_empty() {
32+
return Err("Lua config did not return any value".to_string());
33+
}
34+
35+
let value = values[0];
36+
lua.serialize_to_json(&value)
37+
}
38+
39+
fn ls_println(l: &mut LuaState) -> LuaResult<usize> {
40+
let args = l.get_args();
41+
let mut output = String::new();
42+
for (index, arg) in args.iter().enumerate() {
43+
let s = l.to_string(arg)?;
44+
output.push_str(&s);
45+
if index < args.len() - 1 {
46+
output.push('\t');
47+
}
48+
}
49+
log::info!("{}", output);
50+
Ok(0)
51+
}

crates/emmylua_code_analysis/src/config/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
mod config_loader;
22
mod configs;
33
mod flatten_config;
4+
mod lua_loader;
45
mod pre_process;
56

67
use std::{collections::HashMap, path::Path};

crates/emmylua_doc_cli/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "emmylua_doc_cli"
3-
version = "0.19.0"
3+
version = "0.20.0"
44
edition = "2024"
55
authors = ["CppCXY"]
66
description = "A command-line tool for generating lua documentation."

0 commit comments

Comments
 (0)