diff --git a/.editorconfig b/.editorconfig
index 0d64ba1..a00e5bc 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,6 +1,568 @@
+# Version: 2.0.1 (Using https://semver.org/)
+# Updated: 2020-12-11
+# See https://github.com/RehanSaeed/EditorConfig/releases for release notes.
+# See https://github.com/RehanSaeed/EditorConfig for updates to this file.
+# See http://EditorConfig.org for more information about .editorconfig files.
+
+##########################################
+# Common Settings
+##########################################
+
+# This file is the top-most EditorConfig file
+root = true
+
+# All Files
[*]
+charset = utf-8
indent_style = space
indent_size = 4
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+##########################################
+# File Extension Settings
+##########################################
+
+# Visual Studio Solution Files
+[*.sln]
+indent_style = tab
+
+# Visual Studio XML Project Files
+[*.{csproj,vbproj,vcxproj.filters,proj,projitems,shproj}]
+indent_size = 2
+
+# XML Configuration Files
+[*.{xml,config,props,targets,nuspec,resx,ruleset,vsixmanifest,vsct}]
+indent_size = 2
+
+# JSON Files
+[*.{json,json5,webmanifest}]
+indent_size = 2
+
+# YAML Files
+[*.{yml,yaml}]
+indent_size = 2
+
+# Markdown Files
+[*.md]
+trim_trailing_whitespace = false
+
+# Web Files
+[*.{htm,html,js,jsm,ts,tsx,css,sass,scss,less,svg,vue}]
+indent_size = 2
+
+# Batch Files
+[*.{cmd,bat}]
end_of_line = crlf
-charset = utf-8
-trim_trailing_whitespace = true
\ No newline at end of file
+
+# Bash Files
+[*.sh]
+end_of_line = lf
+
+# Makefiles
+[Makefile]
+indent_style = tab
+
+##########################################
+# Default .NET Code Style Severities
+# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/configuration-options#scope
+##########################################
+
+[*.{cs,csx,cake,vb,vbx}]
+# Default Severity for all .NET Code Style rules below
+dotnet_analyzer_diagnostic.severity = silent
+
+##########################################
+# File Header (Uncomment to support file headers)
+# https://docs.microsoft.com/visualstudio/ide/reference/add-file-header
+##########################################
+
+# [*.{cs,csx,cake,vb,vbx}]
+# file_header_template = \n© PROJECT-AUTHOR\n
+
+# SA1636: File header copyright text should match
+# Justification: .editorconfig supports file headers. If this is changed to a value other than "none", a stylecop.json file will need to added to the project.
+# dotnet_diagnostic.SA1636.severity = none
+
+##########################################
+# .NET Language Conventions
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions
+##########################################
+
+# .NET Code Style Settings
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#net-code-style-settings
+[*.{cs,csx,cake,vb,vbx}]
+# "this." and "Me." qualifiers
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#this-and-me
+#dotnet_style_qualification_for_field = true:warning
+#dotnet_style_qualification_for_property = true:warning
+#dotnet_style_qualification_for_method = true:warning
+#dotnet_style_qualification_for_event = true:warning
+# Language keywords instead of framework type names for type references
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#language-keywords
+dotnet_style_predefined_type_for_locals_parameters_members = true:warning
+dotnet_style_predefined_type_for_member_access = true:warning
+# Modifier preferences
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#normalize-modifiers
+dotnet_style_require_accessibility_modifiers = always:warning
+csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:warning
+visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:warning
+dotnet_style_readonly_field = true:warning
+# Parentheses preferences
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#parentheses-preferences
+dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning
+dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning
+dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning
+dotnet_style_parentheses_in_other_operators = always_for_clarity:suggestion
+# Expression-level preferences
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-level-preferences
+dotnet_style_object_initializer = true:warning
+dotnet_style_collection_initializer = true:warning
+dotnet_style_explicit_tuple_names = true:warning
+dotnet_style_prefer_inferred_tuple_names = true:warning
+dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning
+dotnet_style_prefer_auto_properties = true:warning
+dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning
+dotnet_style_prefer_conditional_expression_over_assignment = false:suggestion
+dotnet_diagnostic.IDE0045.severity = suggestion
+dotnet_style_prefer_conditional_expression_over_return = false:suggestion
+dotnet_diagnostic.IDE0046.severity = suggestion
+dotnet_style_prefer_compound_assignment = true:warning
+# Null-checking preferences
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#null-checking-preferences
+dotnet_style_coalesce_expression = true:warning
+dotnet_style_null_propagation = true:warning
+# Parameter preferences
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#parameter-preferences
+dotnet_code_quality_unused_parameters = all:warning
+# More style options (Undocumented)
+# https://github.com/MicrosoftDocs/visualstudio-docs/issues/3641
+dotnet_style_operator_placement_when_wrapping = end_of_line
+# https://github.com/dotnet/roslyn/pull/40070
+dotnet_style_prefer_simplified_interpolation = true:warning
+
+# C# Code Style Settings
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#c-code-style-settings
+[*.{cs,csx,cake}]
+# Implicit and explicit types
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#implicit-and-explicit-types
+csharp_style_var_for_built_in_types = true:warning
+csharp_style_var_when_type_is_apparent = true:warning
+csharp_style_var_elsewhere = true:warning
+# Expression-bodied members
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-bodied-members
+csharp_style_expression_bodied_methods = true:warning
+csharp_style_expression_bodied_constructors = true:warning
+csharp_style_expression_bodied_operators = true:warning
+csharp_style_expression_bodied_properties = true:warning
+csharp_style_expression_bodied_indexers = true:warning
+csharp_style_expression_bodied_accessors = true:warning
+csharp_style_expression_bodied_lambdas = true:warning
+csharp_style_expression_bodied_local_functions = true:warning
+# Pattern matching
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#pattern-matching
+csharp_style_pattern_matching_over_is_with_cast_check = true:warning
+csharp_style_pattern_matching_over_as_with_null_check = true:warning
+# Inlined variable declarations
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#inlined-variable-declarations
+csharp_style_inlined_variable_declaration = true:warning
+# Expression-level preferences
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-level-preferences
+csharp_prefer_simple_default_expression = true:warning
+# "Null" checking preferences
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#c-null-checking-preferences
+csharp_style_throw_expression = true:warning
+csharp_style_conditional_delegate_call = true:warning
+# Code block preferences
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#code-block-preferences
+csharp_prefer_braces = true:warning
+# Unused value preferences
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#unused-value-preferences
+csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion
+dotnet_diagnostic.IDE0058.severity = suggestion
+csharp_style_unused_value_assignment_preference = discard_variable:suggestion
+dotnet_diagnostic.IDE0059.severity = suggestion
+# Index and range preferences
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#index-and-range-preferences
+csharp_style_prefer_index_operator = true:warning
+csharp_style_prefer_range_operator = true:warning
+# Miscellaneous preferences
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#miscellaneous-preferences
+csharp_style_deconstructed_variable_declaration = true:warning
+csharp_style_pattern_local_over_anonymous_function = true:warning
+csharp_using_directive_placement = outside_namespace:warning
+csharp_prefer_static_local_function = true:warning
+csharp_prefer_simple_using_statement = true:suggestion
+dotnet_diagnostic.IDE0063.severity = suggestion
+
+##########################################
+# .NET Formatting Conventions
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-code-style-settings-reference#formatting-conventions
+##########################################
+
+# Organize usings
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#organize-using-directives
+dotnet_sort_system_directives_first = true
+# Newline options
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#new-line-options
+csharp_new_line_before_open_brace = all
+csharp_new_line_before_else = true
+csharp_new_line_before_catch = true
+csharp_new_line_before_finally = true
+csharp_new_line_before_members_in_object_initializers = true
+csharp_new_line_before_members_in_anonymous_types = true
+csharp_new_line_between_query_expression_clauses = true
+# Indentation options
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#indentation-options
+csharp_indent_case_contents = true
+csharp_indent_switch_labels = true
+csharp_indent_labels = no_change
+csharp_indent_block_contents = true
+csharp_indent_braces = false
+csharp_indent_case_contents_when_block = false
+# Spacing options
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#spacing-options
+csharp_space_after_cast = false
+csharp_space_after_keywords_in_control_flow_statements = true
+csharp_space_between_parentheses = false
+csharp_space_before_colon_in_inheritance_clause = true
+csharp_space_after_colon_in_inheritance_clause = true
+csharp_space_around_binary_operators = before_and_after
+csharp_space_between_method_declaration_parameter_list_parentheses = false
+csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
+csharp_space_between_method_declaration_name_and_open_parenthesis = false
+csharp_space_between_method_call_parameter_list_parentheses = false
+csharp_space_between_method_call_empty_parameter_list_parentheses = false
+csharp_space_between_method_call_name_and_opening_parenthesis = false
+csharp_space_after_comma = true
+csharp_space_before_comma = false
+csharp_space_after_dot = false
+csharp_space_before_dot = false
+csharp_space_after_semicolon_in_for_statement = true
+csharp_space_before_semicolon_in_for_statement = false
+csharp_space_around_declaration_statements = false
+csharp_space_before_open_square_brackets = false
+csharp_space_between_empty_square_brackets = false
+csharp_space_between_square_brackets = false
+# Wrapping options
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#wrap-options
+csharp_preserve_single_line_statements = false
+csharp_preserve_single_line_blocks = true
+
+csharp_style_namespace_declarations = file_scoped
+
+##########################################
+# .NET Naming Conventions
+# https://docs.microsoft.com/visualstudio/ide/editorconfig-naming-conventions
+##########################################
+
+[*.{cs,csx,cake,vb,vbx}]
+dotnet_diagnostic.CA1000.severity = suggestion
+dotnet_diagnostic.CA1001.severity = error
+dotnet_diagnostic.CA1018.severity = error
+dotnet_diagnostic.CA1036.severity = silent
+dotnet_diagnostic.CA1051.severity = suggestion
+dotnet_diagnostic.CA1068.severity = error
+dotnet_diagnostic.CA1069.severity = error
+dotnet_diagnostic.CA1304.severity = error
+dotnet_diagnostic.CA1305.severity = suggestion
+dotnet_diagnostic.CA1307.severity = suggestion
+dotnet_diagnostic.CA1309.severity = suggestion
+dotnet_diagnostic.CA1310.severity = error
+dotnet_diagnostic.CA1507.severity = suggestion
+dotnet_diagnostic.CA1513.severity = suggestion
+dotnet_diagnostic.CA1707.severity = suggestion
+dotnet_diagnostic.CA1708.severity = suggestion
+dotnet_diagnostic.CA1711.severity = suggestion
+dotnet_diagnostic.CA1716.severity = suggestion
+dotnet_diagnostic.CA1720.severity = suggestion
+dotnet_diagnostic.CA1725.severity = suggestion
+dotnet_diagnostic.CA1805.severity = suggestion
+dotnet_diagnostic.CA1816.severity = suggestion
+dotnet_diagnostic.CA1822.severity = suggestion
+dotnet_diagnostic.CA1825.severity = error
+dotnet_diagnostic.CA1826.severity = silent
+dotnet_diagnostic.CA1827.severity = error
+dotnet_diagnostic.CA1829.severity = suggestion
+dotnet_diagnostic.CA1834.severity = error
+dotnet_diagnostic.CA1845.severity = suggestion
+dotnet_diagnostic.CA1848.severity = suggestion
+dotnet_diagnostic.CA1852.severity = suggestion
+dotnet_diagnostic.CA1860.severity = silent
+dotnet_diagnostic.CA2016.severity = suggestion
+dotnet_diagnostic.CA2201.severity = error
+dotnet_diagnostic.CA2206.severity = error
+dotnet_diagnostic.CA2208.severity = error
+dotnet_diagnostic.CA2211.severity = error
+dotnet_diagnostic.CA2249.severity = error
+dotnet_diagnostic.CA2251.severity = error
+dotnet_diagnostic.CA2252.severity = none
+dotnet_diagnostic.CA2254.severity = suggestion
+
+dotnet_diagnostic.CS0169.severity = error
+dotnet_diagnostic.CS0219.severity = error
+dotnet_diagnostic.CS0649.severity = suggestion
+dotnet_diagnostic.CS1998.severity = error
+dotnet_diagnostic.CS8602.severity = error
+dotnet_diagnostic.CS8604.severity = error
+dotnet_diagnostic.CS8618.severity = error
+dotnet_diagnostic.CS0618.severity = suggestion
+dotnet_diagnostic.CS1998.severity = error
+dotnet_diagnostic.CS4014.severity = error
+dotnet_diagnostic.CS8600.severity = error
+dotnet_diagnostic.CS8603.severity = error
+dotnet_diagnostic.CS8625.severity = error
+
+dotnet_diagnostic.BL0005.severity = suggestion
+
+dotnet_diagnostic.MVC1000.severity = suggestion
+
+dotnet_diagnostic.RZ10012.severity = error
+
+dotnet_diagnostic.IDE0004.severity = error # redundant cast
+dotnet_diagnostic.IDE0005.severity = error
+dotnet_diagnostic.IDE0007.severity = error # Use var
+dotnet_diagnostic.IDE0011.severity = error # Use braces on if statements
+dotnet_diagnostic.IDE0010.severity = silent # populate switch
+dotnet_diagnostic.IDE0017.severity = suggestion # initialization can be simplified
+dotnet_diagnostic.IDE0021.severity = silent # expression body for constructors
+dotnet_diagnostic.IDE0022.severity = silent # expression body for methods
+dotnet_diagnostic.IDE0023.severity = suggestion # use expression body for operators
+dotnet_diagnostic.IDE0024.severity = silent # expression body for operators
+dotnet_diagnostic.IDE0025.severity = suggestion # use expression body for properties
+dotnet_diagnostic.IDE0027.severity = suggestion # Use expression body for accessors
+dotnet_diagnostic.IDE0028.severity = silent # expression body for accessors
+dotnet_diagnostic.IDE0032.severity = suggestion # Use auto property
+dotnet_diagnostic.IDE0033.severity = error # prefer tuple name
+dotnet_diagnostic.IDE0037.severity = suggestion # simplify anonymous type
+dotnet_diagnostic.IDE0040.severity = error # modifiers required
+dotnet_diagnostic.IDE0041.severity = error # simplify null
+dotnet_diagnostic.IDE0042.severity = error # deconstruct variable
+dotnet_diagnostic.IDE0044.severity = suggestion # make field only when possible
+dotnet_diagnostic.IDE0047.severity = suggestion # parameter name
+dotnet_diagnostic.IDE0051.severity = error # unused field
+dotnet_diagnostic.IDE0052.severity = error # unused member
+dotnet_diagnostic.IDE0053.severity = suggestion # lambda not needed
+dotnet_diagnostic.IDE0055.severity = suggestion # Fix formatting
+dotnet_diagnostic.IDE0057.severity = suggestion # substring can be simplified
+dotnet_diagnostic.IDE0060.severity = suggestion # unused parameters
+dotnet_diagnostic.IDE0061.severity = suggestion # local expression body
+dotnet_diagnostic.IDE0062.severity = suggestion # local to static
+dotnet_diagnostic.IDE0063.severity = error # simplify using
+dotnet_diagnostic.IDE0066.severity = suggestion # switch expression
+dotnet_diagnostic.IDE0072.severity = suggestion # Populate switch - forces population of all cases even when default specified
+dotnet_diagnostic.IDE0078.severity = suggestion # use pattern matching
+dotnet_diagnostic.IDE0090.severity = suggestion # new can be simplified
+dotnet_diagnostic.IDE0130.severity = suggestion # namespace folder structure
+dotnet_diagnostic.IDE0160.severity = silent # Use block namespaces ARE NOT required
+dotnet_diagnostic.IDE0161.severity = error # Please use file namespaces
+dotnet_diagnostic.IDE0200.severity = suggestion # lambda not needed
+dotnet_diagnostic.IDE1006.severity = suggestion # Naming rule violation: These words cannot contain lower case characters
+dotnet_diagnostic.IDE0260.severity = suggestion # Use pattern matching
+dotnet_diagnostic.IDE0270.severity = suggestion # Null check simplifcation
+dotnet_diagnostic.IDE0290.severity = error # Primary Constructor
+dotnet_diagnostic.IDE0300.severity = suggestion # Collection
+dotnet_diagnostic.IDE0305.severity = suggestion # Collection ToList
+
+dotnet_diagnostic.NX0001.severity = error
+dotnet_diagnostic.NX0002.severity = silent
+dotnet_diagnostic.NX0003.severity = silent
+
+##########################################
+# Styles
+##########################################
+
+# camel_case_style - Define the camelCase style
+dotnet_naming_style.camel_case_style.capitalization = camel_case
+# pascal_case_style - Define the PascalCase style
+dotnet_naming_style.pascal_case_style.capitalization = pascal_case
+# constant_case - Define the CONSTANT_CASE style
+dotnet_naming_style.constant_case.capitalization = all_upper
+dotnet_naming_style.constant_case.word_separator = _
+# first_upper_style - The first character must start with an upper-case character
+dotnet_naming_style.first_upper_style.capitalization = first_word_upper
+# prefix_interface_with_i_style - Interfaces must be PascalCase and the first character of an interface must be an 'I'
+dotnet_naming_style.prefix_interface_with_i_style.capitalization = pascal_case
+dotnet_naming_style.prefix_interface_with_i_style.required_prefix = I
+# prefix_type_parameters_with_t_style - Generic Type Parameters must be PascalCase and the first character must be a 'T'
+dotnet_naming_style.prefix_type_parameters_with_t_style.capitalization = pascal_case
+dotnet_naming_style.prefix_type_parameters_with_t_style.required_prefix = T
+# disallowed_style - Anything that has this style applied is marked as disallowed
+dotnet_naming_style.disallowed_style.capitalization = pascal_case
+dotnet_naming_style.disallowed_style.required_prefix = ____RULE_VIOLATION____
+dotnet_naming_style.disallowed_style.required_suffix = ____RULE_VIOLATION____
+# internal_error_style - This style should never occur... if it does, it indicates a bug in file or in the parser using the file
+dotnet_naming_style.internal_error_style.capitalization = pascal_case
+dotnet_naming_style.internal_error_style.required_prefix = ____INTERNAL_ERROR____
+dotnet_naming_style.internal_error_style.required_suffix = ____INTERNAL_ERROR____
+
+# prefix_interface_with_i_style - Interfaces must be PascalCase and the first character of an interface must be an 'I'
+dotnet_naming_style.underscore_camel_case_style.capitalization = camel_case
+dotnet_naming_style.underscore_camel_case_style.required_prefix = _
+
+##########################################
+# .NET Design Guideline Field Naming Rules
+# Naming rules for fields follow the .NET Framework design guidelines
+# https://docs.microsoft.com/dotnet/standard/design-guidelines/index
+##########################################
+
+# All public/protected/protected_internal constant fields must be constant_case
+# https://docs.microsoft.com/dotnet/standard/design-guidelines/field
+dotnet_naming_symbols.public_protected_constant_fields_group.applicable_accessibilities = public, protected, protected_internal
+dotnet_naming_symbols.public_protected_constant_fields_group.required_modifiers = const
+dotnet_naming_symbols.public_protected_constant_fields_group.applicable_kinds = field
+dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.symbols = public_protected_constant_fields_group
+dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.style = constant_case
+dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.severity = warning
+
+# All public/protected/protected_internal static readonly fields must be constant_case
+# https://docs.microsoft.com/dotnet/standard/design-guidelines/field
+dotnet_naming_symbols.public_protected_static_readonly_fields_group.applicable_accessibilities = public, protected, protected_internal
+dotnet_naming_symbols.public_protected_static_readonly_fields_group.required_modifiers = static, readonly
+dotnet_naming_symbols.public_protected_static_readonly_fields_group.applicable_kinds = field
+dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.symbols = public_protected_static_readonly_fields_group
+dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.style = constant_case
+dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.severity = warning
+
+# No other public/protected/protected_internal fields are allowed
+# https://docs.microsoft.com/dotnet/standard/design-guidelines/field
+dotnet_naming_symbols.other_public_protected_fields_group.applicable_accessibilities = public, protected, protected_internal
+dotnet_naming_symbols.other_public_protected_fields_group.applicable_kinds = field
+dotnet_naming_rule.other_public_protected_fields_disallowed_rule.symbols = other_public_protected_fields_group
+dotnet_naming_rule.other_public_protected_fields_disallowed_rule.style = disallowed_style
+dotnet_naming_rule.other_public_protected_fields_disallowed_rule.severity = error
+
+##########################################
+# StyleCop Field Naming Rules
+# Naming rules for fields follow the StyleCop analyzers
+# This does not override any rules using disallowed_style above
+# https://github.com/DotNetAnalyzers/StyleCopAnalyzers
+##########################################
+
+# All constant fields must be constant_case
+# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1303.md
+dotnet_naming_symbols.stylecop_constant_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected, private
+dotnet_naming_symbols.stylecop_constant_fields_group.required_modifiers = const
+dotnet_naming_symbols.stylecop_constant_fields_group.applicable_kinds = field
+dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.symbols = stylecop_constant_fields_group
+dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.style = constant_case
+dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.severity = warning
+
+# All static readonly fields must be constant_case
+# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1311.md
+dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected, private
+dotnet_naming_symbols.stylecop_static_readonly_fields_group.required_modifiers = static, readonly
+dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_kinds = field
+dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.symbols = stylecop_static_readonly_fields_group
+dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.style = constant_case
+dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.severity = warning
+
+# No non-private instance fields are allowed
+# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1401.md
+dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected
+dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_kinds = field
+dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.symbols = stylecop_fields_must_be_private_group
+dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.style = disallowed_style
+dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.severity = error
+
+# Private fields must be camelCase
+# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1306.md
+dotnet_naming_symbols.stylecop_private_fields_group.applicable_accessibilities = private
+dotnet_naming_symbols.stylecop_private_fields_group.applicable_kinds = field
+dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.symbols = stylecop_private_fields_group
+dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.style = underscore_camel_case_style
+dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.severity = warning
+
+# Local variables must be camelCase
+# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1312.md
+dotnet_naming_symbols.stylecop_local_fields_group.applicable_accessibilities = local
+dotnet_naming_symbols.stylecop_local_fields_group.applicable_kinds = local
+dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.symbols = stylecop_local_fields_group
+dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.style = camel_case_style
+dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.severity = warning
+
+# This rule should never fire. However, it's included for at least two purposes:
+# First, it helps to understand, reason about, and root-case certain types of issues, such as bugs in .editorconfig parsers.
+# Second, it helps to raise immediate awareness if a new field type is added (as occurred recently in C#).
+dotnet_naming_symbols.sanity_check_uncovered_field_case_group.applicable_accessibilities = *
+dotnet_naming_symbols.sanity_check_uncovered_field_case_group.applicable_kinds = field
+dotnet_naming_rule.sanity_check_uncovered_field_case_rule.symbols = sanity_check_uncovered_field_case_group
+dotnet_naming_rule.sanity_check_uncovered_field_case_rule.style = internal_error_style
+dotnet_naming_rule.sanity_check_uncovered_field_case_rule.severity = error
+
+
+##########################################
+# Other Naming Rules
+##########################################
+
+# All of the following must be PascalCase:
+# - Namespaces
+# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-namespaces
+# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1300.md
+# - Classes and Enumerations
+# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces
+# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1300.md
+# - Delegates
+# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces#names-of-common-types
+# - Constructors, Properties, Events, Methods
+# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-type-members
+dotnet_naming_symbols.element_group.applicable_kinds = namespace, class, enum, struct, delegate, event, method, property
+dotnet_naming_rule.element_rule.symbols = element_group
+dotnet_naming_rule.element_rule.style = pascal_case_style
+dotnet_naming_rule.element_rule.severity = warning
+
+# Interfaces use PascalCase and are prefixed with uppercase 'I'
+# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces
+dotnet_naming_symbols.interface_group.applicable_kinds = interface
+dotnet_naming_rule.interface_rule.symbols = interface_group
+dotnet_naming_rule.interface_rule.style = prefix_interface_with_i_style
+dotnet_naming_rule.interface_rule.severity = warning
+
+# Generics Type Parameters use PascalCase and are prefixed with uppercase 'T'
+# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces
+dotnet_naming_symbols.type_parameter_group.applicable_kinds = type_parameter
+dotnet_naming_rule.type_parameter_rule.symbols = type_parameter_group
+dotnet_naming_rule.type_parameter_rule.style = prefix_type_parameters_with_t_style
+dotnet_naming_rule.type_parameter_rule.severity = warning
+
+# Function parameters use camelCase
+# https://docs.microsoft.com/dotnet/standard/design-guidelines/naming-parameters
+dotnet_naming_symbols.parameters_group.applicable_kinds = parameter
+dotnet_naming_rule.parameters_rule.symbols = parameters_group
+dotnet_naming_rule.parameters_rule.style = camel_case_style
+dotnet_naming_rule.parameters_rule.severity = warning
+
+##########################################
+# License
+##########################################
+# The following applies as to the .editorconfig file ONLY, and is
+# included below for reference, per the requirements of the license
+# corresponding to this .editorconfig file.
+# See: https://github.com/RehanSaeed/EditorConfig
+#
+# MIT License
+#
+# Copyright (c) 2017-2019 Muhammad Rehan Saeed
+# Copyright (c) 2019 Henry Gabryjelski
+#
+# Permission is hereby granted, free of charge, to any
+# person obtaining a copy of this software and associated
+# documentation files (the "Software"), to deal in the
+# Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute,
+# sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject
+# to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+##########################################
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
deleted file mode 100644
index 78f0f48..0000000
--- a/.github/FUNDING.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-# These are supported funding model platforms
-
-github: [StefH]
-patreon: # Replace with a single Patreon username
-open_collective: # wiremocknet
-ko_fi: # Replace with a single Ko-fi username
-tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
-community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
-liberapay: # Replace with a single Liberapay username
-issuehunt: # Replace with a single IssueHunt username
-otechie: # Replace with a single Otechie username
-custom: https://www.paypal.me/stefheyenrath
\ No newline at end of file
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..3413224
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,6 @@
+version: 2
+updates:
+ - package-ecosystem: "github-actions" # search for actions - there are other options available
+ directory: "/" # search in .github/workflows under root `/`
+ schedule:
+ interval: "weekly" # check for action update every week
\ No newline at end of file
diff --git a/.github/workflows/CreateRelease.yml b/.github/workflows/CreateRelease.yml
deleted file mode 100644
index fc7a348..0000000
--- a/.github/workflows/CreateRelease.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-name: CreateRelease
-
-on:
- push:
- tags:
- - "*.*.*"
-
-jobs:
- build:
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v2
- - name: Release
- uses: softprops/action-gh-release@v1
diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml
new file mode 100644
index 0000000..f5e8b3d
--- /dev/null
+++ b/.github/workflows/nuget.yml
@@ -0,0 +1,34 @@
+name: "Deploy to Nuget.org"
+
+on:
+ workflow_dispatch:
+
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+ env:
+ DOTNET_CLI_TELEMETRY_OPTOUT: true
+
+ steps:
+ - name: Checkout Project
+ uses: actions/checkout@v4
+
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: 8.0.x
+
+ - name: Restore dependencies
+ run: dotnet restore
+
+ - name: Build
+ run: dotnet build --configuration Release --no-restore
+
+ - name: Test
+ run: dotnet test --no-build --configuration Release --verbosity normal
+
+ - name: Pack
+ run: dotnet pack --no-build --configuration Release Speckle.InterfaceGenerator/Speckle.InterfaceGenerator.csproj --output .
+
+ - name: Push to nuget.org
+ run: dotnet nuget push *.nupkg --source "https://api.nuget.org/v3/index.json" --api-key ${{secrets.CONNECTORS_NUGET_TOKEN }} --skip-duplicate
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 313797d..78e8c22 100644
--- a/.gitignore
+++ b/.gitignore
@@ -350,4 +350,6 @@ MigrationBackup/
.ionide/
/tests/ProxyInterfaceSourceGeneratorTests/Destination/Disposable/*.g.cs
-.idea/.idea.ProxyInterfaceSourceGenerator Solution/.idea/
+.idea/
+
+Speckle.ProxyGenerator.sln.DotSettings
diff --git a/ProxyInterfaceSourceGenerator Solution.sln.DotSettings b/ProxyInterfaceSourceGenerator Solution.sln.DotSettings
deleted file mode 100644
index 860b238..0000000
--- a/ProxyInterfaceSourceGenerator Solution.sln.DotSettings
+++ /dev/null
@@ -1,3 +0,0 @@
-
- True
- True
\ No newline at end of file
diff --git a/ProxyInterfaceSourceGenerator Solution.sln b/Speckle.ProxyGenerator.sln
similarity index 95%
rename from ProxyInterfaceSourceGenerator Solution.sln
rename to Speckle.ProxyGenerator.sln
index 56171fc..971f104 100644
--- a/ProxyInterfaceSourceGenerator Solution.sln
+++ b/Speckle.ProxyGenerator.sln
@@ -1,93 +1,93 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.0.31521.260
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{ED3DA9DD-1E07-444B-A2D7-2DBA280F96D4}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2CE637DC-E8F5-4603-8B57-E51A32F631F1}"
- ProjectSection(SolutionItems) = preProject
- .editorconfig = .editorconfig
- Generate-ReleaseNotes.bat = Generate-ReleaseNotes.bat
- PackageReadme.md = PackageReadme.md
- PackageReleaseNotes.template = PackageReleaseNotes.template
- PackageReleaseNotes.txt = PackageReleaseNotes.txt
- README.md = README.md
- ReleaseNotes.md = ReleaseNotes.md
- ToDo.md = ToDo.md
- EndProjectSection
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{19009F5B-3267-45E2-A8B6-89F2AB47D72C}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src-examples", "src-examples", "{38BA087F-EDA1-4F8A-A140-85B84791B815}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProxyInterfaceSourceGenerator", "src\ProxyInterfaceSourceGenerator\ProxyInterfaceSourceGenerator.csproj", "{12344228-91F4-4502-9595-39584E5ABB34}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProxyInterfaceConsumer", "src-examples\ProxyInterfaceConsumer\ProxyInterfaceConsumer.csproj", "{7E0A10EE-CCC3-4281-9541-B0AF037D3DF9}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProxyInterfaceSourceGeneratorTests", "tests\ProxyInterfaceSourceGeneratorTests\ProxyInterfaceSourceGeneratorTests.csproj", "{1BDB9046-D6D1-4FB4-AAB5-F24E33EEAE0A}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProxyInterfaceConsumerForPnP", "src-examples\ProxyInterfaceConsumerForPnP\ProxyInterfaceConsumerForPnP.csproj", "{5F7DA2C5-B908-4B57-9F5F-BADF1216D89C}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProxyInterfaceConsumerForAkka", "src-examples\ProxyInterfaceConsumerForAkka\ProxyInterfaceConsumerForAkka.csproj", "{590908DF-A813-467A-94E4-3500020D0D54}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProxyInterfaceConsumerViaNuGet", "src-examples\ProxyInterfaceConsumerViaNuGet\ProxyInterfaceConsumerViaNuGet.csproj", "{1EA000E4-6103-4577-8D98-BDDA3BE458A2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- DebugAttach|Any CPU = DebugAttach|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {12344228-91F4-4502-9595-39584E5ABB34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {12344228-91F4-4502-9595-39584E5ABB34}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {12344228-91F4-4502-9595-39584E5ABB34}.DebugAttach|Any CPU.ActiveCfg = DebugAttach|Any CPU
- {12344228-91F4-4502-9595-39584E5ABB34}.DebugAttach|Any CPU.Build.0 = DebugAttach|Any CPU
- {12344228-91F4-4502-9595-39584E5ABB34}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {12344228-91F4-4502-9595-39584E5ABB34}.Release|Any CPU.Build.0 = Release|Any CPU
- {7E0A10EE-CCC3-4281-9541-B0AF037D3DF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {7E0A10EE-CCC3-4281-9541-B0AF037D3DF9}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {7E0A10EE-CCC3-4281-9541-B0AF037D3DF9}.DebugAttach|Any CPU.ActiveCfg = Debug|Any CPU
- {7E0A10EE-CCC3-4281-9541-B0AF037D3DF9}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {7E0A10EE-CCC3-4281-9541-B0AF037D3DF9}.Release|Any CPU.Build.0 = Release|Any CPU
- {1BDB9046-D6D1-4FB4-AAB5-F24E33EEAE0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {1BDB9046-D6D1-4FB4-AAB5-F24E33EEAE0A}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {1BDB9046-D6D1-4FB4-AAB5-F24E33EEAE0A}.DebugAttach|Any CPU.ActiveCfg = DebugAttach|Any CPU
- {1BDB9046-D6D1-4FB4-AAB5-F24E33EEAE0A}.DebugAttach|Any CPU.Build.0 = DebugAttach|Any CPU
- {1BDB9046-D6D1-4FB4-AAB5-F24E33EEAE0A}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {1BDB9046-D6D1-4FB4-AAB5-F24E33EEAE0A}.Release|Any CPU.Build.0 = Release|Any CPU
- {5F7DA2C5-B908-4B57-9F5F-BADF1216D89C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {5F7DA2C5-B908-4B57-9F5F-BADF1216D89C}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {5F7DA2C5-B908-4B57-9F5F-BADF1216D89C}.DebugAttach|Any CPU.ActiveCfg = Debug|Any CPU
- {5F7DA2C5-B908-4B57-9F5F-BADF1216D89C}.DebugAttach|Any CPU.Build.0 = Debug|Any CPU
- {5F7DA2C5-B908-4B57-9F5F-BADF1216D89C}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {5F7DA2C5-B908-4B57-9F5F-BADF1216D89C}.Release|Any CPU.Build.0 = Release|Any CPU
- {590908DF-A813-467A-94E4-3500020D0D54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {590908DF-A813-467A-94E4-3500020D0D54}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {590908DF-A813-467A-94E4-3500020D0D54}.DebugAttach|Any CPU.ActiveCfg = Debug|Any CPU
- {590908DF-A813-467A-94E4-3500020D0D54}.DebugAttach|Any CPU.Build.0 = Debug|Any CPU
- {590908DF-A813-467A-94E4-3500020D0D54}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {590908DF-A813-467A-94E4-3500020D0D54}.Release|Any CPU.Build.0 = Release|Any CPU
- {1EA000E4-6103-4577-8D98-BDDA3BE458A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {1EA000E4-6103-4577-8D98-BDDA3BE458A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {1EA000E4-6103-4577-8D98-BDDA3BE458A2}.DebugAttach|Any CPU.ActiveCfg = Debug|Any CPU
- {1EA000E4-6103-4577-8D98-BDDA3BE458A2}.DebugAttach|Any CPU.Build.0 = Debug|Any CPU
- {1EA000E4-6103-4577-8D98-BDDA3BE458A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {1EA000E4-6103-4577-8D98-BDDA3BE458A2}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(NestedProjects) = preSolution
- {12344228-91F4-4502-9595-39584E5ABB34} = {ED3DA9DD-1E07-444B-A2D7-2DBA280F96D4}
- {7E0A10EE-CCC3-4281-9541-B0AF037D3DF9} = {38BA087F-EDA1-4F8A-A140-85B84791B815}
- {1BDB9046-D6D1-4FB4-AAB5-F24E33EEAE0A} = {19009F5B-3267-45E2-A8B6-89F2AB47D72C}
- {5F7DA2C5-B908-4B57-9F5F-BADF1216D89C} = {38BA087F-EDA1-4F8A-A140-85B84791B815}
- {590908DF-A813-467A-94E4-3500020D0D54} = {38BA087F-EDA1-4F8A-A140-85B84791B815}
- {1EA000E4-6103-4577-8D98-BDDA3BE458A2} = {38BA087F-EDA1-4F8A-A140-85B84791B815}
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {585F071D-051D-441C-9C6B-226D9E15A1F5}
- EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31521.260
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{ED3DA9DD-1E07-444B-A2D7-2DBA280F96D4}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2CE637DC-E8F5-4603-8B57-E51A32F631F1}"
+ ProjectSection(SolutionItems) = preProject
+ .editorconfig = .editorconfig
+ Generate-ReleaseNotes.bat = Generate-ReleaseNotes.bat
+ PackageReadme.md = PackageReadme.md
+ PackageReleaseNotes.template = PackageReleaseNotes.template
+ PackageReleaseNotes.txt = PackageReleaseNotes.txt
+ README.md = README.md
+ ReleaseNotes.md = ReleaseNotes.md
+ ToDo.md = ToDo.md
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{19009F5B-3267-45E2-A8B6-89F2AB47D72C}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src-examples", "src-examples", "{38BA087F-EDA1-4F8A-A140-85B84791B815}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speckle.ProxyGenerator", "src\Speckle.ProxyGenerator\Speckle.ProxyGenerator.csproj", "{12344228-91F4-4502-9595-39584E5ABB34}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProxyInterfaceConsumer", "src-examples\ProxyInterfaceConsumer\ProxyInterfaceConsumer.csproj", "{7E0A10EE-CCC3-4281-9541-B0AF037D3DF9}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProxyInterfaceSourceGeneratorTests", "tests\ProxyInterfaceSourceGeneratorTests\ProxyInterfaceSourceGeneratorTests.csproj", "{1BDB9046-D6D1-4FB4-AAB5-F24E33EEAE0A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProxyInterfaceConsumerForPnP", "src-examples\ProxyInterfaceConsumerForPnP\ProxyInterfaceConsumerForPnP.csproj", "{5F7DA2C5-B908-4B57-9F5F-BADF1216D89C}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProxyInterfaceConsumerForAkka", "src-examples\ProxyInterfaceConsumerForAkka\ProxyInterfaceConsumerForAkka.csproj", "{590908DF-A813-467A-94E4-3500020D0D54}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProxyInterfaceConsumerViaNuGet", "src-examples\ProxyInterfaceConsumerViaNuGet\ProxyInterfaceConsumerViaNuGet.csproj", "{1EA000E4-6103-4577-8D98-BDDA3BE458A2}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ DebugAttach|Any CPU = DebugAttach|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {12344228-91F4-4502-9595-39584E5ABB34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {12344228-91F4-4502-9595-39584E5ABB34}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {12344228-91F4-4502-9595-39584E5ABB34}.DebugAttach|Any CPU.ActiveCfg = DebugAttach|Any CPU
+ {12344228-91F4-4502-9595-39584E5ABB34}.DebugAttach|Any CPU.Build.0 = DebugAttach|Any CPU
+ {12344228-91F4-4502-9595-39584E5ABB34}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {12344228-91F4-4502-9595-39584E5ABB34}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7E0A10EE-CCC3-4281-9541-B0AF037D3DF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7E0A10EE-CCC3-4281-9541-B0AF037D3DF9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7E0A10EE-CCC3-4281-9541-B0AF037D3DF9}.DebugAttach|Any CPU.ActiveCfg = Debug|Any CPU
+ {7E0A10EE-CCC3-4281-9541-B0AF037D3DF9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7E0A10EE-CCC3-4281-9541-B0AF037D3DF9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1BDB9046-D6D1-4FB4-AAB5-F24E33EEAE0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1BDB9046-D6D1-4FB4-AAB5-F24E33EEAE0A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1BDB9046-D6D1-4FB4-AAB5-F24E33EEAE0A}.DebugAttach|Any CPU.ActiveCfg = DebugAttach|Any CPU
+ {1BDB9046-D6D1-4FB4-AAB5-F24E33EEAE0A}.DebugAttach|Any CPU.Build.0 = DebugAttach|Any CPU
+ {1BDB9046-D6D1-4FB4-AAB5-F24E33EEAE0A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1BDB9046-D6D1-4FB4-AAB5-F24E33EEAE0A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5F7DA2C5-B908-4B57-9F5F-BADF1216D89C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5F7DA2C5-B908-4B57-9F5F-BADF1216D89C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5F7DA2C5-B908-4B57-9F5F-BADF1216D89C}.DebugAttach|Any CPU.ActiveCfg = Debug|Any CPU
+ {5F7DA2C5-B908-4B57-9F5F-BADF1216D89C}.DebugAttach|Any CPU.Build.0 = Debug|Any CPU
+ {5F7DA2C5-B908-4B57-9F5F-BADF1216D89C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5F7DA2C5-B908-4B57-9F5F-BADF1216D89C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {590908DF-A813-467A-94E4-3500020D0D54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {590908DF-A813-467A-94E4-3500020D0D54}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {590908DF-A813-467A-94E4-3500020D0D54}.DebugAttach|Any CPU.ActiveCfg = Debug|Any CPU
+ {590908DF-A813-467A-94E4-3500020D0D54}.DebugAttach|Any CPU.Build.0 = Debug|Any CPU
+ {590908DF-A813-467A-94E4-3500020D0D54}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {590908DF-A813-467A-94E4-3500020D0D54}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1EA000E4-6103-4577-8D98-BDDA3BE458A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1EA000E4-6103-4577-8D98-BDDA3BE458A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1EA000E4-6103-4577-8D98-BDDA3BE458A2}.DebugAttach|Any CPU.ActiveCfg = Debug|Any CPU
+ {1EA000E4-6103-4577-8D98-BDDA3BE458A2}.DebugAttach|Any CPU.Build.0 = Debug|Any CPU
+ {1EA000E4-6103-4577-8D98-BDDA3BE458A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1EA000E4-6103-4577-8D98-BDDA3BE458A2}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {12344228-91F4-4502-9595-39584E5ABB34} = {ED3DA9DD-1E07-444B-A2D7-2DBA280F96D4}
+ {7E0A10EE-CCC3-4281-9541-B0AF037D3DF9} = {38BA087F-EDA1-4F8A-A140-85B84791B815}
+ {1BDB9046-D6D1-4FB4-AAB5-F24E33EEAE0A} = {19009F5B-3267-45E2-A8B6-89F2AB47D72C}
+ {5F7DA2C5-B908-4B57-9F5F-BADF1216D89C} = {38BA087F-EDA1-4F8A-A140-85B84791B815}
+ {590908DF-A813-467A-94E4-3500020D0D54} = {38BA087F-EDA1-4F8A-A140-85B84791B815}
+ {1EA000E4-6103-4577-8D98-BDDA3BE458A2} = {38BA087F-EDA1-4F8A-A140-85B84791B815}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {585F071D-051D-441C-9C6B-226D9E15A1F5}
+ EndGlobalSection
+EndGlobal
diff --git a/global.json b/global.json
new file mode 100644
index 0000000..18b689d
--- /dev/null
+++ b/global.json
@@ -0,0 +1,7 @@
+{
+ "sdk": {
+ "version": "8.0.0",
+ "rollForward": "latestMinor",
+ "allowPrerelease": false
+ }
+}
diff --git a/omnisharp.json b/omnisharp.json
deleted file mode 100644
index 0bad48f..0000000
--- a/omnisharp.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "RoslynExtensionsOptions": {
- "enableAnalyzersSupport": true
- }
-}
\ No newline at end of file
diff --git a/src-examples/ProxyInterfaceConsumer/Address.cs b/src-examples/ProxyInterfaceConsumer/Address.cs
index f440fc2..cc6333a 100644
--- a/src-examples/ProxyInterfaceConsumer/Address.cs
+++ b/src-examples/ProxyInterfaceConsumer/Address.cs
@@ -1,4 +1,5 @@
using System;
+using System.Diagnostics.CodeAnalysis;
namespace ProxyInterfaceConsumer
{
@@ -6,11 +7,12 @@ namespace ProxyInterfaceConsumer
{
public int HouseNumber { get; set; }
- public event EventHandler MyEvent;
+ [SuppressMessage("ReSharper", "NullableWarningSuppressionIsUsed")]
+ public event EventHandler MyEvent = null!;
public int Weird { get; set; }
public int Weird2()
{
return 0;
}
}
-}
\ No newline at end of file
+}
diff --git a/src-examples/ProxyInterfaceConsumer/Person.cs b/src-examples/ProxyInterfaceConsumer/Person.cs
index 209f687..f1d4b25 100644
--- a/src-examples/ProxyInterfaceConsumer/Person.cs
+++ b/src-examples/ProxyInterfaceConsumer/Person.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
namespace ProxyInterfaceConsumer
@@ -8,24 +9,29 @@ namespace ProxyInterfaceConsumer
private int PrivateId { get; }
public int Id { get; }
- public object @object { get; set; }
+ [SuppressMessage("ReSharper", "NullableWarningSuppressionIsUsed")]
+ public object @object { get; set; }= null!;
public long? NullableLong { get; }
- public string Name { get; set; }
+ [SuppressMessage("ReSharper", "NullableWarningSuppressionIsUsed")]
+ public string Name { get; set; }= null!;
public string? StringNullable { get; set; }
- public Address Address { get; set; }
+ [SuppressMessage("ReSharper", "NullableWarningSuppressionIsUsed")]
+ public Address Address { get; set; }= null!;
- public List AddressesList { get; set; }
+ [SuppressMessage("ReSharper", "NullableWarningSuppressionIsUsed")]
+ public List AddressesList { get; set; }= null!;
public Dictionary AddressesDict { get; set; } = new Dictionary();
public Dictionary AddressesDict2 { get; set; } = new Dictionary();
public E E { get; set; }
- public IMyInterface MyInterface { get; set; }
+ [SuppressMessage("ReSharper", "NullableWarningSuppressionIsUsed")]
+ public IMyInterface MyInterface { get; set; }= null!;
public bool TMethod(int x, T1 t1, T2 t2)
where T1 : struct
@@ -102,4 +108,4 @@ namespace ProxyInterfaceConsumer
V1,
V2
}
-}
\ No newline at end of file
+}
diff --git a/src-examples/ProxyInterfaceConsumer/Program.cs b/src-examples/ProxyInterfaceConsumer/Program.cs
index 35e7a76..79a5759 100644
--- a/src-examples/ProxyInterfaceConsumer/Program.cs
+++ b/src-examples/ProxyInterfaceConsumer/Program.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
@@ -65,9 +66,10 @@ public class Test
{
public int Id { get; set; }
- public Clazz C { get; }
+ [SuppressMessage("ReSharper", "NullableWarningSuppressionIsUsed")]
+ public Clazz C { get; } = null!;
- public IList Cs { get; set; }
+ public IList Cs { get; set; } = new List();
public int AddString(string s)
{
@@ -87,7 +89,7 @@ public class Test
public sealed class Clazz
{
- public string Name { get; set; }
+ public string Name { get; set; } = string.Empty;
}
[ProxyInterfaceGenerator.Proxy(typeof(Test))]
@@ -98,4 +100,4 @@ public partial interface ITest
[ProxyInterfaceGenerator.Proxy(typeof(Clazz))]
public partial interface IClazz
{
-}
\ No newline at end of file
+}
diff --git a/src-examples/ProxyInterfaceConsumer/ProxyInterfaceConsumer.csproj b/src-examples/ProxyInterfaceConsumer/ProxyInterfaceConsumer.csproj
index acaa276..9f03ec9 100644
--- a/src-examples/ProxyInterfaceConsumer/ProxyInterfaceConsumer.csproj
+++ b/src-examples/ProxyInterfaceConsumer/ProxyInterfaceConsumer.csproj
@@ -24,7 +24,7 @@
-
+
\ No newline at end of file
diff --git a/src-examples/ProxyInterfaceConsumerForAkka/Program.cs b/src-examples/ProxyInterfaceConsumerForAkka/Program.cs
index 7171963..4849601 100644
--- a/src-examples/ProxyInterfaceConsumerForAkka/Program.cs
+++ b/src-examples/ProxyInterfaceConsumerForAkka/Program.cs
@@ -1,3 +1,4 @@
+using System.Diagnostics.CodeAnalysis;
using Akka.Actor;
using ProxyInterfaceConsumerForAkka.Interfaces;
@@ -5,12 +6,13 @@ namespace ProxyInterfaceConsumerForAkka;
public class Program
{
+ [SuppressMessage("ReSharper", "NullableWarningSuppressionIsUsed")]
public static void Main()
{
- Akka.Remote.AddressUid auid = null;
+ Akka.Remote.AddressUid auid = null!;
IAddressUid addressUidProxy = new AddressUidProxy(auid);
- LocalActorRefProvider p = null;
+ LocalActorRefProvider p = null!;
ILocalActorRefProvider proxy = new LocalActorRefProviderProxy(p);
}
-}
\ No newline at end of file
+}
diff --git a/src-examples/ProxyInterfaceConsumerForAkka/ProxyInterfaceConsumerForAkka.csproj b/src-examples/ProxyInterfaceConsumerForAkka/ProxyInterfaceConsumerForAkka.csproj
index c79aed1..2c28d19 100644
--- a/src-examples/ProxyInterfaceConsumerForAkka/ProxyInterfaceConsumerForAkka.csproj
+++ b/src-examples/ProxyInterfaceConsumerForAkka/ProxyInterfaceConsumerForAkka.csproj
@@ -24,7 +24,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
-->
-
+
\ No newline at end of file
diff --git a/src-examples/ProxyInterfaceConsumerForPnP/ProxyInterfaceConsumerForPnP.csproj b/src-examples/ProxyInterfaceConsumerForPnP/ProxyInterfaceConsumerForPnP.csproj
index 33321fc..573790a 100644
--- a/src-examples/ProxyInterfaceConsumerForPnP/ProxyInterfaceConsumerForPnP.csproj
+++ b/src-examples/ProxyInterfaceConsumerForPnP/ProxyInterfaceConsumerForPnP.csproj
@@ -20,7 +20,7 @@
-
+
diff --git a/src-examples/ProxyInterfaceConsumerViaNuGet/Person.cs b/src-examples/ProxyInterfaceConsumerViaNuGet/Person.cs
index b999002..68f67d4 100644
--- a/src-examples/ProxyInterfaceConsumerViaNuGet/Person.cs
+++ b/src-examples/ProxyInterfaceConsumerViaNuGet/Person.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
namespace ProxyInterfaceConsumer
@@ -8,24 +9,29 @@ namespace ProxyInterfaceConsumer
private int PrivateId { get; }
public int Id { get; }
- public object @object { get; set; }
+ [SuppressMessage("ReSharper", "NullableWarningSuppressionIsUsed")]
+ public object @object { get; set; }= null!;
public long? NullableLong { get; }
- public string Name { get; set; }
+ [SuppressMessage("ReSharper", "NullableWarningSuppressionIsUsed")]
+ public string Name { get; set; }= null!;
public string? StringNullable { get; set; }
- public Address Address { get; set; }
+ [SuppressMessage("ReSharper", "NullableWarningSuppressionIsUsed")]
+ public Address Address { get; set; }= null!;
- public List AddressesLIst { get; set; }
+ [SuppressMessage("ReSharper", "NullableWarningSuppressionIsUsed")]
+ public List AddressesLIst { get; set; }= null!;
public Dictionary AddressesDict { get; set; } = new Dictionary();
public Dictionary AddressesDict2 { get; set; } = new Dictionary();
public E E { get; set; }
- public IMyInterface MyInterface { get; set; }
+ [SuppressMessage("ReSharper", "NullableWarningSuppressionIsUsed")]
+ public IMyInterface MyInterface { get; set; }= null!;
public string Add(string s, string @string)
{
@@ -83,4 +89,4 @@ namespace ProxyInterfaceConsumer
V1,
V2
}
-}
\ No newline at end of file
+}
diff --git a/src-examples/ProxyInterfaceConsumerViaNuGet/ProxyInterfaceConsumerViaNuGet.csproj b/src-examples/ProxyInterfaceConsumerViaNuGet/ProxyInterfaceConsumerViaNuGet.csproj
index 82e25f8..3c7d3b6 100644
--- a/src-examples/ProxyInterfaceConsumerViaNuGet/ProxyInterfaceConsumerViaNuGet.csproj
+++ b/src-examples/ProxyInterfaceConsumerViaNuGet/ProxyInterfaceConsumerViaNuGet.csproj
@@ -12,10 +12,10 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
\ No newline at end of file
+
diff --git a/src/ProxyInterfaceSourceGenerator/Builders/MethodParameterBuilder.cs b/src/Speckle.ProxyGenerator/Builders/MethodParameterBuilder.cs
similarity index 100%
rename from src/ProxyInterfaceSourceGenerator/Builders/MethodParameterBuilder.cs
rename to src/Speckle.ProxyGenerator/Builders/MethodParameterBuilder.cs
diff --git a/src/ProxyInterfaceSourceGenerator/Enums/TypeEnum.cs b/src/Speckle.ProxyGenerator/Enums/TypeEnum.cs
similarity index 100%
rename from src/ProxyInterfaceSourceGenerator/Enums/TypeEnum.cs
rename to src/Speckle.ProxyGenerator/Enums/TypeEnum.cs
diff --git a/src/ProxyInterfaceSourceGenerator/Extensions/MethodSymbolExtensions.cs b/src/Speckle.ProxyGenerator/Extensions/MethodSymbolExtensions.cs
similarity index 98%
rename from src/ProxyInterfaceSourceGenerator/Extensions/MethodSymbolExtensions.cs
rename to src/Speckle.ProxyGenerator/Extensions/MethodSymbolExtensions.cs
index 818fcd8..2feb5b2 100644
--- a/src/ProxyInterfaceSourceGenerator/Extensions/MethodSymbolExtensions.cs
+++ b/src/Speckle.ProxyGenerator/Extensions/MethodSymbolExtensions.cs
@@ -1,12 +1,12 @@
-using Microsoft.CodeAnalysis;
-
-namespace ProxyInterfaceSourceGenerator.Extensions;
-
-internal static class MethodSymbolExtensions
-{
- public static string GetMethodNameWithOptionalTypeParameters(this IMethodSymbol method) =>
- !method.IsGenericMethod ? method.Name : $"{method.Name}<{string.Join(", ", method.TypeParameters.Select(tp => tp.Name))}>";
-
- //public static string GetWhereStatement(this IMethodSymbol method) =>
- // !method.IsGenericMethod ? string.Empty : string.Join("", method.TypeParameters.Select(tp => tp.GetWhereConstraints()));
+using Microsoft.CodeAnalysis;
+
+namespace ProxyInterfaceSourceGenerator.Extensions;
+
+internal static class MethodSymbolExtensions
+{
+ public static string GetMethodNameWithOptionalTypeParameters(this IMethodSymbol method) =>
+ !method.IsGenericMethod ? method.Name : $"{method.Name}<{string.Join(", ", method.TypeParameters.Select(tp => tp.Name))}>";
+
+ //public static string GetWhereStatement(this IMethodSymbol method) =>
+ // !method.IsGenericMethod ? string.Empty : string.Join("", method.TypeParameters.Select(tp => tp.GetWhereConstraints()));
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/Extensions/NamedTypeSymbolExtensions.cs b/src/Speckle.ProxyGenerator/Extensions/NamedTypeSymbolExtensions.cs
similarity index 97%
rename from src/ProxyInterfaceSourceGenerator/Extensions/NamedTypeSymbolExtensions.cs
rename to src/Speckle.ProxyGenerator/Extensions/NamedTypeSymbolExtensions.cs
index 1f65fd6..c74ef98 100644
--- a/src/ProxyInterfaceSourceGenerator/Extensions/NamedTypeSymbolExtensions.cs
+++ b/src/Speckle.ProxyGenerator/Extensions/NamedTypeSymbolExtensions.cs
@@ -1,88 +1,88 @@
-using Microsoft.CodeAnalysis;
-
-namespace ProxyInterfaceSourceGenerator.Extensions;
-
-internal static class NamedTypeSymbolExtensions
-{
- public static List GetBaseTypes(this INamedTypeSymbol? type)
- {
- var types = new List();
-
- bool me = true;
- while (type != null && type.SpecialType != SpecialType.System_Object)
- {
- if (!me)
- {
- types.Add(type);
- }
-
- type = type.BaseType;
- me = false;
- }
-
- return types;
- }
-
- public static string GetFullType(this INamedTypeSymbol namedTypeSymbol)
- {
- // https://www.codeproject.com/Articles/861548/Roslyn-Code-Analysis-in-Easy-Samples-Part
- //var str = new StringBuilder(namedTypeSymbol.Name);
-
- //if (namedTypeSymbol.TypeArguments.Count() > 0)
- //{
- // str.AppendFormat("<{0}>", string.Join(", ", namedTypeSymbol.TypeArguments.OfType().Select(typeArg => typeArg.GetFullType())));
- //}
-
- return namedTypeSymbol.OriginalDefinition.ToString();
- }
-
- ///
- /// See https://stackoverflow.com/questions/24157101/roslyns-gettypebymetadataname-and-generic-types
- ///
- public static string ResolveProxyClassName(this INamedTypeSymbol namedTypeSymbol)
- {
- return !namedTypeSymbol.IsGenericType ?
- $"{namedTypeSymbol.Name}Proxy" :
- $"{namedTypeSymbol.Name}Proxy<{string.Join(", ", namedTypeSymbol.TypeArguments.Select(ta => ta.Name))}>";
- }
-
- public static List ResolveImplementedInterfaces(this INamedTypeSymbol symbol, bool proxyBaseClasses)
- {
- // Members implemented by us or base classes should go here.
- var publicMembers = symbol.GetMembers().Where(m => m.DeclaredAccessibility == Accessibility.Public).ToList();
-
- // Direct interfaces, recursive interfaces or base class interfaces should go here.
- var interfaces = new List(symbol.Interfaces);
- var baseType = symbol.BaseType;
- while (proxyBaseClasses && baseType != null && baseType.SpecialType != SpecialType.System_Object)
- {
- publicMembers.AddRange(baseType.GetMembers().Where(m => m.DeclaredAccessibility == Accessibility.Public));
- interfaces.AddRange(baseType.Interfaces);
- baseType = baseType.BaseType;
- }
-
- // Filter explicitly implemented interfaces.
- var realizedInterfaces = new List();
- foreach (var @interface in interfaces)
- {
- var isRealized = true;
- var allMembers = @interface.AllInterfaces.Aggregate(@interface.GetMembers(), (xs, x) => xs.AddRange(x.GetMembers()));
- foreach (var member in allMembers)
- {
- var implementation = symbol.FindImplementationForInterfaceMember(member);
- if (!publicMembers.Contains(implementation!))
- {
- isRealized = false;
- break;
- }
- }
-
- if (isRealized)
- {
- realizedInterfaces.Add(@interface);
- }
- }
-
- return realizedInterfaces;
- }
+using Microsoft.CodeAnalysis;
+
+namespace ProxyInterfaceSourceGenerator.Extensions;
+
+internal static class NamedTypeSymbolExtensions
+{
+ public static List GetBaseTypes(this INamedTypeSymbol? type)
+ {
+ var types = new List();
+
+ bool me = true;
+ while (type != null && type.SpecialType != SpecialType.System_Object)
+ {
+ if (!me)
+ {
+ types.Add(type);
+ }
+
+ type = type.BaseType;
+ me = false;
+ }
+
+ return types;
+ }
+
+ public static string GetFullType(this INamedTypeSymbol namedTypeSymbol)
+ {
+ // https://www.codeproject.com/Articles/861548/Roslyn-Code-Analysis-in-Easy-Samples-Part
+ //var str = new StringBuilder(namedTypeSymbol.Name);
+
+ //if (namedTypeSymbol.TypeArguments.Count() > 0)
+ //{
+ // str.AppendFormat("<{0}>", string.Join(", ", namedTypeSymbol.TypeArguments.OfType().Select(typeArg => typeArg.GetFullType())));
+ //}
+
+ return namedTypeSymbol.OriginalDefinition.ToString();
+ }
+
+ ///
+ /// See https://stackoverflow.com/questions/24157101/roslyns-gettypebymetadataname-and-generic-types
+ ///
+ public static string ResolveProxyClassName(this INamedTypeSymbol namedTypeSymbol)
+ {
+ return !namedTypeSymbol.IsGenericType ?
+ $"{namedTypeSymbol.Name}Proxy" :
+ $"{namedTypeSymbol.Name}Proxy<{string.Join(", ", namedTypeSymbol.TypeArguments.Select(ta => ta.Name))}>";
+ }
+
+ public static List ResolveImplementedInterfaces(this INamedTypeSymbol symbol, bool proxyBaseClasses)
+ {
+ // Members implemented by us or base classes should go here.
+ var publicMembers = symbol.GetMembers().Where(m => m.DeclaredAccessibility == Accessibility.Public).ToList();
+
+ // Direct interfaces, recursive interfaces or base class interfaces should go here.
+ var interfaces = new List(symbol.Interfaces);
+ var baseType = symbol.BaseType;
+ while (proxyBaseClasses && baseType != null && baseType.SpecialType != SpecialType.System_Object)
+ {
+ publicMembers.AddRange(baseType.GetMembers().Where(m => m.DeclaredAccessibility == Accessibility.Public));
+ interfaces.AddRange(baseType.Interfaces);
+ baseType = baseType.BaseType;
+ }
+
+ // Filter explicitly implemented interfaces.
+ var realizedInterfaces = new List();
+ foreach (var @interface in interfaces)
+ {
+ var isRealized = true;
+ var allMembers = @interface.AllInterfaces.Aggregate(@interface.GetMembers(), (xs, x) => xs.AddRange(x.GetMembers()));
+ foreach (var member in allMembers)
+ {
+ var implementation = symbol.FindImplementationForInterfaceMember(member);
+ if (!publicMembers.Contains(implementation!))
+ {
+ isRealized = false;
+ break;
+ }
+ }
+
+ if (isRealized)
+ {
+ realizedInterfaces.Add(@interface);
+ }
+ }
+
+ return realizedInterfaces;
+ }
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/Extensions/ParameterSymbolExtensions.cs b/src/Speckle.ProxyGenerator/Extensions/ParameterSymbolExtensions.cs
similarity index 96%
rename from src/ProxyInterfaceSourceGenerator/Extensions/ParameterSymbolExtensions.cs
rename to src/Speckle.ProxyGenerator/Extensions/ParameterSymbolExtensions.cs
index 0e45469..7b88b22 100644
--- a/src/ProxyInterfaceSourceGenerator/Extensions/ParameterSymbolExtensions.cs
+++ b/src/Speckle.ProxyGenerator/Extensions/ParameterSymbolExtensions.cs
@@ -1,60 +1,60 @@
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using ProxyInterfaceSourceGenerator.Enums;
-
-namespace ProxyInterfaceSourceGenerator.Extensions;
-
-internal static class ParameterSymbolExtensions
-{
- private const string ParameterValueNull = "null";
-
- public static bool IsRef(this IParameterSymbol ps)
- {
- return ps.RefKind is RefKind.Ref or RefKind.RefReadOnly;
- }
-
- public static string GetRefKindPrefix(this IParameterSymbol ps)
- {
- return ps.RefKind switch
- {
- RefKind.In => "in ",
- RefKind.Out => "out ",
- RefKind.Ref => "ref ",
- _ => string.Empty
- };
- }
-
- public static string GetParamsPrefix(this IParameterSymbol ps) => ps.IsParams ? "params " : string.Empty;
-
- public static string GetDefaultValue(this IParameterSymbol ps)
- {
- if (!ps.HasExplicitDefaultValue)
- {
- return string.Empty;
- }
-
- string defaultValue;
- if (ps.ExplicitDefaultValue == null)
- {
- if (ps.NullableAnnotation == NullableAnnotation.Annotated)
- {
- // The parameter is defined as Nullable, so always use "null".
- defaultValue = ParameterValueNull;
- }
- else
- {
- defaultValue = ps.Type.IsReferenceType
- ? ParameterValueNull : // The parameter is a ReferenceType, so use "null".
- $"default({ps.Type})"; // The parameter is not a ReferenceType, so use "default(T)".
- }
- }
- else
- {
- defaultValue = SymbolDisplay.FormatPrimitive(ps.ExplicitDefaultValue, true, false);
- }
-
- return $" = {defaultValue}";
- }
-
- public static TypeEnum GetTypeEnum(this IParameterSymbol p) => p.Type.GetTypeEnum();
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using ProxyInterfaceSourceGenerator.Enums;
+
+namespace ProxyInterfaceSourceGenerator.Extensions;
+
+internal static class ParameterSymbolExtensions
+{
+ private const string ParameterValueNull = "null";
+
+ public static bool IsRef(this IParameterSymbol ps)
+ {
+ return ps.RefKind is RefKind.Ref or RefKind.RefReadOnly;
+ }
+
+ public static string GetRefKindPrefix(this IParameterSymbol ps)
+ {
+ return ps.RefKind switch
+ {
+ RefKind.In => "in ",
+ RefKind.Out => "out ",
+ RefKind.Ref => "ref ",
+ _ => string.Empty
+ };
+ }
+
+ public static string GetParamsPrefix(this IParameterSymbol ps) => ps.IsParams ? "params " : string.Empty;
+
+ public static string GetDefaultValue(this IParameterSymbol ps)
+ {
+ if (!ps.HasExplicitDefaultValue)
+ {
+ return string.Empty;
+ }
+
+ string defaultValue;
+ if (ps.ExplicitDefaultValue == null)
+ {
+ if (ps.NullableAnnotation == NullableAnnotation.Annotated)
+ {
+ // The parameter is defined as Nullable, so always use "null".
+ defaultValue = ParameterValueNull;
+ }
+ else
+ {
+ defaultValue = ps.Type.IsReferenceType
+ ? ParameterValueNull : // The parameter is a ReferenceType, so use "null".
+ $"default({ps.Type})"; // The parameter is not a ReferenceType, so use "default(T)".
+ }
+ }
+ else
+ {
+ defaultValue = SymbolDisplay.FormatPrimitive(ps.ExplicitDefaultValue, true, false);
+ }
+
+ return $" = {defaultValue}";
+ }
+
+ public static TypeEnum GetTypeEnum(this IParameterSymbol p) => p.Type.GetTypeEnum();
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/Extensions/PropertySymbolExtensions.cs b/src/Speckle.ProxyGenerator/Extensions/PropertySymbolExtensions.cs
similarity index 97%
rename from src/ProxyInterfaceSourceGenerator/Extensions/PropertySymbolExtensions.cs
rename to src/Speckle.ProxyGenerator/Extensions/PropertySymbolExtensions.cs
index 07b7e5b..d38ca83 100644
--- a/src/ProxyInterfaceSourceGenerator/Extensions/PropertySymbolExtensions.cs
+++ b/src/Speckle.ProxyGenerator/Extensions/PropertySymbolExtensions.cs
@@ -1,29 +1,29 @@
-using Microsoft.CodeAnalysis;
-using ProxyInterfaceSourceGenerator.Enums;
-using ProxyInterfaceSourceGenerator.FileGenerators;
-
-namespace ProxyInterfaceSourceGenerator.Extensions;
-
-internal static class PropertySymbolExtensions
-{
- public static TypeEnum GetTypeEnum(this IPropertySymbol p) => p.Type.GetTypeEnum();
-
- public static (string PropertyType, string? PropertyName, string GetSet)? ToPropertyDetails(this IPropertySymbol property, string? overrideType = null)
- {
- var getIsPublic = property.GetMethod.IsPublic();
- var setIsPublic = property.SetMethod.IsPublic();
-
- if (!getIsPublic && !setIsPublic)
- {
- return null;
- }
-
- var get = getIsPublic ? "get; " : string.Empty;
- var set = setIsPublic ? "set; " : string.Empty;
-
- var type = !string.IsNullOrEmpty(overrideType) ? overrideType
- : BaseGenerator.FixType(property.Type.ToFullyQualifiedDisplayString(), property.NullableAnnotation);
-
- return (type!, property.GetSanitizedName(), $"{{ {get}{set}}}");
- }
+using Microsoft.CodeAnalysis;
+using ProxyInterfaceSourceGenerator.Enums;
+using ProxyInterfaceSourceGenerator.FileGenerators;
+
+namespace ProxyInterfaceSourceGenerator.Extensions;
+
+internal static class PropertySymbolExtensions
+{
+ public static TypeEnum GetTypeEnum(this IPropertySymbol p) => p.Type.GetTypeEnum();
+
+ public static (string PropertyType, string? PropertyName, string GetSet)? ToPropertyDetails(this IPropertySymbol property, string? overrideType = null)
+ {
+ var getIsPublic = property.GetMethod.IsPublic();
+ var setIsPublic = property.SetMethod.IsPublic();
+
+ if (!getIsPublic && !setIsPublic)
+ {
+ return null;
+ }
+
+ var get = getIsPublic ? "get; " : string.Empty;
+ var set = setIsPublic ? "set; " : string.Empty;
+
+ var type = !string.IsNullOrEmpty(overrideType) ? overrideType
+ : BaseGenerator.FixType(property.Type.ToFullyQualifiedDisplayString(), property.NullableAnnotation);
+
+ return (type!, property.GetSanitizedName(), $"{{ {get}{set}}}");
+ }
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/Extensions/StringExtensions.cs b/src/Speckle.ProxyGenerator/Extensions/StringExtensions.cs
similarity index 100%
rename from src/ProxyInterfaceSourceGenerator/Extensions/StringExtensions.cs
rename to src/Speckle.ProxyGenerator/Extensions/StringExtensions.cs
diff --git a/src/ProxyInterfaceSourceGenerator/Extensions/SymbolExtensions.cs b/src/Speckle.ProxyGenerator/Extensions/SymbolExtensions.cs
similarity index 97%
rename from src/ProxyInterfaceSourceGenerator/Extensions/SymbolExtensions.cs
rename to src/Speckle.ProxyGenerator/Extensions/SymbolExtensions.cs
index cbf5c74..5c34313 100644
--- a/src/ProxyInterfaceSourceGenerator/Extensions/SymbolExtensions.cs
+++ b/src/Speckle.ProxyGenerator/Extensions/SymbolExtensions.cs
@@ -1,74 +1,74 @@
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using System.Text;
-
-namespace ProxyInterfaceSourceGenerator.Extensions;
-
-internal static class SymbolExtensions
-{
- private static readonly string[] ExcludedAttributes =
- {
- "System.Runtime.CompilerServices.NullableAttribute",
- "System.Runtime.CompilerServices.NullableContextAttribute",
- "System.Runtime.CompilerServices.AsyncStateMachineAttribute"
- };
-
- public static IReadOnlyList GetAttributesAsList(this ISymbol symbol)
- {
- return symbol
- .GetAttributes()
- .Where(a => a.AttributeClass.IsPublic() && !ExcludedAttributes.Contains(a.AttributeClass?.ToString(), StringComparer.OrdinalIgnoreCase))
- .Select(a => $"[{a}]")
- .ToArray();
- }
-
- public static string GetAttributesPrefix(this ISymbol symbol)
- {
- var attributes = symbol.GetAttributesAsList();
-
- return attributes.Any() ? $"{string.Join(" ", attributes)} " : string.Empty;
- }
-
- //https://stackoverflow.com/questions/27105909/get-fully-qualified-metadata-name-in-roslyn
- public static string GetFullMetadataName(this ISymbol? s)
- {
- if (s == null || IsRootNamespace(s))
- {
- return string.Empty;
- }
-
- var sb = new StringBuilder(s.MetadataName);
- var last = s;
-
- s = s.ContainingSymbol;
-
- while (!IsRootNamespace(s))
- {
- if (s is ITypeSymbol && last is ITypeSymbol)
- {
- sb.Insert(0, '+');
- }
- else
- {
- sb.Insert(0, '.');
- }
-
- sb.Insert(0, s.OriginalDefinition.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat));
- s = s.ContainingSymbol;
- }
-
- return sb.ToString();
- }
-
- public static string GetSanitizedName(this ISymbol symbol) =>
- symbol.IsKeywordOrReserved() ? $"@{symbol.Name}" : symbol.Name;
-
- public static bool IsKeywordOrReserved(this ISymbol symbol) =>
- SyntaxFacts.GetKeywordKind(symbol.Name) != SyntaxKind.None || SyntaxFacts.GetContextualKeywordKind(symbol.Name) != SyntaxKind.None;
-
- public static bool IsPublic(this ISymbol? symbol) =>
- symbol is { DeclaredAccessibility: Accessibility.Public };
-
- private static bool IsRootNamespace(ISymbol symbol) =>
- symbol is INamespaceSymbol { IsGlobalNamespace: true };
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using System.Text;
+
+namespace ProxyInterfaceSourceGenerator.Extensions;
+
+internal static class SymbolExtensions
+{
+ private static readonly string[] ExcludedAttributes =
+ {
+ "System.Runtime.CompilerServices.NullableAttribute",
+ "System.Runtime.CompilerServices.NullableContextAttribute",
+ "System.Runtime.CompilerServices.AsyncStateMachineAttribute"
+ };
+
+ public static IReadOnlyList GetAttributesAsList(this ISymbol symbol)
+ {
+ return symbol
+ .GetAttributes()
+ .Where(a => a.AttributeClass.IsPublic() && !ExcludedAttributes.Contains(a.AttributeClass?.ToString(), StringComparer.OrdinalIgnoreCase))
+ .Select(a => $"[{a}]")
+ .ToArray();
+ }
+
+ public static string GetAttributesPrefix(this ISymbol symbol)
+ {
+ var attributes = symbol.GetAttributesAsList();
+
+ return attributes.Any() ? $"{string.Join(" ", attributes)} " : string.Empty;
+ }
+
+ //https://stackoverflow.com/questions/27105909/get-fully-qualified-metadata-name-in-roslyn
+ public static string GetFullMetadataName(this ISymbol? s)
+ {
+ if (s == null || IsRootNamespace(s))
+ {
+ return string.Empty;
+ }
+
+ var sb = new StringBuilder(s.MetadataName);
+ var last = s;
+
+ s = s.ContainingSymbol;
+
+ while (!IsRootNamespace(s))
+ {
+ if (s is ITypeSymbol && last is ITypeSymbol)
+ {
+ sb.Insert(0, '+');
+ }
+ else
+ {
+ sb.Insert(0, '.');
+ }
+
+ sb.Insert(0, s.OriginalDefinition.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat));
+ s = s.ContainingSymbol;
+ }
+
+ return sb.ToString();
+ }
+
+ public static string GetSanitizedName(this ISymbol symbol) =>
+ symbol.IsKeywordOrReserved() ? $"@{symbol.Name}" : symbol.Name;
+
+ public static bool IsKeywordOrReserved(this ISymbol symbol) =>
+ SyntaxFacts.GetKeywordKind(symbol.Name) != SyntaxKind.None || SyntaxFacts.GetContextualKeywordKind(symbol.Name) != SyntaxKind.None;
+
+ public static bool IsPublic(this ISymbol? symbol) =>
+ symbol is { DeclaredAccessibility: Accessibility.Public };
+
+ private static bool IsRootNamespace(ISymbol symbol) =>
+ symbol is INamespaceSymbol { IsGlobalNamespace: true };
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/Extensions/SyntaxNodeExtensions.cs b/src/Speckle.ProxyGenerator/Extensions/SyntaxNodeExtensions.cs
similarity index 100%
rename from src/ProxyInterfaceSourceGenerator/Extensions/SyntaxNodeExtensions.cs
rename to src/Speckle.ProxyGenerator/Extensions/SyntaxNodeExtensions.cs
diff --git a/src/ProxyInterfaceSourceGenerator/Extensions/TypeSymbolExtensions.cs b/src/Speckle.ProxyGenerator/Extensions/TypeSymbolExtensions.cs
similarity index 96%
rename from src/ProxyInterfaceSourceGenerator/Extensions/TypeSymbolExtensions.cs
rename to src/Speckle.ProxyGenerator/Extensions/TypeSymbolExtensions.cs
index 7327ae1..9aec671 100644
--- a/src/ProxyInterfaceSourceGenerator/Extensions/TypeSymbolExtensions.cs
+++ b/src/Speckle.ProxyGenerator/Extensions/TypeSymbolExtensions.cs
@@ -1,28 +1,28 @@
-using Microsoft.CodeAnalysis;
-using ProxyInterfaceSourceGenerator.Enums;
-
-namespace ProxyInterfaceSourceGenerator.Extensions;
-
-internal static class TypeSymbolExtensions
-{
- public static TypeEnum GetTypeEnum(this ITypeSymbol ts)
- {
- if (ts.IsValueType || ts.IsString())
- {
- return TypeEnum.ValueTypeOrString;
- }
-
- if (ts.TypeKind == TypeKind.Interface)
- {
- return TypeEnum.Interface;
- }
-
- return TypeEnum.Complex;
- }
-
- public static bool IsString(this ITypeSymbol ts) =>
- ts.ToString().ToLowerInvariant() == "string" || ts.ToString().ToLowerInvariant() == "string?";
-
- public static string ToFullyQualifiedDisplayString(this ITypeSymbol property) =>
- property.ToDisplayString(NullableFlowState.None, SymbolDisplayFormat.FullyQualifiedFormat);
+using Microsoft.CodeAnalysis;
+using ProxyInterfaceSourceGenerator.Enums;
+
+namespace ProxyInterfaceSourceGenerator.Extensions;
+
+internal static class TypeSymbolExtensions
+{
+ public static TypeEnum GetTypeEnum(this ITypeSymbol ts)
+ {
+ if (ts.IsValueType || ts.IsString())
+ {
+ return TypeEnum.ValueTypeOrString;
+ }
+
+ if (ts.TypeKind == TypeKind.Interface)
+ {
+ return TypeEnum.Interface;
+ }
+
+ return TypeEnum.Complex;
+ }
+
+ public static bool IsString(this ITypeSymbol ts) =>
+ ts.ToString().ToLowerInvariant() == "string" || ts.ToString().ToLowerInvariant() == "string?";
+
+ public static string ToFullyQualifiedDisplayString(this ITypeSymbol property) =>
+ property.ToDisplayString(NullableFlowState.None, SymbolDisplayFormat.FullyQualifiedFormat);
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/BaseGenerator.cs b/src/Speckle.ProxyGenerator/FileGenerators/BaseGenerator.cs
similarity index 97%
rename from src/ProxyInterfaceSourceGenerator/FileGenerators/BaseGenerator.cs
rename to src/Speckle.ProxyGenerator/FileGenerators/BaseGenerator.cs
index c399d93..6ba0275 100644
--- a/src/ProxyInterfaceSourceGenerator/FileGenerators/BaseGenerator.cs
+++ b/src/Speckle.ProxyGenerator/FileGenerators/BaseGenerator.cs
@@ -1,262 +1,262 @@
-using System.Collections.Immutable;
-using System.Diagnostics.CodeAnalysis;
-using System.Text;
-using Microsoft.CodeAnalysis;
-using ProxyInterfaceSourceGenerator.Builders;
-using ProxyInterfaceSourceGenerator.Enums;
-using ProxyInterfaceSourceGenerator.Extensions;
-using ProxyInterfaceSourceGenerator.Models;
-
-namespace ProxyInterfaceSourceGenerator.FileGenerators;
-
-internal abstract class BaseGenerator
-{
- protected readonly Context Context;
- protected readonly bool SupportsNullable;
-
- protected BaseGenerator(Context context, bool supportsNullable)
- {
- Context = context;
- SupportsNullable = supportsNullable;
- }
-
- protected string GetPropertyType(IPropertySymbol property, out bool isReplaced)
- {
- return GetReplacedTypeAsString(property.Type, out isReplaced);
- }
-
- protected string GetParameterType(IParameterSymbol property, out bool isReplaced)
- {
- return GetReplacedTypeAsString(property.Type, out isReplaced);
- }
-
- protected bool TryFindProxyDataByTypeName(string type, [NotNullWhen(true)] out ProxyData? proxyData)
- {
- proxyData = Context.Candidates.Values.FirstOrDefault(x => x.FullQualifiedTypeName == type);
- return proxyData != null;
- }
-
- protected string GetWhereStatementFromMethod(IMethodSymbol method)
- {
- if (!method.IsGenericMethod)
- {
- return string.Empty;
- }
-
- var list = new List();
- foreach (var typeParameterSymbol in method.TypeParameters)
- {
- if (TryGetWhereConstraints(typeParameterSymbol, false, out var constraint))
- {
- list.Add(constraint.ToString());
- }
- }
-
- return string.Concat(list);
- }
-
- protected string ResolveInterfaceNameWithOptionalTypeConstraints(INamedTypeSymbol namedTypeSymbol, string interfaceName)
- {
- if (!namedTypeSymbol.IsGenericType)
- {
- return interfaceName;
- }
-
- var str = new StringBuilder($"{interfaceName}<{string.Join(", ", namedTypeSymbol.TypeArguments.Select(ta => ta.Name))}>");
-
- foreach (var typeParameterSymbol in namedTypeSymbol.TypeArguments.OfType())
- {
- if (TryGetWhereConstraints(typeParameterSymbol, false, out var constraint))
- {
- str.Append(constraint);
- }
- }
-
- return str.ToString();
- }
-
- ///
- /// https://www.codeproject.com/Articles/871704/Roslyn-Code-Analysis-in-Easy-Samples-Part-2
- ///
- public bool TryGetWhereConstraints(ITypeParameterSymbol typeParameterSymbol, bool replaceIt, [NotNullWhen(true)] out ConstraintInfo? constraint)
- {
- var constraints = new List();
- if (typeParameterSymbol.HasReferenceTypeConstraint)
- {
- constraints.Add("class");
- }
-
- if (typeParameterSymbol.HasValueTypeConstraint)
- {
- constraints.Add("struct");
- }
-
- foreach (var namedTypeSymbol in typeParameterSymbol.ConstraintTypes.OfType())
- {
- if (replaceIt)
- {
- constraints.Add(GetReplacedTypeAsString(namedTypeSymbol, out _));
- }
- else
- {
- constraints.Add(namedTypeSymbol.GetFullType());
- }
- }
-
- // The new() constraint must be the last constraint specified.
- if (typeParameterSymbol.HasConstructorConstraint)
- {
- constraints.Add("new()");
- }
-
- if (constraints.Count > 0)
- {
- constraint = new(typeParameterSymbol.Name, constraints);
- return true;
- }
-
- constraint = null;
- return false;
- }
-
- internal readonly SymbolDisplayFormat NullableDisplayFormat = new SymbolDisplayFormat(
- globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Included,
- typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
- genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters,
- miscellaneousOptions:
- SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers |
- SymbolDisplayMiscellaneousOptions.UseSpecialTypes |
- SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier);
-
- protected string GetReplacedTypeAsString(ITypeSymbol typeSymbol, out bool isReplaced)
- {
- isReplaced = false;
-
- var typeSymbolAsString = typeSymbol.ToFullyQualifiedDisplayString();
- var nullableTypeSymbolAsString = typeSymbol.ToDisplayString(NullableFlowState.None, NullableDisplayFormat);
-
- if (TryFindProxyDataByTypeName(typeSymbolAsString, out var existing))
- {
- if (!Context.ReplacedTypes.ContainsKey(typeSymbolAsString))
- {
- Context.ReplacedTypes.Add(typeSymbolAsString, existing.FullInterfaceName);
- }
-
- isReplaced = true;
- return FixType(existing.FullInterfaceName, typeSymbol.NullableAnnotation);
- }
-
- ITypeSymbol[] typeArguments;
- if (typeSymbol is INamedTypeSymbol namedTypedSymbol1)
- {
- typeArguments = namedTypedSymbol1.TypeArguments.ToArray();
- }
- else if (typeSymbol is IArrayTypeSymbol arrayTypeSymbol)
- {
- typeArguments = new[] { arrayTypeSymbol.ElementType };
- }
- else
- {
- return FixType(typeSymbolAsString, typeSymbol.NullableAnnotation);
- }
-
- var propertyTypeAsStringToBeModified = nullableTypeSymbolAsString;
- foreach (var typeArgument in typeArguments)
- {
- var typeArgumentAsString = typeArgument.ToFullyQualifiedDisplayString();
-
- if (TryFindProxyDataByTypeName(typeArgumentAsString, out var existingTypeArgument))
- {
- isReplaced = true;
-
- if (!Context.ReplacedTypes.ContainsKey(typeArgumentAsString))
- {
- Context.ReplacedTypes.Add(typeArgumentAsString, existingTypeArgument.FullInterfaceName);
- }
-
- propertyTypeAsStringToBeModified = propertyTypeAsStringToBeModified.Replace(typeArgumentAsString, existingTypeArgument.FullInterfaceName);
- }
- }
-
- return FixType(propertyTypeAsStringToBeModified, typeSymbol.NullableAnnotation);
- }
-
- protected bool TryGetNamedTypeSymbolByFullName(TypeKind kind, string name, IEnumerable usings, [NotNullWhen(true)] out ClassSymbol? classSymbol)
- {
- classSymbol = default;
- const string globalPrefix = "global::";
- if (name.StartsWith(globalPrefix, StringComparison.Ordinal))
- {
- name = name.Substring(globalPrefix.Length);
- }
-
- // The GetTypeByMetadataName method returns null if no type matches the full name or if 2 or more types (in different assemblies) match the full name.
- var symbol = Context.GeneratorExecutionContext.Compilation.GetTypeByMetadataName(name);
-
- if (symbol is not null && symbol.TypeKind == kind)
- {
- classSymbol = new ClassSymbol(symbol, symbol.GetBaseTypes(), symbol.AllInterfaces.ToList());
- return true;
- }
-
- foreach (var @using in usings)
- {
- symbol = Context.GeneratorExecutionContext.Compilation.GetTypeByMetadataName($"{@using}.{name}");
- if (symbol is not null && symbol.TypeKind == kind)
- {
- classSymbol = new ClassSymbol(symbol, symbol.GetBaseTypes(), symbol.AllInterfaces.ToList());
- return true;
- }
- }
-
- return false;
- }
-
- protected IReadOnlyList GetMethodParameters(ImmutableArray parameterSymbols, bool includeType)
- {
- var methodParameters = new List();
- foreach (var parameterSymbol in parameterSymbols)
- {
- string? type = null;
- if (includeType)
- {
- if (parameterSymbol.GetTypeEnum() == TypeEnum.Complex)
- {
- type = GetParameterType(parameterSymbol, out _);
- }
- else
- {
- type = FixType(parameterSymbol.Type.ToFullyQualifiedDisplayString(), parameterSymbol.NullableAnnotation);
- }
- }
-
- methodParameters.Add(MethodParameterBuilder.Build(parameterSymbol, type));
- }
-
- return methodParameters;
- }
-
- protected IReadOnlyList GetExtendsProxyData(ProxyData proxyData, ClassSymbol targetClassSymbol)
- {
- var extendsProxyClasses = new List();
- foreach (var baseType in targetClassSymbol.BaseTypes)
- {
- var candidate = Context.Candidates.Values.FirstOrDefault(ci => ci.FullQualifiedTypeName == baseType.ToFullyQualifiedDisplayString());
- if (candidate is not null)
- {
- extendsProxyClasses.Add(candidate);
- break;
- }
- }
- return extendsProxyClasses;
- }
-
- internal static string FixType(string type, NullableAnnotation nullableAnnotation)
- {
- if (nullableAnnotation == NullableAnnotation.Annotated && !type.EndsWith("?", StringComparison.Ordinal))
- {
- return $"{type}?";
- }
- return type;
- }
+using System.Collections.Immutable;
+using System.Diagnostics.CodeAnalysis;
+using System.Text;
+using Microsoft.CodeAnalysis;
+using ProxyInterfaceSourceGenerator.Builders;
+using ProxyInterfaceSourceGenerator.Enums;
+using ProxyInterfaceSourceGenerator.Extensions;
+using ProxyInterfaceSourceGenerator.Models;
+
+namespace ProxyInterfaceSourceGenerator.FileGenerators;
+
+internal abstract class BaseGenerator
+{
+ protected readonly Context Context;
+ protected readonly bool SupportsNullable;
+
+ protected BaseGenerator(Context context, bool supportsNullable)
+ {
+ Context = context;
+ SupportsNullable = supportsNullable;
+ }
+
+ protected string GetPropertyType(IPropertySymbol property, out bool isReplaced)
+ {
+ return GetReplacedTypeAsString(property.Type, out isReplaced);
+ }
+
+ protected string GetParameterType(IParameterSymbol property, out bool isReplaced)
+ {
+ return GetReplacedTypeAsString(property.Type, out isReplaced);
+ }
+
+ protected bool TryFindProxyDataByTypeName(string type, [NotNullWhen(true)] out ProxyData? proxyData)
+ {
+ proxyData = Context.Candidates.Values.FirstOrDefault(x => x.FullQualifiedTypeName == type);
+ return proxyData != null;
+ }
+
+ protected string GetWhereStatementFromMethod(IMethodSymbol method)
+ {
+ if (!method.IsGenericMethod)
+ {
+ return string.Empty;
+ }
+
+ var list = new List();
+ foreach (var typeParameterSymbol in method.TypeParameters)
+ {
+ if (TryGetWhereConstraints(typeParameterSymbol, false, out var constraint))
+ {
+ list.Add(constraint.ToString());
+ }
+ }
+
+ return string.Concat(list);
+ }
+
+ protected string ResolveInterfaceNameWithOptionalTypeConstraints(INamedTypeSymbol namedTypeSymbol, string interfaceName)
+ {
+ if (!namedTypeSymbol.IsGenericType)
+ {
+ return interfaceName;
+ }
+
+ var str = new StringBuilder($"{interfaceName}<{string.Join(", ", namedTypeSymbol.TypeArguments.Select(ta => ta.Name))}>");
+
+ foreach (var typeParameterSymbol in namedTypeSymbol.TypeArguments.OfType())
+ {
+ if (TryGetWhereConstraints(typeParameterSymbol, false, out var constraint))
+ {
+ str.Append(constraint);
+ }
+ }
+
+ return str.ToString();
+ }
+
+ ///
+ /// https://www.codeproject.com/Articles/871704/Roslyn-Code-Analysis-in-Easy-Samples-Part-2
+ ///
+ public bool TryGetWhereConstraints(ITypeParameterSymbol typeParameterSymbol, bool replaceIt, [NotNullWhen(true)] out ConstraintInfo? constraint)
+ {
+ var constraints = new List();
+ if (typeParameterSymbol.HasReferenceTypeConstraint)
+ {
+ constraints.Add("class");
+ }
+
+ if (typeParameterSymbol.HasValueTypeConstraint)
+ {
+ constraints.Add("struct");
+ }
+
+ foreach (var namedTypeSymbol in typeParameterSymbol.ConstraintTypes.OfType())
+ {
+ if (replaceIt)
+ {
+ constraints.Add(GetReplacedTypeAsString(namedTypeSymbol, out _));
+ }
+ else
+ {
+ constraints.Add(namedTypeSymbol.GetFullType());
+ }
+ }
+
+ // The new() constraint must be the last constraint specified.
+ if (typeParameterSymbol.HasConstructorConstraint)
+ {
+ constraints.Add("new()");
+ }
+
+ if (constraints.Count > 0)
+ {
+ constraint = new(typeParameterSymbol.Name, constraints);
+ return true;
+ }
+
+ constraint = null;
+ return false;
+ }
+
+ internal readonly SymbolDisplayFormat NullableDisplayFormat = new SymbolDisplayFormat(
+ globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Included,
+ typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
+ genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters,
+ miscellaneousOptions:
+ SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers |
+ SymbolDisplayMiscellaneousOptions.UseSpecialTypes |
+ SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier);
+
+ protected string GetReplacedTypeAsString(ITypeSymbol typeSymbol, out bool isReplaced)
+ {
+ isReplaced = false;
+
+ var typeSymbolAsString = typeSymbol.ToFullyQualifiedDisplayString();
+ var nullableTypeSymbolAsString = typeSymbol.ToDisplayString(NullableFlowState.None, NullableDisplayFormat);
+
+ if (TryFindProxyDataByTypeName(typeSymbolAsString, out var existing))
+ {
+ if (!Context.ReplacedTypes.ContainsKey(typeSymbolAsString))
+ {
+ Context.ReplacedTypes.Add(typeSymbolAsString, existing.FullInterfaceName);
+ }
+
+ isReplaced = true;
+ return FixType(existing.FullInterfaceName, typeSymbol.NullableAnnotation);
+ }
+
+ ITypeSymbol[] typeArguments;
+ if (typeSymbol is INamedTypeSymbol namedTypedSymbol1)
+ {
+ typeArguments = namedTypedSymbol1.TypeArguments.ToArray();
+ }
+ else if (typeSymbol is IArrayTypeSymbol arrayTypeSymbol)
+ {
+ typeArguments = new[] { arrayTypeSymbol.ElementType };
+ }
+ else
+ {
+ return FixType(typeSymbolAsString, typeSymbol.NullableAnnotation);
+ }
+
+ var propertyTypeAsStringToBeModified = nullableTypeSymbolAsString;
+ foreach (var typeArgument in typeArguments)
+ {
+ var typeArgumentAsString = typeArgument.ToFullyQualifiedDisplayString();
+
+ if (TryFindProxyDataByTypeName(typeArgumentAsString, out var existingTypeArgument))
+ {
+ isReplaced = true;
+
+ if (!Context.ReplacedTypes.ContainsKey(typeArgumentAsString))
+ {
+ Context.ReplacedTypes.Add(typeArgumentAsString, existingTypeArgument.FullInterfaceName);
+ }
+
+ propertyTypeAsStringToBeModified = propertyTypeAsStringToBeModified.Replace(typeArgumentAsString, existingTypeArgument.FullInterfaceName);
+ }
+ }
+
+ return FixType(propertyTypeAsStringToBeModified, typeSymbol.NullableAnnotation);
+ }
+
+ protected bool TryGetNamedTypeSymbolByFullName(TypeKind kind, string name, IEnumerable usings, [NotNullWhen(true)] out ClassSymbol? classSymbol)
+ {
+ classSymbol = default;
+ const string globalPrefix = "global::";
+ if (name.StartsWith(globalPrefix, StringComparison.Ordinal))
+ {
+ name = name.Substring(globalPrefix.Length);
+ }
+
+ // The GetTypeByMetadataName method returns null if no type matches the full name or if 2 or more types (in different assemblies) match the full name.
+ var symbol = Context.GeneratorExecutionContext.Compilation.GetTypeByMetadataName(name);
+
+ if (symbol is not null && symbol.TypeKind == kind)
+ {
+ classSymbol = new ClassSymbol(symbol, symbol.GetBaseTypes(), symbol.AllInterfaces.ToList());
+ return true;
+ }
+
+ foreach (var @using in usings)
+ {
+ symbol = Context.GeneratorExecutionContext.Compilation.GetTypeByMetadataName($"{@using}.{name}");
+ if (symbol is not null && symbol.TypeKind == kind)
+ {
+ classSymbol = new ClassSymbol(symbol, symbol.GetBaseTypes(), symbol.AllInterfaces.ToList());
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ protected IReadOnlyList GetMethodParameters(ImmutableArray parameterSymbols, bool includeType)
+ {
+ var methodParameters = new List();
+ foreach (var parameterSymbol in parameterSymbols)
+ {
+ string? type = null;
+ if (includeType)
+ {
+ if (parameterSymbol.GetTypeEnum() == TypeEnum.Complex)
+ {
+ type = GetParameterType(parameterSymbol, out _);
+ }
+ else
+ {
+ type = FixType(parameterSymbol.Type.ToFullyQualifiedDisplayString(), parameterSymbol.NullableAnnotation);
+ }
+ }
+
+ methodParameters.Add(MethodParameterBuilder.Build(parameterSymbol, type));
+ }
+
+ return methodParameters;
+ }
+
+ protected IReadOnlyList GetExtendsProxyData(ProxyData proxyData, ClassSymbol targetClassSymbol)
+ {
+ var extendsProxyClasses = new List();
+ foreach (var baseType in targetClassSymbol.BaseTypes)
+ {
+ var candidate = Context.Candidates.Values.FirstOrDefault(ci => ci.FullQualifiedTypeName == baseType.ToFullyQualifiedDisplayString());
+ if (candidate is not null)
+ {
+ extendsProxyClasses.Add(candidate);
+ break;
+ }
+ }
+ return extendsProxyClasses;
+ }
+
+ internal static string FixType(string type, NullableAnnotation nullableAnnotation)
+ {
+ if (nullableAnnotation == NullableAnnotation.Annotated && !type.EndsWith("?", StringComparison.Ordinal))
+ {
+ return $"{type}?";
+ }
+ return type;
+ }
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/ExtraFilesGenerator.cs b/src/Speckle.ProxyGenerator/FileGenerators/ExtraFilesGenerator.cs
similarity index 100%
rename from src/ProxyInterfaceSourceGenerator/FileGenerators/ExtraFilesGenerator.cs
rename to src/Speckle.ProxyGenerator/FileGenerators/ExtraFilesGenerator.cs
diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/IFileGenerator.cs b/src/Speckle.ProxyGenerator/FileGenerators/IFileGenerator.cs
similarity index 96%
rename from src/ProxyInterfaceSourceGenerator/FileGenerators/IFileGenerator.cs
rename to src/Speckle.ProxyGenerator/FileGenerators/IFileGenerator.cs
index 237d747..cb0457c 100644
--- a/src/ProxyInterfaceSourceGenerator/FileGenerators/IFileGenerator.cs
+++ b/src/Speckle.ProxyGenerator/FileGenerators/IFileGenerator.cs
@@ -1,8 +1,8 @@
-using ProxyInterfaceSourceGenerator.Models;
-
-namespace ProxyInterfaceSourceGenerator.FileGenerators;
-
-internal interface IFileGenerator
-{
- FileData GenerateFile();
+using ProxyInterfaceSourceGenerator.Models;
+
+namespace ProxyInterfaceSourceGenerator.FileGenerators;
+
+internal interface IFileGenerator
+{
+ FileData GenerateFile();
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/IFilesGenerator.cs b/src/Speckle.ProxyGenerator/FileGenerators/IFilesGenerator.cs
similarity index 96%
rename from src/ProxyInterfaceSourceGenerator/FileGenerators/IFilesGenerator.cs
rename to src/Speckle.ProxyGenerator/FileGenerators/IFilesGenerator.cs
index 4126668..6a98c78 100644
--- a/src/ProxyInterfaceSourceGenerator/FileGenerators/IFilesGenerator.cs
+++ b/src/Speckle.ProxyGenerator/FileGenerators/IFilesGenerator.cs
@@ -1,8 +1,8 @@
-using ProxyInterfaceSourceGenerator.Models;
-
-namespace ProxyInterfaceSourceGenerator.FileGenerators;
-
-internal interface IFilesGenerator
-{
- IEnumerable GenerateFiles();
+using ProxyInterfaceSourceGenerator.Models;
+
+namespace ProxyInterfaceSourceGenerator.FileGenerators;
+
+internal interface IFilesGenerator
+{
+ IEnumerable GenerateFiles();
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/PartialInterfacesGenerator.cs b/src/Speckle.ProxyGenerator/FileGenerators/PartialInterfacesGenerator.cs
similarity index 97%
rename from src/ProxyInterfaceSourceGenerator/FileGenerators/PartialInterfacesGenerator.cs
rename to src/Speckle.ProxyGenerator/FileGenerators/PartialInterfacesGenerator.cs
index c4c7448..505cb71 100644
--- a/src/ProxyInterfaceSourceGenerator/FileGenerators/PartialInterfacesGenerator.cs
+++ b/src/Speckle.ProxyGenerator/FileGenerators/PartialInterfacesGenerator.cs
@@ -1,184 +1,184 @@
-using System.Diagnostics.CodeAnalysis;
-using System.Text;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using ProxyInterfaceSourceGenerator.Enums;
-using ProxyInterfaceSourceGenerator.Extensions;
-using ProxyInterfaceSourceGenerator.Models;
-using ProxyInterfaceSourceGenerator.Utils;
-
-namespace ProxyInterfaceSourceGenerator.FileGenerators;
-
-internal class PartialInterfacesGenerator : BaseGenerator, IFilesGenerator
-{
- private IReadOnlyCollection _implementedInterfaces = new List();
-
- public PartialInterfacesGenerator(Context context, bool supportsNullable) : base(context, supportsNullable)
- {
- }
-
- public IEnumerable GenerateFiles()
- {
- foreach (var ci in Context.Candidates)
- {
- if (TryGenerateFile(ci.Key, ci.Value, out var file))
- {
- yield return file;
- }
- }
- }
-
- private bool TryGenerateFile(InterfaceDeclarationSyntax ci, ProxyData pd, [NotNullWhen(true)] out FileData? fileData)
- {
- fileData = default;
-
- if (!TryGetNamedTypeSymbolByFullName(TypeKind.Interface, ci.Identifier.ToString(), pd.Usings, out var sourceInterfaceSymbol))
- {
- return false;
- }
-
- if (!TryGetNamedTypeSymbolByFullName(TypeKind.Class, pd.FullMetadataTypeName, pd.Usings, out var targetClassSymbol))
- {
- return false;
- }
-
- var interfaceName = ResolveInterfaceNameWithOptionalTypeConstraints(targetClassSymbol.Symbol, pd.ShortInterfaceName);
-
- fileData = new FileData(
- $"{sourceInterfaceSymbol.Symbol.GetFullMetadataName()}.g.cs",
- CreatePartialInterfaceCode(pd.Namespace, targetClassSymbol, interfaceName, pd)
- );
-
- return true;
- }
-
- private string CreatePartialInterfaceCode(
- string ns,
- ClassSymbol classSymbol,
- string interfaceName,
- ProxyData proxyData)
- {
- var extendsProxyClasses = GetExtendsProxyData(proxyData, classSymbol);
- _implementedInterfaces = classSymbol.Symbol.ResolveImplementedInterfaces(proxyData.ProxyBaseClasses);
- var implementedInterfacesNames = _implementedInterfaces.Select(i => i.ToFullyQualifiedDisplayString()).ToArray();
- var implements = implementedInterfacesNames.Any() ? $" : {string.Join(", ", implementedInterfacesNames)}" : string.Empty;
- var @new = extendsProxyClasses.Any() ? "new " : string.Empty;
- var (namespaceStart, namespaceEnd) = NamespaceBuilder.Build(ns);
- var events = GenerateEvents(classSymbol, proxyData);
- var properties = GenerateProperties(classSymbol, proxyData);
- var methods = GenerateMethods(classSymbol, proxyData).TrimEnd();
-
- return $@"//----------------------------------------------------------------------------------------
-//
-// This code was generated by https://github.com/StefH/ProxyInterfaceSourceGenerator.
-//
-// Changes to this file may cause incorrect behavior and will be lost if
-// the code is regenerated.
-//
-//----------------------------------------------------------------------------------------
-
-{SupportsNullable.IIf("#nullable enable")}
-using System;
-
-{namespaceStart}
- public partial interface {interfaceName}{implements}
- {{
- {@new}{classSymbol} _Instance {{ get; }}
-
-{events +
-properties +
-methods}
- }}
-{namespaceEnd}
-{SupportsNullable.IIf("#nullable restore")}";
- }
-
- private Func InterfaceFilter() where T : ISymbol
- {
- var hashSet = new HashSet();
- foreach (var @interface in _implementedInterfaces)
- {
- var members = @interface.AllInterfaces.Aggregate(@interface.GetMembers(), (xs, x) => xs.AddRange(x.GetMembers()));
- foreach (var member in members)
- {
- hashSet.Add(member.Name);
- }
- }
-
- // Member is not already implemented in another interface.
- return t => !hashSet.Contains(t.Name);
- }
-
- private string GenerateProperties(ClassSymbol targetClassSymbol, ProxyData proxyData)
- {
- var str = new StringBuilder();
-
- foreach (var property in MemberHelper.GetPublicProperties(targetClassSymbol, proxyData, InterfaceFilter()))
- {
- var type = GetPropertyType(property, out var isReplaced);
-
- var getterSetter = isReplaced ? property.ToPropertyDetails(type) : property.ToPropertyDetails();
- if (getterSetter is null)
- {
- continue;
- }
-
- var propertyName = getterSetter.Value.PropertyName;
-
- if (property.IsIndexer)
- {
- var methodParameters = GetMethodParameters(property.Parameters, true);
- propertyName = $"this[{string.Join(", ", methodParameters)}]";
- }
-
- foreach (var attribute in property.GetAttributesAsList())
- {
- str.AppendLine($" {attribute}");
- }
-
- str.AppendLine($" {getterSetter.Value.PropertyType} {propertyName} {getterSetter.Value.GetSet}");
- str.AppendLine();
- }
- return str.ToString();
- }
-
- private string GenerateMethods(ClassSymbol targetClassSymbol, ProxyData proxyData)
- {
- var str = new StringBuilder();
- foreach (var method in MemberHelper.GetPublicMethods(targetClassSymbol, proxyData, InterfaceFilter()))
- {
- var methodParameters = GetMethodParameters(method.Parameters, true);
- var whereStatement = GetWhereStatementFromMethod(method);
-
- foreach (var attribute in method.GetAttributesAsList())
- {
- str.AppendLine($" {attribute}");
- }
-
- str.AppendLine($" {GetReplacedTypeAsString(method.ReturnType, out _)} {method.GetMethodNameWithOptionalTypeParameters()}({string.Join(", ", methodParameters)}){whereStatement};");
- str.AppendLine();
- }
-
- return str.ToString();
- }
-
- private string GenerateEvents(ClassSymbol targetClassSymbol, ProxyData proxyData)
- {
- var str = new StringBuilder();
- foreach (var @event in MemberHelper.GetPublicEvents(targetClassSymbol, proxyData, InterfaceFilter()))
- {
- var ps = @event.First().Parameters.First();
- var type = ps.GetTypeEnum() == TypeEnum.Complex ? GetParameterType(ps, out _) : ps.Type.ToString();
-
- foreach (var attribute in ps.GetAttributesAsList())
- {
- str.AppendLine($" {attribute}");
- }
-
- str.AppendLine($" event {type} {@event.Key.GetSanitizedName()};");
- str.AppendLine();
- }
-
- return str.ToString();
- }
+using System.Diagnostics.CodeAnalysis;
+using System.Text;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using ProxyInterfaceSourceGenerator.Enums;
+using ProxyInterfaceSourceGenerator.Extensions;
+using ProxyInterfaceSourceGenerator.Models;
+using ProxyInterfaceSourceGenerator.Utils;
+
+namespace ProxyInterfaceSourceGenerator.FileGenerators;
+
+internal class PartialInterfacesGenerator : BaseGenerator, IFilesGenerator
+{
+ private IReadOnlyCollection _implementedInterfaces = new List();
+
+ public PartialInterfacesGenerator(Context context, bool supportsNullable) : base(context, supportsNullable)
+ {
+ }
+
+ public IEnumerable GenerateFiles()
+ {
+ foreach (var ci in Context.Candidates)
+ {
+ if (TryGenerateFile(ci.Key, ci.Value, out var file))
+ {
+ yield return file;
+ }
+ }
+ }
+
+ private bool TryGenerateFile(InterfaceDeclarationSyntax ci, ProxyData pd, [NotNullWhen(true)] out FileData? fileData)
+ {
+ fileData = default;
+
+ if (!TryGetNamedTypeSymbolByFullName(TypeKind.Interface, ci.Identifier.ToString(), pd.Usings, out var sourceInterfaceSymbol))
+ {
+ return false;
+ }
+
+ if (!TryGetNamedTypeSymbolByFullName(TypeKind.Class, pd.FullMetadataTypeName, pd.Usings, out var targetClassSymbol))
+ {
+ return false;
+ }
+
+ var interfaceName = ResolveInterfaceNameWithOptionalTypeConstraints(targetClassSymbol.Symbol, pd.ShortInterfaceName);
+
+ fileData = new FileData(
+ $"{sourceInterfaceSymbol.Symbol.GetFullMetadataName()}.g.cs",
+ CreatePartialInterfaceCode(pd.Namespace, targetClassSymbol, interfaceName, pd)
+ );
+
+ return true;
+ }
+
+ private string CreatePartialInterfaceCode(
+ string ns,
+ ClassSymbol classSymbol,
+ string interfaceName,
+ ProxyData proxyData)
+ {
+ var extendsProxyClasses = GetExtendsProxyData(proxyData, classSymbol);
+ _implementedInterfaces = classSymbol.Symbol.ResolveImplementedInterfaces(proxyData.ProxyBaseClasses);
+ var implementedInterfacesNames = _implementedInterfaces.Select(i => i.ToFullyQualifiedDisplayString()).ToArray();
+ var implements = implementedInterfacesNames.Any() ? $" : {string.Join(", ", implementedInterfacesNames)}" : string.Empty;
+ var @new = extendsProxyClasses.Any() ? "new " : string.Empty;
+ var (namespaceStart, namespaceEnd) = NamespaceBuilder.Build(ns);
+ var events = GenerateEvents(classSymbol, proxyData);
+ var properties = GenerateProperties(classSymbol, proxyData);
+ var methods = GenerateMethods(classSymbol, proxyData).TrimEnd();
+
+ return $@"//----------------------------------------------------------------------------------------
+//
+// This code was generated by https://github.com/StefH/ProxyInterfaceSourceGenerator.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//----------------------------------------------------------------------------------------
+
+{SupportsNullable.IIf("#nullable enable")}
+using System;
+
+{namespaceStart}
+ public partial interface {interfaceName}{implements}
+ {{
+ {@new}{classSymbol} _Instance {{ get; }}
+
+{events +
+properties +
+methods}
+ }}
+{namespaceEnd}
+{SupportsNullable.IIf("#nullable restore")}";
+ }
+
+ private Func InterfaceFilter() where T : ISymbol
+ {
+ var hashSet = new HashSet();
+ foreach (var @interface in _implementedInterfaces)
+ {
+ var members = @interface.AllInterfaces.Aggregate(@interface.GetMembers(), (xs, x) => xs.AddRange(x.GetMembers()));
+ foreach (var member in members)
+ {
+ hashSet.Add(member.Name);
+ }
+ }
+
+ // Member is not already implemented in another interface.
+ return t => !hashSet.Contains(t.Name);
+ }
+
+ private string GenerateProperties(ClassSymbol targetClassSymbol, ProxyData proxyData)
+ {
+ var str = new StringBuilder();
+
+ foreach (var property in MemberHelper.GetPublicProperties(targetClassSymbol, proxyData, InterfaceFilter()))
+ {
+ var type = GetPropertyType(property, out var isReplaced);
+
+ var getterSetter = isReplaced ? property.ToPropertyDetails(type) : property.ToPropertyDetails();
+ if (getterSetter is null)
+ {
+ continue;
+ }
+
+ var propertyName = getterSetter.Value.PropertyName;
+
+ if (property.IsIndexer)
+ {
+ var methodParameters = GetMethodParameters(property.Parameters, true);
+ propertyName = $"this[{string.Join(", ", methodParameters)}]";
+ }
+
+ foreach (var attribute in property.GetAttributesAsList())
+ {
+ str.AppendLine($" {attribute}");
+ }
+
+ str.AppendLine($" {getterSetter.Value.PropertyType} {propertyName} {getterSetter.Value.GetSet}");
+ str.AppendLine();
+ }
+ return str.ToString();
+ }
+
+ private string GenerateMethods(ClassSymbol targetClassSymbol, ProxyData proxyData)
+ {
+ var str = new StringBuilder();
+ foreach (var method in MemberHelper.GetPublicMethods(targetClassSymbol, proxyData, InterfaceFilter()))
+ {
+ var methodParameters = GetMethodParameters(method.Parameters, true);
+ var whereStatement = GetWhereStatementFromMethod(method);
+
+ foreach (var attribute in method.GetAttributesAsList())
+ {
+ str.AppendLine($" {attribute}");
+ }
+
+ str.AppendLine($" {GetReplacedTypeAsString(method.ReturnType, out _)} {method.GetMethodNameWithOptionalTypeParameters()}({string.Join(", ", methodParameters)}){whereStatement};");
+ str.AppendLine();
+ }
+
+ return str.ToString();
+ }
+
+ private string GenerateEvents(ClassSymbol targetClassSymbol, ProxyData proxyData)
+ {
+ var str = new StringBuilder();
+ foreach (var @event in MemberHelper.GetPublicEvents(targetClassSymbol, proxyData, InterfaceFilter()))
+ {
+ var ps = @event.First().Parameters.First();
+ var type = ps.GetTypeEnum() == TypeEnum.Complex ? GetParameterType(ps, out _) : ps.Type.ToString();
+
+ foreach (var attribute in ps.GetAttributesAsList())
+ {
+ str.AppendLine($" {attribute}");
+ }
+
+ str.AppendLine($" event {type} {@event.Key.GetSanitizedName()};");
+ str.AppendLine();
+ }
+
+ return str.ToString();
+ }
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.AutoMapper.cs b/src/Speckle.ProxyGenerator/FileGenerators/ProxyClassesGenerator.AutoMapper.cs
similarity index 100%
rename from src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.AutoMapper.cs
rename to src/Speckle.ProxyGenerator/FileGenerators/ProxyClassesGenerator.AutoMapper.cs
diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.Mapster.cs b/src/Speckle.ProxyGenerator/FileGenerators/ProxyClassesGenerator.Mapster.cs
similarity index 100%
rename from src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.Mapster.cs
rename to src/Speckle.ProxyGenerator/FileGenerators/ProxyClassesGenerator.Mapster.cs
diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.cs b/src/Speckle.ProxyGenerator/FileGenerators/ProxyClassesGenerator.cs
similarity index 97%
rename from src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.cs
rename to src/Speckle.ProxyGenerator/FileGenerators/ProxyClassesGenerator.cs
index 58b0cc9..4e9a0bc 100644
--- a/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.cs
+++ b/src/Speckle.ProxyGenerator/FileGenerators/ProxyClassesGenerator.cs
@@ -1,383 +1,383 @@
-using System.Diagnostics.CodeAnalysis;
-using System.Text;
-using Microsoft.CodeAnalysis;
-using ProxyInterfaceSourceGenerator.Builders;
-using ProxyInterfaceSourceGenerator.Enums;
-using ProxyInterfaceSourceGenerator.Extensions;
-using ProxyInterfaceSourceGenerator.Models;
-using ProxyInterfaceSourceGenerator.Types;
-using ProxyInterfaceSourceGenerator.Utils;
-
-namespace ProxyInterfaceSourceGenerator.FileGenerators;
-
-internal partial class ProxyClassesGenerator : BaseGenerator, IFilesGenerator
-{
- public ProxyClassesGenerator(Context context, bool supportsNullable) : base(context, supportsNullable)
- {
- }
-
- public IEnumerable GenerateFiles()
- {
- foreach (var ci in Context.Candidates)
- {
- if (TryGenerateFile(ci.Value, out var file))
- {
- yield return file;
- }
- }
- }
-
- [SuppressMessage("MicrosoftCodeAnalysisCorrectness", "RS1024:Compare symbols correctly", Justification = "")]
- private bool TryGenerateFile(ProxyData pd, [NotNullWhen(true)] out FileData? fileData)
- {
- fileData = default;
-
- if (!TryGetNamedTypeSymbolByFullName(TypeKind.Class, pd.FullMetadataTypeName, pd.Usings, out var targetClassSymbol))
- {
- return false;
- }
-
- var interfaceName = ResolveInterfaceNameWithOptionalTypeConstraints(targetClassSymbol.Symbol, pd.FullInterfaceName);
- var className = targetClassSymbol.Symbol.ResolveProxyClassName();
- var constructorName = $"{targetClassSymbol.Symbol.Name}Proxy";
-
- var extendsProxyClasses = GetExtendsProxyData(pd, targetClassSymbol);
-
- fileData = new FileData(
- $"{targetClassSymbol.Symbol.GetFullMetadataName()}Proxy.g.cs",
- CreateProxyClassCode(pd, targetClassSymbol, extendsProxyClasses, interfaceName, className, constructorName)
- );
-
- return true;
- }
-
- private string CreateProxyClassCode(
- ProxyData pd,
- ClassSymbol targetClassSymbol,
- IReadOnlyList extendsProxyClasses,
- string interfaceName,
- string className,
- string constructorName)
- {
- var firstExtends = extendsProxyClasses.FirstOrDefault();
- var extends = string.Empty;
- var @base = string.Empty;
- var @new = string.Empty;
- var instanceBaseDefinition = string.Empty;
- var instanceBaseSetter = string.Empty;
-
- if (firstExtends is not null)
- {
- extends = $"global::{firstExtends.NamespaceDot}{firstExtends.ShortMetadataName}Proxy, ";
- @base = " : base(instance)";
- @new = "new ";
- instanceBaseDefinition = $"public {firstExtends.FullQualifiedTypeName} _Instance{firstExtends.FullQualifiedTypeName.GetLastPart()} {{ get; }}";
- instanceBaseSetter = $"_Instance{firstExtends.FullQualifiedTypeName.GetLastPart()} = instance;";
- }
-
- var @abstract = string.Empty; // targetClassSymbol.Symbol.IsAbstract ? "abstract " : string.Empty;
- var properties = GeneratePublicProperties(targetClassSymbol, pd);
- var methods = GeneratePublicMethods(targetClassSymbol, pd);
- var events = GenerateEvents(targetClassSymbol, pd);
- var operators = GenerateOperators(targetClassSymbol, pd);
-
- var configurationForMapster = string.Empty;
- if (Context.ReplacedTypes.Count > 0)
- {
- configurationForMapster = GenerateMapperConfigurationForMapster();
- }
-
- var (namespaceStart, namespaceEnd) = NamespaceBuilder.Build(pd.Namespace);
-
- var accessibility = pd.Accessibility == ProxyClassAccessibility.Internal ? "internal" : "public";
-
- return $@"//----------------------------------------------------------------------------------------
-//
-// This code was generated by https://github.com/StefH/ProxyInterfaceSourceGenerator.
-//
-// Changes to this file may cause incorrect behavior and will be lost if
-// the code is regenerated.
-//
-//----------------------------------------------------------------------------------------
-
-{SupportsNullable.IIf("#nullable enable")}
-using System;
-
-{namespaceStart}
- {accessibility} {@abstract}partial class {className} : {extends}{interfaceName}
- {{
- public {@new}{targetClassSymbol} _Instance {{ get; }}
- {instanceBaseDefinition}
-{events +
-properties +
-methods +
-operators}
- public {constructorName}({targetClassSymbol} instance){@base}
- {{
- _Instance = instance;
- {instanceBaseSetter}
-
-{configurationForMapster}
- }}
- }}
-{namespaceEnd}
-{SupportsNullable.IIf("#nullable restore")}";
- }
-
- private string GeneratePublicProperties(ClassSymbol targetClassSymbol, ProxyData proxyData)
- {
- var str = new StringBuilder();
-
- foreach (var property in MemberHelper.GetPublicProperties(targetClassSymbol, proxyData))
- {
- var type = GetPropertyType(property, out var isReplaced);
-
- var instance = !property.IsStatic ?
- "_Instance" :
- $"{targetClassSymbol.Symbol}";
-
- var propertyName = property.GetSanitizedName();
- var instancePropertyName = $"{instance}.{propertyName}";
- if (property.IsIndexer)
- {
- var parameters = GetMethodParameters(property.Parameters, true);
- propertyName = $"this[{string.Join(", ", parameters)}]";
-
- var instanceParameters = GetMethodParameters(property.Parameters, false);
- instancePropertyName = $"{instance}[{string.Join(", ", instanceParameters)}]";
- }
-
- var overrideOrVirtual = string.Empty;
- if (property.IsOverride)
- {
- overrideOrVirtual = "override ";
- }
- else if (property.IsVirtual)
- {
- overrideOrVirtual = "virtual ";
- }
-
- var getIsPublic = property.GetMethod.IsPublic();
- var setIsPublic = property.SetMethod.IsPublic();
-
- if (!getIsPublic && !setIsPublic)
- {
- continue;
- }
-
- string get;
- string set;
- if (isReplaced)
- {
- get = getIsPublic ? $"get => Mapster.TypeAdapter.Adapt<{type}>({instancePropertyName}); " : string.Empty;
- set = setIsPublic ? $"set => {instancePropertyName} = Mapster.TypeAdapter.Adapt<{property.Type}>(value); " : string.Empty;
- }
- else
- {
- get = getIsPublic ? $"get => {instancePropertyName}; " : string.Empty;
- set = setIsPublic ? $"set => {instancePropertyName} = value; " : string.Empty;
- }
-
- foreach (var attribute in property.GetAttributesAsList())
- {
- str.AppendLine($" {attribute}");
- }
-
- str.AppendLine($" public {overrideOrVirtual}{type} {propertyName} {{ {get}{set}}}");
- str.AppendLine();
- }
-
- return str.ToString();
- }
-
- private string GeneratePublicMethods(ClassSymbol targetClassSymbol, ProxyData proxyData)
- {
- var str = new StringBuilder();
-
- var methods = MemberHelper.GetPublicMethods(targetClassSymbol, proxyData);
-
- foreach (var method in methods)
- {
- var methodParameters = new List();
- var invokeParameters = new List();
-
- foreach (var parameterSymbol in method.Parameters)
- {
- var type = GetParameterType(parameterSymbol, out _);
-
- methodParameters.Add(MethodParameterBuilder.Build(parameterSymbol, type));
-
- // Do not add the '_' for a 'ref' parameter.
- invokeParameters.Add($"{parameterSymbol.GetRefKindPrefix()}{parameterSymbol.GetSanitizedName()}{(!parameterSymbol.IsRef()).IIf("_")}");
- }
-
- string overrideOrVirtual = string.Empty;
- if (method.IsOverride && method.OverriddenMethod != null)
- {
- var baseType = method.OverriddenMethod.ContainingType.GetFullType();
- if (TryGetNamedTypeSymbolByFullName(TypeKind.Class, baseType, Enumerable.Empty(), out _))
- {
- overrideOrVirtual = "override ";
- }
- }
- else if (method.IsVirtual)
- {
- overrideOrVirtual = "virtual ";
- }
-
- string returnTypeAsString = GetReplacedTypeAsString(method.ReturnType, out var returnIsReplaced);
-
- var whereStatement = GetWhereStatementFromMethod(method);
-
- foreach (var attribute in method.GetAttributesAsList())
- {
- str.AppendLine($" {attribute}");
- }
-
- str.AppendLine($" public {overrideOrVirtual}{returnTypeAsString} {method.GetMethodNameWithOptionalTypeParameters()}({string.Join(", ", methodParameters)}){whereStatement}");
- str.AppendLine(@" {");
-
- foreach (var ps in method.Parameters.Where(p => !p.IsRef()))
- {
- var type = FixType(ps.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat), ps.Type.NullableAnnotation);
- string normalOrMap = $" = {ps.GetSanitizedName()}";
- if (ps.RefKind == RefKind.Out)
- {
- normalOrMap = string.Empty;
- }
- else
- {
- _ = GetParameterType(ps, out var isReplaced); // TODO : response is not used?
- if (isReplaced)
- {
- normalOrMap = $" = Mapster.TypeAdapter.Adapt<{type}>({ps.GetSanitizedName()})";
- }
- }
-
- str.AppendLine($" {type} {ps.GetSanitizedName()}_{normalOrMap};");
- }
-
- var methodName = method.GetMethodNameWithOptionalTypeParameters();
- var alternateReturnVariableName = $"result_{methodName.GetDeterministicHashCodeAsString()}";
-
- string instance = method.IsStatic ? targetClassSymbol.Symbol.ToFullyQualifiedDisplayString() : "_Instance";
-
- if (returnTypeAsString == "void")
- {
- str.AppendLine($" {instance}.{methodName}({string.Join(", ", invokeParameters)});");
- }
- else
- {
- str.AppendLine($" var {alternateReturnVariableName} = {instance}.{methodName}({string.Join(", ", invokeParameters)});");
- }
-
- foreach (var ps in method.Parameters.Where(p => p.RefKind == RefKind.Out))
- {
- string normalOrMap = $" = {ps.GetSanitizedName()}_";
- if (ps.GetTypeEnum() == TypeEnum.Complex)
- {
- var type = GetParameterType(ps, out var isReplaced);
- if (isReplaced)
- {
- normalOrMap = $" = Mapster.TypeAdapter.Adapt<{type}>({ps.GetSanitizedName()}_)";
- }
- }
-
- str.AppendLine($" {ps.GetSanitizedName()}{normalOrMap};");
- }
-
- if (returnTypeAsString != "void")
- {
- if (returnIsReplaced)
- {
- str.AppendLine($" return Mapster.TypeAdapter.Adapt<{returnTypeAsString}>({alternateReturnVariableName});");
- }
- else
- {
- str.AppendLine($" return {alternateReturnVariableName};");
- }
- }
-
- str.AppendLine(" }");
- str.AppendLine();
- }
-
- return str.ToString();
- }
-
- private string GenerateEvents(ClassSymbol targetClassSymbol, ProxyData proxyData)
- {
- var str = new StringBuilder();
- foreach (var @event in MemberHelper.GetPublicEvents(targetClassSymbol, proxyData))
- {
- var name = @event.Key.GetSanitizedName();
- var ps = @event.First().Parameters.First();
- var type = ps.GetTypeEnum() == TypeEnum.Complex ? GetParameterType(ps, out _) : ps.Type.ToString();
-
- foreach (var attribute in ps.GetAttributesAsList())
- {
- str.AppendLine($" {attribute}");
- }
-
- str.Append($" public event {type} {name} {{");
-
- if (@event.Any(e => e.MethodKind == MethodKind.EventAdd))
- {
- str.Append($" add {{ _Instance.{name} += value; }}");
- }
- if (@event.Any(e => e.MethodKind == MethodKind.EventRemove))
- {
- str.Append($" remove {{ _Instance.{name} -= value; }}");
- }
-
- str.AppendLine(" }");
- str.AppendLine();
- }
-
- return str.ToString();
- }
-
- private string GenerateOperators(ClassSymbol targetClassSymbol, ProxyData proxyData)
- {
- var str = new StringBuilder();
- foreach (var @operator in MemberHelper.GetPublicStaticOperators(targetClassSymbol, proxyData))
- {
- foreach (var attribute in @operator.GetAttributesAsList())
- {
- str.AppendLine($" {attribute}");
- }
-
- if (!@operator.Parameters.Any())
- {
- continue;
- }
-
- var parameter = @operator.Parameters.First();
- var proxyClassName = targetClassSymbol.Symbol.ResolveProxyClassName();
-
- var operatorType = @operator.Name.ToLowerInvariant().Replace("op_", string.Empty);
- if (operatorType == "explicit")
- {
- var returnTypeAsString = GetReplacedTypeAsString(@operator.ReturnType, out _);
-
- str.AppendLine($" public static explicit operator {returnTypeAsString}({proxyClassName} {parameter.Name})");
- str.AppendLine(@" {");
- str.AppendLine($" return ({returnTypeAsString}) {parameter.Name}._Instance;");
- str.AppendLine(@" }");
- }
- else
- {
- var returnTypeAsString = GetReplacedTypeAsString(parameter.Type, out _);
-
- str.AppendLine($" public static implicit operator {proxyClassName}({returnTypeAsString} {parameter.Name})");
- str.AppendLine(@" {");
- str.AppendLine($" return new {proxyClassName}(({targetClassSymbol.Symbol.Name}) {parameter.Name});");
- str.AppendLine(@" }");
- }
-
- str.AppendLine();
- }
-
- return str.ToString();
- }
+using System.Diagnostics.CodeAnalysis;
+using System.Text;
+using Microsoft.CodeAnalysis;
+using ProxyInterfaceSourceGenerator.Builders;
+using ProxyInterfaceSourceGenerator.Enums;
+using ProxyInterfaceSourceGenerator.Extensions;
+using ProxyInterfaceSourceGenerator.Models;
+using ProxyInterfaceSourceGenerator.Types;
+using ProxyInterfaceSourceGenerator.Utils;
+
+namespace ProxyInterfaceSourceGenerator.FileGenerators;
+
+internal partial class ProxyClassesGenerator : BaseGenerator, IFilesGenerator
+{
+ public ProxyClassesGenerator(Context context, bool supportsNullable) : base(context, supportsNullable)
+ {
+ }
+
+ public IEnumerable GenerateFiles()
+ {
+ foreach (var ci in Context.Candidates)
+ {
+ if (TryGenerateFile(ci.Value, out var file))
+ {
+ yield return file;
+ }
+ }
+ }
+
+ [SuppressMessage("MicrosoftCodeAnalysisCorrectness", "RS1024:Compare symbols correctly", Justification = "")]
+ private bool TryGenerateFile(ProxyData pd, [NotNullWhen(true)] out FileData? fileData)
+ {
+ fileData = default;
+
+ if (!TryGetNamedTypeSymbolByFullName(TypeKind.Class, pd.FullMetadataTypeName, pd.Usings, out var targetClassSymbol))
+ {
+ return false;
+ }
+
+ var interfaceName = ResolveInterfaceNameWithOptionalTypeConstraints(targetClassSymbol.Symbol, pd.FullInterfaceName);
+ var className = targetClassSymbol.Symbol.ResolveProxyClassName();
+ var constructorName = $"{targetClassSymbol.Symbol.Name}Proxy";
+
+ var extendsProxyClasses = GetExtendsProxyData(pd, targetClassSymbol);
+
+ fileData = new FileData(
+ $"{targetClassSymbol.Symbol.GetFullMetadataName()}Proxy.g.cs",
+ CreateProxyClassCode(pd, targetClassSymbol, extendsProxyClasses, interfaceName, className, constructorName)
+ );
+
+ return true;
+ }
+
+ private string CreateProxyClassCode(
+ ProxyData pd,
+ ClassSymbol targetClassSymbol,
+ IReadOnlyList extendsProxyClasses,
+ string interfaceName,
+ string className,
+ string constructorName)
+ {
+ var firstExtends = extendsProxyClasses.FirstOrDefault();
+ var extends = string.Empty;
+ var @base = string.Empty;
+ var @new = string.Empty;
+ var instanceBaseDefinition = string.Empty;
+ var instanceBaseSetter = string.Empty;
+
+ if (firstExtends is not null)
+ {
+ extends = $"global::{firstExtends.NamespaceDot}{firstExtends.ShortMetadataName}Proxy, ";
+ @base = " : base(instance)";
+ @new = "new ";
+ instanceBaseDefinition = $"public {firstExtends.FullQualifiedTypeName} _Instance{firstExtends.FullQualifiedTypeName.GetLastPart()} {{ get; }}";
+ instanceBaseSetter = $"_Instance{firstExtends.FullQualifiedTypeName.GetLastPart()} = instance;";
+ }
+
+ var @abstract = string.Empty; // targetClassSymbol.Symbol.IsAbstract ? "abstract " : string.Empty;
+ var properties = GeneratePublicProperties(targetClassSymbol, pd);
+ var methods = GeneratePublicMethods(targetClassSymbol, pd);
+ var events = GenerateEvents(targetClassSymbol, pd);
+ var operators = GenerateOperators(targetClassSymbol, pd);
+
+ var configurationForMapster = string.Empty;
+ if (Context.ReplacedTypes.Count > 0)
+ {
+ configurationForMapster = GenerateMapperConfigurationForMapster();
+ }
+
+ var (namespaceStart, namespaceEnd) = NamespaceBuilder.Build(pd.Namespace);
+
+ var accessibility = pd.Accessibility == ProxyClassAccessibility.Internal ? "internal" : "public";
+
+ return $@"//----------------------------------------------------------------------------------------
+//
+// This code was generated by https://github.com/StefH/ProxyInterfaceSourceGenerator.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//----------------------------------------------------------------------------------------
+
+{SupportsNullable.IIf("#nullable enable")}
+using System;
+
+{namespaceStart}
+ {accessibility} {@abstract}partial class {className} : {extends}{interfaceName}
+ {{
+ public {@new}{targetClassSymbol} _Instance {{ get; }}
+ {instanceBaseDefinition}
+{events +
+properties +
+methods +
+operators}
+ public {constructorName}({targetClassSymbol} instance){@base}
+ {{
+ _Instance = instance;
+ {instanceBaseSetter}
+
+{configurationForMapster}
+ }}
+ }}
+{namespaceEnd}
+{SupportsNullable.IIf("#nullable restore")}";
+ }
+
+ private string GeneratePublicProperties(ClassSymbol targetClassSymbol, ProxyData proxyData)
+ {
+ var str = new StringBuilder();
+
+ foreach (var property in MemberHelper.GetPublicProperties(targetClassSymbol, proxyData))
+ {
+ var type = GetPropertyType(property, out var isReplaced);
+
+ var instance = !property.IsStatic ?
+ "_Instance" :
+ $"{targetClassSymbol.Symbol}";
+
+ var propertyName = property.GetSanitizedName();
+ var instancePropertyName = $"{instance}.{propertyName}";
+ if (property.IsIndexer)
+ {
+ var parameters = GetMethodParameters(property.Parameters, true);
+ propertyName = $"this[{string.Join(", ", parameters)}]";
+
+ var instanceParameters = GetMethodParameters(property.Parameters, false);
+ instancePropertyName = $"{instance}[{string.Join(", ", instanceParameters)}]";
+ }
+
+ var overrideOrVirtual = string.Empty;
+ if (property.IsOverride)
+ {
+ overrideOrVirtual = "override ";
+ }
+ else if (property.IsVirtual)
+ {
+ overrideOrVirtual = "virtual ";
+ }
+
+ var getIsPublic = property.GetMethod.IsPublic();
+ var setIsPublic = property.SetMethod.IsPublic();
+
+ if (!getIsPublic && !setIsPublic)
+ {
+ continue;
+ }
+
+ string get;
+ string set;
+ if (isReplaced)
+ {
+ get = getIsPublic ? $"get => Mapster.TypeAdapter.Adapt<{type}>({instancePropertyName}); " : string.Empty;
+ set = setIsPublic ? $"set => {instancePropertyName} = Mapster.TypeAdapter.Adapt<{property.Type}>(value); " : string.Empty;
+ }
+ else
+ {
+ get = getIsPublic ? $"get => {instancePropertyName}; " : string.Empty;
+ set = setIsPublic ? $"set => {instancePropertyName} = value; " : string.Empty;
+ }
+
+ foreach (var attribute in property.GetAttributesAsList())
+ {
+ str.AppendLine($" {attribute}");
+ }
+
+ str.AppendLine($" public {overrideOrVirtual}{type} {propertyName} {{ {get}{set}}}");
+ str.AppendLine();
+ }
+
+ return str.ToString();
+ }
+
+ private string GeneratePublicMethods(ClassSymbol targetClassSymbol, ProxyData proxyData)
+ {
+ var str = new StringBuilder();
+
+ var methods = MemberHelper.GetPublicMethods(targetClassSymbol, proxyData);
+
+ foreach (var method in methods)
+ {
+ var methodParameters = new List();
+ var invokeParameters = new List();
+
+ foreach (var parameterSymbol in method.Parameters)
+ {
+ var type = GetParameterType(parameterSymbol, out _);
+
+ methodParameters.Add(MethodParameterBuilder.Build(parameterSymbol, type));
+
+ // Do not add the '_' for a 'ref' parameter.
+ invokeParameters.Add($"{parameterSymbol.GetRefKindPrefix()}{parameterSymbol.GetSanitizedName()}{(!parameterSymbol.IsRef()).IIf("_")}");
+ }
+
+ string overrideOrVirtual = string.Empty;
+ if (method.IsOverride && method.OverriddenMethod != null)
+ {
+ var baseType = method.OverriddenMethod.ContainingType.GetFullType();
+ if (TryGetNamedTypeSymbolByFullName(TypeKind.Class, baseType, Enumerable.Empty(), out _))
+ {
+ overrideOrVirtual = "override ";
+ }
+ }
+ else if (method.IsVirtual)
+ {
+ overrideOrVirtual = "virtual ";
+ }
+
+ string returnTypeAsString = GetReplacedTypeAsString(method.ReturnType, out var returnIsReplaced);
+
+ var whereStatement = GetWhereStatementFromMethod(method);
+
+ foreach (var attribute in method.GetAttributesAsList())
+ {
+ str.AppendLine($" {attribute}");
+ }
+
+ str.AppendLine($" public {overrideOrVirtual}{returnTypeAsString} {method.GetMethodNameWithOptionalTypeParameters()}({string.Join(", ", methodParameters)}){whereStatement}");
+ str.AppendLine(@" {");
+
+ foreach (var ps in method.Parameters.Where(p => !p.IsRef()))
+ {
+ var type = FixType(ps.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat), ps.Type.NullableAnnotation);
+ string normalOrMap = $" = {ps.GetSanitizedName()}";
+ if (ps.RefKind == RefKind.Out)
+ {
+ normalOrMap = string.Empty;
+ }
+ else
+ {
+ _ = GetParameterType(ps, out var isReplaced); // TODO : response is not used?
+ if (isReplaced)
+ {
+ normalOrMap = $" = Mapster.TypeAdapter.Adapt<{type}>({ps.GetSanitizedName()})";
+ }
+ }
+
+ str.AppendLine($" {type} {ps.GetSanitizedName()}_{normalOrMap};");
+ }
+
+ var methodName = method.GetMethodNameWithOptionalTypeParameters();
+ var alternateReturnVariableName = $"result_{methodName.GetDeterministicHashCodeAsString()}";
+
+ string instance = method.IsStatic ? targetClassSymbol.Symbol.ToFullyQualifiedDisplayString() : "_Instance";
+
+ if (returnTypeAsString == "void")
+ {
+ str.AppendLine($" {instance}.{methodName}({string.Join(", ", invokeParameters)});");
+ }
+ else
+ {
+ str.AppendLine($" var {alternateReturnVariableName} = {instance}.{methodName}({string.Join(", ", invokeParameters)});");
+ }
+
+ foreach (var ps in method.Parameters.Where(p => p.RefKind == RefKind.Out))
+ {
+ string normalOrMap = $" = {ps.GetSanitizedName()}_";
+ if (ps.GetTypeEnum() == TypeEnum.Complex)
+ {
+ var type = GetParameterType(ps, out var isReplaced);
+ if (isReplaced)
+ {
+ normalOrMap = $" = Mapster.TypeAdapter.Adapt<{type}>({ps.GetSanitizedName()}_)";
+ }
+ }
+
+ str.AppendLine($" {ps.GetSanitizedName()}{normalOrMap};");
+ }
+
+ if (returnTypeAsString != "void")
+ {
+ if (returnIsReplaced)
+ {
+ str.AppendLine($" return Mapster.TypeAdapter.Adapt<{returnTypeAsString}>({alternateReturnVariableName});");
+ }
+ else
+ {
+ str.AppendLine($" return {alternateReturnVariableName};");
+ }
+ }
+
+ str.AppendLine(" }");
+ str.AppendLine();
+ }
+
+ return str.ToString();
+ }
+
+ private string GenerateEvents(ClassSymbol targetClassSymbol, ProxyData proxyData)
+ {
+ var str = new StringBuilder();
+ foreach (var @event in MemberHelper.GetPublicEvents(targetClassSymbol, proxyData))
+ {
+ var name = @event.Key.GetSanitizedName();
+ var ps = @event.First().Parameters.First();
+ var type = ps.GetTypeEnum() == TypeEnum.Complex ? GetParameterType(ps, out _) : ps.Type.ToString();
+
+ foreach (var attribute in ps.GetAttributesAsList())
+ {
+ str.AppendLine($" {attribute}");
+ }
+
+ str.Append($" public event {type} {name} {{");
+
+ if (@event.Any(e => e.MethodKind == MethodKind.EventAdd))
+ {
+ str.Append($" add {{ _Instance.{name} += value; }}");
+ }
+ if (@event.Any(e => e.MethodKind == MethodKind.EventRemove))
+ {
+ str.Append($" remove {{ _Instance.{name} -= value; }}");
+ }
+
+ str.AppendLine(" }");
+ str.AppendLine();
+ }
+
+ return str.ToString();
+ }
+
+ private string GenerateOperators(ClassSymbol targetClassSymbol, ProxyData proxyData)
+ {
+ var str = new StringBuilder();
+ foreach (var @operator in MemberHelper.GetPublicStaticOperators(targetClassSymbol, proxyData))
+ {
+ foreach (var attribute in @operator.GetAttributesAsList())
+ {
+ str.AppendLine($" {attribute}");
+ }
+
+ if (!@operator.Parameters.Any())
+ {
+ continue;
+ }
+
+ var parameter = @operator.Parameters.First();
+ var proxyClassName = targetClassSymbol.Symbol.ResolveProxyClassName();
+
+ var operatorType = @operator.Name.ToLowerInvariant().Replace("op_", string.Empty);
+ if (operatorType == "explicit")
+ {
+ var returnTypeAsString = GetReplacedTypeAsString(@operator.ReturnType, out _);
+
+ str.AppendLine($" public static explicit operator {returnTypeAsString}({proxyClassName} {parameter.Name})");
+ str.AppendLine(@" {");
+ str.AppendLine($" return ({returnTypeAsString}) {parameter.Name}._Instance;");
+ str.AppendLine(@" }");
+ }
+ else
+ {
+ var returnTypeAsString = GetReplacedTypeAsString(parameter.Type, out _);
+
+ str.AppendLine($" public static implicit operator {proxyClassName}({returnTypeAsString} {parameter.Name})");
+ str.AppendLine(@" {");
+ str.AppendLine($" return new {proxyClassName}(({targetClassSymbol.Symbol.Name}) {parameter.Name});");
+ str.AppendLine(@" }");
+ }
+
+ str.AppendLine();
+ }
+
+ return str.ToString();
+ }
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/Models/ClassSymbol.cs b/src/Speckle.ProxyGenerator/Models/ClassSymbol.cs
similarity index 100%
rename from src/ProxyInterfaceSourceGenerator/Models/ClassSymbol.cs
rename to src/Speckle.ProxyGenerator/Models/ClassSymbol.cs
diff --git a/src/ProxyInterfaceSourceGenerator/Models/ConstraintInfo.cs b/src/Speckle.ProxyGenerator/Models/ConstraintInfo.cs
similarity index 100%
rename from src/ProxyInterfaceSourceGenerator/Models/ConstraintInfo.cs
rename to src/Speckle.ProxyGenerator/Models/ConstraintInfo.cs
diff --git a/src/ProxyInterfaceSourceGenerator/Models/Context.cs b/src/Speckle.ProxyGenerator/Models/Context.cs
similarity index 100%
rename from src/ProxyInterfaceSourceGenerator/Models/Context.cs
rename to src/Speckle.ProxyGenerator/Models/Context.cs
diff --git a/src/ProxyInterfaceSourceGenerator/Models/FileData.cs b/src/Speckle.ProxyGenerator/Models/FileData.cs
similarity index 100%
rename from src/ProxyInterfaceSourceGenerator/Models/FileData.cs
rename to src/Speckle.ProxyGenerator/Models/FileData.cs
diff --git a/src/ProxyInterfaceSourceGenerator/Models/ProxyData.cs b/src/Speckle.ProxyGenerator/Models/ProxyData.cs
similarity index 100%
rename from src/ProxyInterfaceSourceGenerator/Models/ProxyData.cs
rename to src/Speckle.ProxyGenerator/Models/ProxyData.cs
diff --git a/src/ProxyInterfaceSourceGenerator/Properties/launchSettings.json b/src/Speckle.ProxyGenerator/Properties/launchSettings.json
similarity index 100%
rename from src/ProxyInterfaceSourceGenerator/Properties/launchSettings.json
rename to src/Speckle.ProxyGenerator/Properties/launchSettings.json
diff --git a/src/ProxyInterfaceSourceGenerator/ProxyInterfaceCodeGenerator.cs b/src/Speckle.ProxyGenerator/ProxyInterfaceCodeGenerator.cs
similarity index 97%
rename from src/ProxyInterfaceSourceGenerator/ProxyInterfaceCodeGenerator.cs
rename to src/Speckle.ProxyGenerator/ProxyInterfaceCodeGenerator.cs
index 40febd6..e63dee5 100644
--- a/src/ProxyInterfaceSourceGenerator/ProxyInterfaceCodeGenerator.cs
+++ b/src/Speckle.ProxyGenerator/ProxyInterfaceCodeGenerator.cs
@@ -1,106 +1,106 @@
-using System.Text;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.Text;
-using ProxyInterfaceSourceGenerator.FileGenerators;
-using ProxyInterfaceSourceGenerator.Models;
-using ProxyInterfaceSourceGenerator.SyntaxReceiver;
-
-namespace ProxyInterfaceSourceGenerator;
-
-[Generator]
-#if DEBUG
-public
-#else
-internal
-#endif
-class ProxyInterfaceCodeGenerator : ISourceGenerator
-{
- private readonly ExtraFilesGenerator _proxyAttributeGenerator = new();
-
- public void Initialize(GeneratorInitializationContext context)
- {
-#if DEBUGATTACH
- if (!System.Diagnostics.Debugger.IsAttached)
- {
- System.Diagnostics.Debugger.Launch();
- }
-#endif
- context.RegisterForSyntaxNotifications(() => new ProxySyntaxReceiver());
- }
-
- public void Execute(GeneratorExecutionContext context)
- {
- try
- {
- if (context.ParseOptions is not CSharpParseOptions csharpParseOptions)
- {
- throw new NotSupportedException("Only C# is supported.");
- }
-
- if (context.SyntaxContextReceiver is not ProxySyntaxReceiver receiver)
- {
- throw new NotSupportedException($"Only {nameof(ProxySyntaxReceiver)} is supported.");
- }
-
- // https://github.com/reactiveui/refit/blob/main/InterfaceStubGenerator.Core/InterfaceStubGenerator.cs
- var supportsNullable = csharpParseOptions.LanguageVersion >= LanguageVersion.CSharp8;
-
- GenerateProxyAttribute(context, receiver);
- GeneratePartialInterfaces(context, receiver, supportsNullable);
- GenerateProxyClasses(context, receiver, supportsNullable);
- }
- catch (Exception exception)
- {
- GenerateError(context, exception);
- }
- }
-
- private void GenerateError(GeneratorExecutionContext context, Exception exception)
- {
- var message = $"/*\r\n{nameof(ProxyInterfaceCodeGenerator)}\r\n\r\n[Exception]\r\n{exception}\r\n\r\n[StackTrace]\r\n{exception.StackTrace}*/";
- context.AddSource("Error.g", SourceText.From(message, Encoding.UTF8));
- }
-
- private void GenerateProxyAttribute(GeneratorExecutionContext ctx, ProxySyntaxReceiver receiver)
- {
- var context = new Context
- {
- GeneratorExecutionContext = ctx,
- Candidates = receiver.CandidateInterfaces
- };
-
- var attributeData = _proxyAttributeGenerator.GenerateFile();
- context.GeneratorExecutionContext.AddSource(attributeData.FileName, SourceText.From(attributeData.Text, Encoding.UTF8));
- }
-
- private static void GeneratePartialInterfaces(GeneratorExecutionContext ctx, ProxySyntaxReceiver receiver, bool supportsNullable)
- {
- var context = new Context
- {
- GeneratorExecutionContext = ctx,
- Candidates = receiver.CandidateInterfaces
- };
-
- var partialInterfacesGenerator = new PartialInterfacesGenerator(context, supportsNullable);
- foreach (var (fileName, text) in partialInterfacesGenerator.GenerateFiles())
- {
- context.GeneratorExecutionContext.AddSource(fileName, SourceText.From(text, Encoding.UTF8));
- }
- }
-
- private static void GenerateProxyClasses(GeneratorExecutionContext ctx, ProxySyntaxReceiver receiver, bool supportsNullable)
- {
- var context = new Context
- {
- GeneratorExecutionContext = ctx,
- Candidates = receiver.CandidateInterfaces
- };
-
- var proxyClassesGenerator = new ProxyClassesGenerator(context, supportsNullable);
- foreach (var (fileName, text) in proxyClassesGenerator.GenerateFiles())
- {
- context.GeneratorExecutionContext.AddSource(fileName, SourceText.From(text, Encoding.UTF8));
- }
- }
+using System.Text;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.Text;
+using ProxyInterfaceSourceGenerator.FileGenerators;
+using ProxyInterfaceSourceGenerator.Models;
+using ProxyInterfaceSourceGenerator.SyntaxReceiver;
+
+namespace ProxyInterfaceSourceGenerator;
+
+[Generator]
+#if DEBUG
+public
+#else
+internal
+#endif
+class ProxyInterfaceCodeGenerator : ISourceGenerator
+{
+ private readonly ExtraFilesGenerator _proxyAttributeGenerator = new();
+
+ public void Initialize(GeneratorInitializationContext context)
+ {
+#if DEBUGATTACH
+ if (!System.Diagnostics.Debugger.IsAttached)
+ {
+ System.Diagnostics.Debugger.Launch();
+ }
+#endif
+ context.RegisterForSyntaxNotifications(() => new ProxySyntaxReceiver());
+ }
+
+ public void Execute(GeneratorExecutionContext context)
+ {
+ try
+ {
+ if (context.ParseOptions is not CSharpParseOptions csharpParseOptions)
+ {
+ throw new NotSupportedException("Only C# is supported.");
+ }
+
+ if (context.SyntaxContextReceiver is not ProxySyntaxReceiver receiver)
+ {
+ throw new NotSupportedException($"Only {nameof(ProxySyntaxReceiver)} is supported.");
+ }
+
+ // https://github.com/reactiveui/refit/blob/main/InterfaceStubGenerator.Core/InterfaceStubGenerator.cs
+ var supportsNullable = csharpParseOptions.LanguageVersion >= LanguageVersion.CSharp8;
+
+ GenerateProxyAttribute(context, receiver);
+ GeneratePartialInterfaces(context, receiver, supportsNullable);
+ GenerateProxyClasses(context, receiver, supportsNullable);
+ }
+ catch (Exception exception)
+ {
+ GenerateError(context, exception);
+ }
+ }
+
+ private void GenerateError(GeneratorExecutionContext context, Exception exception)
+ {
+ var message = $"/*\r\n{nameof(ProxyInterfaceCodeGenerator)}\r\n\r\n[Exception]\r\n{exception}\r\n\r\n[StackTrace]\r\n{exception.StackTrace}*/";
+ context.AddSource("Error.g", SourceText.From(message, Encoding.UTF8));
+ }
+
+ private void GenerateProxyAttribute(GeneratorExecutionContext ctx, ProxySyntaxReceiver receiver)
+ {
+ var context = new Context
+ {
+ GeneratorExecutionContext = ctx,
+ Candidates = receiver.CandidateInterfaces
+ };
+
+ var attributeData = _proxyAttributeGenerator.GenerateFile();
+ context.GeneratorExecutionContext.AddSource(attributeData.FileName, SourceText.From(attributeData.Text, Encoding.UTF8));
+ }
+
+ private static void GeneratePartialInterfaces(GeneratorExecutionContext ctx, ProxySyntaxReceiver receiver, bool supportsNullable)
+ {
+ var context = new Context
+ {
+ GeneratorExecutionContext = ctx,
+ Candidates = receiver.CandidateInterfaces
+ };
+
+ var partialInterfacesGenerator = new PartialInterfacesGenerator(context, supportsNullable);
+ foreach (var (fileName, text) in partialInterfacesGenerator.GenerateFiles())
+ {
+ context.GeneratorExecutionContext.AddSource(fileName, SourceText.From(text, Encoding.UTF8));
+ }
+ }
+
+ private static void GenerateProxyClasses(GeneratorExecutionContext ctx, ProxySyntaxReceiver receiver, bool supportsNullable)
+ {
+ var context = new Context
+ {
+ GeneratorExecutionContext = ctx,
+ Candidates = receiver.CandidateInterfaces
+ };
+
+ var proxyClassesGenerator = new ProxyClassesGenerator(context, supportsNullable);
+ foreach (var (fileName, text) in proxyClassesGenerator.GenerateFiles())
+ {
+ context.GeneratorExecutionContext.AddSource(fileName, SourceText.From(text, Encoding.UTF8));
+ }
+ }
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/ProxyInterfaceSourceGenerator.csproj b/src/Speckle.ProxyGenerator/Speckle.ProxyGenerator.csproj
similarity index 90%
rename from src/ProxyInterfaceSourceGenerator/ProxyInterfaceSourceGenerator.csproj
rename to src/Speckle.ProxyGenerator/Speckle.ProxyGenerator.csproj
index 6cb3c51..1c374e5 100644
--- a/src/ProxyInterfaceSourceGenerator/ProxyInterfaceSourceGenerator.csproj
+++ b/src/Speckle.ProxyGenerator/Speckle.ProxyGenerator.csproj
@@ -4,19 +4,20 @@
0.1.0
netstandard2.0
{12344228-91F4-4502-9595-39584E5ABB34}
- 10
+ Latest
enable
- Stef Heyenrath
+ Speckle
+ Speckle.ProxyGenerator
ProxyInterfaceGenerator
- ProxyInterfaceGenerator
+ Speckle.ProxyGenerator
This project uses Source Generation to generate an interface and a Proxy class for classes. This makes it possible to wrap external classes which do not have an interface, in a Proxy class which makes it easier to Mock and use DI.
class;interface;proxy;SourceGenerator;Analyzer;Generation;Generate;wrap
MIT
$([System.IO.File]::ReadAllText("$(MSBuildProjectDirectory)/../../PackageReleaseNotes.txt"))
- https://github.com/StefH/ProxyInterfaceSourceGenerator
+ https://github.com/specklesystems/ProxyGenerator
git
- https://github.com/StefH/ProxyInterfaceSourceGenerator
+ https://github.com/specklesystems/ProxyGenerator
PackageReadme.md
icon.png
false
@@ -43,7 +44,7 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
@@ -79,4 +80,4 @@
-
\ No newline at end of file
+
diff --git a/src/ProxyInterfaceSourceGenerator/SyntaxReceiver/AttributeArgumentListParser.cs b/src/Speckle.ProxyGenerator/SyntaxReceiver/AttributeArgumentListParser.cs
similarity index 100%
rename from src/ProxyInterfaceSourceGenerator/SyntaxReceiver/AttributeArgumentListParser.cs
rename to src/Speckle.ProxyGenerator/SyntaxReceiver/AttributeArgumentListParser.cs
diff --git a/src/ProxyInterfaceSourceGenerator/SyntaxReceiver/ProxySyntaxReceiver.cs b/src/Speckle.ProxyGenerator/SyntaxReceiver/ProxySyntaxReceiver.cs
similarity index 97%
rename from src/ProxyInterfaceSourceGenerator/SyntaxReceiver/ProxySyntaxReceiver.cs
rename to src/Speckle.ProxyGenerator/SyntaxReceiver/ProxySyntaxReceiver.cs
index 121b340..1294b5e 100644
--- a/src/ProxyInterfaceSourceGenerator/SyntaxReceiver/ProxySyntaxReceiver.cs
+++ b/src/Speckle.ProxyGenerator/SyntaxReceiver/ProxySyntaxReceiver.cs
@@ -1,86 +1,86 @@
-using System.Diagnostics.CodeAnalysis;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using ProxyInterfaceSourceGenerator.Extensions;
-using ProxyInterfaceSourceGenerator.Models;
-
-namespace ProxyInterfaceSourceGenerator.SyntaxReceiver;
-
-internal class ProxySyntaxReceiver : ISyntaxContextReceiver
-{
- private const string GlobalPrefix = "global::";
- private static readonly string[] GenerateProxyAttributes = { "ProxyInterfaceGenerator.Proxy", "Proxy" };
- private static readonly string[] Modifiers = { "public", "partial" };
- public IDictionary CandidateInterfaces { get; } = new Dictionary();
-
- public void OnVisitSyntaxNode(GeneratorSyntaxContext context)
- {
- var syntaxNode = context.Node;
- var semanticModel = context.SemanticModel;
-
- if (syntaxNode is InterfaceDeclarationSyntax interfaceDeclarationSyntax && TryGet(interfaceDeclarationSyntax, out var data, semanticModel!))
- {
- CandidateInterfaces.Add(interfaceDeclarationSyntax, data);
- }
- }
-
- private static string CreateFullInterfaceName(string ns, BaseTypeDeclarationSyntax classDeclarationSyntax)
- {
- return !string.IsNullOrEmpty(ns) ? $"{ns}.{classDeclarationSyntax.Identifier}" : classDeclarationSyntax.Identifier.ToString();
- }
- private static bool TryGet(InterfaceDeclarationSyntax interfaceDeclarationSyntax, [NotNullWhen(true)] out ProxyData? data, SemanticModel semanticModel)
- {
- data = null;
-
- if (interfaceDeclarationSyntax.Modifiers.Select(m => m.ToString()).Except(Modifiers).Any())
- {
- // InterfaceDeclarationSyntax should be "public" and "partial"
- return false;
- }
-
- var attributeList = interfaceDeclarationSyntax.AttributeLists.FirstOrDefault(x => x.Attributes.Any(a => GenerateProxyAttributes.Contains(a.Name.ToString())));
- if (attributeList is null)
- {
- // InterfaceDeclarationSyntax should have the correct attribute
- return false;
- }
-
- var usings = new List();
-
- string ns = interfaceDeclarationSyntax.GetNamespace();
- if (!string.IsNullOrEmpty(ns))
- {
- usings.Add(ns);
- }
-
- if (interfaceDeclarationSyntax.TryGetParentSyntax(out CompilationUnitSyntax? cc))
- {
- foreach (var @using in cc.Usings)
- {
- usings.Add(@using.Name.ToString());
- }
- }
-
- var fluentBuilderAttributeArguments = AttributeArgumentListParser.ParseAttributeArguments(attributeList.Attributes.FirstOrDefault()?.ArgumentList, semanticModel);
-
- var metadataName = fluentBuilderAttributeArguments.MetadataName;
- var globalNamespace = string.IsNullOrEmpty(ns) ? string.Empty : $"{GlobalPrefix}{ns}";
- var namespaceDot = string.IsNullOrEmpty(ns) ? string.Empty : $"{ns}.";
-
- data = new ProxyData(
- @namespace: ns,
- namespaceDot: namespaceDot,
- shortInterfaceName: interfaceDeclarationSyntax.Identifier.ToString(),
- fullInterfaceName: CreateFullInterfaceName(globalNamespace, interfaceDeclarationSyntax), // $"{ns}.{interfaceDeclarationSyntax.Identifier}",
- fullQualifiedTypeName: fluentBuilderAttributeArguments.FullyQualifiedDisplayString,
- fullMetadataTypeName: metadataName,
- shortMetadataTypeName: metadataName.Split('.').Last(),
- usings: usings,
- proxyBaseClasses: fluentBuilderAttributeArguments.ProxyBaseClasses,
- accessibility: fluentBuilderAttributeArguments.Accessibility,
- membersToIgnore: fluentBuilderAttributeArguments.MembersToIgnore
- );
-
- return true;
- }
+using System.Diagnostics.CodeAnalysis;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using ProxyInterfaceSourceGenerator.Extensions;
+using ProxyInterfaceSourceGenerator.Models;
+
+namespace ProxyInterfaceSourceGenerator.SyntaxReceiver;
+
+internal class ProxySyntaxReceiver : ISyntaxContextReceiver
+{
+ private const string GlobalPrefix = "global::";
+ private static readonly string[] GenerateProxyAttributes = { "ProxyInterfaceGenerator.Proxy", "Proxy" };
+ private static readonly string[] Modifiers = { "public", "partial" };
+ public IDictionary CandidateInterfaces { get; } = new Dictionary();
+
+ public void OnVisitSyntaxNode(GeneratorSyntaxContext context)
+ {
+ var syntaxNode = context.Node;
+ var semanticModel = context.SemanticModel;
+
+ if (syntaxNode is InterfaceDeclarationSyntax interfaceDeclarationSyntax && TryGet(interfaceDeclarationSyntax, out var data, semanticModel!))
+ {
+ CandidateInterfaces.Add(interfaceDeclarationSyntax, data);
+ }
+ }
+
+ private static string CreateFullInterfaceName(string ns, BaseTypeDeclarationSyntax classDeclarationSyntax)
+ {
+ return !string.IsNullOrEmpty(ns) ? $"{ns}.{classDeclarationSyntax.Identifier}" : classDeclarationSyntax.Identifier.ToString();
+ }
+ private static bool TryGet(InterfaceDeclarationSyntax interfaceDeclarationSyntax, [NotNullWhen(true)] out ProxyData? data, SemanticModel semanticModel)
+ {
+ data = null;
+
+ if (interfaceDeclarationSyntax.Modifiers.Select(m => m.ToString()).Except(Modifiers).Any())
+ {
+ // InterfaceDeclarationSyntax should be "public" and "partial"
+ return false;
+ }
+
+ var attributeList = interfaceDeclarationSyntax.AttributeLists.FirstOrDefault(x => x.Attributes.Any(a => GenerateProxyAttributes.Contains(a.Name.ToString())));
+ if (attributeList is null)
+ {
+ // InterfaceDeclarationSyntax should have the correct attribute
+ return false;
+ }
+
+ var usings = new List();
+
+ string ns = interfaceDeclarationSyntax.GetNamespace();
+ if (!string.IsNullOrEmpty(ns))
+ {
+ usings.Add(ns);
+ }
+
+ if (interfaceDeclarationSyntax.TryGetParentSyntax(out CompilationUnitSyntax? cc))
+ {
+ foreach (var @using in cc.Usings)
+ {
+ usings.Add(@using.Name.ToString());
+ }
+ }
+
+ var fluentBuilderAttributeArguments = AttributeArgumentListParser.ParseAttributeArguments(attributeList.Attributes.FirstOrDefault()?.ArgumentList, semanticModel);
+
+ var metadataName = fluentBuilderAttributeArguments.MetadataName;
+ var globalNamespace = string.IsNullOrEmpty(ns) ? string.Empty : $"{GlobalPrefix}{ns}";
+ var namespaceDot = string.IsNullOrEmpty(ns) ? string.Empty : $"{ns}.";
+
+ data = new ProxyData(
+ @namespace: ns,
+ namespaceDot: namespaceDot,
+ shortInterfaceName: interfaceDeclarationSyntax.Identifier.ToString(),
+ fullInterfaceName: CreateFullInterfaceName(globalNamespace, interfaceDeclarationSyntax), // $"{ns}.{interfaceDeclarationSyntax.Identifier}",
+ fullQualifiedTypeName: fluentBuilderAttributeArguments.FullyQualifiedDisplayString,
+ fullMetadataTypeName: metadataName,
+ shortMetadataTypeName: metadataName.Split('.').Last(),
+ usings: usings,
+ proxyBaseClasses: fluentBuilderAttributeArguments.ProxyBaseClasses,
+ accessibility: fluentBuilderAttributeArguments.Accessibility,
+ membersToIgnore: fluentBuilderAttributeArguments.MembersToIgnore
+ );
+
+ return true;
+ }
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/Types/FluentBuilderAttributeArguments.cs b/src/Speckle.ProxyGenerator/Types/FluentBuilderAttributeArguments.cs
similarity index 100%
rename from src/ProxyInterfaceSourceGenerator/Types/FluentBuilderAttributeArguments.cs
rename to src/Speckle.ProxyGenerator/Types/FluentBuilderAttributeArguments.cs
diff --git a/src/ProxyInterfaceSourceGenerator/Types/ProxyInterfaceGeneratorAccessibility.cs b/src/Speckle.ProxyGenerator/Types/ProxyInterfaceGeneratorAccessibility.cs
similarity index 100%
rename from src/ProxyInterfaceSourceGenerator/Types/ProxyInterfaceGeneratorAccessibility.cs
rename to src/Speckle.ProxyGenerator/Types/ProxyInterfaceGeneratorAccessibility.cs
diff --git a/src/ProxyInterfaceSourceGenerator/Utils/MemberHelper.cs b/src/Speckle.ProxyGenerator/Utils/MemberHelper.cs
similarity index 97%
rename from src/ProxyInterfaceSourceGenerator/Utils/MemberHelper.cs
rename to src/Speckle.ProxyGenerator/Utils/MemberHelper.cs
index 00cce5c..2eb4a60 100644
--- a/src/ProxyInterfaceSourceGenerator/Utils/MemberHelper.cs
+++ b/src/Speckle.ProxyGenerator/Utils/MemberHelper.cs
@@ -1,125 +1,125 @@
-using Microsoft.CodeAnalysis;
-using ProxyInterfaceSourceGenerator.Models;
-
-namespace ProxyInterfaceSourceGenerator.Utils;
-
-internal static class MemberHelper
-{
- private static readonly string[] ExcludedMethods = { "ToString", "GetHashCode" };
-
- public static IReadOnlyList GetPublicProperties(
- ClassSymbol classSymbol,
- ProxyData proxyData,
- params Func[] filters)
- {
- var allFilters = new List>(filters)
- {
- p => p.Kind == SymbolKind.Property
- };
-
- return GetPublicMembers(classSymbol, proxyData, allFilters.ToArray()).ToArray();
- }
-
- public static IReadOnlyList GetPublicMethods(
- ClassSymbol classSymbol,
- ProxyData proxyData,
- Func? filter = null)
- {
- filter ??= _ => true;
-
- return
- GetPublicMembers(
- classSymbol,
- proxyData,
- m => m.Kind == SymbolKind.Method,
- m => m.MethodKind == MethodKind.Ordinary,
- m => !ExcludedMethods.Contains(m.Name),
- filter)
- .ToArray();
- }
-
- public static IReadOnlyList GetPublicStaticOperators(
- ClassSymbol classSymbol,
- ProxyData proxyData,
- Func? filter = null)
- {
- filter ??= _ => true;
-
- return
- GetPublicMembers(
- classSymbol,
- proxyData,
- m => m.Kind == SymbolKind.Method,
- m => m.MethodKind == MethodKind.Conversion,
- m => !ExcludedMethods.Contains(m.Name),
- filter)
- .ToArray();
- }
-
- public static IReadOnlyList> GetPublicEvents(
- ClassSymbol classSymbol,
- ProxyData proxyData,
- Func? filter = null)
- {
- filter ??= _ => true;
-
-#pragma warning disable CS8619 // Nullability of reference types in value doesn't match target type.
-#pragma warning disable RS1024 // Compare symbols correctly
- return GetPublicMembers(
- classSymbol,
- proxyData,
- m => m.MethodKind is MethodKind.EventAdd or MethodKind.EventRemove/* || m.MethodKind == MethodKind.EventRaise*/,
- filter)
- .GroupBy(e => e.AssociatedSymbol)
- .ToArray();
-#pragma warning restore RS1024 // Compare symbols correctly
-#pragma warning restore CS8619 // Nullability of reference types in value doesn't match target type.
- }
-
- // TODO : do we need also to check for "SanitizedName()" here?
- private static IReadOnlyList GetPublicMembers(
- ClassSymbol classSymbol,
- ProxyData proxyData,
- params Func[] filters
- ) where T : ISymbol
- {
- var membersQuery = classSymbol.Symbol.GetMembers().OfType()
- .Where(m => m.DeclaredAccessibility == Accessibility.Public);
-
- var f = filters.ToList();
- f.Add(x => !proxyData.MembersToIgnore.Contains(x.Name));
- foreach (var filter in f)
- {
- membersQuery = membersQuery.Where(filter);
- }
-
- var ownMembers = membersQuery.ToList();
- var ownMemberNames = ownMembers.Select(x => x.Name);
-
- if (!proxyData.ProxyBaseClasses)
- {
- return ownMembers;
- }
-
- var allMembers = ownMembers;
- var baseType = classSymbol.Symbol.BaseType;
-
- while (baseType != null && baseType.SpecialType != SpecialType.System_Object)
- {
- var baseMembers = baseType.GetMembers().OfType()
- .Where(m => m.DeclaredAccessibility == Accessibility.Public)
- .Where(x => !ownMemberNames.Contains(x.Name));
-
- foreach (var filter in filters)
- {
- baseMembers = baseMembers.Where(filter);
- }
-
- allMembers.AddRange(baseMembers);
-
- baseType = baseType.BaseType;
- }
-
- return allMembers;
- }
+using Microsoft.CodeAnalysis;
+using ProxyInterfaceSourceGenerator.Models;
+
+namespace ProxyInterfaceSourceGenerator.Utils;
+
+internal static class MemberHelper
+{
+ private static readonly string[] ExcludedMethods = { "ToString", "GetHashCode" };
+
+ public static IReadOnlyList GetPublicProperties(
+ ClassSymbol classSymbol,
+ ProxyData proxyData,
+ params Func[] filters)
+ {
+ var allFilters = new List>(filters)
+ {
+ p => p.Kind == SymbolKind.Property
+ };
+
+ return GetPublicMembers(classSymbol, proxyData, allFilters.ToArray()).ToArray();
+ }
+
+ public static IReadOnlyList GetPublicMethods(
+ ClassSymbol classSymbol,
+ ProxyData proxyData,
+ Func? filter = null)
+ {
+ filter ??= _ => true;
+
+ return
+ GetPublicMembers(
+ classSymbol,
+ proxyData,
+ m => m.Kind == SymbolKind.Method,
+ m => m.MethodKind == MethodKind.Ordinary,
+ m => !ExcludedMethods.Contains(m.Name),
+ filter)
+ .ToArray();
+ }
+
+ public static IReadOnlyList GetPublicStaticOperators(
+ ClassSymbol classSymbol,
+ ProxyData proxyData,
+ Func? filter = null)
+ {
+ filter ??= _ => true;
+
+ return
+ GetPublicMembers(
+ classSymbol,
+ proxyData,
+ m => m.Kind == SymbolKind.Method,
+ m => m.MethodKind == MethodKind.Conversion,
+ m => !ExcludedMethods.Contains(m.Name),
+ filter)
+ .ToArray();
+ }
+
+ public static IReadOnlyList> GetPublicEvents(
+ ClassSymbol classSymbol,
+ ProxyData proxyData,
+ Func? filter = null)
+ {
+ filter ??= _ => true;
+
+#pragma warning disable CS8619 // Nullability of reference types in value doesn't match target type.
+#pragma warning disable RS1024 // Compare symbols correctly
+ return GetPublicMembers(
+ classSymbol,
+ proxyData,
+ m => m.MethodKind is MethodKind.EventAdd or MethodKind.EventRemove/* || m.MethodKind == MethodKind.EventRaise*/,
+ filter)
+ .GroupBy(e => e.AssociatedSymbol)
+ .ToArray();
+#pragma warning restore RS1024 // Compare symbols correctly
+#pragma warning restore CS8619 // Nullability of reference types in value doesn't match target type.
+ }
+
+ // TODO : do we need also to check for "SanitizedName()" here?
+ private static IReadOnlyList GetPublicMembers(
+ ClassSymbol classSymbol,
+ ProxyData proxyData,
+ params Func[] filters
+ ) where T : ISymbol
+ {
+ var membersQuery = classSymbol.Symbol.GetMembers().OfType()
+ .Where(m => m.DeclaredAccessibility == Accessibility.Public);
+
+ var f = filters.ToList();
+ f.Add(x => !proxyData.MembersToIgnore.Contains(x.Name));
+ foreach (var filter in f)
+ {
+ membersQuery = membersQuery.Where(filter);
+ }
+
+ var ownMembers = membersQuery.ToList();
+ var ownMemberNames = ownMembers.Select(x => x.Name);
+
+ if (!proxyData.ProxyBaseClasses)
+ {
+ return ownMembers;
+ }
+
+ var allMembers = ownMembers;
+ var baseType = classSymbol.Symbol.BaseType;
+
+ while (baseType != null && baseType.SpecialType != SpecialType.System_Object)
+ {
+ var baseMembers = baseType.GetMembers().OfType()
+ .Where(m => m.DeclaredAccessibility == Accessibility.Public)
+ .Where(x => !ownMemberNames.Contains(x.Name));
+
+ foreach (var filter in filters)
+ {
+ baseMembers = baseMembers.Where(filter);
+ }
+
+ allMembers.AddRange(baseMembers);
+
+ baseType = baseType.BaseType;
+ }
+
+ return allMembers;
+ }
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/Utils/NamespaceHelper.cs b/src/Speckle.ProxyGenerator/Utils/NamespaceHelper.cs
similarity index 100%
rename from src/ProxyInterfaceSourceGenerator/Utils/NamespaceHelper.cs
rename to src/Speckle.ProxyGenerator/Utils/NamespaceHelper.cs
diff --git a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTests.csproj b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTests.csproj
index 6266499..7546c3a 100644
--- a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTests.csproj
+++ b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTests.csproj
@@ -32,7 +32,7 @@
-
+
@@ -69,4 +69,4 @@
-
\ No newline at end of file
+
diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Source/Foo.cs b/tests/ProxyInterfaceSourceGeneratorTests/Source/Foo.cs
index 217f2e8..55d3ddd 100644
--- a/tests/ProxyInterfaceSourceGeneratorTests/Source/Foo.cs
+++ b/tests/ProxyInterfaceSourceGeneratorTests/Source/Foo.cs
@@ -1,3 +1,5 @@
+using System.Diagnostics.CodeAnalysis;
+
namespace ProxyInterfaceSourceGeneratorTests.Source;
public class Foo
@@ -17,7 +19,8 @@ public class Foo
// return new Foo();
//}
- public Foo[] Foos { get; set; }
+ [SuppressMessage("ReSharper", "NullableWarningSuppressionIsUsed")]
+ public Foo[] Foos { get; set; } = null!;
public Foo[] DoSomethingAndGetAnArrayOfFoos()
{
@@ -28,4 +31,4 @@ public class Foo
//{
// return new[] { new Foo() }.ToList();
//}
-}
\ No newline at end of file
+}
diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Source/Foo2.cs b/tests/ProxyInterfaceSourceGeneratorTests/Source/Foo2.cs
index 01dfeb8..00b7e99 100644
--- a/tests/ProxyInterfaceSourceGeneratorTests/Source/Foo2.cs
+++ b/tests/ProxyInterfaceSourceGeneratorTests/Source/Foo2.cs
@@ -1,3 +1,5 @@
+using System.Diagnostics.CodeAnalysis;
+
namespace ProxyInterfaceSourceGeneratorTests.Source;
public class Foo2
@@ -17,7 +19,8 @@ public class Foo2
// return new Foo();
//}
- public Foo2[] Foos { get; set; }
+ [SuppressMessage("ReSharper", "NullableWarningSuppressionIsUsed")]
+ public Foo2[] Foos { get; set; }= null!;
public Foo2[] DoSomethingAndGetAnArrayOfFoos()
{
@@ -33,4 +36,4 @@ public class Foo2
//{
// return new[] { new Foo() }.ToList();
//}
-}
\ No newline at end of file
+}
diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Source/MixedVisibility.cs b/tests/ProxyInterfaceSourceGeneratorTests/Source/MixedVisibility.cs
index 49aa832..035b30b 100644
--- a/tests/ProxyInterfaceSourceGeneratorTests/Source/MixedVisibility.cs
+++ b/tests/ProxyInterfaceSourceGeneratorTests/Source/MixedVisibility.cs
@@ -1,6 +1,9 @@
+using System.Diagnostics.CodeAnalysis;
+
namespace ProxyInterfaceSourceGeneratorTests.Source;
public class MixedVisibility
{
- public string Foo { get; protected set; } //<- this will generate bad code
-}
\ No newline at end of file
+ [SuppressMessage("ReSharper", "NullableWarningSuppressionIsUsed")]
+ public string Foo { get; protected set; } = null!;//<- this will generate bad code
+}
diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Source/Person.cs b/tests/ProxyInterfaceSourceGeneratorTests/Source/Person.cs
index 4608016..e98a4fb 100644
--- a/tests/ProxyInterfaceSourceGeneratorTests/Source/Person.cs
+++ b/tests/ProxyInterfaceSourceGeneratorTests/Source/Person.cs
@@ -29,13 +29,15 @@ namespace ProxyInterfaceSourceGeneratorTests.Source
}
[Display(ResourceType = typeof(PeriodicTimer))]
- public string Name { get; set; }
+ [SuppressMessage("ReSharper", "NullableWarningSuppressionIsUsed")]
+ public string Name { get; set; }= null!;
public string? StringNullable { get; set; }
public long? NullableLong { get; }
- public object @object { get; set; }
+ [SuppressMessage("ReSharper", "NullableWarningSuppressionIsUsed")]
+ public object @object { get; set; }= null!;
public void Void()
{
@@ -131,4 +133,4 @@ namespace ProxyInterfaceSourceGeneratorTests.Source
return true;
}
}
-}
\ No newline at end of file
+}