module; export module lsp.language.semantic:name_resolver; import std; import :type_system; import lsp.language.ast; import lsp.language.symbol; export namespace lsp::language::semantic { struct NameResolutionResult { symbol::SymbolId symbol_id = symbol::kInvalidSymbolId; bool is_ambiguous = false; std::vector candidates; bool IsResolved() const { return symbol_id != symbol::kInvalidSymbolId; } static NameResolutionResult Success(symbol::SymbolId id) { return { id, false, { id } }; } static NameResolutionResult Ambiguous(std::vector symbols) { return { symbols.empty() ? symbol::kInvalidSymbolId : symbols[0], true, std::move(symbols) }; } static NameResolutionResult NotFound() { return { symbol::kInvalidSymbolId, false, {} }; } }; struct OverloadCandidate { symbol::SymbolId symbol_id; int match_score = 0; std::vector arg_conversions; bool operator<(const OverloadCandidate& other) const { return match_score > other.match_score; } }; class NameResolver { public: explicit NameResolver(const symbol::SymbolTable& symbol_table, const TypeSystem& type_system) : symbol_table_(symbol_table), type_system_(type_system) {} NameResolutionResult ResolveName( const std::string& name, symbol::ScopeId scope_id, bool search_parent = true) const; NameResolutionResult ResolveNameAtLocation( const std::string& name, const ast::Location& location) const; NameResolutionResult ResolveMemberAccess( symbol::SymbolId object_symbol_id, const std::string& member_name) const; NameResolutionResult ResolveClassMember( symbol::SymbolId class_id, const std::string& member_name, bool static_only = false) const; NameResolutionResult ResolveFunctionCall( const std::string& function_name, const std::vector>& arg_types, symbol::ScopeId scope_id) const; NameResolutionResult ResolveMethodCall( symbol::SymbolId object_symbol_id, const std::string& method_name, const std::vector>& arg_types) const; NameResolutionResult ResolveQualifiedName( const std::string& qualifier, const std::string& name, symbol::ScopeId scope_id) const; std::optional GetSymbolScope( [[maybe_unused]] symbol::SymbolId symbol_id) const; bool IsSymbolVisibleInScope( [[maybe_unused]] symbol::SymbolId symbol_id, [[maybe_unused]] symbol::ScopeId scope_id) const; private: const symbol::SymbolTable& symbol_table_; const TypeSystem& type_system_; std::vector SearchScopeChain( const std::string& name, symbol::ScopeId start_scope) const; std::optional FindScopeOwnedBy(symbol::SymbolId owner) const; NameResolutionResult SelectBestOverload( const std::vector& candidates) const; OverloadCandidate CalculateOverloadScore( symbol::SymbolId candidate_id, const std::vector>& arg_types) const; std::vector> GetParameterTypes( symbol::SymbolId symbol_id) const; std::optional GetOwnerClassId( [[maybe_unused]] symbol::SymbolId symbol_id) const; bool CheckMemberAccessibility( [[maybe_unused]] const symbol::Symbol& member, [[maybe_unused]] symbol::ScopeId access_scope) const; }; } namespace lsp::language::semantic { NameResolutionResult NameResolver::ResolveName( const std::string& name, symbol::ScopeId scope_id, bool search_parent) const { if (!search_parent) { auto symbols = symbol_table_.FindSymbolsByName(name); if (symbols.empty()) { return NameResolutionResult::NotFound(); } if (symbols.size() == 1) { return NameResolutionResult::Success(symbols[0]); } return NameResolutionResult::Ambiguous(std::move(symbols)); } auto candidates = SearchScopeChain(name, scope_id); if (candidates.empty()) { return NameResolutionResult::NotFound(); } if (candidates.size() == 1) { return NameResolutionResult::Success(candidates[0]); } return NameResolutionResult::Ambiguous(std::move(candidates)); } NameResolutionResult NameResolver::ResolveNameAtLocation( const std::string& name, const ast::Location& location) const { auto scope_id = symbol_table_.scopes().FindScopeAt(location); if (!scope_id) { auto global_scope = symbol_table_.scopes().global_scope(); if (global_scope != symbol::kInvalidScopeId) { scope_id = global_scope; } } if (!scope_id) { return NameResolutionResult::NotFound(); } return ResolveName(name, *scope_id, true); } NameResolutionResult NameResolver::ResolveMemberAccess( symbol::SymbolId object_symbol_id, const std::string& member_name) const { auto object_type = type_system_.GetSymbolType(object_symbol_id); if (!object_type || object_type->kind() != TypeKind::kClass) { return NameResolutionResult::NotFound(); } const auto* class_type = object_type->As(); return ResolveClassMember(class_type->class_id(), member_name, false); } NameResolutionResult NameResolver::ResolveClassMember( symbol::SymbolId class_id, const std::string& member_name, bool static_only) const { const auto* class_symbol = symbol_table_.definition(class_id); if (!class_symbol || !class_symbol->Is()) { return NameResolutionResult::NotFound(); } const auto* class_data = class_symbol->As(); std::vector candidates; for (auto member_id : class_data->members) { const auto* member = symbol_table_.definition(member_id); if (!member) continue; if (member->name() != member_name) continue; if (static_only) { if (member->Is()) { const auto* method = member->As(); if (!method->is_static) continue; } else if (member->Is()) { const auto* field = member->As(); if (!field->is_static) continue; } } candidates.push_back(member_id); } // TODO: 在基类中查找(需要继承图支持) if (candidates.empty()) { return NameResolutionResult::NotFound(); } if (candidates.size() == 1) { return NameResolutionResult::Success(candidates[0]); } return NameResolutionResult::Ambiguous(std::move(candidates)); } NameResolutionResult NameResolver::ResolveFunctionCall( const std::string& function_name, const std::vector>& arg_types, symbol::ScopeId scope_id) const { auto candidates_ids = SearchScopeChain(function_name, scope_id); if (candidates_ids.empty()) { return NameResolutionResult::NotFound(); } if (candidates_ids.size() == 1) { return NameResolutionResult::Success(candidates_ids[0]); } std::vector candidates; for (auto candidate_id : candidates_ids) { auto candidate = CalculateOverloadScore(candidate_id, arg_types); if (candidate.match_score >= 0) { candidates.push_back(candidate); } } return SelectBestOverload(candidates); } NameResolutionResult NameResolver::ResolveMethodCall( symbol::SymbolId object_symbol_id, const std::string& method_name, const std::vector>& arg_types) const { auto resolution = ResolveMemberAccess(object_symbol_id, method_name); if (!resolution.IsResolved()) { return resolution; } if (!resolution.is_ambiguous) { return resolution; } std::vector candidates; for (auto candidate_id : resolution.candidates) { auto candidate = CalculateOverloadScore(candidate_id, arg_types); if (candidate.match_score >= 0) { candidates.push_back(candidate); } } return SelectBestOverload(candidates); } NameResolutionResult NameResolver::ResolveQualifiedName( const std::string& qualifier, const std::string& name, symbol::ScopeId scope_id) const { auto qualifier_result = ResolveName(qualifier, scope_id, true); if (!qualifier_result.IsResolved()) { return qualifier_result; } auto qualifier_symbol = symbol_table_.definition(qualifier_result.symbol_id); if (!qualifier_symbol) { return NameResolutionResult::NotFound(); } if (qualifier_symbol->Is()) { return ResolveClassMember(qualifier_result.symbol_id, name, true); } if (qualifier_symbol->Is()) { auto scope_id = FindScopeOwnedBy(qualifier_result.symbol_id); if (!scope_id) { return NameResolutionResult::NotFound(); } auto symbol_id = symbol_table_.scopes().FindSymbolInScope(*scope_id, name); if (!symbol_id) { return NameResolutionResult::NotFound(); } return NameResolutionResult::Success(*symbol_id); } return NameResolutionResult::NotFound(); } std::optional NameResolver::GetSymbolScope( [[maybe_unused]] symbol::SymbolId symbol_id) const { // TODO: 实现符号到作用域的映射 return std::nullopt; } bool NameResolver::IsSymbolVisibleInScope( [[maybe_unused]] symbol::SymbolId symbol_id, [[maybe_unused]] symbol::ScopeId scope_id) const { // TODO: 实现可见性检查 return true; } std::vector NameResolver::SearchScopeChain( const std::string& name, symbol::ScopeId start_scope) const { std::vector results; symbol::ScopeId current_scope = start_scope; while (current_scope != symbol::kInvalidScopeId) { auto scope_symbols = symbol_table_.scopes().FindSymbols(current_scope, name); results.insert(results.end(), scope_symbols.begin(), scope_symbols.end()); if (!results.empty()) { break; } auto parent = symbol_table_.scopes().GetParent(current_scope); if (!parent) { break; } current_scope = *parent; } return results; } std::optional NameResolver::FindScopeOwnedBy(symbol::SymbolId owner) const { const auto& scopes = symbol_table_.scopes().all_scopes(); for (const auto& [id, scope] : scopes) { if (scope.owner && *scope.owner == owner) { return id; } } return std::nullopt; } NameResolutionResult NameResolver::SelectBestOverload( const std::vector& candidates) const { if (candidates.empty()) { return NameResolutionResult::NotFound(); } auto sorted = candidates; std::sort(sorted.begin(), sorted.end()); if (sorted.size() > 1 && sorted[0].match_score == sorted[1].match_score) { std::vector ambiguous_ids; for (const auto& candidate : sorted) { if (candidate.match_score == sorted[0].match_score) { ambiguous_ids.push_back(candidate.symbol_id); } } return NameResolutionResult::Ambiguous(std::move(ambiguous_ids)); } return NameResolutionResult::Success(sorted[0].symbol_id); } OverloadCandidate NameResolver::CalculateOverloadScore( symbol::SymbolId candidate_id, const std::vector>& arg_types) const { OverloadCandidate result; result.symbol_id = candidate_id; auto param_types = GetParameterTypes(candidate_id); if (param_types.size() != arg_types.size()) { result.match_score = -1; return result; } int total_score = 0; for (std::size_t i = 0; i < arg_types.size(); ++i) { auto compat = type_system_.CheckCompatibility(*arg_types[i], *param_types[i]); if (!compat.is_compatible) { result.match_score = -1; return result; } result.arg_conversions.push_back(compat); if (compat.conversion_cost == 0) { total_score += 100; } else { total_score += std::max(0, 50 - compat.conversion_cost * 10); } if (compat.requires_cast) { total_score -= 20; } } result.match_score = total_score; return result; } std::vector> NameResolver::GetParameterTypes( symbol::SymbolId symbol_id) const { const auto* symbol = symbol_table_.definition(symbol_id); if (!symbol) { return {}; } std::vector> param_types; if (symbol->Is()) { const auto* func = symbol->As(); for (const auto& param : func->parameters) { if (param.type) { auto type = type_system_.GetTypeByName(*param.type); param_types.push_back(type); } else { param_types.push_back(type_system_.GetUnknownType()); } } } else if (symbol->Is()) { const auto* method = symbol->As(); for (const auto& param : method->parameters) { if (param.type) { auto type = type_system_.GetTypeByName(*param.type); param_types.push_back(type); } else { param_types.push_back(type_system_.GetUnknownType()); } } } return param_types; } std::optional NameResolver::GetOwnerClassId( [[maybe_unused]] symbol::SymbolId symbol_id) const { // TODO: 实现符号到所属类的映射 return std::nullopt; } bool NameResolver::CheckMemberAccessibility( [[maybe_unused]] const symbol::Symbol& member, [[maybe_unused]] symbol::ScopeId access_scope) const { // TODO: 实现访问权限检查 return true; } }