context: using System.Linq;
  using System.Threading;
  using Microsoft.Vbe.Interop;
  using Microsoft.VisualStudio.TestTools.UnitTesting;
  using Moq;
  using Rubberduck.Inspections;
  using Rubberduck.Parsing;
  using Rubberduck.Parsing.VBA;
  using Rubberduck.VBEditor.Extensions;
  using Rubberduck.VBEditor.VBEHost;
  using RubberduckTests.Mocks;
  
  namespace RubberduckTests.Inspections
  {
      [TestClass]
      public class MultipleDeclarationsInspectionTests
      {
          [TestMethod]
          [TestCategory("Inspections")]
          public void MultipleDeclarations_ReturnsResult_Variables()
          {
              const string inputCode =
  @"Public Sub Foo()
      Dim var1 As Integer, var2 As String
  End Sub";
  
              //Arrange
              var builder = new MockVbeBuilder();
              VBComponent component;
              var vbe = builder.BuildFromSingleStandardModule(inputCode, out component);
              var mockHost = new Mock<IHostApplication>();
              mockHost.SetupAllProperties();
              var parser = MockParser.Create(vbe.Object, new RubberduckParserState(new Mock<ISinks>().Object));
  
              parser.Parse(new CancellationTokenSource());
              if (parser.State.Status >= ParserState.Error) { Assert.Inconclusive("Parser Error"); }
  
              var inspection = new MultipleDeclarationsInspection(parser.State);
              var inspectionResults = inspection.GetInspectionResults();
  
              Assert.AreEqual(1, inspectionResults.Count());
          }
  
          [TestMethod]
          [TestCategory("Inspections")]
          public void MultipleDeclarations_ReturnsResult_Constants()
          {
              const string inputCode =
  @"Public Sub Foo()
      Const var1 As Integer = 9, var2 As String = ""test""
  End Sub";
  
              //Arrange
              var builder = new MockVbeBuilder();
              VBComponent component;
              var vbe = builder.BuildFromSingleStandardModule(inputCode, out component);
              var mockHost = new Mock<IHostApplication>();
              mockHost.SetupAllProperties();
              var parser = MockParser.Create(vbe.Object, new RubberduckParserState(new Mock<ISinks>().Object));
  
              parser.Parse(new CancellationTokenSource());
              if (parser.State.Status >= ParserState.Error) { Assert.Inconclusive("Parser Error"); }
  
              var inspection = new MultipleDeclarationsInspection(parser.State);
              var inspectionResults = inspection.GetInspectionResults();
  
              Assert.AreEqual(1, inspectionResults.Count());
          }
  
          [TestMethod]
          [TestCategory("Inspections")]
          public void MultipleDeclarations_ReturnsResult_StaticVariables()
          {
              const string inputCode =
  @"Public Sub Foo()
      Static var1 As Integer, var2 As String
  End Sub";
  
              //Arrange
              var builder = new MockVbeBuilder();
              VBComponent component;
              var vbe = builder.BuildFromSingleStandardModule(inputCode, out component);
              var mockHost = new Mock<IHostApplication>();
              mockHost.SetupAllProperties();
              var parser = MockParser.Create(vbe.Object, new RubberduckParserState(new Mock<ISinks>().Object));
  
              parser.Parse(new CancellationTokenSource());
              if (parser.State.Status >= ParserState.Error) { Assert.Inconclusive("Parser Error"); }
  
              var inspection = new MultipleDeclarationsInspection(parser.State);
              var inspectionResults = inspection.GetInspectionResults();
  
              Assert.AreEqual(1, inspectionResults.Count());
          }
  
          [TestMethod]
          [TestCategory("Inspections")]
          public void MultipleDeclarations_ReturnsResult_MultipleDeclarations()
          {
              const string inputCode =
  @"Public Sub Foo()
      Dim var1 As Integer, var2 As String
      Dim var3 As Boolean, var4 As Date
  End Sub";
  
              //Arrange
              var builder = new MockVbeBuilder();
              VBComponent component;
              var vbe = builder.BuildFromSingleStandardModule(inputCode, out component);
              var mockHost = new Mock<IHostApplication>();
              mockHost.SetupAllProperties();
              var parser = MockParser.Create(vbe.Object, new RubberduckParserState(new Mock<ISinks>().Object));
  
              parser.Parse(new CancellationTokenSource());
              if (parser.State.Status >= ParserState.Error) { Assert.Inconclusive("Parser Error"); }
  
              var inspection = new MultipleDeclarationsInspection(parser.State);
              var inspectionResults = inspection.GetInspectionResults();
  
              Assert.AreEqual(2, inspectionResults.Count());
          }
  
          [TestMethod]
          [TestCategory("Inspections")]
          public void MultipleDeclarations_ReturnsResult_SomeDeclarationsSeparate()
          {
              const string inputCode =
  @"Public Sub Foo()
      Dim var1 As Integer, var2 As String
      Dim var3 As Boolean
  End Sub";
  
              //Arrange
              var builder = new MockVbeBuilder();
              VBComponent component;
              var vbe = builder.BuildFromSingleStandardModule(inputCode, out component);
              var mockHost = new Mock<IHostApplication>();
              mockHost.SetupAllProperties();
              var parser = MockParser.Create(vbe.Object, new RubberduckParserState(new Mock<ISinks>().Object));
  
              parser.Parse(new CancellationTokenSource());
              if (parser.State.Status >= ParserState.Error) { Assert.Inconclusive("Parser Error"); }
  
              var inspection = new MultipleDeclarationsInspection(parser.State);
              var inspectionResults = inspection.GetInspectionResults();
  
              Assert.AreEqual(1, inspectionResults.Count());
          }
  
          [TestMethod]
          [TestCategory("Inspections")]
          public void MultipleDeclarations_Ignore_DoesNotReturnResult_Variables()
          {
              const string inputCode =
  @"Public Sub Foo()
      '@Ignore MultipleDeclarations
      Dim var1 As Integer, var2 As String
  End Sub";
  
              //Arrange
              var builder = new MockVbeBuilder();
              VBComponent component;
              var vbe = builder.BuildFromSingleStandardModule(inputCode, out component);
              var mockHost = new Mock<IHostApplication>();
              mockHost.SetupAllProperties();
              var parser = MockParser.Create(vbe.Object, new RubberduckParserState(new Mock<ISinks>().Object));
  
              parser.Parse(new CancellationTokenSource());
              if (parser.State.Status >= ParserState.Error) { Assert.Inconclusive("Parser Error"); }
  
              var inspection = new MultipleDeclarationsInspection(parser.State);
              var inspectionResults = inspection.GetInspectionResults();
  
              Assert.IsFalse(inspectionResults.Any());
          }
  
          [TestMethod]
          [TestCategory("Inspections")]
          public void MultipleDeclarations_QuickFixWorks_Variables()
          {
              const string inputCode =
  @"Public Sub Foo()
      Dim var1 As Integer, var2 As String
  End Sub";
  
              const string expectedCode =
  @"Public Sub Foo()
  Dim var1 As Integer
  Dim var2 As String
  
  End Sub";
  
              //Arrange
              var builder = new MockVbeBuilder();
              VBComponent component;
              var vbe = builder.BuildFromSingleStandardModule(inputCode, out component);
              var project = vbe.Object.VBProjects.Item(0);
              var module = project.VBComponents.Item(0).CodeModule;
              var mockHost = new Mock<IHostApplication>();
              mockHost.SetupAllProperties();
              var parser = MockParser.Create(vbe.Object, new RubberduckParserState(new Mock<ISinks>().Object));
  
              parser.Parse(new CancellationTokenSource());
              if (parser.State.Status >= ParserState.Error) { Assert.Inconclusive("Parser Error"); }
  
              var inspection = new MultipleDeclarationsInspection(parser.State);
              var inspectionResults = inspection.GetInspectionResults();
  
              inspectionResults.First().QuickFixes.First().Fix();
  
              Assert.AreEqual(expectedCode, module.Lines());
          }
  
          [TestMethod]
          [TestCategory("Inspections")]
          public void MultipleDeclarations_QuickFixWorks_Constants()
          {
              const string inputCode =
  @"Public Sub Foo()
      Const var1 As Integer = 9, var2 As String = ""test""
  End Sub";
  
              const string expectedCode =
  @"Public Sub Foo()
  Const var1 As Integer = 9
  Const var2 As String = ""test""
  
  End Sub";
  
              //Arrange
              var builder = new MockVbeBuilder();
              VBComponent component;
              var vbe = builder.BuildFromSingleStandardModule(inputCode, out component);
              var project = vbe.Object.VBProjects.Item(0);
  
gt:             var module = project.VBComponents.Item(0).CodeModule;