Skip to content

Commit b06bdd9

Browse files
committed
[IMP] Follow property functions when following references
When following symbol references, also follow functions that are properties, in addition to variables and class instances. This ensures that properties are correctly resolved to the return type of the underlying function.
1 parent 897a6d9 commit b06bdd9

File tree

1 file changed

+34
-14
lines changed

1 file changed

+34
-14
lines changed

server/src/core/symbols/symbol.rs

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2166,24 +2166,23 @@ impl Symbol {
21662166
}
21672167
}
21682168
}
2169-
if let Symbol::Variable(v) = symbol {
2170-
for eval in v.evaluations.iter() {
2169+
2170+
let sym_type = symbol.typ();
2171+
if sym_type == SymType::VARIABLE || (sym_type == SymType::FUNCTION && symbol.as_func().is_property) {
2172+
for eval in symbol.evaluations().unwrap_or(&vec![]) {
21712173
let ctx = &mut Some(symbol_context.clone().into_iter().chain(context.clone().unwrap_or(HashMap::new()).into_iter()).collect::<HashMap<_, _>>());
21722174
let mut sym = eval.symbol.get_symbol(session, ctx, diagnostics, None);
2173-
match sym {
2174-
EvaluationSymbolPtr::WEAK(ref mut w) => {
2175-
if let Some(base_attr) = symbol_context.get(&S!("base_attr")) {
2176-
if !w.context.get(&S!("is_attr_of_instance")).map(|x| x.as_bool()).unwrap_or(false) {
2177-
w.context.insert(S!("base_attr"), base_attr.clone());
2178-
}
2175+
if let EvaluationSymbolPtr::WEAK(ref mut w) = sym {
2176+
if let Some(base_attr) = symbol_context.get(&S!("base_attr")) {
2177+
if !w.context.get(&S!("is_attr_of_instance")).map(|x| x.as_bool()).unwrap_or(false) {
2178+
w.context.insert(S!("base_attr"), base_attr.clone());
21792179
}
2180-
if let Some(base_attr) = symbol_context.get(&S!("is_attr_of_instance")) {
2181-
if !w.context.get(&S!("is_attr_of_instance")).map(|x| x.as_bool()).unwrap_or(false) {
2182-
w.context.insert(S!("is_attr_of_instance"), base_attr.clone());
2183-
}
2180+
}
2181+
if let Some(base_attr) = symbol_context.get(&S!("is_attr_of_instance")) {
2182+
if !w.context.get(&S!("is_attr_of_instance")).map(|x| x.as_bool()).unwrap_or(false) {
2183+
w.context.insert(S!("is_attr_of_instance"), base_attr.clone());
21842184
}
2185-
},
2186-
_ => {}
2185+
}
21872186
}
21882187
if !sym.is_expired_if_weak() {
21892188
res.push_back(sym);
@@ -2299,7 +2298,28 @@ impl Symbol {
22992298
work_queue.extend(next_sym_refs);
23002299
}
23012300
},
2301+
SymType::FUNCTION => {
2302+
let is_property = sym_rc.borrow().as_func().is_property;
2303+
if !is_property {
2304+
// Functions are final unless they are properties
2305+
results.push(current_eval);
2306+
continue;
2307+
}
2308+
let next_sym_refs = Symbol::next_refs(session, sym_rc.clone(), context, &next_ref_weak.context, stop_on_type, &mut vec![]);
2309+
if next_sym_refs.is_empty() {
2310+
// keep current evaluation
2311+
results.push(current_eval);
2312+
} else {
2313+
// enqueue evaluations to follow, replacing current evaluation
2314+
work_queue.extend(next_sym_refs);
2315+
}
2316+
// TODO: this arm can be easily merged with the one for SymType::CLASS, but
2317+
// - do we need to propagate instance = True here too (like we do for variables, but not class...)?
2318+
// - do we need to build_now for functions like we do for variables? In case yes, BuildSteps::ARCH_EVAL or VALIDATION?
2319+
// - stop_on_type, stop_on_value and max_scope apply also for this case?
2320+
}
23022321
_ => {
2322+
// Other symbol types are final
23032323
results.push(current_eval);
23042324
}
23052325
}

0 commit comments

Comments
 (0)