public void ControlSetCurrentValue(string before, string after) { var testCode = @" namespace RoslynSandbox { using System.Windows; using System.Windows.Controls; public class FooControl : Control { public static void Meh() { var control = new Control(); ↓control.SetCurrentValue(FrameworkElement.DataContextProperty, 1); } } }".AssertReplace("control.SetCurrentValue(FrameworkElement.DataContextProperty, 1);", before); var fixedCode = @" namespace RoslynSandbox { using System.Windows; using System.Windows.Controls; public class FooControl : Control { public static void Meh() { var control = new Control(); control.SetValue(FrameworkElement.DataContextProperty, 1); } } }".AssertReplace("control.SetValue(FrameworkElement.DataContextProperty, 1);", after); RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, testCode, fixedCode); }
public static void ControlSetCurrentValueStyleProperty(string expressionBefore, string expressionAfter) { var before = @" namespace N { using System.Windows; using System.Windows.Controls; public class FooControl : Control { public static void Meh() { var control = new Control(); ↓control.SetCurrentValue(FrameworkElement.StyleProperty, null); } } }".AssertReplace("control.SetCurrentValue(FrameworkElement.StyleProperty, null);", expressionBefore); var after = @" namespace N { using System.Windows; using System.Windows.Controls; public class FooControl : Control { public static void Meh() { var control = new Control(); control.SetValue(FrameworkElement.StyleProperty, null); } } }".AssertReplace("control.SetValue(FrameworkElement.StyleProperty, null);", expressionAfter); RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, before, after); }
public static void WhenMethodAttribute(string before, string after) { var code = @" namespace AspBox { using Microsoft.AspNetCore.Mvc; [ApiController] public class OrdersController : Controller { [HttpGet(""api/Orders/{id}"")] public IActionResult GetId(string id) { return this.Ok(id); } } }".AssertReplace("\"api/Orders/{id}\"", before); var fixedCode = @" namespace AspBox { using Microsoft.AspNetCore.Mvc; [ApiController] public class OrdersController : Controller { [HttpGet(""api/orders/{id}"")] public IActionResult GetId(string id) { return this.Ok(id); } } }".AssertReplace("\"api/orders/{id}\"", after); RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, code, fixedCode); }
public static void DisposeMemberWhenVirtualDisposeMethodUnderscoreNames() { var before = @" namespace N { using System; public abstract class C : IDisposable { ↓private readonly IDisposable _disposable = new Disposable(); private bool _disposed; public void Dispose() { Dispose(true); } protected virtual void Dispose(bool disposing) { if (_disposed) { return; } _disposed = true; if (disposing) { } } protected void ThrowIfDisposed() { if (_disposed) { throw new ObjectDisposedException(GetType().FullName); } } } }"; var after = @" namespace N { using System; public abstract class C : IDisposable { private readonly IDisposable _disposable = new Disposable(); private bool _disposed; public void Dispose() { Dispose(true); } protected virtual void Dispose(bool disposing) { if (_disposed) { return; } _disposed = true; if (disposing) { _disposable.Dispose(); } } protected void ThrowIfDisposed() { if (_disposed) { throw new ObjectDisposedException(GetType().FullName); } } } }"; RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, new[] { Disposable, before }, after); RoslynAssert.FixAll(Analyzer, Fix, ExpectedDiagnostic, new[] { Disposable, before }, after); }
public static void WhenCallingBaseDispose() { var baseClass = @" namespace N { using System; public abstract class BaseClass : IDisposable { private readonly IDisposable disposable = new Disposable(); private bool disposed; /// <inheritdoc/> public void Dispose() { this.Dispose(true); } protected virtual void Dispose(bool disposing) { if (this.disposed) { return; } this.disposed = true; if (disposing) { this.disposable.Dispose(); } } } }"; var before = @" namespace N { using System; public class C : BaseClass { ↓private readonly IDisposable disposable = new Disposable(); protected override void Dispose(bool disposing) { base.Dispose(disposing); } } }"; var after = @" namespace N { using System; public class C : BaseClass { private readonly IDisposable disposable = new Disposable(); protected override void Dispose(bool disposing) { if (disposing) { this.disposable.Dispose(); } base.Dispose(disposing); } } }"; RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, new[] { Disposable, baseClass, before }, after); RoslynAssert.FixAll(Analyzer, Fix, ExpectedDiagnostic, new[] { Disposable, baseClass, before }, after); }
public static void AssignedInCoalesce() { var before = @" namespace N { using System; public sealed class C : IDisposable { ↓private readonly IDisposable created; private bool disposed; public C(IDisposable injected) { this.Disposable = injected ?? (this.created = new Disposable()); } public IDisposable Disposable { get; } public void Dispose() { if (this.disposed) { return; } this.disposed = true; } } }"; var after = @" namespace N { using System; public sealed class C : IDisposable { private readonly IDisposable created; private bool disposed; public C(IDisposable injected) { this.Disposable = injected ?? (this.created = new Disposable()); } public IDisposable Disposable { get; } public void Dispose() { if (this.disposed) { return; } this.disposed = true; this.created?.Dispose(); } } }"; RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, new[] { Disposable, before }, after); RoslynAssert.FixAll(Analyzer, Fix, ExpectedDiagnostic, new[] { Disposable, before }, after); }
public static void SetValueInCallback() { var before = @" namespace N { using System.Windows; public static class Foo { public static readonly DependencyProperty ValueProperty = DependencyProperty.RegisterAttached( ""Value"", typeof(int), typeof(Foo), new PropertyMetadata( default(int), OnValueChanged)); public static readonly DependencyProperty SynchronizedProperty = DependencyProperty.RegisterAttached(""Synchronized"", typeof(int), typeof(Foo), new PropertyMetadata(default(int))); public static void SetValue(this DependencyObject element, int value) { element.SetValue(ValueProperty, value); } [AttachedPropertyBrowsableForChildren(IncludeDescendants = false)] [AttachedPropertyBrowsableForType(typeof(DependencyObject))] public static int GetValue(this DependencyObject element) { return (int)element.GetValue(ValueProperty); } public static void SetSynchronized(this DependencyObject element, int value) { element.SetValue(SynchronizedProperty, value); } [AttachedPropertyBrowsableForChildren(IncludeDescendants = false)] [AttachedPropertyBrowsableForType(typeof(DependencyObject))] public static int GetSynchronized(this DependencyObject element) { return (int)element.GetValue(SynchronizedProperty); } private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ↓d.SetValue(SynchronizedProperty, e.NewValue); } } }"; var after = @" namespace N { using System.Windows; public static class Foo { public static readonly DependencyProperty ValueProperty = DependencyProperty.RegisterAttached( ""Value"", typeof(int), typeof(Foo), new PropertyMetadata( default(int), OnValueChanged)); public static readonly DependencyProperty SynchronizedProperty = DependencyProperty.RegisterAttached(""Synchronized"", typeof(int), typeof(Foo), new PropertyMetadata(default(int))); public static void SetValue(this DependencyObject element, int value) { element.SetValue(ValueProperty, value); } [AttachedPropertyBrowsableForChildren(IncludeDescendants = false)] [AttachedPropertyBrowsableForType(typeof(DependencyObject))] public static int GetValue(this DependencyObject element) { return (int)element.GetValue(ValueProperty); } public static void SetSynchronized(this DependencyObject element, int value) { element.SetValue(SynchronizedProperty, value); } [AttachedPropertyBrowsableForChildren(IncludeDescendants = false)] [AttachedPropertyBrowsableForType(typeof(DependencyObject))] public static int GetSynchronized(this DependencyObject element) { return (int)element.GetValue(SynchronizedProperty); } private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { d.SetCurrentValue(SynchronizedProperty, e.NewValue); } } }"; RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, before, after); }
public static void StaticMemberFromOutside(string statementBefore, string statementAfter) { var fooControl = @" namespace N { using System.Windows; using System.Windows.Controls; public class FooControl : Control { public static readonly DependencyProperty BarProperty = DependencyProperty.Register( ""Bar"", typeof(double), typeof(FooControl), new PropertyMetadata(default(double))); public double Bar { get { return (double)this.GetValue(BarProperty); } set { this.SetValue(BarProperty, value); } } } }"; var before = @" namespace N { using System.Windows; using System.Windows.Controls; public static class Foo { private static readonly FooControl FooControl = new FooControl(); public static void M() { ↓FooControl.Bar = 1; } private static double CreateValue() => 4; private static object CreateObjectValue() => 4; } }".AssertReplace("↓FooControl.Bar = 1;", statementBefore); var after = @" namespace N { using System.Windows; using System.Windows.Controls; public static class Foo { private static readonly FooControl FooControl = new FooControl(); public static void M() { FooControl.SetCurrentValue(FooControl.BarProperty, 1); } private static double CreateValue() => 4; private static object CreateObjectValue() => 4; } }".AssertReplace("FooControl.SetCurrentValue(FooControl.BarProperty, 1);", statementAfter); RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, new[] { before, fooControl }, after); }
public void DependencyPropertyRegisterStaticCallbackCallingInstance() { var testCode = @" namespace RoslynSandbox { using System.Windows; using System.Windows.Controls; public class FooControl : Control { /// <summary>Identifies the <see cref=""Value""/> dependency property.</summary> public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( nameof(Value), typeof(double), typeof(FooControl), new PropertyMetadata( default(double), new PropertyChangedCallback(OnValueChanged))); public double Value { get => (double)this.GetValue(ValueProperty); set => this.SetValue(ValueProperty, value); } protected virtual void ↓OnValueChanged(double oldValue, double newValue) { } private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((FooControl)d).OnValueChanged((double)e.OldValue, (double)e.NewValue); } } }"; var fixedCode = @" namespace RoslynSandbox { using System.Windows; using System.Windows.Controls; public class FooControl : Control { /// <summary>Identifies the <see cref=""Value""/> dependency property.</summary> public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( nameof(Value), typeof(double), typeof(FooControl), new PropertyMetadata( default(double), new PropertyChangedCallback(OnValueChanged))); public double Value { get => (double)this.GetValue(ValueProperty); set => this.SetValue(ValueProperty, value); } /// <summary>This method is invoked when the <see cref=""ValueProperty""/> changes.</summary> /// <param name=""oldValue"">The old value of <see cref=""ValueProperty""/>.</param> /// <param name=""newValue"">The new value of <see cref=""ValueProperty""/>.</param> protected virtual void OnValueChanged(double oldValue, double newValue) { } private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((FooControl)d).OnValueChanged((double)e.OldValue, (double)e.NewValue); } } }"; RoslynAssert.Valid(Analyzer, fixedCode); RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, testCode, fixedCode); }
public static void WhenSettingNestedField() { var c1 = @" namespace N { public class C1 { public int C1Value; } }"; var before = @" namespace N { using System.ComponentModel; using System.Runtime.CompilerServices; public class C : INotifyPropertyChanged { private readonly C1 c1 = new C1(); public event PropertyChangedEventHandler PropertyChanged; public int Value { get => this.c1.C1Value; set { this.c1.C1Value = value; ↓this.OnPropertyChanged(); } } protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }"; var after = @" namespace N { using System.ComponentModel; using System.Runtime.CompilerServices; public class C : INotifyPropertyChanged { private readonly C1 c1 = new C1(); public event PropertyChangedEventHandler PropertyChanged; public int Value { get => this.c1.C1Value; set { if (value == this.c1.C1Value) { return; } this.c1.C1Value = value; this.OnPropertyChanged(); } } protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }"; RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, new[] { c1, before }, after); RoslynAssert.FixAll(Analyzer, Fix, ExpectedDiagnostic, new[] { c1, before }, after); }
public static void PropertyChangedInvokeNoNullCheck() { var before = @" namespace N { using System.ComponentModel; using System.Runtime.CompilerServices; public class C : INotifyPropertyChanged { private int value; public event PropertyChangedEventHandler PropertyChanged; public int Value { get { return this.value; } set { this.value = value; ↓this.PropertyChanged(this, new PropertyChangedEventArgs(nameof(Value))); } } } }"; var after = @" namespace N { using System.ComponentModel; using System.Runtime.CompilerServices; public class C : INotifyPropertyChanged { private int value; public event PropertyChangedEventHandler PropertyChanged; public int Value { get { return this.value; } set { if (value == this.value) { return; } this.value = value; this.PropertyChanged(this, new PropertyChangedEventArgs(nameof(Value))); } } } }"; RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, before, after); RoslynAssert.FixAll(Analyzer, Fix, ExpectedDiagnostic, before, after); }
public static void PropertyChangedInvokeStaticClass() { var before = @" namespace N { using System.ComponentModel; using System.Runtime.CompilerServices; public static class C { private static int value; public static event PropertyChangedEventHandler PropertyChanged; public static int Value { get { return value; } set { value = value; ↓PropertyChanged.Invoke(null, new PropertyChangedEventArgs(nameof(Value))); } } } }"; var after = @" namespace N { using System.ComponentModel; using System.Runtime.CompilerServices; public static class C { private static int value; public static event PropertyChangedEventHandler PropertyChanged; public static int Value { get { return value; } set { if (value == value) { return; } value = value; PropertyChanged.Invoke(null, new PropertyChangedEventArgs(nameof(Value))); } } } }"; RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, before, after); RoslynAssert.FixAll(Analyzer, Fix, ExpectedDiagnostic, before, after); }
public static void CallsRaisePropertyChangedWithEventArgs() { var before = @" namespace N { using System.ComponentModel; public class C : INotifyPropertyChanged { private int p; public event PropertyChangedEventHandler PropertyChanged; public int P { get { return this.p; } set { this.p = value; ↓this.OnPropertyChanged(new PropertyChangedEventArgs(nameof(P))); } } protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) { this.PropertyChanged?.Invoke(this, e); } } }"; var after = @" namespace N { using System.ComponentModel; public class C : INotifyPropertyChanged { private int p; public event PropertyChangedEventHandler PropertyChanged; public int P { get { return this.p; } set { if (value == this.p) { return; } this.p = value; this.OnPropertyChanged(new PropertyChangedEventArgs(nameof(P))); } } protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) { this.PropertyChanged?.Invoke(this, e); } } }"; RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, before, after); RoslynAssert.FixAll(Analyzer, Fix, ExpectedDiagnostic, before, after); }
public static void DependencyPropertyRegister(string metadata) { var before = @" namespace N { using System; using System.Collections.ObjectModel; using System.Windows; using System.Windows.Controls; public class FooControl : Control { public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( nameof(Value), typeof(double), typeof(FooControl), new PropertyMetadata(1, null, ↓WrongName)); public double Value { get { return (double)this.GetValue(ValueProperty); } set { this.SetValue(ValueProperty, value); } } private static object WrongName(DependencyObject d, object baseValue) { return baseValue; } } }".AssertReplace("new PropertyMetadata(1, null, ↓WrongName)", metadata); var after = @" namespace N { using System; using System.Collections.ObjectModel; using System.Windows; using System.Windows.Controls; public class FooControl : Control { public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( nameof(Value), typeof(double), typeof(FooControl), new PropertyMetadata(1, null, CoerceValue)); public double Value { get { return (double)this.GetValue(ValueProperty); } set { this.SetValue(ValueProperty, value); } } private static object CoerceValue(DependencyObject d, object baseValue) { return baseValue; } } }".AssertReplace("new PropertyMetadata(1, null, CoerceValue)", metadata.AssertReplace("↓WrongName", "CoerceValue")); RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, before, after); RoslynAssert.FixAll(Analyzer, Fix, ExpectedDiagnostic, before, after); }
public static void DependencyPropertyRegisterReadOnly() { var before = @" namespace N { using System.Windows; using System.Windows.Controls; public class FooControl : Control { private static readonly DependencyPropertyKey ValuePropertyKey = DependencyProperty.RegisterReadOnly( nameof(Value), typeof(double), typeof(FooControl), new PropertyMetadata(1.0, null, ↓WrongName)); public static readonly DependencyProperty ValueProperty = ValuePropertyKey.DependencyProperty; public double Value { get { return (double)this.GetValue(ValueProperty); } set { this.SetValue(ValuePropertyKey, value); } } private static object WrongName(DependencyObject d, object baseValue) { return baseValue; } } }"; var after = @" namespace N { using System.Windows; using System.Windows.Controls; public class FooControl : Control { private static readonly DependencyPropertyKey ValuePropertyKey = DependencyProperty.RegisterReadOnly( nameof(Value), typeof(double), typeof(FooControl), new PropertyMetadata(1.0, null, CoerceValue)); public static readonly DependencyProperty ValueProperty = ValuePropertyKey.DependencyProperty; public double Value { get { return (double)this.GetValue(ValueProperty); } set { this.SetValue(ValuePropertyKey, value); } } private static object CoerceValue(DependencyObject d, object baseValue) { return baseValue; } } }"; RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, before, after); }
public void DependencyPropertyRegisterWithMetadata(string metadata) { var testCode = @" namespace RoslynSandbox { using System.Windows; using System.Windows.Controls; public class FooControl : Control { public static readonly DependencyProperty BarProperty = DependencyProperty.Register( nameof(Bar), typeof(int), typeof(FooControl), new PropertyMetadata(default(int), OnBarChanged)); public int Bar { get => (int)this.GetValue(BarProperty); set => this.SetValue(BarProperty, value); } protected virtual void ↓OnBarChanged(object oldValue, object newValue) { } private static void OnBarChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var control = (FooControl)d; control.OnBarChanged(e.OldValue, e.NewValue); } private static object CoerceBar(DependencyObject d, object baseValue) { if (baseValue is int i && i < 0) { return 0; } return baseValue; } } }".AssertReplace("new PropertyMetadata(default(int), OnBarChanged)", metadata); var fixedCode = @" namespace RoslynSandbox { using System.Windows; using System.Windows.Controls; public class FooControl : Control { public static readonly DependencyProperty BarProperty = DependencyProperty.Register( nameof(Bar), typeof(int), typeof(FooControl), new PropertyMetadata(default(int), OnBarChanged)); public int Bar { get => (int)this.GetValue(BarProperty); set => this.SetValue(BarProperty, value); } /// <summary>This method is invoked when the <see cref=""BarProperty""/> changes.</summary> /// <param name=""oldValue"">The old value of <see cref=""BarProperty""/>.</param> /// <param name=""newValue"">The new value of <see cref=""BarProperty""/>.</param> protected virtual void OnBarChanged(object oldValue, object newValue) { } private static void OnBarChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var control = (FooControl)d; control.OnBarChanged(e.OldValue, e.NewValue); } private static object CoerceBar(DependencyObject d, object baseValue) { if (baseValue is int i && i < 0) { return 0; } return baseValue; } } }".AssertReplace("new PropertyMetadata(default(int), OnBarChanged)", metadata); RoslynAssert.Valid(Analyzer, fixedCode); RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, testCode, fixedCode); }
public void DependencyPropertyRegisterMissingDocsNoParameters() { var testCode = @" namespace RoslynSandbox { using System.Windows; using System.Windows.Controls; public class FooControl : Control { /// <summary>Identifies the <see cref=""Value""/> dependency property.</summary> public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( nameof(Value), typeof(double), typeof(FooControl), new PropertyMetadata( default(double), new PropertyChangedCallback((d, e) => ((FooControl)d).OnValueChanged()))); public double Value { get => (double)this.GetValue(ValueProperty); set => this.SetValue(ValueProperty, value); } protected virtual void OnValueChanged() { } } }"; var fixedCode = @" namespace RoslynSandbox { using System.Windows; using System.Windows.Controls; public class FooControl : Control { /// <summary>Identifies the <see cref=""Value""/> dependency property.</summary> public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( nameof(Value), typeof(double), typeof(FooControl), new PropertyMetadata( default(double), new PropertyChangedCallback((d, e) => ((FooControl)d).OnValueChanged()))); public double Value { get => (double)this.GetValue(ValueProperty); set => this.SetValue(ValueProperty, value); } /// <summary>This method is invoked when the <see cref=""ValueProperty""/> changes.</summary> protected virtual void OnValueChanged() { } } }"; RoslynAssert.Valid(Analyzer, fixedCode); RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, testCode, fixedCode); }
public static void UseTrySet() { var before = @" namespace N { using System; using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; public class C : INotifyPropertyChanged { private string name; public event PropertyChangedEventHandler PropertyChanged; public string Name { get => this.name; set { this.name = value; ↓this.OnPropertyChanged(); } } protected bool TrySet<T>(ref T field, T value, [CallerMemberName] string propertyName = null) { if (EqualityComparer<T>.Default.Equals(field, value)) { return false; } field = value; this.OnPropertyChanged(propertyName); return true; } protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }"; var after = @" namespace N { using System; using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; public class C : INotifyPropertyChanged { private string name; public event PropertyChangedEventHandler PropertyChanged; public string Name { get => this.name; set => this.TrySet(ref this.name, value); } protected bool TrySet<T>(ref T field, T value, [CallerMemberName] string propertyName = null) { if (EqualityComparer<T>.Default.Equals(field, value)) { return false; } field = value; this.OnPropertyChanged(propertyName); return true; } protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }"; RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, before, after, fixTitle: "TrySet(ref field, value)"); RoslynAssert.FixAll(Analyzer, Fix, ExpectedDiagnostic, before, after, fixTitle: "TrySet(ref field, value)"); }
public static void AssignInLambda() { var before = @" namespace N { using System.Windows; using System.Windows.Controls; public class FooControl : Control { public static readonly DependencyProperty BarProperty = DependencyProperty.Register( ""Bar"", typeof(int), typeof(FooControl), new PropertyMetadata(default(int))); public FooControl() { this.Loaded += (sender, args) => { ↓this.Bar = 1; }; } public int Bar { get { return (int)this.GetValue(BarProperty); } set { this.SetValue(BarProperty, value); } } } }"; var after = @" namespace N { using System.Windows; using System.Windows.Controls; public class FooControl : Control { public static readonly DependencyProperty BarProperty = DependencyProperty.Register( ""Bar"", typeof(int), typeof(FooControl), new PropertyMetadata(default(int))); public FooControl() { this.Loaded += (sender, args) => { this.SetCurrentValue(BarProperty, 1); }; } public int Bar { get { return (int)this.GetValue(BarProperty); } set { this.SetValue(BarProperty, value); } } } }"; RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, before, after); }
public static void CallsOnPropertyChangedInternalClassInternalProperty() { var before = @" namespace N { using System.ComponentModel; using System.Runtime.CompilerServices; internal class C : INotifyPropertyChanged { private int value; public event PropertyChangedEventHandler PropertyChanged; internal int Value { get { return this.value; } set { this.value = value; ↓this.OnPropertyChanged(nameof(Value)); } } protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }"; var after = @" namespace N { using System.ComponentModel; using System.Runtime.CompilerServices; internal class C : INotifyPropertyChanged { private int value; public event PropertyChangedEventHandler PropertyChanged; internal int Value { get { return this.value; } set { if (value == this.value) { return; } this.value = value; this.OnPropertyChanged(nameof(Value)); } } protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }"; RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, before, after); RoslynAssert.FixAll(Analyzer, Fix, ExpectedDiagnostic, before, after); }
public static void SetValueWithTrivia(bool underscore, string setExpression) { var code = @" namespace N { using System.Windows; using System.Windows.Controls; public class FooControl : Control { public static readonly DependencyProperty BarProperty = DependencyProperty.Register( ""Bar"", typeof(int), typeof(FooControl), new PropertyMetadata(default(int))); public int Bar { get { return (int)this.GetValue(BarProperty); } set { this.SetValue(BarProperty, value); } } public void M() { // comment before ↓this.SetValue(BarProperty, 1); // line comment // comment after } private int CreateValue() => 4; } }".AssertReplace("1", setExpression) .AssertReplace("this.", underscore ? string.Empty : "this."); var after = @" namespace N { using System.Windows; using System.Windows.Controls; public class FooControl : Control { public static readonly DependencyProperty BarProperty = DependencyProperty.Register( ""Bar"", typeof(int), typeof(FooControl), new PropertyMetadata(default(int))); public int Bar { get { return (int)this.GetValue(BarProperty); } set { this.SetValue(BarProperty, value); } } public void M() { // comment before this.SetCurrentValue(BarProperty, 1); // line comment // comment after } private int CreateValue() => 4; } }".AssertReplace("1", setExpression) .AssertReplace("this.", underscore ? string.Empty : "this."); RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, code, after); }
public static void UseTrySetUnderscoreNoCallerMemberName() { var before = @" namespace N { using System.Collections.Generic; using System.ComponentModel; public class C : INotifyPropertyChanged { private string _name; public event PropertyChangedEventHandler PropertyChanged; public string Name { get => _name; set { _name = value; ↓OnPropertyChanged(nameof(Name)); } } protected bool TrySet<T>(ref T field, T value, string propertyName) { if (EqualityComparer<T>.Default.Equals(field, value)) { return false; } field = value; OnPropertyChanged(propertyName); return true; } protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }"; var after = @" namespace N { using System.Collections.Generic; using System.ComponentModel; public class C : INotifyPropertyChanged { private string _name; public event PropertyChangedEventHandler PropertyChanged; public string Name { get => _name; set => TrySet(ref _name, value, nameof(Name)); } protected bool TrySet<T>(ref T field, T value, string propertyName) { if (EqualityComparer<T>.Default.Equals(field, value)) { return false; } field = value; OnPropertyChanged(propertyName); return true; } protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }"; RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, before, after, fixTitle: "TrySet(ref field, value, propertyName)"); RoslynAssert.FixAll(Analyzer, Fix, ExpectedDiagnostic, before, after, fixTitle: "TrySet(ref field, value, propertyName)"); }
public static void LocalInSwitchCase() { var before = @" namespace N { using System; using System.IO; class C { public C(StringComparison comparison) { switch (comparison) { case StringComparison.CurrentCulture: break; case StringComparison.CurrentCultureIgnoreCase: break; case StringComparison.InvariantCulture: break; case StringComparison.InvariantCultureIgnoreCase: break; case StringComparison.Ordinal: break; case StringComparison.OrdinalIgnoreCase: ↓var stream = File.OpenRead(string.Empty); break; default: throw new ArgumentOutOfRangeException(nameof(comparison), comparison, null); } } } }"; var after = @" namespace N { using System; using System.IO; class C { public C(StringComparison comparison) { switch (comparison) { case StringComparison.CurrentCulture: break; case StringComparison.CurrentCultureIgnoreCase: break; case StringComparison.InvariantCulture: break; case StringComparison.InvariantCultureIgnoreCase: break; case StringComparison.Ordinal: break; case StringComparison.OrdinalIgnoreCase: using (var stream = File.OpenRead(string.Empty)) { } break; default: throw new ArgumentOutOfRangeException(nameof(comparison), comparison, null); } } } }"; RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, before, after, fixTitle: "Add using to end of block."); RoslynAssert.FixAll(Analyzer, Fix, ExpectedDiagnostic, before, after, fixTitle: "Add using to end of block."); }
public void AddOwnerAttachedPropertyInSource() { var fooCode = @" namespace RoslynSandbox { using System.Windows; public static class Foo { public static readonly DependencyProperty BarProperty = DependencyProperty.RegisterAttached( ""Bar"", typeof(int), typeof(Foo), new FrameworkPropertyMetadata( default(int), FrameworkPropertyMetadataOptions.Inherits)); public static void SetBar(DependencyObject element, int value) { element.SetValue(BarProperty, value); } public static int GetBar(DependencyObject element) { return (int) element.GetValue(BarProperty); } } }"; var testCode = @" namespace RoslynSandbox { using System.Windows; using System.Windows.Controls; public class FooControl : Control { public static readonly DependencyProperty BarProperty = Foo.BarProperty.AddOwner(typeof(FooControl)); public int ↓Error { get { return (int) this.GetValue(BarProperty); } set { this.SetValue(BarProperty, value); } } } }"; var fixedCode = @" namespace RoslynSandbox { using System.Windows; using System.Windows.Controls; public class FooControl : Control { public static readonly DependencyProperty BarProperty = Foo.BarProperty.AddOwner(typeof(FooControl)); public int Bar { get { return (int) this.GetValue(BarProperty); } set { this.SetValue(BarProperty, value); } } } }"; RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, new[] { testCode, fooCode }, fixedCode); }
public static void DisposeAfterIfNotDisposingReturn() { var before = @" namespace N { using System; using System.IO; public class C : IDisposable { ↓private readonly Stream stream = File.OpenRead(string.Empty); private bool disposed; public void Dispose() { this.Dispose(true); } protected virtual void Dispose(bool disposing) { if (this.disposed) { return; } this.disposed = true; if (!disposing) { return; } } protected void ThrowIfDisposed() { if (this.disposed) { throw new ObjectDisposedException(GetType().FullName); } } } }"; var after = @" namespace N { using System; using System.IO; public class C : IDisposable { private readonly Stream stream = File.OpenRead(string.Empty); private bool disposed; public void Dispose() { this.Dispose(true); } protected virtual void Dispose(bool disposing) { if (this.disposed) { return; } this.disposed = true; if (!disposing) { return; } this.stream?.Dispose(); } protected void ThrowIfDisposed() { if (this.disposed) { throw new ObjectDisposedException(GetType().FullName); } } } }"; RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, before, after); RoslynAssert.FixAll(Analyzer, Fix, ExpectedDiagnostic, before, after); }
public void DependencyPropertyRegisterReadOnly() { var testCode = @" namespace RoslynSandbox { using System.Windows; using System.Windows.Controls; public class FooControl : Control { private static readonly DependencyPropertyKey ValuePropertyKey = DependencyProperty.RegisterReadOnly( nameof(Value), typeof(int), typeof(FooControl), new PropertyMetadata(1.0, OnValueChanged)); public static readonly DependencyProperty ValueProperty = ValuePropertyKey.DependencyProperty; public int Value { get { return (int)this.GetValue(ValueProperty); } set { this.SetValue(ValuePropertyKey, value); } } private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var control = (↓Control)d; } } }"; var fixedCode = @" namespace RoslynSandbox { using System.Windows; using System.Windows.Controls; public class FooControl : Control { private static readonly DependencyPropertyKey ValuePropertyKey = DependencyProperty.RegisterReadOnly( nameof(Value), typeof(int), typeof(FooControl), new PropertyMetadata(1.0, OnValueChanged)); public static readonly DependencyProperty ValueProperty = ValuePropertyKey.DependencyProperty; public int Value { get { return (int)this.GetValue(ValueProperty); } set { this.SetValue(ValuePropertyKey, value); } } private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var control = (FooControl)d; } } }"; RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, testCode, fixedCode); }
public static void WhenBaseHasPublicOverrideDisposeAndThrowIfDisposed() { var baseClass = @" namespace N { using System; public class BaseClass : IDisposable { private bool disposed; public virtual void Dispose() { if (this.disposed) { return; } this.disposed = true; } protected virtual void ThrowIfDisposed() { if (this.disposed) { throw new ObjectDisposedException(GetType().FullName); } } } }"; var before = @" namespace N { using System.IO; public class C : BaseClass { ↓private readonly Stream stream = File.OpenRead(string.Empty); private bool disposed; public override void Dispose() { if (this.disposed) { return; } this.disposed = true; base.Dispose(); } } }"; var after = @" namespace N { using System.IO; public class C : BaseClass { private readonly Stream stream = File.OpenRead(string.Empty); private bool disposed; public override void Dispose() { if (this.disposed) { return; } this.disposed = true; this.stream?.Dispose(); base.Dispose(); } } }"; RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, new[] { baseClass, before }, after); RoslynAssert.FixAll(Analyzer, Fix, ExpectedDiagnostic, new[] { baseClass, before }, after); }
public static void NotifyingProperty(string equals) { var before = @" namespace N { using System.ComponentModel; using System.Runtime.Serialization; [DataContract] public class C : INotifyPropertyChanged { private string value; public event PropertyChangedEventHandler PropertyChanged; public C(string value) { ↓this.Value = value; } [DataMember] public string Value { get => this.value; private set { if (value == this.value) { return; } this.value = value; this.OnPropertyChanged(); } } protected virtual void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) { this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }".AssertReplace("value == this.value", equals); var after = @" namespace N { using System.ComponentModel; using System.Runtime.Serialization; [DataContract] public class C : INotifyPropertyChanged { private string value; public event PropertyChangedEventHandler PropertyChanged; public C(string value) { this.value = value; } [DataMember] public string Value { get => this.value; private set { if (value == this.value) { return; } this.value = value; this.OnPropertyChanged(); } } protected virtual void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) { this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }".AssertReplace("value == this.value", equals); RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, before, after); }
public static void DisposeSecondMemberWhenOverriddenDisposeMethodNoCurlies() { var baseClass = @" namespace N { using System; public class BaseClass : IDisposable { private bool disposed; public void Dispose() { this.Dispose(true); } protected virtual void Dispose(bool disposing) { if (this.disposed) { return; } this.disposed = true; if (disposing) { } } protected void ThrowIfDisposed() { if (this.disposed) { throw new ObjectDisposedException(GetType().FullName); } } } }"; var before = @" namespace N { using System.IO; public class C : BaseClass { private readonly Stream stream1 = File.OpenRead(string.Empty); ↓private readonly Stream stream2 = File.OpenRead(string.Empty); private bool disposed; protected override void Dispose(bool disposing) { if (this.disposed) { return; } this.disposed = true; if (disposing) this.stream1.Dispose(); base.Dispose(disposing); } } }"; var after = @" namespace N { using System.IO; public class C : BaseClass { private readonly Stream stream1 = File.OpenRead(string.Empty); private readonly Stream stream2 = File.OpenRead(string.Empty); private bool disposed; protected override void Dispose(bool disposing) { if (this.disposed) { return; } this.disposed = true; if (disposing) { this.stream1.Dispose(); this.stream2?.Dispose(); } base.Dispose(disposing); } } }"; RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, new[] { baseClass, before }, after); RoslynAssert.FixAll(Analyzer, Fix, ExpectedDiagnostic, new[] { baseClass, before }, after); }
public static void WhenShadowingLocalKeyword() { var before = @" namespace N { using System.ComponentModel; using System.Runtime.CompilerServices; public class C : INotifyPropertyChanged { public C(bool a) { var @default = a; ↓X = a; } private bool @default; public bool X { get => @default; set { if (value == @default) { return; } @default = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }"; var after = @" namespace N { using System.ComponentModel; using System.Runtime.CompilerServices; public class C : INotifyPropertyChanged { public C(bool a) { var @default = a; this.@default = a; } private bool @default; public bool X { get => @default; set { if (value == @default) { return; } @default = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }"; RoslynAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, new[] { ViewModelBase, before }, after); }