public void CalculateSpan_StartPositionExceedsSnapshotLength_ReturnsSpanWithEndOfFile()
        {
            // These values were taken from a real analysis issue
            // Rule "cpp:S113 - no newline at end of file" returns an offset after the end of the file.

            // Arrange
            var issue = new DummyAnalysisIssueLocation
            {
                StartLine       = 53,
                StartLineOffset = 2,
                EndLine         = 53,
                EndLineOffset   = 3,
                LineHash        = "some hash"
            };

            var firstLine = new VSLineDescription
            {
                ZeroBasedLineNumber = 52,
                LineLength          = 1,
                LineStartPosition   = 1599,
                Text = "some text"
            };

            // Second line should not be used in this case
            var secondLine = new VSLineDescription
            {
                ZeroBasedLineNumber = -999,
                LineLength          = -999,
                LineStartPosition   = -999
            };

            checksumCalculatorMock.Setup(x => x.Calculate(firstLine.Text)).Returns(issue.LineHash);

            var textSnapshotMock = CreateSnapshotMock(snapShotLength: 1600, lines: new[] { firstLine, secondLine });

            // Act
            var result = testSubject.CalculateSpan(issue, textSnapshotMock.Object);

            // Assert
            result.IsEmpty.Should().BeFalse();
            result.Start.Position.Should().Be(1599); // firstLine.LineStartPosition. Ignore offset because that will take us beyond the end of file
            result.End.Position.Should().Be(1600);   // snapshot length
        }
        public void CalculateSpan_EndLineIsZero_ReturnsSpanOfTheEntireStartLine()
        {
            // If issue.EndLine is zero the whole of the start line should be selected

            // Arrange
            var issue = new DummyAnalysisIssueLocation
            {
                StartLine       = 22,
                StartLineOffset = 2,
                EndLine         = 0,
                EndLineOffset   = 0,
                LineHash        = "some hash"
            };

            var firstLine = new VSLineDescription
            {
                ZeroBasedLineNumber = 21,
                LineLength          = 34,
                LineStartPosition   = 103,
                Text = "some text"
            };

            // The second VS line shouldn't be used in this case
            var secondLine = new VSLineDescription
            {
                ZeroBasedLineNumber = 25,
                LineLength          = 100,
                LineStartPosition   = 1010
            };

            checksumCalculatorMock.Setup(x => x.Calculate(firstLine.Text)).Returns(issue.LineHash);

            var textSnapshotMock = CreateSnapshotMock(lines: new[] { firstLine, secondLine });

            // Act
            var result = testSubject.CalculateSpan(issue, textSnapshotMock.Object);

            // Assert
            result.IsEmpty.Should().BeFalse();
            result.Start.Position.Should().Be(103); // firstLine.LineStartPosition. Ignore issue.StartLineOffset in this case
            result.End.Position.Should().Be(137);   // firstLine.LineStartPosition +  firstLine.LineLength
        }
        public void CalculateSpan_IssueLinesInsideSnapshot_ReturnsSpanWithCorrectPositions()
        {
            // Arrange
            var issue = new DummyAnalysisIssueLocation
            {
                StartLine       = 3,
                StartLineOffset = 10,
                EndLine         = 4,
                EndLineOffset   = 20,
                LineHash        = "some hash"
            };

            var firstLine = new VSLineDescription
            {
                ZeroBasedLineNumber = 2,
                LineLength          = 10,
                LineStartPosition   = 35,
                Text = "some text"
            };

            var secondLine = new VSLineDescription
            {
                ZeroBasedLineNumber = 3,
                LineLength          = 25,
                LineStartPosition   = 47
            };

            checksumCalculatorMock.Setup(x => x.Calculate(firstLine.Text)).Returns(issue.LineHash);

            var textSnapshotMock = CreateSnapshotMock(lines: new[] { firstLine, secondLine });

            // Act
            var result = testSubject.CalculateSpan(issue, textSnapshotMock.Object);

            // Assert
            result.IsEmpty.Should().BeFalse();
            result.Start.Position.Should().Be(45); // firstLine.LineStartPosition + issue.StartLineOffset
            result.End.Position.Should().Be(67);   // secondLine.LineStartPosition + issue.EndLineOffset
        }
        public void CalculateSpan_EndPositionExceedsSnapshotLength()
        {
            // Defensive: handle the issue end position being beyond the end of the snapshot
            // (we have not seen this in practice so far)

            // Arrange
            var issue = new DummyAnalysisIssueLocation
            {
                StartLine       = 53,
                StartLineOffset = 2,
                EndLine         = 53,
                EndLineOffset   = 12,
                LineHash        = "some hash"
            };

            // The issue is on a single line in this case, but the issue end position
            // is beyond the end of the line.
            var vsLine = new VSLineDescription
            {
                ZeroBasedLineNumber = 52,
                LineLength          = 10,
                LineStartPosition   = 1599,
                Text = "some text"
            };

            var textSnapshotMock = CreateSnapshotMock(lines: vsLine, snapShotLength: 1602);

            checksumCalculatorMock.Setup(x => x.Calculate(vsLine.Text)).Returns(issue.LineHash);

            // Act
            var result = testSubject.CalculateSpan(issue, textSnapshotMock.Object);

            // Assert
            result.IsEmpty.Should().BeFalse();
            result.Start.Position.Should().Be(1601); // vsLine.LineStartPosition + issue.StartLineOffset
            result.End.Position.Should().Be(1602);   // snapshot length
        }