diff --git a/kclvm/sema/src/core/scope.rs b/kclvm/sema/src/core/scope.rs index d4e9b723b..51d19c4f5 100644 --- a/kclvm/sema/src/core/scope.rs +++ b/kclvm/sema/src/core/scope.rs @@ -493,65 +493,74 @@ impl Scope for LocalSymbolScope { ) -> Option { match self.defs.get(name) { Some(symbol_ref) => return Some(*symbol_ref), - None => match (local, get_def_from_owner) { - // Search in the current scope and owner - (true, true) => { + None => { + // Try to get the attributes in the schema's protocol and mixin, and get the schema attr by `get_def_from_owner` + if let LocalSymbolScopeKind::SchemaDef = self.kind { if let Some(owner) = self.owner.as_ref() { - let owner_symbol = symbol_data.get_symbol(*owner)?; - if let Some(symbol_ref) = - owner_symbol.get_attribute(name, symbol_data, module_info) - { - return Some(symbol_ref); + if let Some(owner_schema) = symbol_data.get_schema_symbol(*owner) { + let attrs = + owner_schema.get_protocol_and_mixin_attrs(symbol_data, module_info); + for attr in attrs { + if let Some(symbol) = symbol_data.get_symbol(attr) { + if symbol.get_name() == name { + return Some(attr); + } + } + } } } - None - } - // Search only in the current scope - (true, false) => { - let parent = scope_data.get_scope(&self.parent)?; - return parent.look_up_def( - name, - scope_data, - symbol_data, - module_info, - local, - get_def_from_owner, - ); } - // Search in the current scope, parent scope and owner - (false, true) => { - if let Some(owner) = self.owner.as_ref() { - let owner_symbol = symbol_data.get_symbol(*owner)?; - if let Some(symbol_ref) = - owner_symbol.get_attribute(name, symbol_data, module_info) - { - return Some(symbol_ref); + + match (local, get_def_from_owner) { + // Search in the current scope and owner + (true, true) => { + if let Some(owner) = self.owner.as_ref() { + let owner_symbol = symbol_data.get_symbol(*owner)?; + if let Some(symbol_ref) = + owner_symbol.get_attribute(name, symbol_data, module_info) + { + return Some(symbol_ref); + } } - }; - - let parent = scope_data.get_scope(&self.parent)?; - return parent.look_up_def( - name, - scope_data, - symbol_data, - module_info, - local, - get_def_from_owner, - ); - } - // Search in the current and parent scope - (false, false) => { - let parent = scope_data.get_scope(&self.parent)?; - return parent.look_up_def( - name, - scope_data, - symbol_data, - module_info, - local, - get_def_from_owner, - ); + None + } + // Search only in the current scope + (true, false) => None, + // Search in the current scope, parent scope and owner + (false, true) => { + if let Some(owner) = self.owner.as_ref() { + let owner_symbol = symbol_data.get_symbol(*owner)?; + if let Some(symbol_ref) = + owner_symbol.get_attribute(name, symbol_data, module_info) + { + return Some(symbol_ref); + } + }; + + let parent = scope_data.get_scope(&self.parent)?; + return parent.look_up_def( + name, + scope_data, + symbol_data, + module_info, + local, + get_def_from_owner, + ); + } + // Search in the current and parent scope + (false, false) => { + let parent = scope_data.get_scope(&self.parent)?; + return parent.look_up_def( + name, + scope_data, + symbol_data, + module_info, + local, + get_def_from_owner, + ); + } } - }, + } } } diff --git a/kclvm/sema/src/core/symbol.rs b/kclvm/sema/src/core/symbol.rs index 6a0485bf6..fcfaa52a7 100644 --- a/kclvm/sema/src/core/symbol.rs +++ b/kclvm/sema/src/core/symbol.rs @@ -1253,16 +1253,12 @@ impl SchemaSymbol { } } - pub fn get_self_attr( + pub fn get_protocol_and_mixin_attrs( &self, data: &SymbolData, module_info: Option<&ModuleInfo>, ) -> Vec { let mut result = vec![]; - for attribute in self.attributes.values() { - result.push(*attribute); - } - if let Some(for_host) = self.for_host { if let Some(for_host) = data.get_symbol(for_host) { result.append(&mut for_host.get_all_attributes(data, module_info)) @@ -1273,6 +1269,20 @@ impl SchemaSymbol { result.append(&mut mixin.get_all_attributes(data, module_info)) } } + + result + } + + pub fn get_self_attr( + &self, + data: &SymbolData, + module_info: Option<&ModuleInfo>, + ) -> Vec { + let mut result = vec![]; + for attribute in self.attributes.values() { + result.push(*attribute); + } + result.extend(self.get_protocol_and_mixin_attrs(data, module_info)); result } } diff --git a/kclvm/tools/src/LSP/src/goto_def.rs b/kclvm/tools/src/LSP/src/goto_def.rs index 2e94bb04e..4ccb68e55 100644 --- a/kclvm/tools/src/LSP/src/goto_def.rs +++ b/kclvm/tools/src/LSP/src/goto_def.rs @@ -551,4 +551,18 @@ mod tests { 33, 10 ); + + goto_def_test_snapshot!( + goto_protocol_attr, + "src/test_data/goto_def_test/goto_protocol/goto_protocol.k", + 6, + 17 + ); + + goto_def_test_snapshot!( + goto_protocol_attr_1, + "src/test_data/goto_def_test/goto_protocol/goto_protocol.k", + 8, + 13 + ); } diff --git a/kclvm/tools/src/LSP/src/snapshots/kcl_language_server__goto_def__tests__goto_protocol_attr.snap b/kclvm/tools/src/LSP/src/snapshots/kcl_language_server__goto_def__tests__goto_protocol_attr.snap new file mode 100644 index 000000000..2acbdbb07 --- /dev/null +++ b/kclvm/tools/src/LSP/src/snapshots/kcl_language_server__goto_def__tests__goto_protocol_attr.snap @@ -0,0 +1,5 @@ +--- +source: tools/src/LSP/src/goto_def.rs +expression: "format!(\"{:?}\", { fmt_resp(& res) })" +--- +"path: \"src/test_data/goto_def_test/goto_protocol/goto_protocol.k\", range: Range { start: Position { line: 1, character: 4 }, end: Position { line: 1, character: 8 } }" diff --git a/kclvm/tools/src/LSP/src/snapshots/kcl_language_server__goto_def__tests__goto_protocol_attr_1.snap b/kclvm/tools/src/LSP/src/snapshots/kcl_language_server__goto_def__tests__goto_protocol_attr_1.snap new file mode 100644 index 000000000..2acbdbb07 --- /dev/null +++ b/kclvm/tools/src/LSP/src/snapshots/kcl_language_server__goto_def__tests__goto_protocol_attr_1.snap @@ -0,0 +1,5 @@ +--- +source: tools/src/LSP/src/goto_def.rs +expression: "format!(\"{:?}\", { fmt_resp(& res) })" +--- +"path: \"src/test_data/goto_def_test/goto_protocol/goto_protocol.k\", range: Range { start: Position { line: 1, character: 4 }, end: Position { line: 1, character: 8 } }" diff --git a/kclvm/tools/src/LSP/src/test_data/goto_def_test/goto_protocol/goto_protocol.k b/kclvm/tools/src/LSP/src/test_data/goto_def_test/goto_protocol/goto_protocol.k new file mode 100644 index 000000000..2788435cc --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/goto_def_test/goto_protocol/goto_protocol.k @@ -0,0 +1,8 @@ +protocol AProtocol: + name?: str + +mixin AMixin for AProtocol: + config = { + data = name + } + data = name \ No newline at end of file