diff --git a/Configuration.props b/Configuration.props index 34cd72852..42a55c6d3 100644 --- a/Configuration.props +++ b/Configuration.props @@ -69,6 +69,7 @@ $(BuildOutputDirectory)lib\packs\Microsoft.Android.Runtime.$(AndroidApiLevel).android-x64\$(AndroidPackVersion)\runtimes\android-x64\ $(BuildOutputDirectory)lib\packs\$(MicrosoftAndroidSdkPackName)\$(AndroidPackVersion)\ $(MicrosoftAndroidSdkPackDir)\tools\ + $(BuildOutputDirectory)lib\packs\Microsoft.Android.Ref.$(AndroidApiLevel)\$(AndroidPackVersion)\analyzers\dotnet\cs\ -j$(HostCpuCount) mono --debug=casts diff --git a/Xamarin.Android.Build.Tasks.sln b/Xamarin.Android.Build.Tasks.sln index 29fa734d9..4dbf9a5aa 100644 --- a/Xamarin.Android.Build.Tasks.sln +++ b/Xamarin.Android.Build.Tasks.sln @@ -25,6 +25,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Android.Build.Bas EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Xamarin.Android.Tools.AndroidSdk", "external\xamarin-android-tools\src\Xamarin.Android.Tools.AndroidSdk\Xamarin.Android.Tools.AndroidSdk.csproj", "{E34BCFA0-CAA4-412C-AA1C-75DB8D67D157}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{4A5EE838-A906-4711-972E-E680B0AA68BD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Android.Sdk.Analysis", "src\Microsoft.Android.Sdk.Analysis\Microsoft.Android.Sdk.Analysis.csproj", "{0D00DD34-3E94-4166-9DEE-12355E4C98A0}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution src\Xamarin.Android.NamingCustomAttributes\Xamarin.Android.NamingCustomAttributes.projitems*{3f1f2f50-af1a-4a5a-bedb-193372f068d7}*SharedItemsImports = 5 @@ -74,6 +78,10 @@ Global {E34BCFA0-CAA4-412C-AA1C-75DB8D67D157}.Debug|Any CPU.Build.0 = Debug|Any CPU {E34BCFA0-CAA4-412C-AA1C-75DB8D67D157}.Release|Any CPU.ActiveCfg = Release|Any CPU {E34BCFA0-CAA4-412C-AA1C-75DB8D67D157}.Release|Any CPU.Build.0 = Release|Any CPU + {0D00DD34-3E94-4166-9DEE-12355E4C98A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0D00DD34-3E94-4166-9DEE-12355E4C98A0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0D00DD34-3E94-4166-9DEE-12355E4C98A0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0D00DD34-3E94-4166-9DEE-12355E4C98A0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -84,6 +92,7 @@ Global {DE40756E-57F6-4AF2-B155-55E3A88CCED8} = {385E71CC-BAE5-488B-805E-ACAE55F01DF5} {3DE17662-DCD6-4F49-AF06-D39AACC8649A} = {385E71CC-BAE5-488B-805E-ACAE55F01DF5} {E34BCFA0-CAA4-412C-AA1C-75DB8D67D157} = {385E71CC-BAE5-488B-805E-ACAE55F01DF5} + {0D00DD34-3E94-4166-9DEE-12355E4C98A0} = {4A5EE838-A906-4711-972E-E680B0AA68BD} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {F32556C5-6FD4-4F1D-884A-DEDF2EE865F6} diff --git a/Xamarin.Android.sln b/Xamarin.Android.sln index eaf3ea4fb..831275998 100644 --- a/Xamarin.Android.sln +++ b/Xamarin.Android.sln @@ -121,6 +121,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "create-android-api", "build EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Xamarin.Android.Tools.Aidl-Tests", "tests\Xamarin.Android.Tools.Aidl-Tests\Xamarin.Android.Tools.Aidl-Tests.csproj", "{A39B6D7C-6616-40D6-8AE4-C6CEE93D2708}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{FFCF518F-2A4A-40A2-9174-2EE13B76C723}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Android.Sdk.Analysis", "src\Microsoft.Android.Sdk.Analysis\Microsoft.Android.Sdk.Analysis.csproj", "{5E806C9F-1B67-4B6B-A6AB-258834250DBB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|AnyCPU = Debug|AnyCPU @@ -335,6 +339,10 @@ Global {A39B6D7C-6616-40D6-8AE4-C6CEE93D2708}.Debug|AnyCPU.Build.0 = Debug|Any CPU {A39B6D7C-6616-40D6-8AE4-C6CEE93D2708}.Release|AnyCPU.ActiveCfg = Release|Any CPU {A39B6D7C-6616-40D6-8AE4-C6CEE93D2708}.Release|AnyCPU.Build.0 = Release|Any CPU + {5E806C9F-1B67-4B6B-A6AB-258834250DBB}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU + {5E806C9F-1B67-4B6B-A6AB-258834250DBB}.Debug|AnyCPU.Build.0 = Debug|Any CPU + {5E806C9F-1B67-4B6B-A6AB-258834250DBB}.Release|AnyCPU.ActiveCfg = Release|Any CPU + {5E806C9F-1B67-4B6B-A6AB-258834250DBB}.Release|AnyCPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -393,6 +401,7 @@ Global {C0E44558-FEE3-4DD3-986A-3F46DD1BF41B} = {04E3E11E-B47D-4599-8AFC-50515A95E715} {BA4D889D-066B-4C2C-A973-09E319CBC396} = {E351F97D-EA4F-4E7F-AAA0-8EBB1F2A4A62} {A39B6D7C-6616-40D6-8AE4-C6CEE93D2708} = {CAB438D8-B0F5-4AF0-BEBD-9E2ADBD7B483} + {5E806C9F-1B67-4B6B-A6AB-258834250DBB} = {FFCF518F-2A4A-40A2-9174-2EE13B76C723} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {53A1F287-EFB2-4D97-A4BB-4A5E145613F6} diff --git a/build-tools/create-packs/ConfigureLocalWorkload.targets b/build-tools/create-packs/ConfigureLocalWorkload.targets index 379848d03..6a4a6b824 100644 --- a/build-tools/create-packs/ConfigureLocalWorkload.targets +++ b/build-tools/create-packs/ConfigureLocalWorkload.targets @@ -2,6 +2,7 @@ <_FrameworkListInputs Include="$(MicrosoftAndroidRefPackDir)**" /> + <_FrameworkListInputs Include="$(MicrosoftAndroidSdkAnalysisOutDir)Microsoft.Android.Sdk.Analysis.dll" /> <_FrameworkListOutputs Include="$(BuildOutputDirectory)lib\packs\Microsoft.Android.Ref.$(AndroidDefaultTargetDotnetApiLevel)\$(AndroidPackVersion)\data\FrameworkList.xml" /> <_FrameworkListOutputs Include="$(BuildOutputDirectory)lib\packs\Microsoft.Android.Ref.$(AndroidLatestStableApiLevel)\$(AndroidPackVersion)\data\FrameworkList.xml" /> <_FrameworkListOutputs Include="$(BuildOutputDirectory)lib\packs\Microsoft.Android.Ref.$(AndroidLatestUnstableApiLevel)\$(AndroidPackVersion)\data\FrameworkList.xml" /> diff --git a/build-tools/create-packs/Directory.Build.targets b/build-tools/create-packs/Directory.Build.targets index 7a0b67e7f..c06a6b600 100644 --- a/build-tools/create-packs/Directory.Build.targets +++ b/build-tools/create-packs/Directory.Build.targets @@ -28,7 +28,7 @@ Files="@(_PackageFiles)" FileClassifications="@(FrameworkListFileClass)" TargetFile="$(FrameworkListFile)" - TargetFilePrefixes="ref;runtimes" + TargetFilePrefixes="ref;runtimes;analyzers" RootAttributes="@(FrameworkListRootAttributes)" /> diff --git a/build-tools/create-packs/Microsoft.Android.Ref.proj b/build-tools/create-packs/Microsoft.Android.Ref.proj index 9a1bdd0da..d55e8dafe 100644 --- a/build-tools/create-packs/Microsoft.Android.Ref.proj +++ b/build-tools/create-packs/Microsoft.Android.Ref.proj @@ -13,6 +13,7 @@ by projects that use the Microsoft.Android framework in .NET 6+. Microsoft.Android.Ref.$(AndroidApiLevel) Microsoft.Android reference assemblies for API $(AndroidApiLevel). Please do not reference directly. <_AndroidRefPackAssemblyPath>ref\$(DotNetTargetFramework) + <_AndroidRefPackAnalyzersPath>analyzers\dotnet\cs @@ -36,11 +37,14 @@ by projects that use the Microsoft.Android framework in .NET 6+. <_AndroidRefPackAssemblies Include="$(_MonoAndroidNETDefaultOutDir)ref\Mono.Android.Runtime.dll" /> <_AndroidRefPackAssemblies Include="$(_MonoAndroidNETOutputRoot)$(AndroidLatestStableApiLevel)\ref\Mono.Android.Export.dll" /> + <_AndroidRefPackAnalyzers Include="$(MicrosoftAndroidSdkAnalysisOutDir)Microsoft.Android.Sdk.Analysis.dll" /> + <_PackageFiles Include="@(_AndroidRefPackAssemblies)" PackagePath="$(_AndroidRefPackAssemblyPath)" TargetPath="$(_AndroidRefPackAssemblyPath)" /> + <_PackageFiles Include="@(_AndroidRefPackAnalyzers)" PackagePath="$(_AndroidRefPackAnalyzersPath)" TargetPath="$(_AndroidRefPackAnalyzersPath)" /> <_PackageFiles Include="$(_MonoAndroidNETDefaultOutDir)Java.Interop.xml" PackagePath="$(_AndroidRefPackAssemblyPath)" /> <_PackageFiles Include="$(_MonoAndroidNETDefaultOutDir)Mono.Android.xml" PackagePath="$(_AndroidRefPackAssemblyPath)" /> <_PackageFiles Include="$(_MonoAndroidNETDefaultOutDir)mono.android.jar" PackagePath="$(_AndroidRefPackAssemblyPath)" /> diff --git a/eng/Versions.props b/eng/Versions.props index 24fdf4150..65dcac20e 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -6,7 +6,7 @@ 9.0.0-rtm.24473.2 9.0.0-rtm.24473.2 7.0.0-beta.22103.1 - 9.0.0-beta.24408.2 + 10.0.0-beta.24476.2 9.0.0-rtm.24469.1 $(MicrosoftNETWorkloadEmscriptenCurrentManifest90100TransportVersion) 7.0.100-rc.1.22410.7 diff --git a/src/Microsoft.Android.Sdk.Analysis/Microsoft.Android.Sdk.Analysis.csproj b/src/Microsoft.Android.Sdk.Analysis/Microsoft.Android.Sdk.Analysis.csproj new file mode 100644 index 000000000..6f7a62412 --- /dev/null +++ b/src/Microsoft.Android.Sdk.Analysis/Microsoft.Android.Sdk.Analysis.csproj @@ -0,0 +1,19 @@ + + + + netstandard2.0 + false + $(MicrosoftAndroidSdkAnalysisOutDir) + true + latest + true + ..\..\product.snk + + + + + + + + + \ No newline at end of file diff --git a/src/Microsoft.Android.Sdk.Analysis/ResourceDesignerDiagnosticSuppressor.cs b/src/Microsoft.Android.Sdk.Analysis/ResourceDesignerDiagnosticSuppressor.cs new file mode 100644 index 000000000..0b22e1c23 --- /dev/null +++ b/src/Microsoft.Android.Sdk.Analysis/ResourceDesignerDiagnosticSuppressor.cs @@ -0,0 +1,71 @@ +using System.Linq; +using System.Collections.Immutable; +using System.Threading; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Text; + +[DiagnosticAnalyzer(LanguageNames.CSharp)] +public class ResourceDesignerDiagnosticSuppressor : DiagnosticSuppressor +{ + private const string DesignerNamespace = "_Microsoft.Android.Resource.Designer"; + private static readonly SuppressionDescriptor Rule = new( + "XAD0001", + "IDE0002", + "The Resource Designer class should not be simplified." + ); + + public override ImmutableArray SupportedSuppressions + => ImmutableArray.Create(Rule); + + public override void ReportSuppressions(SuppressionAnalysisContext context) + { + foreach (var diagnostic in context.ReportedDiagnostics) + { + if (diagnostic.Id != Rule.SuppressedDiagnosticId) + continue; + Location location = diagnostic.Location; + SyntaxTree syntaxTree = location.SourceTree; + if (syntaxTree is null) + continue; + + SyntaxNode root = syntaxTree.GetRoot(context.CancellationToken); + SyntaxNode syntaxNode = root.FindNode(location.SourceSpan) + .DescendantNodesAndSelf() + .FirstOrDefault (); + + if (syntaxNode is null) + continue; + + SemanticModel model = context.GetSemanticModel(syntaxTree); + ISymbol typeSymbol = model.GetSymbolInfo (syntaxNode).Symbol; + if (typeSymbol is not INamedTypeSymbol namedTypeSymbol) + continue; + + if (IsResourceDesignerDerivedType(namedTypeSymbol)) + { + Suppression suppression = Suppression.Create(Rule, diagnostic); + context.ReportSuppression(suppression); + } + } + } + + private static bool IsResourceDesignerDerivedType(INamedTypeSymbol typeSymbol) + { + return IsDerivedFrom(typeSymbol, DesignerNamespace); + } + + private static bool IsDerivedFrom(INamedTypeSymbol typeSymbol, string baseClassName) + { + while (typeSymbol != null) + { + if (typeSymbol.ToDisplayString().StartsWith(baseClassName)) + { + return true; + } + typeSymbol = typeSymbol.BaseType; + } + return false; + } +} \ No newline at end of file diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerAssembly.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerAssembly.cs index d1f165c4d..4f61d5d6d 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerAssembly.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerAssembly.cs @@ -123,6 +123,12 @@ namespace Xamarin.Android.Tasks TypeReference e = ImportType ("System.ComponentModel.EditorBrowsableState", module, netstandardDef.MainModule); var editorBrowserAttr = new CustomAttribute (editorBrowserConstructor); editorBrowserAttr.ConstructorArguments.Add (new CustomAttributeArgument (e, System.ComponentModel.EditorBrowsableState.Never)); + + MethodReference generatedCodeConstructor = ImportCustomAttributeConstructor (cache, "System.CodeDom.Compiler.GeneratedCodeAttribute", module, netstandardDef.MainModule, argCount: 2); + var generatedCodeAttr = new CustomAttribute (generatedCodeConstructor); + generatedCodeAttr.ConstructorArguments.Add (new CustomAttributeArgument (module.TypeSystem.String, nameof(GenerateResourceDesignerAssembly))); + var version = typeof(GenerateResourceDesignerAssembly).Assembly.GetName().Version; + generatedCodeAttr.ConstructorArguments.Add (new CustomAttributeArgument (module.TypeSystem.String, version.ToString ())); var att = TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.Public | TypeAttributes.BeforeFieldInit; @@ -139,6 +145,7 @@ namespace Xamarin.Android.Tasks ); CreateCtor (cache, resourceDesigner, module); resourceDesigner.CustomAttributes.Add (editorBrowserAttr); + resourceDesigner.CustomAttributes.Add (generatedCodeAttr); module.Types.Add (resourceDesigner); TypeDefinition constDesigner = null; if (IsApplication) { @@ -152,6 +159,7 @@ namespace Xamarin.Android.Tasks ); CreateCtor (cache, constDesigner, module); constDesigner.CustomAttributes.Add (editorBrowserAttr); + constDesigner.CustomAttributes.Add (generatedCodeAttr); module.Types.Add (constDesigner); } diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerIntermediateClass.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerIntermediateClass.cs index 22f9d4cf3..7308996b8 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerIntermediateClass.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerIntermediateClass.cs @@ -21,6 +21,7 @@ namespace Xamarin.Android.Tasks // //------------------------------------------------------------------------------ using System; +using System.CodeDom.Compiler; namespace %NAMESPACE% { #pragma warning disable IDE0002 @@ -28,6 +29,7 @@ namespace %NAMESPACE% { /// Android Resource Designer class. /// Exposes the Android Resource designer assembly into the project Namespace. /// + [GeneratedCode(""%TOOL%"", ""%VERSION%"")] public partial class Resource : %BASECLASS% { } #pragma warning restore IDE0002 @@ -40,6 +42,7 @@ namespace %NAMESPACE% { //------------------------------------------------------------------------------ namespace %NAMESPACE% +[] type Resource = %BASECLASS% "; @@ -54,11 +57,19 @@ type Resource = %BASECLASS% //bool isVB = string.Equals (extension, ".vb", StringComparison.OrdinalIgnoreCase); bool isFSharp = string.Equals (language, "F#", StringComparison.OrdinalIgnoreCase); bool isCSharp = string.Equals (language, "C#", StringComparison.OrdinalIgnoreCase); + var version = typeof(GenerateResourceDesignerIntermediateClass).Assembly.GetName().Version; string template = ""; - if (isCSharp) - template = CSharpTemplate.Replace ("%NAMESPACE%", Namespace).Replace ("%BASECLASS%", ns); - else if (isFSharp) - template = FSharpTemplate.Replace ("%NAMESPACE%", Namespace).Replace ("%BASECLASS%", ns); + if (isCSharp) { + template = CSharpTemplate.Replace ("%NAMESPACE%", Namespace) + .Replace ("%BASECLASS%", ns) + .Replace ("%VERSION%", version.ToString ()) + .Replace ("%TOOL%", nameof (GenerateResourceDesignerIntermediateClass)); + } else if (isFSharp) { + template = FSharpTemplate.Replace ("%NAMESPACE%", Namespace) + .Replace ("%BASECLASS%", ns) + .Replace ("%VERSION%", version.ToString ()) + .Replace ("%TOOL%", nameof (GenerateResourceDesignerIntermediateClass)); + } Files.CopyIfStringChanged (template, OutputFile.ItemSpec); return !Log.HasLoggedErrors;