Skip to content

Commit 72c5c6f

Browse files
committed
Merge remote-tracking branch 'EmmyLuaLs/main' into update
2 parents 8e3901f + 21e835d commit 72c5c6f

62 files changed

Lines changed: 1650 additions & 378 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CONTRIBUTING.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ Our project is organized into several crates:
1515
| [🧹 **emmylua_formatter**](./crates/emmylua_formatter) | [![emmylua_formatter](https://img.shields.io/crates/v/emmylua_formatter.svg?style=flat-square)](https://crates.io/crates/emmylua_formatter) | The Lua formatter used by the EmmyLua Analyzer Rust workspace. |
1616

1717

18+
Note: We don't accept PRs that change formatting output, but you can report formatting bugs via issues — I'll verify and fix them myself. This is because most people aren't fully aware of the complexities involved in formatting
19+
1820
## Testing
1921

2022
We use the standard Rust testing harness, along with assert macros from [`googletest-rust`]:

Cargo.lock

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

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ mimalloc = { version = "0.1.50" }
5555
googletest = "0.14.2"
5656
ntest = "0.9.5"
5757
unicode-general-category = "1.0.0"
58-
luars = { version = "0.26.0", features = ["serde", "sandbox"] }
58+
luars = { version = "0.26.1", features = ["serde", "sandbox"] }
5959
# request's default-tls feature pulls in a dependency on aws-lc-rs,
6060
# which causes a linking error on Windows
6161
reqwest = { version = "0.13.1", default-features = false, features = [

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,6 @@ emmylua_doc_cli ./src --output ./docs
198198
- [**Configuration**](./docs/config/emmyrc_json_EN.md) - Advanced configuration options
199199
- [**Formatter Guide**](./docs/emmylua_formatter/README_EN.md) - Formatter behavior, options, and usage guide
200200
- [**Annotations Reference**](./docs/emmylua_doc/annotations_EN/README.md) - Detailed annotation documentation
201-
- [**Old Formatter**](https://github.com/CppCXY/EmmyLuaCodeStyle/blob/master/README_EN.md) - Formatting and style guidelines
202201
- [**External Formatter Integration**](./docs/external_format/external_formatter_options_EN.md) - Using external formatters
203202

204203
---

crates/emmylua_code_analysis/resources/schema.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,13 @@
828828
},
829829
"EmmyrcLuaVersion": {
830830
"oneOf": [
831+
{
832+
"type": "string",
833+
"enum": [
834+
"LuaJIT-Ext",
835+
"LuaJIT3"
836+
]
837+
},
831838
{
832839
"description": "Lua 5.1",
833840
"type": "string",

crates/emmylua_code_analysis/src/compilation/analyzer/decl/stats.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ use super::{DeclAnalyzer, members::find_index_owner};
1616
pub fn analyze_local_stat(analyzer: &mut DeclAnalyzer, stat: LuaLocalStat) -> Option<()> {
1717
let local_name_list = stat.get_local_name_list().collect::<Vec<_>>();
1818
let value_expr_list = stat.get_value_exprs().collect::<Vec<_>>();
19+
let is_const = if stat.is_const() {
20+
Some(LocalAttribute::Const)
21+
} else {
22+
None
23+
};
1924

2025
for (index, local_name) in local_name_list.iter().enumerate() {
2126
let name = if let Some(name_token) = local_name.get_name_token() {
@@ -29,10 +34,10 @@ pub fn analyze_local_stat(analyzer: &mut DeclAnalyzer, stat: LuaLocalStat) -> Op
2934
} else if attrib.is_close() {
3035
Some(LocalAttribute::Close)
3136
} else {
32-
None
37+
is_const.clone()
3338
}
3439
} else {
35-
None
40+
is_const.clone()
3641
};
3742

3843
let file_id = analyzer.get_file_id();
@@ -312,6 +317,11 @@ pub fn analyze_func_stat(analyzer: &mut DeclAnalyzer, stat: LuaFuncStat) -> Opti
312317
pub fn analyze_local_func_stat(analyzer: &mut DeclAnalyzer, stat: LuaLocalFuncStat) -> Option<()> {
313318
let local_name = stat.get_local_name()?;
314319
let name_token = local_name.get_name_token()?;
320+
let is_const = if stat.is_const() {
321+
Some(LocalAttribute::Const)
322+
} else {
323+
None
324+
};
315325
let name = name_token.get_name_text();
316326
let range = local_name.get_range();
317327
let file_id = analyzer.get_file_id();
@@ -321,7 +331,7 @@ pub fn analyze_local_func_stat(analyzer: &mut DeclAnalyzer, stat: LuaLocalFuncSt
321331
range,
322332
LuaDeclExtra::Local {
323333
kind: local_name.syntax().kind(),
324-
attrib: None,
334+
attrib: is_const,
325335
},
326336
None,
327337
);

crates/emmylua_code_analysis/src/compilation/analyzer/flow/bind_analyze/exprs/bind_binary_expr.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub fn bind_binary_expr(
1818
match op_token.get_op() {
1919
BinaryOperator::OpAnd => bind_and_expr(binder, binary_expr, current),
2020
BinaryOperator::OpOr => bind_or_expr(binder, binary_expr, current),
21+
BinaryOperator::OpNilCoalescing => bind_or_expr(binder, binary_expr, current),
2122
_ => {
2223
bind_each_child(binder, LuaAst::LuaBinaryExpr(binary_expr.clone()), current);
2324
Some(())
@@ -74,7 +75,7 @@ pub fn is_binary_logical(expr: &LuaExpr) -> bool {
7475

7576
return matches!(
7677
op_token.get_op(),
77-
BinaryOperator::OpAnd | BinaryOperator::OpOr
78+
BinaryOperator::OpAnd | BinaryOperator::OpOr | BinaryOperator::OpNilCoalescing
7879
);
7980
}
8081
LuaExpr::ParenExpr(paren_expr) => {

crates/emmylua_code_analysis/src/compilation/analyzer/flow/bind_analyze/exprs/mod.rs

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ mod bind_binary_expr;
22

33
use emmylua_parser::{
44
LuaAst, LuaAstNode, LuaCallExpr, LuaClosureExpr, LuaExpr, LuaIndexExpr, LuaNameExpr,
5-
LuaTableExpr, LuaUnaryExpr, UnaryOperator,
5+
LuaTableExpr, LuaTernaryExpr, LuaUnaryExpr, UnaryOperator,
66
};
77

88
use crate::{
99
FlowId, FlowNodeKind,
1010
compilation::analyzer::flow::{
11-
bind_analyze::{bind_each_child, exprs::bind_binary_expr::is_binary_logical},
11+
bind_analyze::{
12+
bind_each_child, exprs::bind_binary_expr::is_binary_logical, finish_flow_label,
13+
},
1214
binder::FlowBinder,
1315
},
1416
};
@@ -54,6 +56,7 @@ pub fn bind_expr(binder: &mut FlowBinder, expr: LuaExpr, current: FlowId) -> Flo
5456
LuaExpr::IndexExpr(index_expr) => bind_index_expr(binder, index_expr, current),
5557
LuaExpr::BinaryExpr(binary_expr) => bind_binary_expr(binder, binary_expr, current),
5658
LuaExpr::UnaryExpr(unary_expr) => bind_unary_expr(binder, unary_expr, current),
59+
LuaExpr::TernaryExpr(ternary_expr) => bind_ternary_expr(binder, ternary_expr, current),
5760
};
5861

5962
current
@@ -92,10 +95,34 @@ pub fn bind_index_expr(
9295
current: FlowId,
9396
) -> Option<()> {
9497
binder.bind_syntax_node(index_expr.get_syntax_id(), current);
98+
if index_expr.is_safe_index() {
99+
return bind_safe_index_expr(binder, index_expr, current);
100+
}
95101
bind_each_child(binder, LuaAst::LuaIndexExpr(index_expr.clone()), current);
96102
Some(())
97103
}
98104

105+
fn bind_safe_index_expr(
106+
binder: &mut FlowBinder,
107+
index_expr: LuaIndexExpr,
108+
current: FlowId,
109+
) -> Option<()> {
110+
let prefix_expr = index_expr.get_prefix_expr()?;
111+
112+
let pre_access = binder.create_branch_label();
113+
bind_condition_expr(
114+
binder,
115+
prefix_expr,
116+
current,
117+
pre_access,
118+
binder.false_target,
119+
);
120+
let current = finish_flow_label(binder, pre_access, current);
121+
122+
bind_each_child(binder, LuaAst::LuaIndexExpr(index_expr), current);
123+
Some(())
124+
}
125+
99126
pub fn bind_paren_expr(
100127
binder: &mut FlowBinder,
101128
paren_expr: emmylua_parser::LuaParenExpr,
@@ -143,3 +170,32 @@ pub fn bind_call_expr(
143170
bind_each_child(binder, LuaAst::LuaCallExpr(call_expr.clone()), current);
144171
Some(())
145172
}
173+
174+
fn bind_ternary_expr(
175+
binder: &mut FlowBinder,
176+
ternary_expr: LuaTernaryExpr,
177+
current: FlowId,
178+
) -> Option<()> {
179+
let condition = ternary_expr.get_condition_expr()?;
180+
let (true_expr, false_expr) = ternary_expr.get_true_false_exprs()?;
181+
182+
let pre_false = binder.create_branch_label();
183+
bind_condition_expr(binder, condition, current, binder.true_target, pre_false);
184+
let current = finish_flow_label(binder, pre_false, current);
185+
bind_condition_expr(
186+
binder,
187+
true_expr,
188+
current,
189+
binder.true_target,
190+
binder.false_target,
191+
);
192+
bind_condition_expr(
193+
binder,
194+
false_expr,
195+
current,
196+
binder.true_target,
197+
binder.false_target,
198+
);
199+
200+
Some(())
201+
}

crates/emmylua_code_analysis/src/compilation/analyzer/flow/bind_analyze/mod.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ use crate::{
1212
comment::bind_comment,
1313
exprs::bind_expr,
1414
stats::{
15-
bind_assign_stat, bind_break_stat, bind_call_expr_stat, bind_do_stat,
16-
bind_for_range_stat, bind_for_stat, bind_func_stat, bind_goto_stat, bind_if_stat,
17-
bind_label_stat, bind_local_func_stat, bind_local_stat, bind_repeat_stat,
18-
bind_return_stat, bind_while_stat,
15+
bind_assign_stat, bind_break_stat, bind_call_expr_stat, bind_continue_stat,
16+
bind_do_stat, bind_for_range_stat, bind_for_stat, bind_func_stat, bind_goto_stat,
17+
bind_if_stat, bind_label_stat, bind_local_func_stat, bind_local_stat,
18+
bind_repeat_stat, bind_return_stat, bind_while_stat,
1919
},
2020
},
2121
binder::FlowBinder,
@@ -41,7 +41,7 @@ fn bind_block(binder: &mut FlowBinder, block: LuaBlock, current: FlowId) -> Flow
4141

4242
if let Some(flow_node) = binder.get_flow(return_flow_id) {
4343
match &flow_node.kind {
44-
FlowNodeKind::Return | FlowNodeKind::Break => {
44+
FlowNodeKind::Return | FlowNodeKind::Break | FlowNodeKind::Continue => {
4545
return_flow_id = binder.unreachable;
4646
can_change_flow = false;
4747
}
@@ -72,6 +72,9 @@ fn bind_node(binder: &mut FlowBinder, node: LuaAst, current: FlowId) -> FlowId {
7272
}
7373
LuaAst::LuaLabelStat(label_stat) => bind_label_stat(binder, label_stat, current),
7474
LuaAst::LuaBreakStat(break_stat) => bind_break_stat(binder, break_stat, current),
75+
LuaAst::LuaContinueStat(continue_stat) => {
76+
bind_continue_stat(binder, continue_stat, current)
77+
}
7578
LuaAst::LuaGotoStat(goto_stat) => bind_goto_stat(binder, goto_stat, current),
7679
LuaAst::LuaReturnStat(return_stat) => bind_return_stat(binder, return_stat, current),
7780
LuaAst::LuaDoStat(do_stat) => bind_do_stat(binder, do_stat, current),

crates/emmylua_code_analysis/src/compilation/analyzer/flow/bind_analyze/stats.rs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use emmylua_parser::{
22
BinaryOperator, LuaAssignStat, LuaAst, LuaAstNode, LuaAstToken, LuaBlock, LuaBreakStat,
3-
LuaCallArgList, LuaCallExprStat, LuaDoStat, LuaExpr, LuaForRangeStat, LuaForStat, LuaFuncStat,
4-
LuaGotoStat, LuaIfStat, LuaLabelStat, LuaLiteralToken, LuaLocalName, LuaLocalStat,
5-
LuaRepeatStat, LuaReturnStat, LuaVarExpr, LuaWhileStat, NumberResult, UnaryOperator,
3+
LuaCallArgList, LuaCallExprStat, LuaContinueStat, LuaDoStat, LuaExpr, LuaForRangeStat,
4+
LuaForStat, LuaFuncStat, LuaGotoStat, LuaIfStat, LuaLabelStat, LuaLiteralToken, LuaLocalName,
5+
LuaLocalStat, LuaRepeatStat, LuaReturnStat, LuaVarExpr, LuaWhileStat, NumberResult,
6+
UnaryOperator,
67
};
78

89
use crate::{
@@ -261,6 +262,29 @@ pub fn bind_break_stat(
261262
break_flow_id
262263
}
263264

265+
pub fn bind_continue_stat(
266+
binder: &mut FlowBinder,
267+
continue_stat: LuaContinueStat,
268+
current: FlowId,
269+
) -> FlowId {
270+
let continue_flow_id = binder.create_continue();
271+
if let Some(loop_flow) = binder.get_flow(binder.loop_label)
272+
&& loop_flow.kind.is_unreachable()
273+
{
274+
// report a error if we are trying to continue outside a loop
275+
binder.report_error(AnalyzeError::new(
276+
DiagnosticCode::SyntaxError,
277+
&t!("Continue outside loop"),
278+
continue_stat.get_range(),
279+
));
280+
return current;
281+
}
282+
283+
binder.add_antecedent(continue_flow_id, current);
284+
binder.add_antecedent(binder.loop_label, continue_flow_id);
285+
continue_flow_id
286+
}
287+
264288
pub fn bind_goto_stat(binder: &mut FlowBinder, goto_stat: LuaGotoStat, current: FlowId) -> FlowId {
265289
// Goto statements are handled separately in the flow analysis
266290
// They will be processed when we analyze the labels

0 commit comments

Comments
 (0)