From 19aea6002b41f539d6cbad0b5e533f3d2dc9c5c9 Mon Sep 17 00:00:00 2001 From: Morten Nielsen Date: Tue, 27 Feb 2024 22:05:55 -0800 Subject: [PATCH 1/5] Adds an analyzer that detects whether UseArcGISToolkit has been added --- ...ISRuntime.Toolkit.Analyzers.Test.projitems | 26 ++ ...rcGISRuntime.Toolkit.Analyzers.Test.shproj | 13 + .../CSharpAnalyzerVerifier`1+Test.cs | 26 ++ .../Verifiers/CSharpAnalyzerVerifier`1.cs | 38 +++ .../Verifiers/CSharpCodeFixVerifier`2+Test.cs | 29 ++ .../Verifiers/CSharpCodeFixVerifier`2.cs | 61 ++++ .../CSharpCodeRefactoringVerifier`1+Test.cs | 26 ++ .../CSharpCodeRefactoringVerifier`1.cs | 36 +++ .../Verifiers/CSharpVerifierHelper.cs | 33 +++ .../VisualBasicAnalyzerVerifier`1+Test.cs | 17 ++ .../VisualBasicAnalyzerVerifier`1.cs | 38 +++ .../VisualBasicCodeFixVerifier`2+Test.cs | 16 + .../Verifiers/VisualBasicCodeFixVerifier`2.cs | 61 ++++ ...sualBasicCodeRefactoringVerifier`1+Test.cs | 14 + .../VisualBasicCodeRefactoringVerifier`1.cs | 36 +++ .../CodeFixResources.Designer.cs | 72 +++++ .../CodeFixResources.resx | 124 ++++++++ ...me.Toolkit.Maui.Analyzers.CodeFixes.csproj | 27 ++ .../Properties/AssemblyInfo.cs | 1 + .../Properties/launchSettings.json | 8 + ...itInitializationAnalyzerCodeFixProvider.cs | 73 +++++ .../BaseAnalyzersUnitTests.cs | 49 +++ ...me.Toolkit.Maui.Analyzers.UnitTests.csproj | 36 +++ .../UseToolkitInitializationAnalyzerTests.cs | 129 ++++++++ .../AnalyzerReleases.Shipped.md | 7 + .../AnalyzerReleases.Unshipped.md | 6 + ...rcGISRuntime.Toolkit.Maui.Analyzers.csproj | 27 ++ .../Properties/AssemblyInfo.cs | 1 + .../Properties/launchSettings.json | 8 + .../Resources.Designer.cs | 90 ++++++ .../Toolkit.Maui.Analyzers/Resources.resx | 129 ++++++++ .../UseToolkitInitializationAnalyzer.cs | 88 ++++++ src/Directory.Build.props | 5 +- src/Esri.ArcGISRuntime.Toolkit.sln | 136 +++++++++ .../Esri.ArcGISRuntime.Toolkit.Maui.csproj | 17 +- src/Toolkit/Toolkit.Maui/tools/install.ps1 | 272 +++++++++++++++++ src/Toolkit/Toolkit.Maui/tools/uninstall.ps1 | 279 ++++++++++++++++++ 37 files changed, 2051 insertions(+), 3 deletions(-) create mode 100644 src/Analyzers/Toolkit.Analyzers.Test/Esri.ArcGISRuntime.Toolkit.Analyzers.Test.projitems create mode 100644 src/Analyzers/Toolkit.Analyzers.Test/Esri.ArcGISRuntime.Toolkit.Analyzers.Test.shproj create mode 100644 src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpAnalyzerVerifier`1+Test.cs create mode 100644 src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpAnalyzerVerifier`1.cs create mode 100644 src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpCodeFixVerifier`2+Test.cs create mode 100644 src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpCodeFixVerifier`2.cs create mode 100644 src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpCodeRefactoringVerifier`1+Test.cs create mode 100644 src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpCodeRefactoringVerifier`1.cs create mode 100644 src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpVerifierHelper.cs create mode 100644 src/Analyzers/Toolkit.Analyzers.Test/Verifiers/VisualBasicAnalyzerVerifier`1+Test.cs create mode 100644 src/Analyzers/Toolkit.Analyzers.Test/Verifiers/VisualBasicAnalyzerVerifier`1.cs create mode 100644 src/Analyzers/Toolkit.Analyzers.Test/Verifiers/VisualBasicCodeFixVerifier`2+Test.cs create mode 100644 src/Analyzers/Toolkit.Analyzers.Test/Verifiers/VisualBasicCodeFixVerifier`2.cs create mode 100644 src/Analyzers/Toolkit.Analyzers.Test/Verifiers/VisualBasicCodeRefactoringVerifier`1+Test.cs create mode 100644 src/Analyzers/Toolkit.Analyzers.Test/Verifiers/VisualBasicCodeRefactoringVerifier`1.cs create mode 100644 src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/CodeFixResources.Designer.cs create mode 100644 src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/CodeFixResources.resx create mode 100644 src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/Esri.ArcGISRuntime.Toolkit.Maui.Analyzers.CodeFixes.csproj create mode 100644 src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/Properties/AssemblyInfo.cs create mode 100644 src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/Properties/launchSettings.json create mode 100644 src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/UseToolkitInitializationAnalyzerCodeFixProvider.cs create mode 100644 src/Analyzers/Toolkit.Maui.Analyzers.UnitTests/BaseAnalyzersUnitTests.cs create mode 100644 src/Analyzers/Toolkit.Maui.Analyzers.UnitTests/Esri.ArcGISRuntime.Toolkit.Maui.Analyzers.UnitTests.csproj create mode 100644 src/Analyzers/Toolkit.Maui.Analyzers.UnitTests/UseToolkitInitializationAnalyzerTests.cs create mode 100644 src/Analyzers/Toolkit.Maui.Analyzers/AnalyzerReleases.Shipped.md create mode 100644 src/Analyzers/Toolkit.Maui.Analyzers/AnalyzerReleases.Unshipped.md create mode 100644 src/Analyzers/Toolkit.Maui.Analyzers/Esri.ArcGISRuntime.Toolkit.Maui.Analyzers.csproj create mode 100644 src/Analyzers/Toolkit.Maui.Analyzers/Properties/AssemblyInfo.cs create mode 100644 src/Analyzers/Toolkit.Maui.Analyzers/Properties/launchSettings.json create mode 100644 src/Analyzers/Toolkit.Maui.Analyzers/Resources.Designer.cs create mode 100644 src/Analyzers/Toolkit.Maui.Analyzers/Resources.resx create mode 100644 src/Analyzers/Toolkit.Maui.Analyzers/UseToolkitInitializationAnalyzer.cs create mode 100644 src/Toolkit/Toolkit.Maui/tools/install.ps1 create mode 100644 src/Toolkit/Toolkit.Maui/tools/uninstall.ps1 diff --git a/src/Analyzers/Toolkit.Analyzers.Test/Esri.ArcGISRuntime.Toolkit.Analyzers.Test.projitems b/src/Analyzers/Toolkit.Analyzers.Test/Esri.ArcGISRuntime.Toolkit.Analyzers.Test.projitems new file mode 100644 index 000000000..299e72d44 --- /dev/null +++ b/src/Analyzers/Toolkit.Analyzers.Test/Esri.ArcGISRuntime.Toolkit.Analyzers.Test.projitems @@ -0,0 +1,26 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + true + 61fbc238-623c-42ff-8c47-95d710a1e66f + + + Esri.ArcGISRuntime.Toolkit.Analyzers.Test + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Analyzers/Toolkit.Analyzers.Test/Esri.ArcGISRuntime.Toolkit.Analyzers.Test.shproj b/src/Analyzers/Toolkit.Analyzers.Test/Esri.ArcGISRuntime.Toolkit.Analyzers.Test.shproj new file mode 100644 index 000000000..2972ca157 --- /dev/null +++ b/src/Analyzers/Toolkit.Analyzers.Test/Esri.ArcGISRuntime.Toolkit.Analyzers.Test.shproj @@ -0,0 +1,13 @@ + + + + 61fbc238-623c-42ff-8c47-95d710a1e66f + 14.0 + + + + + + + + diff --git a/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpAnalyzerVerifier`1+Test.cs b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpAnalyzerVerifier`1+Test.cs new file mode 100644 index 000000000..0e3198b4f --- /dev/null +++ b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpAnalyzerVerifier`1+Test.cs @@ -0,0 +1,26 @@ +using Microsoft.CodeAnalysis.CSharp.Testing; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing.Verifiers; + +namespace Esri.ArcGISRuntime.Toolkit.Analyzers.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/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpAnalyzerVerifier`1.cs b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpAnalyzerVerifier`1.cs new file mode 100644 index 000000000..711eb4de0 --- /dev/null +++ b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpAnalyzerVerifier`1.cs @@ -0,0 +1,38 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Testing; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.CodeAnalysis.Testing.Verifiers; +using System.Threading; +using System.Threading.Tasks; + +namespace Esri.ArcGISRuntime.Toolkit.Analyzers.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/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpCodeFixVerifier`2+Test.cs b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpCodeFixVerifier`2+Test.cs new file mode 100644 index 000000000..bc12d7e60 --- /dev/null +++ b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpCodeFixVerifier`2+Test.cs @@ -0,0 +1,29 @@ +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.Testing; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing.Verifiers; +using System.Numerics; + +namespace Esri.ArcGISRuntime.Toolkit.Analyzers.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/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpCodeFixVerifier`2.cs b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpCodeFixVerifier`2.cs new file mode 100644 index 000000000..b238f311a --- /dev/null +++ b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpCodeFixVerifier`2.cs @@ -0,0 +1,61 @@ +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; +using System.Threading; +using System.Threading.Tasks; + +namespace Esri.ArcGISRuntime.Toolkit.Analyzers.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/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpCodeRefactoringVerifier`1+Test.cs b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpCodeRefactoringVerifier`1+Test.cs new file mode 100644 index 000000000..32862c11e --- /dev/null +++ b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpCodeRefactoringVerifier`1+Test.cs @@ -0,0 +1,26 @@ +using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.CSharp.Testing; +using Microsoft.CodeAnalysis.Testing.Verifiers; + +namespace Esri.ArcGISRuntime.Toolkit.Analyzers.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/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpCodeRefactoringVerifier`1.cs b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpCodeRefactoringVerifier`1.cs new file mode 100644 index 000000000..52122abcf --- /dev/null +++ b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpCodeRefactoringVerifier`1.cs @@ -0,0 +1,36 @@ +using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.Testing; +using System.Threading; +using System.Threading.Tasks; + +namespace Esri.ArcGISRuntime.Toolkit.Analyzers.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/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpVerifierHelper.cs b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpVerifierHelper.cs new file mode 100644 index 000000000..5a10f4875 --- /dev/null +++ b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/CSharpVerifierHelper.cs @@ -0,0 +1,33 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using System; +using System.Collections.Immutable; + +namespace Esri.ArcGISRuntime.Toolkit.Analyzers.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/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/VisualBasicAnalyzerVerifier`1+Test.cs b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/VisualBasicAnalyzerVerifier`1+Test.cs new file mode 100644 index 000000000..01d07f5f5 --- /dev/null +++ b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/VisualBasicAnalyzerVerifier`1+Test.cs @@ -0,0 +1,17 @@ +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing.Verifiers; +using Microsoft.CodeAnalysis.VisualBasic.Testing; + +namespace Esri.ArcGISRuntime.Toolkit.Analyzers.Test +{ + public static partial class VisualBasicAnalyzerVerifier + where TAnalyzer : DiagnosticAnalyzer, new() + { + public class Test : VisualBasicAnalyzerTest + { + public Test() + { + } + } + } +} diff --git a/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/VisualBasicAnalyzerVerifier`1.cs b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/VisualBasicAnalyzerVerifier`1.cs new file mode 100644 index 000000000..510a69e3d --- /dev/null +++ b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/VisualBasicAnalyzerVerifier`1.cs @@ -0,0 +1,38 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.CodeAnalysis.Testing.Verifiers; +using Microsoft.CodeAnalysis.VisualBasic.Testing; +using System.Threading; +using System.Threading.Tasks; + +namespace Esri.ArcGISRuntime.Toolkit.Analyzers.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/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/VisualBasicCodeFixVerifier`2+Test.cs b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/VisualBasicCodeFixVerifier`2+Test.cs new file mode 100644 index 000000000..f03c6dece --- /dev/null +++ b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/VisualBasicCodeFixVerifier`2+Test.cs @@ -0,0 +1,16 @@ +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing.Verifiers; +using Microsoft.CodeAnalysis.VisualBasic.Testing; + +namespace Esri.ArcGISRuntime.Toolkit.Analyzers.Test +{ + public static partial class VisualBasicCodeFixVerifier + where TAnalyzer : DiagnosticAnalyzer, new() + where TCodeFix : CodeFixProvider, new() + { + public class Test : VisualBasicCodeFixTest + { + } + } +} diff --git a/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/VisualBasicCodeFixVerifier`2.cs b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/VisualBasicCodeFixVerifier`2.cs new file mode 100644 index 000000000..9ac2b4d68 --- /dev/null +++ b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/VisualBasicCodeFixVerifier`2.cs @@ -0,0 +1,61 @@ +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; +using System.Threading; +using System.Threading.Tasks; + +namespace Esri.ArcGISRuntime.Toolkit.Analyzers.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/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/VisualBasicCodeRefactoringVerifier`1+Test.cs b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/VisualBasicCodeRefactoringVerifier`1+Test.cs new file mode 100644 index 000000000..6c75d103c --- /dev/null +++ b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/VisualBasicCodeRefactoringVerifier`1+Test.cs @@ -0,0 +1,14 @@ +using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.Testing.Verifiers; +using Microsoft.CodeAnalysis.VisualBasic.Testing; + +namespace Esri.ArcGISRuntime.Toolkit.Analyzers.Test +{ + public static partial class VisualBasicCodeRefactoringVerifier + where TCodeRefactoring : CodeRefactoringProvider, new() + { + public class Test : VisualBasicCodeRefactoringTest + { + } + } +} diff --git a/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/VisualBasicCodeRefactoringVerifier`1.cs b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/VisualBasicCodeRefactoringVerifier`1.cs new file mode 100644 index 000000000..c07c20295 --- /dev/null +++ b/src/Analyzers/Toolkit.Analyzers.Test/Verifiers/VisualBasicCodeRefactoringVerifier`1.cs @@ -0,0 +1,36 @@ +using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.Testing; +using System.Threading; +using System.Threading.Tasks; + +namespace Esri.ArcGISRuntime.Toolkit.Analyzers.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/src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/CodeFixResources.Designer.cs b/src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/CodeFixResources.Designer.cs new file mode 100644 index 000000000..469de8136 --- /dev/null +++ b/src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/CodeFixResources.Designer.cs @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------------ +// +// 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 Esri.ArcGISRuntime.Maui.Analyzers { + 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("Esri.ArcGISRuntime.Maui.Analyzers.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; + } + } + + /// + /// Looks up a localized string similar to Add `.UseArcGISToolkit()`. + /// + internal static string Initialize_ArcGIS_Runtime_Toolkit_for__NET_MAUI_Before_UseMauiApp { + get { + return ResourceManager.GetString("Initialize ArcGIS Runtime Toolkit for .NET MAUI Before UseMauiApp", resourceCulture); + } + } + } +} diff --git a/src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/CodeFixResources.resx b/src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/CodeFixResources.resx new file mode 100644 index 000000000..b62b42190 --- /dev/null +++ b/src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/CodeFixResources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + Add `.UseArcGISToolkit()` + Add `.UseArcGISToolkit()` + + \ No newline at end of file diff --git a/src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/Esri.ArcGISRuntime.Toolkit.Maui.Analyzers.CodeFixes.csproj b/src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/Esri.ArcGISRuntime.Toolkit.Maui.Analyzers.CodeFixes.csproj new file mode 100644 index 000000000..2eb309085 --- /dev/null +++ b/src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/Esri.ArcGISRuntime.Toolkit.Maui.Analyzers.CodeFixes.csproj @@ -0,0 +1,27 @@ + + + + netstandard2.0 + false + true + Esri.ArcGISRuntime.Maui.Analyzers + + + + + + + + + + + + + + + + + + + + diff --git a/src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/Properties/AssemblyInfo.cs b/src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..cd0848ea8 --- /dev/null +++ b/src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/Properties/AssemblyInfo.cs @@ -0,0 +1 @@ +[assembly: System.Resources.NeutralResourcesLanguage("en")] \ No newline at end of file diff --git a/src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/Properties/launchSettings.json b/src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/Properties/launchSettings.json new file mode 100644 index 000000000..b453e5d2a --- /dev/null +++ b/src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "CommunityToolkit.Maui.Sample": { + "commandName": "DebugRoslynComponent", + "targetProject": "..\\..\\samples\\CommunityToolkit.Maui.Sample\\CommunityToolkit.Maui.Sample.csproj" + } + } +} \ No newline at end of file diff --git a/src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/UseToolkitInitializationAnalyzerCodeFixProvider.cs b/src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/UseToolkitInitializationAnalyzerCodeFixProvider.cs new file mode 100644 index 000000000..cc323c73e --- /dev/null +++ b/src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/UseToolkitInitializationAnalyzerCodeFixProvider.cs @@ -0,0 +1,73 @@ +using System.Collections.Immutable; +using System.Composition; +using System.Linq.Expressions; +using System.Reflection.Metadata.Ecma335; +using System.Runtime.InteropServices.ComTypes; +using Esri.ArcGISRuntime.Maui.Analyzers; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Rename; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace Esri.ArcGISRuntime.Toolkit.Maui.Analyzers; + +[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(UseToolkitInitializationAnalyzerCodeFixProvider)), Shared] +public class UseToolkitInitializationAnalyzerCodeFixProvider : CodeFixProvider +{ + public sealed override ImmutableArray FixableDiagnosticIds { get; } = ImmutableArray.Create(UseToolkitInitializationAnalyzer.DiagnosticId); + + public sealed override FixAllProvider GetFixAllProvider() => 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; + + // Find the type declaration identified by the diagnostic. + var declaration = root?.FindToken(diagnosticSpan.Start).Parent?.AncestorsAndSelf().OfType().Last() ?? throw new InvalidOperationException(); + + // Register a code action that will invoke the fix. + context.RegisterCodeFix( + CodeAction.Create( + title: CodeFixResources.Initialize_ArcGIS_Runtime_Toolkit_for__NET_MAUI_Before_UseMauiApp, + createChangedDocument: c => AddUseArcGISToolkit(context.Document, declaration, c), + equivalenceKey: nameof(CodeFixResources.Initialize_ArcGIS_Runtime_Toolkit_for__NET_MAUI_Before_UseMauiApp)), + diagnostic); + } + + static async Task AddUseArcGISToolkit(Document document, InvocationExpressionSyntax invocationExpression, CancellationToken cancellationToken) + { + var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + if (root is null) + { + return document; + } + + var updatedInvocationExpression = + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, invocationExpression, IdentifierName("UseArcGISToolkit"))); + + var mauiToolkitUsingStatement = + UsingDirective( + QualifiedName( + QualifiedName(QualifiedName(IdentifierName("Esri"), IdentifierName("ArcGISRuntime")), IdentifierName("Toolkit")), + IdentifierName("Maui"))); + + var newRoot = root.ReplaceNode(invocationExpression, updatedInvocationExpression); + + if (newRoot is CompilationUnitSyntax compilationSyntax) + { + newRoot = compilationSyntax.AddUsings(mauiToolkitUsingStatement); + } + + var newDocument = document.WithSyntaxRoot(newRoot); + + return newDocument; + } +} \ No newline at end of file diff --git a/src/Analyzers/Toolkit.Maui.Analyzers.UnitTests/BaseAnalyzersUnitTests.cs b/src/Analyzers/Toolkit.Maui.Analyzers.UnitTests/BaseAnalyzersUnitTests.cs new file mode 100644 index 000000000..c35699061 --- /dev/null +++ b/src/Analyzers/Toolkit.Maui.Analyzers.UnitTests/BaseAnalyzersUnitTests.cs @@ -0,0 +1,49 @@ +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Immutable; +using System.Threading; +using System.Threading.Tasks; +using Esri.ArcGISRuntime.Toolkit.Analyzers.Test; + +namespace Esri.ArcGISRuntime.Toolkit.Maui.Analyzers.UnitTests; +public abstract class BaseAnalyzersUnitTest + where TAnalyzer : DiagnosticAnalyzer, new() + where TCodeFix : CodeFixProvider, new() +{ + private static readonly Lazy _lazyNet8_MAUI = + new Lazy(() => + { + return new ReferenceAssemblies("net8.0", new PackageIdentity("Microsoft.NETCore.App.Ref", "8.0.2"), System.IO.Path.Combine("ref", "net8.0")) + .AddPackages(ImmutableArray.Create(new PackageIdentity[] { + new PackageIdentity("Microsoft.Maui.Controls", "8.0.3"), + new PackageIdentity("Esri.ArcGISRuntime.Maui", "200.3.0"), + new PackageIdentity("Esri.ArcGISRuntime.Toolkit.Maui", "200.3.0")})); + }); + public static ReferenceAssemblies Net8_MAUI => _lazyNet8_MAUI.Value; + + protected static async Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] expected) + { + var test = new CSharpCodeFixVerifier.Test + { + ReferenceAssemblies = Net8_MAUI, + TestCode = source, + }; + test.ExpectedDiagnostics.AddRange(expected); + await test.RunAsync(CancellationToken.None); + } + protected static async Task VerifyCodeFixAsync(string source, DiagnosticResult expected, string fixedSource) + { + var test = new CSharpCodeFixVerifier.Test + { + ReferenceAssemblies = Net8_MAUI, + TestCode = source, + FixedCode = fixedSource + }; + test.ExpectedDiagnostics.Add(expected); + await test.RunAsync(CancellationToken.None); + } + protected DiagnosticResult Diagnostic(string diagnosticId) => Esri.ArcGISRuntime.Toolkit.Analyzers.Test.CSharpCodeFixVerifier.Diagnostic(diagnosticId); +} \ No newline at end of file diff --git a/src/Analyzers/Toolkit.Maui.Analyzers.UnitTests/Esri.ArcGISRuntime.Toolkit.Maui.Analyzers.UnitTests.csproj b/src/Analyzers/Toolkit.Maui.Analyzers.UnitTests/Esri.ArcGISRuntime.Toolkit.Maui.Analyzers.UnitTests.csproj new file mode 100644 index 000000000..9045186f5 --- /dev/null +++ b/src/Analyzers/Toolkit.Maui.Analyzers.UnitTests/Esri.ArcGISRuntime.Toolkit.Maui.Analyzers.UnitTests.csproj @@ -0,0 +1,36 @@ + + + + net8.0 + false + true + true + $(BaseIntermediateOutputPath)\GF + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Analyzers/Toolkit.Maui.Analyzers.UnitTests/UseToolkitInitializationAnalyzerTests.cs b/src/Analyzers/Toolkit.Maui.Analyzers.UnitTests/UseToolkitInitializationAnalyzerTests.cs new file mode 100644 index 000000000..c0d25f61d --- /dev/null +++ b/src/Analyzers/Toolkit.Maui.Analyzers.UnitTests/UseToolkitInitializationAnalyzerTests.cs @@ -0,0 +1,129 @@ +using Microsoft.CodeAnalysis.Testing; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Threading; +using System.Threading.Tasks; +using Esri.ArcGISRuntime.Toolkit.Analyzers.Test; + +namespace Esri.ArcGISRuntime.Toolkit.Maui.Analyzers.UnitTests; + +[TestClass] +public class UseToolkitInitializationAnalyzerTests : BaseAnalyzersUnitTest +{ + [TestMethod] + public void UseToolkitInitializationAnalyzerId() + { + Assert.AreEqual("AMT001", UseToolkitInitializationAnalyzer.DiagnosticId); + } + + [TestMethod] + public async Task DetectMissingUseCall() + { + var testCode = @" +using Microsoft.Maui.Hosting; +using Microsoft.Maui.Controls.Hosting; +namespace MyMauiApp; +public class App : global::Microsoft.Maui.Controls.Application { } +public static class MauiProgram +{ + public static MauiApp CreateMauiApp() + { + var builder = MauiApp.CreateBuilder(); + {|#0:builder + .UseMauiApp() + .ConfigureFonts(fonts => + { + fonts.AddFont(""OpenSans-Regular.ttf"", ""OpenSansRegular""); + fonts.AddFont(""OpenSans-Semibold.ttf"", ""OpenSansSemibold""); + })|};//.UseArcGISRuntime().UseArcGISToolkit(); + return builder.Build(); + } +} +"; + + var expected = Diagnostic("AMT001").WithLocation(0); + //var expected = Diagnostic("AMT001"); + await VerifyAnalyzerAsync(testCode, expected); + } + + [TestMethod] + public async Task DetectUseCallPresent() + { + var testCode = @" +using Microsoft.Maui.Hosting; +using Microsoft.Maui.Controls.Hosting; +using Esri.ArcGISRuntime.Maui; +using Esri.ArcGISRuntime.Toolkit.Maui; +namespace MyMauiApp; +public class App : global::Microsoft.Maui.Controls.Application { } +public static class MauiProgram +{ + public static MauiApp CreateMauiApp() + { + var builder = MauiApp.CreateBuilder(); + builder + .UseMauiApp() + .ConfigureFonts(fonts => { + fonts.AddFont(""OpenSans-Regular.ttf"", ""OpenSansRegular""); + fonts.AddFont(""OpenSans-Semibold.ttf"", ""OpenSansSemibold""); + }).UseArcGISRuntime().UseArcGISToolkit(); + return builder.Build(); + } +}"; + await VerifyAnalyzerAsync(testCode); + } + + [TestMethod] + public async Task CodeFixer() + { + var testCode = @" +using Microsoft.Maui.Hosting; +using Microsoft.Maui.Controls.Hosting; +namespace MyMauiApp; +public class App : global::Microsoft.Maui.Controls.Application { } +public static class MauiProgram +{ + public static MauiApp CreateMauiApp() + { + var builder = MauiApp.CreateBuilder(); + {|#0:builder + .UseMauiApp() + .ConfigureFonts(fonts => + { + fonts.AddFont(""OpenSans-Regular.ttf"", ""OpenSansRegular""); + fonts.AddFont(""OpenSans-Semibold.ttf"", ""OpenSansSemibold""); + })|}; + return builder.Build(); + } +} +"; + + + var fixedCode = @" +using Microsoft.Maui.Hosting; +using Microsoft.Maui.Controls.Hosting; +using Esri.ArcGISRuntime.Toolkit.Maui; + +namespace MyMauiApp; +public class App : global::Microsoft.Maui.Controls.Application { } +public static class MauiProgram +{ + public static MauiApp CreateMauiApp() + { + var builder = MauiApp.CreateBuilder(); + builder + .UseMauiApp() + .ConfigureFonts(fonts => + { + fonts.AddFont(""OpenSans-Regular.ttf"", ""OpenSansRegular""); + fonts.AddFont(""OpenSans-Semibold.ttf"", ""OpenSansSemibold""); + }).UseArcGISToolkit(); + return builder.Build(); + } +} +"; + + var expected = Diagnostic("AMT001").WithLocation(0); + await VerifyCodeFixAsync(testCode, expected, fixedCode); + } + +} \ No newline at end of file diff --git a/src/Analyzers/Toolkit.Maui.Analyzers/AnalyzerReleases.Shipped.md b/src/Analyzers/Toolkit.Maui.Analyzers/AnalyzerReleases.Shipped.md new file mode 100644 index 000000000..c15f0ad3e --- /dev/null +++ b/src/Analyzers/Toolkit.Maui.Analyzers/AnalyzerReleases.Shipped.md @@ -0,0 +1,7 @@ +## Release 200.4.0 + +### New Rules + +Rule ID | Severity | Notes +--------|----------|------- +AMT001 | Error | `.UseArcGISToolkit()` Not Found on MauiAppBuilder \ No newline at end of file diff --git a/src/Analyzers/Toolkit.Maui.Analyzers/AnalyzerReleases.Unshipped.md b/src/Analyzers/Toolkit.Maui.Analyzers/AnalyzerReleases.Unshipped.md new file mode 100644 index 000000000..2476aca96 --- /dev/null +++ b/src/Analyzers/Toolkit.Maui.Analyzers/AnalyzerReleases.Unshipped.md @@ -0,0 +1,6 @@ +## Release 200.4.0 + +### New Rules + +Rule ID | Severity | Notes +--------|----------|------- \ No newline at end of file diff --git a/src/Analyzers/Toolkit.Maui.Analyzers/Esri.ArcGISRuntime.Toolkit.Maui.Analyzers.csproj b/src/Analyzers/Toolkit.Maui.Analyzers/Esri.ArcGISRuntime.Toolkit.Maui.Analyzers.csproj new file mode 100644 index 000000000..fa57621b8 --- /dev/null +++ b/src/Analyzers/Toolkit.Maui.Analyzers/Esri.ArcGISRuntime.Toolkit.Maui.Analyzers.csproj @@ -0,0 +1,27 @@ + + + + netstandard2.0 + false + true + + + true + + + *$(MSBuildProjectFile)* + + + + + + + + + + + + + + + diff --git a/src/Analyzers/Toolkit.Maui.Analyzers/Properties/AssemblyInfo.cs b/src/Analyzers/Toolkit.Maui.Analyzers/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..cd0848ea8 --- /dev/null +++ b/src/Analyzers/Toolkit.Maui.Analyzers/Properties/AssemblyInfo.cs @@ -0,0 +1 @@ +[assembly: System.Resources.NeutralResourcesLanguage("en")] \ No newline at end of file diff --git a/src/Analyzers/Toolkit.Maui.Analyzers/Properties/launchSettings.json b/src/Analyzers/Toolkit.Maui.Analyzers/Properties/launchSettings.json new file mode 100644 index 000000000..1a3eee2de --- /dev/null +++ b/src/Analyzers/Toolkit.Maui.Analyzers/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "CommunityToolkit.Sample": { + "commandName": "DebugRoslynComponent", + "targetProject": "..\\..\\samples\\CommunityToolkit.Maui.Sample\\CommunityToolkit.Maui.Sample.csproj" + } + } +} \ No newline at end of file diff --git a/src/Analyzers/Toolkit.Maui.Analyzers/Resources.Designer.cs b/src/Analyzers/Toolkit.Maui.Analyzers/Resources.Designer.cs new file mode 100644 index 000000000..2d07920ab --- /dev/null +++ b/src/Analyzers/Toolkit.Maui.Analyzers/Resources.Designer.cs @@ -0,0 +1,90 @@ +//------------------------------------------------------------------------------ +// +// 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 Esri.ArcGISRuntime.Toolkit.Maui.Analyzers { + 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("Esri.ArcGISRuntime.Toolkit.Maui.Analyzers.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; + } + } + + /// + /// Looks up a localized string similar to `.UseArcGISToolkit()` must be chained to `.UseMauiApp<T>()`. + /// + internal static string InitalizationMessageFormat { + get { + return ResourceManager.GetString("InitalizationMessageFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to `.UseArcGISToolkit()` is required to initalize ArcGIS Runtime Toolkit for .NET MAUI.. + /// + internal static string InitializationErrorMessage { + get { + return ResourceManager.GetString("InitializationErrorMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to `.UseArcGISToolkit()` Not Found on MauiAppBuilder. + /// + internal static string InitializationErrorTitle { + get { + return ResourceManager.GetString("InitializationErrorTitle", resourceCulture); + } + } + } +} diff --git a/src/Analyzers/Toolkit.Maui.Analyzers/Resources.resx b/src/Analyzers/Toolkit.Maui.Analyzers/Resources.resx new file mode 100644 index 000000000..5e515455e --- /dev/null +++ b/src/Analyzers/Toolkit.Maui.Analyzers/Resources.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + `.UseArcGISToolkit()` must be chained to `.UseMauiApp<T>()` + + + `.UseArcGISToolkit()` is required to initalize ArcGIS Runtime Toolkit for .NET MAUI. + + + `.UseArcGISToolkit()` Not Found on MauiAppBuilder + + \ No newline at end of file diff --git a/src/Analyzers/Toolkit.Maui.Analyzers/UseToolkitInitializationAnalyzer.cs b/src/Analyzers/Toolkit.Maui.Analyzers/UseToolkitInitializationAnalyzer.cs new file mode 100644 index 000000000..e357b0930 --- /dev/null +++ b/src/Analyzers/Toolkit.Maui.Analyzers/UseToolkitInitializationAnalyzer.cs @@ -0,0 +1,88 @@ +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Esri.ArcGISRuntime.Toolkit.Maui.Analyzers; + +[DiagnosticAnalyzer(LanguageNames.CSharp)] +public class UseToolkitInitializationAnalyzer : DiagnosticAnalyzer +{ + public const string DiagnosticId = "AMT001"; + + const string category = "Initialization"; + + static readonly LocalizableString title = new LocalizableResourceString(nameof(Resources.InitializationErrorTitle), Resources.ResourceManager, typeof(Resources)); + static readonly LocalizableString messageFormat = new LocalizableResourceString(nameof(Resources.InitalizationMessageFormat), Resources.ResourceManager, typeof(Resources)); + static readonly LocalizableString description = new LocalizableResourceString(nameof(Resources.InitializationErrorMessage), Resources.ResourceManager, typeof(Resources)); + + static readonly DiagnosticDescriptor rule = new(DiagnosticId, title, messageFormat, category, DiagnosticSeverity.Error, isEnabledByDefault: true, description: description); + + public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(rule); + + public override void Initialize(AnalysisContext context) + { + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + context.EnableConcurrentExecution(); + context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.ExpressionStatement); + } + + static void AnalyzeNode(SyntaxNodeAnalysisContext context) + { + var expressionStatement = (ExpressionStatementSyntax)context.Node; + var root = expressionStatement.SyntaxTree.GetRoot(); + + if (HasUseArcGISToolkit(root)) + { + return; + } + + if (CheckIfItIsUseMauiMethod(expressionStatement)) + { + var expression = GetInvocationExpressionSyntax(expressionStatement); + var diagnostic = Diagnostic.Create(rule, expression.GetLocation()); + context.ReportDiagnostic(diagnostic); + } + } + + static bool CheckIfItIsUseMauiMethod(ExpressionStatementSyntax expressionStatement) => + expressionStatement.DescendantNodes() + .OfType() + .Any(x => x.Identifier.ValueText.Equals("UseMauiApp", StringComparison.Ordinal) + && x.TypeArgumentList.Arguments.Count is 1); + + static bool HasUseArcGISToolkit(SyntaxNode root) + { + foreach (var method in root.DescendantNodes().OfType()) + { + if (method.DescendantNodes().OfType().Any(x => x.DescendantNodes().Any(x => x.ToString().Contains(".UseArcGISToolkit(")))) + { + return true; + } + } + + return false; + } + + static InvocationExpressionSyntax GetInvocationExpressionSyntax(SyntaxNode parent) + { + foreach (var child in parent.ChildNodes()) + { + if (child is InvocationExpressionSyntax expressionSyntax) + { + return expressionSyntax; + } + else + { + var expression = GetInvocationExpressionSyntax(child); + + if (expression is not null) + { + return expression; + } + } + } + throw new InvalidOperationException("Wow, this shouldn't happen, please open a bug here: https://github.com/Esri/arcgis-maps-sdk-dotnet-toolkit/issues/new/choose"); + } +} \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 3f85bef49..5623b2ac3 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -27,9 +27,10 @@ $(MSBuildProjectName.Contains('.SampleApp.')) $(MSBuildProjectName.Contains('.Test')) $(MSBuildProjectDirectory.Contains('ProjectTemplates')) + $(MSBuildProjectDirectory.Contains('Analyzers')) - false - true + false + true diff --git a/src/Esri.ArcGISRuntime.Toolkit.sln b/src/Esri.ArcGISRuntime.Toolkit.sln index 6167c296b..d4cde5123 100644 --- a/src/Esri.ArcGISRuntime.Toolkit.sln +++ b/src/Esri.ArcGISRuntime.Toolkit.sln @@ -33,6 +33,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Toolkit.SampleApp.WinUI", " EndProject Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Esri.ArcGISRuntime.Toolkit.UI.Controls", "Toolkit\Toolkit.UI.Controls\Esri.ArcGISRuntime.Toolkit.UI.Controls.shproj", "{D9B86D10-7483-47EE-994E-9764FDB07B20}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Analyzers", "Analyzers", "{8BEEA12E-FC7C-4577-80D9-A2C4FDB76208}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Esri.ArcGISRuntime.Toolkit.Maui.Analyzers", "Analyzers\Toolkit.Maui.Analyzers\Esri.ArcGISRuntime.Toolkit.Maui.Analyzers.csproj", "{9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Esri.ArcGISRuntime.Toolkit.Maui.Analyzers.CodeFixes", "Analyzers\Toolkit.Maui.Analyzers.CodeFixes\Esri.ArcGISRuntime.Toolkit.Maui.Analyzers.CodeFixes.csproj", "{BF6231E6-1900-458B-8520-4B236CDBDB20}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Esri.ArcGISRuntime.Toolkit.Maui.Analyzers.UnitTests", "Analyzers\Toolkit.Maui.Analyzers.UnitTests\Esri.ArcGISRuntime.Toolkit.Maui.Analyzers.UnitTests.csproj", "{7A6C1C09-8CD6-4C8E-B866-248429B4848F}" +EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Esri.ArcGISRuntime.Toolkit.Analyzers.Test", "Analyzers\Toolkit.Analyzers.Test\Esri.ArcGISRuntime.Toolkit.Analyzers.Test.shproj", "{61FBC238-623C-42FF-8C47-95D710A1E66F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Ad-Hoc|Any CPU = Ad-Hoc|Any CPU @@ -436,6 +446,126 @@ Global {A2625DFB-69E8-4880-98CB-E2BF5FEA6B58}.Release|x86.ActiveCfg = Release|x86 {A2625DFB-69E8-4880-98CB-E2BF5FEA6B58}.Release|x86.Build.0 = Release|x86 {A2625DFB-69E8-4880-98CB-E2BF5FEA6B58}.Release|x86.Deploy.0 = Release|x86 + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Ad-Hoc|ARM64.ActiveCfg = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Ad-Hoc|ARM64.Build.0 = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.AppStore|ARM.Build.0 = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.AppStore|ARM64.ActiveCfg = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.AppStore|ARM64.Build.0 = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.AppStore|x64.ActiveCfg = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.AppStore|x64.Build.0 = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.AppStore|x86.ActiveCfg = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.AppStore|x86.Build.0 = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Debug|ARM.ActiveCfg = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Debug|ARM.Build.0 = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Debug|ARM64.Build.0 = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Debug|x64.ActiveCfg = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Debug|x64.Build.0 = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Debug|x86.ActiveCfg = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Debug|x86.Build.0 = Debug|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Release|Any CPU.Build.0 = Release|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Release|ARM.ActiveCfg = Release|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Release|ARM.Build.0 = Release|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Release|ARM64.ActiveCfg = Release|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Release|ARM64.Build.0 = Release|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Release|x64.ActiveCfg = Release|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Release|x64.Build.0 = Release|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Release|x86.ActiveCfg = Release|Any CPU + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA}.Release|x86.Build.0 = Release|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Ad-Hoc|ARM64.ActiveCfg = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Ad-Hoc|ARM64.Build.0 = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.AppStore|ARM.Build.0 = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.AppStore|ARM64.ActiveCfg = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.AppStore|ARM64.Build.0 = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.AppStore|x64.ActiveCfg = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.AppStore|x64.Build.0 = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.AppStore|x86.ActiveCfg = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.AppStore|x86.Build.0 = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Debug|ARM.ActiveCfg = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Debug|ARM.Build.0 = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Debug|ARM64.Build.0 = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Debug|x64.ActiveCfg = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Debug|x64.Build.0 = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Debug|x86.ActiveCfg = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Debug|x86.Build.0 = Debug|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Release|Any CPU.Build.0 = Release|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Release|ARM.ActiveCfg = Release|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Release|ARM.Build.0 = Release|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Release|ARM64.ActiveCfg = Release|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Release|ARM64.Build.0 = Release|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Release|x64.ActiveCfg = Release|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Release|x64.Build.0 = Release|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Release|x86.ActiveCfg = Release|Any CPU + {BF6231E6-1900-458B-8520-4B236CDBDB20}.Release|x86.Build.0 = Release|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Ad-Hoc|ARM64.ActiveCfg = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Ad-Hoc|ARM64.Build.0 = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.AppStore|ARM.Build.0 = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.AppStore|ARM64.ActiveCfg = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.AppStore|ARM64.Build.0 = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.AppStore|x64.ActiveCfg = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.AppStore|x64.Build.0 = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.AppStore|x86.ActiveCfg = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.AppStore|x86.Build.0 = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Debug|ARM.ActiveCfg = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Debug|ARM.Build.0 = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Debug|ARM64.Build.0 = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Debug|x64.ActiveCfg = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Debug|x64.Build.0 = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Debug|x86.ActiveCfg = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Debug|x86.Build.0 = Debug|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Release|Any CPU.Build.0 = Release|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Release|ARM.ActiveCfg = Release|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Release|ARM.Build.0 = Release|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Release|ARM64.ActiveCfg = Release|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Release|ARM64.Build.0 = Release|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Release|x64.ActiveCfg = Release|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Release|x64.Build.0 = Release|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Release|x86.ActiveCfg = Release|Any CPU + {7A6C1C09-8CD6-4C8E-B866-248429B4848F}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -451,6 +581,10 @@ Global {FE10E0C1-FFF3-4767-BD4A-D5C61B17C2C4} = {94D7A0A9-8C78-4E5E-9EAB-6C5D1CF0E8A0} {A2625DFB-69E8-4880-98CB-E2BF5FEA6B58} = {94D7A0A9-8C78-4E5E-9EAB-6C5D1CF0E8A0} {D9B86D10-7483-47EE-994E-9764FDB07B20} = {BD5B4F64-D32F-4DF3-B34D-070B7D526579} + {9ACB975A-FA7A-45FC-898B-ABC48BBE1ACA} = {8BEEA12E-FC7C-4577-80D9-A2C4FDB76208} + {BF6231E6-1900-458B-8520-4B236CDBDB20} = {8BEEA12E-FC7C-4577-80D9-A2C4FDB76208} + {7A6C1C09-8CD6-4C8E-B866-248429B4848F} = {8BEEA12E-FC7C-4577-80D9-A2C4FDB76208} + {61FBC238-623C-42FF-8C47-95D710A1E66F} = {8BEEA12E-FC7C-4577-80D9-A2C4FDB76208} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BD437263-1C96-46A9-A641-C312BF7DAF99} @@ -459,6 +593,8 @@ Global Toolkit\Toolkit.UI.Controls\Esri.ArcGISRuntime.Toolkit.UI.Controls.projitems*{531b2297-2343-4692-8d66-878b0ad158cd}*SharedItemsImports = 5 Toolkit\Toolkit\Esri.ArcGISRuntime.Toolkit.Shared.projitems*{531b2297-2343-4692-8d66-878b0ad158cd}*SharedItemsImports = 5 Toolkit\Toolkit\Esri.ArcGISRuntime.Toolkit.Shared.projitems*{5f3cad93-6062-450a-8771-7b4645caf598}*SharedItemsImports = 13 + Analyzers\Toolkit.Analyzers.Test\Esri.ArcGISRuntime.Toolkit.Analyzers.Test.projitems*{61fbc238-623c-42ff-8c47-95d710a1e66f}*SharedItemsImports = 13 + Analyzers\Toolkit.Analyzers.Test\Esri.ArcGISRuntime.Toolkit.Analyzers.Test.projitems*{7a6c1c09-8cd6-4c8e-b866-248429b4848f}*SharedItemsImports = 5 Toolkit\Toolkit.UI.Controls\Esri.ArcGISRuntime.Toolkit.UI.Controls.projitems*{a6431f30-a608-4c78-80be-548c322cbe75}*SharedItemsImports = 5 Toolkit\Toolkit\Esri.ArcGISRuntime.Toolkit.Shared.projitems*{a6431f30-a608-4c78-80be-548c322cbe75}*SharedItemsImports = 5 Toolkit\Toolkit.UI.Controls\Esri.ArcGISRuntime.Toolkit.UI.Controls.projitems*{bdb163a7-b221-4e9f-a960-92a849ba3f3f}*SharedItemsImports = 5 diff --git a/src/Toolkit/Toolkit.Maui/Esri.ArcGISRuntime.Toolkit.Maui.csproj b/src/Toolkit/Toolkit.Maui/Esri.ArcGISRuntime.Toolkit.Maui.csproj index 13c32caa3..ed08b0ed3 100644 --- a/src/Toolkit/Toolkit.Maui/Esri.ArcGISRuntime.Toolkit.Maui.csproj +++ b/src/Toolkit/Toolkit.Maui/Esri.ArcGISRuntime.Toolkit.Maui.csproj @@ -20,7 +20,7 @@ - + @@ -47,4 +47,19 @@ + + + $(TargetsForTfmSpecificContentInPackage);_AddAnalyzersToOutput + + + + + + + + + + + + diff --git a/src/Toolkit/Toolkit.Maui/tools/install.ps1 b/src/Toolkit/Toolkit.Maui/tools/install.ps1 new file mode 100644 index 000000000..f9bd7896a --- /dev/null +++ b/src/Toolkit/Toolkit.Maui/tools/install.ps1 @@ -0,0 +1,272 @@ +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 +# MIInugYJKoZIhvcNAQcCoIInqzCCJ6cCAQExDzANBglghkgBZQMEAgEFADB5Bgor +# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG +# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCA/i+qRUHsWzI0s +# FVk99zLgt/HOEQ33uvkFsWtHTHZgf6CCDYEwggX/MIID56ADAgECAhMzAAACUosz +# qviV8znbAAAAAAJSMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD +# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy +# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p +# bmcgUENBIDIwMTEwHhcNMjEwOTAyMTgzMjU5WhcNMjIwOTAxMTgzMjU5WjB0MQsw +# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u +# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy +# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +# AQDQ5M+Ps/X7BNuv5B/0I6uoDwj0NJOo1KrVQqO7ggRXccklyTrWL4xMShjIou2I +# sbYnF67wXzVAq5Om4oe+LfzSDOzjcb6ms00gBo0OQaqwQ1BijyJ7NvDf80I1fW9O +# L76Kt0Wpc2zrGhzcHdb7upPrvxvSNNUvxK3sgw7YTt31410vpEp8yfBEl/hd8ZzA +# v47DCgJ5j1zm295s1RVZHNp6MoiQFVOECm4AwK2l28i+YER1JO4IplTH44uvzX9o +# RnJHaMvWzZEpozPy4jNO2DDqbcNs4zh7AWMhE1PWFVA+CHI/En5nASvCvLmuR/t8 +# q4bc8XR8QIZJQSp+2U6m2ldNAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE +# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUNZJaEUGL2Guwt7ZOAu4efEYXedEw +# UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1 +# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDY3NTk3MB8GA1UdIwQYMBaAFEhu +# ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu +# bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w +# Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3 +# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx +# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAFkk3 +# uSxkTEBh1NtAl7BivIEsAWdgX1qZ+EdZMYbQKasY6IhSLXRMxF1B3OKdR9K/kccp +# kvNcGl8D7YyYS4mhCUMBR+VLrg3f8PUj38A9V5aiY2/Jok7WZFOAmjPRNNGnyeg7 +# l0lTiThFqE+2aOs6+heegqAdelGgNJKRHLWRuhGKuLIw5lkgx9Ky+QvZrn/Ddi8u +# TIgWKp+MGG8xY6PBvvjgt9jQShlnPrZ3UY8Bvwy6rynhXBaV0V0TTL0gEx7eh/K1 +# o8Miaru6s/7FyqOLeUS4vTHh9TgBL5DtxCYurXbSBVtL1Fj44+Od/6cmC9mmvrti +# yG709Y3Rd3YdJj2f3GJq7Y7KdWq0QYhatKhBeg4fxjhg0yut2g6aM1mxjNPrE48z +# 6HWCNGu9gMK5ZudldRw4a45Z06Aoktof0CqOyTErvq0YjoE4Xpa0+87T/PVUXNqf +# 7Y+qSU7+9LtLQuMYR4w3cSPjuNusvLf9gBnch5RqM7kaDtYWDgLyB42EfsxeMqwK +# WwA+TVi0HrWRqfSx2olbE56hJcEkMjOSKz3sRuupFCX3UroyYf52L+2iVTrda8XW +# esPG62Mnn3T8AuLfzeJFuAbfOSERx7IFZO92UPoXE1uEjL5skl1yTZB3MubgOA4F +# 8KoRNhviFAEST+nG8c8uIsbZeb08SeYQMqjVEmkwggd6MIIFYqADAgECAgphDpDS +# AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK +# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 +# IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0 +# ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla +# MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS +# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT +# H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB +# AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG +# OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S +# 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz +# y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7 +# 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u +# M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33 +# X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl +# XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP +# 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB +# l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF +# RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM +# CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ +# BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud +# DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO +# 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0 +# LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y +# Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p +# Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y +# Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB +# FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw +# cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA +# XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY +# 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj +# 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd +# d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ +# Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf +# wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ +# aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j +# NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B +# xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96 +# eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7 +# r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I +# RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIZjzCCGYsCAQEwgZUwfjELMAkG +# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx +# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z +# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAlKLM6r4lfM52wAAAAACUjAN +# BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor +# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgRjg7DcI6 +# uhYfXWwAQ6hK0mPW7iyr2tzHR0DHSDJkscIwQgYKKwYBBAGCNwIBDDE0MDKgFIAS +# AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN +# BgkqhkiG9w0BAQEFAASCAQB3ERGpqvGnJrsyU0d9lERK2TJW4/OONhZAFjxrEvEk +# PzdH0Fk0otvagAvjHzJ3q0G8C7gwRbXIyGgiYYIMefheNvgd/UKnubUGEzeG9h0/ +# biX5Ro1mxuHBYvc3vqvWD292jXMg00iRmexDsTny8YgSAAWsTdkE8/W2ooEfbG1T +# QkCg6ds9btpA1D1znVYpEbviCJoAfHLbNBr5nzAadgWjQM8nnb3UTvmLDIs5b1LO +# 3lm9w485IBFRnfrj6QinVsCbSD7PU/N1hPY7rKfM9ScZC6QT6kjyuVVa1Ft+VYLH +# qlV9hE6B4CGeB8qkko4x+MKovgbdpCgYz3eePWCakZywoYIXGTCCFxUGCisGAQQB +# gjcDAwExghcFMIIXAQYJKoZIhvcNAQcCoIIW8jCCFu4CAQMxDzANBglghkgBZQME +# AgEFADCCAVkGCyqGSIb3DQEJEAEEoIIBSASCAUQwggFAAgEBBgorBgEEAYRZCgMB +# MDEwDQYJYIZIAWUDBAIBBQAEIC58WTh4Q8r6c2kVXmD8xoHEhya2jc6YZ43KUAIy +# flB4AgZh/WKJ50gYEzIwMjIwMjExMTkwMzQwLjE1M1owBIACAfSggdikgdUwgdIx +# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt +# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1p +# Y3Jvc29mdCBJcmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEmMCQGA1UECxMdVGhh +# bGVzIFRTUyBFU046M0JENC00QjgwLTY5QzMxJTAjBgNVBAMTHE1pY3Jvc29mdCBU +# aW1lLVN0YW1wIFNlcnZpY2WgghFoMIIHFDCCBPygAwIBAgITMwAAAYm0v4YwhBxL +# jwABAAABiTANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMK +# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 +# IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0Eg +# MjAxMDAeFw0yMTEwMjgxOTI3NDFaFw0yMzAxMjYxOTI3NDFaMIHSMQswCQYDVQQG +# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG +# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQg +# SXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJjAkBgNVBAsTHVRoYWxlcyBUU1Mg +# RVNOOjNCRDQtNEI4MC02OUMzMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFt +# cCBTZXJ2aWNlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvQZXxZFm +# a6plmuOyvNpV8xONOwcYolZG/BjyZWGSk5JOGaLyrKId5VxVHWHlsmJE4Svnzsdp +# sKmVx8otONveIUFvSceEZp8VXmu5m1fu8L7c+3lwXcibjccqtEvtQslokQVx0r+L +# 54abrNDarwFG73IaRidIS1i9c+unJ8oYyhDRLrCysFAVxyQhPNZkWK7Z8/VGukaK +# LAWHXCh/+R53h42gFL+9/mAALxzCXXuofi8f/XKCm7xNwVc1hONCCz6oq94AufzV +# NkkIW4brUQgYpCcJm9U0XNmQvtropYDn9UtY8YQ0NKenXPtdgLHdQ8Nnv3igErKL +# rWI0a5n5jjdKfwk+8mvakqdZmlOseeOS1XspQNJAK1uZllAITcnQZOcO5ofjOQ33 +# ujWckAXdz+/x3o7l4AU/TSOMzGZMwhUdtVwC3dSbItpSVFgnjM2COEJ9zgCadvOi +# rGDLN471jZI2jClkjsJTdgPk343TQA4JFvds/unZq0uLr+niZ3X44OBx2x+gVlln +# 2c4UbZXNueA4yS1TJGbbJFIILAmTUA9Auj5eISGTbNiyWx79HnCOTar39QEKozm4 +# LnTmDXy0/KI/H/nYZGKuTHfckP28wQS06rD+fDS5xLwcRMCW92DkHXmtbhGyRilB +# OL5LxZelQfxt54wl4WUC0AdAEolPekODwO8CAwEAAaOCATYwggEyMB0GA1UdDgQW +# BBSXbx+zR1p4IIAeguA6rHKkrfl7UDAfBgNVHSMEGDAWgBSfpxVdAF5iXYP05dJl +# pxtTNRnpcjBfBgNVHR8EWDBWMFSgUqBQhk5odHRwOi8vd3d3Lm1pY3Jvc29mdC5j +# b20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIwMjAx +# MCgxKS5jcmwwbAYIKwYBBQUHAQEEYDBeMFwGCCsGAQUFBzAChlBodHRwOi8vd3d3 +# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMFRpbWUtU3Rh +# bXAlMjBQQ0ElMjAyMDEwKDEpLmNydDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoG +# CCsGAQUFBwMIMA0GCSqGSIb3DQEBCwUAA4ICAQCOtLdpWUI4KwfLLrfaKrLB92Dq +# bAspGWM41TaO4Jl+sHxPo522uu3GKQCjmkRWreHtlfyy9kOk7LWax3k3ke8Gtfet +# fbh7qH0LeV2XOWg39BOnHf6mTcZq7FYSZZch1JDQjc98+Odlow+oWih0Dbt4CV/e +# 19ZcE+1n1zzWkskUEd0f5jPIUis33p+vkY8szduAtCcIcPFUhI8Hb5alPUAPMjGz +# wKb7NIKbnf8j8cP18As5IveckF0oh1cw63RY/vPK62LDYdpi7WnG2ObvngfWVKtw +# iwTI4jHj2cO9q37HDe/PPl216gSpUZh0ap24mKmMDfcKp1N4mEdsxz4oseOrPYeF +# sHHWJFJ6Aivvqn70KTeJpp5r+DxSqbeSy0mxIUOq/lAaUxgNSQVUX26t8r+fciko +# fKv23WHrtRV3t7rVTsB9YzrRaiikmz68K5HWdt9MqULxPQPo+ppZ0LRqkOae466+ +# UKRY0JxWtdrMc5vHlHZfnqjawj/RsM2S6Q6fa9T9CnY1Nz7DYBG3yZJyCPFsrgU0 +# 5s9ljqfsSptpFdUh9R4ce+L71SWDLM2x/1MFLLHAMbXsEp8KloEGtaDULnxtfS2t +# YhfuKGqRXoEfDPAMnIdTvQPh3GHQ4SjkkBARHL0MY75alhGTKHWjC2aLVOo8obKI +# Bk8hfnFDUf/EyVw4uTCCB3EwggVZoAMCAQICEzMAAAAVxedrngKbSZkAAAAAABUw +# DQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5n +# dG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9y +# YXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmljYXRlIEF1dGhv +# cml0eSAyMDEwMB4XDTIxMDkzMDE4MjIyNVoXDTMwMDkzMDE4MzIyNVowfDELMAkG +# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx +# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9z +# b2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw +# ggIKAoICAQDk4aZM57RyIQt5osvXJHm9DtWC0/3unAcH0qlsTnXIyjVX9gF/bErg +# 4r25PhdgM/9cT8dm95VTcVrifkpa/rg2Z4VGIwy1jRPPdzLAEBjoYH1qUoNEt6aO +# RmsHFPPFdvWGUNzBRMhxXFExN6AKOG6N7dcP2CZTfDlhAnrEqv1yaa8dq6z2Nr41 +# JmTamDu6GnszrYBbfowQHJ1S/rboYiXcag/PXfT+jlPP1uyFVk3v3byNpOORj7I5 +# LFGc6XBpDco2LXCOMcg1KL3jtIckw+DJj361VI/c+gVVmG1oO5pGve2krnopN6zL +# 64NF50ZuyjLVwIYwXE8s4mKyzbnijYjklqwBSru+cakXW2dg3viSkR4dPf0gz3N9 +# QZpGdc3EXzTdEonW/aUgfX782Z5F37ZyL9t9X4C626p+Nuw2TPYrbqgSUei/BQOj +# 0XOmTTd0lBw0gg/wEPK3Rxjtp+iZfD9M269ewvPV2HM9Q07BMzlMjgK8QmguEOqE +# UUbi0b1qGFphAXPKZ6Je1yh2AuIzGHLXpyDwwvoSCtdjbwzJNmSLW6CmgyFdXzB0 +# kZSU2LlQ+QuJYfM2BjUYhEfb3BvR/bLUHMVr9lxSUV0S2yW6r1AFemzFER1y7435 +# UsSFF5PAPBXbGjfHCBUYP3irRbb1Hode2o+eFnJpxq57t7c+auIurQIDAQABo4IB +# 3TCCAdkwEgYJKwYBBAGCNxUBBAUCAwEAATAjBgkrBgEEAYI3FQIEFgQUKqdS/mTE +# mr6CkTxGNSnPEP8vBO4wHQYDVR0OBBYEFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMFwG +# A1UdIARVMFMwUQYMKwYBBAGCN0yDfQEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93 +# d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0bTATBgNV +# HSUEDDAKBggrBgEFBQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNV +# HQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo +# 0T2UkFvXzpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29m +# dC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5j +# cmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jv +# c29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDAN +# BgkqhkiG9w0BAQsFAAOCAgEAnVV9/Cqt4SwfZwExJFvhnnJL/Klv6lwUtj5OR2R4 +# sQaTlz0xM7U518JxNj/aZGx80HU5bbsPMeTCj/ts0aGUGCLu6WZnOlNN3Zi6th54 +# 2DYunKmCVgADsAW+iehp4LoJ7nvfam++Kctu2D9IdQHZGN5tggz1bSNU5HhTdSRX +# ud2f8449xvNo32X2pFaq95W2KFUn0CS9QKC/GbYSEhFdPSfgQJY4rPf5KYnDvBew +# VIVCs/wMnosZiefwC2qBwoEZQhlSdYo2wh3DYXMuLGt7bj8sCXgU6ZGyqVvfSaN0 +# DLzskYDSPeZKPmY7T7uG+jIa2Zb0j/aRAfbOxnT99kxybxCrdTDFNLB62FD+Cljd +# QDzHVG2dY3RILLFORy3BFARxv2T5JL5zbcqOCb2zAVdJVGTZc9d/HltEAY5aGZFr +# DZ+kKNxnGSgkujhLmm77IVRrakURR6nxt67I6IleT53S0Ex2tVdUCbFpAUR+fKFh +# bHP+CrvsQWY9af3LwUFJfn6Tvsv4O+S3Fb+0zj6lMVGEvL8CwYKiexcdFYmNcP7n +# tdAoGokLjzbaukz5m/8K6TT4JDVnK+ANuOaMmdbhIurwJ0I9JZTmdHRbatGePu1+ +# oDEzfbzL6Xu/OHBE0ZDxyKs6ijoIYn/ZcGNTTY3ugm2lBRDBcQZqELQdVTNYs6Fw +# ZvKhggLXMIICQAIBATCCAQChgdikgdUwgdIxCzAJBgNVBAYTAlVTMRMwEQYDVQQI +# EwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv +# ZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh +# dGlvbnMgTGltaXRlZDEmMCQGA1UECxMdVGhhbGVzIFRTUyBFU046M0JENC00Qjgw +# LTY5QzMxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2WiIwoB +# ATAHBgUrDgMCGgMVACGlCa3ketyeuey7bJNpWkMuiCcQoIGDMIGApH4wfDELMAkG +# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx +# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9z +# b2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwDQYJKoZIhvcNAQEFBQACBQDlsRtBMCIY +# DzIwMjIwMjEyMDEyODMzWhgPMjAyMjAyMTMwMTI4MzNaMHcwPQYKKwYBBAGEWQoE +# ATEvMC0wCgIFAOWxG0ECAQAwCgIBAAICDbMCAf8wBwIBAAICEW8wCgIFAOWybMEC +# AQAwNgYKKwYBBAGEWQoEAjEoMCYwDAYKKwYBBAGEWQoDAqAKMAgCAQACAwehIKEK +# MAgCAQACAwGGoDANBgkqhkiG9w0BAQUFAAOBgQCImCpEJ2AlAWBBkDABmkqIh1kM +# LPDyea3b7evhOk+YSwXCzxnBIXuppujFT3tnk7w0p0a5YS9uwqbDM/M6rAUMBAR0 +# boHamumEITNF5nVh0rlYyRZQ3WraVD2YPhouUINQavmS8ueYoh6r3HeM9QPBAnNB +# vv7GDrZ637+2Dfe60jGCBA0wggQJAgEBMIGTMHwxCzAJBgNVBAYTAlVTMRMwEQYD +# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy +# b3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1w +# IFBDQSAyMDEwAhMzAAABibS/hjCEHEuPAAEAAAGJMA0GCWCGSAFlAwQCAQUAoIIB +# SjAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwLwYJKoZIhvcNAQkEMSIEIL86 +# iebNndOm+CAgIp67s6y+HI1wHdhaMPILGf48RtXXMIH6BgsqhkiG9w0BCRACLzGB +# 6jCB5zCB5DCBvQQgZndHMdxQV1VsbpWHOTHqWEycvcRJm7cY69l/UmT8j0UwgZgw +# gYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE +# BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYD +# VQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAAYm0v4YwhBxL +# jwABAAABiTAiBCDET+l3keOFFxaIqOZWSSuWNO774Ng/t5pe3p4QXoKcvjANBgkq +# hkiG9w0BAQsFAASCAgADYrNFej7RbihwGcC0jF+cTik+HJog++dPEDXeIyBB+2pw +# 23hC5KaX9H05ZknluIq2oxf2MLpKL+gA+76T3k5PnzPNJFDogUn5eFIIsMRpNF0h +# MtPWoPJWYFK2odvKz1HwsuqHRg6hO//NwORcv4xPeAWEFO5+DOXzZKKp/BVDGe/D +# c++y9/l41qpz/F2c3a1lugdqnZz7ZeoaQ8/JMlwrmMbciqcAytCn9A59EWJ1xYd/ +# DaDhQ5Rd8hkcckuxJksjWf6URmc91cb4Jdatkyupq3dDGwCkjGNd2xetrOpqMLOZ +# quoDONSgc9rGrhkf3xgKKVRhLg9bxd3f2oQ0IsOBg2AC5td1eqp6TILc0gei2E3I +# uEAW1d+KXDnajvQmvQkaFHr5wEocTTLgrDglOPPhEaEumSTJS7jKFzUKHiBU005p +# CgQ1So2WJ2RqFx0ppez1N1AFczOVLFllK3WGPLkDsN1GgT0nFfoqvs1WKkzyb2d2 +# /v6PVER9xGky7LCu62dhsJCAFUbxF2dJxaC5ofrl98VaO/z72J9on9BTz+eCtcJ9 +# rDIpqktGeL02f6+4zctFCyi2wgm6eh8kKvRlAPmN4/MNt9pWHtEV//xFGzGeDajr +# diRhDoMZwsuon4QwS8b2YcKMoZ6gZ2lZah3960fTTmvBTBNqeBtR94KWCy0C0A== +# SIG # End signature block diff --git a/src/Toolkit/Toolkit.Maui/tools/uninstall.ps1 b/src/Toolkit/Toolkit.Maui/tools/uninstall.ps1 new file mode 100644 index 000000000..17fd92001 --- /dev/null +++ b/src/Toolkit/Toolkit.Maui/tools/uninstall.ps1 @@ -0,0 +1,279 @@ +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 +# MIInugYJKoZIhvcNAQcCoIInqzCCJ6cCAQExDzANBglghkgBZQMEAgEFADB5Bgor +# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG +# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDC68wb97fg0QGL +# yXrxJhYfmibzcOh8caqC0uZprfczDaCCDYEwggX/MIID56ADAgECAhMzAAACUosz +# qviV8znbAAAAAAJSMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD +# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy +# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p +# bmcgUENBIDIwMTEwHhcNMjEwOTAyMTgzMjU5WhcNMjIwOTAxMTgzMjU5WjB0MQsw +# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u +# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy +# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +# AQDQ5M+Ps/X7BNuv5B/0I6uoDwj0NJOo1KrVQqO7ggRXccklyTrWL4xMShjIou2I +# sbYnF67wXzVAq5Om4oe+LfzSDOzjcb6ms00gBo0OQaqwQ1BijyJ7NvDf80I1fW9O +# L76Kt0Wpc2zrGhzcHdb7upPrvxvSNNUvxK3sgw7YTt31410vpEp8yfBEl/hd8ZzA +# v47DCgJ5j1zm295s1RVZHNp6MoiQFVOECm4AwK2l28i+YER1JO4IplTH44uvzX9o +# RnJHaMvWzZEpozPy4jNO2DDqbcNs4zh7AWMhE1PWFVA+CHI/En5nASvCvLmuR/t8 +# q4bc8XR8QIZJQSp+2U6m2ldNAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE +# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUNZJaEUGL2Guwt7ZOAu4efEYXedEw +# UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1 +# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDY3NTk3MB8GA1UdIwQYMBaAFEhu +# ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu +# bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w +# Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3 +# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx +# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAFkk3 +# uSxkTEBh1NtAl7BivIEsAWdgX1qZ+EdZMYbQKasY6IhSLXRMxF1B3OKdR9K/kccp +# kvNcGl8D7YyYS4mhCUMBR+VLrg3f8PUj38A9V5aiY2/Jok7WZFOAmjPRNNGnyeg7 +# l0lTiThFqE+2aOs6+heegqAdelGgNJKRHLWRuhGKuLIw5lkgx9Ky+QvZrn/Ddi8u +# TIgWKp+MGG8xY6PBvvjgt9jQShlnPrZ3UY8Bvwy6rynhXBaV0V0TTL0gEx7eh/K1 +# o8Miaru6s/7FyqOLeUS4vTHh9TgBL5DtxCYurXbSBVtL1Fj44+Od/6cmC9mmvrti +# yG709Y3Rd3YdJj2f3GJq7Y7KdWq0QYhatKhBeg4fxjhg0yut2g6aM1mxjNPrE48z +# 6HWCNGu9gMK5ZudldRw4a45Z06Aoktof0CqOyTErvq0YjoE4Xpa0+87T/PVUXNqf +# 7Y+qSU7+9LtLQuMYR4w3cSPjuNusvLf9gBnch5RqM7kaDtYWDgLyB42EfsxeMqwK +# WwA+TVi0HrWRqfSx2olbE56hJcEkMjOSKz3sRuupFCX3UroyYf52L+2iVTrda8XW +# esPG62Mnn3T8AuLfzeJFuAbfOSERx7IFZO92UPoXE1uEjL5skl1yTZB3MubgOA4F +# 8KoRNhviFAEST+nG8c8uIsbZeb08SeYQMqjVEmkwggd6MIIFYqADAgECAgphDpDS +# AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK +# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 +# IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0 +# ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla +# MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS +# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT +# H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB +# AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG +# OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S +# 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz +# y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7 +# 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u +# M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33 +# X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl +# XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP +# 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB +# l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF +# RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM +# CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ +# BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud +# DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO +# 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0 +# LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y +# Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p +# Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y +# Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB +# FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw +# cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA +# XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY +# 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj +# 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd +# d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ +# Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf +# wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ +# aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j +# NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B +# xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96 +# eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7 +# r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I +# RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIZjzCCGYsCAQEwgZUwfjELMAkG +# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx +# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z +# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAlKLM6r4lfM52wAAAAACUjAN +# BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor +# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgF1ypFyzl +# AvvWGVCeXczrfpXmJNm9vpyjcwd4y4ivfqowQgYKKwYBBAGCNwIBDDE0MDKgFIAS +# AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN +# BgkqhkiG9w0BAQEFAASCAQAvi2rSDkhC82RJ4uqq/0WbHkOkzq1hrF6HxneBTNj8 +# KX+niFtee3CYVfWaSAQ6xvOiLupRX3fsSfhabRQ+Jl8k28voGrTK1OC906OO3tUN +# jdmv1PooWdxJNt2EbzQrap5Ui9KTUv4mJ4c836HAVMBPCJiq5NwmzAHfbgBxCaYq +# +hupIf+gk8vuNB1bltILgNmU/smJt9OuGqSo5TrFajzb+35SqjnCz9JtAtbPNZvA +# X9N37UPhITOecceAQmrHiEPbA7eu6VDp6VPjPfCEO7a+frWa83chEd4qzyou9xu5 +# 3gnj7Ro8nFDnGyUe0+0oCaYGXO9fbIMN1HG2IZg5suj5oYIXGTCCFxUGCisGAQQB +# gjcDAwExghcFMIIXAQYJKoZIhvcNAQcCoIIW8jCCFu4CAQMxDzANBglghkgBZQME +# AgEFADCCAVkGCyqGSIb3DQEJEAEEoIIBSASCAUQwggFAAgEBBgorBgEEAYRZCgMB +# MDEwDQYJYIZIAWUDBAIBBQAEIH+XBTHuyyHZnIXrFWIe64WLvHx5GUFMCM6A56T1 +# KwBtAgZh/WKJ52UYEzIwMjIwMjExMTkwMzQwLjU0OFowBIACAfSggdikgdUwgdIx +# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt +# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1p +# Y3Jvc29mdCBJcmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEmMCQGA1UECxMdVGhh +# bGVzIFRTUyBFU046M0JENC00QjgwLTY5QzMxJTAjBgNVBAMTHE1pY3Jvc29mdCBU +# aW1lLVN0YW1wIFNlcnZpY2WgghFoMIIHFDCCBPygAwIBAgITMwAAAYm0v4YwhBxL +# jwABAAABiTANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMK +# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 +# IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0Eg +# MjAxMDAeFw0yMTEwMjgxOTI3NDFaFw0yMzAxMjYxOTI3NDFaMIHSMQswCQYDVQQG +# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG +# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQg +# SXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJjAkBgNVBAsTHVRoYWxlcyBUU1Mg +# RVNOOjNCRDQtNEI4MC02OUMzMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFt +# cCBTZXJ2aWNlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvQZXxZFm +# a6plmuOyvNpV8xONOwcYolZG/BjyZWGSk5JOGaLyrKId5VxVHWHlsmJE4Svnzsdp +# sKmVx8otONveIUFvSceEZp8VXmu5m1fu8L7c+3lwXcibjccqtEvtQslokQVx0r+L +# 54abrNDarwFG73IaRidIS1i9c+unJ8oYyhDRLrCysFAVxyQhPNZkWK7Z8/VGukaK +# LAWHXCh/+R53h42gFL+9/mAALxzCXXuofi8f/XKCm7xNwVc1hONCCz6oq94AufzV +# NkkIW4brUQgYpCcJm9U0XNmQvtropYDn9UtY8YQ0NKenXPtdgLHdQ8Nnv3igErKL +# rWI0a5n5jjdKfwk+8mvakqdZmlOseeOS1XspQNJAK1uZllAITcnQZOcO5ofjOQ33 +# ujWckAXdz+/x3o7l4AU/TSOMzGZMwhUdtVwC3dSbItpSVFgnjM2COEJ9zgCadvOi +# rGDLN471jZI2jClkjsJTdgPk343TQA4JFvds/unZq0uLr+niZ3X44OBx2x+gVlln +# 2c4UbZXNueA4yS1TJGbbJFIILAmTUA9Auj5eISGTbNiyWx79HnCOTar39QEKozm4 +# LnTmDXy0/KI/H/nYZGKuTHfckP28wQS06rD+fDS5xLwcRMCW92DkHXmtbhGyRilB +# OL5LxZelQfxt54wl4WUC0AdAEolPekODwO8CAwEAAaOCATYwggEyMB0GA1UdDgQW +# BBSXbx+zR1p4IIAeguA6rHKkrfl7UDAfBgNVHSMEGDAWgBSfpxVdAF5iXYP05dJl +# pxtTNRnpcjBfBgNVHR8EWDBWMFSgUqBQhk5odHRwOi8vd3d3Lm1pY3Jvc29mdC5j +# b20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIwMjAx +# MCgxKS5jcmwwbAYIKwYBBQUHAQEEYDBeMFwGCCsGAQUFBzAChlBodHRwOi8vd3d3 +# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMFRpbWUtU3Rh +# bXAlMjBQQ0ElMjAyMDEwKDEpLmNydDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoG +# CCsGAQUFBwMIMA0GCSqGSIb3DQEBCwUAA4ICAQCOtLdpWUI4KwfLLrfaKrLB92Dq +# bAspGWM41TaO4Jl+sHxPo522uu3GKQCjmkRWreHtlfyy9kOk7LWax3k3ke8Gtfet +# fbh7qH0LeV2XOWg39BOnHf6mTcZq7FYSZZch1JDQjc98+Odlow+oWih0Dbt4CV/e +# 19ZcE+1n1zzWkskUEd0f5jPIUis33p+vkY8szduAtCcIcPFUhI8Hb5alPUAPMjGz +# wKb7NIKbnf8j8cP18As5IveckF0oh1cw63RY/vPK62LDYdpi7WnG2ObvngfWVKtw +# iwTI4jHj2cO9q37HDe/PPl216gSpUZh0ap24mKmMDfcKp1N4mEdsxz4oseOrPYeF +# sHHWJFJ6Aivvqn70KTeJpp5r+DxSqbeSy0mxIUOq/lAaUxgNSQVUX26t8r+fciko +# fKv23WHrtRV3t7rVTsB9YzrRaiikmz68K5HWdt9MqULxPQPo+ppZ0LRqkOae466+ +# UKRY0JxWtdrMc5vHlHZfnqjawj/RsM2S6Q6fa9T9CnY1Nz7DYBG3yZJyCPFsrgU0 +# 5s9ljqfsSptpFdUh9R4ce+L71SWDLM2x/1MFLLHAMbXsEp8KloEGtaDULnxtfS2t +# YhfuKGqRXoEfDPAMnIdTvQPh3GHQ4SjkkBARHL0MY75alhGTKHWjC2aLVOo8obKI +# Bk8hfnFDUf/EyVw4uTCCB3EwggVZoAMCAQICEzMAAAAVxedrngKbSZkAAAAAABUw +# DQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5n +# dG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9y +# YXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmljYXRlIEF1dGhv +# cml0eSAyMDEwMB4XDTIxMDkzMDE4MjIyNVoXDTMwMDkzMDE4MzIyNVowfDELMAkG +# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx +# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9z +# b2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw +# ggIKAoICAQDk4aZM57RyIQt5osvXJHm9DtWC0/3unAcH0qlsTnXIyjVX9gF/bErg +# 4r25PhdgM/9cT8dm95VTcVrifkpa/rg2Z4VGIwy1jRPPdzLAEBjoYH1qUoNEt6aO +# RmsHFPPFdvWGUNzBRMhxXFExN6AKOG6N7dcP2CZTfDlhAnrEqv1yaa8dq6z2Nr41 +# JmTamDu6GnszrYBbfowQHJ1S/rboYiXcag/PXfT+jlPP1uyFVk3v3byNpOORj7I5 +# LFGc6XBpDco2LXCOMcg1KL3jtIckw+DJj361VI/c+gVVmG1oO5pGve2krnopN6zL +# 64NF50ZuyjLVwIYwXE8s4mKyzbnijYjklqwBSru+cakXW2dg3viSkR4dPf0gz3N9 +# QZpGdc3EXzTdEonW/aUgfX782Z5F37ZyL9t9X4C626p+Nuw2TPYrbqgSUei/BQOj +# 0XOmTTd0lBw0gg/wEPK3Rxjtp+iZfD9M269ewvPV2HM9Q07BMzlMjgK8QmguEOqE +# UUbi0b1qGFphAXPKZ6Je1yh2AuIzGHLXpyDwwvoSCtdjbwzJNmSLW6CmgyFdXzB0 +# kZSU2LlQ+QuJYfM2BjUYhEfb3BvR/bLUHMVr9lxSUV0S2yW6r1AFemzFER1y7435 +# UsSFF5PAPBXbGjfHCBUYP3irRbb1Hode2o+eFnJpxq57t7c+auIurQIDAQABo4IB +# 3TCCAdkwEgYJKwYBBAGCNxUBBAUCAwEAATAjBgkrBgEEAYI3FQIEFgQUKqdS/mTE +# mr6CkTxGNSnPEP8vBO4wHQYDVR0OBBYEFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMFwG +# A1UdIARVMFMwUQYMKwYBBAGCN0yDfQEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93 +# d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0bTATBgNV +# HSUEDDAKBggrBgEFBQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNV +# HQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo +# 0T2UkFvXzpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29m +# dC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5j +# cmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jv +# c29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDAN +# BgkqhkiG9w0BAQsFAAOCAgEAnVV9/Cqt4SwfZwExJFvhnnJL/Klv6lwUtj5OR2R4 +# sQaTlz0xM7U518JxNj/aZGx80HU5bbsPMeTCj/ts0aGUGCLu6WZnOlNN3Zi6th54 +# 2DYunKmCVgADsAW+iehp4LoJ7nvfam++Kctu2D9IdQHZGN5tggz1bSNU5HhTdSRX +# ud2f8449xvNo32X2pFaq95W2KFUn0CS9QKC/GbYSEhFdPSfgQJY4rPf5KYnDvBew +# VIVCs/wMnosZiefwC2qBwoEZQhlSdYo2wh3DYXMuLGt7bj8sCXgU6ZGyqVvfSaN0 +# DLzskYDSPeZKPmY7T7uG+jIa2Zb0j/aRAfbOxnT99kxybxCrdTDFNLB62FD+Cljd +# QDzHVG2dY3RILLFORy3BFARxv2T5JL5zbcqOCb2zAVdJVGTZc9d/HltEAY5aGZFr +# DZ+kKNxnGSgkujhLmm77IVRrakURR6nxt67I6IleT53S0Ex2tVdUCbFpAUR+fKFh +# bHP+CrvsQWY9af3LwUFJfn6Tvsv4O+S3Fb+0zj6lMVGEvL8CwYKiexcdFYmNcP7n +# tdAoGokLjzbaukz5m/8K6TT4JDVnK+ANuOaMmdbhIurwJ0I9JZTmdHRbatGePu1+ +# oDEzfbzL6Xu/OHBE0ZDxyKs6ijoIYn/ZcGNTTY3ugm2lBRDBcQZqELQdVTNYs6Fw +# ZvKhggLXMIICQAIBATCCAQChgdikgdUwgdIxCzAJBgNVBAYTAlVTMRMwEQYDVQQI +# EwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv +# ZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh +# dGlvbnMgTGltaXRlZDEmMCQGA1UECxMdVGhhbGVzIFRTUyBFU046M0JENC00Qjgw +# LTY5QzMxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2WiIwoB +# ATAHBgUrDgMCGgMVACGlCa3ketyeuey7bJNpWkMuiCcQoIGDMIGApH4wfDELMAkG +# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx +# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9z +# b2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwDQYJKoZIhvcNAQEFBQACBQDlsRtBMCIY +# DzIwMjIwMjEyMDEyODMzWhgPMjAyMjAyMTMwMTI4MzNaMHcwPQYKKwYBBAGEWQoE +# ATEvMC0wCgIFAOWxG0ECAQAwCgIBAAICDbMCAf8wBwIBAAICEW8wCgIFAOWybMEC +# AQAwNgYKKwYBBAGEWQoEAjEoMCYwDAYKKwYBBAGEWQoDAqAKMAgCAQACAwehIKEK +# MAgCAQACAwGGoDANBgkqhkiG9w0BAQUFAAOBgQCImCpEJ2AlAWBBkDABmkqIh1kM +# LPDyea3b7evhOk+YSwXCzxnBIXuppujFT3tnk7w0p0a5YS9uwqbDM/M6rAUMBAR0 +# boHamumEITNF5nVh0rlYyRZQ3WraVD2YPhouUINQavmS8ueYoh6r3HeM9QPBAnNB +# vv7GDrZ637+2Dfe60jGCBA0wggQJAgEBMIGTMHwxCzAJBgNVBAYTAlVTMRMwEQYD +# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy +# b3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1w +# IFBDQSAyMDEwAhMzAAABibS/hjCEHEuPAAEAAAGJMA0GCWCGSAFlAwQCAQUAoIIB +# SjAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwLwYJKoZIhvcNAQkEMSIEIKY2 +# Onyhltfi0+oc/UMKaXc0H6Ckw2gGK1/qmjRZNiXnMIH6BgsqhkiG9w0BCRACLzGB +# 6jCB5zCB5DCBvQQgZndHMdxQV1VsbpWHOTHqWEycvcRJm7cY69l/UmT8j0UwgZgw +# gYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE +# BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYD +# VQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAAYm0v4YwhBxL +# jwABAAABiTAiBCDET+l3keOFFxaIqOZWSSuWNO774Ng/t5pe3p4QXoKcvjANBgkq +# hkiG9w0BAQsFAASCAgB7AQ0Dv3muHoNAt+cccMfYk23lHgh8LGBitCSFwu0q7ufv +# sXkoaIpwW0U0GikWhQoCH0U38SuzVbafg49FiE6ftkjOtiE03PwPYi1S6NSoDdaV +# kUuvjz3OcuN1IHg3CyLn2dO8xbUlWCUfgoWhI1nax9ch7wT4Sw8RdmGKdYTZoZmq +# vPXFRtDyZdmJDMDbTql/Brye8oEsDMoYKMmEYhY1t9TlusnWfUbxuBnyMqg/FkBy +# QF78WFfT8mygMqUGmINxPGT6daxqmq3nfAC2vOtLT4DplNYMEymfDceJzBhb8VCT +# UHc2CWK0qKT+eqwn30NBkwh//8aNHlXaA9Yq/9k2y+axIGdxFfG+X0stipRRpEXb +# xCFm7FPD5/S4ddBH829yEZLZ4XTwSZ6YS/d3mFzu5rgZl3UhjOJPXx40GQtUiDP4 +# XQZ/wW3154X/KtTypv62/Hl+CiMUrsO7MXtgwClfbJ3osg+zlpJgdraetVgmAUc1 +# mjz2GCYX7rIliGkAJREKn4rV2MZzuGLEpTjz9dB+1Xp9Ndi9q3jQgs6k3IDIUube +# YjPFFuPmFWRyi6oPTXmc4ExtTIewPvrOhwQ5q4ysxylkXoTS+UQt94BY2SvR+TMu +# 6doU+0Y73xsO8Zz+lREh3fjBsDbPAgOV5989X6bmkJEEIwIK8LYgqvyED8XXTg== +# SIG # End signature block From 5a3260c89ffc652b921221f517e53e58c9a0d73d Mon Sep 17 00:00:00 2001 From: Morten Nielsen Date: Wed, 28 Feb 2024 08:03:32 -0800 Subject: [PATCH 2/5] Add xmlns prefix to Maui toolkit --- src/Toolkit/Toolkit.Maui/AssemblyInfo.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Toolkit/Toolkit.Maui/AssemblyInfo.cs b/src/Toolkit/Toolkit.Maui/AssemblyInfo.cs index 92fdc5787..b7d853e28 100644 --- a/src/Toolkit/Toolkit.Maui/AssemblyInfo.cs +++ b/src/Toolkit/Toolkit.Maui/AssemblyInfo.cs @@ -5,3 +5,6 @@ [assembly: System.Runtime.Versioning.SupportedOSPlatform("ios14.0")] [assembly: System.Runtime.Versioning.SupportedOSPlatform("maccatalyst14.0")] #endif + +[assembly: Microsoft.Maui.Controls.XmlnsPrefix("http://schemas.esri.com/arcgis/runtime/2013", "esri")] +[assembly: XmlnsDefinition("http://schemas.esri.com/arcgis/runtime/2013", "Esri.ArcGISRuntime.Toolkit.Maui")] From 90e1532c0a6a8c69972f6846f90006d6cc2df894 Mon Sep 17 00:00:00 2001 From: Morten Nielsen Date: Thu, 7 Mar 2024 12:27:31 -0800 Subject: [PATCH 3/5] Delete src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/Properties/launchSettings.json --- .../Properties/launchSettings.json | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/Properties/launchSettings.json diff --git a/src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/Properties/launchSettings.json b/src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/Properties/launchSettings.json deleted file mode 100644 index b453e5d2a..000000000 --- a/src/Analyzers/Toolkit.Maui.Analyzers.CodeFixes/Properties/launchSettings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "profiles": { - "CommunityToolkit.Maui.Sample": { - "commandName": "DebugRoslynComponent", - "targetProject": "..\\..\\samples\\CommunityToolkit.Maui.Sample\\CommunityToolkit.Maui.Sample.csproj" - } - } -} \ No newline at end of file From 765317feb809a55982e6e748c4256c2362da97f8 Mon Sep 17 00:00:00 2001 From: Morten Nielsen Date: Thu, 7 Mar 2024 12:28:26 -0800 Subject: [PATCH 4/5] Delete src/Analyzers/Toolkit.Maui.Analyzers/Properties/launchSettings.json --- .../Toolkit.Maui.Analyzers/Properties/launchSettings.json | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 src/Analyzers/Toolkit.Maui.Analyzers/Properties/launchSettings.json diff --git a/src/Analyzers/Toolkit.Maui.Analyzers/Properties/launchSettings.json b/src/Analyzers/Toolkit.Maui.Analyzers/Properties/launchSettings.json deleted file mode 100644 index 1a3eee2de..000000000 --- a/src/Analyzers/Toolkit.Maui.Analyzers/Properties/launchSettings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "profiles": { - "CommunityToolkit.Sample": { - "commandName": "DebugRoslynComponent", - "targetProject": "..\\..\\samples\\CommunityToolkit.Maui.Sample\\CommunityToolkit.Maui.Sample.csproj" - } - } -} \ No newline at end of file From bb7e2800c49a81765fdd72c1091087c6a8130d6f Mon Sep 17 00:00:00 2001 From: dotMorten Date: Mon, 25 Mar 2024 10:23:13 -0700 Subject: [PATCH 5/5] Fix analyzer warnings and update warning message --- .../UseToolkitInitializationAnalyzerTests.cs | 8 ++++---- .../Toolkit.Maui.Analyzers/AnalyzerReleases.Shipped.md | 6 +++--- .../Toolkit.Maui.Analyzers/AnalyzerReleases.Unshipped.md | 8 +++----- .../UseToolkitInitializationAnalyzer.cs | 2 +- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/Analyzers/Toolkit.Maui.Analyzers.UnitTests/UseToolkitInitializationAnalyzerTests.cs b/src/Analyzers/Toolkit.Maui.Analyzers.UnitTests/UseToolkitInitializationAnalyzerTests.cs index c0d25f61d..3d2d5666a 100644 --- a/src/Analyzers/Toolkit.Maui.Analyzers.UnitTests/UseToolkitInitializationAnalyzerTests.cs +++ b/src/Analyzers/Toolkit.Maui.Analyzers.UnitTests/UseToolkitInitializationAnalyzerTests.cs @@ -12,7 +12,7 @@ public class UseToolkitInitializationAnalyzerTests : BaseAnalyzersUnitTest