From e3dd2b8e2600d6a1e0cf96a228def6cbed647c46 Mon Sep 17 00:00:00 2001 From: nikiforovall Date: Tue, 17 Sep 2024 08:55:28 +0300 Subject: [PATCH] add Nall.NEST.MigtarionAnalyzer --- .github/workflows/build.yaml | 67 ++++ LICENSE.md | 21 ++ analyzer/.editorconfig | 283 ++++++++++++++++ analyzer/.gitignore | 306 ++++++++++++++++++ .../CodeFixResources.Designer.cs | 63 ++++ .../CodeFixResources.resx | 120 +++++++ ...ll.NEST.MigtarionAnalyzer.CodeFixes.csproj | 22 ++ ...icsearchNetInsteadOfNestCodeFixProvider.cs | 109 +++++++ ...Nall.NEST.MigtarionAnalyzer.Package.csproj | 45 +++ .../tools/install.ps1 | 275 ++++++++++++++++ .../tools/uninstall.ps1 | 282 ++++++++++++++++ .../Nall.NEST.MigtarionAnalyzer.Test.csproj | 30 ++ .../UseElasticsearchNetInsteadOfNestTests.cs | 186 +++++++++++ .../CSharpAnalyzerVerifier`1+Test.cs | 33 ++ .../Verifiers/CSharpAnalyzerVerifier`1.cs | 34 ++ .../Verifiers/CSharpCodeFixVerifier`2+Test.cs | 35 ++ .../Verifiers/CSharpCodeFixVerifier`2.cs | 60 ++++ .../CSharpCodeRefactoringVerifier`1+Test.cs | 33 ++ .../CSharpCodeRefactoringVerifier`1.cs | 39 +++ .../Verifiers/CSharpVerifierHelper.cs | 37 +++ .../VisualBasicAnalyzerVerifier`1+Test.cs | 14 + .../VisualBasicAnalyzerVerifier`1.cs | 34 ++ .../VisualBasicCodeFixVerifier`2+Test.cs | 13 + .../Verifiers/VisualBasicCodeFixVerifier`2.cs | 60 ++++ ...sualBasicCodeRefactoringVerifier`1+Test.cs | 11 + .../VisualBasicCodeRefactoringVerifier`1.cs | 39 +++ .../Nall.NEST.MigtarionAnalyzer.Vsix.csproj | 48 +++ .../source.extension.vsixmanifest | 24 ++ .../Nall.NEST.MigtarionAnalyzer.csproj | 21 ++ .../Resources.Designer.cs | 63 ++++ .../Resources.resx | 120 +++++++ .../UseElasticsearchNetInsteadOfNest.cs | 70 ++++ analyzer/Playground/Playground.csproj | 15 + analyzer/Playground/Program.cs | 15 + analyzer/README.md | 9 + analyzer/analyzer.sln | 52 +++ analyzer/global.json | 7 + 37 files changed, 2695 insertions(+) create mode 100644 .github/workflows/build.yaml create mode 100644 LICENSE.md create mode 100644 analyzer/.editorconfig create mode 100644 analyzer/.gitignore create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer.CodeFixes/CodeFixResources.Designer.cs create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer.CodeFixes/CodeFixResources.resx create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer.CodeFixes/Nall.NEST.MigtarionAnalyzer.CodeFixes.csproj create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer.CodeFixes/UseElasticsearchNetInsteadOfNestCodeFixProvider.cs create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer.Package/Nall.NEST.MigtarionAnalyzer.Package.csproj create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer.Package/tools/install.ps1 create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer.Package/tools/uninstall.ps1 create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer.Test/Nall.NEST.MigtarionAnalyzer.Test.csproj create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer.Test/UseElasticsearchNetInsteadOfNestTests.cs create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpAnalyzerVerifier`1+Test.cs create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpAnalyzerVerifier`1.cs create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpCodeFixVerifier`2+Test.cs create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpCodeFixVerifier`2.cs create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpCodeRefactoringVerifier`1+Test.cs create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpCodeRefactoringVerifier`1.cs create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpVerifierHelper.cs create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/VisualBasicAnalyzerVerifier`1+Test.cs create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/VisualBasicAnalyzerVerifier`1.cs create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/VisualBasicCodeFixVerifier`2+Test.cs create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/VisualBasicCodeFixVerifier`2.cs create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/VisualBasicCodeRefactoringVerifier`1+Test.cs create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/VisualBasicCodeRefactoringVerifier`1.cs create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer.Vsix/Nall.NEST.MigtarionAnalyzer.Vsix.csproj create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer.Vsix/source.extension.vsixmanifest create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer/Nall.NEST.MigtarionAnalyzer.csproj create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer/Resources.Designer.cs create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer/Resources.resx create mode 100644 analyzer/Nall.NEST.MigtarionAnalyzer/UseElasticsearchNetInsteadOfNest.cs create mode 100644 analyzer/Playground/Playground.csproj create mode 100644 analyzer/Playground/Program.cs create mode 100644 analyzer/README.md create mode 100644 analyzer/analyzer.sln create mode 100644 analyzer/global.json diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..3723d40 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,67 @@ +name: "Build" + +on: + push: + branches: + - main + paths-ignore: + - '**/*.md' + - '**/*.gitignore' + - '**/*.gitattributes' + workflow_dispatch: + paths-ignore: + - '**/*.md' + - '**/*.gitignore' + - '**/*.gitattributes' + +jobs: + build: + if: github.event_name == 'push' && contains(toJson(github.event.commits), '***NO_CI***') == false && contains(toJson(github.event.commits), '[ci skip]') == false && contains(toJson(github.event.commits), '[skip ci]') == false + name: Build + runs-on: windows-latest + env: + DOTNET_CLI_TELEMETRY_OPTOUT: 1 + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 + DOTNET_NOLOGO: true + DOTNET_GENERATE_ASPNET_CERTIFICATE: false + DOTNET_ADD_GLOBAL_TOOLS_TO_PATH: false + DOTNET_MULTILEVEL_LOOKUP: 0 + PACKAGE_PROJECT: analyzer\Nall.NEST.MigtarionAnalyzer\Nall.NEST.MigtarionAnalyzer.Package\ + VSIX_PROJECT: analyzer\Nall.NEST.MigtarionAnalyzer\Nall.NEST.MigtarionAnalyzer.Vsix\ + + steps: + - uses: actions/checkout@v2 + + - name: Setup .NET Core SDK + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 5.0.x + + - name: Setup MSBuild + uses: microsoft/setup-msbuild@v1 + + - name: Setup NuGet + uses: NuGet/setup-nuget@v1.0.5 + + - name: Add GPR Source + run: nuget sources Add -Name "GPR" -Source ${{ secrets.GPR_URI }} -UserName ${{ secrets.GPR_USERNAME }} -Password ${{ secrets.GITHUB_TOKEN }} + + - name: Build NuGet Package + run: | + msbuild /restore ${{ env.PACKAGE_PROJECT }} /p:Configuration=Release /p:PackageOutputPath=${{ github.workspace }}\artifacts + + - name: Build VSIX Package + run: | + msbuild /restore ${{ env.VSIX_PROJECT }} /p:Configuration=Release /p:OutDir=${{ github.workspace }}\artifacts + + - name: Push to GitHub Packages + run: nuget push ${{ github.workspace }}\artifacts\*.nupkg -Source "GPR" + + # upload artifacts + - name: Upload artifacts + uses: actions/upload-artifact@v2 + with: + name: release-pacakges + path: | + ${{ github.workspace }}\artifacts\**\*.vsix + ${{ github.workspace }}\artifacts\**\*.nupkg \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..829376c --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Oleksii Nikiforov + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/analyzer/.editorconfig b/analyzer/.editorconfig new file mode 100644 index 0000000..186f645 --- /dev/null +++ b/analyzer/.editorconfig @@ -0,0 +1,283 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Don't use tabs for indentation. +[*] +indent_style = space +# (Please don't specify an indent_size here; that has too many unintended consequences.) + +[*.{tf,tfvars,hcl}] +indent_size = 2 + +# Code files +[*.{cs,csx,vb,vbx}] +indent_size = 4 +insert_final_newline = true +charset = utf-8-bom + +# XML project files +[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] +indent_size = 2 + +# XML config files +[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] +indent_size = 2 + +# JSON files +[*.json] +indent_size = 2 + +# Powershell files +[*.ps1] +indent_size = 2 + +# Dotnet code style settings: +[*.{cs,vb}] +dotnet_diagnostic.xUnit2018.severity = none # "do not compare an object's exact type to the abstract class" is a valid assert, but very noisy right now + +# Sort using and Import directives with System.* appearing first +dotnet_sort_system_directives_first = true +dotnet_separate_import_directive_groups = false +# Avoid "this." and "Me." if not necessary +dotnet_style_qualification_for_field = false:refactoring +dotnet_style_qualification_for_property = false:refactoring +dotnet_style_qualification_for_method = false:refactoring +dotnet_style_qualification_for_event = false:refactoring + +# Use language keywords instead of framework type names for type references +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion + +# Suggest more modern language features when available +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion + +# Whitespace options +dotnet_style_allow_multiple_blank_lines_experimental = false + +# Non-private static fields are PascalCase +dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.symbols = non_private_static_fields +dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.style = non_private_static_field_style + +dotnet_naming_symbols.non_private_static_fields.applicable_kinds = field +dotnet_naming_symbols.non_private_static_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected +dotnet_naming_symbols.non_private_static_fields.required_modifiers = static + +dotnet_naming_style.non_private_static_field_style.capitalization = pascal_case + +# Non-private readonly fields are PascalCase +dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.symbols = non_private_readonly_fields +dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.style = non_private_readonly_field_style + +dotnet_naming_symbols.non_private_readonly_fields.applicable_kinds = field +dotnet_naming_symbols.non_private_readonly_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected +dotnet_naming_symbols.non_private_readonly_fields.required_modifiers = readonly + +dotnet_naming_style.non_private_readonly_field_style.capitalization = pascal_case + +# Constants are PascalCase +dotnet_naming_rule.constants_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.constants_should_be_pascal_case.symbols = constants +dotnet_naming_rule.constants_should_be_pascal_case.style = constant_style + +dotnet_naming_symbols.constants.applicable_kinds = field, local +dotnet_naming_symbols.constants.required_modifiers = const + +dotnet_naming_style.constant_style.capitalization = pascal_case + +# Static fields are camelCase and start with s_ +dotnet_naming_rule.static_fields_should_be_camel_case.severity = suggestion +dotnet_naming_rule.static_fields_should_be_camel_case.symbols = static_fields +dotnet_naming_rule.static_fields_should_be_camel_case.style = static_field_style + +dotnet_naming_symbols.static_fields.applicable_kinds = field +dotnet_naming_symbols.static_fields.required_modifiers = static + +dotnet_naming_style.static_field_style.capitalization = camel_case +dotnet_naming_style.static_field_style.required_prefix = s_ + +# Instance fields are camelCase and start with _ +dotnet_naming_rule.instance_fields_should_be_camel_case.severity = suggestion +dotnet_naming_rule.instance_fields_should_be_camel_case.symbols = instance_fields +dotnet_naming_rule.instance_fields_should_be_camel_case.style = instance_field_style + +dotnet_naming_symbols.instance_fields.applicable_kinds = field + +dotnet_naming_style.instance_field_style.capitalization = camel_case +dotnet_naming_style.instance_field_style.required_prefix = _ + +# Locals and parameters are camelCase +dotnet_naming_rule.locals_should_be_camel_case.severity = suggestion +dotnet_naming_rule.locals_should_be_camel_case.symbols = locals_and_parameters +dotnet_naming_rule.locals_should_be_camel_case.style = camel_case_style + +dotnet_naming_symbols.locals_and_parameters.applicable_kinds = parameter, local + +dotnet_naming_style.camel_case_style.capitalization = camel_case + +# Local functions are PascalCase +dotnet_naming_rule.local_functions_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.local_functions_should_be_pascal_case.symbols = local_functions +dotnet_naming_rule.local_functions_should_be_pascal_case.style = local_function_style + +dotnet_naming_symbols.local_functions.applicable_kinds = local_function + +dotnet_naming_style.local_function_style.capitalization = pascal_case + +# By default, name items with PascalCase +dotnet_naming_rule.members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.members_should_be_pascal_case.symbols = all_members +dotnet_naming_rule.members_should_be_pascal_case.style = pascal_case_style + +dotnet_naming_symbols.all_members.applicable_kinds = * + +dotnet_naming_style.pascal_case_style.capitalization = pascal_case + +# IDE0055: Fix formatting +# Workaround for https://github.com/dotnet/roslyn/issues/70570 +dotnet_diagnostic.IDE0055.severity = warning + +# CSharp code style settings: +[*.cs] +max_line_length=100 +# Newline settings +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 = flush_left + +# Whitespace options +csharp_style_allow_embedded_statements_on_same_line_experimental = false +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = false +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = false +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = false + +# Prefer "var" everywhere +csharp_style_var_for_built_in_types = true:suggestion +csharp_style_var_when_type_is_apparent = true:suggestion +csharp_style_var_elsewhere = true:suggestion + +# Prefer method-like constructs to have a block body +csharp_style_expression_bodied_methods = false:none +csharp_style_expression_bodied_constructors = false:none +csharp_style_expression_bodied_operators = false:none + +# Prefer property-like constructs to have an expression-body +csharp_style_expression_bodied_properties = true:none +csharp_style_expression_bodied_indexers = true:none +csharp_style_expression_bodied_accessors = true:none + +# Suggest more modern language features when available +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 +csharp_style_throw_expression = true:suggestion +csharp_style_conditional_delegate_call = true:suggestion +csharp_style_prefer_extended_property_pattern = true:suggestion + +# 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 = do_not_ignore +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 + +# Blocks are allowed +csharp_prefer_braces = true:error +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = false +csharp_place_attribute_on_same_line = never +csharp_max_initializer_elements_on_line = 1 +csharp_max_array_initializer_elements_on_line = 1 + +# CS4014: Because this call is not awaited, execution of the current method continues before the call is completed +dotnet_diagnostic.CS4014.severity = error + +# VSTHRD200: Use "Async" suffix for async methods +dotnet_diagnostic.VSTHRD200.severity = error + +# VSTHRD011: Use AsyncLazy instead +dotnet_diagnostic.VSTHRD011.severity = none + +# Consider calling Task.ConfigureAwait(Boolean) to signal your intention for continuation. +dotnet_diagnostic.CA2007.severity = none + +# CA1848: Use the LoggerMessage delegates +# Consider to use this approach later: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/loggermessage?view=aspnetcore-6.0 +# BUG: broken in dotnet7, will be fixed in dotnet8: https://github.com/dotnet/roslyn-analyzers/issues/6281 +dotnet_diagnostic.CA1848.severity = none + +# CA1308: Normalize strings to uppercase +dotnet_diagnostic.CA1308.severity = none + +# CS8618: Non-nullable field is uninitialized. Consider declaring as nullable. +dotnet_diagnostic.CS8618.severity = none + +# CA1707: Identifiers should not contain underscores +dotnet_diagnostic.CA1707.severity = none + +# CA1819: Properties should not return arrays +dotnet_diagnostic.CA1819.severity = none + +# IDE1006: Naming Styles +dotnet_diagnostic.IDE1006.severity = warning + +# VSTHRD111: Use ConfigureAwait(bool) +dotnet_diagnostic.VSTHRD111.severity = silent + +# CA2007: Consider calling ConfigureAwait on the awaited task +dotnet_diagnostic.CA2007.severity = silent + +# CA1716: Conflicts with the reserved language keyword +dotnet_diagnostic.CA1716.severity = silent + +# IDE0051: Remove unused private members +dotnet_diagnostic.IDE0051.severity = warning + +# Default severity for analyzer diagnostics with category 'CodeQuality' +dotnet_analyzer_diagnostic.category-CodeQuality.severity = warning + +# CS1591: Missing XML comment for publicly visible type or member +dotnet_diagnostic.CS1591.severity = silent + +# IDE0011: Add braces +dotnet_diagnostic.IDE0011.severity = suggestion + +# IDE0005: Using directive is unnecessary. +dotnet_diagnostic.IDE0005.severity = warning diff --git a/analyzer/.gitignore b/analyzer/.gitignore new file mode 100644 index 0000000..14ac32b --- /dev/null +++ b/analyzer/.gitignore @@ -0,0 +1,306 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# Azure Functions localsettings file +local.settings.json + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +#*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# Ionide +.ionide/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Include override files you do wish to add to version control using negated pattern +# +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc + +.terraform.lock.hcl + +# Terragrunt +.terragrunt-cache + +# OS X / macOS +.DS_Store + +Artifacts \ No newline at end of file diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer.CodeFixes/CodeFixResources.Designer.cs b/analyzer/Nall.NEST.MigtarionAnalyzer.CodeFixes/CodeFixResources.Designer.cs new file mode 100644 index 0000000..0b6c387 --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer.CodeFixes/CodeFixResources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Analyzer { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class CodeFixResources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal CodeFixResources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Analyzer.CodeFixResources", typeof(CodeFixResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer.CodeFixes/CodeFixResources.resx b/analyzer/Nall.NEST.MigtarionAnalyzer.CodeFixes/CodeFixResources.resx new file mode 100644 index 0000000..c7e0d4b --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer.CodeFixes/CodeFixResources.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer.CodeFixes/Nall.NEST.MigtarionAnalyzer.CodeFixes.csproj b/analyzer/Nall.NEST.MigtarionAnalyzer.CodeFixes/Nall.NEST.MigtarionAnalyzer.CodeFixes.csproj new file mode 100644 index 0000000..e6ed196 --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer.CodeFixes/Nall.NEST.MigtarionAnalyzer.CodeFixes.csproj @@ -0,0 +1,22 @@ + + + + netstandard2.0 + false + Nall.NEST.MigtarionAnalyzer + + + + + + + + + + + + + + + + diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer.CodeFixes/UseElasticsearchNetInsteadOfNestCodeFixProvider.cs b/analyzer/Nall.NEST.MigtarionAnalyzer.CodeFixes/UseElasticsearchNetInsteadOfNestCodeFixProvider.cs new file mode 100644 index 0000000..9e36472 --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer.CodeFixes/UseElasticsearchNetInsteadOfNestCodeFixProvider.cs @@ -0,0 +1,109 @@ +using System.Collections.Immutable; +using System.Composition; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Nall.NEST.MigtarionAnalyzer +{ + [ + ExportCodeFixProvider( + LanguageNames.CSharp, + Name = nameof(UseElasticsearchNetInsteadOfNestCodeFixProvider) + ), + Shared + ] + public class UseElasticsearchNetInsteadOfNestCodeFixProvider : CodeFixProvider + { + public sealed override ImmutableArray FixableDiagnosticIds + { + get { return ImmutableArray.Create(UseElasticsearchNetInsteadOfNest.DiagnosticId); } + } + + public sealed override FixAllProvider GetFixAllProvider() + { + return WellKnownFixAllProviders.BatchFixer; + } + + public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) + { + var root = await context + .Document.GetSyntaxRootAsync(context.CancellationToken) + .ConfigureAwait(false); + + var diagnostic = context.Diagnostics.First(); + var diagnosticSpan = diagnostic.Location.SourceSpan; + + var declaration = root.FindToken(diagnosticSpan.Start) + .Parent.AncestorsAndSelf() + .OfType() + .First(); + + context.RegisterCodeFix( + CodeAction.Create( + title: "Use ElasticsearchClient instead of IElasticClient", + createChangedDocument: c => + ReplaceWithElasticsearchClientAsync(context.Document, declaration, c), + equivalenceKey: nameof(UseElasticsearchNetInsteadOfNestCodeFixProvider) + ), + diagnostic + ); + } + + private async Task ReplaceWithElasticsearchClientAsync( + Document document, + IdentifierNameSyntax identifierName, + CancellationToken cancellationToken + ) + { + var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + var semanticModel = await document + .GetSemanticModelAsync(cancellationToken) + .ConfigureAwait(false); + + // Replace the using directive + var oldUsingDirective = root.DescendantNodes() + .OfType() + .FirstOrDefault(u => u.Name.ToString() == "Nest"); + + if (oldUsingDirective != null) + { + var newUsingDirective = SyntaxFactory.UsingDirective( + SyntaxFactory.ParseName("Elastic.Clients.Elasticsearch") + ).WithTriviaFrom(oldUsingDirective); // Preserve trivia + root = root.ReplaceNode(oldUsingDirective, newUsingDirective); + } + else + { + // If there's no existing Nest using directive, add the new one + var firstUsingDirective = root.DescendantNodes() + .OfType() + .FirstOrDefault(); + if (firstUsingDirective != null) + { + var newUsingDirective = SyntaxFactory.UsingDirective( + SyntaxFactory.ParseName("Elastic.Clients.Elasticsearch") + ); + root = root.InsertNodesBefore(firstUsingDirective, new[] { newUsingDirective }); + } + } + + // Replace IElasticClient with ElasticsearchClient + var nodesToReplace = root.DescendantNodes() + .OfType() + .Where(node => node.Identifier.ValueText == "IElasticClient"); + + root = root.ReplaceNodes( + nodesToReplace, + (node, _) => SyntaxFactory.IdentifierName("ElasticsearchClient").WithTriviaFrom(node) // Preserve trivia + ); + + return document.WithSyntaxRoot(root); + } + } +} diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer.Package/Nall.NEST.MigtarionAnalyzer.Package.csproj b/analyzer/Nall.NEST.MigtarionAnalyzer.Package/Nall.NEST.MigtarionAnalyzer.Package.csproj new file mode 100644 index 0000000..f3b0eed --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer.Package/Nall.NEST.MigtarionAnalyzer.Package.csproj @@ -0,0 +1,45 @@ + + + + netstandard2.0 + false + true + true + + + + Nall.NEST.MigtarionAnalyzer + 1.0.0.0 + Oleksii_Nikiforov + https://github.com/NikiforovAll/elasticsearch-dotnet-playground/LICENSE.md + https://github.com/NikiforovAll/elasticsearch-dotnet-playground + + https://github.com/NikiforovAll/elasticsearch-dotnet-playground + false + + This package helps with migration from Nest to Elastic.Clients.Elasticsearch + Copyright + analyzers + true + true + + $(TargetsForTfmSpecificContentInPackage);_AddAnalyzersToOutput + + + + + + + + + + + + + + + + + + + diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer.Package/tools/install.ps1 b/analyzer/Nall.NEST.MigtarionAnalyzer.Package/tools/install.ps1 new file mode 100644 index 0000000..fb6f2fa --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer.Package/tools/install.ps1 @@ -0,0 +1,275 @@ +param($installPath, $toolsPath, $package, $project) + +if($project.Object.SupportsPackageDependencyResolution) +{ + if($project.Object.SupportsPackageDependencyResolution()) + { + # Do not install analyzers via install.ps1, instead let the project system handle it. + return + } +} + +$analyzersPaths = Join-Path (Join-Path (Split-Path -Path $toolsPath -Parent) "analyzers") * -Resolve + +foreach($analyzersPath in $analyzersPaths) +{ + if (Test-Path $analyzersPath) + { + # Install the language agnostic analyzers. + foreach ($analyzerFilePath in Get-ChildItem -Path "$analyzersPath\*.dll" -Exclude *.resources.dll) + { + if($project.Object.AnalyzerReferences) + { + $project.Object.AnalyzerReferences.Add($analyzerFilePath.FullName) + } + } + } +} + +# $project.Type gives the language name like (C# or VB.NET) +$languageFolder = "" +if($project.Type -eq "C#") +{ + $languageFolder = "cs" +} +if($project.Type -eq "VB.NET") +{ + $languageFolder = "vb" +} +if($languageFolder -eq "") +{ + return +} + +foreach($analyzersPath in $analyzersPaths) +{ + # Install language specific analyzers. + $languageAnalyzersPath = join-path $analyzersPath $languageFolder + if (Test-Path $languageAnalyzersPath) + { + foreach ($analyzerFilePath in Get-ChildItem -Path "$languageAnalyzersPath\*.dll" -Exclude *.resources.dll) + { + if($project.Object.AnalyzerReferences) + { + $project.Object.AnalyzerReferences.Add($analyzerFilePath.FullName) + } + } + } +} +# SIG # Begin signature block +# MIIoKgYJKoZIhvcNAQcCoIIoGzCCKBcCAQExDzANBglghkgBZQMEAgEFADB5Bgor +# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG +# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCA/i+qRUHsWzI0s +# FVk99zLgt/HOEQ33uvkFsWtHTHZgf6CCDXYwggX0MIID3KADAgECAhMzAAADTrU8 +# esGEb+srAAAAAANOMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD +# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy +# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p +# bmcgUENBIDIwMTEwHhcNMjMwMzE2MTg0MzI5WhcNMjQwMzE0MTg0MzI5WjB0MQsw +# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u +# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy +# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +# AQDdCKiNI6IBFWuvJUmf6WdOJqZmIwYs5G7AJD5UbcL6tsC+EBPDbr36pFGo1bsU +# p53nRyFYnncoMg8FK0d8jLlw0lgexDDr7gicf2zOBFWqfv/nSLwzJFNP5W03DF/1 +# 1oZ12rSFqGlm+O46cRjTDFBpMRCZZGddZlRBjivby0eI1VgTD1TvAdfBYQe82fhm +# WQkYR/lWmAK+vW/1+bO7jHaxXTNCxLIBW07F8PBjUcwFxxyfbe2mHB4h1L4U0Ofa +# +HX/aREQ7SqYZz59sXM2ySOfvYyIjnqSO80NGBaz5DvzIG88J0+BNhOu2jl6Dfcq +# jYQs1H/PMSQIK6E7lXDXSpXzAgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE +# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUnMc7Zn/ukKBsBiWkwdNfsN5pdwAw +# RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW +# MBQGA1UEBRMNMjMwMDEyKzUwMDUxNjAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci +# tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j +# b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG +# CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu +# Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0 +# MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBAD21v9pHoLdBSNlFAjmk +# mx4XxOZAPsVxxXbDyQv1+kGDe9XpgBnT1lXnx7JDpFMKBwAyIwdInmvhK9pGBa31 +# TyeL3p7R2s0L8SABPPRJHAEk4NHpBXxHjm4TKjezAbSqqbgsy10Y7KApy+9UrKa2 +# kGmsuASsk95PVm5vem7OmTs42vm0BJUU+JPQLg8Y/sdj3TtSfLYYZAaJwTAIgi7d +# hzn5hatLo7Dhz+4T+MrFd+6LUa2U3zr97QwzDthx+RP9/RZnur4inzSQsG5DCVIM +# pA1l2NWEA3KAca0tI2l6hQNYsaKL1kefdfHCrPxEry8onJjyGGv9YKoLv6AOO7Oh +# JEmbQlz/xksYG2N/JSOJ+QqYpGTEuYFYVWain7He6jgb41JbpOGKDdE/b+V2q/gX +# UgFe2gdwTpCDsvh8SMRoq1/BNXcr7iTAU38Vgr83iVtPYmFhZOVM0ULp/kKTVoir +# IpP2KCxT4OekOctt8grYnhJ16QMjmMv5o53hjNFXOxigkQWYzUO+6w50g0FAeFa8 +# 5ugCCB6lXEk21FFB1FdIHpjSQf+LP/W2OV/HfhC3uTPgKbRtXo83TZYEudooyZ/A +# Vu08sibZ3MkGOJORLERNwKm2G7oqdOv4Qj8Z0JrGgMzj46NFKAxkLSpE5oHQYP1H +# tPx1lPfD7iNSbJsP6LiUHXH1MIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq +# hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x +# EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv +# bjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 +# IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEwOTA5WjB+MQswCQYDVQQG +# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG +# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQg +# Q29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC +# CgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+laUKq4BjgaBEm6f8MMHt03 +# a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc6Whe0t+bU7IKLMOv2akr +# rnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4Ddato88tt8zpcoRb0Rrrg +# OGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+lD3v++MrWhAfTVYoonpy +# 4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nkkDstrjNYxbc+/jLTswM9 +# sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6A4aN91/w0FK/jJSHvMAh +# dCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmdX4jiJV3TIUs+UsS1Vz8k +# A/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL5zmhD+kjSbwYuER8ReTB +# w3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zdsGbiwZeBe+3W7UvnSSmn +# Eyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3T8HhhUSJxAlMxdSlQy90 +# lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS4NaIjAsCAwEAAaOCAe0w +# ggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRIbmTlUAXTgqoXNzcitW2o +# ynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYD +# VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBDuRQFTuHqp8cx0SOJNDBa +# BgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny +# bC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3JsMF4GCCsG +# AQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3dy5taWNyb3NvZnQuY29t +# L3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3J0MIGfBgNV +# HSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEFBQcCARYzaHR0cDovL3d3 +# dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1hcnljcHMuaHRtMEAGCCsG +# AQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkAYwB5AF8AcwB0AGEAdABl +# AG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn8oalmOBUeRou09h0ZyKb +# C5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7v0epo/Np22O/IjWll11l +# hJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0bpdS1HXeUOeLpZMlEPXh6 +# I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/KmtYSWMfCWluWpiW5IP0 +# wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvyCInWH8MyGOLwxS3OW560 +# STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBpmLJZiWhub6e3dMNABQam +# ASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJihsMdYzaXht/a8/jyFqGa +# J+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYbBL7fQccOKO7eZS/sl/ah +# XJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbSoqKfenoi+kiVH6v7RyOA +# 9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sLgOppO6/8MO0ETI7f33Vt +# Y5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtXcVZOSEXAQsmbdlsKgEhr +# /Xmfwb1tbWrJUnMTDXpQzTGCGgowghoGAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw +# EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN +# aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp +# Z25pbmcgUENBIDIwMTECEzMAAANOtTx6wYRv6ysAAAAAA04wDQYJYIZIAWUDBAIB +# BQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO +# MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIEY4Ow3COroWH11sAEOoStJj +# 1u4sq9rcx0dAx0gyZLHCMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8A +# cwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEB +# BQAEggEAFlSLlk17KQp2AwLbr5e4T5zyE44MGZOdNejIip+Mg8co8qho16qdNSvg +# AhvoJYxPJJr70DSCU9BIUoWY7hXoi9S4P08YlAid7BUT5OciIgHlrb8I900LaE+S +# 83rSvfVU1CZCjiSwcgng5DD2VPRo0Lu4G9p2Ky14dyOPwtPvrpsib5s9kewZLdiy +# /KxEDLKX8P+cHat1xH7RaZLDNxweRS6GSomjE2vjOlQHNSW879XR8bSoAt/m4uR1 +# WyrAxTGZb4miEYX+I5HsrWvbZLw9NSCJ/crbbap3LIobfQtK5binjY7v4MQp/5Oq +# y4S/4FAfwhWDXfaQfq6YTeOjHRVQbKGCF5QwgheQBgorBgEEAYI3AwMBMYIXgDCC +# F3wGCSqGSIb3DQEHAqCCF20wghdpAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFSBgsq +# hkiG9w0BCRABBKCCAUEEggE9MIIBOQIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFl +# AwQCAQUABCCV3irbWIoYz2Llfx9YQhUNtcP6GOrL7+YTUXQ4y5qzWAIGZNTJrsAW +# GBMyMDIzMDgzMTAwMTI1OC45ODNaMASAAgH0oIHRpIHOMIHLMQswCQYDVQQGEwJV +# UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE +# ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1l +# cmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046OTIwMC0w +# NUUwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2Wg +# ghHqMIIHIDCCBQigAwIBAgITMwAAAc9SNr5xS81IygABAAABzzANBgkqhkiG9w0B +# AQsFADB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE +# BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYD +# VQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDAeFw0yMzA1MjUxOTEy +# MTFaFw0yNDAyMDExOTEyMTFaMIHLMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz +# aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv +# cnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25z +# MScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046OTIwMC0wNUUwLUQ5NDcxJTAjBgNV +# BAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggIiMA0GCSqGSIb3DQEB +# AQUAA4ICDwAwggIKAoICAQC4Pct+15TYyrUje553lzBQodgmd5Bz7WuH8SdHpAoW +# z+01TrHExBSuaMKnxvVMsyYtas5h6aopUGAS5WKVLZAvUtH62TKmAE0JK+i1hafi +# CSXLZPcRexxeRkOqeZefLBzXp0nudMOXUUab333Ss8LkoK4l3LYxm1Ebsr3b2OTo +# 2ebsAoNJ4kSxmVuPM7C+RDhGtVKR/EmHsQ9GcwGmluu54bqiVFd0oAFBbw4txTU1 +# mruIGWP/i+sgiNqvdV/wah/QcrKiGlpWiOr9a5aGrJaPSQD2xgEDdPbrSflYxsRM +# dZCJI8vzvOv6BluPcPPGGVLEaU7OszdYjK5f4Z5Su/lPK1eST5PC4RFsVcOiS4L0 +# sI4IFZywIdDJHoKgdqWRp6Q5vEDk8kvZz6HWFnYLOlHuqMEYvQLr6OgooYU9z0A5 +# cMLHEIHYV1xiaBzx2ERiRY9MUPWohh+TpZWEUZlUm/q9anXVRN0ujejm6OsUVFDs +# sIMszRNCqEotJGwtHHm5xrCKuJkFr8GfwNelFl+XDoHXrQYL9zY7Np+frsTXQpKR +# NnmI1ashcn5EC+wxUt/EZIskWzewEft0/+/0g3+8YtMkUdaQE5+8e7C8UMiXOHkM +# K25jNNQqLCedlJwFIf9ir9SpMc72NR+1j6Uebiz/ZPV74do3jdVvq7DiPFlTb92U +# KwIDAQABo4IBSTCCAUUwHQYDVR0OBBYEFDaeKPtp0eTSVdG+gZc5BDkabTg4MB8G +# A1UdIwQYMBaAFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMF8GA1UdHwRYMFYwVKBSoFCG +# Tmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUy +# MFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNybDBsBggrBgEFBQcBAQRgMF4w +# XAYIKwYBBQUHMAKGUGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2Vy +# dHMvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3J0MAwG +# A1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwDgYDVR0PAQH/BAQD +# AgeAMA0GCSqGSIb3DQEBCwUAA4ICAQBQgm4pnA0xkd/9uKXJMzdMYyxUfUm/ZusU +# Ba32MEZXQuMGp20pSuX2VW9/tpTMo5bkaJdBVoUyd2DbDsNb1kjr/36ntT0jvL3A +# oWStAFhZBypmpPbx+BPK49ZlejlM4d5epX668tRRGfFip9Til9yKRfXBrXnM/q64 +# IinN7zXEQ3FFQhdJMzt8ibXClO7eFA+1HiwZPWysYWPb/ZOFobPEMvXie+GmEbTK +# bhE5tze6RrA9aejjP+v1ouFoD5bMj5Qg+wfZXqe+hfYKpMd8QOnQyez+Nlj1ityn +# OZWfwHVR7dVwV0yLSlPT+yHIO8g+3fWiAwpoO17bDcntSZ7YOBljXrIgad4W4gX+ +# 4tp1eBsc6XWIITPBNzxQDZZRxD4rXzOB6XRlEVJdYZQ8gbXOirg/dNvS2GxcR50Q +# dOXDAumdEHaGNHb6y2InJadCPp2iT5QLC4MnzR+YZno1b8mWpCdOdRs9g21QbbrI +# 06iLk9KD61nx7K5ReSucuS5Z9nbkIBaLUxDesFhr1wmd1ynf0HQ51Swryh7YI7TX +# T0jr81mbvvI9xtoqjFvIhNBsICdCfTR91ylJTH8WtUlpDhEgSqWt3gzNLPTSvXAx +# XTpIM583sZdd+/2YGADMeWmt8PuMce6GsIcLCOF2NiYZ10SXHZS5HRrLrChuzedD +# RisWpIu5uTCCB3EwggVZoAMCAQICEzMAAAAVxedrngKbSZkAAAAAABUwDQYJKoZI +# hvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw +# DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x +# MjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAy +# MDEwMB4XDTIxMDkzMDE4MjIyNVoXDTMwMDkzMDE4MzIyNVowfDELMAkGA1UEBhMC +# VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV +# BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp +# bWUtU3RhbXAgUENBIDIwMTAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +# AQDk4aZM57RyIQt5osvXJHm9DtWC0/3unAcH0qlsTnXIyjVX9gF/bErg4r25Phdg +# M/9cT8dm95VTcVrifkpa/rg2Z4VGIwy1jRPPdzLAEBjoYH1qUoNEt6aORmsHFPPF +# dvWGUNzBRMhxXFExN6AKOG6N7dcP2CZTfDlhAnrEqv1yaa8dq6z2Nr41JmTamDu6 +# GnszrYBbfowQHJ1S/rboYiXcag/PXfT+jlPP1uyFVk3v3byNpOORj7I5LFGc6XBp +# Dco2LXCOMcg1KL3jtIckw+DJj361VI/c+gVVmG1oO5pGve2krnopN6zL64NF50Zu +# yjLVwIYwXE8s4mKyzbnijYjklqwBSru+cakXW2dg3viSkR4dPf0gz3N9QZpGdc3E +# XzTdEonW/aUgfX782Z5F37ZyL9t9X4C626p+Nuw2TPYrbqgSUei/BQOj0XOmTTd0 +# lBw0gg/wEPK3Rxjtp+iZfD9M269ewvPV2HM9Q07BMzlMjgK8QmguEOqEUUbi0b1q +# GFphAXPKZ6Je1yh2AuIzGHLXpyDwwvoSCtdjbwzJNmSLW6CmgyFdXzB0kZSU2LlQ +# +QuJYfM2BjUYhEfb3BvR/bLUHMVr9lxSUV0S2yW6r1AFemzFER1y7435UsSFF5PA +# PBXbGjfHCBUYP3irRbb1Hode2o+eFnJpxq57t7c+auIurQIDAQABo4IB3TCCAdkw +# EgYJKwYBBAGCNxUBBAUCAwEAATAjBgkrBgEEAYI3FQIEFgQUKqdS/mTEmr6CkTxG +# NSnPEP8vBO4wHQYDVR0OBBYEFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMFwGA1UdIARV +# MFMwUQYMKwYBBAGCN0yDfQEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWlj +# cm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0bTATBgNVHSUEDDAK +# BggrBgEFBQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMC +# AYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvX +# zpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20v +# cGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYI +# KwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5j +# b20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDANBgkqhkiG +# 9w0BAQsFAAOCAgEAnVV9/Cqt4SwfZwExJFvhnnJL/Klv6lwUtj5OR2R4sQaTlz0x +# M7U518JxNj/aZGx80HU5bbsPMeTCj/ts0aGUGCLu6WZnOlNN3Zi6th542DYunKmC +# VgADsAW+iehp4LoJ7nvfam++Kctu2D9IdQHZGN5tggz1bSNU5HhTdSRXud2f8449 +# xvNo32X2pFaq95W2KFUn0CS9QKC/GbYSEhFdPSfgQJY4rPf5KYnDvBewVIVCs/wM +# nosZiefwC2qBwoEZQhlSdYo2wh3DYXMuLGt7bj8sCXgU6ZGyqVvfSaN0DLzskYDS +# PeZKPmY7T7uG+jIa2Zb0j/aRAfbOxnT99kxybxCrdTDFNLB62FD+CljdQDzHVG2d +# Y3RILLFORy3BFARxv2T5JL5zbcqOCb2zAVdJVGTZc9d/HltEAY5aGZFrDZ+kKNxn +# GSgkujhLmm77IVRrakURR6nxt67I6IleT53S0Ex2tVdUCbFpAUR+fKFhbHP+Crvs +# QWY9af3LwUFJfn6Tvsv4O+S3Fb+0zj6lMVGEvL8CwYKiexcdFYmNcP7ntdAoGokL +# jzbaukz5m/8K6TT4JDVnK+ANuOaMmdbhIurwJ0I9JZTmdHRbatGePu1+oDEzfbzL +# 6Xu/OHBE0ZDxyKs6ijoIYn/ZcGNTTY3ugm2lBRDBcQZqELQdVTNYs6FwZvKhggNN +# MIICNQIBATCB+aGB0aSBzjCByzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp +# bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw +# b3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEn +# MCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjkyMDAtMDVFMC1EOTQ3MSUwIwYDVQQD +# ExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloiMKAQEwBwYFKw4DAhoDFQDq +# 8xzVXwLguauAQj1rrJ4/TyEMm6CBgzCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYD +# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy +# b3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1w +# IFBDQSAyMDEwMA0GCSqGSIb3DQEBCwUAAgUA6JpNsjAiGA8yMDIzMDgzMDIzMjIy +# NloYDzIwMjMwODMxMjMyMjI2WjB0MDoGCisGAQQBhFkKBAExLDAqMAoCBQDomk2y +# AgEAMAcCAQACAi7oMAcCAQACAhLnMAoCBQDom58yAgEAMDYGCisGAQQBhFkKBAIx +# KDAmMAwGCisGAQQBhFkKAwKgCjAIAgEAAgMHoSChCjAIAgEAAgMBhqAwDQYJKoZI +# hvcNAQELBQADggEBADE16CHIs3WeXYKQG9djja+StAB7gsNJxV9p+CETL3847UL3 +# +DIeoj6p5g0FkS8PJK2xc+UbcNx6XJO+WUXEbU9GL4mrOCQjYOM+i3r8FEU+l3Gh +# 6ZG/9ygsIYRXEfDKK4lsbrrUkFQs9nDISHT3f8JZEJJXSsGmwcHWlNC0LC8bv0Jp +# e2Bw2+SNc6SlGD8Vv45r4WFPHhfSioCz4HSsF1He3/2Wku7OH85FKvugBlsca7+F +# bpGsDSL4LO9bv60DxuD+8xBZuyTB8s64ifCGlOXCNpK5VaHND48PhoJbuD0COwlM +# Rn5NlT6T4hhtkPOqNscMlzYHmTOKc5NhWK8PyrIxggQNMIIECQIBATCBkzB8MQsw +# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u +# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNy +# b3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAAc9SNr5xS81IygABAAABzzAN +# BglghkgBZQMEAgEFAKCCAUowGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMC8G +# CSqGSIb3DQEJBDEiBCAjGiC3/PscCMBvPZjpZqbYcL2WRZ+Ecf74oiIPQKkjSzCB +# +gYLKoZIhvcNAQkQAi8xgeowgecwgeQwgb0EILPpsLqeNS4NuYXE2VJlMuvQeWVA +# 80ZDFhpOPjSzhPa/MIGYMIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh +# c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD +# b3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIw +# MTACEzMAAAHPUja+cUvNSMoAAQAAAc8wIgQgWdbLA3Co0zf3nE5086HU0tdn0vK7 +# yXyU9aAFpszvWFIwDQYJKoZIhvcNAQELBQAEggIANrHN06oaP0N1lUSxxoJteJgI +# fQjN82xV5VSE0cwNCBy05fg1VydPERF59+MIwIlJHhikSo3YOj5tt3AohC78U46P +# 2IdrLHKlA3rjiLUGwQvGUKJUSsEH4uueA1mmh9jwUBJhY3NjTcMQaQqp/oxZTaya +# l7NqbubBIZvsDD126SUr8jtVWtZZzw8pnWCFb4Rijii4fY1UiQzfQLFwqQuid6tE +# I0AaY3IoTlp7U9K2wfAPWcP1G7n3qv+990GEiQlGJlCfIJSSJQodzL2QZF5HCn/K +# SfgkRPn3y/Aax8683mWCT8zricYzO3MZ9j0T7tAcqOiWb7PFCsk5Va44lq4Gv0u+ +# +60FYCAA/Qn6eMuNkqIpBeIK0+NYUcMSwPdY/riKXdgkVLwChEJC5WWznD/Iqsil +# Jj9XYailhXzYx7Pa2MLays62LPwCnUxRQBTD9/rL3XQMj69iA4lisb51dKAtrqAU +# 53aRXFn+twYYFTAUQ/oNK14nZEQE5H53xAfhphMokJOu+CnQQKeCMeYlex6Q4zfw +# TQxP/xXZ+QW2cSZTwh1d5iE0XMhKCZxhxIOF/rRA+75L5GUz60reRZPeH/7USYZL +# VPc0+kxIdSbNFJAhAp0u59wSMQdBofor3+HfDfmxmoSjfCSH4TvOkNIulX1PPJPX +# UB7H4n7XHWJPkUU0cUw= +# SIG # End signature block diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer.Package/tools/uninstall.ps1 b/analyzer/Nall.NEST.MigtarionAnalyzer.Package/tools/uninstall.ps1 new file mode 100644 index 0000000..e42f2dc --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer.Package/tools/uninstall.ps1 @@ -0,0 +1,282 @@ +param($installPath, $toolsPath, $package, $project) + +if($project.Object.SupportsPackageDependencyResolution) +{ + if($project.Object.SupportsPackageDependencyResolution()) + { + # Do not uninstall analyzers via uninstall.ps1, instead let the project system handle it. + return + } +} + +$analyzersPaths = Join-Path (Join-Path (Split-Path -Path $toolsPath -Parent) "analyzers") * -Resolve + +foreach($analyzersPath in $analyzersPaths) +{ + # Uninstall the language agnostic analyzers. + if (Test-Path $analyzersPath) + { + foreach ($analyzerFilePath in Get-ChildItem -Path "$analyzersPath\*.dll" -Exclude *.resources.dll) + { + if($project.Object.AnalyzerReferences) + { + $project.Object.AnalyzerReferences.Remove($analyzerFilePath.FullName) + } + } + } +} + +# $project.Type gives the language name like (C# or VB.NET) +$languageFolder = "" +if($project.Type -eq "C#") +{ + $languageFolder = "cs" +} +if($project.Type -eq "VB.NET") +{ + $languageFolder = "vb" +} +if($languageFolder -eq "") +{ + return +} + +foreach($analyzersPath in $analyzersPaths) +{ + # Uninstall language specific analyzers. + $languageAnalyzersPath = join-path $analyzersPath $languageFolder + if (Test-Path $languageAnalyzersPath) + { + foreach ($analyzerFilePath in Get-ChildItem -Path "$languageAnalyzersPath\*.dll" -Exclude *.resources.dll) + { + if($project.Object.AnalyzerReferences) + { + try + { + $project.Object.AnalyzerReferences.Remove($analyzerFilePath.FullName) + } + catch + { + + } + } + } + } +} +# SIG # Begin signature block +# MIIoLQYJKoZIhvcNAQcCoIIoHjCCKBoCAQExDzANBglghkgBZQMEAgEFADB5Bgor +# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG +# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDC68wb97fg0QGL +# yXrxJhYfmibzcOh8caqC0uZprfczDaCCDXYwggX0MIID3KADAgECAhMzAAADTrU8 +# esGEb+srAAAAAANOMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD +# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy +# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p +# bmcgUENBIDIwMTEwHhcNMjMwMzE2MTg0MzI5WhcNMjQwMzE0MTg0MzI5WjB0MQsw +# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u +# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy +# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +# AQDdCKiNI6IBFWuvJUmf6WdOJqZmIwYs5G7AJD5UbcL6tsC+EBPDbr36pFGo1bsU +# p53nRyFYnncoMg8FK0d8jLlw0lgexDDr7gicf2zOBFWqfv/nSLwzJFNP5W03DF/1 +# 1oZ12rSFqGlm+O46cRjTDFBpMRCZZGddZlRBjivby0eI1VgTD1TvAdfBYQe82fhm +# WQkYR/lWmAK+vW/1+bO7jHaxXTNCxLIBW07F8PBjUcwFxxyfbe2mHB4h1L4U0Ofa +# +HX/aREQ7SqYZz59sXM2ySOfvYyIjnqSO80NGBaz5DvzIG88J0+BNhOu2jl6Dfcq +# jYQs1H/PMSQIK6E7lXDXSpXzAgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE +# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUnMc7Zn/ukKBsBiWkwdNfsN5pdwAw +# RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW +# MBQGA1UEBRMNMjMwMDEyKzUwMDUxNjAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci +# tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j +# b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG +# CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu +# Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0 +# MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBAD21v9pHoLdBSNlFAjmk +# mx4XxOZAPsVxxXbDyQv1+kGDe9XpgBnT1lXnx7JDpFMKBwAyIwdInmvhK9pGBa31 +# TyeL3p7R2s0L8SABPPRJHAEk4NHpBXxHjm4TKjezAbSqqbgsy10Y7KApy+9UrKa2 +# kGmsuASsk95PVm5vem7OmTs42vm0BJUU+JPQLg8Y/sdj3TtSfLYYZAaJwTAIgi7d +# hzn5hatLo7Dhz+4T+MrFd+6LUa2U3zr97QwzDthx+RP9/RZnur4inzSQsG5DCVIM +# pA1l2NWEA3KAca0tI2l6hQNYsaKL1kefdfHCrPxEry8onJjyGGv9YKoLv6AOO7Oh +# JEmbQlz/xksYG2N/JSOJ+QqYpGTEuYFYVWain7He6jgb41JbpOGKDdE/b+V2q/gX +# UgFe2gdwTpCDsvh8SMRoq1/BNXcr7iTAU38Vgr83iVtPYmFhZOVM0ULp/kKTVoir +# IpP2KCxT4OekOctt8grYnhJ16QMjmMv5o53hjNFXOxigkQWYzUO+6w50g0FAeFa8 +# 5ugCCB6lXEk21FFB1FdIHpjSQf+LP/W2OV/HfhC3uTPgKbRtXo83TZYEudooyZ/A +# Vu08sibZ3MkGOJORLERNwKm2G7oqdOv4Qj8Z0JrGgMzj46NFKAxkLSpE5oHQYP1H +# tPx1lPfD7iNSbJsP6LiUHXH1MIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq +# hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x +# EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv +# bjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 +# IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEwOTA5WjB+MQswCQYDVQQG +# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG +# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQg +# Q29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC +# CgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+laUKq4BjgaBEm6f8MMHt03 +# a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc6Whe0t+bU7IKLMOv2akr +# rnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4Ddato88tt8zpcoRb0Rrrg +# OGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+lD3v++MrWhAfTVYoonpy +# 4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nkkDstrjNYxbc+/jLTswM9 +# sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6A4aN91/w0FK/jJSHvMAh +# dCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmdX4jiJV3TIUs+UsS1Vz8k +# A/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL5zmhD+kjSbwYuER8ReTB +# w3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zdsGbiwZeBe+3W7UvnSSmn +# Eyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3T8HhhUSJxAlMxdSlQy90 +# lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS4NaIjAsCAwEAAaOCAe0w +# ggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRIbmTlUAXTgqoXNzcitW2o +# ynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYD +# VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBDuRQFTuHqp8cx0SOJNDBa +# BgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny +# bC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3JsMF4GCCsG +# AQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3dy5taWNyb3NvZnQuY29t +# L3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3J0MIGfBgNV +# HSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEFBQcCARYzaHR0cDovL3d3 +# dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1hcnljcHMuaHRtMEAGCCsG +# AQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkAYwB5AF8AcwB0AGEAdABl +# AG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn8oalmOBUeRou09h0ZyKb +# C5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7v0epo/Np22O/IjWll11l +# hJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0bpdS1HXeUOeLpZMlEPXh6 +# I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/KmtYSWMfCWluWpiW5IP0 +# wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvyCInWH8MyGOLwxS3OW560 +# STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBpmLJZiWhub6e3dMNABQam +# ASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJihsMdYzaXht/a8/jyFqGa +# J+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYbBL7fQccOKO7eZS/sl/ah +# XJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbSoqKfenoi+kiVH6v7RyOA +# 9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sLgOppO6/8MO0ETI7f33Vt +# Y5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtXcVZOSEXAQsmbdlsKgEhr +# /Xmfwb1tbWrJUnMTDXpQzTGCGg0wghoJAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw +# EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN +# aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp +# Z25pbmcgUENBIDIwMTECEzMAAANOtTx6wYRv6ysAAAAAA04wDQYJYIZIAWUDBAIB +# BQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO +# MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIBdcqRcs5QL71hlQnl3M636V +# 5iTZvb6co3MHeMuIr36qMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8A +# cwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEB +# BQAEggEARbhO/zqm6SWBf6DSJ3P1r82VjSyMGXaLtMfTOq/bqHOXPOqC25R1v5uO +# zu4ri+UOS8dU6EfW6C9Xf/Z1Ue/oxrvxn5j8mPvsmcs5OyDO0hW0Wv6pYEy5Z5up +# mfcqvfUfl3+ir29lgPuz0f1mLpz0XxqhjqElEi5RfZD1k1YVg65f0qHroP2txql5 +# TfC77DXJ8verzVm1wqXBHTAERQD94TJobahYTCmyaudMjLUVFakv2lTMv0YTnrQR +# So006ZQg3i1jcVCJt/bRDGKh3xUo1IHgoh3NjMEkxT3iWt8rnX8Us6T6Zg8B2OxC +# 0EnuIu/eYYUlYTLQxO9eks7w1kVcUqGCF5cwgheTBgorBgEEAYI3AwMBMYIXgzCC +# F38GCSqGSIb3DQEHAqCCF3AwghdsAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFSBgsq +# hkiG9w0BCRABBKCCAUEEggE9MIIBOQIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFl +# AwQCAQUABCBQ1HvJFFsT0ICl6oEZlSNN8DlUeQobBHt/oTUGN6iKBgIGZNTKS0Bc +# GBMyMDIzMDgzMTAwMTI1OC4zODVaMASAAgH0oIHRpIHOMIHLMQswCQYDVQQGEwJV +# UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE +# ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1l +# cmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046N0YwMC0w +# NUUwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2Wg +# ghHtMIIHIDCCBQigAwIBAgITMwAAAdWpAs/Fp8npWgABAAAB1TANBgkqhkiG9w0B +# AQsFADB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE +# BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYD +# VQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDAeFw0yMzA1MjUxOTEy +# MzBaFw0yNDAyMDExOTEyMzBaMIHLMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz +# aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv +# cnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25z +# MScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046N0YwMC0wNUUwLUQ5NDcxJTAjBgNV +# BAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggIiMA0GCSqGSIb3DQEB +# AQUAA4ICDwAwggIKAoICAQDFfak57Oph9vuxtloABiLc6enT+yKH619b+OhGdkyh +# gNzkX80KUGI/jEqOVMV4Sqt/UPFFidx2t7v2SETj2tAzuVKtDfq2HBpu80vZ0vyQ +# DydVt4MDL4tJSKqgYofCxDIBrWzJJjgBolKdOJx1ut2TyOc+UOm7e92tVPHpjdg+ +# Omf31TLUf/oouyAOJ/Inn2ih3ASP0QYm+AFQjhYDNDu8uzMdwHF5QdwsscNa9PVS +# GedLdDLo9jL6DoPF4NYo06lvvEQuSJ9ImwZfBGLy/8hpE7RD4ewvJKmM1+t6eQuE +# sTXjrGM2WjkW18SgUZ8n+VpL2uk6AhDkCa355I531p0Jkqpoon7dHuLUdZSQO40q +# mVIQ6qQCanvImTqmNgE/rPJ0rgr0hMPI/uR1T/iaL0mEq4bqak+3sa8I+FAYOI/P +# C7V+zEek+sdyWtaX+ndbGlv/RJb5mQaGn8NunbkfvHD1Qt5D0rmtMOekYMq7QjYq +# E3FEP/wAY4TDuJxstjsa2HXi2yUDEg4MJL6/JvsQXToOZ+IxR6KT5t5fB5FpZYBp +# VLMma3pm5z6VXvkXrYs33NXJqVWLwiswa7NUFV87Es2sou9Idw3yAZmHIYWgOQ+D +# IY1nY3aG5DODiwN1rJyEb+mbWDagrdVxcncr6UKKO49eoNTXEW+scUf6GwXG0KEy +# mQIDAQABo4IBSTCCAUUwHQYDVR0OBBYEFK/QXKNO35bBMOz3R5giX7Ala2OaMB8G +# A1UdIwQYMBaAFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMF8GA1UdHwRYMFYwVKBSoFCG +# Tmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUy +# MFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNybDBsBggrBgEFBQcBAQRgMF4w +# XAYIKwYBBQUHMAKGUGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2Vy +# dHMvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3J0MAwG +# A1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwDgYDVR0PAQH/BAQD +# AgeAMA0GCSqGSIb3DQEBCwUAA4ICAQBmRddqvQuyjRpx0HGxvOqffFrbgFAg0j82 +# v0v7R+/8a70S2V4t7yKYKSsQGI6pvt1A8JGmuZyjmIXmw23AkI5bZkxvSgws8rrB +# tJw9vakEckcWFQb7JG6b618x0s9Q3DL0dRq46QZRnm7U6234lecvjstAow30dP0T +# nIacPWKpPc3QgB+WDnglN2fdT1ruQ6WIVBenmpjpG9ypRANKUx5NRcpdJAQW2FqE +# HTS3Ntb+0tCqIkNHJ5aFsF6ehRovWZp0MYIz9bpJHix0VrjdLVMOpe7wv62t90E3 +# UrE2KmVwpQ5wsMD6YUscoCsSRQZrA5AbwTOCZJpeG2z3vDo/huvPK8TeTJ2Ltu/I +# tXgxIlIOQp/tbHAiN8Xptw/JmIZg9edQ/FiDaIIwG5YHsfm2u7TwOFyd6OqLw18Z +# 5j/IvDPzlkwWJxk6RHJF5dS4s3fnyLw3DHBe5Dav6KYB4n8x/cEmD/R44/8gS5Pf +# uG1srjLdyyGtyh0KiRDSmjw+fa7i1VPoemidDWNZ7ksNadMad4ZoDvgkqOV4A6a+ +# N8HIc/P6g0irrezLWUgbKXSN8iH9RP+WJFx5fBHE4AFxrbAUQ2Zn5jDmHAI3wYcQ +# DnnEYP51A75WFwPsvBrfrb1+6a1fuTEH1AYdOOMy8fX8xKo0E0Ys+7bxIvFPsUpS +# zfFjBolmhzCCB3EwggVZoAMCAQICEzMAAAAVxedrngKbSZkAAAAAABUwDQYJKoZI +# hvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw +# DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x +# MjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAy +# MDEwMB4XDTIxMDkzMDE4MjIyNVoXDTMwMDkzMDE4MzIyNVowfDELMAkGA1UEBhMC +# VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV +# BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp +# bWUtU3RhbXAgUENBIDIwMTAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +# AQDk4aZM57RyIQt5osvXJHm9DtWC0/3unAcH0qlsTnXIyjVX9gF/bErg4r25Phdg +# M/9cT8dm95VTcVrifkpa/rg2Z4VGIwy1jRPPdzLAEBjoYH1qUoNEt6aORmsHFPPF +# dvWGUNzBRMhxXFExN6AKOG6N7dcP2CZTfDlhAnrEqv1yaa8dq6z2Nr41JmTamDu6 +# GnszrYBbfowQHJ1S/rboYiXcag/PXfT+jlPP1uyFVk3v3byNpOORj7I5LFGc6XBp +# Dco2LXCOMcg1KL3jtIckw+DJj361VI/c+gVVmG1oO5pGve2krnopN6zL64NF50Zu +# yjLVwIYwXE8s4mKyzbnijYjklqwBSru+cakXW2dg3viSkR4dPf0gz3N9QZpGdc3E +# XzTdEonW/aUgfX782Z5F37ZyL9t9X4C626p+Nuw2TPYrbqgSUei/BQOj0XOmTTd0 +# lBw0gg/wEPK3Rxjtp+iZfD9M269ewvPV2HM9Q07BMzlMjgK8QmguEOqEUUbi0b1q +# GFphAXPKZ6Je1yh2AuIzGHLXpyDwwvoSCtdjbwzJNmSLW6CmgyFdXzB0kZSU2LlQ +# +QuJYfM2BjUYhEfb3BvR/bLUHMVr9lxSUV0S2yW6r1AFemzFER1y7435UsSFF5PA +# PBXbGjfHCBUYP3irRbb1Hode2o+eFnJpxq57t7c+auIurQIDAQABo4IB3TCCAdkw +# EgYJKwYBBAGCNxUBBAUCAwEAATAjBgkrBgEEAYI3FQIEFgQUKqdS/mTEmr6CkTxG +# NSnPEP8vBO4wHQYDVR0OBBYEFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMFwGA1UdIARV +# MFMwUQYMKwYBBAGCN0yDfQEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWlj +# cm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0bTATBgNVHSUEDDAK +# BggrBgEFBQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMC +# AYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvX +# zpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20v +# cGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYI +# KwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5j +# b20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDANBgkqhkiG +# 9w0BAQsFAAOCAgEAnVV9/Cqt4SwfZwExJFvhnnJL/Klv6lwUtj5OR2R4sQaTlz0x +# M7U518JxNj/aZGx80HU5bbsPMeTCj/ts0aGUGCLu6WZnOlNN3Zi6th542DYunKmC +# VgADsAW+iehp4LoJ7nvfam++Kctu2D9IdQHZGN5tggz1bSNU5HhTdSRXud2f8449 +# xvNo32X2pFaq95W2KFUn0CS9QKC/GbYSEhFdPSfgQJY4rPf5KYnDvBewVIVCs/wM +# nosZiefwC2qBwoEZQhlSdYo2wh3DYXMuLGt7bj8sCXgU6ZGyqVvfSaN0DLzskYDS +# PeZKPmY7T7uG+jIa2Zb0j/aRAfbOxnT99kxybxCrdTDFNLB62FD+CljdQDzHVG2d +# Y3RILLFORy3BFARxv2T5JL5zbcqOCb2zAVdJVGTZc9d/HltEAY5aGZFrDZ+kKNxn +# GSgkujhLmm77IVRrakURR6nxt67I6IleT53S0Ex2tVdUCbFpAUR+fKFhbHP+Crvs +# QWY9af3LwUFJfn6Tvsv4O+S3Fb+0zj6lMVGEvL8CwYKiexcdFYmNcP7ntdAoGokL +# jzbaukz5m/8K6TT4JDVnK+ANuOaMmdbhIurwJ0I9JZTmdHRbatGePu1+oDEzfbzL +# 6Xu/OHBE0ZDxyKs6ijoIYn/ZcGNTTY3ugm2lBRDBcQZqELQdVTNYs6FwZvKhggNQ +# MIICOAIBATCB+aGB0aSBzjCByzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp +# bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw +# b3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEn +# MCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjdGMDAtMDVFMC1EOTQ3MSUwIwYDVQQD +# ExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloiMKAQEwBwYFKw4DAhoDFQBO +# Ei+S/ZVFe6w1Id31m6Kge26lNKCBgzCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYD +# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy +# b3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1w +# IFBDQSAyMDEwMA0GCSqGSIb3DQEBCwUAAgUA6JpN3jAiGA8yMDIzMDgzMDIzMjMx +# MFoYDzIwMjMwODMxMjMyMzEwWjB3MD0GCisGAQQBhFkKBAExLzAtMAoCBQDomk3e +# AgEAMAoCAQACAiLLAgH/MAcCAQACAhLTMAoCBQDom59eAgEAMDYGCisGAQQBhFkK +# BAIxKDAmMAwGCisGAQQBhFkKAwKgCjAIAgEAAgMHoSChCjAIAgEAAgMBhqAwDQYJ +# KoZIhvcNAQELBQADggEBAC/zAZ9IEqD3nHBUWwxFTfnDSRErnCJ6XGxH5jOVtR0t +# 9pi7yCpApLpA2D12g1lcv4ugnwGpsbwmFjrcF4WlHemRa77qv409xNhNKrnh3H+U +# X2hvy9Utp9LiJiqS7lOW5VN1Uv+LbnA+FWt//4J+YLv44D/dliUGjYX623X7KiEX +# dbdXPR/Sn+W2YVQ19O8liKaFDnDnIAz+WLCfL6EaoGu4Te/Mr65Khy3YWTwQfXxr +# gR/JMDzLzWossnGszYCN8S8d9X6mfzWuYv4JHLEiThW++WbMLeT2hhKPomcbvqU4 +# wPb/ylDrTrWuAr/fVndECXVjCIzYJiFwOWn/ZfN9FpQxggQNMIIECQIBATCBkzB8 +# MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVk +# bW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1N +# aWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAAdWpAs/Fp8npWgABAAAB +# 1TANBglghkgBZQMEAgEFAKCCAUowGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEE +# MC8GCSqGSIb3DQEJBDEiBCAHS+EjBkJ/YPugQQv1D7eXVQOI4DWPIYpUxpssheDN +# lTCB+gYLKoZIhvcNAQkQAi8xgeowgecwgeQwgb0EINm/I4YM166JMM7EKIcYvlcb +# r2CHjKC0LUOmpZIbBsH/MIGYMIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgT +# Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m +# dCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENB +# IDIwMTACEzMAAAHVqQLPxafJ6VoAAQAAAdUwIgQgBVj4mNvMkXn0xEeEe3i6urr/ +# L5Eh2p4uPk3zOcR/jHIwDQYJKoZIhvcNAQELBQAEggIAiKbnM5VQAwi5gWDevpEJ +# oHiZRrb0HApEUkca54Oye2+5tyRfWo3ruZvLZueHWsbEzYXclOscHVPjyR1t6s+p +# W13utx4mDab1BaJCBq1q9IH1HDfCf/kSMb0H02UDNBumrt1s5/oaiiY75S3kigpt +# XHCKV/AKbi+4vORYdBwJhWvy4kug+zZHWAp7+K4rVeAaMbWOitriFPQaSdZlOkNT +# VKMbYUtX6VEnhyfr5O390TxPJCdkDznT6rAf5FlQEkim7wb2gb/Osi73KF0dtnRd +# 0ePNT4GxulYTrAhHsZmyuinh/FIyqJDtW3C+2eVt/lx6GJfAtDA/gVCe9mAL4bYv +# 7vjocHeLvWJ8bc0PYMCRZXMsU2zkJqVJ7pZWq+z5hGQAHemrQj9hUZBXCEFVZ8dd +# jEZbIsg2nwZOFakhvdAvvGlTXPbRMOCHblToXAKA8ksRbLob8CDL6Cstoy5VL3al +# fOAWLj3FYITlvGvAYCtJzHrHdqyphL805Co1syR6YDopR8tDrxgWzJKAby5fIolP +# 7SfunXsCa0n3xx80aaxR0apljIXZWBSMGZdJmVzASQFxlexNsU1PmaLmmpn0fih/ +# 567e+kyzFG1wiw5btwttSW9hKgCX+yze1B4IK4yquTQSfPikrCpbBaFZ0OlWmOnL +# r0eKAKY3WDyxYgNyeg6KeCc= +# SIG # End signature block diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Nall.NEST.MigtarionAnalyzer.Test.csproj b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Nall.NEST.MigtarionAnalyzer.Test.csproj new file mode 100644 index 0000000..c368247 --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Nall.NEST.MigtarionAnalyzer.Test.csproj @@ -0,0 +1,30 @@ + + + + net8.0 + + true + true + + + + + + + + + + + + + + + + + + + + + + + diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer.Test/UseElasticsearchNetInsteadOfNestTests.cs b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/UseElasticsearchNetInsteadOfNestTests.cs new file mode 100644 index 0000000..7988135 --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/UseElasticsearchNetInsteadOfNestTests.cs @@ -0,0 +1,186 @@ +using System.Threading.Tasks; +using Analyzer.Test; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Testing; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.CodeAnalysis.Testing.Verifiers; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Nest; + +namespace Nall.NEST.MigtarionAnalyzer.Test; + +[TestClass] +public class UseElasticsearchNetInsteadOfNestTests +{ + [TestMethod] + public async Task TestNestUsage() + { + var test = + @" + using Nest; + public class ElasticsearchService + { + private readonly {|#0:IElasticClient|} _client; + + public ElasticsearchService({|#1:IElasticClient|} client) + { + _client = client; + } + }"; + + var expected1 = VerifyCS + .Diagnostic("ELS001") + .WithLocation(0) + .WithArguments("IElasticClient"); + + var expected2 = VerifyCS + .Diagnostic("ELS001") + .WithLocation(1) + .WithArguments("IElasticClient"); + + await VerifyCS.VerifyAnalyzerAsync(test, expected1, expected2); + } + + //Diagnostic and CodeFix both triggered and checked for + [TestMethod] + public async Task TestCodeFix() + { + var test = """ + using Nest; + + public class ElasticsearchService + { + private readonly {|#0:IElasticClient|} _client; + } + """; + + var fixtest = """ + using Elastic.Clients.Elasticsearch; + + public class ElasticsearchService + { + private readonly ElasticsearchClient _client; + } + """; + + var expected = VerifyCS + .Diagnostic("ELS001") + .WithLocation(0) + .WithArguments("IElasticClient"); + + await VerifyCS.VerifyCodeFixAsync(test, [expected], fixtest); + } + + [TestMethod] + public async Task TestCodeFixPreservesWhitespace() + { + var test = """ + using Nest; + + public class ElasticsearchService + { + private readonly {|#0:IElasticClient|} _client; + + public ElasticsearchService( {|#1:IElasticClient|} client) + { + _client = client; + } + } + """; + + var fixtest = """ + using Elastic.Clients.Elasticsearch; + + public class ElasticsearchService + { + private readonly ElasticsearchClient _client; + + public ElasticsearchService( ElasticsearchClient client) + { + _client = client; + } + } + """; + + var expected1 = VerifyCS + .Diagnostic("ELS001") + .WithLocation(0) + .WithArguments("IElasticClient"); + + var expected2 = VerifyCS + .Diagnostic("ELS001") + .WithLocation(1) + .WithArguments("IElasticClient"); + + await VerifyCS.VerifyCodeFixAsync(test, [expected1, expected2], fixtest); + } +} + +public static class VerifyCS +{ + private static readonly MetadataReference s_nestReference = MetadataReference.CreateFromFile( + typeof(IElasticClient).Assembly.Location + ); + private static readonly MetadataReference s_elasticReference = MetadataReference.CreateFromFile( + typeof(Elastic.Clients.Elasticsearch.ElasticsearchClient).Assembly.Location + ); + + public static DiagnosticResult Diagnostic(string diagnosticId) => + CSharpAnalyzerVerifier.Diagnostic( + diagnosticId + ); + + public static Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] expected) + { + var test = new Test { TestCode = source }; + test.TestState.AdditionalReferences.Add(s_nestReference); + test.TestState.AdditionalReferences.Add(s_elasticReference); + test.ExpectedDiagnostics.AddRange(expected); + return test.RunAsync(); + } + + public static Task VerifyCodeFixAsync( + string source, + DiagnosticResult[] expected, + string fixedSource + ) + { + var test = new Test { TestCode = source, FixedCode = fixedSource }; + test.TestState.AdditionalReferences.Add(s_nestReference); + test.TestState.AdditionalReferences.Add(s_elasticReference); + test.ExpectedDiagnostics.AddRange(expected); + // we need this becaues of + // error CS1705: Assembly 'Elastic.Clients.Elasticsearch' with identity 'Elastic.Clients.Elasticsearch, Version=8.0.0.0, Culture=neutral, PublicKeyToken=96c599bbe3e70f5d' uses 'System.Runtime, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' which has a higher version than referenced assembly 'System.Runtime' with identity 'System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' + test.CompilerDiagnostics = CompilerDiagnostics.None; + return test.RunAsync(); + } + + private class Test + : CSharpCodeFixTest< + UseElasticsearchNetInsteadOfNest, + UseElasticsearchNetInsteadOfNestCodeFixProvider, + MSTestVerifier + > + { + public Test() + { + SolutionTransforms.Add( + (solution, projectId) => + { + var compilationOptions = solution.GetProject(projectId).CompilationOptions; + compilationOptions = compilationOptions.WithSpecificDiagnosticOptions( + compilationOptions.SpecificDiagnosticOptions.SetItems( + CSharpVerifierHelper.NullableWarnings + ) + ); + solution = solution.WithProjectCompilationOptions( + projectId, + compilationOptions + ); + + return solution; + } + ); + } + } +} diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpAnalyzerVerifier`1+Test.cs b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpAnalyzerVerifier`1+Test.cs new file mode 100644 index 0000000..e580ba6 --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpAnalyzerVerifier`1+Test.cs @@ -0,0 +1,33 @@ +using Microsoft.CodeAnalysis.CSharp.Testing; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing.Verifiers; + +namespace Analyzer.Test; + +public static partial class CSharpAnalyzerVerifier + where TAnalyzer : DiagnosticAnalyzer, new() +{ + public class Test : CSharpAnalyzerTest + { + public Test() + { + SolutionTransforms.Add( + (solution, projectId) => + { + var compilationOptions = solution.GetProject(projectId).CompilationOptions; + compilationOptions = compilationOptions.WithSpecificDiagnosticOptions( + compilationOptions.SpecificDiagnosticOptions.SetItems( + CSharpVerifierHelper.NullableWarnings + ) + ); + solution = solution.WithProjectCompilationOptions( + projectId, + compilationOptions + ); + + return solution; + } + ); + } + } +} diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpAnalyzerVerifier`1.cs b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpAnalyzerVerifier`1.cs new file mode 100644 index 0000000..c452445 --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpAnalyzerVerifier`1.cs @@ -0,0 +1,34 @@ +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Testing; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.CodeAnalysis.Testing.Verifiers; + +namespace Analyzer.Test; + +public static partial class CSharpAnalyzerVerifier + where TAnalyzer : DiagnosticAnalyzer, new() +{ + /// + public static DiagnosticResult Diagnostic() => + CSharpAnalyzerVerifier.Diagnostic(); + + /// + public static DiagnosticResult Diagnostic(string diagnosticId) => + CSharpAnalyzerVerifier.Diagnostic(diagnosticId); + + /// + public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor) => + CSharpAnalyzerVerifier.Diagnostic(descriptor); + + /// + public static async Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] expected) + { + var test = new Test { TestCode = source, }; + + test.ExpectedDiagnostics.AddRange(expected); + await test.RunAsync(CancellationToken.None); + } +} diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpCodeFixVerifier`2+Test.cs b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpCodeFixVerifier`2+Test.cs new file mode 100644 index 0000000..34cc980 --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpCodeFixVerifier`2+Test.cs @@ -0,0 +1,35 @@ +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.Testing; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing.Verifiers; + +namespace Analyzer.Test; + +public static partial class CSharpCodeFixVerifier + where TAnalyzer : DiagnosticAnalyzer, new() + where TCodeFix : CodeFixProvider, new() +{ + public class Test : CSharpCodeFixTest + { + public Test() + { + SolutionTransforms.Add( + (solution, projectId) => + { + var compilationOptions = solution.GetProject(projectId).CompilationOptions; + compilationOptions = compilationOptions.WithSpecificDiagnosticOptions( + compilationOptions.SpecificDiagnosticOptions.SetItems( + CSharpVerifierHelper.NullableWarnings + ) + ); + solution = solution.WithProjectCompilationOptions( + projectId, + compilationOptions + ); + + return solution; + } + ); + } + } +} diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpCodeFixVerifier`2.cs b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpCodeFixVerifier`2.cs new file mode 100644 index 0000000..5eb8de9 --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpCodeFixVerifier`2.cs @@ -0,0 +1,60 @@ +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.Testing; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.CodeAnalysis.Testing.Verifiers; + +namespace Analyzer.Test; + +public static partial class CSharpCodeFixVerifier + where TAnalyzer : DiagnosticAnalyzer, new() + where TCodeFix : CodeFixProvider, new() +{ + /// + public static DiagnosticResult Diagnostic() => + CSharpCodeFixVerifier.Diagnostic(); + + /// + public static DiagnosticResult Diagnostic(string diagnosticId) => + CSharpCodeFixVerifier.Diagnostic(diagnosticId); + + /// + public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor) => + CSharpCodeFixVerifier.Diagnostic(descriptor); + + /// + public static async Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] expected) + { + var test = new Test { TestCode = source, }; + + test.ExpectedDiagnostics.AddRange(expected); + await test.RunAsync(CancellationToken.None); + } + + /// + public static async Task VerifyCodeFixAsync(string source, string fixedSource) => + await VerifyCodeFixAsync(source, DiagnosticResult.EmptyDiagnosticResults, fixedSource); + + /// + public static async Task VerifyCodeFixAsync( + string source, + DiagnosticResult expected, + string fixedSource + ) => await VerifyCodeFixAsync(source, new[] { expected }, fixedSource); + + /// + public static async Task VerifyCodeFixAsync( + string source, + DiagnosticResult[] expected, + string fixedSource + ) + { + var test = new Test { TestCode = source, FixedCode = fixedSource, }; + + test.ExpectedDiagnostics.AddRange(expected); + await test.RunAsync(CancellationToken.None); + } +} diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpCodeRefactoringVerifier`1+Test.cs b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpCodeRefactoringVerifier`1+Test.cs new file mode 100644 index 0000000..7df39e2 --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpCodeRefactoringVerifier`1+Test.cs @@ -0,0 +1,33 @@ +using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.CSharp.Testing; +using Microsoft.CodeAnalysis.Testing.Verifiers; + +namespace Analyzer.Test; + +public static partial class CSharpCodeRefactoringVerifier + where TCodeRefactoring : CodeRefactoringProvider, new() +{ + public class Test : CSharpCodeRefactoringTest + { + public Test() + { + SolutionTransforms.Add( + (solution, projectId) => + { + var compilationOptions = solution.GetProject(projectId).CompilationOptions; + compilationOptions = compilationOptions.WithSpecificDiagnosticOptions( + compilationOptions.SpecificDiagnosticOptions.SetItems( + CSharpVerifierHelper.NullableWarnings + ) + ); + solution = solution.WithProjectCompilationOptions( + projectId, + compilationOptions + ); + + return solution; + } + ); + } + } +} diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpCodeRefactoringVerifier`1.cs b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpCodeRefactoringVerifier`1.cs new file mode 100644 index 0000000..4ebaf55 --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpCodeRefactoringVerifier`1.cs @@ -0,0 +1,39 @@ +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.Testing; + +namespace Analyzer.Test; + +public static partial class CSharpCodeRefactoringVerifier + where TCodeRefactoring : CodeRefactoringProvider, new() +{ + /// + public static async Task VerifyRefactoringAsync(string source, string fixedSource) + { + await VerifyRefactoringAsync(source, DiagnosticResult.EmptyDiagnosticResults, fixedSource); + } + + /// + public static async Task VerifyRefactoringAsync( + string source, + DiagnosticResult expected, + string fixedSource + ) + { + await VerifyRefactoringAsync(source, new[] { expected }, fixedSource); + } + + /// + public static async Task VerifyRefactoringAsync( + string source, + DiagnosticResult[] expected, + string fixedSource + ) + { + var test = new Test { TestCode = source, FixedCode = fixedSource, }; + + test.ExpectedDiagnostics.AddRange(expected); + await test.RunAsync(CancellationToken.None); + } +} diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpVerifierHelper.cs b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpVerifierHelper.cs new file mode 100644 index 0000000..ca2918c --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/CSharpVerifierHelper.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; + +namespace Analyzer.Test; + +internal static class CSharpVerifierHelper +{ + /// + /// By default, the compiler reports diagnostics for nullable reference types at + /// , and the analyzer test framework defaults to only validating + /// diagnostics at . This map contains all compiler diagnostic IDs + /// related to nullability mapped to , which is then used to enable all + /// of these warnings for default validation during analyzer and code fix tests. + /// + internal static ImmutableDictionary NullableWarnings { get; } = + GetNullableWarningsFromCompiler(); + + private static ImmutableDictionary GetNullableWarningsFromCompiler() + { + string[] args = { "/warnaserror:nullable" }; + var commandLineArguments = CSharpCommandLineParser.Default.Parse( + args, + baseDirectory: Environment.CurrentDirectory, + sdkDirectory: Environment.CurrentDirectory + ); + var nullableWarnings = commandLineArguments.CompilationOptions.SpecificDiagnosticOptions; + + // Workaround for https://github.com/dotnet/roslyn/issues/41610 + nullableWarnings = nullableWarnings + .SetItem("CS8632", ReportDiagnostic.Error) + .SetItem("CS8669", ReportDiagnostic.Error); + + return nullableWarnings; + } +} diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/VisualBasicAnalyzerVerifier`1+Test.cs b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/VisualBasicAnalyzerVerifier`1+Test.cs new file mode 100644 index 0000000..99678c5 --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/VisualBasicAnalyzerVerifier`1+Test.cs @@ -0,0 +1,14 @@ +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing.Verifiers; +using Microsoft.CodeAnalysis.VisualBasic.Testing; + +namespace Analyzer.Test; + +public static partial class VisualBasicAnalyzerVerifier + where TAnalyzer : DiagnosticAnalyzer, new() +{ + public class Test : VisualBasicAnalyzerTest + { + public Test() { } + } +} diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/VisualBasicAnalyzerVerifier`1.cs b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/VisualBasicAnalyzerVerifier`1.cs new file mode 100644 index 0000000..61bfa79 --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/VisualBasicAnalyzerVerifier`1.cs @@ -0,0 +1,34 @@ +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.CodeAnalysis.Testing.Verifiers; +using Microsoft.CodeAnalysis.VisualBasic.Testing; + +namespace Analyzer.Test; + +public static partial class VisualBasicAnalyzerVerifier + where TAnalyzer : DiagnosticAnalyzer, new() +{ + /// + public static DiagnosticResult Diagnostic() => + VisualBasicAnalyzerVerifier.Diagnostic(); + + /// + public static DiagnosticResult Diagnostic(string diagnosticId) => + VisualBasicAnalyzerVerifier.Diagnostic(diagnosticId); + + /// + public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor) => + VisualBasicAnalyzerVerifier.Diagnostic(descriptor); + + /// + public static async Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] expected) + { + var test = new Test { TestCode = source, }; + + test.ExpectedDiagnostics.AddRange(expected); + await test.RunAsync(CancellationToken.None); + } +} diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/VisualBasicCodeFixVerifier`2+Test.cs b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/VisualBasicCodeFixVerifier`2+Test.cs new file mode 100644 index 0000000..c39b2b3 --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/VisualBasicCodeFixVerifier`2+Test.cs @@ -0,0 +1,13 @@ +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing.Verifiers; +using Microsoft.CodeAnalysis.VisualBasic.Testing; + +namespace Analyzer.Test; + +public static partial class VisualBasicCodeFixVerifier + where TAnalyzer : DiagnosticAnalyzer, new() + where TCodeFix : CodeFixProvider, new() +{ + public class Test : VisualBasicCodeFixTest { } +} diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/VisualBasicCodeFixVerifier`2.cs b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/VisualBasicCodeFixVerifier`2.cs new file mode 100644 index 0000000..371deb8 --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/VisualBasicCodeFixVerifier`2.cs @@ -0,0 +1,60 @@ +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.CodeAnalysis.Testing.Verifiers; +using Microsoft.CodeAnalysis.VisualBasic.Testing; + +namespace Analyzer.Test; + +public static partial class VisualBasicCodeFixVerifier + where TAnalyzer : DiagnosticAnalyzer, new() + where TCodeFix : CodeFixProvider, new() +{ + /// + public static DiagnosticResult Diagnostic() => + VisualBasicCodeFixVerifier.Diagnostic(); + + /// + public static DiagnosticResult Diagnostic(string diagnosticId) => + VisualBasicCodeFixVerifier.Diagnostic(diagnosticId); + + /// + public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor) => + VisualBasicCodeFixVerifier.Diagnostic(descriptor); + + /// + public static async Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] expected) + { + var test = new Test { TestCode = source, }; + + test.ExpectedDiagnostics.AddRange(expected); + await test.RunAsync(CancellationToken.None); + } + + /// + public static async Task VerifyCodeFixAsync(string source, string fixedSource) => + await VerifyCodeFixAsync(source, DiagnosticResult.EmptyDiagnosticResults, fixedSource); + + /// + public static async Task VerifyCodeFixAsync( + string source, + DiagnosticResult expected, + string fixedSource + ) => await VerifyCodeFixAsync(source, new[] { expected }, fixedSource); + + /// + public static async Task VerifyCodeFixAsync( + string source, + DiagnosticResult[] expected, + string fixedSource + ) + { + var test = new Test { TestCode = source, FixedCode = fixedSource, }; + + test.ExpectedDiagnostics.AddRange(expected); + await test.RunAsync(CancellationToken.None); + } +} diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/VisualBasicCodeRefactoringVerifier`1+Test.cs b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/VisualBasicCodeRefactoringVerifier`1+Test.cs new file mode 100644 index 0000000..36515f0 --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/VisualBasicCodeRefactoringVerifier`1+Test.cs @@ -0,0 +1,11 @@ +using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.Testing.Verifiers; +using Microsoft.CodeAnalysis.VisualBasic.Testing; + +namespace Analyzer.Test; + +public static partial class VisualBasicCodeRefactoringVerifier + where TCodeRefactoring : CodeRefactoringProvider, new() +{ + public class Test : VisualBasicCodeRefactoringTest { } +} diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/VisualBasicCodeRefactoringVerifier`1.cs b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/VisualBasicCodeRefactoringVerifier`1.cs new file mode 100644 index 0000000..dcc5ade --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer.Test/Verifiers/VisualBasicCodeRefactoringVerifier`1.cs @@ -0,0 +1,39 @@ +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.Testing; + +namespace Analyzer.Test; + +public static partial class VisualBasicCodeRefactoringVerifier + where TCodeRefactoring : CodeRefactoringProvider, new() +{ + /// + public static async Task VerifyRefactoringAsync(string source, string fixedSource) + { + await VerifyRefactoringAsync(source, DiagnosticResult.EmptyDiagnosticResults, fixedSource); + } + + /// + public static async Task VerifyRefactoringAsync( + string source, + DiagnosticResult expected, + string fixedSource + ) + { + await VerifyRefactoringAsync(source, new[] { expected }, fixedSource); + } + + /// + public static async Task VerifyRefactoringAsync( + string source, + DiagnosticResult[] expected, + string fixedSource + ) + { + var test = new Test { TestCode = source, FixedCode = fixedSource, }; + + test.ExpectedDiagnostics.AddRange(expected); + await test.RunAsync(CancellationToken.None); + } +} diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer.Vsix/Nall.NEST.MigtarionAnalyzer.Vsix.csproj b/analyzer/Nall.NEST.MigtarionAnalyzer.Vsix/Nall.NEST.MigtarionAnalyzer.Vsix.csproj new file mode 100644 index 0000000..1bf3288 --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer.Vsix/Nall.NEST.MigtarionAnalyzer.Vsix.csproj @@ -0,0 +1,48 @@ + + + + + + net472 + Nall.NEST.MigtarionAnalyzer.Vsix + Nall.NEST.MigtarionAnalyzer.Vsix + + + + false + false + false + false + false + false + Roslyn + + + + + + + + Program + $(DevEnvDir)devenv.exe + /rootsuffix $(VSSDKTargetPlatformRegRootSuffix) + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer.Vsix/source.extension.vsixmanifest b/analyzer/Nall.NEST.MigtarionAnalyzer.Vsix/source.extension.vsixmanifest new file mode 100644 index 0000000..427d9ff --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer.Vsix/source.extension.vsixmanifest @@ -0,0 +1,24 @@ + + + + + Nall.NEST.MigtarionAnalyzer + This package helps with migration from Nest to Elastic.Clients.Elasticsearch. + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer/Nall.NEST.MigtarionAnalyzer.csproj b/analyzer/Nall.NEST.MigtarionAnalyzer/Nall.NEST.MigtarionAnalyzer.csproj new file mode 100644 index 0000000..6382486 --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer/Nall.NEST.MigtarionAnalyzer.csproj @@ -0,0 +1,21 @@ + + + + netstandard2.0 + false + + + *$(MSBuildProjectFile)* + + + + + + + + + + + + + diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer/Resources.Designer.cs b/analyzer/Nall.NEST.MigtarionAnalyzer/Resources.Designer.cs new file mode 100644 index 0000000..eca05f9 --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Analayzer { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Analayzer.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer/Resources.resx b/analyzer/Nall.NEST.MigtarionAnalyzer/Resources.resx new file mode 100644 index 0000000..c7e0d4b --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer/Resources.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/analyzer/Nall.NEST.MigtarionAnalyzer/UseElasticsearchNetInsteadOfNest.cs b/analyzer/Nall.NEST.MigtarionAnalyzer/UseElasticsearchNetInsteadOfNest.cs new file mode 100644 index 0000000..350b0c7 --- /dev/null +++ b/analyzer/Nall.NEST.MigtarionAnalyzer/UseElasticsearchNetInsteadOfNest.cs @@ -0,0 +1,70 @@ +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Nall.NEST.MigtarionAnalyzer +{ + [DiagnosticAnalyzer(LanguageNames.CSharp)] + public class UseElasticsearchNetInsteadOfNest : DiagnosticAnalyzer + { + public const string DiagnosticId = "ELS001"; + + private static readonly LocalizableString s_title = "Use ElasticsearchClient"; + private static readonly LocalizableString s_messageFormat = + "Use ElasticsearchClient instead of IElasticClient"; + private static readonly LocalizableString s_description = + "NEST is deprecated. Use the official Elasticsearch.Net client instead."; + private const string Category = "Usage"; + + private static readonly DiagnosticDescriptor s_rule = new DiagnosticDescriptor( + DiagnosticId, + s_title, + s_messageFormat, + Category, + DiagnosticSeverity.Warning, + isEnabledByDefault: true, + description: s_description + ); + + public override ImmutableArray SupportedDiagnostics + { + get { return ImmutableArray.Create(s_rule); } + } + + public override void Initialize(AnalysisContext context) + { + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + context.EnableConcurrentExecution(); + + // See https://github.com/dotnet/roslyn/blob/main/docs/analyzers/Analyzer%20Actions%20Semantics.md for more information + context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.IdentifierName); + } + + private static void AnalyzeNode(SyntaxNodeAnalysisContext context) + { + var identifierNode = (IdentifierNameSyntax)context.Node; + + if (identifierNode.Identifier.Text != "IElasticClient") + { + return; + } + + //var symbolInfo = context.SemanticModel.GetSymbolInfo(identifierNode); + //if (symbolInfo.Symbol == null) + //{ + // return; + //} + // + //var containingNamespace = symbolInfo.Symbol.ContainingNamespace; + //if (containingNamespace == null || containingNamespace.ToString() != "Nest") + //{ + // return; + //} + + var diagnostic = Diagnostic.Create(s_rule, identifierNode.GetLocation()); + context.ReportDiagnostic(diagnostic); + } + } +} diff --git a/analyzer/Playground/Playground.csproj b/analyzer/Playground/Playground.csproj new file mode 100644 index 0000000..c563425 --- /dev/null +++ b/analyzer/Playground/Playground.csproj @@ -0,0 +1,15 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + diff --git a/analyzer/Playground/Program.cs b/analyzer/Playground/Program.cs new file mode 100644 index 0000000..5c5d417 --- /dev/null +++ b/analyzer/Playground/Program.cs @@ -0,0 +1,15 @@ +using System.Text.Json; +using Elastic.Transport; +using Nest; + +var settings = new ConnectionSettings(new Uri("https://elastic:elastic@127.0.0.1:9200/")) + .DisableDirectStreaming() + .ServerCertificateValidationCallback(CertificateValidations.AllowAll); + +var client = new ElasticClient(settings); + +var nodeInfo = await client.Nodes.InfoAsync(); + +Console.WriteLine( + JsonSerializer.Serialize(nodeInfo, new JsonSerializerOptions { WriteIndented = true }) +); diff --git a/analyzer/README.md b/analyzer/README.md new file mode 100644 index 0000000..1499b5f --- /dev/null +++ b/analyzer/README.md @@ -0,0 +1,9 @@ +# Nall.NEST.MigtarionAnalyzer + +This package helps with migration from Nest to Elastic.Clients.Elasticsearch + +```bash +dotnet format analyzers ./path/to/folder \ + --verify-no-changes \ + --diagnostics ELS001 \ + --severity info \ No newline at end of file diff --git a/analyzer/analyzer.sln b/analyzer/analyzer.sln new file mode 100644 index 0000000..a0d0605 --- /dev/null +++ b/analyzer/analyzer.sln @@ -0,0 +1,52 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nall.NEST.MigtarionAnalyzer", "Nall.NEST.MigtarionAnalyzer\Nall.NEST.MigtarionAnalyzer.csproj", "{5B3F3DB1-20B9-4834-83CC-17334839193B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nall.NEST.MigtarionAnalyzer.CodeFixes", "Nall.NEST.MigtarionAnalyzer.CodeFixes\Nall.NEST.MigtarionAnalyzer.CodeFixes.csproj", "{480B9220-B0B2-4517-9980-F2C1B19B099C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nall.NEST.MigtarionAnalyzer.Package", "Nall.NEST.MigtarionAnalyzer.Package\Nall.NEST.MigtarionAnalyzer.Package.csproj", "{2F963F87-9C92-4C23-8802-B5584B565E0C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nall.NEST.MigtarionAnalyzer.Test", "Nall.NEST.MigtarionAnalyzer.Test\Nall.NEST.MigtarionAnalyzer.Test.csproj", "{C4F70E21-C467-49CA-93A9-4FE0DEFC6F21}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nall.NEST.MigtarionAnalyzer.Vsix", "Nall.NEST.MigtarionAnalyzer.Vsix\Nall.NEST.MigtarionAnalyzer.Vsix.csproj", "{60AA48E2-2F4D-4CD9-9CCC-F4B9332B3865}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Playground", "Playground\Playground.csproj", "{CAF7F28D-995E-4FB8-BAE9-13C082C3BAEB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5B3F3DB1-20B9-4834-83CC-17334839193B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5B3F3DB1-20B9-4834-83CC-17334839193B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5B3F3DB1-20B9-4834-83CC-17334839193B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5B3F3DB1-20B9-4834-83CC-17334839193B}.Release|Any CPU.Build.0 = Release|Any CPU + {480B9220-B0B2-4517-9980-F2C1B19B099C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {480B9220-B0B2-4517-9980-F2C1B19B099C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {480B9220-B0B2-4517-9980-F2C1B19B099C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {480B9220-B0B2-4517-9980-F2C1B19B099C}.Release|Any CPU.Build.0 = Release|Any CPU + {2F963F87-9C92-4C23-8802-B5584B565E0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2F963F87-9C92-4C23-8802-B5584B565E0C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2F963F87-9C92-4C23-8802-B5584B565E0C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2F963F87-9C92-4C23-8802-B5584B565E0C}.Release|Any CPU.Build.0 = Release|Any CPU + {C4F70E21-C467-49CA-93A9-4FE0DEFC6F21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C4F70E21-C467-49CA-93A9-4FE0DEFC6F21}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C4F70E21-C467-49CA-93A9-4FE0DEFC6F21}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C4F70E21-C467-49CA-93A9-4FE0DEFC6F21}.Release|Any CPU.Build.0 = Release|Any CPU + {60AA48E2-2F4D-4CD9-9CCC-F4B9332B3865}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {60AA48E2-2F4D-4CD9-9CCC-F4B9332B3865}.Debug|Any CPU.Build.0 = Debug|Any CPU + {60AA48E2-2F4D-4CD9-9CCC-F4B9332B3865}.Release|Any CPU.ActiveCfg = Release|Any CPU + {60AA48E2-2F4D-4CD9-9CCC-F4B9332B3865}.Release|Any CPU.Build.0 = Release|Any CPU + {CAF7F28D-995E-4FB8-BAE9-13C082C3BAEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CAF7F28D-995E-4FB8-BAE9-13C082C3BAEB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CAF7F28D-995E-4FB8-BAE9-13C082C3BAEB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CAF7F28D-995E-4FB8-BAE9-13C082C3BAEB}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/analyzer/global.json b/analyzer/global.json new file mode 100644 index 0000000..61d1ed0 --- /dev/null +++ b/analyzer/global.json @@ -0,0 +1,7 @@ +{ + "sdk": { + "version": "8.0.401", + "rollForward": "latestMajor", + "allowPrerelease": false + } +}