diff --git a/.editorconfig b/.editorconfig index e69de29..8ff0b94 100644 --- a/.editorconfig +++ b/.editorconfig @@ -0,0 +1,198 @@ +# editorconfig.org + +# top-most EditorConfig file +root = true + +# Default settings: +# A newline ending every file +# Use 4 spaces as indentation +[*] +insert_final_newline = true +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true + +[project.json] +indent_size = 2 + +# C# and Visual Basic files +[*.{cs,vb}] +charset = utf-8 + +# Miscellaneous style rules +dotnet_sort_system_directives_first = true +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion + +# avoid this. unless absolutely necessary +dotnet_style_qualification_for_field = false:suggestion +dotnet_style_qualification_for_property = false:suggestion +dotnet_style_qualification_for_method = false:suggestion +dotnet_style_qualification_for_event = false:suggestion + +# name all constant fields using PascalCase +dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields +dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style +dotnet_naming_symbols.constant_fields.applicable_kinds = field +dotnet_naming_symbols.constant_fields.required_modifiers = const +dotnet_naming_style.pascal_case_style.capitalization = pascal_case + +# static fields should have s_ prefix +dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion +dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields +dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style +dotnet_naming_symbols.static_fields.applicable_kinds = field +dotnet_naming_symbols.static_fields.required_modifiers = static +dotnet_naming_symbols.static_fields.applicable_accessibilities = private, internal, private_protected +dotnet_naming_style.static_prefix_style.required_prefix = s_ +dotnet_naming_style.static_prefix_style.capitalization = camel_case + +# internal and private fields should be _camelCase +dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion +dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields +dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style +dotnet_naming_symbols.private_internal_fields.applicable_kinds = field +dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal +dotnet_naming_style.camel_case_underscore_style.required_prefix = _ +dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case + +# Code quality +dotnet_style_readonly_field = true:suggestion +dotnet_code_quality_unused_parameters = non_public:suggestion + +# Expression-level preferences +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_auto_properties = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:refactoring +dotnet_style_prefer_conditional_expression_over_return = true:refactoring + +# C# files +[*.cs] +# New line preferences +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 preferences +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_switch_labels = true +csharp_indent_labels = one_less_than_current + + + +# Modifier preferences +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion + +# Code style defaults +csharp_using_directive_placement = outside_namespace:suggestion +csharp_prefer_braces = true:warning +csharp_preserve_single_line_blocks = true:none +csharp_prefer_static_local_function = true:suggestion +csharp_prefer_simple_using_statement = false:none +csharp_style_prefer_switch_expression = true:suggestion + +# Expression-bodied members +csharp_style_expression_bodied_methods = true:refactoring +csharp_style_expression_bodied_constructors = true:refactoring +csharp_style_expression_bodied_operators = true:refactoring +csharp_style_expression_bodied_properties = true:refactoring +csharp_style_expression_bodied_indexers = true:refactoring +csharp_style_expression_bodied_accessors = true:refactoring +csharp_style_expression_bodied_lambdas = true:refactoring +csharp_style_expression_bodied_local_functions = true:refactoring + +# Pattern matching +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion + +# Expression-level preferences +csharp_prefer_simple_default_expression = true:suggestion + +# Null checking preferences +csharp_style_throw_expression = true:suggestion +csharp_style_conditional_delegate_call = true:suggestion + +# Other features +csharp_style_prefer_index_operator = false:none +csharp_style_prefer_range_operator = false:none +csharp_style_pattern_local_over_anonymous_function = false:none + +# Space preferences +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_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_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +# Namespace preference +csharp_style_namespace_declarations = file_scoped:suggestion + +# Types: use keywords instead of BCL types, and permit var only when the type is clear +csharp_style_var_for_built_in_types = false:suggestion +csharp_style_var_when_type_is_apparent = true:suggestion +csharp_style_var_elsewhere = false:suggestion + +# Visual Basic files +[*.vb] +# Modifier preferences +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:suggestion + +# Xml project files +[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}] +indent_size = 2 + +# Xml build files +[*.builds] +indent_size = 2 + +# Xml files +[*.{xml,stylecop,resx,ruleset}] +indent_size = 2 + +# Xml config files +[*.{props,targets,config,nuspec}] +indent_size = 2 + +# Shell scripts +[*.sh] +end_of_line = lf + +[*.{cmd, bat}] +end_of_line = crlf + +# Markdown files +[*.md] +# Double trailing spaces can be used for BR tags, and other instances are enforced by Markdownlint +trim_trailing_whitespace = false diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml new file mode 100644 index 0000000..6c9c849 --- /dev/null +++ b/.github/workflows/code-quality.yml @@ -0,0 +1,23 @@ +name: Code Quality + +on: [push, pull_request] + +jobs: + code-quality: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.x' + + - name: Restore dependencies + run: dotnet restore + + - name: Build with analyzers + run: dotnet build --no-restore + + - name: Check code formatting + run: dotnet format --verify-no-changes diff --git a/Basics.Tests/Basics.Tests.csproj b/Basics.Tests/Basics.Tests.csproj index 8ee22cd..90369df 100644 --- a/Basics.Tests/Basics.Tests.csproj +++ b/Basics.Tests/Basics.Tests.csproj @@ -10,7 +10,15 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + all diff --git a/Basics.Tests/StringFormatterTest.cs b/Basics.Tests/StringFormatterTest.cs index af0e3f0..8623687 100644 --- a/Basics.Tests/StringFormatterTest.cs +++ b/Basics.Tests/StringFormatterTest.cs @@ -1,4 +1,4 @@ -using Basics_0.Services; +using Basics.Services; using Xunit; namespace Basics.Test; @@ -33,5 +33,32 @@ public void SetPrefix_ChangesPrefixInFormatting() // Assert Assert.Equal("TEST: Jane Smith", result); } - -}; \ No newline at end of file + + [Fact] + public void CreateEmail_WithValidInputs_ReturnsCorrectEmail() + { + // Arrange + string userName = "berezin"; + string domain = "misha.ru"; + + // Act + var result = StringFormatter.CreateEmail(userName, domain); + + // Assert + Assert.Equal("berezin@misha.ru", result); + } + + [Fact] + public void RepeatString_WithPositiveCount_ReturnsRepeatedString() + { + // Arrange + string input = "abc"; + int count = 3; + + // Act + var result = StringFormatter.RepeatString(input, count); + + // Assert + Assert.Equal("abcabcabc", result); + } +}; diff --git a/Basics/Basics.csproj b/Basics/Basics.csproj index 127bde1..0d8066b 100644 --- a/Basics/Basics.csproj +++ b/Basics/Basics.csproj @@ -3,9 +3,23 @@ Exe net8.0 - Basics_0 + Basics enable enable + latest + All + true + $(NoWarn);CA1303 + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/Basics/Models/User.cs b/Basics/Models/User.cs index 74c7e65..9e835ad 100644 --- a/Basics/Models/User.cs +++ b/Basics/Models/User.cs @@ -1,25 +1,21 @@ -namespace Basics_0.Models; +namespace Basics.Models; public class User { - public int id; - public string Name; - private string _email; + public int Id { get; } + + private readonly string _name = "Ruslan"; + + private string _email = string.Empty; - public User() - { - id = 0; - Name = "Unknown"; - _email = ""; - } - public string GetInfo() + public string GetInfo { - return $"User: {Name}, ID: {id}"; + get => $"User: {_name}, ID: {Id} Email: {_email}"; } public void SetEmail(string email) { _email = email; } -} \ No newline at end of file +} diff --git a/Basics/Program.cs b/Basics/Program.cs index e5dff12..31b797d 100644 --- a/Basics/Program.cs +++ b/Basics/Program.cs @@ -1,3 +1,3 @@ -// See https://aka.ms/new-console-template for more information +// See https://aka.ms/new-console-template for more information -Console.WriteLine("Hello, World!"); \ No newline at end of file +Console.WriteLine("Hello, World!"); diff --git a/Basics/Services/StringFormatter.cs b/Basics/Services/StringFormatter.cs index 9362779..6800a47 100644 --- a/Basics/Services/StringFormatter.cs +++ b/Basics/Services/StringFormatter.cs @@ -1,4 +1,6 @@ -namespace Basics_0.Services; +using System.Text; + +namespace Basics.Services; public class StringFormatter { @@ -20,19 +22,23 @@ public void SetPrefix(string prefix) _prefix = prefix; } - public string CreateEmail(string userName, string domain) + public static string CreateEmail(string userName, string domain) { var email = $"{userName}@{domain}"; return email; } - public string RepeatString(string input, int count) + public static string RepeatString(string input, int count) { - string result = ""; + ArgumentNullException.ThrowIfNull(input); + + var builder = new StringBuilder(input.Length * count); + for (int i = 0; i < count; i++) { - result += input; + builder.Append(input); } - return result; + + return builder.ToString(); } -} \ No newline at end of file +}