root = true

[*]
charset = utf-8
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true
end_of_line = crlf

[*.{json,yml,yaml,axaml,xaml,xml,csproj,props,targets,config,slnx}]
indent_size = 2

[*.md]
trim_trailing_whitespace = false

[*.cs]
max_line_length = 120

#### .NET code style ####

# Usings
dotnet_sort_system_directives_first = true
dotnet_separate_import_directive_groups = false
csharp_using_directive_placement = outside_namespace:warning

# Namespaces
csharp_style_namespace_declarations = file_scoped:warning

# this. qualification
dotnet_style_qualification_for_field = false:warning
dotnet_style_qualification_for_property = false:warning
dotnet_style_qualification_for_method = false:warning
dotnet_style_qualification_for_event = false:warning

# Language keywords over BCL type names
dotnet_style_predefined_type_for_locals_parameters_members = true:warning
dotnet_style_predefined_type_for_member_access = true:warning

# Modifiers
dotnet_style_require_accessibility_modifiers = for_non_interface_members:warning
csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async:warning
dotnet_style_readonly_field = true:warning
csharp_prefer_static_local_function = true:warning

# var
csharp_style_var_for_built_in_types = false:suggestion
csharp_style_var_when_type_is_apparent = true:warning
csharp_style_var_elsewhere = false:suggestion

# Expression-bodied members
csharp_style_expression_bodied_methods = when_on_single_line:suggestion
csharp_style_expression_bodied_constructors = when_on_single_line:suggestion
csharp_style_expression_bodied_properties = when_on_single_line:warning
csharp_style_expression_bodied_accessors = when_on_single_line:warning
csharp_style_expression_bodied_lambdas = when_on_single_line:suggestion
csharp_style_expression_bodied_local_functions = when_on_single_line:suggestion

# Pattern matching and modern syntax
csharp_style_pattern_matching_over_is_with_cast_check = true:warning
csharp_style_pattern_matching_over_as_with_null_check = true:warning
csharp_style_prefer_switch_expression = true:warning
csharp_style_prefer_pattern_matching = true:warning
csharp_style_prefer_not_pattern = true:warning
csharp_style_throw_expression = true:suggestion
csharp_style_conditional_delegate_call = true:warning
csharp_prefer_simple_using_statement = true:warning
csharp_style_prefer_primary_constructors = true:suggestion
csharp_style_prefer_range_operator = true:warning
csharp_style_prefer_index_operator = true:warning
csharp_style_inlined_variable_declaration = true:warning
csharp_style_deconstructed_variable_declaration = true:suggestion
csharp_prefer_braces = true:suggestion
csharp_style_prefer_top_level_statements = false:suggestion

# Null checking
dotnet_style_coalesce_expression = true:warning
dotnet_style_null_propagation = true:warning
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning

# Expression-level preferences
dotnet_style_object_initializer = true:warning
dotnet_style_collection_initializer = true:warning
dotnet_style_prefer_collection_expression = when_types_loosely_match:warning
dotnet_style_explicit_tuple_names = true:warning
dotnet_style_prefer_auto_properties = true:warning
dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion
dotnet_style_prefer_conditional_expression_over_return = true:suggestion
dotnet_style_prefer_compound_assignment = true:warning
dotnet_style_prefer_simplified_boolean_expressions = true:warning
dotnet_style_namespace_match_folder = true:warning

# Unnecessary code
dotnet_diagnostic.IDE0005.severity = warning
dotnet_code_quality_unused_parameters = non_public:suggestion
csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion

# Formatting is owned by csharpier (`dotnet csharpier check .`), not by Roslyn.
# The two disagree on wrapping in a few places, and with TreatWarningsAsErrors on that
# disagreement would make a csharpier-formatted file unbuildable. One formatter wins.
dotnet_diagnostic.IDE0055.severity = suggestion

#### Naming ####

dotnet_naming_rule.interfaces_start_with_i.severity = warning
dotnet_naming_rule.interfaces_start_with_i.symbols = interface
dotnet_naming_rule.interfaces_start_with_i.style = begins_with_i

dotnet_naming_rule.types_pascal_case.severity = warning
dotnet_naming_rule.types_pascal_case.symbols = types
dotnet_naming_rule.types_pascal_case.style = pascal_case

dotnet_naming_rule.members_pascal_case.severity = warning
dotnet_naming_rule.members_pascal_case.symbols = non_field_members
dotnet_naming_rule.members_pascal_case.style = pascal_case

dotnet_naming_rule.constants_pascal_case.severity = warning
dotnet_naming_rule.constants_pascal_case.symbols = constants
dotnet_naming_rule.constants_pascal_case.style = pascal_case

dotnet_naming_rule.static_readonly_pascal_case.severity = warning
dotnet_naming_rule.static_readonly_pascal_case.symbols = static_readonly_fields
dotnet_naming_rule.static_readonly_pascal_case.style = pascal_case

dotnet_naming_rule.private_fields_underscore.severity = warning
dotnet_naming_rule.private_fields_underscore.symbols = private_fields
dotnet_naming_rule.private_fields_underscore.style = underscore_camel_case

dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = *

dotnet_naming_symbols.types.applicable_kinds = class,struct,interface,enum,delegate
dotnet_naming_symbols.types.applicable_accessibilities = *

dotnet_naming_symbols.non_field_members.applicable_kinds = property,event,method
dotnet_naming_symbols.non_field_members.applicable_accessibilities = *

dotnet_naming_symbols.constants.applicable_kinds = field
dotnet_naming_symbols.constants.required_modifiers = const

dotnet_naming_symbols.static_readonly_fields.applicable_kinds = field
dotnet_naming_symbols.static_readonly_fields.required_modifiers = static,readonly

dotnet_naming_symbols.private_fields.applicable_kinds = field
dotnet_naming_symbols.private_fields.applicable_accessibilities = private,private_protected

dotnet_naming_style.begins_with_i.required_prefix = I
dotnet_naming_style.begins_with_i.capitalization = pascal_case

dotnet_naming_style.pascal_case.capitalization = pascal_case

dotnet_naming_style.underscore_camel_case.required_prefix = _
dotnet_naming_style.underscore_camel_case.capitalization = camel_case

#### Analyzer tuning ####

# LoggerMessage delegates: not worth the ceremony in a desktop shell.
dotnet_diagnostic.CA1848.severity = none
# "Could be static": XAML `{Binding}` only reaches instance members, so view models legitimately
# expose constants as instance properties. A micro-optimisation rule, not a correctness one.
dotnet_diagnostic.CA1822.severity = suggestion
# Static factory methods on generic result types (ParseOutcome<T>.Success) are the
# idiomatic shape; CA1000 predates them and has no useful replacement to offer.
dotnet_diagnostic.CA1000.severity = none
# Localisation of literal strings is out of scope for now.
dotnet_diagnostic.CA1303.severity = none
# Avalonia views intentionally expose collection properties.
dotnet_diagnostic.CA2227.severity = none
dotnet_diagnostic.CA1002.severity = none
# InvariantGlobalization is on; culture-explicit overloads everywhere add noise.
dotnet_diagnostic.CA1304.severity = suggestion
dotnet_diagnostic.CA1305.severity = suggestion
dotnet_diagnostic.CA1310.severity = suggestion

[tests/**/*.cs]
dotnet_diagnostic.CA1707.severity = none
dotnet_diagnostic.CA1861.severity = none
dotnet_diagnostic.IDE0058.severity = none
