Skip to content

Commit 6b6f41c

Browse files
authored
Merge pull request #297 from xuhuanzy/diagnostic
diagnostic
2 parents 57a133d + 3b7c498 commit 6b6f41c

30 files changed

Lines changed: 680 additions & 109 deletions

File tree

crates/emmylua_code_analysis/resources/std/global.lua

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -390,13 +390,11 @@ function setmetatable(table, metatable) end
390390
--- represents 10, 'B' represents 11, and so forth, with 'Z' representing 35. If
391391
--- the string `e` is not a valid numeral in the given base, the function
392392
--- returns **nil**.
393-
---@overload fun(e:number, base?: int):number
394-
---@overload fun(e:string, base?: int):number?
395-
---@overload fun(e:any, base?:int):nil
393+
---@overload fun(e: string, base: integer):integer?
396394
---@param e any
397-
---@param base? int
398395
---@return number?
399-
function tonumber(e, base) end
396+
---@nodiscard
397+
function tonumber(e) end
400398

401399
---
402400
--- Receives a value of any type and converts it to a string in a human-readable

crates/emmylua_code_analysis/resources/std/math.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ function math.tan(x) return 0 end
186186
---
187187
--- If the value `x` is convertible to an integer, returns that integer.
188188
--- Otherwise, returns `nil`.
189-
---@param x number
189+
---@param x any
190190
---@return integer?
191191
function math.tointeger(x) end
192192

crates/emmylua_code_analysis/resources/std/table.lua

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,12 @@ table = {}
2121
--- `list[i]..sep..list[i+1] ... sep..list[j]`. The default value for
2222
--- `sep` is the empty string, the default for `i` is 1, and the default for
2323
--- `j` is #list. If `i` is greater than `j`, returns the empty string.
24-
---@overload fun(list:string[]):string
25-
---@overload fun(list:string[], sep:string):string
26-
---@overload fun(list:string[], sep:string, i:integer):string
27-
---@param list string[]
28-
---@param sep string
29-
---@param i integer
30-
---@param j integer
24+
---@param list table
25+
---@param sep? string
26+
---@param i? integer
27+
---@param j? integer
3128
---@return string
29+
---@nodiscard
3230
function table.concat(list, sep, i, j) end
3331

3432
---

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

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ use emmylua_parser::{
44
};
55

66
use crate::{
7+
compilation::analyzer::unresolve::UnResolveTableField,
78
db_index::{LuaDecl, LuaMember, LuaMemberKey, LuaMemberOwner},
8-
FileId, InFiled, LuaDeclExtra, LuaDeclId, LuaMemberFeature, LuaMemberId, LuaSignatureId,
9+
FileId, InFiled, InferFailReason, LuaDeclExtra, LuaDeclId, LuaMemberFeature, LuaMemberId,
10+
LuaSignatureId,
911
};
1012

1113
use super::DeclAnalyzer;
@@ -180,18 +182,33 @@ fn analyze_closure_params(
180182
Some(())
181183
}
182184

183-
pub fn analyze_table_expr(analyzer: &mut DeclAnalyzer, expr: LuaTableExpr) -> Option<()> {
184-
if expr.is_object() {
185+
pub fn analyze_table_expr(analyzer: &mut DeclAnalyzer, table_expr: LuaTableExpr) -> Option<()> {
186+
if table_expr.is_object() {
185187
let file_id = analyzer.get_file_id();
186188
let owner_id = LuaMemberOwner::Element(InFiled {
187189
file_id,
188-
value: expr.get_range(),
190+
value: table_expr.get_range(),
189191
});
192+
let decl_feature = if analyzer.is_meta {
193+
LuaMemberFeature::MetaDefine
194+
} else {
195+
LuaMemberFeature::FileDefine
196+
};
190197

191-
for field in expr.get_fields() {
198+
for field in table_expr.get_fields() {
192199
if let Some(field_key) = field.get_field_key() {
193-
let key: LuaMemberKey = field_key.into();
200+
let key: LuaMemberKey = field_key.clone().into();
194201
if key.is_none() {
202+
if let Some(field_expr) = field_key.get_expr() {
203+
let unresolve_member = UnResolveTableField {
204+
file_id: analyzer.get_file_id(),
205+
table_expr: table_expr.clone(),
206+
field: field.clone(),
207+
decl_feature,
208+
reason: InferFailReason::UnResolveExpr(field_expr.clone()),
209+
};
210+
analyzer.add_unresolved(unresolve_member.into());
211+
}
195212
continue;
196213
}
197214

@@ -201,12 +218,6 @@ pub fn analyze_table_expr(analyzer: &mut DeclAnalyzer, expr: LuaTableExpr) -> Op
201218
field.get_syntax_id(),
202219
);
203220

204-
let decl_feature = if analyzer.is_meta {
205-
LuaMemberFeature::MetaDefine
206-
} else {
207-
LuaMemberFeature::FileDefine
208-
};
209-
210221
let member_id = LuaMemberId::new(field.get_syntax_id(), file_id);
211222
let member = LuaMember::new(owner_id.clone(), member_id, key, decl_feature, None);
212223
analyzer.db.get_member_index_mut().add_member(member);

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

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::{
77
profile::Profile,
88
};
99

10-
use super::AnalyzeContext;
10+
use super::{unresolve::UnResolve, AnalyzeContext};
1111
use emmylua_parser::{LuaAst, LuaAstNode, LuaChunk, LuaFuncStat, LuaSyntaxKind, LuaVarExpr};
1212
use rowan::{TextRange, TextSize, WalkEvent};
1313

@@ -18,14 +18,18 @@ use crate::{
1818

1919
pub(crate) fn analyze(db: &mut DbIndex, context: &mut AnalyzeContext) {
2020
let _p = Profile::cond_new("decl analyze", context.tree_list.len() > 1);
21-
for in_filed_tree in context.tree_list.iter() {
21+
let tree_list = context.tree_list.clone();
22+
for in_filed_tree in tree_list.iter() {
2223
db.get_reference_index_mut()
2324
.create_local_reference(in_filed_tree.file_id);
2425
let mut analyzer =
2526
DeclAnalyzer::new(db, in_filed_tree.file_id, in_filed_tree.value.clone());
2627
analyzer.analyze();
27-
let decl_tree = analyzer.get_decl_tree();
28+
let (decl_tree, unresolved) = analyzer.get_decl_tree();
2829
db.get_decl_index_mut().add_decl_tree(decl_tree);
30+
for unresolve in unresolved {
31+
context.add_unresolve(unresolve);
32+
}
2933
}
3034
}
3135

@@ -138,6 +142,7 @@ pub struct DeclAnalyzer<'a> {
138142
decl: LuaDeclarationTree,
139143
scopes: Vec<LuaScopeId>,
140144
is_meta: bool,
145+
pub unresolved: Vec<UnResolve>,
141146
}
142147

143148
impl<'a> DeclAnalyzer<'a> {
@@ -148,6 +153,7 @@ impl<'a> DeclAnalyzer<'a> {
148153
decl: LuaDeclarationTree::new(file_id),
149154
scopes: Vec::new(),
150155
is_meta: false,
156+
unresolved: Vec::new(),
151157
}
152158
}
153159

@@ -161,8 +167,16 @@ impl<'a> DeclAnalyzer<'a> {
161167
}
162168
}
163169

164-
pub fn get_decl_tree(self) -> LuaDeclarationTree {
165-
self.decl
170+
pub fn get_file_id(&self) -> FileId {
171+
self.decl.file_id()
172+
}
173+
174+
pub fn add_unresolved(&mut self, unresolved: UnResolve) {
175+
self.unresolved.push(unresolved);
176+
}
177+
178+
pub fn get_decl_tree(self) -> (LuaDeclarationTree, Vec<UnResolve>) {
179+
(self.decl, self.unresolved)
166180
}
167181

168182
pub fn create_scope(&mut self, range: TextRange, kind: LuaScopeKind) {
@@ -206,10 +220,6 @@ impl<'a> DeclAnalyzer<'a> {
206220
pub fn find_decl(&self, name: &str, position: TextSize) -> Option<&LuaDecl> {
207221
self.decl.find_local_decl(name, position)
208222
}
209-
210-
pub fn get_file_id(&self) -> FileId {
211-
self.decl.file_id()
212-
}
213223
}
214224

215225
fn is_method_func_stat(stat: &LuaFuncStat) -> Option<bool> {

crates/emmylua_code_analysis/src/compilation/analyzer/flow/var_analyze.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,20 +61,20 @@ pub fn analyze_ref_assign(
6161
}
6262

6363
let (var_exprs, value_exprs) = assign_stat.get_var_and_expr_list();
64-
let index = var_exprs
64+
let var_index = var_exprs
6565
.iter()
6666
.position(|it| it.get_position() == var_expr.get_position())?;
6767

6868
if value_exprs.len() == 0 {
6969
return None;
7070
}
7171

72-
let (value_expr, idx) = if let Some(expr) = value_exprs.get(index) {
72+
let (value_expr, idx) = if let Some(expr) = value_exprs.get(var_index) {
7373
(expr.clone(), 0)
7474
} else {
7575
(
7676
value_exprs.last()?.clone(),
77-
(index - value_exprs.len()) as i32,
77+
(var_index - (value_exprs.len() - 1)) as i32,
7878
)
7979
};
8080

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

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,24 @@ pub fn analyze_local_stat(analyzer: &mut LuaAnalyzer, local_stat: LuaLocalStat)
4444
if let LuaType::MuliReturn(multi) = expr_type {
4545
expr_type = multi.get_type(0)?.clone();
4646
}
47-
4847
let decl_id = LuaDeclId::new(analyzer.file_id, position);
48+
// 当`call`参数包含表时, 表可能未被分析, 需要延迟
49+
if let LuaType::Instance(instance) = &expr_type {
50+
if instance.get_base().is_unknown() {
51+
if call_expr_has_effect_table_arg(expr).is_some() {
52+
let unresolve = UnResolveDecl {
53+
file_id: analyzer.file_id,
54+
decl_id,
55+
expr: expr.clone(),
56+
ret_idx: 0,
57+
reason: InferFailReason::UnResolveExpr(expr.clone()),
58+
};
59+
analyzer.add_unresolved(unresolve.into());
60+
continue;
61+
}
62+
}
63+
}
64+
4965
merge_decl_expr_type(analyzer.db, &mut analyzer.infer_cache, decl_id, expr_type);
5066
}
5167
Err(InferFailReason::None) => {
@@ -134,6 +150,20 @@ pub fn analyze_local_stat(analyzer: &mut LuaAnalyzer, local_stat: LuaLocalStat)
134150
Some(())
135151
}
136152

153+
fn call_expr_has_effect_table_arg(expr: &LuaExpr) -> Option<()> {
154+
if let LuaExpr::CallExpr(call_expr) = expr {
155+
let args_list = call_expr.get_args_list()?;
156+
for arg in args_list.get_args() {
157+
if let LuaExpr::TableExpr(table_expr) = arg {
158+
if !table_expr.is_empty() {
159+
return Some(());
160+
}
161+
}
162+
}
163+
}
164+
None
165+
}
166+
137167
#[derive(Debug, Clone)]
138168
enum TypeOwner {
139169
Decl(LuaDeclId),

crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/mod.rs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,17 @@ mod resolve_closure;
77
use crate::{
88
db_index::{DbIndex, LuaDeclId, LuaMemberId, LuaSignatureId},
99
profile::Profile,
10-
FileId, InferFailReason, LuaSemanticDeclId,
10+
FileId, InferFailReason, LuaMemberFeature, LuaSemanticDeclId,
1111
};
1212
use check_reason::{resolve_all_reason, resolve_as_any};
13-
use emmylua_parser::{LuaAssignStat, LuaCallExpr, LuaExpr, LuaFuncStat, LuaTableField};
13+
use emmylua_parser::{
14+
LuaAssignStat, LuaCallExpr, LuaExpr, LuaFuncStat, LuaTableExpr, LuaTableField,
15+
};
1416
use infer_manager::InferCacheManager;
1517
pub use merge_type::{merge_decl_expr_type, merge_member_type};
1618
use resolve::{
1719
try_resolve_decl, try_resolve_iter_var, try_resolve_member, try_resolve_module,
18-
try_resolve_module_ref, try_resolve_return_point,
20+
try_resolve_module_ref, try_resolve_return_point, try_resolve_table_field,
1921
};
2022
use resolve_closure::{
2123
try_resolve_closure_params, try_resolve_closure_parent_params, try_resolve_closure_return,
@@ -92,6 +94,9 @@ fn try_resolve(
9294
try_resolve_closure_parent_params(db, config, un_resolve_closure_params)
9395
.unwrap_or(false)
9496
}
97+
UnResolve::TableField(un_resolve_table_field) => {
98+
try_resolve_table_field(db, config, un_resolve_table_field).unwrap_or(false)
99+
}
95100
UnResolve::None => continue,
96101
};
97102

@@ -116,6 +121,7 @@ pub enum UnResolve {
116121
ClosureReturn(Box<UnResolveClosureReturn>),
117122
ClosureParentParams(Box<UnResolveParentClosureParams>),
118123
ModuleRef(Box<UnResolveModuleRef>),
124+
TableField(Box<UnResolveTableField>),
119125
}
120126

121127
#[allow(dead_code)]
@@ -140,6 +146,7 @@ impl UnResolve {
140146
UnResolve::ClosureParentParams(un_resolve_closure_params) => {
141147
Some(un_resolve_closure_params.file_id)
142148
}
149+
UnResolve::TableField(un_resolve_table_field) => Some(un_resolve_table_field.file_id),
143150
UnResolve::ModuleRef(_) => None,
144151
UnResolve::None => None,
145152
}
@@ -279,3 +286,18 @@ impl From<UnResolveParentClosureParams> for UnResolve {
279286
UnResolve::ClosureParentParams(Box::new(un_resolve_closure_params))
280287
}
281288
}
289+
290+
#[derive(Debug)]
291+
pub struct UnResolveTableField {
292+
pub file_id: FileId,
293+
pub table_expr: LuaTableExpr,
294+
pub field: LuaTableField,
295+
pub decl_feature: LuaMemberFeature,
296+
pub reason: InferFailReason,
297+
}
298+
299+
impl From<UnResolveTableField> for UnResolve {
300+
fn from(un_resolve_table_field: UnResolveTableField) -> Self {
301+
UnResolve::TableField(Box::new(un_resolve_table_field))
302+
}
303+
}

0 commit comments

Comments
 (0)