From cc86111f72ca50591cc662e55b201fb1de5f78c9 Mon Sep 17 00:00:00 2001 From: jxnkwlp Date: Sun, 7 Jul 2024 23:10:20 +0800 Subject: [PATCH] code format --- .editorconfig | 508 ++++++++++++- NginxConfigParser/IToken.cs | 20 +- NginxConfigParser/NginxConfig.cs | 718 +++++++++--------- NginxConfigParser/NginxConfigParser.csproj | 38 +- NginxConfigParser/Parser.cs | 201 +++-- NginxConfigParser/Token.cs | 131 ++-- NginxConfigParser/TokenType.cs | 13 +- .../NginxConfigParserTests.csproj | 2 +- NginxConfigParserTests/Program.cs | 188 +++-- 9 files changed, 1161 insertions(+), 658 deletions(-) diff --git a/.editorconfig b/.editorconfig index f834dc7..d7df767 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,9 +1,507 @@ root = true +# All Files [*] -charset = utf-8-bom -indent_style = space -indent_size = 4 +charset = utf-8-bom +end_of_line = crlf +indent_style = space +indent_size = 4 +tab_width = 4 +insert_final_newline = true trim_trailing_whitespace = true -insert_final_newline = true -end_of_line = crlf + +# 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,mdx}] +indent_size = 2 +trim_trailing_whitespace = false + +# Web Files +[*.{htm,html,cjs,cts,ctsx,mjs,mts,mtsx,css,sass,scss,less,pcss,svg,vue}] +indent_size = 2 + +[*.{js,jsm,ts,tsx}] +indent_size = 4 + +# Batch Files +[*.{cmd,bat}] +end_of_line = crlf + +# Bash Files +[*.sh] +end_of_line = lf + +# C# files +[*.cs] +# Microsoft .NET properties +csharp_new_line_before_members_in_object_initializers = false +csharp_preferred_modifier_order = public, private, protected, internal, file, new, static, abstract, virtual, sealed, readonly, override, extern, unsafe, volatile, async, required:suggestion +csharp_style_prefer_utf8_string_literals = true:suggestion +csharp_style_var_elsewhere = true:suggestion +csharp_style_var_for_built_in_types = true:suggestion +csharp_style_var_when_type_is_apparent = true:suggestion +dotnet_naming_rule.constants_rule.import_to_resharper = as_predefined +dotnet_naming_rule.constants_rule.severity = warning +dotnet_naming_rule.constants_rule.style = pascal_case +dotnet_naming_rule.constants_rule.symbols = constants_symbols +dotnet_naming_rule.event_rule.import_to_resharper = as_predefined +dotnet_naming_rule.event_rule.severity = warning +dotnet_naming_rule.event_rule.style = pascal_case +dotnet_naming_rule.event_rule.symbols = event_symbols +dotnet_naming_rule.interfaces_rule.import_to_resharper = as_predefined +dotnet_naming_rule.interfaces_rule.severity = warning +dotnet_naming_rule.interfaces_rule.style = begins_with_i +dotnet_naming_rule.interfaces_rule.symbols = interfaces_symbols +dotnet_naming_rule.method_rule.import_to_resharper = as_predefined +dotnet_naming_rule.method_rule.severity = warning +dotnet_naming_rule.method_rule.style = pascal_case +dotnet_naming_rule.method_rule.symbols = method_symbols +dotnet_naming_rule.private_constants_rule.import_to_resharper = as_predefined +dotnet_naming_rule.private_constants_rule.severity = warning +dotnet_naming_rule.private_constants_rule.style = pascal_case +dotnet_naming_rule.private_constants_rule.symbols = private_constants_symbols +dotnet_naming_rule.private_instance_fields_rule.import_to_resharper = as_predefined +dotnet_naming_rule.private_instance_fields_rule.severity = warning +dotnet_naming_rule.private_instance_fields_rule.style = begins_with__ +dotnet_naming_rule.private_instance_fields_rule.symbols = private_instance_fields_symbols +dotnet_naming_rule.private_static_fields_rule.import_to_resharper = as_predefined +dotnet_naming_rule.private_static_fields_rule.severity = warning +dotnet_naming_rule.private_static_fields_rule.style = begins_with__ +dotnet_naming_rule.private_static_fields_rule.symbols = private_static_fields_symbols +dotnet_naming_rule.private_static_readonly_rule.import_to_resharper = as_predefined +dotnet_naming_rule.private_static_readonly_rule.severity = warning +dotnet_naming_rule.private_static_readonly_rule.style = pascal_case +dotnet_naming_rule.private_static_readonly_rule.symbols = private_static_readonly_symbols +dotnet_naming_rule.property_rule.import_to_resharper = as_predefined +dotnet_naming_rule.property_rule.severity = warning +dotnet_naming_rule.property_rule.style = pascal_case +dotnet_naming_rule.property_rule.symbols = property_symbols +dotnet_naming_rule.public_fields_rule.import_to_resharper = as_predefined +dotnet_naming_rule.public_fields_rule.severity = warning +dotnet_naming_rule.public_fields_rule.style = pascal_case +dotnet_naming_rule.public_fields_rule.symbols = public_fields_symbols +dotnet_naming_rule.static_readonly_rule.import_to_resharper = as_predefined +dotnet_naming_rule.static_readonly_rule.severity = warning +dotnet_naming_rule.static_readonly_rule.style = pascal_case +dotnet_naming_rule.static_readonly_rule.symbols = static_readonly_symbols +dotnet_naming_rule.types_and_namespaces_rule.import_to_resharper = as_predefined +dotnet_naming_rule.types_and_namespaces_rule.severity = warning +dotnet_naming_rule.types_and_namespaces_rule.style = pascal_case +dotnet_naming_rule.types_and_namespaces_rule.symbols = types_and_namespaces_symbols +dotnet_naming_rule.unity_serialized_field_rule.import_to_resharper = True +dotnet_naming_rule.unity_serialized_field_rule.resharper_description = Unity serialized field +dotnet_naming_rule.unity_serialized_field_rule.resharper_guid = 5f0fdb63-c892-4d2c-9324-15c80b22a7ef +dotnet_naming_rule.unity_serialized_field_rule.severity = warning +dotnet_naming_rule.unity_serialized_field_rule.style = lower_camel_case_style +dotnet_naming_rule.unity_serialized_field_rule.symbols = unity_serialized_field_symbols +dotnet_naming_style.lower_camel_case_style.capitalization = camel_case +dotnet_naming_symbols.constants_symbols.applicable_accessibilities = public,internal,protected,protected_internal,private_protected +dotnet_naming_symbols.constants_symbols.applicable_kinds = field +dotnet_naming_symbols.constants_symbols.required_modifiers = const +dotnet_naming_symbols.event_symbols.applicable_accessibilities = * +dotnet_naming_symbols.event_symbols.applicable_kinds = event +dotnet_naming_symbols.interfaces_symbols.applicable_accessibilities = * +dotnet_naming_symbols.interfaces_symbols.applicable_kinds = interface +dotnet_naming_symbols.method_symbols.applicable_accessibilities = * +dotnet_naming_symbols.method_symbols.applicable_kinds = method +dotnet_naming_symbols.private_constants_symbols.applicable_accessibilities = private +dotnet_naming_symbols.private_constants_symbols.applicable_kinds = field +dotnet_naming_symbols.private_constants_symbols.required_modifiers = const +dotnet_naming_symbols.private_instance_fields_symbols.applicable_accessibilities = private +dotnet_naming_symbols.private_instance_fields_symbols.applicable_kinds = field +dotnet_naming_symbols.private_static_fields_symbols.applicable_accessibilities = private +dotnet_naming_symbols.private_static_fields_symbols.applicable_kinds = field +dotnet_naming_symbols.private_static_fields_symbols.required_modifiers = static +dotnet_naming_symbols.private_static_readonly_symbols.applicable_accessibilities = private +dotnet_naming_symbols.private_static_readonly_symbols.applicable_kinds = field +dotnet_naming_symbols.private_static_readonly_symbols.required_modifiers = static,readonly +dotnet_naming_symbols.property_symbols.applicable_accessibilities = * +dotnet_naming_symbols.property_symbols.applicable_kinds = property +dotnet_naming_symbols.public_fields_symbols.applicable_accessibilities = public,internal,protected,protected_internal,private_protected +dotnet_naming_symbols.public_fields_symbols.applicable_kinds = field +dotnet_naming_symbols.static_readonly_symbols.applicable_accessibilities = public,internal,protected,protected_internal,private_protected +dotnet_naming_symbols.static_readonly_symbols.applicable_kinds = field +dotnet_naming_symbols.static_readonly_symbols.required_modifiers = static,readonly +dotnet_naming_symbols.types_and_namespaces_symbols.applicable_accessibilities = * +dotnet_naming_symbols.types_and_namespaces_symbols.applicable_kinds = namespace,class,struct,enum,delegate +dotnet_naming_symbols.unity_serialized_field_symbols.applicable_accessibilities = * +dotnet_naming_symbols.unity_serialized_field_symbols.applicable_kinds = +dotnet_naming_symbols.unity_serialized_field_symbols.resharper_applicable_kinds = unity_serialised_field +dotnet_naming_symbols.unity_serialized_field_symbols.resharper_required_modifiers = instance +dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:none +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:none +dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion +dotnet_style_qualification_for_event = false:suggestion +dotnet_style_qualification_for_field = false:suggestion +dotnet_style_qualification_for_method = false:suggestion +dotnet_style_qualification_for_property = false:suggestion +dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion + +# ReSharper properties +resharper_autodetect_indent_settings = true +resharper_braces_for_for = required +resharper_braces_for_foreach = required +resharper_braces_for_ifelse = required +resharper_braces_for_while = required +resharper_braces_redundant = false +resharper_csharp_brace_style = next_line +resharper_csharp_naming_rule.constants = AaBb +resharper_csharp_naming_rule.event = AaBb +resharper_csharp_naming_rule.interfaces = I + AaBb +resharper_csharp_naming_rule.method = AaBb +resharper_csharp_naming_rule.private_constants = AaBb +resharper_csharp_naming_rule.private_instance_fields = _ + aaBb +resharper_csharp_naming_rule.private_static_fields = _ + aaBb +resharper_csharp_naming_rule.private_static_readonly = AaBb +resharper_csharp_naming_rule.property = AaBb +resharper_csharp_naming_rule.public_fields = AaBb +resharper_csharp_naming_rule.static_readonly = AaBb +resharper_csharp_naming_rule.types_and_namespaces = AaBb +resharper_formatter_off_tag = @formatter:off +resharper_formatter_on_tag = @formatter:on +resharper_formatter_tags_enabled = true +resharper_keep_existing_declaration_block_arrangement = false +resharper_keep_existing_embedded_block_arrangement = false +resharper_keep_existing_enum_arrangement = false +resharper_use_heuristics_for_body_style = true +resharper_use_indent_from_vs = false + +# ReSharper inspection severities +resharper_arrange_accessor_owner_body_highlighting = suggestion +resharper_arrange_redundant_parentheses_highlighting = hint +resharper_arrange_this_qualifier_highlighting = hint +resharper_arrange_type_member_modifiers_highlighting = hint +resharper_arrange_type_modifiers_highlighting = hint +resharper_built_in_type_reference_style_for_member_access_highlighting = hint +resharper_built_in_type_reference_style_highlighting = hint +resharper_enforce_do_while_statement_braces_highlighting = warning +resharper_enforce_fixed_statement_braces_highlighting = warning +resharper_enforce_foreach_statement_braces_highlighting = warning +resharper_enforce_for_statement_braces_highlighting = warning +resharper_enforce_if_statement_braces_highlighting = warning +resharper_enforce_lock_statement_braces_highlighting = warning +resharper_enforce_using_statement_braces_highlighting = warning +resharper_enforce_while_statement_braces_highlighting = warning +resharper_redundant_base_qualifier_highlighting = warning +resharper_suggest_var_or_type_built_in_types_highlighting = hint +resharper_suggest_var_or_type_elsewhere_highlighting = hint +resharper_suggest_var_or_type_simple_types_highlighting = hint +resharper_web_config_module_not_resolved_highlighting = warning +resharper_web_config_type_not_resolved_highlighting = warning +resharper_web_config_wrong_module_highlighting = warning + + +dotnet_style_operator_placement_when_wrapping = beginning_of_line +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_auto_properties = true:silent +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_compound_assignment = true:suggestion +dotnet_style_prefer_simplified_interpolation = true:suggestion +dotnet_style_namespace_match_folder = true:suggestion +dotnet_style_readonly_field = true:suggestion +dotnet_style_predefined_type_for_locals_parameters_members = true:silent +dotnet_style_predefined_type_for_member_access = true:silent +dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent +dotnet_style_allow_multiple_blank_lines_experimental = true:silent +dotnet_style_allow_statement_immediately_after_block_experimental = true:silent +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent +dotnet_code_quality_unused_parameters = all:suggestion +dotnet_style_qualification_for_event = false:silent +dotnet_style_qualification_for_method = false:silent +dotnet_style_qualification_for_property = false:silent +dotnet_style_qualification_for_field = false:silent + +#### .NET Coding Conventions #### + +# Organize usings +dotnet_separate_import_directive_groups = false +dotnet_sort_system_directives_first = true +file_header_template = + +# this. and Me. preferences +dotnet_style_qualification_for_event = false +dotnet_style_qualification_for_field = false +dotnet_style_qualification_for_method = false +dotnet_style_qualification_for_property = false + +# Language keywords vs BCL types preferences +dotnet_style_predefined_type_for_locals_parameters_members = true +dotnet_style_predefined_type_for_member_access = true + +# Parentheses preferences +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_operators = never_if_unnecessary +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity + +# Modifier preferences +dotnet_style_require_accessibility_modifiers = for_non_interface_members + +# Expression-level preferences +dotnet_style_coalesce_expression = true +dotnet_style_collection_initializer = true +dotnet_style_explicit_tuple_names = true +dotnet_style_namespace_match_folder = true +dotnet_style_null_propagation = true +dotnet_style_object_initializer = true +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_prefer_auto_properties = true +dotnet_style_prefer_compound_assignment = true +dotnet_style_prefer_conditional_expression_over_assignment = true +dotnet_style_prefer_conditional_expression_over_return = true +dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed +dotnet_style_prefer_inferred_anonymous_type_member_names = true +dotnet_style_prefer_inferred_tuple_names = true +dotnet_style_prefer_is_null_check_over_reference_equality_method = true +dotnet_style_prefer_simplified_boolean_expressions = true +dotnet_style_prefer_simplified_interpolation = true + +# Field preferences +dotnet_style_readonly_field = true + +# Parameter preferences +dotnet_code_quality_unused_parameters = all + +# Suppression preferences +dotnet_remove_unnecessary_suppression_exclusions = none + +# New line preferences +dotnet_style_allow_multiple_blank_lines_experimental = true +dotnet_style_allow_statement_immediately_after_block_experimental = true + +#### C# Coding Conventions #### + +# var preferences +csharp_style_var_elsewhere = false:silent +csharp_style_var_for_built_in_types = false:silent +csharp_style_var_when_type_is_apparent = false:silent + +# Expression-bodied members +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = false:silent +csharp_style_expression_bodied_methods = false:silent +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_properties = true:silent + +# Pattern matching preferences +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_prefer_extended_property_pattern = true:suggestion +csharp_style_prefer_not_pattern = true:suggestion +csharp_style_prefer_pattern_matching = true:silent +csharp_style_prefer_switch_expression = true:suggestion + +# Null-checking preferences +csharp_style_conditional_delegate_call = true:suggestion + +# Modifier preferences +csharp_prefer_static_local_function = true:suggestion +csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async +csharp_style_prefer_readonly_struct = true:suggestion +csharp_style_prefer_readonly_struct_member = true:suggestion + +# Code-block preferences +csharp_prefer_simple_using_statement = true:silent +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_prefer_top_level_statements = true:silent + +# Expression-level preferences +csharp_prefer_simple_default_expression = true:suggestion +csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_prefer_index_operator = true:suggestion +csharp_style_prefer_local_over_anonymous_function = true:suggestion +csharp_style_prefer_null_check_over_type_check = true:suggestion +csharp_style_prefer_range_operator = true:suggestion +csharp_style_prefer_tuple_swap = true:suggestion +csharp_style_prefer_utf8_string_literals = true:suggestion +csharp_style_throw_expression = true:suggestion +csharp_style_unused_value_assignment_preference = discard_variable:suggestion +csharp_style_unused_value_expression_statement_preference = discard_variable:silent + +# 'using' directive preferences + +# New line preferences +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent +csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent + +#### C# Formatting Rules #### + +# New line preferences +csharp_new_line_before_catch = true +csharp_new_line_before_else = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_open_brace = all +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_labels = one_less_than_current +csharp_indent_switch_labels = true + +# 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_around_declaration_statements = false +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 + +# Wrapping preferences +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = true + +#### Naming styles #### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.private_or_internal_field_should_be_begins_with__.severity = warning +dotnet_naming_rule.private_or_internal_field_should_be_begins_with__.symbols = private_or_internal_field +dotnet_naming_rule.private_or_internal_field_should_be_begins_with__.style = begins_with__ + +dotnet_naming_rule.static_field_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.static_field_should_be_pascal_case.symbols = static_field +dotnet_naming_rule.static_field_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.static_field.applicable_kinds = field +dotnet_naming_symbols.static_field.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.static_field.required_modifiers = static + +dotnet_naming_symbols.private_or_internal_field.applicable_kinds = field +dotnet_naming_symbols.private_or_internal_field.applicable_accessibilities = internal, private, private_protected +dotnet_naming_symbols.private_or_internal_field.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +dotnet_naming_style.begins_with__.required_prefix = _ +dotnet_naming_style.begins_with__.required_suffix = +dotnet_naming_style.begins_with__.word_separator = +dotnet_naming_style.begins_with__.capitalization = camel_case + +# +dotnet_style_allow_multiple_blank_lines_experimental = true:silent +dotnet_style_allow_statement_immediately_after_block_experimental = true:silent + +# +dotnet_analyzer_diagnostic.category-roslynator.severity = warning +# Enable/disable all analyzers by default +# NOTE: This option can be used only in .roslynatorconfig file +roslynator_analyzers.enabled_by_default = true + +# Enable/disable all refactorings +roslynator_refactorings.enabled = true + +# Enable/disable all compiler diagnostic fixes +roslynator_compiler_diagnostic_fixes.enabled = true +tab_width = 4 + +# +dotnet_diagnostic.ide0011.severity = silent +dotnet_diagnostic.CA1848.severity = silent +dotnet_diagnostic.CA1305.severity = silent +dotnet_diagnostic.CA2016.severity = warning +dotnet_diagnostic.RCS1141.severity = silent +dotnet_diagnostic.RCS1251.severity = silent + +[{*.har,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.stylelintrc,bowerrc,jest.config}] +indent_style = space +indent_size = 2 + +[*.{appxmanifest,asax,ascx,aspx,axaml,build,c,c++,cc,cginc,compute,cp,cpp,cs,cshtml,cu,cuh,cxx,dtd,fs,fsi,fsscript,fsx,fx,fxh,h,hh,hlsl,hlsli,hlslinc,hpp,hxx,inc,inl,ino,ipp,ixx,master,ml,mli,mpp,mq4,mq5,mqh,nuspec,paml,razor,resw,resx,shader,skin,tpp,usf,ush,vb,xaml,xamlx,xoml,xsd}] +indent_style = space +indent_size = 4 +tab_width = 4 diff --git a/NginxConfigParser/IToken.cs b/NginxConfigParser/IToken.cs index 683cdfe..7ff416d 100644 --- a/NginxConfigParser/IToken.cs +++ b/NginxConfigParser/IToken.cs @@ -1,14 +1,12 @@ -namespace NginxConfigParser -{ - public interface IToken - { - } +namespace NginxConfigParser; - public interface IValueToken : IToken - { - string Key { get; } - string Value { get; set; } - string Comment { get; set; } - } +public interface IToken +{ +} +public interface IValueToken : IToken +{ + string Key { get; } + string Value { get; set; } + string Comment { get; set; } } diff --git a/NginxConfigParser/NginxConfig.cs b/NginxConfigParser/NginxConfig.cs index e3f1569..f79b0cd 100644 --- a/NginxConfigParser/NginxConfig.cs +++ b/NginxConfigParser/NginxConfig.cs @@ -5,91 +5,144 @@ using System.Text; using System.Text.RegularExpressions; -namespace NginxConfigParser +namespace NginxConfigParser; + +/// +/// Represents an nginx configuration file operation object. +/// +public class NginxConfig { + private static readonly Regex KeyRegex = new(@"^[\w]+(\[\d+\])?$"); + + private readonly Parser _parser; + + private IList _tokens = new List(); + + protected NginxConfig(Parser parser) + { + _parser = parser; + + Initial(); + } + /// - /// Represents an nginx configuration file operation object. + /// Create an new /// - public class NginxConfig + public static NginxConfig Create() { - private readonly Parser _parser; + var parser = new Parser(string.Empty); - private IList _tokens = new List(); + return new NginxConfig(parser); + } - protected NginxConfig(Parser parser) + /// + /// Load from specific file + /// + /// The file path + /// + /// + /// + public static NginxConfig LoadFrom(string fileName) + { + if (string.IsNullOrWhiteSpace(fileName)) { - _parser = parser; - - Initial(); + throw new ArgumentException($"'{nameof(fileName)}' cannot be null or whitespace.", nameof(fileName)); } - /// - /// Create an new - /// - public static NginxConfig Create() + if (!File.Exists(fileName)) { - var parser = new Parser(string.Empty); - - return new NginxConfig(parser); + throw new FileNotFoundException(fileName); } - /// - /// Load from specific file - /// - /// The file path - /// - public static NginxConfig LoadFrom(string fileName) + // var fs = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite); + + var content = File.ReadAllText(fileName); + + return Load(content); + } + + /// + /// Load from file content + /// + /// The string of file content + /// + /// + public static NginxConfig Load(string content) + { + if (content is null) { - if (string.IsNullOrWhiteSpace(fileName)) - { - throw new ArgumentException($"'{nameof(fileName)}' cannot be null or whitespace.", nameof(fileName)); - } + throw new ArgumentNullException(nameof(content)); + } - if (!File.Exists(fileName)) - { - throw new FileNotFoundException(fileName); - } + var parser = new Parser(content); - // var fs = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite); + return new NginxConfig(parser); + } - var content = File.ReadAllText(fileName); + private void Initial() + { + _parser.Parse(); + _tokens = _parser.GetTokens().ToList(); + } - return Load(content); - } + /// + /// Get all values + /// + public IEnumerable GetTokens() => _tokens; - /// - /// Load from file content - /// - /// The string of file content - /// - public static NginxConfig Load(string content) + /// + /// Read value from given the key path. + /// if the key not exist, will return null. + /// + /// + public IValueToken GetToken(string keyPath) + { + if (string.IsNullOrWhiteSpace(keyPath)) { - if (content is null) - { - throw new ArgumentNullException(nameof(content)); - } + throw new ArgumentException($"'{nameof(keyPath)}' cannot be null or whitespace.", nameof(keyPath)); + } - var parser = new Parser(content); + return GetTokenFromPath(keyPath); + } - return new NginxConfig(parser); + /// + /// Read value list from given the key path. + /// + /// + public IList GetTokens(string keyPath) + { + if (string.IsNullOrWhiteSpace(keyPath)) + { + throw new ArgumentException($"'{nameof(keyPath)}' cannot be null or whitespace.", nameof(keyPath)); } - private void Initial() + return GetTokensFromPath(keyPath); + } + + /// + /// Read all values from specific group key + /// + /// + public GroupToken GetGroup(string key) + { + if (string.IsNullOrWhiteSpace(key)) { - _parser.Parse(); - _tokens = _parser.GetTokens().ToList(); + throw new ArgumentException($"'{nameof(key)}' cannot be null or whitespace.", nameof(key)); } - /// - /// Get all values - /// - public IEnumerable GetTokens() => _tokens; + var find = _tokens.Where(x => x is GroupToken).FirstOrDefault(x => ((IValueToken)x).Key == key); + + return find as GroupToken; + } - /// - /// Read value from given the key path. - /// if the key not exist, will return null. - /// - public IValueToken GetToken(string keyPath) + /// + /// Read value from given the key path. + /// if the key not exist, will return null. + /// + /// + public IValueToken this[string keyPath] + { + get { if (string.IsNullOrWhiteSpace(keyPath)) { @@ -98,394 +151,361 @@ public IValueToken GetToken(string keyPath) return GetTokenFromPath(keyPath); } + } - /// - /// Read value list from given the key path. - /// - public IList GetTokens(string keyPath) + /// + /// Add or update value by the key path + /// + /// The key path + /// The string value + /// Add as group when key path not found + /// The comment + /// + /// + public NginxConfig AddOrUpdate(string keyPath, string value, bool addAsGroup = false, string comment = null) + { + if (string.IsNullOrWhiteSpace(keyPath)) { - if (string.IsNullOrWhiteSpace(keyPath)) - { - throw new ArgumentException($"'{nameof(keyPath)}' cannot be null or whitespace.", nameof(keyPath)); - } - - return GetTokensFromPath(keyPath); + throw new ArgumentException($"'{nameof(keyPath)}' cannot be null or whitespace.", nameof(keyPath)); } - /// - /// Read all values from specific group key - /// - public GroupToken GetGroup(string key) - { - if (string.IsNullOrWhiteSpace(key)) - { - throw new ArgumentException($"'{nameof(key)}' cannot be null or whitespace.", nameof(key)); - } + var tokens = _tokens; - var find = _tokens.Where(x => x is GroupToken).FirstOrDefault(x => ((IValueToken)x).Key == key); + var paths = keyPath.Split(':'); - return find as GroupToken; - } + GroupToken groupToken = null; - /// - /// Read value from given the key path. - /// if the key not exist, will return null. - /// - public IValueToken this[string keyPath] - { - get - { - if (string.IsNullOrWhiteSpace(keyPath)) - { - throw new ArgumentException($"'{nameof(keyPath)}' cannot be null or whitespace.", nameof(keyPath)); - } + int length = paths.Length; - return GetTokenFromPath(keyPath); - } - } - - /// - /// Add or update value by the key path - /// - /// The key path - /// The string value - /// Add as group when key path not found - /// The comment - public NginxConfig AddOrUpdate(string keyPath, string value, bool addAsGroup = false, string comment = null) + for (int i = 0; i < length; i++) { - if (string.IsNullOrWhiteSpace(keyPath)) - { - throw new ArgumentException($"'{nameof(keyPath)}' cannot be null or whitespace.", nameof(keyPath)); - } - - var tokens = _tokens; + var (key, index) = ResolveKey(paths[i]); - var paths = keyPath.Split(':'); + IToken find = null; + IEnumerable findTokens; + if (groupToken == null) + findTokens = FindTokens(tokens, key); + else + findTokens = FindTokens(groupToken.Tokens, key); - GroupToken groupToken = null; + if (index > findTokens.Count()) + throw new IndexOutOfRangeException($"The key '{key}' index must be <= {findTokens.Count()}"); - int length = paths.Length; + if (index <= findTokens.Count() - 1) + find = findTokens.ElementAt(index); - for (int i = 0; i < length; i++) + if (find != null) { - var (key, index) = ResolveKey(paths[i]); + if (find is ValueToken valueToken) + { + if (i == length - 1) + { + valueToken.Value = value; + valueToken.Comment = comment; + break; + } - IToken find = null; - IEnumerable findTokens; - if (groupToken == null) - findTokens = tokens.Where(x => x is IValueToken).Where(x => ((IValueToken)x).Key == key); - else - findTokens = groupToken.Tokens.Where(x => x is IValueToken).Where(x => ((IValueToken)x).Key == key); + throw new Exception($"The token '{find}' already exists."); + } - if (index > findTokens.Count()) - throw new IndexOutOfRangeException($"The key '{key}' index must be <= {findTokens.Count()}"); + groupToken = (GroupToken)find; + } + else if (i == length - 1) + { + IValueToken newToken = new ValueToken(groupToken, key, value, comment); - if (index <= findTokens.Count() - 1) - find = findTokens.ElementAt(index); + if (addAsGroup) + { + newToken = new GroupToken(groupToken, key, value, comment); + } - if (find != null) + if (groupToken == null) { - if (find is ValueToken valueToken) - if (i == length - 1) - { - valueToken.Value = value; - valueToken.Comment = comment; - break; - } - else - throw new System.Exception($"The token '{find}' has been exist."); - - groupToken = (GroupToken)find; + tokens.Add(newToken); } else { - if (i == length - 1) - { - IValueToken newToken = new ValueToken(groupToken, key, value, comment); - - if (addAsGroup) - { - newToken = new GroupToken(groupToken, key, value, comment); - } - - if (groupToken == null) - { - tokens.Add(newToken); - } - else - { - groupToken.Add(newToken); - } - } - else - { - var newGroupToken = new GroupToken(groupToken, key); - if (groupToken == null) - { - tokens.Add(newGroupToken); - } - else - { - groupToken.Add(newGroupToken); - } - groupToken = newGroupToken; - } + groupToken.Add(newToken); } } - - return this; + else + { + var newGroupToken = new GroupToken(groupToken, key); + if (groupToken == null) + { + tokens.Add(newGroupToken); + } + else + { + groupToken.Add(newGroupToken); + } + groupToken = newGroupToken; + } } - /// - /// Remove the value by key path - /// - public NginxConfig Remove(string keyPath) + return this; + } + + /// + /// Remove the value by key path + /// + /// + /// + public NginxConfig Remove(string keyPath) + { + if (string.IsNullOrWhiteSpace(keyPath)) { - if (string.IsNullOrWhiteSpace(keyPath)) - { - throw new ArgumentException($"'{nameof(keyPath)}' cannot be null or whitespace.", nameof(keyPath)); - } + throw new ArgumentException($"'{nameof(keyPath)}' cannot be null or whitespace.", nameof(keyPath)); + } - var tokens = _tokens; + var tokens = _tokens; - var paths = keyPath.Split(':'); + var paths = keyPath.Split(':'); - GroupToken groupToken = null; + GroupToken groupToken = null; - int length = paths.Length; + int length = paths.Length; - for (int i = 0; i < length; i++) - { - var (key, index) = ResolveKey(paths[i]); + for (int i = 0; i < length; i++) + { + var (key, index) = ResolveKey(paths[i]); - IToken find = null; - IEnumerable findTokens; + IToken find = null; + IEnumerable findTokens; - if (groupToken == null) - findTokens = tokens.Where(x => x is IValueToken).Where(x => ((IValueToken)x).Key == key); - else - findTokens = groupToken.Tokens.Where(x => x is IValueToken).Where(x => ((IValueToken)x).Key == key); + if (groupToken == null) + findTokens = FindTokens(tokens, key); + else + findTokens = FindTokens(groupToken.Tokens, key); - if (i == length - 1) + if (i == length - 1) + { + // remove + if (groupToken == null) { - // remove - if (groupToken == null) - findTokens.ToList().ForEach(item => - { - tokens.Remove(item); - }); - else - findTokens.ToList().ForEach(item => - { - groupToken.Tokens.Remove(item); - }); + foreach (var item in findTokens) + { + tokens.Remove(item); + } } else { - if (index > findTokens.Count()) - throw new IndexOutOfRangeException($"The key '{key}' index must be <= {findTokens.Count()}"); - - if (index <= findTokens.Count() - 1) - find = findTokens.ElementAt(index); - - if (find != null && find is GroupToken) + foreach (var item in findTokens) { - groupToken = (GroupToken)find; - } - else - { - // not found , break. - break; + groupToken.Tokens.Remove(item); } } } + else + { + var findTokensCount = findTokens.Count(); + if (index > findTokensCount) + throw new IndexOutOfRangeException($"The key '{key}' index must be <= {findTokensCount}"); - return this; - } + if (index <= findTokensCount - 1) + find = findTokens.ElementAt(index); - /// - /// Save the configuration content to specific file - /// - /// The file path - public void Save(string fileName) - { - if (string.IsNullOrWhiteSpace(fileName)) - { - throw new ArgumentException($"'{nameof(fileName)}' cannot be null or whitespace.", nameof(fileName)); + if (find != null && find is GroupToken groupToken1) + { + groupToken = groupToken1; + } + else + { + // not found , break. + break; + } } - - Save(fileName, Encoding.Default); } - /// - /// Save the configuration content to specific file - /// - /// The file path - /// The file encoding - public void Save(string fileName, Encoding encoding) + return this; + } + + /// + /// Save the configuration content to specific file + /// + /// The file path + /// + public void Save(string fileName) + { + if (string.IsNullOrWhiteSpace(fileName)) { - if (string.IsNullOrWhiteSpace(fileName)) - { - throw new ArgumentException($"'{nameof(fileName)}' cannot be null or whitespace.", nameof(fileName)); - } + throw new ArgumentException($"'{nameof(fileName)}' cannot be null or whitespace.", nameof(fileName)); + } - if (encoding is null) - { - throw new ArgumentNullException(nameof(encoding)); - } + Save(fileName, Encoding.Default); + } - using (StringWriter sw = new StringWriter(new StringBuilder())) - { - WriteTokenString(_tokens, sw, 0); - using (StreamWriter fsWriter = new StreamWriter(fileName,false,encoding)) - { - fsWriter.NewLine = Environment.NewLine; - fsWriter.Write(sw); - } - } + /// + /// Save the configuration content to specific file + /// + /// The file path + /// The file encoding + /// + /// + public void Save(string fileName, Encoding encoding) + { + if (string.IsNullOrWhiteSpace(fileName)) + { + throw new ArgumentException($"'{nameof(fileName)}' cannot be null or whitespace.", nameof(fileName)); } - /// - /// Return configuration file content - /// - public override string ToString() + if (encoding is null) { - StringWriter sw = new StringWriter(new StringBuilder()); + throw new ArgumentNullException(nameof(encoding)); + } - WriteTokenString(_tokens, sw, 0); + using StringWriter sw = new StringWriter(new StringBuilder()); - return sw.GetStringBuilder().ToString(); + WriteTokenString(_tokens, sw, 0); + using (StreamWriter fsWriter = new StreamWriter(fileName, false, encoding)) + { + fsWriter.NewLine = Environment.NewLine; + fsWriter.Write(sw); } + } - private void WriteTokenString(IEnumerable tokens, TextWriter textWriter, int level = 0) - { - var normalTokens = tokens.Where(x => x is CommentToken || x is ValueToken); - var groupTokens = tokens.Where(x => x is GroupToken); - textWriter.NewLine = Environment.NewLine; - foreach (var token in normalTokens) - { - if (token is CommentToken comment) - textWriter.WriteLine(PadLeftSpace(comment.ToString(), level)); + /// + /// Return configuration file content + /// + public override string ToString() + { + using StringWriter sw = new StringWriter(new StringBuilder()); - else if (token is ValueToken vaue) - textWriter.WriteLine(PadLeftSpace(vaue.ToString(), level)); - } + WriteTokenString(_tokens, sw, 0); - foreach (GroupToken group in groupTokens) - { - //if (group.Parent != null) - textWriter.WriteLine(); + return sw.GetStringBuilder().ToString(); + } - if (!string.IsNullOrWhiteSpace(group.Comment)) - textWriter.WriteLine(PadLeftSpace($"{group.Key} {group.Value} {{ # {group.Comment}", level)); - else - textWriter.WriteLine(PadLeftSpace($"{group.Key} {group.Value} {{ ", level)); + private void WriteTokenString(IEnumerable tokens, TextWriter textWriter, int level = 0) + { + var normalTokens = tokens.Where(x => x is CommentToken || x is ValueToken); + var groupTokens = tokens.Where(x => x is GroupToken); - WriteTokenString(group.Tokens, textWriter, level + 1); + textWriter.NewLine = Environment.NewLine; - // end - textWriter.WriteLine(PadLeftSpace("}", level)); - } + foreach (var token in normalTokens) + { + if (token is CommentToken comment) + textWriter.WriteLine(PadLeftSpace(comment.ToString(), level)); + else if (token is ValueToken vaue) + textWriter.WriteLine(PadLeftSpace(vaue.ToString(), level)); } - private string PadLeftSpace(string text, int level = 0) + foreach (GroupToken group in groupTokens) { - return text.PadLeft(text.Length + level * 2, ' '); + //if (group.Parent != null) + textWriter.WriteLine(); + + if (!string.IsNullOrWhiteSpace(group.Comment)) + textWriter.WriteLine(PadLeftSpace($"{group.Key} {group.Value} {{ # {group.Comment}", level)); + else + textWriter.WriteLine(PadLeftSpace($"{group.Key} {group.Value} {{ ", level)); + + WriteTokenString(group.Tokens, textWriter, level + 1); + + // end + textWriter.WriteLine(PadLeftSpace("}", level)); } + } - private IValueToken GetTokenFromPath(string keyPath) - { - var tokens = _tokens; + private string PadLeftSpace(string text, int level = 0) + { + return text.PadLeft(text.Length + (level * 2), ' '); + } - var paths = keyPath.Split(':'); + private IValueToken GetTokenFromPath(string keyPath) + { + var tokens = _tokens; - IValueToken result = null; + var paths = keyPath.Split(':'); - foreach (var key in paths) - { - var (keyName, index) = ResolveKey(key); + IValueToken result = null; - result = FindToken(tokens, keyName, index); - if (result != null) - { - if (result is GroupToken groupToken) - tokens = groupToken.Tokens.ToList(); - } - else - break; - } + foreach (var key in paths) + { + var (keyName, index) = ResolveKey(key); - return result; + result = FindToken(tokens, keyName, index); + if (result != null) + { + if (result is GroupToken groupToken) + tokens = groupToken.Tokens.ToList(); + } + else + { + break; + } } - private IList GetTokensFromPath(string keyPath) - { - var tokens = _tokens; + return result; + } + + private IList GetTokensFromPath(string keyPath) + { + var tokens = _tokens; + + var paths = keyPath.Split(':'); - var paths = keyPath.Split(':'); + IEnumerable result = null; - IEnumerable result = null; + IValueToken current = null; - IValueToken current = null; + for (int i = 0; i < paths.Length; i++) + { + var (keyName, index) = ResolveKey(paths[i]); - for (int i = 0; i < paths.Length; i++) + if (i == paths.Length - 1) + { + result = FindTokens(tokens, keyName); + } + else { - var (keyName, index) = ResolveKey(paths[i]); + current = FindToken(tokens, keyName, index); - if (i == paths.Length - 1) + if (current != null && current is GroupToken groupToken) { - result = FindTokens(tokens, keyName); - } - else - { - current = FindToken(tokens, keyName, index); - - if (current != null && current is GroupToken groupToken) - { - tokens = groupToken.Tokens.ToList(); - } + tokens = groupToken.Tokens.ToList(); } } - - return result.ToList(); } - private static IValueToken FindToken(IEnumerable tokens, string key, int index = 0) - { - return tokens.Where(x => x is IValueToken).Where(x => ((IValueToken)x).Key == key).ElementAtOrDefault(index) as IValueToken; - } + return result.ToList(); + } + + private static IValueToken FindToken(IEnumerable tokens, string key, int index = 0) + { + return tokens.Where(x => x is IValueToken valueToken && valueToken.Key == key).ElementAtOrDefault(index) as IValueToken; + } - private static IEnumerable FindTokens(IEnumerable tokens, string key) + private static IEnumerable FindTokens(IEnumerable tokens, string key) + { + return tokens.Where(x => x is IValueToken valueToken && valueToken.Key == key).Cast().ToArray(); + } + + private (string key, int index) ResolveKey(string key) + { + if (!KeyRegex.IsMatch(key)) { - return tokens.Where(x => x is IValueToken).Where(x => ((IValueToken)x).Key == key).Cast(); + throw new Exception($"The key '{key}' format is incorrect"); } - private (string key, int index) ResolveKey(string key) - { - if (!Regex.IsMatch(key, @"^[\w]+(\[\d+\])?$")) - { - throw new Exception($"The key '{key}' format is incorrect"); - } + var numberStartSymbol = key.IndexOf('['); - var numberStartSymbol = key.IndexOf('['); + var index = 0; + string keyName = key; - var index = 0; - string keyName = key; + if (numberStartSymbol > 0) + { + var numberStartIndex = numberStartSymbol + 1; - if (numberStartSymbol > 0) + if (!int.TryParse(key.Substring(numberStartIndex, key.Length - 1 - numberStartIndex), out index)) { - var numberStartIndex = numberStartSymbol + 1; - - if (!int.TryParse(key.Substring(numberStartIndex, key.Length - 1 - numberStartIndex), out index)) - { - // TODO - } - - keyName = key.Substring(0, numberStartSymbol); + // TODO } - return (keyName, index); + keyName = key.Substring(0, numberStartSymbol); } + return (keyName, index); } } diff --git a/NginxConfigParser/NginxConfigParser.csproj b/NginxConfigParser/NginxConfigParser.csproj index a461456..0b8bbfd 100644 --- a/NginxConfigParser/NginxConfigParser.csproj +++ b/NginxConfigParser/NginxConfigParser.csproj @@ -1,24 +1,26 @@  - - netstandard2.0 - Passingwind - 0.1.0 - MIT - https://github.com/jxnkwlp/NginxConfigParser - https://github.com/jxnkwlp/NginxConfigParser - Github - nginx - A .net standard library for reading and writing nginx configuration files. - Passingwind - + + netstandard2.0;netstandard2.1 + Passingwind + 0.1.4 + MIT + https://github.com/jxnkwlp/NginxConfigParser + https://github.com/jxnkwlp/NginxConfigParser + Github + nginx, nginx config + README.md + A .net standard library for reading and writing nginx configuration files. + Passingwind + latest + - - bin\NginxConfigParser.xml - + + bin\NginxConfigParser.xml + - - - + + + diff --git a/NginxConfigParser/Parser.cs b/NginxConfigParser/Parser.cs index 5647bf1..eb7c23c 100644 --- a/NginxConfigParser/Parser.cs +++ b/NginxConfigParser/Parser.cs @@ -2,145 +2,138 @@ using System.Collections.Generic; using System.IO; -namespace NginxConfigParser +namespace NginxConfigParser; + +public class Parser { - public class Parser + private readonly string _content = string.Empty; + private GroupToken _currentGroupToken; + private ValueToken _currentToken; + + private readonly List _tokens = new List(); + + public Parser(string content) { - //private readonly bool _ignoreError; - private readonly string _content = string.Empty; - private GroupToken _currentGroupToken = null; - private ValueToken _currentToken = null; + _content = content ?? throw new ArgumentNullException(nameof(content)); + } - private readonly List _tokens = new List(); + public IReadOnlyList GetTokens() => _tokens; - public Parser(string content) - { - _content = content ?? throw new ArgumentNullException(nameof(content)); - } + public void Parse() + { + var lineIndex = 0; - public IReadOnlyList GetTokens() => _tokens; + StringReader sr = new StringReader(_content); + string line = string.Empty; - public void Parse() + while ((line = sr.ReadLine()) != null) { - var lineIndex = 0; + lineIndex++; - StringReader sr = new StringReader(_content); - string line = string.Empty; + if (string.IsNullOrEmpty(line)) + continue; - while ((line = sr.ReadLine()) != null) - { - lineIndex++; + var text = line.Trim(); - if (string.IsNullOrEmpty(line)) - continue; + ParseLine(text, lineIndex); + } + } - var text = line.Trim(); + private void AddToken(IToken token) + { + if (_currentGroupToken != null) + _currentGroupToken.Tokens.Add(token); + else _tokens.Add(token); + } - ParseLine(text, lineIndex); - } - } + private void ParseLine(string text, int lineIndex) + { + var keyEndSymbol = text.IndexOf(' '); + var endSymbol = text.IndexOf(';'); + var commendSymbol = text.IndexOf('#'); + var groupStartSymbol = text.IndexOf('{'); + var groupEndSymbol = text.IndexOf('}'); - private void AddToken(IToken token) + if (text.Length == 0) { - if (_currentGroupToken != null) - _currentGroupToken.Tokens.Add(token); - else _tokens.Add(token); + return; } - private void ParseLine(string text, int lineIndex) + if (text[0] == '#') { - var keyEndSymbol = text.IndexOf(' '); - var endSymbol = text.IndexOf(';'); - var commendSymbol = text.IndexOf('#'); - var groupStartSymbol = text.IndexOf('{'); - var groupEndSymbol = text.IndexOf('}'); - - //var temp = text.Split(new string[] { " ", ";", "{", "}" }, System.StringSplitOptions.RemoveEmptyEntries).ToList(); - if (text.Length == 0) + var commendToken = new CommentToken(text.Trim().TrimStart('#').Trim()); + AddToken(commendToken); + return; + } + else if (text[0] == '\'') + { + if (_currentToken != null && _currentToken is ValueToken valueToken) { - return; - } + valueToken.Value += text.Trim(); - if (text[0] == '#') - { - var commendToken = new CommentToken(text.Trim().TrimStart('#').Trim()); - AddToken(commendToken); - return; - } - else if (text[0] == '\'') - { - if (_currentToken != null && _currentToken is ValueToken valueToken) + if (endSymbol > -1) { - valueToken.Value += text.Trim(); - - if (endSymbol > -1) - { - valueToken.Value = valueToken.Value.TrimEnd(';').Replace("\'\'", null); - AddToken(valueToken); - } - - return; + valueToken.Value = valueToken.Value.TrimEnd(';').Replace("\'\'", null); + AddToken(valueToken); } - else - throw new Exception(""); - } - else if (text[0] == '}') - { - if (_currentGroupToken?.Parent != null) - _currentGroupToken = _currentGroupToken?.Parent; - else - _currentGroupToken = null; - - _currentToken = null; return; } + throw new Exception(""); + } + else if (text[0] == '}') + { + _currentGroupToken = _currentGroupToken?.Parent; - string key = string.Empty; - string value = string.Empty; - string commend = string.Empty; + _currentToken = null; - if (keyEndSymbol > -1) - key = text.Substring(0, keyEndSymbol); + return; + } - if (groupStartSymbol > keyEndSymbol) - { - value = text.Substring(keyEndSymbol + 1, groupStartSymbol - keyEndSymbol - 1); - } - else if (endSymbol > keyEndSymbol) - value = text.Substring(keyEndSymbol + 1, endSymbol - keyEndSymbol - 1); - else if (endSymbol == -1) - { - value = text.Substring(keyEndSymbol + 1); - } + string key = string.Empty; + string value = string.Empty; + string commend = string.Empty; - if (commendSymbol > keyEndSymbol) - commend = text.Substring(commendSymbol + 1).Trim().TrimStart('#').Trim(); + if (keyEndSymbol > -1) + key = text.Substring(0, keyEndSymbol); - if (groupStartSymbol > -1) - { - var groupToken = new GroupToken(_currentGroupToken, key, value, commend); - AddToken(groupToken); - _currentGroupToken = groupToken; - return; - } + if (groupStartSymbol > keyEndSymbol) + { + value = text.Substring(keyEndSymbol + 1, groupStartSymbol - keyEndSymbol - 1); + } + else if (endSymbol > keyEndSymbol) + { + value = text.Substring(keyEndSymbol + 1, endSymbol - keyEndSymbol - 1); + } + else if (endSymbol == -1) + { + value = text.Substring(keyEndSymbol + 1); + } - if (groupStartSymbol == -1 && endSymbol == -1) - { - _currentToken = new ValueToken(_currentGroupToken, key, value, commend); - return; - } + if (commendSymbol > keyEndSymbol) + commend = text.Substring(commendSymbol + 1).Trim().TrimStart('#').Trim(); - if (endSymbol > -1) - { - AddToken(new ValueToken(_currentGroupToken, key, value?.Trim(), commend)); - return; - } + if (groupStartSymbol > -1) + { + var groupToken = new GroupToken(_currentGroupToken, key, value, commend); + AddToken(groupToken); + _currentGroupToken = groupToken; + return; + } - throw new Exception(""); + if (groupStartSymbol == -1 && endSymbol == -1) + { + _currentToken = new ValueToken(_currentGroupToken, key, value, commend); + return; } + if (endSymbol > -1) + { + AddToken(new ValueToken(_currentGroupToken, key, value?.Trim(), commend)); + return; + } + throw new Exception(""); } } diff --git a/NginxConfigParser/Token.cs b/NginxConfigParser/Token.cs index f192581..c7506e0 100644 --- a/NginxConfigParser/Token.cs +++ b/NginxConfigParser/Token.cs @@ -1,85 +1,82 @@ using System.Collections.Generic; -using System.Linq; -namespace NginxConfigParser +namespace NginxConfigParser; + +public class CommentToken : IToken { - public class CommentToken : IToken + public string Content { get; set; } + + public CommentToken(string text) { - public string Content { get; set; } + Content = text; + } - public CommentToken(string text) - { - Content = text; - } + public override string ToString() => $"# {Content}"; +} - public override string ToString() => $"# {Content}"; +public class ValueToken : IValueToken +{ + public ValueToken(GroupToken parent, string key, string value = null, string comment = null) + { + Key = key; + Value = value; + Comment = comment; + Parent = parent; } - public class ValueToken : IValueToken + public GroupToken Parent { get; } + + public string Key { get; } + public string Value { get; set; } + public string Comment { get; set; } + + public override string ToString() { - public ValueToken(GroupToken parent, string key, string value = null, string comment = null) - { - Key = key; - Value = value; - Comment = comment; - Parent = parent; - } - - public GroupToken Parent { get; } - - public string Key { get; } - public string Value { get; set; } - public string Comment { get; set; } - - public override string ToString() - { - if (!string.IsNullOrWhiteSpace(Comment)) - return $"{Key} {Value}; # {Comment}"; - else - return $"{Key} {Value};"; - } + if (!string.IsNullOrWhiteSpace(Comment)) + return $"{Key} {Value}; # {Comment}"; + + return $"{Key} {Value};"; } +} - public class GroupToken : IValueToken +public class GroupToken : IValueToken +{ + public GroupToken(GroupToken parent, string key, string value = null, string comment = null) { - public GroupToken(GroupToken parent, string key, string value = null, string comment = null) - { - Key = key; - Value = value == null ? value : value.Trim(); - Comment = comment; - Tokens = new List(); - Parent = parent; - } - - public string Key { get; } - public string Value { get; set; } - public string Comment { get; set; } - - public IList Tokens { get; } - - public GroupToken Parent { get; } - - public void Add(IToken token) - { - Tokens.Add(token); - } - - public void Add(string key, string value, string comment = null) - { - Add(new ValueToken(this, key, value, comment)); - } - - public override string ToString() - { - if (!string.IsNullOrWhiteSpace(Comment)) - return $"{Key} {Value}; # {Comment} => [{Tokens.Count()}]"; - else - return $"{Key} {Value} => [{Tokens.Count()}]"; - } + Key = key; + Value = value == null ? value : value.Trim(); + Comment = comment; + Tokens = new List(); + Parent = parent; + } + public string Key { get; } + public string Value { get; set; } + public string Comment { get; set; } + + public IList Tokens { get; } + + public GroupToken Parent { get; } + + public void Add(IToken token) + { + Tokens.Add(token); } - public class RootToken + public void Add(string key, string value, string comment = null) { + Add(new ValueToken(this, key, value, comment)); } + + public override string ToString() + { + if (!string.IsNullOrWhiteSpace(Comment)) + return $"{Key} {Value}; # {Comment} => [{Tokens.Count}]"; + + return $"{Key} {Value} => [{Tokens.Count}]"; + } +} + +public class RootToken +{ } diff --git a/NginxConfigParser/TokenType.cs b/NginxConfigParser/TokenType.cs index c1435c3..5bbf200 100644 --- a/NginxConfigParser/TokenType.cs +++ b/NginxConfigParser/TokenType.cs @@ -1,9 +1,8 @@ -namespace NginxConfigParser +namespace NginxConfigParser; + +internal enum TokenType { - internal enum TokenType - { - Comment, - KeyValue, - Group, - } + Comment = 0, + KeyValue = 1, + Group = 2, } diff --git a/NginxConfigParserTests/NginxConfigParserTests.csproj b/NginxConfigParserTests/NginxConfigParserTests.csproj index 99f825c..2c1f817 100644 --- a/NginxConfigParserTests/NginxConfigParserTests.csproj +++ b/NginxConfigParserTests/NginxConfigParserTests.csproj @@ -2,7 +2,7 @@ Exe - net5.0 + net8.0 false diff --git a/NginxConfigParserTests/Program.cs b/NginxConfigParserTests/Program.cs index 27f6108..433bf23 100644 --- a/NginxConfigParserTests/Program.cs +++ b/NginxConfigParserTests/Program.cs @@ -3,103 +3,99 @@ using System.Linq; using NginxConfigParser; -namespace NginxConfigParserTests +namespace NginxConfigParserTests; + +internal static class Program { - internal class Program + private static void Main(string[] args) { - private static void Main(string[] args) - { - Console.WriteLine("Hello World!"); - - // create new file - NginxConfig.Create() - .AddOrUpdate("http:server:listen", "80") - .AddOrUpdate("http:server:root", "/var/wwwroot") - // add location - .AddOrUpdate("http:server:location", "/", true, comment: "default") - .AddOrUpdate("http:server:location:root", "/app1") - // add location - .AddOrUpdate("http:server:location[1]", "~ ^/(images|javascript|js|css|flash|media|static)/", true) - .AddOrUpdate("http:server:location[1]:root", "/app2") - .AddOrUpdate("http:server:location[1]:expires", "/1d") - // add location - .AddOrUpdate("http:server:location[2]", "~/api", true, comment: "api") - .AddOrUpdate("http:server:location[2]:proxy_pass", "http://server.com") - // save file - .Save("temp2.conf"); - - Console.WriteLine("temp2.conf content: "); - Console.WriteLine(File.ReadAllText("temp2.conf")); - - // load exist files - var config = NginxConfig.LoadFrom("test.conf"); - - // read group - var group = config.GetGroup("http"); - Console.WriteLine(config.GetGroup("http")); - - // read key - Console.WriteLine(config["error_log"]); - Console.WriteLine(config.GetToken("error_log")); - - // read key - Console.WriteLine(config["http"]); - - // read key - //Console.WriteLine(config["http:include"]); - //Console.WriteLine(config["http:include[1]"]); - - // read key - config.GetTokens("http:include").ToList().ForEach(item => - { - Console.WriteLine(item); - }); - - // read - Console.WriteLine(config["http:sendfile"]); - Console.WriteLine(config.GetToken("http:sendfile")); - - // update value - config.AddOrUpdate("http:sendfile", "off", comment: "updated!"); - Console.WriteLine(config["http:sendfile"]); - - // add value - config.AddOrUpdate("http:root", "/var/wwwroot"); - Console.WriteLine(config["http:root"]); - - // add group and value - config.AddOrUpdate("http:server2:root", "/var/wwwroot"); - Console.WriteLine(config["http:server2:root"]); - - //config.AddOrUpdate("http:server:root", "/var/wwwroot", "updated 1"); - //Console.WriteLine(config["http:server:root"]); - - // update - config.AddOrUpdate("http:server[0]:root", "/var/wwwroot", comment: "updated 2"); - Console.WriteLine(config["http:server[0]:root"]); - - // update - config.AddOrUpdate("http:server[1]:root", "/var/wwwroot", comment: "updated 3"); - Console.WriteLine(config["http:server[1]:root"]); - - // add group and value - config.AddOrUpdate("http:server[3]:root", "/var/wwwroot", comment: "new"); - Console.WriteLine(config["http:server[3]:root"]); - - // add value to group - config.AddOrUpdate("http:server[3]:location", "/", true, comment: "new loaction"); - config.AddOrUpdate("http:server[3]:location:root", "/var/wwwroot"); - Console.WriteLine(config["http:server[3]:location:root"]); - - // remove - // config.Remove("http:upstream"); - - // save as file - config.Save("temp.conf"); - - // get content and save - // Console.WriteLine(config.ToString()); - // File.WriteAllText("temp2.conf", config.ToString()); - } + Console.WriteLine("Hello World!"); + + // create new file + NginxConfig.Create() + .AddOrUpdate("http:server:listen", "80") + .AddOrUpdate("http:server:root", "/var/wwwroot") + // add location + .AddOrUpdate("http:server:location", "/", true, comment: "default") + .AddOrUpdate("http:server:location:root", "/app1") + // add location + .AddOrUpdate("http:server:location[1]", "~ ^/(images|javascript|js|css|flash|media|static)/", true) + .AddOrUpdate("http:server:location[1]:root", "/app2") + .AddOrUpdate("http:server:location[1]:expires", "/1d") + // add location + .AddOrUpdate("http:server:location[2]", "~/api", true, comment: "api") + .AddOrUpdate("http:server:location[2]:proxy_pass", "http://server.com") + // save file + .Save("temp2.conf"); + + Console.WriteLine("temp2.conf content: "); + Console.WriteLine(File.ReadAllText("temp2.conf")); + + // load exist files + var config = NginxConfig.LoadFrom("test.conf"); + + // read group + var group = config.GetGroup("http"); + Console.WriteLine(config.GetGroup("http")); + + // read key + Console.WriteLine(config["error_log"]); + Console.WriteLine(config.GetToken("error_log")); + + // read key + Console.WriteLine(config["http"]); + + // read key + //Console.WriteLine(config["http:include"]); + //Console.WriteLine(config["http:include[1]"]); + + // read key + config.GetTokens("http:include").ToList().ForEach(item => Console.WriteLine(item)); + + // read + Console.WriteLine(config["http:sendfile"]); + Console.WriteLine(config.GetToken("http:sendfile")); + + // update value + config.AddOrUpdate("http:sendfile", "off", comment: "updated!"); + Console.WriteLine(config["http:sendfile"]); + + // add value + config.AddOrUpdate("http:root", "/var/wwwroot"); + Console.WriteLine(config["http:root"]); + + // add group and value + config.AddOrUpdate("http:server2:root", "/var/wwwroot"); + Console.WriteLine(config["http:server2:root"]); + + //config.AddOrUpdate("http:server:root", "/var/wwwroot", "updated 1"); + //Console.WriteLine(config["http:server:root"]); + + // update + config.AddOrUpdate("http:server[0]:root", "/var/wwwroot", comment: "updated 2"); + Console.WriteLine(config["http:server[0]:root"]); + + // update + config.AddOrUpdate("http:server[1]:root", "/var/wwwroot", comment: "updated 3"); + Console.WriteLine(config["http:server[1]:root"]); + + // add group and value + config.AddOrUpdate("http:server[3]:root", "/var/wwwroot", comment: "new"); + Console.WriteLine(config["http:server[3]:root"]); + + // add value to group + config.AddOrUpdate("http:server[3]:location", "/", true, comment: "new loaction") + .AddOrUpdate("http:server[3]:location:root", "/var/wwwroot"); + Console.WriteLine(config["http:server[3]:location:root"]); + + // remove + // config.Remove("http:upstream"); + + // save as file + config.Save("temp.conf"); + + // get content and save + // Console.WriteLine(config.ToString()); + // File.WriteAllText("temp2.conf", config.ToString()); } }