diff --git a/Avalonia.sln b/Avalonia.sln index a792774d94..5043f474c2 100644 --- a/Avalonia.sln +++ b/Avalonia.sln @@ -117,6 +117,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1 build\Base.props = build\Base.props build\Binding.props = build\Binding.props build\CoreLibraries.props = build\CoreLibraries.props + build\DevAnalyzers.props = build\DevAnalyzers.props build\EmbedXaml.props = build\EmbedXaml.props build\HarfBuzzSharp.props = build\HarfBuzzSharp.props build\JetBrains.Annotations.props = build\JetBrains.Annotations.props @@ -234,7 +235,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.PlatformSupport", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.iOS", "samples\ControlCatalog.iOS\ControlCatalog.iOS.csproj", "{70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.PlatformSupport.UnitTests", "tests\Avalonia.PlatformSupport.UnitTests\Avalonia.PlatformSupport.UnitTests.csproj", "{CE910927-CE5A-456F-BC92-E4C757354A5C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.PlatformSupport.UnitTests", "tests\Avalonia.PlatformSupport.UnitTests\Avalonia.PlatformSupport.UnitTests.csproj", "{CE910927-CE5A-456F-BC92-E4C757354A5C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevAnalyzers", "src\tools\DevAnalyzers\DevAnalyzers.csproj", "{2B390431-288C-435C-BB6B-A374033BD8D1}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -2238,6 +2241,30 @@ Global {CE910927-CE5A-456F-BC92-E4C757354A5C}.Release|iPhone.Build.0 = Release|Any CPU {CE910927-CE5A-456F-BC92-E4C757354A5C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {CE910927-CE5A-456F-BC92-E4C757354A5C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {2B390431-288C-435C-BB6B-A374033BD8D1}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {2B390431-288C-435C-BB6B-A374033BD8D1}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {2B390431-288C-435C-BB6B-A374033BD8D1}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {2B390431-288C-435C-BB6B-A374033BD8D1}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {2B390431-288C-435C-BB6B-A374033BD8D1}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {2B390431-288C-435C-BB6B-A374033BD8D1}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {2B390431-288C-435C-BB6B-A374033BD8D1}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {2B390431-288C-435C-BB6B-A374033BD8D1}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {2B390431-288C-435C-BB6B-A374033BD8D1}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {2B390431-288C-435C-BB6B-A374033BD8D1}.AppStore|iPhone.Build.0 = Debug|Any CPU + {2B390431-288C-435C-BB6B-A374033BD8D1}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {2B390431-288C-435C-BB6B-A374033BD8D1}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {2B390431-288C-435C-BB6B-A374033BD8D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2B390431-288C-435C-BB6B-A374033BD8D1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2B390431-288C-435C-BB6B-A374033BD8D1}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {2B390431-288C-435C-BB6B-A374033BD8D1}.Debug|iPhone.Build.0 = Debug|Any CPU + {2B390431-288C-435C-BB6B-A374033BD8D1}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {2B390431-288C-435C-BB6B-A374033BD8D1}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {2B390431-288C-435C-BB6B-A374033BD8D1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2B390431-288C-435C-BB6B-A374033BD8D1}.Release|Any CPU.Build.0 = Release|Any CPU + {2B390431-288C-435C-BB6B-A374033BD8D1}.Release|iPhone.ActiveCfg = Release|Any CPU + {2B390431-288C-435C-BB6B-A374033BD8D1}.Release|iPhone.Build.0 = Release|Any CPU + {2B390431-288C-435C-BB6B-A374033BD8D1}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {2B390431-288C-435C-BB6B-A374033BD8D1}.Release|iPhoneSimulator.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -2303,6 +2330,7 @@ Global {A0D0A6A4-5C72-4ADA-9B27-621C7D94F270} = {9B9E3891-2366-4253-A952-D08BCEB71098} {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B} = {9B9E3891-2366-4253-A952-D08BCEB71098} {CE910927-CE5A-456F-BC92-E4C757354A5C} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} + {2B390431-288C-435C-BB6B-A374033BD8D1} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A} diff --git a/build/DevAnalyzers.props b/build/DevAnalyzers.props new file mode 100644 index 0000000000..28959dbd47 --- /dev/null +++ b/build/DevAnalyzers.props @@ -0,0 +1,9 @@ + + + + + diff --git a/src/Android/Avalonia.Android/Avalonia.Android.csproj b/src/Android/Avalonia.Android/Avalonia.Android.csproj index 203c3accd6..ad27888f26 100644 --- a/src/Android/Avalonia.Android/Avalonia.Android.csproj +++ b/src/Android/Avalonia.Android/Avalonia.Android.csproj @@ -16,4 +16,5 @@ + diff --git a/src/Avalonia.Animation/Avalonia.Animation.csproj b/src/Avalonia.Animation/Avalonia.Animation.csproj index d81d14bbff..80726f2884 100644 --- a/src/Avalonia.Animation/Avalonia.Animation.csproj +++ b/src/Avalonia.Animation/Avalonia.Animation.csproj @@ -11,4 +11,5 @@ + diff --git a/src/Avalonia.Base/Avalonia.Base.csproj b/src/Avalonia.Base/Avalonia.Base.csproj index 376075df2a..637b86d759 100644 --- a/src/Avalonia.Base/Avalonia.Base.csproj +++ b/src/Avalonia.Base/Avalonia.Base.csproj @@ -12,4 +12,5 @@ + diff --git a/src/Avalonia.Controls.DataGrid/Avalonia.Controls.DataGrid.csproj b/src/Avalonia.Controls.DataGrid/Avalonia.Controls.DataGrid.csproj index c89157dc0f..0438e4e0e8 100644 --- a/src/Avalonia.Controls.DataGrid/Avalonia.Controls.DataGrid.csproj +++ b/src/Avalonia.Controls.DataGrid/Avalonia.Controls.DataGrid.csproj @@ -23,4 +23,5 @@ + diff --git a/src/Avalonia.Controls/Avalonia.Controls.csproj b/src/Avalonia.Controls/Avalonia.Controls.csproj index 543a513d57..5d34261bdf 100644 --- a/src/Avalonia.Controls/Avalonia.Controls.csproj +++ b/src/Avalonia.Controls/Avalonia.Controls.csproj @@ -19,4 +19,5 @@ + diff --git a/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj b/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj index 1fc3604f70..bb908e07dc 100644 --- a/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj +++ b/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj @@ -34,4 +34,5 @@ + diff --git a/src/Avalonia.Dialogs/Avalonia.Dialogs.csproj b/src/Avalonia.Dialogs/Avalonia.Dialogs.csproj index 770d15ea27..a311efdfb0 100644 --- a/src/Avalonia.Dialogs/Avalonia.Dialogs.csproj +++ b/src/Avalonia.Dialogs/Avalonia.Dialogs.csproj @@ -15,4 +15,5 @@ + diff --git a/src/Avalonia.Input/Avalonia.Input.csproj b/src/Avalonia.Input/Avalonia.Input.csproj index e66d1d7e7c..6e0321b3aa 100644 --- a/src/Avalonia.Input/Avalonia.Input.csproj +++ b/src/Avalonia.Input/Avalonia.Input.csproj @@ -15,4 +15,5 @@ + diff --git a/src/Avalonia.Interactivity/Avalonia.Interactivity.csproj b/src/Avalonia.Interactivity/Avalonia.Interactivity.csproj index 03a53f7d86..fa115ed980 100644 --- a/src/Avalonia.Interactivity/Avalonia.Interactivity.csproj +++ b/src/Avalonia.Interactivity/Avalonia.Interactivity.csproj @@ -11,4 +11,5 @@ + \ No newline at end of file diff --git a/src/Avalonia.Layout/Avalonia.Layout.csproj b/src/Avalonia.Layout/Avalonia.Layout.csproj index f2c4b0540b..d94c3eb101 100644 --- a/src/Avalonia.Layout/Avalonia.Layout.csproj +++ b/src/Avalonia.Layout/Avalonia.Layout.csproj @@ -10,4 +10,5 @@ + diff --git a/src/Avalonia.Native/Avalonia.Native.csproj b/src/Avalonia.Native/Avalonia.Native.csproj index 70ab38e786..2001a2fcbc 100644 --- a/src/Avalonia.Native/Avalonia.Native.csproj +++ b/src/Avalonia.Native/Avalonia.Native.csproj @@ -28,4 +28,6 @@ + + diff --git a/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj b/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj index 2b32926008..07cd295711 100644 --- a/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj +++ b/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj @@ -9,5 +9,7 @@ - + + + diff --git a/src/Avalonia.Styling/Avalonia.Styling.csproj b/src/Avalonia.Styling/Avalonia.Styling.csproj index 139ba1bd2e..260cfb0516 100644 --- a/src/Avalonia.Styling/Avalonia.Styling.csproj +++ b/src/Avalonia.Styling/Avalonia.Styling.csproj @@ -10,4 +10,5 @@ + diff --git a/src/Avalonia.Visuals/Avalonia.Visuals.csproj b/src/Avalonia.Visuals/Avalonia.Visuals.csproj index a0b1f99fa1..7e9947812b 100644 --- a/src/Avalonia.Visuals/Avalonia.Visuals.csproj +++ b/src/Avalonia.Visuals/Avalonia.Visuals.csproj @@ -19,4 +19,5 @@ + diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj b/src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj index f75c96c759..b89ea8399a 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj @@ -12,5 +12,6 @@ - + + diff --git a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj index 548aae31a8..6624392258 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj +++ b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj @@ -68,4 +68,5 @@ + diff --git a/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj b/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj index 21370b3bf5..119f57973c 100644 --- a/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj +++ b/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj @@ -18,4 +18,5 @@ + diff --git a/src/Shared/ModuleInitializer.cs b/src/Shared/ModuleInitializer.cs index c14b150c1a..b5bb31ed81 100644 --- a/src/Shared/ModuleInitializer.cs +++ b/src/Shared/ModuleInitializer.cs @@ -3,7 +3,7 @@ namespace System.Runtime.CompilerServices #if !NET5_0_OR_GREATER internal class ModuleInitializerAttribute : Attribute { - + } #endif } diff --git a/src/Skia/Avalonia.Skia/Avalonia.Skia.csproj b/src/Skia/Avalonia.Skia/Avalonia.Skia.csproj index 50ace8209c..26c0fb756e 100644 --- a/src/Skia/Avalonia.Skia/Avalonia.Skia.csproj +++ b/src/Skia/Avalonia.Skia/Avalonia.Skia.csproj @@ -16,5 +16,6 @@ - + + diff --git a/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj b/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj index a1d8a60cb9..bd1f05b30f 100644 --- a/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj +++ b/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj @@ -18,4 +18,5 @@ + diff --git a/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj b/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj index 9f49808422..cc8a40e2d4 100644 --- a/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj +++ b/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj @@ -18,4 +18,5 @@ + diff --git a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj index ba842757d7..b9a1880435 100644 --- a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj +++ b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj @@ -16,5 +16,6 @@ - + + diff --git a/src/iOS/Avalonia.iOS/Avalonia.iOS.csproj b/src/iOS/Avalonia.iOS/Avalonia.iOS.csproj index 39a0305b1e..4e134b7d4e 100644 --- a/src/iOS/Avalonia.iOS/Avalonia.iOS.csproj +++ b/src/iOS/Avalonia.iOS/Avalonia.iOS.csproj @@ -19,4 +19,6 @@ + + diff --git a/src/tools/DevAnalyzers/DevAnalyzers.csproj b/src/tools/DevAnalyzers/DevAnalyzers.csproj new file mode 100644 index 0000000000..53e3e74e76 --- /dev/null +++ b/src/tools/DevAnalyzers/DevAnalyzers.csproj @@ -0,0 +1,17 @@ + + + + netstandard2.0 + 10 + enable + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + diff --git a/src/tools/DevAnalyzers/GenericVirtualAnalyzer.cs b/src/tools/DevAnalyzers/GenericVirtualAnalyzer.cs new file mode 100644 index 0000000000..8ecd9119f6 --- /dev/null +++ b/src/tools/DevAnalyzers/GenericVirtualAnalyzer.cs @@ -0,0 +1,40 @@ +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace DevAnalyzers; + +[DiagnosticAnalyzer(LanguageNames.CSharp)] +public class GenericVirtualAnalyzer : DiagnosticAnalyzer +{ + public const string DiagnosticId = "AVADEV1001"; + + private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( + DiagnosticId, + "Do not use generic virtual methods", + "Method '{0}' is a generic virtual method", + "Performance", + DiagnosticSeverity.Warning, + isEnabledByDefault: true, + description: "Generic virtual methods affect JIT startup time adversly and should be avoided."); + + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); + + public override void Initialize(AnalysisContext context) + { + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + context.EnableConcurrentExecution(); + context.RegisterSymbolAction(AnalyzeMethod, SymbolKind.Method); + } + + private static void AnalyzeMethod(SymbolAnalysisContext context) + { + var symbol = (IMethodSymbol)context.Symbol; + + if (symbol.IsGenericMethod && + (symbol.IsVirtual || symbol.ContainingType.TypeKind == TypeKind.Interface)) + { + context.ReportDiagnostic(Diagnostic.Create(Rule, symbol.Locations[0], symbol.Name)); + } + } +} diff --git a/src/tools/DevAnalyzers/GlobalSuppressions.cs b/src/tools/DevAnalyzers/GlobalSuppressions.cs new file mode 100644 index 0000000000..9428b904b8 --- /dev/null +++ b/src/tools/DevAnalyzers/GlobalSuppressions.cs @@ -0,0 +1,8 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("MicrosoftCodeAnalysisReleaseTracking", "RS2008:Enable analyzer release tracking")]