diff --git a/cpp/libclang/integration_test/cases/template_partial_specialization_ids/BUILD b/cpp/libclang/integration_test/cases/template_partial_specialization_ids/BUILD new file mode 100644 index 00000000..f8532b65 --- /dev/null +++ b/cpp/libclang/integration_test/cases/template_partial_specialization_ids/BUILD @@ -0,0 +1,30 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +load("//cpp/libclang/integration_test:test_rules.bzl", "cpp_parser_integration_test") + +cc_library( + name = "template_partial_specialization_ids", + srcs = ["specialization.cpp"], + hdrs = [ + "specialization.h", + "specialization_with_return.h", + "specialization_without_return.h", + ], + visibility = ["//cpp/libclang:__subpackages__"], +) + +cpp_parser_integration_test( + name = "test_template_partial_specialization_ids", + expected_output = ["expected.json"], + target = ":template_partial_specialization_ids", +) diff --git a/cpp/libclang/integration_test/cases/template_partial_specialization_ids/expected.json b/cpp/libclang/integration_test/cases/template_partial_specialization_ids/expected.json new file mode 100644 index 00000000..cd4a0cea --- /dev/null +++ b/cpp/libclang/integration_test/cases/template_partial_specialization_ids/expected.json @@ -0,0 +1,142 @@ +{ + "functions": [], + "types": { + "demo::Endpoint": { + "enclosing_namespace_id": "demo", + "entity_type": "Class", + "enum_literals": [], + "id": "demo::Endpoint", + "methods": [ + { + "modifiers": [], + "name": "Request", + "parameters": [ + { + "is_pack_expansion": true, + "is_variadic": false, + "name": "args", + "param_type": "const ArgTypes &" + } + ], + "return_type": "ReturnType", + "template_parameters": null, + "visibility": "public", + "source_location": { + "file": "./cpp/libclang/integration_test/cases/template_partial_specialization_ids/specialization_with_return.h", + "line": 28 + } + } + ], + "name": "Endpoint", + "relationships": [], + "source_location": { + "file": "./cpp/libclang/integration_test/cases/template_partial_specialization_ids/specialization_with_return.h", + "line": 25 + }, + "template_parameters": [ + { + "Type": { + "is_pack": false, + "name": "ReturnType" + } + }, + { + "Type": { + "is_pack": true, + "name": "ArgTypes" + } + } + ], + "type_aliases": [], + "variables": [ + { + "data_type": "int", + "is_static": false, + "name": "parameter_count_", + "source_location": { + "file": "./cpp/libclang/integration_test/cases/template_partial_specialization_ids/specialization_with_return.h", + "line": 31 + }, + "visibility": "private" + } + ] + }, + "demo::Endpoint": { + "enclosing_namespace_id": "demo", + "entity_type": "Class", + "enum_literals": [], + "id": "demo::Endpoint", + "methods": [ + { + "modifiers": [], + "name": "Notify", + "parameters": [ + { + "is_pack_expansion": true, + "is_variadic": false, + "name": "args", + "param_type": "const ArgTypes &" + } + ], + "return_type": "void", + "template_parameters": null, + "visibility": "public", + "source_location": { + "file": "./cpp/libclang/integration_test/cases/template_partial_specialization_ids/specialization_without_return.h", + "line": 28 + } + } + ], + "name": "Endpoint", + "relationships": [], + "source_location": { + "file": "./cpp/libclang/integration_test/cases/template_partial_specialization_ids/specialization_without_return.h", + "line": 25 + }, + "template_parameters": [ + { + "Type": { + "is_pack": true, + "name": "ArgTypes" + } + } + ], + "type_aliases": [], + "variables": [ + { + "data_type": "int", + "is_static": false, + "name": "notification_count_", + "source_location": { + "file": "./cpp/libclang/integration_test/cases/template_partial_specialization_ids/specialization_without_return.h", + "line": 31 + }, + "visibility": "private" + } + ] + }, + "demo::Endpoint": { + "enclosing_namespace_id": "demo", + "entity_type": "Class", + "enum_literals": [], + "id": "demo::Endpoint", + "methods": [], + "name": "Endpoint", + "relationships": [], + "source_location": { + "file": "./cpp/libclang/integration_test/cases/template_partial_specialization_ids/specialization.h", + "line": 23 + }, + "template_parameters": [ + { + "Type": { + "is_pack": false, + "name": "Signature" + } + } + ], + "type_aliases": [], + "variables": [] + } + } +} diff --git a/cpp/libclang/integration_test/cases/template_partial_specialization_ids/run_test.rs b/cpp/libclang/integration_test/cases/template_partial_specialization_ids/run_test.rs new file mode 100644 index 00000000..74f7d943 --- /dev/null +++ b/cpp/libclang/integration_test/cases/template_partial_specialization_ids/run_test.rs @@ -0,0 +1,19 @@ +// ******************************************************************************* +// Copyright (c) 2026 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// This program and the accompanying materials are made available under the +// terms of the Apache License Version 2.0 which is available at +// +// +// SPDX-License-Identifier: Apache-2.0 +// ******************************************************************************* + +use test_framework::run_parser_case; + +#[test] +fn test_template_partial_specialization_ids() { + run_parser_case(); +} diff --git a/cpp/libclang/integration_test/cases/template_partial_specialization_ids/specialization.cpp b/cpp/libclang/integration_test/cases/template_partial_specialization_ids/specialization.cpp new file mode 100644 index 00000000..870a57ce --- /dev/null +++ b/cpp/libclang/integration_test/cases/template_partial_specialization_ids/specialization.cpp @@ -0,0 +1,15 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +#include "specialization_with_return.h" +#include "specialization_without_return.h" diff --git a/cpp/libclang/integration_test/cases/template_partial_specialization_ids/specialization.h b/cpp/libclang/integration_test/cases/template_partial_specialization_ids/specialization.h new file mode 100644 index 00000000..55117529 --- /dev/null +++ b/cpp/libclang/integration_test/cases/template_partial_specialization_ids/specialization.h @@ -0,0 +1,30 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +#ifndef CPP_LIBCLANG_INTEGRATION_TEST_CASES_TEMPLATE_PARTIAL_SPECIALIZATION_IDS_SPECIALIZATION_H +#define CPP_LIBCLANG_INTEGRATION_TEST_CASES_TEMPLATE_PARTIAL_SPECIALIZATION_IDS_SPECIALIZATION_H + +namespace demo +{ + +// Primary template kept in its own header so the parser has to merge it with +// function-signature partial specializations declared elsewhere. +template +class Endpoint +{ + static_assert(sizeof(Signature) == 0, "Endpoint only supports function-signature template arguments."); +}; + +} // namespace demo + +#endif // CPP_LIBCLANG_INTEGRATION_TEST_CASES_TEMPLATE_PARTIAL_SPECIALIZATION_IDS_SPECIALIZATION_H diff --git a/cpp/libclang/integration_test/cases/template_partial_specialization_ids/specialization_with_return.h b/cpp/libclang/integration_test/cases/template_partial_specialization_ids/specialization_with_return.h new file mode 100644 index 00000000..430befeb --- /dev/null +++ b/cpp/libclang/integration_test/cases/template_partial_specialization_ids/specialization_with_return.h @@ -0,0 +1,36 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +#ifndef CPP_LIBCLANG_INTEGRATION_TEST_CASES_TEMPLATE_PARTIAL_SPECIALIZATION_IDS_SPECIALIZATION_WITH_RETURN_H +#define CPP_LIBCLANG_INTEGRATION_TEST_CASES_TEMPLATE_PARTIAL_SPECIALIZATION_IDS_SPECIALIZATION_WITH_RETURN_H + +#include "specialization.h" + +namespace demo +{ + +// Covers a partial specialization that binds both a regular template parameter +// and a parameter pack from a function-signature template argument. +template +class Endpoint +{ + public: + ReturnType Request(const ArgTypes&... args); + + private: + int parameter_count_; +}; + +} // namespace demo + +#endif // CPP_LIBCLANG_INTEGRATION_TEST_CASES_TEMPLATE_PARTIAL_SPECIALIZATION_IDS_SPECIALIZATION_WITH_RETURN_H diff --git a/cpp/libclang/integration_test/cases/template_partial_specialization_ids/specialization_without_return.h b/cpp/libclang/integration_test/cases/template_partial_specialization_ids/specialization_without_return.h new file mode 100644 index 00000000..b7b7ab03 --- /dev/null +++ b/cpp/libclang/integration_test/cases/template_partial_specialization_ids/specialization_without_return.h @@ -0,0 +1,36 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +#ifndef CPP_LIBCLANG_INTEGRATION_TEST_CASES_TEMPLATE_PARTIAL_SPECIALIZATION_IDS_SPECIALIZATION_WITHOUT_RETURN_H +#define CPP_LIBCLANG_INTEGRATION_TEST_CASES_TEMPLATE_PARTIAL_SPECIALIZATION_IDS_SPECIALIZATION_WITHOUT_RETURN_H + +#include "specialization.h" + +namespace demo +{ + +// Mirrors the void-return specialization pattern used by ProxyMethod and keeps +// the parameter pack in the specialization itself. +template +class Endpoint +{ + public: + void Notify(const ArgTypes&... args); + + private: + int notification_count_; +}; + +} // namespace demo + +#endif // CPP_LIBCLANG_INTEGRATION_TEST_CASES_TEMPLATE_PARTIAL_SPECIALIZATION_IDS_SPECIALIZATION_WITHOUT_RETURN_H diff --git a/cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/BUILD b/cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/BUILD new file mode 100644 index 00000000..d5b63281 --- /dev/null +++ b/cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/BUILD @@ -0,0 +1,30 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +load("//cpp/libclang/integration_test:test_rules.bzl", "cpp_parser_integration_test") + +cc_library( + name = "template_partial_specialization_relationship_target", + srcs = ["relationship.cpp"], + hdrs = [ + "endpoint.h", + "endpoint_without_return.h", + "holder.h", + ], + visibility = ["//cpp/libclang:__subpackages__"], +) + +cpp_parser_integration_test( + name = "test_template_partial_specialization_relationship_target", + expected_output = ["expected.json"], + target = ":template_partial_specialization_relationship_target", +) diff --git a/cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/endpoint.h b/cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/endpoint.h new file mode 100644 index 00000000..0cba3979 --- /dev/null +++ b/cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/endpoint.h @@ -0,0 +1,30 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +#ifndef CPP_LIBCLANG_INTEGRATION_TEST_CASES_TEMPLATE_PARTIAL_SPECIALIZATION_RELATIONSHIP_TARGET_ENDPOINT_H +#define CPP_LIBCLANG_INTEGRATION_TEST_CASES_TEMPLATE_PARTIAL_SPECIALIZATION_RELATIONSHIP_TARGET_ENDPOINT_H + +namespace demo +{ + +// Primary template exists as a distinct entity, and the relationship logic +// currently prefers this template base over a concrete specialization target. +template +class Endpoint +{ + static_assert(sizeof(Signature) == 0, "Endpoint only supports function-signature template arguments."); +}; + +} // namespace demo + +#endif // CPP_LIBCLANG_INTEGRATION_TEST_CASES_TEMPLATE_PARTIAL_SPECIALIZATION_RELATIONSHIP_TARGET_ENDPOINT_H diff --git a/cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/endpoint_without_return.h b/cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/endpoint_without_return.h new file mode 100644 index 00000000..17f86495 --- /dev/null +++ b/cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/endpoint_without_return.h @@ -0,0 +1,34 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +#ifndef CPP_LIBCLANG_INTEGRATION_TEST_CASES_TEMPLATE_PARTIAL_SPECIALIZATION_RELATIONSHIP_TARGET_ENDPOINT_WITHOUT_RETURN_H +#define CPP_LIBCLANG_INTEGRATION_TEST_CASES_TEMPLATE_PARTIAL_SPECIALIZATION_RELATIONSHIP_TARGET_ENDPOINT_WITHOUT_RETURN_H + +#include "endpoint.h" + +namespace demo +{ + +template +class Endpoint +{ + public: + void Notify(const ArgTypes&... args); + + private: + int notification_count_; +}; + +} // namespace demo + +#endif // CPP_LIBCLANG_INTEGRATION_TEST_CASES_TEMPLATE_PARTIAL_SPECIALIZATION_RELATIONSHIP_TARGET_ENDPOINT_WITHOUT_RETURN_H diff --git a/cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/expected.json b/cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/expected.json new file mode 100644 index 00000000..08ac6dd0 --- /dev/null +++ b/cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/expected.json @@ -0,0 +1,121 @@ +{ + "functions": [], + "types": { + "demo::Endpoint": { + "enclosing_namespace_id": "demo", + "entity_type": "Class", + "enum_literals": [], + "id": "demo::Endpoint", + "methods": [ + { + "modifiers": [], + "name": "Notify", + "parameters": [ + { + "is_pack_expansion": true, + "is_variadic": false, + "name": "args", + "param_type": "const ArgTypes &" + } + ], + "return_type": "void", + "template_parameters": null, + "visibility": "public", + "source_location": { + "file": "./cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/endpoint_without_return.h", + "line": 26 + } + } + ], + "name": "Endpoint", + "relationships": [], + "source_location": { + "file": "./cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/endpoint_without_return.h", + "line": 23 + }, + "template_parameters": [ + { + "Type": { + "is_pack": true, + "name": "ArgTypes" + } + } + ], + "type_aliases": [], + "variables": [ + { + "data_type": "int", + "is_static": false, + "name": "notification_count_", + "source_location": { + "file": "./cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/endpoint_without_return.h", + "line": 29 + }, + "visibility": "private" + } + ] + }, + "demo::Endpoint": { + "enclosing_namespace_id": "demo", + "entity_type": "Class", + "enum_literals": [], + "id": "demo::Endpoint", + "methods": [], + "name": "Endpoint", + "relationships": [], + "source_location": { + "file": "./cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/endpoint.h", + "line": 23 + }, + "template_parameters": [ + { + "Type": { + "is_pack": false, + "name": "Signature" + } + } + ], + "type_aliases": [], + "variables": [] + }, + "demo::Holder": { + "enclosing_namespace_id": "demo", + "entity_type": "Class", + "enum_literals": [], + "id": "demo::Holder", + "methods": [], + "name": "Holder", + "relationships": [ + { + "source": "demo::Holder", + "target": "demo::Endpoint", + "relation_type": "Composition", + "source_multiplicity": null, + "target_multiplicity": null, + "source_location": { + "file": "./cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/holder.h", + "line": 31 + } + } + ], + "source_location": { + "file": "./cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/holder.h", + "line": 24 + }, + "template_parameters": null, + "type_aliases": [], + "variables": [ + { + "data_type": "demo::Endpoint", + "is_static": false, + "name": "endpoint_", + "source_location": { + "file": "./cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/holder.h", + "line": 31 + }, + "visibility": "private" + } + ] + } + } +} diff --git a/cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/holder.h b/cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/holder.h new file mode 100644 index 00000000..80e46744 --- /dev/null +++ b/cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/holder.h @@ -0,0 +1,36 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +#ifndef CPP_LIBCLANG_INTEGRATION_TEST_CASES_TEMPLATE_PARTIAL_SPECIALIZATION_RELATIONSHIP_TARGET_HOLDER_H +#define CPP_LIBCLANG_INTEGRATION_TEST_CASES_TEMPLATE_PARTIAL_SPECIALIZATION_RELATIONSHIP_TARGET_HOLDER_H + +#include "endpoint_without_return.h" + +namespace demo +{ + +// The member type names a partial specialization, but the inferred +// relationship target still resolves to the template base entity. +class Holder +{ + private: + // relationship_target is demo::Endpoint (primary template), + // rather than demo::Endpoint (specialization). + // The relationship model currently resolves this relationship to the primary template. + // This is a known model limitation, not an issue with the visitor pipeline. + Endpoint endpoint_; +}; + +} // namespace demo + +#endif // CPP_LIBCLANG_INTEGRATION_TEST_CASES_TEMPLATE_PARTIAL_SPECIALIZATION_RELATIONSHIP_TARGET_HOLDER_H diff --git a/cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/relationship.cpp b/cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/relationship.cpp new file mode 100644 index 00000000..b0566c88 --- /dev/null +++ b/cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/relationship.cpp @@ -0,0 +1,14 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +#include "holder.h" diff --git a/cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/run_test.rs b/cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/run_test.rs new file mode 100644 index 00000000..93847c33 --- /dev/null +++ b/cpp/libclang/integration_test/cases/template_partial_specialization_relationship_target/run_test.rs @@ -0,0 +1,19 @@ +// ******************************************************************************* +// Copyright (c) 2026 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// This program and the accompanying materials are made available under the +// terms of the Apache License Version 2.0 which is available at +// +// +// SPDX-License-Identifier: Apache-2.0 +// ******************************************************************************* + +use test_framework::run_parser_case; + +#[test] +fn test_template_partial_specialization_relationship_target() { + run_parser_case(); +} diff --git a/cpp/libclang/src/visitor/src/class_parser_helper.rs b/cpp/libclang/src/visitor/src/class_parser_helper.rs index 9974ee05..11786a67 100644 --- a/cpp/libclang/src/visitor/src/class_parser_helper.rs +++ b/cpp/libclang/src/visitor/src/class_parser_helper.rs @@ -101,6 +101,9 @@ impl ResolvedType { /// /// Traversal policy: /// - Template prefers first resolvable argument, then falls back to template base. + /// This intentionally keeps relationship targets at the template-family + /// level for now, even when the model also contains partial-specialization + /// entities with more specific ids. /// - Function prefers return type, then parameter types. /// - Wrapper/qualifier/array nodes delegate to their inner element. pub fn relationship_target_entity_id(&self) -> Option<&str> { @@ -136,7 +139,8 @@ impl ResolvedType { /// Returns a direct referenced entity id for base-type style lookups. /// /// Unlike `relationship_target_entity_id`, this intentionally keeps template-base - /// semantics for inheritance resolution. + /// semantics for inheritance resolution and does not attempt to target a + /// particular partial specialization entity. pub fn referenced_entity_id(&self) -> Option<&str> { match self.referenced_entity_root() { ResolvedType::UserDefined(id) => Some(id), diff --git a/cpp/libclang/src/visitor/src/class_visitor.rs b/cpp/libclang/src/visitor/src/class_visitor.rs index 14c22eb6..f614011e 100644 --- a/cpp/libclang/src/visitor/src/class_visitor.rs +++ b/cpp/libclang/src/visitor/src/class_visitor.rs @@ -65,10 +65,7 @@ impl ClassVisitor { return None; }; - let id = match namespace { - Some(ns) if !ns.is_empty() => format!("{ns}::{name}"), - _ => name.clone(), - }; + let id = class_entity_id(entity, namespace, &name); let mut builder = ParsedClassInfo { id: id.clone(), @@ -145,6 +142,21 @@ impl ClassVisitor { } } +fn class_entity_id(entity: &Entity, namespace: Option<&str>, name: &str) -> String { + let base_name = if entity.get_kind() == EntityKind::ClassTemplatePartialSpecialization { + entity + .get_display_name() + .unwrap_or_else(|| name.to_string()) + } else { + name.to_string() + }; + + match namespace { + Some(ns) if !ns.is_empty() => format!("{ns}::{base_name}"), + _ => base_name, + } +} + pub(crate) fn parse_source_location(entity: &Entity) -> SourceLocation { let Some(location) = entity.get_location() else { return SourceLocation::default(); diff --git a/cpp/libclang/src/visitor/src/visitor.rs b/cpp/libclang/src/visitor/src/visitor.rs index 3734a680..eae6f1ee 100644 --- a/cpp/libclang/src/visitor/src/visitor.rs +++ b/cpp/libclang/src/visitor/src/visitor.rs @@ -73,7 +73,7 @@ impl<'a> Visitor<'a> { EntityKind::ClassDecl | EntityKind::StructDecl => { ClassVisitor::visit(self.ctx, entity); } - EntityKind::ClassTemplate => { + EntityKind::ClassTemplate | EntityKind::ClassTemplatePartialSpecialization => { self.ctx.is_templated = true; ClassVisitor::visit(self.ctx, entity); // ClassTemplate parsing already processes all members,