Skip to content

Commit 709830b

Browse files
committed
Handle missing explicit : UserControl
Fix #302
1 parent 31c44e2 commit 709830b

2 files changed

Lines changed: 55 additions & 1 deletion

File tree

WpfAnalyzers.Test/WPF0015RegisteredOwnerTypeMustBeDependencyObjectTests/Valid.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,4 +287,36 @@ public static int GetBar(DependencyObject element)
287287

288288
RoslynAssert.Valid(Analyzer, code);
289289
}
290+
291+
[Test]
292+
public static void Issue302()
293+
{
294+
var code = @"
295+
namespace N
296+
{
297+
using System.Windows;
298+
using System.Windows.Controls;
299+
300+
public class FooControl
301+
{
302+
public static readonly DependencyProperty BarProperty = DependencyProperty.Register(
303+
""Bar"",
304+
typeof(int),
305+
typeof(FooControl),
306+
new PropertyMetadata(default(int)));
307+
308+
public FooControl()
309+
{
310+
this.InitializeComponent();
311+
}
312+
313+
public int Bar
314+
{
315+
get { return (int)GetValue(BarProperty); }
316+
set { SetValue(BarProperty, value); }
317+
}
318+
}
319+
}";
320+
RoslynAssert.NoAnalyzerDiagnostics(Analyzer, code);
321+
}
290322
}

WpfAnalyzers/WPF0015RegisteredOwnerTypeMustBeDependencyObject.cs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
namespace WpfAnalyzers;
22

33
using System.Collections.Immutable;
4+
45
using Gu.Roslyn.AnalyzerExtensions;
6+
57
using Microsoft.CodeAnalysis;
68
using Microsoft.CodeAnalysis.CSharp;
79
using Microsoft.CodeAnalysis.CSharp.Syntax;
@@ -44,9 +46,29 @@ private static void Handle(SyntaxNodeAnalysisContext context)
4446
private static void HandleArgument(SyntaxNodeAnalysisContext context, ArgumentSyntax argument)
4547
{
4648
if (argument.TryGetTypeofValue(context.SemanticModel, context.CancellationToken, out var ownerType) &&
47-
!ownerType.IsAssignableTo(KnownSymbols.DependencyObject, context.SemanticModel.Compilation))
49+
!ownerType.IsAssignableTo(KnownSymbols.DependencyObject, context.SemanticModel.Compilation) &&
50+
!IsUserControl())
4851
{
4952
context.ReportDiagnostic(Diagnostic.Create(Descriptors.WPF0015RegisteredOwnerTypeMustBeDependencyObject, argument.GetLocation(), KnownSymbols.DependencyProperty.RegisterAttached.Name));
5053
}
54+
55+
bool IsUserControl() => context.Node.FirstAncestor<ClassDeclarationSyntax>() is { } classDeclaration &&
56+
!classDeclaration.Modifiers.Any(SyntaxKind.StaticKeyword) &&
57+
classDeclaration.TryFindConstructor(x => x.ParameterList.Parameters.Count == 0, out var ctor) &&
58+
InvokesInitializeComponent(ctor);
59+
60+
bool InvokesInitializeComponent(ConstructorDeclarationSyntax ctor)
61+
{
62+
using var walker = Gu.Roslyn.AnalyzerExtensions.InvocationWalker.Borrow(ctor);
63+
foreach (var candidate in walker.Invocations)
64+
{
65+
if (candidate.MethodName() == "InitializeComponent")
66+
{
67+
return true;
68+
}
69+
}
70+
71+
return false;
72+
}
5173
}
5274
}

0 commit comments

Comments
 (0)