Greenfield skeleton for a parser desktop app. The domain is deliberately a placeholder — IParser<TIn,TOut> plus two sample parsers — so the shell is runnable and verifiable end to end before real logic lands. Layers run one way: Core (no Avalonia, no IO) <- Infrastructure <- UI <- Desktop. UI is a class library rather than the exe so headless tests build real views without dragging in Program.cs, Serilog or the container. Adaptive layout is built from what Avalonia actually offers, since it has no AdaptiveTrigger or media queries: ResponsiveLayout observes Visual.Bounds and projects a breakpoint onto both an attached property and :compact/:medium/ :expanded pseudoclasses, with 24px hysteresis so dragging a window edge cannot make the layout flap. Pane state lives in the view model because a style setter loses to a local value permanently; styles own only the visual variance. Stack notes worth remembering: Avalonia.ReactiveUI is deprecated in favour of ReactiveUI.Avalonia, and ReactiveUI 24 runs on the Primitives engine (RxVoid, ISequencer, Signal<T>) and no longer self-initialises. Avalonia.Headless.XUnit 12.x requires xUnit v3. InvariantGlobalization must stay false or Semi.Avalonia throws in its static constructor. 102 tests across three projects, including headless guards for the two failures that are otherwise completely silent: a stylesheet whose selectors match nothing, and a light palette too low-contrast for cards to read. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
179 lines
7.5 KiB
INI
179 lines
7.5 KiB
INI
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
|