├── .gitignore ├── EnumeratorCallAnalyzer ├── EnumeratorCallAnalyzer.Test │ ├── TestFile.cs │ ├── Verifiers │ │ ├── VisualBasicCodeRefactoringVerifier`1+Test.cs │ │ ├── VisualBasicAnalyzerVerifier`1+Test.cs │ │ ├── VisualBasicCodeFixVerifier`2+Test.cs │ │ ├── CSharpAnalyzerVerifier`1+Test.cs │ │ ├── CSharpCodeRefactoringVerifier`1+Test.cs │ │ ├── CSharpCodeFixVerifier`2+Test.cs │ │ ├── CSharpCodeRefactoringVerifier`1.cs │ │ ├── VisualBasicCodeRefactoringVerifier`1.cs │ │ ├── CSharpVerifierHelper.cs │ │ ├── CSharpAnalyzerVerifier`1.cs │ │ ├── VisualBasicAnalyzerVerifier`1.cs │ │ ├── CSharpCodeFixVerifier`2.cs │ │ └── VisualBasicCodeFixVerifier`2.cs │ ├── EnumeratorCallAnalyzer.Test.csproj │ └── EnumeratorCallAnalyzerUnitTests.cs ├── EnumeratorCallAnalyzer │ ├── EnumeratorCallAnalyzer.csproj │ ├── EnumeratorCallAnalyzerAnalyzer.cs │ ├── Resources.Designer.cs │ └── Resources.resx ├── EnumeratorCallAnalyzer.CodeFixes │ ├── EnumeratorCallAnalyzer.CodeFixes.csproj │ ├── CodeFixResources.Designer.cs │ ├── EnumeratorCallAnalyzerCodeFixProvider.cs │ └── CodeFixResources.resx ├── EnumeratorCallAnalyzer.Vsix │ ├── source.extension.vsixmanifest │ └── EnumeratorCallAnalyzer.Vsix.csproj └── EnumeratorCallAnalyzer.Package │ ├── EnumeratorCallAnalyzer.Package.csproj │ └── tools │ ├── install.ps1 │ └── uninstall.ps1 ├── checker.gif ├── NuGet.config ├── README.md └── EnumeratorCallAnalyzer.sln /.gitignore: -------------------------------------------------------------------------------- 1 | *.user 2 | bin 3 | obj 4 | .vs 5 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.Test/TestFile.cs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /checker.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wappenull/EnumeratorCallAnalyzer/master/checker.gif -------------------------------------------------------------------------------- /NuGet.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.Test/Verifiers/VisualBasicCodeRefactoringVerifier`1+Test.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis.CodeRefactorings; 2 | using Microsoft.CodeAnalysis.Testing.Verifiers; 3 | using Microsoft.CodeAnalysis.VisualBasic.Testing; 4 | 5 | namespace EnumeratorCallAnalyzer.Test 6 | { 7 | public static partial class VisualBasicCodeRefactoringVerifier 8 | where TCodeRefactoring : CodeRefactoringProvider, new() 9 | { 10 | public class Test : VisualBasicCodeRefactoringTest 11 | { 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.Test/Verifiers/VisualBasicAnalyzerVerifier`1+Test.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis.Diagnostics; 2 | using Microsoft.CodeAnalysis.Testing.Verifiers; 3 | using Microsoft.CodeAnalysis.VisualBasic.Testing; 4 | 5 | namespace EnumeratorCallAnalyzer.Test 6 | { 7 | public static partial class VisualBasicAnalyzerVerifier 8 | where TAnalyzer : DiagnosticAnalyzer, new() 9 | { 10 | public class Test : VisualBasicAnalyzerTest 11 | { 12 | public Test( ) 13 | { 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.Test/Verifiers/VisualBasicCodeFixVerifier`2+Test.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis.CodeFixes; 2 | using Microsoft.CodeAnalysis.Diagnostics; 3 | using Microsoft.CodeAnalysis.Testing.Verifiers; 4 | using Microsoft.CodeAnalysis.VisualBasic.Testing; 5 | 6 | namespace EnumeratorCallAnalyzer.Test 7 | { 8 | public static partial class VisualBasicCodeFixVerifier 9 | where TAnalyzer : DiagnosticAnalyzer, new() 10 | where TCodeFix : CodeFixProvider, new() 11 | { 12 | public class Test : VisualBasicCodeFixTest 13 | { 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | false 6 | 7 | 8 | *$(MSBuildProjectFullPath)* 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.CodeFixes/EnumeratorCallAnalyzer.CodeFixes.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | false 6 | EnumeratorCallAnalyzer 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.Test/Verifiers/CSharpAnalyzerVerifier`1+Test.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis.CSharp.Testing; 2 | using Microsoft.CodeAnalysis.Diagnostics; 3 | using Microsoft.CodeAnalysis.Testing.Verifiers; 4 | 5 | namespace EnumeratorCallAnalyzer.Test 6 | { 7 | public static partial class CSharpAnalyzerVerifier 8 | where TAnalyzer : DiagnosticAnalyzer, new() 9 | { 10 | public class Test : CSharpAnalyzerTest 11 | { 12 | public Test( ) 13 | { 14 | SolutionTransforms.Add( ( solution, projectId ) => 15 | { 16 | var compilationOptions = solution.GetProject(projectId).CompilationOptions; 17 | compilationOptions = compilationOptions.WithSpecificDiagnosticOptions( 18 | compilationOptions.SpecificDiagnosticOptions.SetItems( CSharpVerifierHelper.NullableWarnings ) ); 19 | solution = solution.WithProjectCompilationOptions( projectId, compilationOptions ); 20 | 21 | return solution; 22 | } ); 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.Test/Verifiers/CSharpCodeRefactoringVerifier`1+Test.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis.CodeRefactorings; 2 | using Microsoft.CodeAnalysis.CSharp.Testing; 3 | using Microsoft.CodeAnalysis.Testing.Verifiers; 4 | 5 | namespace EnumeratorCallAnalyzer.Test 6 | { 7 | public static partial class CSharpCodeRefactoringVerifier 8 | where TCodeRefactoring : CodeRefactoringProvider, new() 9 | { 10 | public class Test : CSharpCodeRefactoringTest 11 | { 12 | public Test( ) 13 | { 14 | SolutionTransforms.Add( ( solution, projectId ) => 15 | { 16 | var compilationOptions = solution.GetProject(projectId).CompilationOptions; 17 | compilationOptions = compilationOptions.WithSpecificDiagnosticOptions( 18 | compilationOptions.SpecificDiagnosticOptions.SetItems( CSharpVerifierHelper.NullableWarnings ) ); 19 | solution = solution.WithProjectCompilationOptions( projectId, compilationOptions ); 20 | 21 | return solution; 22 | } ); 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.Test/Verifiers/CSharpCodeFixVerifier`2+Test.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis.CodeFixes; 2 | using Microsoft.CodeAnalysis.CSharp.Testing; 3 | using Microsoft.CodeAnalysis.Diagnostics; 4 | using Microsoft.CodeAnalysis.Testing.Verifiers; 5 | 6 | namespace EnumeratorCallAnalyzer.Test 7 | { 8 | public static partial class CSharpCodeFixVerifier 9 | where TAnalyzer : DiagnosticAnalyzer, new() 10 | where TCodeFix : CodeFixProvider, new() 11 | { 12 | public class Test : CSharpCodeFixTest 13 | { 14 | public Test( ) 15 | { 16 | SolutionTransforms.Add( ( solution, projectId ) => 17 | { 18 | var compilationOptions = solution.GetProject(projectId).CompilationOptions; 19 | compilationOptions = compilationOptions.WithSpecificDiagnosticOptions( 20 | compilationOptions.SpecificDiagnosticOptions.SetItems( CSharpVerifierHelper.NullableWarnings ) ); 21 | solution = solution.WithProjectCompilationOptions( projectId, compilationOptions ); 22 | 23 | return solution; 24 | } ); 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EnumeratorCallAnalyzer 2 | A Roslyn analyzer that catch wrong Unity coroutine call. 3 | 4 | It will catch a coroutine call without yield return similar to: 5 | 6 | Coroutine( ); 7 | 8 | Suppose `Coroutine` is a function defined with: 9 | 10 | IEnumerator Coroutine( ) { ... } 11 | 12 | And will attempt to change to 13 | 14 | yield return Coroutine( ); 15 | 16 | ![Alt text](./checker.gif) 17 | 18 | - Solution file is created with VS2019 19 | - The solution will output VSIX for install with Visual Studio. 20 | - Roslyn SDK required to compile, see guide below. 21 | - It could serve as starting point for making more convenient analyzer to suit developer's need. 22 | 23 | It was created with the help of 24 | - [Roslyn Analyzers and how to use them with Unity][3] (This article also show more practical examples on how to use analyzer to enforce coding style) 25 | - [Writing a Roslyn analyzer][4] 26 | - [How to write a Roslyn Analyzer][5] 27 | 28 | Repo was created by inspration from discussion of https://stackoverflow.com/questions/67820221 (Thanks everyone!) 29 | 30 | (I always got dupe hammer in SO whenever I started a new question, this time it was not too bad, I guess) 31 | 32 | [3]: https://arztsamuel.github.io/en/blogs/2019/Roslyn-Analyzers-and-Unity.html 33 | [4]: https://www.meziantou.net/writing-a-roslyn-analyzer.htm 34 | [5]: https://devblogs.microsoft.com/dotnet/how-to-write-a-roslyn-analyzer/ 35 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.Test/EnumeratorCallAnalyzer.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.0 5 | 6 | true 7 | true 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.Test/Verifiers/CSharpCodeRefactoringVerifier`1.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis.CodeRefactorings; 2 | using Microsoft.CodeAnalysis.Testing; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | 6 | namespace EnumeratorCallAnalyzer.Test 7 | { 8 | public static partial class CSharpCodeRefactoringVerifier 9 | where TCodeRefactoring : CodeRefactoringProvider, new() 10 | { 11 | /// 12 | public static async Task VerifyRefactoringAsync( string source, string fixedSource ) 13 | { 14 | await VerifyRefactoringAsync( source, DiagnosticResult.EmptyDiagnosticResults, fixedSource ); 15 | } 16 | 17 | /// 18 | public static async Task VerifyRefactoringAsync( string source, DiagnosticResult expected, string fixedSource ) 19 | { 20 | await VerifyRefactoringAsync( source, new[] { expected }, fixedSource ); 21 | } 22 | 23 | /// 24 | public static async Task VerifyRefactoringAsync( string source, DiagnosticResult[] expected, string fixedSource ) 25 | { 26 | var test = new Test 27 | { 28 | TestCode = source, 29 | FixedCode = fixedSource, 30 | }; 31 | 32 | test.ExpectedDiagnostics.AddRange( expected ); 33 | await test.RunAsync( CancellationToken.None ); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.Test/Verifiers/VisualBasicCodeRefactoringVerifier`1.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis.CodeRefactorings; 2 | using Microsoft.CodeAnalysis.Testing; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | 6 | namespace EnumeratorCallAnalyzer.Test 7 | { 8 | public static partial class VisualBasicCodeRefactoringVerifier 9 | where TCodeRefactoring : CodeRefactoringProvider, new() 10 | { 11 | /// 12 | public static async Task VerifyRefactoringAsync( string source, string fixedSource ) 13 | { 14 | await VerifyRefactoringAsync( source, DiagnosticResult.EmptyDiagnosticResults, fixedSource ); 15 | } 16 | 17 | /// 18 | public static async Task VerifyRefactoringAsync( string source, DiagnosticResult expected, string fixedSource ) 19 | { 20 | await VerifyRefactoringAsync( source, new[] { expected }, fixedSource ); 21 | } 22 | 23 | /// 24 | public static async Task VerifyRefactoringAsync( string source, DiagnosticResult[] expected, string fixedSource ) 25 | { 26 | var test = new Test 27 | { 28 | TestCode = source, 29 | FixedCode = fixedSource, 30 | }; 31 | 32 | test.ExpectedDiagnostics.AddRange( expected ); 33 | await test.RunAsync( CancellationToken.None ); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.Test/Verifiers/CSharpVerifierHelper.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CSharp; 3 | using System; 4 | using System.Collections.Immutable; 5 | 6 | namespace EnumeratorCallAnalyzer.Test 7 | { 8 | internal static class CSharpVerifierHelper 9 | { 10 | /// 11 | /// By default, the compiler reports diagnostics for nullable reference types at 12 | /// , and the analyzer test framework defaults to only validating 13 | /// diagnostics at . This map contains all compiler diagnostic IDs 14 | /// related to nullability mapped to , which is then used to enable all 15 | /// of these warnings for default validation during analyzer and code fix tests. 16 | /// 17 | internal static ImmutableDictionary NullableWarnings { get; } = GetNullableWarningsFromCompiler( ); 18 | 19 | private static ImmutableDictionary GetNullableWarningsFromCompiler( ) 20 | { 21 | string[] args = { "/warnaserror:nullable" }; 22 | var commandLineArguments = CSharpCommandLineParser.Default.Parse(args, baseDirectory: Environment.CurrentDirectory, sdkDirectory: Environment.CurrentDirectory); 23 | var nullableWarnings = commandLineArguments.CompilationOptions.SpecificDiagnosticOptions; 24 | 25 | // Workaround for https://github.com/dotnet/roslyn/issues/41610 26 | nullableWarnings = nullableWarnings 27 | .SetItem( "CS8632", ReportDiagnostic.Error ) 28 | .SetItem( "CS8669", ReportDiagnostic.Error ); 29 | 30 | return nullableWarnings; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.Test/Verifiers/CSharpAnalyzerVerifier`1.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CSharp.Testing; 3 | using Microsoft.CodeAnalysis.Diagnostics; 4 | using Microsoft.CodeAnalysis.Testing; 5 | using Microsoft.CodeAnalysis.Testing.Verifiers; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace EnumeratorCallAnalyzer.Test 10 | { 11 | public static partial class CSharpAnalyzerVerifier 12 | where TAnalyzer : DiagnosticAnalyzer, new() 13 | { 14 | /// 15 | public static DiagnosticResult Diagnostic( ) 16 | => CSharpAnalyzerVerifier.Diagnostic( ); 17 | 18 | /// 19 | public static DiagnosticResult Diagnostic( string diagnosticId ) 20 | => CSharpAnalyzerVerifier.Diagnostic( diagnosticId ); 21 | 22 | /// 23 | public static DiagnosticResult Diagnostic( DiagnosticDescriptor descriptor ) 24 | => CSharpAnalyzerVerifier.Diagnostic( descriptor ); 25 | 26 | /// 27 | public static async Task VerifyAnalyzerAsync( string source, params DiagnosticResult[] expected ) 28 | { 29 | var test = new Test 30 | { 31 | TestCode = source, 32 | }; 33 | 34 | test.ExpectedDiagnostics.AddRange( expected ); 35 | await test.RunAsync( CancellationToken.None ); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.Test/Verifiers/VisualBasicAnalyzerVerifier`1.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.Diagnostics; 3 | using Microsoft.CodeAnalysis.Testing; 4 | using Microsoft.CodeAnalysis.Testing.Verifiers; 5 | using Microsoft.CodeAnalysis.VisualBasic.Testing; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace EnumeratorCallAnalyzer.Test 10 | { 11 | public static partial class VisualBasicAnalyzerVerifier 12 | where TAnalyzer : DiagnosticAnalyzer, new() 13 | { 14 | /// 15 | public static DiagnosticResult Diagnostic( ) 16 | => VisualBasicAnalyzerVerifier.Diagnostic( ); 17 | 18 | /// 19 | public static DiagnosticResult Diagnostic( string diagnosticId ) 20 | => VisualBasicAnalyzerVerifier.Diagnostic( diagnosticId ); 21 | 22 | /// 23 | public static DiagnosticResult Diagnostic( DiagnosticDescriptor descriptor ) 24 | => VisualBasicAnalyzerVerifier.Diagnostic( descriptor ); 25 | 26 | /// 27 | public static async Task VerifyAnalyzerAsync( string source, params DiagnosticResult[] expected ) 28 | { 29 | var test = new Test 30 | { 31 | TestCode = source, 32 | }; 33 | 34 | test.ExpectedDiagnostics.AddRange( expected ); 35 | await test.RunAsync( CancellationToken.None ); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.Vsix/source.extension.vsixmanifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | EnumeratorCallAnalyzer 6 | This is a sample diagnostic extension for the .NET Compiler Platform ("Roslyn"). 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.Vsix/EnumeratorCallAnalyzer.Vsix.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | net472 7 | EnumeratorCallAnalyzer.Vsix 8 | EnumeratorCallAnalyzer.Vsix 9 | 10 | 11 | 12 | false 13 | false 14 | false 15 | false 16 | false 17 | false 18 | Roslyn 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | Program 27 | $(DevEnvDir)devenv.exe 28 | /rootsuffix $(VSSDKTargetPlatformRegRootSuffix) 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.Package/EnumeratorCallAnalyzer.Package.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | false 6 | true 7 | true 8 | 9 | 10 | 11 | EnumeratorCallAnalyzer 12 | 1.0.0.0 13 | Wappen 14 | http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE 15 | http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE 16 | http://ICON_URL_HERE_OR_DELETE_THIS_LINE 17 | http://REPOSITORY_URL_HERE_OR_DELETE_THIS_LINE 18 | false 19 | EnumeratorCallAnalyzer 20 | Summary of changes made in this release of the package. 21 | Copyright 22 | EnumeratorCallAnalyzer, analyzers 23 | true 24 | 25 | $(TargetsForTfmSpecificContentInPackage);_AddAnalyzersToOutput 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.Test/EnumeratorCallAnalyzerUnitTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis.Testing; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using System.Threading.Tasks; 4 | using VerifyCS = EnumeratorCallAnalyzer.Test.CSharpCodeFixVerifier< 5 | EnumeratorCallAnalyzer.EnumeratorCallAnalyzerAnalyzer, 6 | EnumeratorCallAnalyzer.EnumeratorCallAnalyzerCodeFixProvider>; 7 | 8 | namespace EnumeratorCallAnalyzer.Test 9 | { 10 | [TestClass] 11 | public class EnumeratorCallAnalyzerUnitTest 12 | { 13 | const string BadCase = @" 14 | using System; 15 | using System.Collections; 16 | public class Test 17 | { 18 | IEnumerator CallingSite() 19 | { 20 | // Comment before 21 | [|Coroutine();|] // Comment after 22 | yield return null; 23 | } 24 | 25 | IEnumerator Coroutine() 26 | { 27 | yield return null; 28 | } 29 | }"; 30 | 31 | //No diagnostics expected to show up 32 | [TestMethod] 33 | public async Task BareCase_Diagnostic( ) 34 | { 35 | await VerifyCS.VerifyAnalyzerAsync( BadCase ); 36 | } 37 | 38 | [TestMethod] 39 | public async Task GoodCase_NoDiagnostic( ) 40 | { 41 | var test = @" 42 | using System; 43 | using System.Collections; 44 | public class Test 45 | { 46 | IEnumerator CallingSite() 47 | { 48 | // Good calls 49 | yield return Coroutine(); 50 | var generator = Coroutine(); 51 | } 52 | 53 | IEnumerator Coroutine() 54 | { 55 | yield return null; 56 | } 57 | }"; 58 | await VerifyCS.VerifyAnalyzerAsync( test ); 59 | } 60 | 61 | //Diagnostic and CodeFix both triggered and checked for 62 | [TestMethod] 63 | public async Task CodeFixText( ) 64 | { 65 | var expectedFix = @" 66 | using System; 67 | using System.Collections; 68 | public class Test 69 | { 70 | IEnumerator CallingSite() 71 | { 72 | // Comment before 73 | yield return Coroutine(); // Comment after 74 | yield return null; 75 | } 76 | 77 | IEnumerator Coroutine() 78 | { 79 | yield return null; 80 | } 81 | }"; 82 | 83 | await VerifyCS.VerifyCodeFixAsync( BadCase, expectedFix ); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.Test/Verifiers/CSharpCodeFixVerifier`2.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CodeFixes; 3 | using Microsoft.CodeAnalysis.CSharp.Testing; 4 | using Microsoft.CodeAnalysis.Diagnostics; 5 | using Microsoft.CodeAnalysis.Testing; 6 | using Microsoft.CodeAnalysis.Testing.Verifiers; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | 10 | namespace EnumeratorCallAnalyzer.Test 11 | { 12 | public static partial class CSharpCodeFixVerifier 13 | where TAnalyzer : DiagnosticAnalyzer, new() 14 | where TCodeFix : CodeFixProvider, new() 15 | { 16 | /// 17 | public static DiagnosticResult Diagnostic( ) 18 | => CSharpCodeFixVerifier.Diagnostic( ); 19 | 20 | /// 21 | public static DiagnosticResult Diagnostic( string diagnosticId ) 22 | => CSharpCodeFixVerifier.Diagnostic( diagnosticId ); 23 | 24 | /// 25 | public static DiagnosticResult Diagnostic( DiagnosticDescriptor descriptor ) 26 | => CSharpCodeFixVerifier.Diagnostic( descriptor ); 27 | 28 | /// 29 | public static async Task VerifyAnalyzerAsync( string source, params DiagnosticResult[] expected ) 30 | { 31 | var test = new Test 32 | { 33 | TestCode = source, 34 | }; 35 | 36 | test.ExpectedDiagnostics.AddRange( expected ); 37 | await test.RunAsync( CancellationToken.None ); 38 | } 39 | 40 | /// 41 | public static async Task VerifyCodeFixAsync( string source, string fixedSource ) 42 | => await VerifyCodeFixAsync( source, DiagnosticResult.EmptyDiagnosticResults, fixedSource ); 43 | 44 | /// 45 | public static async Task VerifyCodeFixAsync( string source, DiagnosticResult expected, string fixedSource ) 46 | => await VerifyCodeFixAsync( source, new[] { expected }, fixedSource ); 47 | 48 | /// 49 | public static async Task VerifyCodeFixAsync( string source, DiagnosticResult[] expected, string fixedSource ) 50 | { 51 | var test = new Test 52 | { 53 | TestCode = source, 54 | FixedCode = fixedSource, 55 | }; 56 | 57 | test.ExpectedDiagnostics.AddRange( expected ); 58 | await test.RunAsync( CancellationToken.None ); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.Test/Verifiers/VisualBasicCodeFixVerifier`2.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CodeFixes; 3 | using Microsoft.CodeAnalysis.Diagnostics; 4 | using Microsoft.CodeAnalysis.Testing; 5 | using Microsoft.CodeAnalysis.Testing.Verifiers; 6 | using Microsoft.CodeAnalysis.VisualBasic.Testing; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | 10 | namespace EnumeratorCallAnalyzer.Test 11 | { 12 | public static partial class VisualBasicCodeFixVerifier 13 | where TAnalyzer : DiagnosticAnalyzer, new() 14 | where TCodeFix : CodeFixProvider, new() 15 | { 16 | /// 17 | public static DiagnosticResult Diagnostic( ) 18 | => VisualBasicCodeFixVerifier.Diagnostic( ); 19 | 20 | /// 21 | public static DiagnosticResult Diagnostic( string diagnosticId ) 22 | => VisualBasicCodeFixVerifier.Diagnostic( diagnosticId ); 23 | 24 | /// 25 | public static DiagnosticResult Diagnostic( DiagnosticDescriptor descriptor ) 26 | => VisualBasicCodeFixVerifier.Diagnostic( descriptor ); 27 | 28 | /// 29 | public static async Task VerifyAnalyzerAsync( string source, params DiagnosticResult[] expected ) 30 | { 31 | var test = new Test 32 | { 33 | TestCode = source, 34 | }; 35 | 36 | test.ExpectedDiagnostics.AddRange( expected ); 37 | await test.RunAsync( CancellationToken.None ); 38 | } 39 | 40 | /// 41 | public static async Task VerifyCodeFixAsync( string source, string fixedSource ) 42 | => await VerifyCodeFixAsync( source, DiagnosticResult.EmptyDiagnosticResults, fixedSource ); 43 | 44 | /// 45 | public static async Task VerifyCodeFixAsync( string source, DiagnosticResult expected, string fixedSource ) 46 | => await VerifyCodeFixAsync( source, new[] { expected }, fixedSource ); 47 | 48 | /// 49 | public static async Task VerifyCodeFixAsync( string source, DiagnosticResult[] expected, string fixedSource ) 50 | { 51 | var test = new Test 52 | { 53 | TestCode = source, 54 | FixedCode = fixedSource, 55 | }; 56 | 57 | test.ExpectedDiagnostics.AddRange( expected ); 58 | await test.RunAsync( CancellationToken.None ); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.CodeFixes/CodeFixResources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace EnumeratorCallAnalyzer { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class CodeFixResources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal CodeFixResources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("EnumeratorCallAnalyzer.CodeFixResources", typeof(CodeFixResources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized string similar to Insert yield return. 65 | /// 66 | internal static string CodeFixTitle { 67 | get { 68 | return ResourceManager.GetString("CodeFixTitle", resourceCulture); 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31205.134 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnumeratorCallAnalyzer", "EnumeratorCallAnalyzer\EnumeratorCallAnalyzer\EnumeratorCallAnalyzer.csproj", "{F54196DF-CCAC-4FE2-9027-6C5F5B18F8DE}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnumeratorCallAnalyzer.CodeFixes", "EnumeratorCallAnalyzer\EnumeratorCallAnalyzer.CodeFixes\EnumeratorCallAnalyzer.CodeFixes.csproj", "{915E9239-B3D1-4930-99EC-AC7200D00C91}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnumeratorCallAnalyzer.Package", "EnumeratorCallAnalyzer\EnumeratorCallAnalyzer.Package\EnumeratorCallAnalyzer.Package.csproj", "{74D94A8D-3551-4E10-9B0B-590D86B410A6}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnumeratorCallAnalyzer.Test", "EnumeratorCallAnalyzer\EnumeratorCallAnalyzer.Test\EnumeratorCallAnalyzer.Test.csproj", "{EE083175-37C3-4746-8C6A-69FC0D29314A}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnumeratorCallAnalyzer.Vsix", "EnumeratorCallAnalyzer\EnumeratorCallAnalyzer.Vsix\EnumeratorCallAnalyzer.Vsix.csproj", "{7AC5FA1A-82DB-485B-8A14-5BA56192E138}" 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Any CPU = Debug|Any CPU 19 | Release|Any CPU = Release|Any CPU 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {F54196DF-CCAC-4FE2-9027-6C5F5B18F8DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {F54196DF-CCAC-4FE2-9027-6C5F5B18F8DE}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {F54196DF-CCAC-4FE2-9027-6C5F5B18F8DE}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {F54196DF-CCAC-4FE2-9027-6C5F5B18F8DE}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {915E9239-B3D1-4930-99EC-AC7200D00C91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {915E9239-B3D1-4930-99EC-AC7200D00C91}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {915E9239-B3D1-4930-99EC-AC7200D00C91}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {915E9239-B3D1-4930-99EC-AC7200D00C91}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {74D94A8D-3551-4E10-9B0B-590D86B410A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {74D94A8D-3551-4E10-9B0B-590D86B410A6}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {74D94A8D-3551-4E10-9B0B-590D86B410A6}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {74D94A8D-3551-4E10-9B0B-590D86B410A6}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {EE083175-37C3-4746-8C6A-69FC0D29314A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {EE083175-37C3-4746-8C6A-69FC0D29314A}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {EE083175-37C3-4746-8C6A-69FC0D29314A}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {EE083175-37C3-4746-8C6A-69FC0D29314A}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {7AC5FA1A-82DB-485B-8A14-5BA56192E138}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {7AC5FA1A-82DB-485B-8A14-5BA56192E138}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {7AC5FA1A-82DB-485B-8A14-5BA56192E138}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {7AC5FA1A-82DB-485B-8A14-5BA56192E138}.Release|Any CPU.Build.0 = Release|Any CPU 42 | EndGlobalSection 43 | GlobalSection(SolutionProperties) = preSolution 44 | HideSolutionNode = FALSE 45 | EndGlobalSection 46 | GlobalSection(ExtensibilityGlobals) = postSolution 47 | SolutionGuid = {BA451AF2-0A31-46FE-A699-3941663BF6EA} 48 | EndGlobalSection 49 | EndGlobal 50 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer/EnumeratorCallAnalyzerAnalyzer.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CSharp; 3 | using Microsoft.CodeAnalysis.CSharp.Syntax; 4 | using Microsoft.CodeAnalysis.Diagnostics; 5 | using System; 6 | using System.Collections; 7 | using System.Collections.Generic; 8 | using System.Collections.Immutable; 9 | using System.Linq; 10 | using System.Threading; 11 | 12 | namespace EnumeratorCallAnalyzer 13 | { 14 | [DiagnosticAnalyzer( LanguageNames.CSharp )] 15 | public class EnumeratorCallAnalyzerAnalyzer : DiagnosticAnalyzer 16 | { 17 | public const string DiagnosticId = "EnumeratorCallAnalyzer"; 18 | 19 | private static readonly LocalizableString Title = new LocalizableResourceString(nameof(Resources.AnalyzerTitle), Resources.ResourceManager, typeof(Resources)); 20 | private static readonly LocalizableString MessageFormat = new LocalizableResourceString(nameof(Resources.AnalyzerMessageFormat), Resources.ResourceManager, typeof(Resources)); 21 | private static readonly LocalizableString Description = new LocalizableResourceString(nameof(Resources.AnalyzerDescription), Resources.ResourceManager, typeof(Resources)); 22 | private const string Category = "Usage"; 23 | 24 | private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Warning, isEnabledByDefault: true, description: Description); 25 | 26 | public override ImmutableArray SupportedDiagnostics { get { return ImmutableArray.Create( Rule ); } } 27 | 28 | public override void Initialize( AnalysisContext context ) 29 | { 30 | context.EnableConcurrentExecution( ); 31 | context.ConfigureGeneratedCodeAnalysis( GeneratedCodeAnalysisFlags.Analyze|GeneratedCodeAnalysisFlags.ReportDiagnostics ); 32 | 33 | // The AnalyzeNode method will be called for each InvocationExpression of the Syntax tree 34 | context.RegisterSyntaxNodeAction( _CheckCoroutineCall, SyntaxKind.InvocationExpression ); 35 | } 36 | 37 | private void _CheckCoroutineCall( SyntaxNodeAnalysisContext context ) 38 | { 39 | var fcall = (InvocationExpressionSyntax)context.Node; 40 | 41 | // Filter only bare function call 42 | // like: Coroutine( ); 43 | // not: yield return Coroutine( ); 44 | // not: var generator = Coroutine( ); 45 | var parent = fcall.Parent; 46 | 47 | // The bare call will only have 48 | // - ExpressionStatementSyntax 49 | // - InvocationExpressionSyntax 50 | // - SemicolonToken 51 | bool isBareCall = (parent is ExpressionStatementSyntax) && parent.ChildNodes( ).Count( ) == 1; 52 | if( !isBareCall ) 53 | return; // Skip, it is not bare 54 | 55 | // Check if function has returning type of something based off IEnumerator 56 | var invokedMethod = context.SemanticModel.GetSymbolInfo( fcall ).Symbol as IMethodSymbol; // Since this is in InvocationExpressionSyntax, it is pretty sure a IMethodSymbol 57 | if( invokedMethod == null ) 58 | return; 59 | 60 | // Lucky that IEnumerator can be checked with SpecialType.System_Collections_IEnumerator. No crazy type crawling here. 61 | if( invokedMethod.ReturnType.SpecialType == SpecialType.System_Collections_IEnumerator ) 62 | { 63 | var diagnostic = Diagnostic.Create(Rule, fcall.Parent.GetLocation(), invokedMethod.Name ); // messageArg will fill the '{0}' part in analyzer format 64 | context.ReportDiagnostic( diagnostic ); 65 | } 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.CodeFixes/EnumeratorCallAnalyzerCodeFixProvider.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CodeActions; 3 | using Microsoft.CodeAnalysis.CodeFixes; 4 | using Microsoft.CodeAnalysis.CSharp; 5 | using Microsoft.CodeAnalysis.CSharp.Syntax; 6 | using Microsoft.CodeAnalysis.Formatting; 7 | using Microsoft.CodeAnalysis.Rename; 8 | using Microsoft.CodeAnalysis.Text; 9 | using System; 10 | using System.Collections.Generic; 11 | using System.Collections.Immutable; 12 | using System.Composition; 13 | using System.Linq; 14 | using System.Threading; 15 | using System.Threading.Tasks; 16 | 17 | namespace EnumeratorCallAnalyzer 18 | { 19 | [ExportCodeFixProvider( LanguageNames.CSharp, Name = nameof( EnumeratorCallAnalyzerCodeFixProvider ) ), Shared] 20 | public class EnumeratorCallAnalyzerCodeFixProvider : CodeFixProvider 21 | { 22 | public sealed override ImmutableArray FixableDiagnosticIds 23 | { 24 | get { return ImmutableArray.Create( EnumeratorCallAnalyzerAnalyzer.DiagnosticId ); } 25 | } 26 | 27 | public sealed override FixAllProvider GetFixAllProvider( ) 28 | { 29 | // See https://github.com/dotnet/roslyn/blob/master/docs/analyzers/FixAllProvider.md for more information on Fix All Providers 30 | return WellKnownFixAllProviders.BatchFixer; 31 | } 32 | 33 | public sealed override async Task RegisterCodeFixesAsync( CodeFixContext context ) 34 | { 35 | var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); 36 | 37 | var diagnostic = context.Diagnostics.First(); 38 | var diagnosticSpan = diagnostic.Location.SourceSpan; 39 | 40 | // Find the type declaration identified by the diagnostic. 41 | var declaration = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType().First(); 42 | 43 | // Register a code action that will invoke the fix. 44 | context.RegisterCodeFix( 45 | CodeAction.Create( 46 | title: CodeFixResources.CodeFixTitle, 47 | createChangedDocument: c => PrependYieldReturnAsync( context.Document, root, declaration, c ), 48 | equivalenceKey: nameof( CodeFixResources.CodeFixTitle ) ), 49 | diagnostic ); 50 | } 51 | 52 | private Task PrependYieldReturnAsync( Document document, SyntaxNode root, InvocationExpressionSyntax invocationExpr, CancellationToken cancellationToken ) 53 | { 54 | // document in this context is what code span reported from analyzer 55 | // It would be 'StatementSyntax' level on top of InvocationExpressionSyntax 56 | 57 | // From: 58 | // Coroutine( ); 59 | // - ExpressionStatementSyntax <- replacingPart 60 | // - InvocationExpressionSyntax <- invocationExpr 61 | // - SemicolonToken 62 | 63 | // We want: 64 | // yield return Coroutine( ); 65 | // - YieldReturnStatementSyntax 66 | // - InvocationExpressionSyntax <- invocationExpr 67 | // - SemicolonToken 68 | 69 | var replacingPart = invocationExpr.Parent; 70 | 71 | YieldStatementSyntax yieldRoot = SyntaxFactory.YieldStatement( SyntaxKind.YieldReturnStatement, invocationExpr.WithoutTrivia( ) ) 72 | .WithLeadingTrivia( invocationExpr.GetLeadingTrivia( ) ) // These are required to retain leading/trailing comments 73 | .WithTrailingTrivia( replacingPart.GetTrailingTrivia( ) ); 74 | 75 | yieldRoot = yieldRoot.WithAdditionalAnnotations( Formatter.Annotation ); 76 | var newRoot = root.ReplaceNode( replacingPart, yieldRoot ); // Finally substitution 77 | return Task.FromResult( document.WithSyntaxRoot( newRoot ) ); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace EnumeratorCallAnalyzer { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("EnumeratorCallAnalyzer.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized string similar to Enumerator function call should use with yield return. 65 | /// 66 | internal static string AnalyzerDescription { 67 | get { 68 | return ResourceManager.GetString("AnalyzerDescription", resourceCulture); 69 | } 70 | } 71 | 72 | /// 73 | /// Looks up a localized string similar to Enumerator function '{0}' should use with yield return. 74 | /// 75 | internal static string AnalyzerMessageFormat { 76 | get { 77 | return ResourceManager.GetString("AnalyzerMessageFormat", resourceCulture); 78 | } 79 | } 80 | 81 | /// 82 | /// Looks up a localized string similar to Enumerator function call check. 83 | /// 84 | internal static string AnalyzerTitle { 85 | get { 86 | return ResourceManager.GetString("AnalyzerTitle", resourceCulture); 87 | } 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.CodeFixes/CodeFixResources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | Insert yield return 122 | The title of the code fix. 123 | 124 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | Enumerator function call should use with yield return 122 | An optional longer localizable description of the diagnostic. 123 | 124 | 125 | Enumerator function '{0}' should use with yield return 126 | The format-able message the diagnostic displays. 127 | 128 | 129 | Enumerator function call check 130 | The title of the diagnostic. 131 | 132 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.Package/tools/install.ps1: -------------------------------------------------------------------------------- 1 | param($installPath, $toolsPath, $package, $project) 2 | 3 | if($project.Object.SupportsPackageDependencyResolution) 4 | { 5 | if($project.Object.SupportsPackageDependencyResolution()) 6 | { 7 | # Do not install analyzers via install.ps1, instead let the project system handle it. 8 | return 9 | } 10 | } 11 | 12 | $analyzersPaths = Join-Path (Join-Path (Split-Path -Path $toolsPath -Parent) "analyzers") * -Resolve 13 | 14 | foreach($analyzersPath in $analyzersPaths) 15 | { 16 | if (Test-Path $analyzersPath) 17 | { 18 | # Install the language agnostic analyzers. 19 | foreach ($analyzerFilePath in Get-ChildItem -Path "$analyzersPath\*.dll" -Exclude *.resources.dll) 20 | { 21 | if($project.Object.AnalyzerReferences) 22 | { 23 | $project.Object.AnalyzerReferences.Add($analyzerFilePath.FullName) 24 | } 25 | } 26 | } 27 | } 28 | 29 | # $project.Type gives the language name like (C# or VB.NET) 30 | $languageFolder = "" 31 | if($project.Type -eq "C#") 32 | { 33 | $languageFolder = "cs" 34 | } 35 | if($project.Type -eq "VB.NET") 36 | { 37 | $languageFolder = "vb" 38 | } 39 | if($languageFolder -eq "") 40 | { 41 | return 42 | } 43 | 44 | foreach($analyzersPath in $analyzersPaths) 45 | { 46 | # Install language specific analyzers. 47 | $languageAnalyzersPath = join-path $analyzersPath $languageFolder 48 | if (Test-Path $languageAnalyzersPath) 49 | { 50 | foreach ($analyzerFilePath in Get-ChildItem -Path "$languageAnalyzersPath\*.dll" -Exclude *.resources.dll) 51 | { 52 | if($project.Object.AnalyzerReferences) 53 | { 54 | $project.Object.AnalyzerReferences.Add($analyzerFilePath.FullName) 55 | } 56 | } 57 | } 58 | } 59 | # SIG # Begin signature block 60 | # MIIjkgYJKoZIhvcNAQcCoIIjgzCCI38CAQExDzANBglghkgBZQMEAgEFADB5Bgor 61 | # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG 62 | # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCA/i+qRUHsWzI0s 63 | # FVk99zLgt/HOEQ33uvkFsWtHTHZgf6CCDYEwggX/MIID56ADAgECAhMzAAABh3IX 64 | # chVZQMcJAAAAAAGHMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD 65 | # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy 66 | # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p 67 | # bmcgUENBIDIwMTEwHhcNMjAwMzA0MTgzOTQ3WhcNMjEwMzAzMTgzOTQ3WjB0MQsw 68 | # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u 69 | # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy 70 | # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB 71 | # AQDOt8kLc7P3T7MKIhouYHewMFmnq8Ayu7FOhZCQabVwBp2VS4WyB2Qe4TQBT8aB 72 | # znANDEPjHKNdPT8Xz5cNali6XHefS8i/WXtF0vSsP8NEv6mBHuA2p1fw2wB/F0dH 73 | # sJ3GfZ5c0sPJjklsiYqPw59xJ54kM91IOgiO2OUzjNAljPibjCWfH7UzQ1TPHc4d 74 | # weils8GEIrbBRb7IWwiObL12jWT4Yh71NQgvJ9Fn6+UhD9x2uk3dLj84vwt1NuFQ 75 | # itKJxIV0fVsRNR3abQVOLqpDugbr0SzNL6o8xzOHL5OXiGGwg6ekiXA1/2XXY7yV 76 | # Fc39tledDtZjSjNbex1zzwSXAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE 77 | # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUhov4ZyO96axkJdMjpzu2zVXOJcsw 78 | # UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1 79 | # ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDU4Mzg1MB8GA1UdIwQYMBaAFEhu 80 | # ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu 81 | # bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w 82 | # Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3 83 | # Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx 84 | # MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAixmy 85 | # S6E6vprWD9KFNIB9G5zyMuIjZAOuUJ1EK/Vlg6Fb3ZHXjjUwATKIcXbFuFC6Wr4K 86 | # NrU4DY/sBVqmab5AC/je3bpUpjtxpEyqUqtPc30wEg/rO9vmKmqKoLPT37svc2NV 87 | # BmGNl+85qO4fV/w7Cx7J0Bbqk19KcRNdjt6eKoTnTPHBHlVHQIHZpMxacbFOAkJr 88 | # qAVkYZdz7ikNXTxV+GRb36tC4ByMNxE2DF7vFdvaiZP0CVZ5ByJ2gAhXMdK9+usx 89 | # zVk913qKde1OAuWdv+rndqkAIm8fUlRnr4saSCg7cIbUwCCf116wUJ7EuJDg0vHe 90 | # yhnCeHnBbyH3RZkHEi2ofmfgnFISJZDdMAeVZGVOh20Jp50XBzqokpPzeZ6zc1/g 91 | # yILNyiVgE+RPkjnUQshd1f1PMgn3tns2Cz7bJiVUaqEO3n9qRFgy5JuLae6UweGf 92 | # AeOo3dgLZxikKzYs3hDMaEtJq8IP71cX7QXe6lnMmXU/Hdfz2p897Zd+kU+vZvKI 93 | # 3cwLfuVQgK2RZ2z+Kc3K3dRPz2rXycK5XCuRZmvGab/WbrZiC7wJQapgBodltMI5 94 | # GMdFrBg9IeF7/rP4EqVQXeKtevTlZXjpuNhhjuR+2DMt/dWufjXpiW91bo3aH6Ea 95 | # jOALXmoxgltCp1K7hrS6gmsvj94cLRf50QQ4U8Qwggd6MIIFYqADAgECAgphDpDS 96 | # AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK 97 | # V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 98 | # IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0 99 | # ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla 100 | # MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS 101 | # ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT 102 | # H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB 103 | # AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG 104 | # OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S 105 | # 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz 106 | # y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7 107 | # 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u 108 | # M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33 109 | # X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl 110 | # XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP 111 | # 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB 112 | # l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF 113 | # RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM 114 | # CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ 115 | # BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud 116 | # DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO 117 | # 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0 118 | # LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y 119 | # Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p 120 | # Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y 121 | # Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB 122 | # FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw 123 | # cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA 124 | # XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY 125 | # 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj 126 | # 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd 127 | # d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ 128 | # Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf 129 | # wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ 130 | # aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j 131 | # NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B 132 | # xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96 133 | # eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7 134 | # r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I 135 | # RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIVZzCCFWMCAQEwgZUwfjELMAkG 136 | # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx 137 | # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z 138 | # b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAYdyF3IVWUDHCQAAAAABhzAN 139 | # BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor 140 | # BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgRjg7DcI6 141 | # uhYfXWwAQ6hK0mPW7iyr2tzHR0DHSDJkscIwQgYKKwYBBAGCNwIBDDE0MDKgFIAS 142 | # AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN 143 | # BgkqhkiG9w0BAQEFAASCAQCMjRK3YvDB0Sy30hadcXmGkSLrq7U7R+bkBh+FsWz8 144 | # CLSdV9Sh1z6mmVlEk6jHf7h3fiMEZwXGSvBEH4dc+equuU9KhYkhfTTfd3SSCER6 145 | # swWv/vqzQgz7WZOzuDuOrMc4lqCc3qUeLCeFnZEjfDKgymUi7UaTDofM0HNZtYA1 146 | # f2kLORo2CzvvZLHK+xQYvefFFrCsHSiNFvH5zM9142c1aMpGVgyuB6cBxL3johS/ 147 | # 7i4myLHr9LB7GcSmEYqDH5q4mxgNNtunYqEyK0V0b/UI0b9q1p50KJPag9zh/HB0 148 | # Q+fY1t8guPwGoxkO+hqDV6k1R3tJBHG5c8kDSCVR/CbVoYIS8TCCEu0GCisGAQQB 149 | # gjcDAwExghLdMIIS2QYJKoZIhvcNAQcCoIISyjCCEsYCAQMxDzANBglghkgBZQME 150 | # AgEFADCCAVUGCyqGSIb3DQEJEAEEoIIBRASCAUAwggE8AgEBBgorBgEEAYRZCgMB 151 | # MDEwDQYJYIZIAWUDBAIBBQAEIHQWatv8aXHB68pc0SETnr9LF64Haou9lbLES5Og 152 | # 6ES0AgZgDz5A4W0YEzIwMjEwMTI4MTM1MzExLjc1N1owBIACAfSggdSkgdEwgc4x 153 | # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt 154 | # b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1p 155 | # Y3Jvc29mdCBPcGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMg 156 | # VFNTIEVTTjo2MEJDLUUzODMtMjYzNTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUt 157 | # U3RhbXAgU2VydmljZaCCDkQwggT1MIID3aADAgECAhMzAAABJt+6SyK5goIHAAAA 158 | # AAEmMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo 159 | # aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y 160 | # cG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEw 161 | # MB4XDTE5MTIxOTAxMTQ1OVoXDTIxMDMxNzAxMTQ1OVowgc4xCzAJBgNVBAYTAlVT 162 | # MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK 163 | # ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVy 164 | # YXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjo2MEJD 165 | # LUUzODMtMjYzNTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vydmlj 166 | # ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ4wvoacTvMNlXQTtfF/ 167 | # Cx5Ol3X0fcjUNMvjLgTmO5+WHYJFbp725P3+qvFKDRQHWEI1Sz0gB24urVDIjXjB 168 | # h5NVNJVMQJI2tltv7M4/4IbhZJb3xzQW7LolEoZYUZanBTUuyly9osCg4o5joViT 169 | # 2GtmyxK+Fv5kC20l2opeaeptd/E7ceDAFRM87hiNCsK/KHyC+8+swnlg4gTOey6z 170 | # QqhzgNsG6HrjLBuDtDs9izAMwS2yWT0T52QA9h3Q+B1C9ps2fMKMe+DHpG+0c61D 171 | # 94Yh6cV2XHib4SBCnwIFZAeZE2UJ4qPANSYozI8PH+E5rCT3SVqYvHou97HsXvP2 172 | # I3MCAwEAAaOCARswggEXMB0GA1UdDgQWBBRJq6wfF7B+mEKN0VimX8ajNA5hQTAf 173 | # BgNVHSMEGDAWgBTVYzpcijGQ80N7fEYbxTNoWoVtVTBWBgNVHR8ETzBNMEugSaBH 174 | # hkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNU 175 | # aW1TdGFQQ0FfMjAxMC0wNy0wMS5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUF 176 | # BzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1RpbVN0 177 | # YVBDQV8yMDEwLTA3LTAxLmNydDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsG 178 | # AQUFBwMIMA0GCSqGSIb3DQEBCwUAA4IBAQBAlvudaOlv9Cfzv56bnX41czF6tLtH 179 | # LB46l6XUch+qNN45ZmOTFwLot3JjwSrn4oycQ9qTET1TFDYd1QND0LiXmKz9OqBX 180 | # ai6S8XdyCQEZvfL82jIAs9pwsAQ6XvV9jNybPStRgF/sOAM/Deyfmej9Tg9FcRwX 181 | # ank2qgzdZZNb8GoEze7f1orcTF0Q89IUXWIlmwEwQFYF1wjn87N4ZxL9Z/xA2m/R 182 | # 1zizFylWP/mpamCnVfZZLkafFLNUNVmcvc+9gM7vceJs37d3ydabk4wR6ObR34sW 183 | # aLppmyPlsI1Qq5Lu6bJCWoXzYuWpkoK6oEep1gML6SRC3HKVS3UscZhtMIIGcTCC 184 | # BFmgAwIBAgIKYQmBKgAAAAAAAjANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMC 185 | # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV 186 | # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJv 187 | # b3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMTAwNzAxMjEzNjU1WhcN 188 | # MjUwNzAxMjE0NjU1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv 189 | # bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0 190 | # aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCCASIw 191 | # DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkdDbx3EYo6IOz8E5f1+n9plGt0 192 | # VBDVpQoAgoX77XxoSyxfxcPlYcJ2tz5mK1vwFVMnBDEfQRsalR3OCROOfGEwWbEw 193 | # RA/xYIiEVEMM1024OAizQt2TrNZzMFcmgqNFDdDq9UeBzb8kYDJYYEbyWEeGMoQe 194 | # dGFnkV+BVLHPk0ySwcSmXdFhE24oxhr5hoC732H8RsEnHSRnEnIaIYqvS2SJUGKx 195 | # Xf13Hz3wV3WsvYpCTUBR0Q+cBj5nf/VmwAOWRH7v0Ev9buWayrGo8noqCjHw2k4G 196 | # kbaICDXoeByw6ZnNPOcvRLqn9NxkvaQBwSAJk3jN/LzAyURdXhacAQVPIk0CAwEA 197 | # AaOCAeYwggHiMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBTVYzpcijGQ80N7 198 | # fEYbxTNoWoVtVTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMC 199 | # AYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvX 200 | # zpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20v 201 | # cGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYI 202 | # KwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5j 203 | # b20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDCBoAYDVR0g 204 | # AQH/BIGVMIGSMIGPBgkrBgEEAYI3LgMwgYEwPQYIKwYBBQUHAgEWMWh0dHA6Ly93 205 | # d3cubWljcm9zb2Z0LmNvbS9QS0kvZG9jcy9DUFMvZGVmYXVsdC5odG0wQAYIKwYB 206 | # BQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AUABvAGwAaQBjAHkAXwBTAHQAYQB0AGUA 207 | # bQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAAfmiFEN4sbgmD+BcQM9naOh 208 | # IW+z66bM9TG+zwXiqf76V20ZMLPCxWbJat/15/B4vceoniXj+bzta1RXCCtRgkQS 209 | # +7lTjMz0YBKKdsxAQEGb3FwX/1z5Xhc1mCRWS3TvQhDIr79/xn/yN31aPxzymXlK 210 | # kVIArzgPF/UveYFl2am1a+THzvbKegBvSzBEJCI8z+0DpZaPWSm8tv0E4XCfMkon 211 | # /VWvL/625Y4zu2JfmttXQOnxzplmkIz/amJ/3cVKC5Em4jnsGUpxY517IW3DnKOi 212 | # PPp/fZZqkHimbdLhnPkd/DjYlPTGpQqWhqS9nhquBEKDuLWAmyI4ILUl5WTs9/S/ 213 | # fmNZJQ96LjlXdqJxqgaKD4kWumGnEcua2A5HmoDF0M2n0O99g/DhO3EJ3110mCII 214 | # YdqwUB5vvfHhAN/nMQekkzr3ZUd46PioSKv33nJ+YWtvd6mBy6cJrDm77MbL2IK0 215 | # cs0d9LiFAR6A+xuJKlQ5slvayA1VmXqHczsI5pgt6o3gMy4SKfXAL1QnIffIrE7a 216 | # KLixqduWsqdCosnPGUFN4Ib5KpqjEWYw07t0MkvfY3v1mYovG8chr1m1rtxEPJdQ 217 | # cdeh0sVV42neV8HR3jDA/czmTfsNv11P6Z0eGTgvvM9YBS7vDaBQNdrvCScc1bN+ 218 | # NR4Iuto229Nfj950iEkSoYIC0jCCAjsCAQEwgfyhgdSkgdEwgc4xCzAJBgNVBAYT 219 | # AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD 220 | # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBP 221 | # cGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjo2 222 | # MEJDLUUzODMtMjYzNTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vy 223 | # dmljZaIjCgEBMAcGBSsOAwIaAxUACmcyOWmZxErpq06B8dy6oMZ6//yggYMwgYCk 224 | # fjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH 225 | # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD 226 | # Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIF 227 | # AOO8XzYwIhgPMjAyMTAxMjgwMTUyNTRaGA8yMDIxMDEyOTAxNTI1NFowdzA9Bgor 228 | # BgEEAYRZCgQBMS8wLTAKAgUA47xfNgIBADAKAgEAAgIbLwIB/zAHAgEAAgITKTAK 229 | # AgUA472wtgIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIB 230 | # AAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAC77bUsJUEVTSYlY 231 | # wKFpNKL8dbjlzb8EutPbxa952QSEIxgMUycq0Db9t3QSPfWd919JnobZ+0PCoE2A 232 | # Pu4Os73CDKVzF+bwFgLRnttBccwAsgy7d1pWtQcfyIh9O+l/HislSXsFH5zawEs5 233 | # 9uvH8UtGX1jExKlXKnmQriZYTlTCMYIDDTCCAwkCAQEwgZMwfDELMAkGA1UEBhMC 234 | # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV 235 | # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp 236 | # bWUtU3RhbXAgUENBIDIwMTACEzMAAAEm37pLIrmCggcAAAAAASYwDQYJYIZIAWUD 237 | # BAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0B 238 | # CQQxIgQgfLtPMEgO0BfdMeIvsY3gSnjcAKLOUnkiV89CXQ7fmqkwgfoGCyqGSIb3 239 | # DQEJEAIvMYHqMIHnMIHkMIG9BCA2/c/vnr1ecAzvapOWZ2xGfAkzrkfpGcrvMW07 240 | # CQl1DzCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u 241 | # MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp 242 | # b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAB 243 | # Jt+6SyK5goIHAAAAAAEmMCIEILgdbWcIe050A6mMuy1I+6mT4dgtx0U15aTsUnn0 244 | # tfP4MA0GCSqGSIb3DQEBCwUABIIBAI2O4PAlewLHuXky0KYOlR03qPHYvVDSIZWv 245 | # ydszjrgdE02PX1qWo6ZyiuPuyM+ssKiHImpy/wCt2aQk/PPAOIgJVhyhsyc2N0h/ 246 | # Hb1cBDGdpwfDndZquf5pwrqfNm2KM9tk7nDkKa0O0C7VpfOgSdamThZiaOZDJVhp 247 | # A3pTsR1LhA17Wih8bgDRsZRCiEPhrfeWBMb3nMjyox3zg+XL0yFmvfcyOWkn/I3o 248 | # 4jj8KKqJ2SwJTJqRWqNg036ilkaayzpFA2XX55s2cdAmPpVh8VuTRLrKVx00/TXS 249 | # hGHM1fgii3urBBNUn8TSXTcUZFpnb9dWJFbxi0aHcHq8iq0J90g= 250 | # SIG # End signature block 251 | -------------------------------------------------------------------------------- /EnumeratorCallAnalyzer/EnumeratorCallAnalyzer.Package/tools/uninstall.ps1: -------------------------------------------------------------------------------- 1 | param($installPath, $toolsPath, $package, $project) 2 | 3 | if($project.Object.SupportsPackageDependencyResolution) 4 | { 5 | if($project.Object.SupportsPackageDependencyResolution()) 6 | { 7 | # Do not uninstall analyzers via uninstall.ps1, instead let the project system handle it. 8 | return 9 | } 10 | } 11 | 12 | $analyzersPaths = Join-Path (Join-Path (Split-Path -Path $toolsPath -Parent) "analyzers") * -Resolve 13 | 14 | foreach($analyzersPath in $analyzersPaths) 15 | { 16 | # Uninstall the language agnostic analyzers. 17 | if (Test-Path $analyzersPath) 18 | { 19 | foreach ($analyzerFilePath in Get-ChildItem -Path "$analyzersPath\*.dll" -Exclude *.resources.dll) 20 | { 21 | if($project.Object.AnalyzerReferences) 22 | { 23 | $project.Object.AnalyzerReferences.Remove($analyzerFilePath.FullName) 24 | } 25 | } 26 | } 27 | } 28 | 29 | # $project.Type gives the language name like (C# or VB.NET) 30 | $languageFolder = "" 31 | if($project.Type -eq "C#") 32 | { 33 | $languageFolder = "cs" 34 | } 35 | if($project.Type -eq "VB.NET") 36 | { 37 | $languageFolder = "vb" 38 | } 39 | if($languageFolder -eq "") 40 | { 41 | return 42 | } 43 | 44 | foreach($analyzersPath in $analyzersPaths) 45 | { 46 | # Uninstall language specific analyzers. 47 | $languageAnalyzersPath = join-path $analyzersPath $languageFolder 48 | if (Test-Path $languageAnalyzersPath) 49 | { 50 | foreach ($analyzerFilePath in Get-ChildItem -Path "$languageAnalyzersPath\*.dll" -Exclude *.resources.dll) 51 | { 52 | if($project.Object.AnalyzerReferences) 53 | { 54 | try 55 | { 56 | $project.Object.AnalyzerReferences.Remove($analyzerFilePath.FullName) 57 | } 58 | catch 59 | { 60 | 61 | } 62 | } 63 | } 64 | } 65 | } 66 | # SIG # Begin signature block 67 | # MIIjkgYJKoZIhvcNAQcCoIIjgzCCI38CAQExDzANBglghkgBZQMEAgEFADB5Bgor 68 | # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG 69 | # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDC68wb97fg0QGL 70 | # yXrxJhYfmibzcOh8caqC0uZprfczDaCCDYEwggX/MIID56ADAgECAhMzAAABh3IX 71 | # chVZQMcJAAAAAAGHMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD 72 | # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy 73 | # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p 74 | # bmcgUENBIDIwMTEwHhcNMjAwMzA0MTgzOTQ3WhcNMjEwMzAzMTgzOTQ3WjB0MQsw 75 | # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u 76 | # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy 77 | # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB 78 | # AQDOt8kLc7P3T7MKIhouYHewMFmnq8Ayu7FOhZCQabVwBp2VS4WyB2Qe4TQBT8aB 79 | # znANDEPjHKNdPT8Xz5cNali6XHefS8i/WXtF0vSsP8NEv6mBHuA2p1fw2wB/F0dH 80 | # sJ3GfZ5c0sPJjklsiYqPw59xJ54kM91IOgiO2OUzjNAljPibjCWfH7UzQ1TPHc4d 81 | # weils8GEIrbBRb7IWwiObL12jWT4Yh71NQgvJ9Fn6+UhD9x2uk3dLj84vwt1NuFQ 82 | # itKJxIV0fVsRNR3abQVOLqpDugbr0SzNL6o8xzOHL5OXiGGwg6ekiXA1/2XXY7yV 83 | # Fc39tledDtZjSjNbex1zzwSXAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE 84 | # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUhov4ZyO96axkJdMjpzu2zVXOJcsw 85 | # UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1 86 | # ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDU4Mzg1MB8GA1UdIwQYMBaAFEhu 87 | # ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu 88 | # bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w 89 | # Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3 90 | # Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx 91 | # MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAixmy 92 | # S6E6vprWD9KFNIB9G5zyMuIjZAOuUJ1EK/Vlg6Fb3ZHXjjUwATKIcXbFuFC6Wr4K 93 | # NrU4DY/sBVqmab5AC/je3bpUpjtxpEyqUqtPc30wEg/rO9vmKmqKoLPT37svc2NV 94 | # BmGNl+85qO4fV/w7Cx7J0Bbqk19KcRNdjt6eKoTnTPHBHlVHQIHZpMxacbFOAkJr 95 | # qAVkYZdz7ikNXTxV+GRb36tC4ByMNxE2DF7vFdvaiZP0CVZ5ByJ2gAhXMdK9+usx 96 | # zVk913qKde1OAuWdv+rndqkAIm8fUlRnr4saSCg7cIbUwCCf116wUJ7EuJDg0vHe 97 | # yhnCeHnBbyH3RZkHEi2ofmfgnFISJZDdMAeVZGVOh20Jp50XBzqokpPzeZ6zc1/g 98 | # yILNyiVgE+RPkjnUQshd1f1PMgn3tns2Cz7bJiVUaqEO3n9qRFgy5JuLae6UweGf 99 | # AeOo3dgLZxikKzYs3hDMaEtJq8IP71cX7QXe6lnMmXU/Hdfz2p897Zd+kU+vZvKI 100 | # 3cwLfuVQgK2RZ2z+Kc3K3dRPz2rXycK5XCuRZmvGab/WbrZiC7wJQapgBodltMI5 101 | # GMdFrBg9IeF7/rP4EqVQXeKtevTlZXjpuNhhjuR+2DMt/dWufjXpiW91bo3aH6Ea 102 | # jOALXmoxgltCp1K7hrS6gmsvj94cLRf50QQ4U8Qwggd6MIIFYqADAgECAgphDpDS 103 | # AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK 104 | # V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 105 | # IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0 106 | # ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla 107 | # MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS 108 | # ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT 109 | # H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB 110 | # AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG 111 | # OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S 112 | # 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz 113 | # y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7 114 | # 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u 115 | # M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33 116 | # X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl 117 | # XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP 118 | # 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB 119 | # l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF 120 | # RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM 121 | # CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ 122 | # BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud 123 | # DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO 124 | # 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0 125 | # LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y 126 | # Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p 127 | # Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y 128 | # Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB 129 | # FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw 130 | # cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA 131 | # XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY 132 | # 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj 133 | # 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd 134 | # d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ 135 | # Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf 136 | # wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ 137 | # aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j 138 | # NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B 139 | # xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96 140 | # eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7 141 | # r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I 142 | # RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIVZzCCFWMCAQEwgZUwfjELMAkG 143 | # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx 144 | # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z 145 | # b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAYdyF3IVWUDHCQAAAAABhzAN 146 | # BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor 147 | # BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgF1ypFyzl 148 | # AvvWGVCeXczrfpXmJNm9vpyjcwd4y4ivfqowQgYKKwYBBAGCNwIBDDE0MDKgFIAS 149 | # AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN 150 | # BgkqhkiG9w0BAQEFAASCAQAlvp3kobQ3njGrv7T9mKm8viQ7IsK06yFq43ZwDIob 151 | # rkxRRMZKKJfaJ2pkkTtMun/wzMjQ7hqbULUO22lywwNy3t7uNINETfPReIYNIG9p 152 | # KZ3t8zI1T+7B9Vpm5t9LC9hQp1yrj88LcA1QAaFcvjn1sxUOGlLFK2jsa2AUcrwr 153 | # QpiVDX+OOdExw+EJTUBil/kvAtXHdCT1qkH3JzzSBYiCLGq2pW4AuVvlL0iiRKeT 154 | # /AW6TY9SuOUoG0aOZZzLAuCp6qA7ovKqRAGoFpcAaGXQokWRLU4se3/2meBksksu 155 | # ZlP1paBMHbT1ZLJP095SzhwYfsw7IDkC0Zt1OLq7IdwwoYIS8TCCEu0GCisGAQQB 156 | # gjcDAwExghLdMIIS2QYJKoZIhvcNAQcCoIISyjCCEsYCAQMxDzANBglghkgBZQME 157 | # AgEFADCCAVUGCyqGSIb3DQEJEAEEoIIBRASCAUAwggE8AgEBBgorBgEEAYRZCgMB 158 | # MDEwDQYJYIZIAWUDBAIBBQAEIMdwQTCmst1vtKyhKIg+hpE9VQEH7XzRp1eSg9au 159 | # tOz7AgZgEAenLh4YEzIwMjEwMTI4MTM1MzExLjM0N1owBIACAfSggdSkgdEwgc4x 160 | # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt 161 | # b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1p 162 | # Y3Jvc29mdCBPcGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMg 163 | # VFNTIEVTTjo0NjJGLUUzMTktM0YyMDElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUt 164 | # U3RhbXAgU2VydmljZaCCDkQwggT1MIID3aADAgECAhMzAAABJMvNAqEXcFyaAAAA 165 | # AAEkMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo 166 | # aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y 167 | # cG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEw 168 | # MB4XDTE5MTIxOTAxMTQ1N1oXDTIxMDMxNzAxMTQ1N1owgc4xCzAJBgNVBAYTAlVT 169 | # MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK 170 | # ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVy 171 | # YXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjo0NjJG 172 | # LUUzMTktM0YyMDElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vydmlj 173 | # ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJCbKjgNnhjvMlnRNAtx 174 | # 7X3N5ZZkSfUFULyWsVJ1pnyMsSITimg1q3OQ1Ikf0/3gg8UG5TIRm7wH8sjBtoB3 175 | # nuzFz11CegIFcanYnt050JvnrUTKeAPUR5pLpTeP3QEgL+CWOc4lTg/XxjnQv01F 176 | # D7TTn9DEuO3kp0GQ87Mjd5ssxK0K1q4IWNFAyRpx5n8Vm3Vm1iiVL5FMDUKsl5G/ 177 | # SqQdiEDn8cqYbqWMVzWH94PdKdw1mIHToBRCNsR9BHHWzNkSS+R0WRipBSSorKT7 178 | # cuLlEBYhDo8AY3uMGlv0kLRLHASZ+sz2nfkpW2CVt+bHhVmM6/5qiu2f7eYoTYJu 179 | # cFECAwEAAaOCARswggEXMB0GA1UdDgQWBBS7HdFyrGKIhDxvypLA1lD/wGRSsDAf 180 | # BgNVHSMEGDAWgBTVYzpcijGQ80N7fEYbxTNoWoVtVTBWBgNVHR8ETzBNMEugSaBH 181 | # hkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNU 182 | # aW1TdGFQQ0FfMjAxMC0wNy0wMS5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUF 183 | # BzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1RpbVN0 184 | # YVBDQV8yMDEwLTA3LTAxLmNydDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsG 185 | # AQUFBwMIMA0GCSqGSIb3DQEBCwUAA4IBAQBo3QzNuNRgzdflwA4U7f3e2CcGlwdg 186 | # 6ii498cBiSrTpWKO3qqz5pvgHAk4hh6y/FLY80R59inLwcVuyD24S3JEdSie4y1t 187 | # C5JptweR1qlxRJCRM4vG7nPtIC4eAMKcXgovu0mTFv7xpFAVpRuvuepR91gIde32 188 | # 8lv1HTTJCV/LBBk83Xi7nCGPF59FxeIrcE32xt4YJgEpEAikeMqvWCTMyPqlmvx9 189 | # J92fxU3cQcw2j2EWwqOD5T3Nz2HWfPV80sihD1A6Y5HhjpS9taDPs7CI58I211F3 190 | # ysegNyOesG3MTrSJHyPMLKYFDxcG1neV0liktv+TW927sUOVczcSUhQLMIIGcTCC 191 | # BFmgAwIBAgIKYQmBKgAAAAAAAjANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMC 192 | # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV 193 | # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJv 194 | # b3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMTAwNzAxMjEzNjU1WhcN 195 | # MjUwNzAxMjE0NjU1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv 196 | # bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0 197 | # aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCCASIw 198 | # DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkdDbx3EYo6IOz8E5f1+n9plGt0 199 | # VBDVpQoAgoX77XxoSyxfxcPlYcJ2tz5mK1vwFVMnBDEfQRsalR3OCROOfGEwWbEw 200 | # RA/xYIiEVEMM1024OAizQt2TrNZzMFcmgqNFDdDq9UeBzb8kYDJYYEbyWEeGMoQe 201 | # dGFnkV+BVLHPk0ySwcSmXdFhE24oxhr5hoC732H8RsEnHSRnEnIaIYqvS2SJUGKx 202 | # Xf13Hz3wV3WsvYpCTUBR0Q+cBj5nf/VmwAOWRH7v0Ev9buWayrGo8noqCjHw2k4G 203 | # kbaICDXoeByw6ZnNPOcvRLqn9NxkvaQBwSAJk3jN/LzAyURdXhacAQVPIk0CAwEA 204 | # AaOCAeYwggHiMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBTVYzpcijGQ80N7 205 | # fEYbxTNoWoVtVTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMC 206 | # AYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvX 207 | # zpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20v 208 | # cGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYI 209 | # KwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5j 210 | # b20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDCBoAYDVR0g 211 | # AQH/BIGVMIGSMIGPBgkrBgEEAYI3LgMwgYEwPQYIKwYBBQUHAgEWMWh0dHA6Ly93 212 | # d3cubWljcm9zb2Z0LmNvbS9QS0kvZG9jcy9DUFMvZGVmYXVsdC5odG0wQAYIKwYB 213 | # BQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AUABvAGwAaQBjAHkAXwBTAHQAYQB0AGUA 214 | # bQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAAfmiFEN4sbgmD+BcQM9naOh 215 | # IW+z66bM9TG+zwXiqf76V20ZMLPCxWbJat/15/B4vceoniXj+bzta1RXCCtRgkQS 216 | # +7lTjMz0YBKKdsxAQEGb3FwX/1z5Xhc1mCRWS3TvQhDIr79/xn/yN31aPxzymXlK 217 | # kVIArzgPF/UveYFl2am1a+THzvbKegBvSzBEJCI8z+0DpZaPWSm8tv0E4XCfMkon 218 | # /VWvL/625Y4zu2JfmttXQOnxzplmkIz/amJ/3cVKC5Em4jnsGUpxY517IW3DnKOi 219 | # PPp/fZZqkHimbdLhnPkd/DjYlPTGpQqWhqS9nhquBEKDuLWAmyI4ILUl5WTs9/S/ 220 | # fmNZJQ96LjlXdqJxqgaKD4kWumGnEcua2A5HmoDF0M2n0O99g/DhO3EJ3110mCII 221 | # YdqwUB5vvfHhAN/nMQekkzr3ZUd46PioSKv33nJ+YWtvd6mBy6cJrDm77MbL2IK0 222 | # cs0d9LiFAR6A+xuJKlQ5slvayA1VmXqHczsI5pgt6o3gMy4SKfXAL1QnIffIrE7a 223 | # KLixqduWsqdCosnPGUFN4Ib5KpqjEWYw07t0MkvfY3v1mYovG8chr1m1rtxEPJdQ 224 | # cdeh0sVV42neV8HR3jDA/czmTfsNv11P6Z0eGTgvvM9YBS7vDaBQNdrvCScc1bN+ 225 | # NR4Iuto229Nfj950iEkSoYIC0jCCAjsCAQEwgfyhgdSkgdEwgc4xCzAJBgNVBAYT 226 | # AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD 227 | # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBP 228 | # cGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjo0 229 | # NjJGLUUzMTktM0YyMDElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vy 230 | # dmljZaIjCgEBMAcGBSsOAwIaAxUAlwPlNCq+Un54UfxLe/wKS1Xc4nqggYMwgYCk 231 | # fjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH 232 | # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD 233 | # Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIF 234 | # AOO9KO8wIhgPMjAyMTAxMjgxNjEzMzVaGA8yMDIxMDEyOTE2MTMzNVowdzA9Bgor 235 | # BgEEAYRZCgQBMS8wLTAKAgUA470o7wIBADAKAgEAAgIdzgIB/zAHAgEAAgITSTAK 236 | # AgUA4756bwIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIB 237 | # AAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBAEiUh4QVb7vaceUo 238 | # /TtRAhp98XfrRN5mZ4KyZDuNDYKfBaGx8hnyD2BgIjkQ59KzIVNfkv8PBXhLaQK7 239 | # u7k4S23kUWQ/zsRYm5EutcKXB3zrW4Ym0TpwiMTJ8arMFj3BIYjZCMFqUxdAxiH/ 240 | # CD+FIK0vvPSTRZ00KPqi5idqCj3TMYIDDTCCAwkCAQEwgZMwfDELMAkGA1UEBhMC 241 | # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV 242 | # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp 243 | # bWUtU3RhbXAgUENBIDIwMTACEzMAAAEky80CoRdwXJoAAAAAASQwDQYJYIZIAWUD 244 | # BAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0B 245 | # CQQxIgQgrLzvm34azoh15/K+sBdmMol8NxD/FT4rQfDgBXN/atwwgfoGCyqGSIb3 246 | # DQEJEAIvMYHqMIHnMIHkMIG9BCBiOOHoohqL+X7Xa/25jp1wTrQxYlYGLszis/nA 247 | # TirjIDCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u 248 | # MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp 249 | # b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAB 250 | # JMvNAqEXcFyaAAAAAAEkMCIEILvfBT5GpMSMrQo5TU1VuEC6URcoooi2maNoHgLo 251 | # yvsvMA0GCSqGSIb3DQEBCwUABIIBAIxWH4gHkyfHcF3w9aW9L1OaBOjv/Zmq7V1R 252 | # pj4tkkyuQKPqIi9gdq4wMxToI1m4IM/9I8FwLI1LH/6AWBLTfdkFr4mOMFyflO5v 253 | # gya84Pij48E/37XOOBG5S454c4Sgj6OQcZb1Ljb+QNf+6JovAhUdLL4ZLmdvuK5X 254 | # amv+cjYVV3jSJYMSx8d0w22rPmJVB25h1NZlJvPKZdKGc28ub2IxnvALF6SYaR5u 255 | # AQVzIzltI+lm1Owqt9JAuuif6YYhh/P4Z4PfXWtY/2xsIqYHbQwizlu/3Hs9UK60 256 | # VE+jyR89LdWrWqCW0orWrNwUFBiYIuupntcRH/1LMk6Tr/CJa64= 257 | # SIG # End signature block 258 | --------------------------------------------------------------------------------