From 4ff849855d18e764b90f22d23f2cb4659c3990b1 Mon Sep 17 00:00:00 2001 From: Sophia Chen Date: Thu, 23 Jan 2025 12:22:06 -0800 Subject: [PATCH 1/5] first commit --- src/cswinrt/code_writers.h | 38 ++++++++++++++++++++++++++++++++++++++ src/cswinrt/main.cpp | 1 + 2 files changed, 39 insertions(+) diff --git a/src/cswinrt/code_writers.h b/src/cswinrt/code_writers.h index c1bd3ba86..0d8c3b130 100644 --- a/src/cswinrt/code_writers.h +++ b/src/cswinrt/code_writers.h @@ -8631,6 +8631,44 @@ _defaultLazy = new Lazy<%>(() => GetDefaultReference<%.Vftbl>()); bind(type)); } + void write_abstract_class_method(writer& w, MethodDef const& method, std::string_view platform_attribute) + { + auto method_name = method.Name(); + method_signature signature{ method }; + + w.write(R"( +%% % % %(%); +)", +platform_attribute, +"protected", +"abstract override", +bind(signature), +method_name, +bind_list(", ", signature.params())); + } + + void write_abstract_class(writer& w, TypeDef const& type) + { + auto type_namespace = type.TypeNamespace(); + auto type_name = write_type_name_temp(w, type); + w.write(R"( +%protected abstract class % : % +{ +)", +bind(type, true), +"Abstract" + type_name, +type_name); + auto platform_attribute = write_platform_attribute_temp(w, type); + + for (auto&& method : type.MethodList()) + { + write_abstract_class_method(w, method, ""); + } + + w.write(R"( +} +)"); + } void write_class(writer& w, TypeDef const& type) { diff --git a/src/cswinrt/main.cpp b/src/cswinrt/main.cpp index bce9f2f62..5adc0f1fe 100644 --- a/src/cswinrt/main.cpp +++ b/src/cswinrt/main.cpp @@ -238,6 +238,7 @@ Where is one or more of: } else { + write_abstract_class(w, type); write_class(w, type); add_base_type_entry(type, typeNameToBaseTypeMap); add_metadata_type_entry(type, authoredTypeNameToMetadataTypeNameMap); From 9d205711f4c3fbf26f0d02ac24003882ba7425ea Mon Sep 17 00:00:00 2001 From: Sophia Chen Date: Thu, 23 Jan 2025 15:24:02 -0800 Subject: [PATCH 2/5] add more for events and props --- src/cswinrt/code_writers.h | 74 ++++++++++++++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 6 deletions(-) diff --git a/src/cswinrt/code_writers.h b/src/cswinrt/code_writers.h index 0d8c3b130..a26112822 100644 --- a/src/cswinrt/code_writers.h +++ b/src/cswinrt/code_writers.h @@ -8631,8 +8631,57 @@ _defaultLazy = new Lazy<%>(() => GetDefaultReference<%.Vftbl>()); bind(type)); } + void write_abstract_class_event(writer& w, Event const& event, std::string_view platform_attribute) + { + auto external_event_name = event.Name(); + auto event_type = w.write_temp("%", bind(get_type_semantics(event.EventType()), typedef_name_type::Projected, false)); + + w.write(R"( +%% % event % %; +)", +platform_attribute, +"protected", +"abstract override", +event_type, +external_event_name +); + + } + + void write_abstract_class_property(writer& w, Property const& prop, std::string_view platform_attribute) + { + auto [getter, setter] = get_property_methods(prop); + auto prop_type = write_prop_type(w, prop); + auto external_prop_name = prop.Name(); + + w.write(R"( +%% % % % {)", +platform_attribute, +"protected", +"abstract override", +prop_type, +external_prop_name); + if (getter) + { + w.write(R"( get; )"); + } + + if (setter) + { + w.write(R"( set;)"); + } + + w.write(R"( } +)"); + } + void write_abstract_class_method(writer& w, MethodDef const& method, std::string_view platform_attribute) { + if (is_special(method)) + { + return; + } + auto method_name = method.Name(); method_signature signature{ method }; @@ -8651,22 +8700,35 @@ bind_list(", ", signature.params())); { auto type_namespace = type.TypeNamespace(); auto type_name = write_type_name_temp(w, type); + auto abstract_type_name = "Abstract" + type_name; w.write(R"( -%protected abstract class % : % -{ +%% % class % : % { )", bind(type, true), -"Abstract" + type_name, +"public", +"abstract", +abstract_type_name, type_name); + auto platform_attribute = write_platform_attribute_temp(w, type); for (auto&& method : type.MethodList()) { - write_abstract_class_method(w, method, ""); + write_abstract_class_method(w, method, platform_attribute); } - w.write(R"( -} + for (auto&& event : type.EventList()) + { + write_abstract_class_event(w, event, platform_attribute); + } + + for (auto&& prop : type.PropertyList()) + { + write_abstract_class_property(w, prop, platform_attribute); + } + + w.write(R"(} + )"); } From 3d31042c8d46fd527881322fd059890abd42369d Mon Sep 17 00:00:00 2001 From: Sophia Chen Date: Mon, 27 Jan 2025 18:38:13 -0800 Subject: [PATCH 3/5] not protected --- src/cswinrt/code_writers.h | 26 ++++++++++++++++++++------ src/cswinrt/main.cpp | 4 +++- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/cswinrt/code_writers.h b/src/cswinrt/code_writers.h index a26112822..8567b6d4a 100644 --- a/src/cswinrt/code_writers.h +++ b/src/cswinrt/code_writers.h @@ -1206,9 +1206,14 @@ namespace cswinrt auto access_spec = is_protected || is_overridable ? "protected " : "public "; std::string method_spec = ""; + if (settings.abstract_class) + { + method_spec = "virtual "; + } + // If this interface is overridable but the type is sealed, don't mark the member as virtual. // The C# compiler errors out about declaring a virtual member in a sealed class. - if (is_overridable && !class_type.Flags().Sealed() || settings.abstract_class) + if (is_overridable && !class_type.Flags().Sealed()) { // All overridable methods in the WinRT type system have protected visibility. access_spec = "protected "; @@ -1532,12 +1537,21 @@ remove => %; { auto visibility = "public "; + if (settings.abstract_class) + { + visibility = "public virtual "; + } + if (is_protected) { visibility = "protected "; + if (settings.abstract_class) + { + visibility = "protected virtual "; + } } - if (is_overridable || settings.abstract_class) + if (is_overridable) { visibility = "protected virtual "; } @@ -3458,7 +3472,7 @@ private % AsInternal(InterfaceTag<%> _) => % ?? Make_%(); { auto& [prop_type, getter_target, getter_platform, setter_target, setter_platform, is_overridable, is_public, is_private, getter_prop, setter_prop] = prop_data; if (is_private) continue; - std::string_view access_spec = (is_public && !settings.abstract_class) ? "public "sv : "protected "sv; + std::string_view access_spec = is_public ? "public "sv : "protected "sv; std::string_view method_spec = (is_overridable || settings.abstract_class)? "virtual "sv : ""sv; write_property(w, prop_name, prop_name, prop_type, getter_prop.has_value() ? w.write_temp("%", bind(getter_prop.value().first)) : getter_target, @@ -8640,7 +8654,7 @@ _defaultLazy = new Lazy<%>(() => GetDefaultReference<%.Vftbl>()); %% % event % %; )", platform_attribute, -"protected", +"public", "abstract override", event_type, external_event_name @@ -8657,7 +8671,7 @@ external_event_name w.write(R"( %% % % % {)", platform_attribute, -"protected", +"public", "abstract override", prop_type, external_prop_name); @@ -8689,7 +8703,7 @@ external_prop_name); %% % % %(%); )", platform_attribute, -"protected", +"public", "abstract override", bind(signature), method_name, diff --git a/src/cswinrt/main.cpp b/src/cswinrt/main.cpp index 5adc0f1fe..aad4a5ec9 100644 --- a/src/cswinrt/main.cpp +++ b/src/cswinrt/main.cpp @@ -238,7 +238,9 @@ Where is one or more of: } else { - write_abstract_class(w, type); + if (settings.abstract_class) { + write_abstract_class(w, type); + } write_class(w, type); add_base_type_entry(type, typeNameToBaseTypeMap); add_metadata_type_entry(type, authoredTypeNameToMetadataTypeNameMap); From b454fa783ca05b83f77c748f9adc6c97c009f923 Mon Sep 17 00:00:00 2001 From: Sophia Chen Date: Tue, 28 Jan 2025 15:57:28 -0800 Subject: [PATCH 4/5] do not generate for sealed types --- src/cswinrt/code_writers.h | 8 ++++---- src/cswinrt/main.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cswinrt/code_writers.h b/src/cswinrt/code_writers.h index 8567b6d4a..5d528aa95 100644 --- a/src/cswinrt/code_writers.h +++ b/src/cswinrt/code_writers.h @@ -1206,7 +1206,7 @@ namespace cswinrt auto access_spec = is_protected || is_overridable ? "protected " : "public "; std::string method_spec = ""; - if (settings.abstract_class) + if (settings.abstract_class && !class_type.Flags().Sealed()) { method_spec = "virtual "; } @@ -1537,7 +1537,7 @@ remove => %; { auto visibility = "public "; - if (settings.abstract_class) + if (settings.abstract_class && !class_type.Flags().Sealed()) { visibility = "public virtual "; } @@ -1545,7 +1545,7 @@ remove => %; if (is_protected) { visibility = "protected "; - if (settings.abstract_class) + if (settings.abstract_class && !class_type.Flags().Sealed()) { visibility = "protected virtual "; } @@ -3473,7 +3473,7 @@ private % AsInternal(InterfaceTag<%> _) => % ?? Make_%(); auto& [prop_type, getter_target, getter_platform, setter_target, setter_platform, is_overridable, is_public, is_private, getter_prop, setter_prop] = prop_data; if (is_private) continue; std::string_view access_spec = is_public ? "public "sv : "protected "sv; - std::string_view method_spec = (is_overridable || settings.abstract_class)? "virtual "sv : ""sv; + std::string_view method_spec = (is_overridable || (settings.abstract_class && !type.Flags().Sealed()))? "virtual "sv : ""sv; write_property(w, prop_name, prop_name, prop_type, getter_prop.has_value() ? w.write_temp("%", bind(getter_prop.value().first)) : getter_target, setter_prop.has_value() ? w.write_temp("%", bind(setter_prop.value().first)) : setter_target, diff --git a/src/cswinrt/main.cpp b/src/cswinrt/main.cpp index aad4a5ec9..0a807a610 100644 --- a/src/cswinrt/main.cpp +++ b/src/cswinrt/main.cpp @@ -238,7 +238,7 @@ Where is one or more of: } else { - if (settings.abstract_class) { + if (settings.abstract_class && !type.Flags().Sealed()) { write_abstract_class(w, type); } write_class(w, type); From 0e0887d837794449d714ca5506945c5e49fc3451 Mon Sep 17 00:00:00 2001 From: Sophia Chen Date: Wed, 12 Feb 2025 16:05:18 -0800 Subject: [PATCH 5/5] overridable, visibility, and constructor changes --- src/cswinrt/code_writers.h | 94 +++++++++++++++++++++++++++++++------- 1 file changed, 78 insertions(+), 16 deletions(-) diff --git a/src/cswinrt/code_writers.h b/src/cswinrt/code_writers.h index 5d528aa95..9a87ec272 100644 --- a/src/cswinrt/code_writers.h +++ b/src/cswinrt/code_writers.h @@ -8645,16 +8645,23 @@ _defaultLazy = new Lazy<%>(() => GetDefaultReference<%.Vftbl>()); bind(type)); } - void write_abstract_class_event(writer& w, Event const& event, std::string_view platform_attribute) + void write_abstract_class_event(writer& w, Event const& event, bool is_overridable, bool is_protected, std::string_view platform_attribute) { auto external_event_name = event.Name(); auto event_type = w.write_temp("%", bind(get_type_semantics(event.EventType()), typedef_name_type::Projected, false)); + auto visibility = "public"; + + if (is_protected || is_overridable) + { + visibility = "protected"; + } + w.write(R"( %% % event % %; )", platform_attribute, -"public", +visibility, "abstract override", event_type, external_event_name @@ -8689,21 +8696,29 @@ external_prop_name); )"); } - void write_abstract_class_method(writer& w, MethodDef const& method, std::string_view platform_attribute) + void write_abstract_class_method(writer& w, MethodDef const& method, bool is_overridable, bool is_protected, std::string_view platform_attribute) { if (is_special(method)) { return; } + auto method_name = method.Name(); method_signature signature{ method }; + auto visibility = "public"; + + if (is_protected || is_overridable) + { + visibility = "protected"; + } + w.write(R"( %% % % %(%); )", platform_attribute, -"public", +visibility, "abstract override", bind(signature), method_name, @@ -8725,21 +8740,68 @@ abstract_type_name, type_name); auto platform_attribute = write_platform_attribute_temp(w, type); + bool hasEmptyConstructor = false; + for (auto&& [interface_name, factory] : get_attributed_types(w, type)) + { + if (factory.composable) + { + for (auto&& method : factory.type.MethodList()) + { + method_signature signature{ method }; + if (signature.params().size() == 0) + { + hasEmptyConstructor = true; + } + } + } + } - for (auto&& method : type.MethodList()) - { - write_abstract_class_method(w, method, platform_attribute); - } + if (!hasEmptyConstructor) { + w.write(R"( +public %() : base(WinRT.DerivedComposed.Instance) +{ +} +)", +abstract_type_name +); + } + + + for (auto&& ii : type.InterfaceImpl()) + { + auto is_overridable = has_attribute(ii, "Windows.Foundation.Metadata", "OverridableAttribute"); + auto is_protected = has_attribute(ii, "Windows.Foundation.Metadata", "ProtectedAttribute"); + + auto semantics = get_type_semantics(ii.Interface()); + + for_typedef(w, semantics, [&](auto&& type) + { + for (auto&& method : type.MethodList()) + { + if (!is_static(method)) + { + write_abstract_class_method(w, method, is_overridable, is_protected, platform_attribute); + } + } + + for (auto&& event : type.EventList()) + { - for (auto&& event : type.EventList()) - { - write_abstract_class_event(w, event, platform_attribute); - } + if (!is_static(event.Parent())) + { + write_abstract_class_event(w, event, is_overridable, is_protected, platform_attribute); + } + } - for (auto&& prop : type.PropertyList()) - { - write_abstract_class_property(w, prop, platform_attribute); - } + for (auto&& prop : type.PropertyList()) + { + if (!is_static(prop.Parent())) + { + write_abstract_class_property(w, prop, platform_attribute); + } + } + }); + } w.write(R"(}