public void ConstructorCycle(DiagnosticAnalyzer analyzer)
        {
            var testCode = @"
namespace RoslynSandbox
{
    using System;

    public class Constructors : IDisposable
    {
        private IDisposable disposable;

        public Constructors(int i, IDisposable disposable)
            : this(disposable, i)
        {
            this.disposable = disposable;
        }

        public Constructors(IDisposable disposable, int i)
            : this(i, disposable)
        {
            this.disposable = disposable;
        }

        public void Dispose()
        {
        }
    }
}";
            var solution = CodeFactory.CreateSolution(testCode, CodeFactory.DefaultCompilationOptions(analyzer, AnalyzerAssert.SuppressedDiagnostics), AnalyzerAssert.MetadataReferences);

            AnalyzerAssert.NoDiagnostics(Analyze.GetDiagnostics(analyzer, solution));
        }
        public void WithSyntaxErrors(DiagnosticAnalyzer analyzer)
        {
            var testCode = @"
namespace RoslynSandbox
{
    using System;
    using System.IO;

    public class Foo : SyntaxError
    {
        private readonly Stream stream = File.SyntaxError(string.Empty);
        private bool disposed;

        protected override void Dispose(bool disposing)
        {
            if (this.syntaxError)
            {
                return;
            }

            this.disposed = true;
            if (disposing)
            {
                this.stream.Dispose();
            }

            base.Dispose(disposing);
        }
    }
}";
            var solution = CodeFactory.CreateSolution(testCode, CodeFactory.DefaultCompilationOptions(analyzer, AnalyzerAssert.SuppressedDiagnostics), AnalyzerAssert.MetadataReferences);

            AnalyzerAssert.NoDiagnostics(Analyze.GetDiagnostics(analyzer, solution));
        }
Example #3
0
        public void InsideObservableFromEventArg()
        {
            var fooCode = @"
namespace RoslynSandbox
{
    using System;

    public class Foo
    {
        public event EventHandler<int> SomeEvent;
    }
}";

            var testCode = @"
namespace RoslynSandbox
{
    using System;

    public class Bar
    {
        public Bar()
        {
            var foo = new Foo();
            System.Reactive.Linq.Observable.FromEvent<System.EventHandler, EventArgs>(
                h => (_, e) => h(e),
                h => foo.SomeEvent += h,
                h => foo.SomeEvent -= h)
                                           .Subscribe(_ => Console.WriteLine(string.Empty));
        }
    }
}";

            AnalyzerAssert.NoDiagnostics <GUREA11PreferObservableFromEvent>(fooCode, testCode);
        }
Example #4
0
        public void GenericConstraint()
        {
            var fooCode  = @"
namespace RoslynSandbox
{
    using System.ComponentModel;
    using System.Runtime.CompilerServices;

    public interface IFoo : INotifyPropertyChanged
    {
        public int Value { get; }
    }
}";
            var testCode = @"
namespace RoslynSandbox
{
    using System;
    using Gu.Reactive;

    public class Bar<T>
        where T : class, IFoo
    {
        public Bar(T foo)
        {
            foo.ObservePropertyChanged(x => x.Value)
               .Subscribe(_ => Console.WriteLine(string.Empty));
        }
    }
}";

            AnalyzerAssert.NoDiagnostics <GUREA03PathMustNotify>(fooCode, testCode);
        }
Example #5
0
        public void ActionOfInt()
        {
            var fooCode = @"
namespace RoslynSandbox
{
    using System;

    public class Foo
    {
        public event Action<int> SomeEvent;
    }
}";

            var testCode = @"
namespace RoslynSandbox
{
    using System;

    public class Bar
    {
        public Bar()
        {
            var foo = new Foo();
            System.Reactive.Linq.Observable.FromEvent<System.Action<int>, int>(
                h => foo.SomeEvent += h,
                h => foo.SomeEvent -= h)
                                           .Subscribe(_ => Console.WriteLine(string.Empty));
        }
    }
}";

            AnalyzerAssert.NoDiagnostics <GUREA12ObservableFromEventDelegateType>(fooCode, testCode);
        }
Example #6
0
        public void ObservingGetOnlyPropertyInSelf()
        {
            var fooCode  = @"
namespace RoslynSandbox
{
    using System.ComponentModel;
    using System.Runtime.CompilerServices;

    internal class Foo : INotifyPropertyChanged
    {
        private int _value;

        public event PropertyChangedEventHandler PropertyChanged;

        public int Value
        {
            get
            {
                return _value;
            }

            set
            {
                if (value == _value)
                {
                    return;
                }

                _value = value;
                OnPropertyChanged();
            }
        }

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}";
            var testCode = @"namespace RoslynSandbox
{
    using System;
    using Gu.Reactive;

    internal class Meh
    {
        public Meh()
        {
            this.Foo = new Foo();
            this.Foo.ObserveFullPropertyPathSlim(x => x.Value)
                    .Subscribe(_ => Console.WriteLine(""meh""));
        }

        public Foo Foo { get; }
    }
}";

            AnalyzerAssert.NoDiagnostics <GUREA01DontObserveMutableProperty>(fooCode, testCode);
        }
Example #7
0
        public void WhenSingleLine()
        {
            var fooCode  = @"
namespace RoslynSandbox
{
    using System.ComponentModel;
    using System.Runtime.CompilerServices;

    public class Foo : 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.OnPropertyChanged();
            }
        }

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}";
            var testCode = @"
namespace RoslynSandbox
{
    using System.Reactive.Linq;
    using Gu.Reactive;

    public class FooCondition : Condition
    {
        public FooCondition(Foo foo)
            : base(
                foo.ObservePropertyChangedSlim(x => x.Value),
                () => foo.Value == 2)
        {
        }
    }
}";

            AnalyzerAssert.NoDiagnostics <GUREA08InlineSingleLine>(fooCode, testCode);
        }
Example #8
0
        public void OneLevel()
        {
            var fooCode  = @"
namespace RoslynSandbox
{
    using System.ComponentModel;
    using System.Runtime.CompilerServices;

    public class Foo : 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.OnPropertyChanged();
            }
        }

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}";
            var testCode = @"
namespace RoslynSandbox
{
    using System;
    using Gu.Reactive;

    public class Bar
    {
        public Bar()
        {
            var foo = new Foo();
            foo.ObservePropertyChanged(x => x.Value)
               .Subscribe(_ => Console.WriteLine(string.Empty));
        }
    }
}";

            AnalyzerAssert.NoDiagnostics <GUREA03PathMustNotify>(fooCode, testCode);
        }
Example #9
0
        public void WhenUsingNullableValue()
        {
            var fooCode = @"
namespace RoslynSandbox
{
    using System.ComponentModel;
    using System.Runtime.CompilerServices;

    public sealed class Foo : INotifyPropertyChanged
    {
        private int? value;

        public event PropertyChangedEventHandler PropertyChanged;

        public int? Value
        {
            get => this.value;

            set
            {
                if (value == this.value)
                {
                    return;
                }

                this.value = value;
                this.OnPropertyChanged();
            }
        }

        private void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}";

            var testCode = @"
namespace RoslynSandbox
{
    using Gu.Reactive;

    public class FooCondition : Condition
    {
        public FooCondition(Foo foo)
            : base(
                foo.ObservePropertyChangedSlim(x => x.Value),
                () => { return foo.Value == null ? (bool?)null : foo.Value.Value == 1; })
        {
        }
    }
}";

            AnalyzerAssert.NoDiagnostics <GUREA02ObservableAndCriteriaMustMatch>(fooCode, testCode);
        }
Example #10
0
        public void MultipleIEnumerableInterfaces()
        {
            var testCode    = @"
namespace RoslynSandbox
{
    using System.Collections;
    using System.Collections.Generic;

    class Foo : IEnumerable<IEnumerable<char>>, IEnumerable<int>
    {
        IEnumerator<int> IEnumerable<int>.GetEnumerator()
        {
            yield return 42;
        }

        void GetEnumerator(int x)
        {
        }

        IEnumerator<IEnumerable<char>> IEnumerable<IEnumerable<char>>.GetEnumerator()
        {
            yield return string.Empty;
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return ((IEnumerable<IEnumerable<char>>)this).GetEnumerator();
        }
    }

    public class A
    {
        public void F()
        {
            foreach(int a in new Foo())
            {
            }
        }
    }
}";
            var sln         = CodeFactory.CreateSolution(testCode, CodeFactory.DefaultCompilationOptions(Analyzer), AnalyzerAssert.MetadataReferences);
            var diagnostics = Analyze.GetDiagnostics(Analyzer, sln);

            AnalyzerAssert.NoDiagnostics(diagnostics);
        }
Example #11
0
        public void AndConditionSortArgs()
        {
            var testCode = @"
namespace RoslynSandbox
{
    using Gu.Reactive;

    public class FooCondition : AndCondition
    {
        public FooCondition(Condition1 condition1, Condition2 condition2)
            : base(condition1, condition2)
        {
        }
    }
}";

            AnalyzerAssert.NoDiagnostics <GUREA13SyncParametersAndArgs>(Condition1, Condition2, testCode);
        }
Example #12
0
        public void CtorCallingSelf(DiagnosticAnalyzer analyzer)
        {
            var testCode    = @"
namespace RoslynSandbox
{
    internal abstract class Foo
    {
        public Foo()
            : this()
        {
        }
    }
}";
            var sln         = CodeFactory.CreateSolution(testCode, CodeFactory.DefaultCompilationOptions(analyzer), AnalyzerAssert.MetadataReferences);
            var diagnostics = Analyze.GetDiagnostics(analyzer, sln);

            AnalyzerAssert.NoDiagnostics(diagnostics);
        }
Example #13
0
        public void GenericProperty()
        {
            var iBarCode = @"
namespace RoslynSandbox
{
    using System.ComponentModel;
    using System.Runtime.CompilerServices;

    public interface IBar : INotifyPropertyChanged
    {
        int Value { get; set; }
    }
}";

            var iFooCode = @"
namespace RoslynSandbox
{
    using System.ComponentModel;
    using System.Runtime.CompilerServices;

    public interface IFoo<T> : INotifyPropertyChanged
        where T: class, IBar
    {
        T Bar { get; set; }
    }
}";
            var testCode = @"
namespace RoslynSandbox
{
    using System;
    using Gu.Reactive;

    public class Bar
    {
        public Bar(IFoo<IBar> foo)
        {
            foo.ObservePropertyChangedSlim(x => x.Bar.Value)
               .Subscribe(_ => Console.WriteLine(string.Empty));
        }
    }
}";

            AnalyzerAssert.NoDiagnostics <GUREA03PathMustNotify>(iBarCode, iFooCode, testCode);
        }
Example #14
0
        public void Correct()
        {
            var testCode = @"
namespace RoslynSandbox
{
    using Gu.Reactive;

    public class FooCondition : Condition
    {
        public FooCondition(Foo foo)
            : base(
                foo.ObservePropertyChangedSlim(x => x.Value1),
                () => foo.Value1 == 2)
        {
        }
    }
}";

            AnalyzerAssert.NoDiagnostics <GUREA02ObservableAndCriteriaMustMatch>(FooCode, testCode);
        }
Example #15
0
        public void WhenPassingSlimToConditionCtor()
        {
            var testCode = @"
namespace RoslynSandbox
{
    using Gu.Reactive;

    public class FooCondition : Condition
    {
        public FooCondition(Foo foo)
            : base(
                foo.ObservePropertyChangedSlim(x => x.Value1),
                () => foo.Value1 == 2)
        {
        }
    }
}";

            AnalyzerAssert.NoDiagnostics <GUREA04PreferSlim>(FooCode, testCode);
        }
Example #16
0
        public void ObservableCollectionCount()
        {
            var testCode = @"
namespace RoslynSandbox
{
    using System;
    using Gu.Reactive;

    public class Bar
    {
        public Bar(System.Collections.ObjectModel.ObservableCollection<int> foo)
        {
            foo.ObservePropertyChanged(x => x.Count)
               .Subscribe(_ => Console.WriteLine(string.Empty));
        }
    }
}";

            AnalyzerAssert.NoDiagnostics <GUREA03PathMustNotify>(testCode);
        }
Example #17
0
        public void WhenSubscribingToSlimUsingArg()
        {
            var testCode = @"
namespace RoslynSandbox
{
    using System;
    using Gu.Reactive;

    public class Bar
    {
        public Bar()
        {
            var foo = new Foo();
            foo.ObservePropertyChangedSlim(x => x.Value1)
               .Subscribe(x => Console.WriteLine(x.PropertyName));
        }
    }
}";

            AnalyzerAssert.NoDiagnostics <GUREA04PreferSlim>(FooCode, testCode);
        }
            public void Recursion()
            {
                var code     = @"
namespace RoslynSandbox
{
    using System;

    public class C<T1, T2>
        where T1 : T2
        where T2 : T1
    {
        public static void Bar()
        {
            var type = typeof(C<,>).MakeGenericType(typeof(int), typeof(int));
        }
    }
}";
                var solution = CodeFactory.CreateSolution(code, CodeFactory.DefaultCompilationOptions(Analyzer), AnalyzerAssert.MetadataReferences);

                AnalyzerAssert.NoDiagnostics(Analyze.GetDiagnostics(Analyzer, solution));
            }
Example #19
0
        public void WhenCorrectOrder()
        {
            var testCode = @"
namespace RoslynSandbox
{
    using System.Reactive.Linq;
    using Gu.Reactive;

    public class FooCondition : Condition
    {
        public FooCondition(Foo foo)
            : base(
                foo.ObservePropertyChangedSlim(x => x.Value),
                () => foo.Value == 2)
        {
        }
    }
}";

            AnalyzerAssert.NoDiagnostics <GUREA09ObservableBeforeCriteria>(FooCode, testCode);
        }
Example #20
0
        public void WhenNoMerge()
        {
            var testCode = @"
namespace RoslynSandbox
{
    using System.Reactive.Linq;
    using Gu.Reactive;

    public class FooCondition : Condition
    {
        public FooCondition(Foo foo)
            : base(
                foo.ObservePropertyChangedSlim(x => x.Value),
                () => foo.Value == 2)
        {
        }
    }
}";

            AnalyzerAssert.NoDiagnostics <GUREA10DontMergeInObservable>(FooCode, testCode);
        }
Example #21
0
        public void Run(DiagnosticAnalyzer analyzer)
        {
            var diagnostics = Analyze.GetDiagnostics(Solution, analyzer);

            AnalyzerAssert.NoDiagnostics(diagnostics);
        }
Example #22
0
        public void IgnoreUsageInThrowTwoLevels()
        {
            var fooCode  = @"
namespace RoslynSandbox
{
    using System;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;

    public sealed class Foo : INotifyPropertyChanged, IDisposable
    {
        private bool disposed;
        private Bar bar;

        public event PropertyChangedEventHandler PropertyChanged;

        public Bar Bar
        {
            get
            {
                ThrowIfDisposed();
                return this.bar;
            }

            set
            {
                ThrowIfDisposed();
                if (ReferenceEquals(value, this.bar))
                {
                    return;
                }

                this.bar = value;
                this.OnPropertyChanged();
            }
        }

        public void Dispose()
        {
            if (this.disposed)
            {
                return;
            }

            this.disposed = true;
        }

        private void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private void ThrowIfDisposed()
        {
            if (this.disposed)
            {
                throw new ObjectDisposedException(this.GetType().FullName);
            }
        }
    }
}";
            var barCode  = @"
namespace RoslynSandbox
{
    using System.ComponentModel;
    using System.Runtime.CompilerServices;

    public class Bar : INotifyPropertyChanged, IDisposable
    {
        private int value;

        public event PropertyChangedEventHandler PropertyChanged;

        public int Value
        {
            get
            {
                ThrowIfDisposed();
                return this.value;
            }

            set
            {
                ThrowIfDisposed();
                if (value == this.value)
                {
                    return;
                }

                this.value = value;
                this.OnPropertyChanged();
            }
        }

        public void Dispose()
        {
            if (this.disposed)
            {
                return;
            }

            this.disposed = true;
        }

        private void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private void ThrowIfDisposed()
        {
            if (this.disposed)
            {
                throw new ObjectDisposedException(this.GetType().FullName);
            }
        }
    }
}";
            var testCode = @"
namespace RoslynSandbox
{
    using Gu.Reactive;

    public class FooCondition : Condition
    {
        public FooCondition(Foo foo)
            : base(
                foo.ObservePropertyChangedSlim(x => x.Value),
                () => foo.Value == 2)
        {
        }
    }
}";

            AnalyzerAssert.NoDiagnostics <GUREA02ObservableAndCriteriaMustMatch>(fooCode, barCode, testCode);
        }
            public void Issue63()
            {
                var viewModelBaseCode  = @"
namespace MVVM
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Reflection;

    using System.Runtime.CompilerServices;

    /// <summary>
    /// Base class for all ViewModel classes in the application.
    /// It provides support for property change notifications
    /// and has a DisplayName property. This class is abstract.
    /// </summary>
    public abstract class ViewModelBase : INotifyPropertyChanged, IDisposable
    {
        private readonly List<IDisposable> disposables = new List<IDisposable>();
        private readonly object disposeLock = new object();
        private bool isDisposed;

        protected ViewModelBase()
        {
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void Dispose()
        {
            lock (disposeLock)
            {
                this.OnDispose();

                if (isDisposed)
                    return;

                foreach (var disposable in disposables)
                    disposable.Dispose();

                isDisposed = true;
            }
        }

        protected virtual void OnDispose()
        {
        }
    }
}";
                var popupViewModelCode = @"
namespace ProjectX.ViewModel
{
    using System;
    using MVVM;

    public class PopupViewModel : ViewModelBase
    {
        public PopupViewModel()
        {
            ClosePopupCommand = new ClosePopupCommand(this);
        }

        // Gives an IDISP006 warning (need to implement IDispose)
        public ClosePopupCommand ClosePopupCommand { get; }

        protected override void OnDispose()
        {
            ClosePopupCommand.Dispose();
            CloseProgramCommand.Dispose();
        }
    }
}";

                var closePopupCommandCode = @"
namespace ProjectX.Commands
{
    using System;

    public sealed class ClosePopupCommand : IDisposable
    {
        private readonly object disposeLock = new object();
        private bool isDisposed;
        private bool isBusy = false;

        internal ClosePopupCommand()
        {
        }

        public event EventHandler CanExecuteChanged;

        public void Dispose()
        {
            lock (disposeLock)
            {
                if (isDisposed)
                    return;

                // Here we have code that actually needs to be disposed off...

                isDisposed = true;
            }
        }
    }
}";

                var solution = CodeFactory.CreateSolution(
                    new[] { viewModelBaseCode, popupViewModelCode, closePopupCommandCode },
                    CodeFactory.DefaultCompilationOptions(Analyzer, AnalyzerAssert.SuppressedDiagnostics),
                    AnalyzerAssert.MetadataReferences);

                AnalyzerAssert.NoDiagnostics(Analyze.GetDiagnostics(Analyzer, solution));
            }
Example #24
0
        public void WhenUsingImmutableProperty()
        {
            var fooCode = @"
namespace RoslynSandbox
{
    using System.ComponentModel;
    using System.Runtime.CompilerServices;

    public sealed class Foo : INotifyPropertyChanged
    {
        private Bar bar;

        public event PropertyChangedEventHandler PropertyChanged;

        public Bar Bar
        {
            get => this.bar;

            set
            {
                if (ReferenceEquals(value, this.bar))
                {
                    return;
                }

                this.bar = value;
                this.OnPropertyChanged();
            }
        }

        private void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}";

            var barCode  = @"
namespace RoslynSandbox
{
    public class Bar
    {
        public Bar(int value)
        {
            Value = value;
        }

        public int Value { get; }
    }
}";
            var testCode = @"
namespace RoslynSandbox
{
    using Gu.Reactive;

    public class FooCondition : Condition
    {
        public FooCondition(Foo foo)
            : base(
                foo.ObservePropertyChangedSlim(x => x.Bar),
                () => foo.Bar.Value == 2)
        {
        }
    }
}";

            AnalyzerAssert.NoDiagnostics <GUREA02ObservableAndCriteriaMustMatch>(fooCode, barCode, testCode);
        }