From dbc3c802a32e632263270cacdcc5bcf572cd5f0a Mon Sep 17 00:00:00 2001 From: Max Katz Date: Mon, 17 Apr 2023 01:29:06 -0400 Subject: [PATCH 01/13] Add Analyzers project to the main package --- Avalonia.sln | 2 +- build/DevAnalyzers.props | 2 +- packages/Avalonia/Avalonia.csproj | 4 ++ .../Avalonia.Analyzers.csproj | 2 +- ...valoniaPropertyAnalyzer.CompileAnalyzer.cs | 0 .../AvaloniaPropertyAnalyzer.cs | 1 - .../Avalonia.Analyzers/GlobalSuppressions.cs | 8 +++ .../OnPropertyChangedOverrideAnalyzer.cs | 59 +++++++++++++++++++ 8 files changed, 74 insertions(+), 4 deletions(-) rename src/tools/{PublicAnalyzers => Avalonia.Analyzers}/Avalonia.Analyzers.csproj (97%) rename src/tools/{PublicAnalyzers => Avalonia.Analyzers}/AvaloniaPropertyAnalyzer.CompileAnalyzer.cs (100%) rename src/tools/{PublicAnalyzers => Avalonia.Analyzers}/AvaloniaPropertyAnalyzer.cs (99%) create mode 100644 src/tools/Avalonia.Analyzers/GlobalSuppressions.cs create mode 100644 src/tools/Avalonia.Analyzers/OnPropertyChangedOverrideAnalyzer.cs diff --git a/Avalonia.sln b/Avalonia.sln index f33b782479..acbf1e6bbb 100644 --- a/Avalonia.sln +++ b/Avalonia.sln @@ -233,7 +233,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReactiveUIDemo", "samples\R EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GpuInterop", "samples\GpuInterop\GpuInterop.csproj", "{C810060E-3809-4B74-A125-F11533AF9C1B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Analyzers", "src\tools\PublicAnalyzers\Avalonia.Analyzers.csproj", "{C692FE73-43DB-49CE-87FC-F03ED61F25C9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Analyzers", "src\tools\Avalonia.Analyzers\Avalonia.Analyzers.csproj", "{C692FE73-43DB-49CE-87FC-F03ED61F25C9}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{176582E8-46AF-416A-85C1-13A5C6744497}" ProjectSection(SolutionItems) = preProject diff --git a/build/DevAnalyzers.props b/build/DevAnalyzers.props index 7d021d051f..dffd3098c3 100644 --- a/build/DevAnalyzers.props +++ b/build/DevAnalyzers.props @@ -5,7 +5,7 @@ ReferenceOutputAssembly="false" OutputItemType="Analyzer" SetTargetFramework="TargetFramework=netstandard2.0"/> - + diff --git a/src/tools/PublicAnalyzers/Avalonia.Analyzers.csproj b/src/tools/Avalonia.Analyzers/Avalonia.Analyzers.csproj similarity index 97% rename from src/tools/PublicAnalyzers/Avalonia.Analyzers.csproj rename to src/tools/Avalonia.Analyzers/Avalonia.Analyzers.csproj index 31b8d08541..39eaab1289 100644 --- a/src/tools/PublicAnalyzers/Avalonia.Analyzers.csproj +++ b/src/tools/Avalonia.Analyzers/Avalonia.Analyzers.csproj @@ -11,7 +11,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/src/tools/PublicAnalyzers/AvaloniaPropertyAnalyzer.CompileAnalyzer.cs b/src/tools/Avalonia.Analyzers/AvaloniaPropertyAnalyzer.CompileAnalyzer.cs similarity index 100% rename from src/tools/PublicAnalyzers/AvaloniaPropertyAnalyzer.CompileAnalyzer.cs rename to src/tools/Avalonia.Analyzers/AvaloniaPropertyAnalyzer.CompileAnalyzer.cs diff --git a/src/tools/PublicAnalyzers/AvaloniaPropertyAnalyzer.cs b/src/tools/Avalonia.Analyzers/AvaloniaPropertyAnalyzer.cs similarity index 99% rename from src/tools/PublicAnalyzers/AvaloniaPropertyAnalyzer.cs rename to src/tools/Avalonia.Analyzers/AvaloniaPropertyAnalyzer.cs index d1d9071d17..d1ffd82f99 100644 --- a/src/tools/PublicAnalyzers/AvaloniaPropertyAnalyzer.cs +++ b/src/tools/Avalonia.Analyzers/AvaloniaPropertyAnalyzer.cs @@ -14,7 +14,6 @@ using Microsoft.CodeAnalysis.Operations; namespace Avalonia.Analyzers; [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] -[SuppressMessage("MicrosoftCodeAnalysisReleaseTracking", "RS2008:Enable analyzer release tracking")] public partial class AvaloniaPropertyAnalyzer : DiagnosticAnalyzer { private const string Category = "AvaloniaProperty"; diff --git a/src/tools/Avalonia.Analyzers/GlobalSuppressions.cs b/src/tools/Avalonia.Analyzers/GlobalSuppressions.cs new file mode 100644 index 0000000000..9428b904b8 --- /dev/null +++ b/src/tools/Avalonia.Analyzers/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")] diff --git a/src/tools/Avalonia.Analyzers/OnPropertyChangedOverrideAnalyzer.cs b/src/tools/Avalonia.Analyzers/OnPropertyChangedOverrideAnalyzer.cs new file mode 100644 index 0000000000..6fbfe28bd8 --- /dev/null +++ b/src/tools/Avalonia.Analyzers/OnPropertyChangedOverrideAnalyzer.cs @@ -0,0 +1,59 @@ +using System.Collections.Immutable; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Avalonia.Analyzers; + +[DiagnosticAnalyzer(LanguageNames.CSharp)] +public class OnPropertyChangedOverrideAnalyzer : DiagnosticAnalyzer +{ + public const string DiagnosticId = "AVA2001"; + + private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor( + DiagnosticId, + "Missing invoke base.OnPropertyChanged", + "Method '{0}' do not invoke base.{0}", + "Potential issue", + DiagnosticSeverity.Warning, + isEnabledByDefault: true, + description: "The OnPropertyChanged of the base class was not invoked in the override method declaration, which could lead to unwanted behavior."); + + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); + + public override void Initialize(AnalysisContext context) + { + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + context.EnableConcurrentExecution(); + context.RegisterSyntaxNodeAction(AnalyzeMethod, SyntaxKind.MethodDeclaration); + } + + private static void AnalyzeMethod(SyntaxNodeAnalysisContext context) + { + var method = (MethodDeclarationSyntax)context.Node; + if (context.SemanticModel.GetDeclaredSymbol(method, context.CancellationToken) is IMethodSymbol currentMethod + && currentMethod.Name == "OnPropertyChanged" + && currentMethod.OverriddenMethod is IMethodSymbol originalMethod) + { + var baseInvocations = method.Body?.DescendantNodes().OfType(); + if (baseInvocations?.Any() == true) + { + foreach (var baseInvocation in baseInvocations) + { + if (baseInvocation.Parent is SyntaxNode parent) + { + var targetSymbol = context.SemanticModel.GetSymbolInfo(parent, context.CancellationToken); + if (SymbolEqualityComparer.Default.Equals(targetSymbol.Symbol, originalMethod)) + { + return; + } + } + } + } + context.ReportDiagnostic(Diagnostic.Create(Rule, currentMethod.Locations[0], currentMethod.Name)); + } + } + +} From 4dbd7cb2a0e0878367ecf7dc5a38609f0b2066d4 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Mon, 17 Apr 2023 01:36:30 -0400 Subject: [PATCH 02/13] Disable most of analyzers --- .../AvaloniaPropertyAnalyzer.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/tools/Avalonia.Analyzers/AvaloniaPropertyAnalyzer.cs b/src/tools/Avalonia.Analyzers/AvaloniaPropertyAnalyzer.cs index d1ffd82f99..9eb4cecc8b 100644 --- a/src/tools/Avalonia.Analyzers/AvaloniaPropertyAnalyzer.cs +++ b/src/tools/Avalonia.Analyzers/AvaloniaPropertyAnalyzer.cs @@ -3,7 +3,6 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; using System.Collections.ObjectModel; -using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Runtime.Serialization; using Microsoft.CodeAnalysis; @@ -67,7 +66,7 @@ public partial class AvaloniaPropertyAnalyzer : DiagnosticAnalyzer "Type mismatch: AvaloniaProperty owner is {0}, which is not the containing type", Category, DiagnosticSeverity.Warning, - isEnabledByDefault: true, + isEnabledByDefault: false, // TODO: autogenerate property metadata preserved in ref assembly "The owner of an AvaloniaProperty should generally be the containing type. This ensures that the property can be used as expected in XAML.", TypeMismatchTag); @@ -77,7 +76,7 @@ public partial class AvaloniaPropertyAnalyzer : DiagnosticAnalyzer "Unexpected property use: {0} is neither owned by nor attached to {1}", Category, DiagnosticSeverity.Warning, - isEnabledByDefault: true, + isEnabledByDefault: false, // TODO: autogenerate property metadata preserved in ref assembly "It is possible to use any AvaloniaProperty with any AvaloniaObject. However, each AvaloniaProperty an object uses on itself should be either owned by that object, or attached to that object.", InappropriateReadWriteTag); @@ -87,7 +86,7 @@ public partial class AvaloniaPropertyAnalyzer : DiagnosticAnalyzer "Inappropriate assignment: An AvaloniaObject should use SetCurrentValue when setting its own StyledProperty or AttachedProperty values", Category, DiagnosticSeverity.Warning, - isEnabledByDefault: true, + isEnabledByDefault: false, // TODO: autogenerate property metadata preserved in ref assembly "The standard means of setting an AvaloniaProperty is to call the SetValue method (often via a CLR property setter). This will forcibly overwrite values from sources like styles and templates, " + "which is something that should only be done by consumers of the control, not the control itself. Controls which want to set their own values should instead call the SetCurrentValue method, or " + "refactor the property into a DirectProperty. An assignment is exempt from this diagnostic in two scenarios: when it is forwarding a constructor parameter, and when the target object is derived " + @@ -100,7 +99,7 @@ public partial class AvaloniaPropertyAnalyzer : DiagnosticAnalyzer "Superfluous owner: {0} is already an owner of {1} via {2}", Category, DiagnosticSeverity.Warning, - isEnabledByDefault: true, + isEnabledByDefault: false, // TODO: autogenerate property metadata preserved in ref assembly "Ownership of an AvaloniaProperty is inherited along the type hierarchy. There is no need for a derived type to assert ownership over a base type's properties. This diagnostic can be a symptom of an incorrect property owner elsewhere.", InappropriateReadWriteTag); @@ -110,7 +109,7 @@ public partial class AvaloniaPropertyAnalyzer : DiagnosticAnalyzer "Name collision: {0} has the same name as {1}", Category, DiagnosticSeverity.Warning, - isEnabledByDefault: true, + isEnabledByDefault: false, // TODO: autogenerate property metadata preserved in ref assembly "Querying for an AvaloniaProperty by name requires that each property associated with a type have a unique name.", NameCollisionTag); @@ -120,7 +119,7 @@ public partial class AvaloniaPropertyAnalyzer : DiagnosticAnalyzer "Name collision: {0} owns multiple Avalonia properties with the name '{1}' {2}", Category, DiagnosticSeverity.Warning, - isEnabledByDefault: true, + isEnabledByDefault: false, // TODO: autogenerate property metadata preserved in ref assembly "It is unclear which AvaloniaProperty this CLR property refers to. Ensure that each AvaloniaProperty associated with a type has a unique name. If you need to change behaviour of a base property in your class, call its OverrideMetadata or OverrideDefaultValue methods.", NameCollisionTag); @@ -170,7 +169,7 @@ public partial class AvaloniaPropertyAnalyzer : DiagnosticAnalyzer "Type mismatch: CLR property type differs from the value type of {0} {1}", Category, DiagnosticSeverity.Warning, - isEnabledByDefault: true, + isEnabledByDefault: false, // TODO: autogenerate property metadata preserved in ref assembly "The AvaloniaObject.GetValue and AvaloniaObject.SetValue methods are public, and do not call CLR properties on the owning type. A CLR property changing the value type (even when an implicit cast is possible) is ineffective and can lead to InvalidCastException to be thrown.", TypeMismatchTag, AssociatedClrPropertyTag); From ead92a6122a4617b19b40356fd537b50d91fa449 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Mon, 17 Apr 2023 01:37:47 -0400 Subject: [PATCH 03/13] Fix SetCurrentValue warnings --- src/Avalonia.Base/Media/DashStyle.cs | 2 +- src/Avalonia.Base/Media/GradientBrush.cs | 2 +- src/Avalonia.Base/Media/PolyLineSegment.cs | 2 +- src/Avalonia.Base/Media/TransformGroup.cs | 9 +++++---- src/Avalonia.Controls/Calendar/CalendarButton.cs | 2 +- src/Avalonia.Controls/Calendar/CalendarDayButton.cs | 2 +- src/Avalonia.Controls/ColumnDefinition.cs | 2 +- src/Avalonia.Controls/Documents/Span.cs | 4 ++-- src/Avalonia.Controls/GridSplitter.cs | 2 +- src/Avalonia.Controls/LayoutTransformControl.cs | 4 ++-- src/Avalonia.Controls/NativeMenuItemSeparator.cs | 2 +- src/Avalonia.Controls/Primitives/OverlayPopupHost.cs | 2 +- .../Primitives/SelectingItemsControl.cs | 8 ++++---- src/Avalonia.Controls/Primitives/UniformGrid.cs | 2 +- .../PullToRefresh/RefreshVisualizer.cs | 2 +- src/Avalonia.Controls/RowDefinition.cs | 4 ++-- src/Avalonia.Controls/TabControl.cs | 11 ++++++----- src/Avalonia.Controls/TabItem.cs | 8 ++++---- src/Avalonia.Controls/ToggleSwitch.cs | 2 +- .../Diagnostics/Controls/Application.cs | 4 ++-- 20 files changed, 39 insertions(+), 37 deletions(-) diff --git a/src/Avalonia.Base/Media/DashStyle.cs b/src/Avalonia.Base/Media/DashStyle.cs index 4749bfa401..338737d2ab 100644 --- a/src/Avalonia.Base/Media/DashStyle.cs +++ b/src/Avalonia.Base/Media/DashStyle.cs @@ -46,7 +46,7 @@ namespace Avalonia.Media /// The dash sequence offset. public DashStyle(IEnumerable? dashes, double offset) { - Dashes = (dashes as AvaloniaList) ?? new AvaloniaList(dashes ?? Array.Empty()); + SetCurrentValue(DashesProperty, (dashes as AvaloniaList) ?? new AvaloniaList(dashes ?? Array.Empty())); Offset = offset; } diff --git a/src/Avalonia.Base/Media/GradientBrush.cs b/src/Avalonia.Base/Media/GradientBrush.cs index e1654a01b2..0ec753201a 100644 --- a/src/Avalonia.Base/Media/GradientBrush.cs +++ b/src/Avalonia.Base/Media/GradientBrush.cs @@ -40,7 +40,7 @@ namespace Avalonia.Media /// public GradientBrush() { - this.GradientStops = new GradientStops(); + SetCurrentValue(GradientStopsProperty, new GradientStops()); } /// diff --git a/src/Avalonia.Base/Media/PolyLineSegment.cs b/src/Avalonia.Base/Media/PolyLineSegment.cs index 5c48c11e19..7de5e1afa5 100644 --- a/src/Avalonia.Base/Media/PolyLineSegment.cs +++ b/src/Avalonia.Base/Media/PolyLineSegment.cs @@ -30,7 +30,7 @@ namespace Avalonia.Media /// public PolyLineSegment() { - Points = new Points(); + SetCurrentValue(PointsProperty, new Points()); } /// diff --git a/src/Avalonia.Base/Media/TransformGroup.cs b/src/Avalonia.Base/Media/TransformGroup.cs index 0465efd5a5..c048234f8c 100644 --- a/src/Avalonia.Base/Media/TransformGroup.cs +++ b/src/Avalonia.Base/Media/TransformGroup.cs @@ -13,15 +13,16 @@ namespace Avalonia.Media public TransformGroup() { - Children = new Transforms(); - Children.ResetBehavior = ResetBehavior.Remove; - Children.CollectionChanged += delegate + var children = new Transforms(); + children.ResetBehavior = ResetBehavior.Remove; + children.CollectionChanged += delegate { - Children.ForEachItem( + children.ForEachItem( (tr) => tr.Changed += ChildTransform_Changed, (tr) => tr.Changed -= ChildTransform_Changed, () => { }); }; + SetCurrentValue(ChildrenProperty, children); } private void ChildTransform_Changed(object? sender, System.EventArgs e) diff --git a/src/Avalonia.Controls/Calendar/CalendarButton.cs b/src/Avalonia.Controls/Calendar/CalendarButton.cs index d8672cbf18..b35298b101 100644 --- a/src/Avalonia.Controls/Calendar/CalendarButton.cs +++ b/src/Avalonia.Controls/Calendar/CalendarButton.cs @@ -39,7 +39,7 @@ namespace Avalonia.Controls.Primitives public CalendarButton() : base() { - Content = DateTimeHelper.GetCurrentDateFormat().AbbreviatedMonthNames[0]; + SetCurrentValue(ContentProperty, DateTimeHelper.GetCurrentDateFormat().AbbreviatedMonthNames[0]); } /// diff --git a/src/Avalonia.Controls/Calendar/CalendarDayButton.cs b/src/Avalonia.Controls/Calendar/CalendarDayButton.cs index 3d0befdba7..ea3ca8e8fc 100644 --- a/src/Avalonia.Controls/Calendar/CalendarDayButton.cs +++ b/src/Avalonia.Controls/Calendar/CalendarDayButton.cs @@ -34,7 +34,7 @@ namespace Avalonia.Controls.Primitives : base() { //Focusable = false; - Content = DefaultContent.ToString(CultureInfo.CurrentCulture); + SetCurrentValue(ContentProperty, DefaultContent.ToString(CultureInfo.CurrentCulture)); } /// diff --git a/src/Avalonia.Controls/ColumnDefinition.cs b/src/Avalonia.Controls/ColumnDefinition.cs index 2eb3ae3010..b28faba863 100644 --- a/src/Avalonia.Controls/ColumnDefinition.cs +++ b/src/Avalonia.Controls/ColumnDefinition.cs @@ -46,8 +46,8 @@ namespace Avalonia.Controls /// The width of the column. /// The width unit of the column. public ColumnDefinition(double value, GridUnitType type) + : this(new GridLength(value, type)) { - Width = new GridLength(value, type); } /// diff --git a/src/Avalonia.Controls/Documents/Span.cs b/src/Avalonia.Controls/Documents/Span.cs index d3565cbdd5..a4f3264c4d 100644 --- a/src/Avalonia.Controls/Documents/Span.cs +++ b/src/Avalonia.Controls/Documents/Span.cs @@ -20,10 +20,10 @@ namespace Avalonia.Controls.Documents public Span() { - Inlines = new InlineCollection + SetCurrentValue(InlinesProperty, new InlineCollection { LogicalChildren = LogicalChildren - }; + }); } /// diff --git a/src/Avalonia.Controls/GridSplitter.cs b/src/Avalonia.Controls/GridSplitter.cs index 4684304725..50d1004f34 100644 --- a/src/Avalonia.Controls/GridSplitter.cs +++ b/src/Avalonia.Controls/GridSplitter.cs @@ -707,7 +707,7 @@ namespace Avalonia.Controls RenderTransform = _translation }; - Child = _decorator; + SetCurrentValue(ChildProperty, _decorator); } /// diff --git a/src/Avalonia.Controls/LayoutTransformControl.cs b/src/Avalonia.Controls/LayoutTransformControl.cs index f747e278f0..02d2eeef5b 100644 --- a/src/Avalonia.Controls/LayoutTransformControl.cs +++ b/src/Avalonia.Controls/LayoutTransformControl.cs @@ -63,7 +63,7 @@ namespace Avalonia.Controls { if (TransformRoot == null || LayoutTransform == null) { - LayoutTransform = RenderTransform; + SetCurrentValue(LayoutTransformProperty, RenderTransform); return base.ArrangeOverride(finalSize); } @@ -176,7 +176,7 @@ namespace Avalonia.Controls else { _renderTransformChangedEvent?.Dispose(); - LayoutTransform = null; + SetCurrentValue(LayoutTransformProperty, null); } } } diff --git a/src/Avalonia.Controls/NativeMenuItemSeparator.cs b/src/Avalonia.Controls/NativeMenuItemSeparator.cs index f55d714884..55b3fd08de 100644 --- a/src/Avalonia.Controls/NativeMenuItemSeparator.cs +++ b/src/Avalonia.Controls/NativeMenuItemSeparator.cs @@ -4,7 +4,7 @@ { public NativeMenuItemSeparator() { - Header = "-"; + SetCurrentValue(HeaderProperty, "-"); } } } diff --git a/src/Avalonia.Controls/Primitives/OverlayPopupHost.cs b/src/Avalonia.Controls/Primitives/OverlayPopupHost.cs index 7ed055f2e5..0acc488885 100644 --- a/src/Avalonia.Controls/Primitives/OverlayPopupHost.cs +++ b/src/Avalonia.Controls/Primitives/OverlayPopupHost.cs @@ -31,7 +31,7 @@ namespace Avalonia.Controls.Primitives /// public void SetChild(Control? control) { - Content = control; + SetCurrentValue(ContentProperty, control); } /// diff --git a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs index 663a315732..ac3e87c03d 100644 --- a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs +++ b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs @@ -701,7 +701,7 @@ namespace Avalonia.Controls.Primitives if (value is null) { // Clearing SelectedValueBinding makes the SelectedValue the item itself - SelectedValue = SelectedItem; + SetCurrentValue(SelectedValueProperty, SelectedItem); return; } @@ -721,7 +721,7 @@ namespace Avalonia.Controls.Primitives } // Re-evaluate SelectedValue with the new binding - SelectedValue = _bindingHelper.Evaluate(selectedItem); + SetCurrentValue(SelectedValueProperty, _bindingHelper.Evaluate(selectedItem)); } finally { @@ -1092,7 +1092,7 @@ namespace Avalonia.Controls.Primitives try { _isSelectionChangeActive = true; - SelectedValue = item; + SetCurrentValue(SelectedValueProperty, item); } finally { @@ -1106,7 +1106,7 @@ namespace Avalonia.Controls.Primitives try { _isSelectionChangeActive = true; - SelectedValue = _bindingHelper.Evaluate(item); + SetCurrentValue(SelectedValueProperty, _bindingHelper.Evaluate(item)); } finally { diff --git a/src/Avalonia.Controls/Primitives/UniformGrid.cs b/src/Avalonia.Controls/Primitives/UniformGrid.cs index 09554412db..fea35d867a 100644 --- a/src/Avalonia.Controls/Primitives/UniformGrid.cs +++ b/src/Avalonia.Controls/Primitives/UniformGrid.cs @@ -123,7 +123,7 @@ namespace Avalonia.Controls.Primitives if (FirstColumn >= Columns) { - FirstColumn = 0; + SetCurrentValue(FirstColumnProperty, 0); } var itemCount = FirstColumn; diff --git a/src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs b/src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs index 8dc19eb1d4..e110396d95 100644 --- a/src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs +++ b/src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs @@ -192,7 +192,7 @@ namespace Avalonia.Controls UpdateContent(); }; - Content = _content; + SetCurrentValue(ContentProperty, _content); } else { diff --git a/src/Avalonia.Controls/RowDefinition.cs b/src/Avalonia.Controls/RowDefinition.cs index fac795035b..8aaaff8cc9 100644 --- a/src/Avalonia.Controls/RowDefinition.cs +++ b/src/Avalonia.Controls/RowDefinition.cs @@ -46,8 +46,8 @@ namespace Avalonia.Controls /// The height of the row. /// The height unit of the column. public RowDefinition(double value, GridUnitType type) + : this(new GridLength(value, type)) { - Height = new GridLength(value, type); } /// @@ -56,7 +56,7 @@ namespace Avalonia.Controls /// The height of the column. public RowDefinition(GridLength height) { - Height = height; + SetCurrentValue(HeightProperty, height); } /// diff --git a/src/Avalonia.Controls/TabControl.cs b/src/Avalonia.Controls/TabControl.cs index 74cf54beb8..502e128641 100644 --- a/src/Avalonia.Controls/TabControl.cs +++ b/src/Avalonia.Controls/TabControl.cs @@ -162,8 +162,8 @@ namespace Avalonia.Controls if (index == SelectedIndex && element is ContentControl container) { - SelectedContentTemplate = container.ContentTemplate; - SelectedContent = container.Content; + SetCurrentValue(SelectedContentTemplateProperty, container.ContentTemplate); + SetCurrentValue(SelectedContentProperty, container.Content); } } @@ -187,14 +187,15 @@ namespace Avalonia.Controls { if (SelectedIndex == -1) { - SelectedContent = SelectedContentTemplate = null; + SetCurrentValue(SelectedContentProperty, null); + SetCurrentValue(SelectedContentTemplateProperty, null); } else { var container = SelectedItem as IContentControl ?? ContainerFromIndex(SelectedIndex) as IContentControl; - SelectedContentTemplate = container?.ContentTemplate; - SelectedContent = container?.Content; + SetCurrentValue(SelectedContentTemplateProperty, container?.ContentTemplate); + SetCurrentValue(SelectedContentProperty, container?.Content); } } diff --git a/src/Avalonia.Controls/TabItem.cs b/src/Avalonia.Controls/TabItem.cs index 46265fb5bc..8303153a4b 100644 --- a/src/Avalonia.Controls/TabItem.cs +++ b/src/Avalonia.Controls/TabItem.cs @@ -66,14 +66,14 @@ namespace Avalonia.Controls { if (Header != headered.Header) { - Header = headered.Header; + SetCurrentValue(HeaderProperty, headered.Header); } } else { if (!(obj.NewValue is Control)) { - Header = obj.NewValue; + SetCurrentValue(HeaderProperty, obj.NewValue); } } } @@ -81,9 +81,9 @@ namespace Avalonia.Controls { if (Header == obj.OldValue) { - Header = obj.NewValue; + SetCurrentValue(HeaderProperty, obj.NewValue); } - } + } } } } diff --git a/src/Avalonia.Controls/ToggleSwitch.cs b/src/Avalonia.Controls/ToggleSwitch.cs index a28e9791f6..108deba257 100644 --- a/src/Avalonia.Controls/ToggleSwitch.cs +++ b/src/Avalonia.Controls/ToggleSwitch.cs @@ -201,7 +201,7 @@ namespace Avalonia.Controls } else { - IsChecked = shouldBecomeChecked; + SetCurrentValue(IsCheckedProperty, shouldBecomeChecked); } } else diff --git a/src/Avalonia.Diagnostics/Diagnostics/Controls/Application.cs b/src/Avalonia.Diagnostics/Diagnostics/Controls/Application.cs index 5bc9909ef3..fb0504ba1e 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/Controls/Application.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/Controls/Application.cs @@ -37,7 +37,7 @@ namespace Avalonia.Diagnostics.Controls _ => null }; - RequestedThemeVariant = application.RequestedThemeVariant; + SetCurrentValue(RequestedThemeVariantProperty, application.RequestedThemeVariant); _application.PropertyChanged += ApplicationOnPropertyChanged; } @@ -131,7 +131,7 @@ namespace Avalonia.Diagnostics.Controls { if (e.Property == Avalonia.Application.RequestedThemeVariantProperty) { - RequestedThemeVariant = e.GetNewValue(); + SetCurrentValue(RequestedThemeVariantProperty, e.GetNewValue()); } } From e909bdb005121766a253194663c0f3e5bd636d0d Mon Sep 17 00:00:00 2001 From: Max Katz Date: Mon, 17 Apr 2023 01:38:32 -0400 Subject: [PATCH 04/13] Fix some other AVP warnings --- .../Pages/CustomDrawingExampleControl.cs | 11 +++++------ src/Avalonia.Controls/DefinitionBase.cs | 12 ++---------- src/Avalonia.Controls/Flyouts/PopupFlyoutBase.cs | 2 +- src/Avalonia.Controls/MenuItem.cs | 6 ------ .../PullToRefresh/RefreshVisualizer.cs | 2 +- src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj | 1 + .../Avalonia.Themes.Fluent.csproj | 1 + .../Avalonia.Themes.Simple.csproj | 1 + 8 files changed, 12 insertions(+), 24 deletions(-) diff --git a/samples/ControlCatalog/Pages/CustomDrawingExampleControl.cs b/samples/ControlCatalog/Pages/CustomDrawingExampleControl.cs index 549cf3d740..782435ae06 100644 --- a/samples/ControlCatalog/Pages/CustomDrawingExampleControl.cs +++ b/samples/ControlCatalog/Pages/CustomDrawingExampleControl.cs @@ -19,18 +19,16 @@ namespace ControlCatalog.Pages public static readonly StyledProperty ScaleProperty = AvaloniaProperty.Register(nameof(Scale), 1.0d); public double Scale { get => GetValue(ScaleProperty); set => SetValue(ScaleProperty, value); } - public static readonly StyledProperty RotationProperty = AvaloniaProperty.Register(nameof(Rotation)); + public static readonly StyledProperty RotationProperty = AvaloniaProperty.Register(nameof(Rotation), + coerce: (_, val) => val % (Math.PI * 2)); + /// /// Rotation, measured in Radians! /// public double Rotation { get => GetValue(RotationProperty); - set - { - double valueToUse = value % (Math.PI * 2); - SetValue(RotationProperty, valueToUse); - } + set => SetValue(RotationProperty, value); } public static readonly StyledProperty ViewportCenterYProperty = AvaloniaProperty.Register(nameof(ViewportCenterY), 0.0d); @@ -213,5 +211,6 @@ namespace ControlCatalog.Pages return workingPoint; } + } } diff --git a/src/Avalonia.Controls/DefinitionBase.cs b/src/Avalonia.Controls/DefinitionBase.cs index eb587fb157..d0752b8aa6 100644 --- a/src/Avalonia.Controls/DefinitionBase.cs +++ b/src/Avalonia.Controls/DefinitionBase.cs @@ -37,7 +37,7 @@ namespace Avalonia.Controls { // start with getting SharedSizeGroup value. // this property is NOT inherited which should result in better overall perf. - if (SharedSizeGroup is { } sharedSizeGroupId && PrivateSharedSizeScope is { } privateSharedSizeScope) + if (SharedSizeGroup is { } sharedSizeGroupId && GetValue(PrivateSharedSizeScopeProperty) is { } privateSharedSizeScope) { _sharedState = privateSharedSizeScope.EnsureSharedState(sharedSizeGroupId); _sharedState.AddMember(this); @@ -333,7 +333,7 @@ namespace Avalonia.Controls if (definition._sharedState == null && sharedSizeGroupId != null - && definition.PrivateSharedSizeScope is { } privateSharedSizeScope) + && definition.GetValue(PrivateSharedSizeScopeProperty) is { } privateSharedSizeScope) { // if definition is not registered and both: shared size group id AND private shared scope // are available, then register definition. @@ -412,14 +412,6 @@ namespace Avalonia.Controls } } - /// - /// Private getter of shared state collection dynamic property. - /// - private SharedSizeScope? PrivateSharedSizeScope - { - get { return GetValue(PrivateSharedSizeScopeProperty); } - } - /// /// Convenience accessor to UseSharedMinimum flag /// diff --git a/src/Avalonia.Controls/Flyouts/PopupFlyoutBase.cs b/src/Avalonia.Controls/Flyouts/PopupFlyoutBase.cs index 9ed4737c7c..5b23b5030f 100644 --- a/src/Avalonia.Controls/Flyouts/PopupFlyoutBase.cs +++ b/src/Avalonia.Controls/Flyouts/PopupFlyoutBase.cs @@ -44,7 +44,7 @@ namespace Avalonia.Controls.Primitives /// Defines the property /// public static readonly StyledProperty OverlayInputPassThroughElementProperty = - Popup.OverlayInputPassThroughElementProperty.AddOwner(); + Popup.OverlayInputPassThroughElementProperty.AddOwner(); private readonly Lazy _popupLazy; private Rect? _enlargedPopupRect; diff --git a/src/Avalonia.Controls/MenuItem.cs b/src/Avalonia.Controls/MenuItem.cs index a0dbf33a1d..72febcfedb 100644 --- a/src/Avalonia.Controls/MenuItem.cs +++ b/src/Avalonia.Controls/MenuItem.cs @@ -53,12 +53,6 @@ namespace Avalonia.Controls public static readonly StyledProperty InputGestureProperty = AvaloniaProperty.Register(nameof(InputGesture)); - /// - /// Defines the property. - /// - public static readonly StyledProperty IsSelectedProperty = - SelectingItemsControl.IsSelectedProperty.AddOwner(); - /// /// Defines the property. /// diff --git a/src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs b/src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs index e110396d95..db83977bc6 100644 --- a/src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs +++ b/src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs @@ -99,7 +99,7 @@ namespace Avalonia.Controls } } - internal PullDirection PullDirection + public PullDirection PullDirection { get => GetValue(PullDirectionProperty); set => SetValue(PullDirectionProperty, value); diff --git a/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj b/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj index 22ee548823..4cae8e82df 100644 --- a/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj +++ b/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj @@ -12,4 +12,5 @@ + diff --git a/src/Avalonia.Themes.Fluent/Avalonia.Themes.Fluent.csproj b/src/Avalonia.Themes.Fluent/Avalonia.Themes.Fluent.csproj index 8d266ce82f..e63a0c9c26 100644 --- a/src/Avalonia.Themes.Fluent/Avalonia.Themes.Fluent.csproj +++ b/src/Avalonia.Themes.Fluent/Avalonia.Themes.Fluent.csproj @@ -15,4 +15,5 @@ + diff --git a/src/Avalonia.Themes.Simple/Avalonia.Themes.Simple.csproj b/src/Avalonia.Themes.Simple/Avalonia.Themes.Simple.csproj index 4aa6b66743..03193599ed 100644 --- a/src/Avalonia.Themes.Simple/Avalonia.Themes.Simple.csproj +++ b/src/Avalonia.Themes.Simple/Avalonia.Themes.Simple.csproj @@ -15,4 +15,5 @@ + From a9688a83a1d7aa68068434a625078b114b5af998 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Mon, 17 Apr 2023 01:38:55 -0400 Subject: [PATCH 05/13] Suppress warnings that are expected behavior --- src/Avalonia.Base/ClassBindingManager.cs | 2 ++ src/Avalonia.Base/StyledElement.cs | 1 + src/Avalonia.Base/Styling/ThemeVariant.cs | 4 ++++ src/Avalonia.Base/Visual.cs | 1 + src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs | 2 ++ src/Avalonia.Controls/ContextMenu.cs | 2 ++ src/Avalonia.Controls/ListBox.cs | 8 ++++++++ src/Avalonia.Controls/Primitives/VisualLayerManager.cs | 3 +++ src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs | 1 + .../SplitView/SplitViewTemplateSettings.cs | 2 ++ src/Avalonia.Controls/TabControl.cs | 2 ++ src/Avalonia.Controls/TabItem.cs | 2 ++ src/Avalonia.Controls/TopLevel.cs | 4 ++-- src/Avalonia.ReactiveUI/ReactiveUserControl.cs | 1 + src/Avalonia.ReactiveUI/ReactiveWindow.cs | 1 + 15 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Base/ClassBindingManager.cs b/src/Avalonia.Base/ClassBindingManager.cs index a9726cb86e..55f3a7892a 100644 --- a/src/Avalonia.Base/ClassBindingManager.cs +++ b/src/Avalonia.Base/ClassBindingManager.cs @@ -17,6 +17,8 @@ namespace Avalonia return target.Bind(prop, source, anchor); } + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1001:The same AvaloniaProperty should not be registered twice", + Justification = "Classes.attr binding feature is implemented using intermediate avalonia properties for each class")] private static AvaloniaProperty RegisterClassProxyProperty(string className) { var prop = AvaloniaProperty.Register("__AvaloniaReserved::Classes::" + className); diff --git a/src/Avalonia.Base/StyledElement.cs b/src/Avalonia.Base/StyledElement.cs index 5881efce1e..3270fe4614 100644 --- a/src/Avalonia.Base/StyledElement.cs +++ b/src/Avalonia.Base/StyledElement.cs @@ -289,6 +289,7 @@ namespace Avalonia public StyledElement? Parent { get; private set; } /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1030:StyledProperty accessors should not have side effects", Justification = "False positive?")] public ThemeVariant ActualThemeVariant => GetValue(ThemeVariant.ActualThemeVariantProperty); /// diff --git a/src/Avalonia.Base/Styling/ThemeVariant.cs b/src/Avalonia.Base/Styling/ThemeVariant.cs index 389136b0f5..23bc15dfa7 100644 --- a/src/Avalonia.Base/Styling/ThemeVariant.cs +++ b/src/Avalonia.Base/Styling/ThemeVariant.cs @@ -9,6 +9,10 @@ namespace Avalonia.Styling; /// Specifies a UI theme variant that should be used for the Control and Application types. /// [TypeConverter(typeof(ThemeVariantTypeConverter))] +[System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1010:AvaloniaProperty objects should be owned by the type in which they are stored", + Justification = "ActualThemeVariant and RequestedThemeVariant properties are shared Avalonia.Base and Avalonia.Controls projects," + + "but shouldn't be visible on the StyledElement class." + + "Ideally we woould introduce readonly styled properties.")] public sealed record ThemeVariant { /// diff --git a/src/Avalonia.Base/Visual.cs b/src/Avalonia.Base/Visual.cs index 79cc760fc6..8717b5340a 100644 --- a/src/Avalonia.Base/Visual.cs +++ b/src/Avalonia.Base/Visual.cs @@ -329,6 +329,7 @@ namespace Avalonia /// /// Gets the control's parent visual. /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1032", Justification = "GetVisualParent extension method is supposed to be used instead.")] internal Visual? VisualParent => _visualParent; /// diff --git a/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs b/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs index e10cc1d100..20711eecbc 100644 --- a/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs +++ b/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs @@ -2042,6 +2042,8 @@ namespace Avalonia.Controls /// /// Identifies the Value dependency property. /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1002:AvaloniaProperty objects should not be owned by a generic type", + Justification = "This property is not supposed to be used from XAML.")] public static readonly StyledProperty ValueProperty = AvaloniaProperty.Register, T>(nameof(Value)); diff --git a/src/Avalonia.Controls/ContextMenu.cs b/src/Avalonia.Controls/ContextMenu.cs index fc4b11bd4a..63e28ea14d 100644 --- a/src/Avalonia.Controls/ContextMenu.cs +++ b/src/Avalonia.Controls/ContextMenu.cs @@ -56,6 +56,8 @@ namespace Avalonia.Controls /// /// Defines the property. /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1013", + Justification = "We keep PlacementModeProperty for backward compatibility.")] public static readonly StyledProperty PlacementProperty = Popup.PlacementProperty.AddOwner(); diff --git a/src/Avalonia.Controls/ListBox.cs b/src/Avalonia.Controls/ListBox.cs index e665c2db90..e5f0b50555 100644 --- a/src/Avalonia.Controls/ListBox.cs +++ b/src/Avalonia.Controls/ListBox.cs @@ -29,18 +29,24 @@ namespace Avalonia.Controls /// /// Defines the property. /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1010", + Justification = "This property is owned by SelectingItemsControl, but protected there. ListBox changes its visibility.")] public static readonly new DirectProperty SelectedItemsProperty = SelectingItemsControl.SelectedItemsProperty; /// /// Defines the property. /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1010", + Justification = "This property is owned by SelectingItemsControl, but protected there. ListBox changes its visibility.")] public static readonly new DirectProperty SelectionProperty = SelectingItemsControl.SelectionProperty; /// /// Defines the property. /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1010", + Justification = "This property is owned by SelectingItemsControl, but protected there. ListBox changes its visibility.")] public static readonly new StyledProperty SelectionModeProperty = SelectingItemsControl.SelectionModeProperty; @@ -84,6 +90,8 @@ namespace Avalonia.Controls /// Note that the selection mode only applies to selections made via user interaction. /// Multiple selections can be made programmatically regardless of the value of this property. /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1012", + Justification = "This property is owned by SelectingItemsControl, but protected there. ListBox changes its visibility.")] public new SelectionMode SelectionMode { get { return base.SelectionMode; } diff --git a/src/Avalonia.Controls/Primitives/VisualLayerManager.cs b/src/Avalonia.Controls/Primitives/VisualLayerManager.cs index 351ed5d716..35676474dd 100644 --- a/src/Avalonia.Controls/Primitives/VisualLayerManager.cs +++ b/src/Avalonia.Controls/Primitives/VisualLayerManager.cs @@ -29,6 +29,9 @@ namespace Avalonia.Controls.Primitives } } + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1030")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1031", + Justification = "A hack to make ChromeOverlayLayer lazily creatable. It is expected that GetValue(ChromeOverlayLayerProperty) alone won't work.")] public ChromeOverlayLayer ChromeOverlayLayer { get diff --git a/src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs b/src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs index db83977bc6..45227eef77 100644 --- a/src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs +++ b/src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs @@ -71,6 +71,7 @@ namespace Avalonia.Controls /// /// Gets or sets a value that indicates the refresh state of the visualizer. /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1032", Justification = "False positive")] protected RefreshVisualizerState RefreshVisualizerState { get diff --git a/src/Avalonia.Controls/SplitView/SplitViewTemplateSettings.cs b/src/Avalonia.Controls/SplitView/SplitViewTemplateSettings.cs index f2cbf55986..8c59de7420 100644 --- a/src/Avalonia.Controls/SplitView/SplitViewTemplateSettings.cs +++ b/src/Avalonia.Controls/SplitView/SplitViewTemplateSettings.cs @@ -17,12 +17,14 @@ AvaloniaProperty.Register( nameof(PaneColumnGridLength)); + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1032", Justification = "This property is supposed to be a styled readonly property.")] public double ClosedPaneWidth { get => GetValue(ClosedPaneWidthProperty); internal set => SetValue(ClosedPaneWidthProperty, value); } + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1032", Justification = "This property is supposed to be a styled readonly property.")] public GridLength PaneColumnGridLength { get => GetValue(PaneColumnGridLengthProperty); diff --git a/src/Avalonia.Controls/TabControl.cs b/src/Avalonia.Controls/TabControl.cs index 502e128641..2e27cfd123 100644 --- a/src/Avalonia.Controls/TabControl.cs +++ b/src/Avalonia.Controls/TabControl.cs @@ -115,6 +115,7 @@ namespace Avalonia.Controls /// /// The content of the selected tab. /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1032", Justification = "This property is supposed to be a styled readonly property.")] public object? SelectedContent { get { return GetValue(SelectedContentProperty); } @@ -127,6 +128,7 @@ namespace Avalonia.Controls /// /// The content template of the selected tab. /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1032", Justification = "This property is supposed to be a styled readonly property.")] public IDataTemplate? SelectedContentTemplate { get { return GetValue(SelectedContentTemplateProperty); } diff --git a/src/Avalonia.Controls/TabItem.cs b/src/Avalonia.Controls/TabItem.cs index 8303153a4b..60e9a7c88c 100644 --- a/src/Avalonia.Controls/TabItem.cs +++ b/src/Avalonia.Controls/TabItem.cs @@ -42,6 +42,8 @@ namespace Avalonia.Controls /// /// The tab strip placement. /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1031", + Justification = "This property is supposed to be inherited only and settable on parent TabControl.")] public Dock TabStripPlacement { get { return GetValue(TabStripPlacementProperty); } diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 07b1e9b51f..f86554ec4f 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -83,11 +83,11 @@ namespace Avalonia.Controls /// public static readonly StyledProperty ActualThemeVariantProperty = - ThemeVariantScope.ActualThemeVariantProperty.AddOwner(); + ThemeVariantScope.ActualThemeVariantProperty.AddOwner(); /// public static readonly StyledProperty RequestedThemeVariantProperty = - ThemeVariantScope.RequestedThemeVariantProperty.AddOwner(); + ThemeVariantScope.RequestedThemeVariantProperty.AddOwner(); /// /// Defines the SystemBarColor attached property. diff --git a/src/Avalonia.ReactiveUI/ReactiveUserControl.cs b/src/Avalonia.ReactiveUI/ReactiveUserControl.cs index 21cdef2634..b0978dc3f6 100644 --- a/src/Avalonia.ReactiveUI/ReactiveUserControl.cs +++ b/src/Avalonia.ReactiveUI/ReactiveUserControl.cs @@ -17,6 +17,7 @@ namespace Avalonia.ReactiveUI /// ViewModel type. public class ReactiveUserControl : UserControl, IViewFor where TViewModel : class { + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1002", Justification = "Generic avalonia property is expected here.")] public static readonly StyledProperty ViewModelProperty = AvaloniaProperty .Register, TViewModel?>(nameof(ViewModel)); diff --git a/src/Avalonia.ReactiveUI/ReactiveWindow.cs b/src/Avalonia.ReactiveUI/ReactiveWindow.cs index 726fb3d661..14e9353096 100644 --- a/src/Avalonia.ReactiveUI/ReactiveWindow.cs +++ b/src/Avalonia.ReactiveUI/ReactiveWindow.cs @@ -17,6 +17,7 @@ namespace Avalonia.ReactiveUI /// ViewModel type. public class ReactiveWindow : Window, IViewFor where TViewModel : class { + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1002", Justification = "Generic avalonia property is expected here.")] public static readonly StyledProperty ViewModelProperty = AvaloniaProperty .Register, TViewModel?>(nameof(ViewModel)); From ad96c64aa26710a20eaafaeb06e62948b4b46ecf Mon Sep 17 00:00:00 2001 From: Max Katz Date: Mon, 17 Apr 2023 01:39:13 -0400 Subject: [PATCH 06/13] Mark Avalonia Analyzers as errors --- .editorconfig | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.editorconfig b/.editorconfig index a144ec8843..6337257e8f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -186,6 +186,23 @@ csharp_wrap_before_ternary_opsigns = false # Avalonia DevAnalyzer preferences dotnet_diagnostic.AVADEV2001.severity = error +# Avalonia PublicAnalyzer preferences +dotnet_diagnostic.AVP1000.severity = error +dotnet_diagnostic.AVP1001.severity = error +dotnet_diagnostic.AVP1002.severity = error +dotnet_diagnostic.AVP1010.severity = error +dotnet_diagnostic.AVP1011.severity = error +dotnet_diagnostic.AVP1012.severity = error +dotnet_diagnostic.AVP1013.severity = error +dotnet_diagnostic.AVP1020.severity = error +dotnet_diagnostic.AVP1021.severity = error +dotnet_diagnostic.AVP1022.severity = error +dotnet_diagnostic.AVP1030.severity = error +dotnet_diagnostic.AVP1031.severity = error +dotnet_diagnostic.AVP1032.severity = error +dotnet_diagnostic.AVP1040.severity = error +dotnet_diagnostic.AVA2001.severity = error + # Xaml files [*.{xaml,axaml}] indent_size = 2 From 3c6fa1a578841b74d213b65ef1dac0191e19da26 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Mon, 17 Apr 2023 01:39:20 -0400 Subject: [PATCH 07/13] Fix missed ItemsSource --- src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml b/src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml index 6004d42120..5ec91ec9b9 100644 --- a/src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml @@ -3,7 +3,7 @@ - + Alabama Alaska Arizona @@ -12,7 +12,7 @@ Colorado Connecticut Delaware - + From d3fb8dee89dc9fd398ece99dd743b3b94bc4666f Mon Sep 17 00:00:00 2001 From: Max Katz Date: Mon, 17 Apr 2023 02:16:37 -0400 Subject: [PATCH 08/13] Build fixes --- samples/IntegrationTestApp/IntegrationTestApp.csproj | 1 + src/Avalonia.Controls/Application.cs | 2 ++ src/Avalonia.Controls/AutoCompleteBox/AutoCompleteFilterMode.cs | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/samples/IntegrationTestApp/IntegrationTestApp.csproj b/samples/IntegrationTestApp/IntegrationTestApp.csproj index 1356eeb526..398743a353 100644 --- a/samples/IntegrationTestApp/IntegrationTestApp.csproj +++ b/samples/IntegrationTestApp/IntegrationTestApp.csproj @@ -3,6 +3,7 @@ WinExe net7.0 enable + $(NoWarn);AVP1012 diff --git a/src/Avalonia.Controls/Application.cs b/src/Avalonia.Controls/Application.cs index be3d5424fb..e907fd5988 100644 --- a/src/Avalonia.Controls/Application.cs +++ b/src/Avalonia.Controls/Application.cs @@ -94,6 +94,8 @@ namespace Avalonia } /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1031", Justification = "This property is supposed to be a styled readonly property.")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1030", Justification = "False positive.")] public ThemeVariant ActualThemeVariant => GetValue(ActualThemeVariantProperty); /// diff --git a/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteFilterMode.cs b/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteFilterMode.cs index c17f5a19ab..fa956a79fe 100644 --- a/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteFilterMode.cs +++ b/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteFilterMode.cs @@ -9,7 +9,7 @@ namespace Avalonia.Controls { /// /// Specifies how text in the text box portion of the - /// control is used to filter items specified by the + /// control is used to filter items specified by the /// property for display in the drop-down. /// public enum AutoCompleteFilterMode From 7e0a7d5aab0b9f83e5d423267031d1c0292b5040 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Tue, 18 Apr 2023 22:32:42 -0400 Subject: [PATCH 09/13] Disable more analyzers --- src/tools/Avalonia.Analyzers/AvaloniaPropertyAnalyzer.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tools/Avalonia.Analyzers/AvaloniaPropertyAnalyzer.cs b/src/tools/Avalonia.Analyzers/AvaloniaPropertyAnalyzer.cs index 9eb4cecc8b..7de0e8eac4 100644 --- a/src/tools/Avalonia.Analyzers/AvaloniaPropertyAnalyzer.cs +++ b/src/tools/Avalonia.Analyzers/AvaloniaPropertyAnalyzer.cs @@ -129,7 +129,7 @@ public partial class AvaloniaPropertyAnalyzer : DiagnosticAnalyzer "Bad name: An AvaloniaProperty named '{0}' is being assigned to {1}. These names do not relate.", Category, DiagnosticSeverity.Warning, - isEnabledByDefault: true, + isEnabledByDefault: false, // TODO: autogenerate property metadata preserved in ref assembly "An AvaloniaProperty should be stored in a field or property which contains its name. For example, a property named \"Brush\" should be assigned to a field called \"BrushProperty\".\nPrivate symbols are exempt from this diagnostic.", NameCollisionTag); @@ -139,7 +139,7 @@ public partial class AvaloniaPropertyAnalyzer : DiagnosticAnalyzer "Side effects: '{0}' is an AvaloniaProperty which can be {1} without the use of this CLR property. This {2} accessor should do nothing except call {3}.", Category, DiagnosticSeverity.Warning, - isEnabledByDefault: true, + isEnabledByDefault: false, // TODO: autogenerate property metadata preserved in ref assembly "The AvaloniaObject.GetValue and AvaloniaObject.SetValue methods are public, and do not call any user CLR properties. To execute code before or after the property is set, consider: 1) adding a Coercion method, b) adding a static observer with AvaloniaProperty.Changed.AddClassHandler, and/or c) overriding the AvaloniaObject.OnPropertyChanged method.", AssociatedClrPropertyTag); @@ -149,7 +149,7 @@ public partial class AvaloniaPropertyAnalyzer : DiagnosticAnalyzer "Missing accessor: {0} is {1}, but this CLR property lacks a {2} accessor", Category, DiagnosticSeverity.Warning, - isEnabledByDefault: true, + isEnabledByDefault: false, // TODO: autogenerate property metadata preserved in ref assembly "The AvaloniaObject.GetValue and AvaloniaObject.SetValue methods are public, and do not call CLR properties on the owning type. Not providing both CLR property accessors is ineffective.", AssociatedClrPropertyTag); @@ -159,7 +159,7 @@ public partial class AvaloniaPropertyAnalyzer : DiagnosticAnalyzer "Inconsistent accessibility: CLR {0} accessibility does not match accessibility of {1}", Category, DiagnosticSeverity.Warning, - isEnabledByDefault: true, + isEnabledByDefault: false, // TODO: autogenerate property metadata preserved in ref assembly "The AvaloniaObject.GetValue and AvaloniaObject.SetValue methods are public, and do not call CLR properties on the owning type. Defining a CLR property with different accessibility from its associated AvaloniaProperty is ineffective.", AssociatedClrPropertyTag); From f522845a583cf1f911c909625a64119c7e70b972 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Tue, 18 Apr 2023 22:37:34 -0400 Subject: [PATCH 10/13] Fix AutoCompleteBox --- .../Controls/AutoCompleteBox.xaml | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml b/src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml index 5ec91ec9b9..2113ae4cb0 100644 --- a/src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml @@ -1,17 +1,20 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:generic="using:System.Collections.Generic"> - Alabama - Alaska - Arizona - Arkansas - California - Colorado - Connecticut - Delaware + + Alabama + Alaska + Arizona + Arkansas + California + Colorado + Connecticut + Delaware + From 6523320a7b73f13aba091069b2b58fd69692d25c Mon Sep 17 00:00:00 2001 From: Max Katz Date: Tue, 18 Apr 2023 22:43:38 -0400 Subject: [PATCH 11/13] Revert some of SetCurrentValue This reverts commit ead92a6122a4617b19b40356fd537b50d91fa449. --- src/Avalonia.Base/Media/DashStyle.cs | 2 +- src/Avalonia.Base/Media/GradientBrush.cs | 2 +- src/Avalonia.Base/Media/PolyLineSegment.cs | 2 +- src/Avalonia.Base/Media/TransformGroup.cs | 9 ++++----- src/Avalonia.Controls/Calendar/CalendarButton.cs | 2 +- src/Avalonia.Controls/Calendar/CalendarDayButton.cs | 2 +- src/Avalonia.Controls/Documents/Span.cs | 4 ++-- src/Avalonia.Controls/GridSplitter.cs | 2 +- src/Avalonia.Controls/LayoutTransformControl.cs | 2 +- src/Avalonia.Controls/NativeMenuItemSeparator.cs | 2 +- src/Avalonia.Controls/Primitives/OverlayPopupHost.cs | 2 +- .../Primitives/SelectingItemsControl.cs | 8 ++++---- .../PullToRefresh/RefreshVisualizer.cs | 2 +- src/Avalonia.Controls/TabControl.cs | 11 +++++------ src/Avalonia.Controls/TabItem.cs | 6 +++--- 15 files changed, 28 insertions(+), 30 deletions(-) diff --git a/src/Avalonia.Base/Media/DashStyle.cs b/src/Avalonia.Base/Media/DashStyle.cs index 338737d2ab..4749bfa401 100644 --- a/src/Avalonia.Base/Media/DashStyle.cs +++ b/src/Avalonia.Base/Media/DashStyle.cs @@ -46,7 +46,7 @@ namespace Avalonia.Media /// The dash sequence offset. public DashStyle(IEnumerable? dashes, double offset) { - SetCurrentValue(DashesProperty, (dashes as AvaloniaList) ?? new AvaloniaList(dashes ?? Array.Empty())); + Dashes = (dashes as AvaloniaList) ?? new AvaloniaList(dashes ?? Array.Empty()); Offset = offset; } diff --git a/src/Avalonia.Base/Media/GradientBrush.cs b/src/Avalonia.Base/Media/GradientBrush.cs index 0ec753201a..e1654a01b2 100644 --- a/src/Avalonia.Base/Media/GradientBrush.cs +++ b/src/Avalonia.Base/Media/GradientBrush.cs @@ -40,7 +40,7 @@ namespace Avalonia.Media /// public GradientBrush() { - SetCurrentValue(GradientStopsProperty, new GradientStops()); + this.GradientStops = new GradientStops(); } /// diff --git a/src/Avalonia.Base/Media/PolyLineSegment.cs b/src/Avalonia.Base/Media/PolyLineSegment.cs index 7de5e1afa5..5c48c11e19 100644 --- a/src/Avalonia.Base/Media/PolyLineSegment.cs +++ b/src/Avalonia.Base/Media/PolyLineSegment.cs @@ -30,7 +30,7 @@ namespace Avalonia.Media /// public PolyLineSegment() { - SetCurrentValue(PointsProperty, new Points()); + Points = new Points(); } /// diff --git a/src/Avalonia.Base/Media/TransformGroup.cs b/src/Avalonia.Base/Media/TransformGroup.cs index c048234f8c..0465efd5a5 100644 --- a/src/Avalonia.Base/Media/TransformGroup.cs +++ b/src/Avalonia.Base/Media/TransformGroup.cs @@ -13,16 +13,15 @@ namespace Avalonia.Media public TransformGroup() { - var children = new Transforms(); - children.ResetBehavior = ResetBehavior.Remove; - children.CollectionChanged += delegate + Children = new Transforms(); + Children.ResetBehavior = ResetBehavior.Remove; + Children.CollectionChanged += delegate { - children.ForEachItem( + Children.ForEachItem( (tr) => tr.Changed += ChildTransform_Changed, (tr) => tr.Changed -= ChildTransform_Changed, () => { }); }; - SetCurrentValue(ChildrenProperty, children); } private void ChildTransform_Changed(object? sender, System.EventArgs e) diff --git a/src/Avalonia.Controls/Calendar/CalendarButton.cs b/src/Avalonia.Controls/Calendar/CalendarButton.cs index b35298b101..d8672cbf18 100644 --- a/src/Avalonia.Controls/Calendar/CalendarButton.cs +++ b/src/Avalonia.Controls/Calendar/CalendarButton.cs @@ -39,7 +39,7 @@ namespace Avalonia.Controls.Primitives public CalendarButton() : base() { - SetCurrentValue(ContentProperty, DateTimeHelper.GetCurrentDateFormat().AbbreviatedMonthNames[0]); + Content = DateTimeHelper.GetCurrentDateFormat().AbbreviatedMonthNames[0]; } /// diff --git a/src/Avalonia.Controls/Calendar/CalendarDayButton.cs b/src/Avalonia.Controls/Calendar/CalendarDayButton.cs index ea3ca8e8fc..3d0befdba7 100644 --- a/src/Avalonia.Controls/Calendar/CalendarDayButton.cs +++ b/src/Avalonia.Controls/Calendar/CalendarDayButton.cs @@ -34,7 +34,7 @@ namespace Avalonia.Controls.Primitives : base() { //Focusable = false; - SetCurrentValue(ContentProperty, DefaultContent.ToString(CultureInfo.CurrentCulture)); + Content = DefaultContent.ToString(CultureInfo.CurrentCulture); } /// diff --git a/src/Avalonia.Controls/Documents/Span.cs b/src/Avalonia.Controls/Documents/Span.cs index a4f3264c4d..d3565cbdd5 100644 --- a/src/Avalonia.Controls/Documents/Span.cs +++ b/src/Avalonia.Controls/Documents/Span.cs @@ -20,10 +20,10 @@ namespace Avalonia.Controls.Documents public Span() { - SetCurrentValue(InlinesProperty, new InlineCollection + Inlines = new InlineCollection { LogicalChildren = LogicalChildren - }); + }; } /// diff --git a/src/Avalonia.Controls/GridSplitter.cs b/src/Avalonia.Controls/GridSplitter.cs index 50d1004f34..4684304725 100644 --- a/src/Avalonia.Controls/GridSplitter.cs +++ b/src/Avalonia.Controls/GridSplitter.cs @@ -707,7 +707,7 @@ namespace Avalonia.Controls RenderTransform = _translation }; - SetCurrentValue(ChildProperty, _decorator); + Child = _decorator; } /// diff --git a/src/Avalonia.Controls/LayoutTransformControl.cs b/src/Avalonia.Controls/LayoutTransformControl.cs index 02d2eeef5b..06069a897e 100644 --- a/src/Avalonia.Controls/LayoutTransformControl.cs +++ b/src/Avalonia.Controls/LayoutTransformControl.cs @@ -176,7 +176,7 @@ namespace Avalonia.Controls else { _renderTransformChangedEvent?.Dispose(); - SetCurrentValue(LayoutTransformProperty, null); + ClearValue(LayoutTransformProperty); } } } diff --git a/src/Avalonia.Controls/NativeMenuItemSeparator.cs b/src/Avalonia.Controls/NativeMenuItemSeparator.cs index 55b3fd08de..f55d714884 100644 --- a/src/Avalonia.Controls/NativeMenuItemSeparator.cs +++ b/src/Avalonia.Controls/NativeMenuItemSeparator.cs @@ -4,7 +4,7 @@ { public NativeMenuItemSeparator() { - SetCurrentValue(HeaderProperty, "-"); + Header = "-"; } } } diff --git a/src/Avalonia.Controls/Primitives/OverlayPopupHost.cs b/src/Avalonia.Controls/Primitives/OverlayPopupHost.cs index 0acc488885..7ed055f2e5 100644 --- a/src/Avalonia.Controls/Primitives/OverlayPopupHost.cs +++ b/src/Avalonia.Controls/Primitives/OverlayPopupHost.cs @@ -31,7 +31,7 @@ namespace Avalonia.Controls.Primitives /// public void SetChild(Control? control) { - SetCurrentValue(ContentProperty, control); + Content = control; } /// diff --git a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs index ac3e87c03d..663a315732 100644 --- a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs +++ b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs @@ -701,7 +701,7 @@ namespace Avalonia.Controls.Primitives if (value is null) { // Clearing SelectedValueBinding makes the SelectedValue the item itself - SetCurrentValue(SelectedValueProperty, SelectedItem); + SelectedValue = SelectedItem; return; } @@ -721,7 +721,7 @@ namespace Avalonia.Controls.Primitives } // Re-evaluate SelectedValue with the new binding - SetCurrentValue(SelectedValueProperty, _bindingHelper.Evaluate(selectedItem)); + SelectedValue = _bindingHelper.Evaluate(selectedItem); } finally { @@ -1092,7 +1092,7 @@ namespace Avalonia.Controls.Primitives try { _isSelectionChangeActive = true; - SetCurrentValue(SelectedValueProperty, item); + SelectedValue = item; } finally { @@ -1106,7 +1106,7 @@ namespace Avalonia.Controls.Primitives try { _isSelectionChangeActive = true; - SetCurrentValue(SelectedValueProperty, _bindingHelper.Evaluate(item)); + SelectedValue = _bindingHelper.Evaluate(item); } finally { diff --git a/src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs b/src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs index 45227eef77..0ee2d69a73 100644 --- a/src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs +++ b/src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs @@ -193,7 +193,7 @@ namespace Avalonia.Controls UpdateContent(); }; - SetCurrentValue(ContentProperty, _content); + Content = _content; } else { diff --git a/src/Avalonia.Controls/TabControl.cs b/src/Avalonia.Controls/TabControl.cs index 2e27cfd123..310dd34382 100644 --- a/src/Avalonia.Controls/TabControl.cs +++ b/src/Avalonia.Controls/TabControl.cs @@ -164,8 +164,8 @@ namespace Avalonia.Controls if (index == SelectedIndex && element is ContentControl container) { - SetCurrentValue(SelectedContentTemplateProperty, container.ContentTemplate); - SetCurrentValue(SelectedContentProperty, container.Content); + SelectedContentTemplate = container.ContentTemplate; + SelectedContent = container.Content; } } @@ -189,15 +189,14 @@ namespace Avalonia.Controls { if (SelectedIndex == -1) { - SetCurrentValue(SelectedContentProperty, null); - SetCurrentValue(SelectedContentTemplateProperty, null); + SelectedContent = SelectedContentTemplate = null; } else { var container = SelectedItem as IContentControl ?? ContainerFromIndex(SelectedIndex) as IContentControl; - SetCurrentValue(SelectedContentTemplateProperty, container?.ContentTemplate); - SetCurrentValue(SelectedContentProperty, container?.Content); + SelectedContentTemplate = container?.ContentTemplate; + SelectedContent = container?.Content; } } diff --git a/src/Avalonia.Controls/TabItem.cs b/src/Avalonia.Controls/TabItem.cs index 60e9a7c88c..4068404952 100644 --- a/src/Avalonia.Controls/TabItem.cs +++ b/src/Avalonia.Controls/TabItem.cs @@ -68,14 +68,14 @@ namespace Avalonia.Controls { if (Header != headered.Header) { - SetCurrentValue(HeaderProperty, headered.Header); + Header = headered.Header; } } else { if (!(obj.NewValue is Control)) { - SetCurrentValue(HeaderProperty, obj.NewValue); + Header = obj.NewValue; } } } @@ -83,7 +83,7 @@ namespace Avalonia.Controls { if (Header == obj.OldValue) { - SetCurrentValue(HeaderProperty, obj.NewValue); + Header = obj.NewValue; } } } From 7d26c16a10ca97a69995af32cb913a6b11fcda6a Mon Sep 17 00:00:00 2001 From: Max Katz Date: Tue, 18 Apr 2023 22:47:53 -0400 Subject: [PATCH 12/13] Configure AVP1012 as a warning --- .editorconfig | 2 +- src/Avalonia.Base/Media/DashStyle.cs | 2 ++ src/Avalonia.Base/Media/GradientBrush.cs | 2 ++ src/Avalonia.Base/Media/PolyLineSegment.cs | 2 ++ src/Avalonia.Base/Media/TransformGroup.cs | 2 ++ src/Avalonia.Controls/Documents/Span.cs | 2 ++ 6 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index 6337257e8f..d07618df6c 100644 --- a/.editorconfig +++ b/.editorconfig @@ -192,7 +192,7 @@ dotnet_diagnostic.AVP1001.severity = error dotnet_diagnostic.AVP1002.severity = error dotnet_diagnostic.AVP1010.severity = error dotnet_diagnostic.AVP1011.severity = error -dotnet_diagnostic.AVP1012.severity = error +dotnet_diagnostic.AVP1012.severity = warning dotnet_diagnostic.AVP1013.severity = error dotnet_diagnostic.AVP1020.severity = error dotnet_diagnostic.AVP1021.severity = error diff --git a/src/Avalonia.Base/Media/DashStyle.cs b/src/Avalonia.Base/Media/DashStyle.cs index 4749bfa401..2529b9317d 100644 --- a/src/Avalonia.Base/Media/DashStyle.cs +++ b/src/Avalonia.Base/Media/DashStyle.cs @@ -44,6 +44,8 @@ namespace Avalonia.Media /// /// The dashes collection. /// The dash sequence offset. + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1012", + Justification = "Collection properties shouldn't be set with SetCurrentValue.")] public DashStyle(IEnumerable? dashes, double offset) { Dashes = (dashes as AvaloniaList) ?? new AvaloniaList(dashes ?? Array.Empty()); diff --git a/src/Avalonia.Base/Media/GradientBrush.cs b/src/Avalonia.Base/Media/GradientBrush.cs index e1654a01b2..971d4fdd58 100644 --- a/src/Avalonia.Base/Media/GradientBrush.cs +++ b/src/Avalonia.Base/Media/GradientBrush.cs @@ -38,6 +38,8 @@ namespace Avalonia.Media /// /// Initializes a new instance of the class. /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1012", + Justification = "Collection properties shouldn't be set with SetCurrentValue.")] public GradientBrush() { this.GradientStops = new GradientStops(); diff --git a/src/Avalonia.Base/Media/PolyLineSegment.cs b/src/Avalonia.Base/Media/PolyLineSegment.cs index 5c48c11e19..276bb66a4a 100644 --- a/src/Avalonia.Base/Media/PolyLineSegment.cs +++ b/src/Avalonia.Base/Media/PolyLineSegment.cs @@ -28,6 +28,8 @@ namespace Avalonia.Media /// /// Initializes a new instance of the class. /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1012", + Justification = "Collection properties shouldn't be set with SetCurrentValue.")] public PolyLineSegment() { Points = new Points(); diff --git a/src/Avalonia.Base/Media/TransformGroup.cs b/src/Avalonia.Base/Media/TransformGroup.cs index 0465efd5a5..ae5e54c414 100644 --- a/src/Avalonia.Base/Media/TransformGroup.cs +++ b/src/Avalonia.Base/Media/TransformGroup.cs @@ -11,6 +11,8 @@ namespace Avalonia.Media public static readonly StyledProperty ChildrenProperty = AvaloniaProperty.Register(nameof(Children)); + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1012", + Justification = "Collection properties shouldn't be set with SetCurrentValue.")] public TransformGroup() { Children = new Transforms(); diff --git a/src/Avalonia.Controls/Documents/Span.cs b/src/Avalonia.Controls/Documents/Span.cs index d3565cbdd5..7931ecbbde 100644 --- a/src/Avalonia.Controls/Documents/Span.cs +++ b/src/Avalonia.Controls/Documents/Span.cs @@ -18,6 +18,8 @@ namespace Avalonia.Controls.Documents AvaloniaProperty.Register( nameof(Inlines)); + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1012", + Justification = "Collection properties shouldn't be set with SetCurrentValue.")] public Span() { Inlines = new InlineCollection From 3da148f5c2732622db5eaeec0906416900635c49 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Wed, 19 Apr 2023 00:33:44 -0400 Subject: [PATCH 13/13] Fix analyzers nuget package --- nukebuild/numerge.config | 5 +++++ .../Avalonia.Analyzers.csproj | 19 ++++++++++++------- .../GeneratorContextExtensions.cs | 2 +- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/nukebuild/numerge.config b/nukebuild/numerge.config index 09f22ec527..71b77bee93 100644 --- a/nukebuild/numerge.config +++ b/nukebuild/numerge.config @@ -16,6 +16,11 @@ "Id": "Avalonia.Generators", "IgnoreMissingFrameworkBinaries": true, "DoNotMergeDependencies": true + }, + { + "Id": "Avalonia.Analyzers", + "IgnoreMissingFrameworkBinaries": true, + "DoNotMergeDependencies": true } ] } diff --git a/src/tools/Avalonia.Analyzers/Avalonia.Analyzers.csproj b/src/tools/Avalonia.Analyzers/Avalonia.Analyzers.csproj index 39eaab1289..c27801db61 100644 --- a/src/tools/Avalonia.Analyzers/Avalonia.Analyzers.csproj +++ b/src/tools/Avalonia.Analyzers/Avalonia.Analyzers.csproj @@ -1,17 +1,22 @@  - netstandard2.0 - enable + false + Avalonia.Analyzers true + true + true - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + + + + + + diff --git a/src/tools/Avalonia.Generators/GeneratorContextExtensions.cs b/src/tools/Avalonia.Generators/GeneratorContextExtensions.cs index d057e8732e..3e4426e6bb 100644 --- a/src/tools/Avalonia.Generators/GeneratorContextExtensions.cs +++ b/src/tools/Avalonia.Generators/GeneratorContextExtensions.cs @@ -20,7 +20,7 @@ internal static class GeneratorContextExtensions public static void ReportNameGeneratorUnhandledError(this GeneratorExecutionContext context, Exception error) => context.Report(UnhandledErrorDescriptorId, "Unhandled exception occured while generating typed Name references. " + - "Please file an issue: https://github.com/avaloniaui/Avalonia.Generators", + "Please file an issue: https://github.com/avaloniaui/Avalonia", error.ToString()); public static void ReportNameGeneratorInvalidType(this GeneratorExecutionContext context, string typeName) =>