root=true

# Use UNIX line endings for .sh fils so we play nice cross platform
[*.sh]
end_of_line = lf

[*.cs]
indent_style = space
indent_size = 4

# 
# NOTE: 
#
# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference
# 
# Good resource for most values
# https://github.com/dotnet/roslyn/blob/master/.editorconfig 
#

# Avoid "this." for methods, fields, events and properties
dotnet_style_qualification_for_field = false:error
dotnet_style_qualification_for_method = false:error
dotnet_style_qualification_for_property = false:error
dotnet_style_qualification_for_event = false:error

# Use language keywords instead of framework type names for type references (such as int not Int32)
dotnet_style_predefined_type_for_locals_parameters_members = true:error
dotnet_style_predefined_type_for_member_access = true:error

# Prefer "var" everywhere
csharp_style_var_for_built_in_types = true:error
csharp_style_var_when_type_is_apparent = true:error
csharp_style_var_elsewhere = true:error

# Prefer method-like constructs to have a block body (using {})
# csharp_style_expression_bodied_methods = false:error
# csharp_style_expression_bodied_constructors = false:error
# csharp_style_expression_bodied_operators = false:error

# Prefer property-like constructs to have an expression-body (properties using => instead of {})
csharp_style_expression_bodied_properties = true:error
csharp_style_expression_bodied_indexers = true:error
csharp_style_expression_bodied_accessors = true:error

# Force objects to initialize their members inside {} on construction
dotnet_style_object_initializer = true:error
dotnet_style_collection_initializer = true:error

# Force pattern matching over cast checking
#               if (o is int i)
#   instead of: if (o is int) { var i = (int)o; }
csharp_style_pattern_matching_over_is_with_cast_check = true:error

# Force pattern matching over null checking
#                if (o is string s)
#    instead of: var s = (string)o; if (s != null) {}
csharp_style_pattern_matching_over_as_with_null_check = true:error

# Force using tuple names never the Item1, Item2 etc...
dotnet_style_explicit_tuple_names = true:error

# Force inline variable declaration
#             SomeCall(out onError e)
# instead of: int e; SomeCall(out e);
csharp_style_inlined_variable_declaration = true:error

# Force use of ?? for throwing on null checks
#             var b = a ?? throw();
# instead of: if (a == null) { throw(); } b = a;
csharp_style_throw_expression = true:error

# Force calling delegates with null check
#             func?.Invoke()
# instead of: if (func != null) func();
csharp_style_conditional_delegate_call = true:error

# Force expression coalescing 
#             var a = x ?? y;
# instead of: var a = x == null ? y : x;
dotnet_style_coalesce_expression = true:error

# Force null propagation
#             var s = o?.ToString()
# instead of: var s = o == null ? null : o.ToString()
dotnet_style_null_propagation = true:error

#
# NAMING CONVENTIONS
# https://github.com/dotnet/roslyn/pull/15065
#
#   NOTE: Order of priority works here, so to exclude private static members
#         from the m-prefix style place it before the prefix rule
#

# Any static field and Properties should be just PascalCase
dotnet_naming_rule.static_fields_pascal.severity = error
dotnet_naming_rule.static_fields_pascal.symbols  = static_fields_pascal_symbols
dotnet_naming_rule.static_fields_pascal.style    = static_fields_pascal_style

dotnet_naming_style.static_fields_pascal_style.capitalization         = pascal_case
dotnet_naming_symbols.static_fields_pascal_symbols.applicable_kinds   = field
dotnet_naming_symbols.static_fields_pascal_symbols.required_modifiers = static

# Member fields must start with 'm' then PascalCase
dotnet_naming_rule.members_start_with_m.severity = error
dotnet_naming_rule.members_start_with_m.symbols  = members_start_with_m_symbols
dotnet_naming_rule.members_start_with_m.style    = members_start_with_m_style

dotnet_naming_style.members_start_with_m_style.capitalization         = pascal_case
dotnet_naming_style.members_start_with_m_style.required_prefix        = m
dotnet_naming_symbols.members_start_with_m_symbols.applicable_kinds   = field
dotnet_naming_symbols.members_start_with_m_symbols.required_modifiers = private,internal,private,protected,protected_internal

# Async methods end with Async
dotnet_naming_rule.async_methods_must_end_with_async.severity = error
dotnet_naming_rule.async_methods_must_end_with_async.symbols  = async_methods_must_end_with_async_symbols
dotnet_naming_rule.async_methods_must_end_with_async.style    = async_methods_must_end_with_async_style

dotnet_naming_symbols.async_methods_must_end_with_async_symbols.applicable_kinds   = method
dotnet_naming_symbols.async_methods_must_end_with_async_symbols.required_modifiers = async

dotnet_naming_style.async_methods_must_end_with_async_style.capitalization  = pascal_case
dotnet_naming_style.async_methods_must_end_with_async_style.required_suffix = Async

# Properties and Enums are PascalCase
dotnet_naming_rule.properties_pascal.severity = error
dotnet_naming_rule.properties_pascal.symbols  = properties_pascal_symbols
dotnet_naming_rule.properties_pascal.style    = properties_pascal_style

dotnet_naming_style.properties_pascal_style.capitalization         = pascal_case
dotnet_naming_symbols.properties_pascal_symbols.applicable_kinds   = property,enum

# Classes, Structs, Events, Delegates, Methods and Interfaces are PascalCase
dotnet_naming_rule.class_pascal.severity = error
dotnet_naming_rule.class_pascal.symbols  = class_pascal_symbols
dotnet_naming_rule.class_pascal.style    = class_pascal_style

dotnet_naming_style.class_pascal_style.capitalization         = pascal_case
dotnet_naming_symbols.class_pascal_symbols.applicable_kinds   = class,interface,struct,method,event,delegate
