public void CreatePreviewCorrectly_WithNestedGrid_MultipleIdenticalRows()
        {
            var original = "<Page>"
                           + Environment.NewLine + "    <Grid>"
                           + Environment.NewLine + "        <Grid.RowDefinitions>"
                           + Environment.NewLine + "            ☆<RowDefinition Height=\"*\" />"
                           + Environment.NewLine + "            <RowDefinition Height=\"Auto\" />"
                           + Environment.NewLine + "            <RowDefinition Height=\"*\" />"
                           + Environment.NewLine + "        </Grid.RowDefinitions>"
                           + Environment.NewLine + ""
                           + Environment.NewLine + "        <Grid Grid.Row=\"1\">"
                           + Environment.NewLine + "            <!-- content -->"
                           + Environment.NewLine + "        </Grid>"
                           + Environment.NewLine + ""
                           + Environment.NewLine + "        <TextBlock Text=\"Footer\" Grid.Row=\"2\" />"
                           + Environment.NewLine + "        <TextBlock Text=\"OtherFooter\" Grid.Row=\"2\" />"
                           + Environment.NewLine + "    </Grid>"
                           + Environment.NewLine + "</Page>";

            var expected = "<Page>"
                           + Environment.NewLine + "    <Grid>"
                           + Environment.NewLine + "        <Grid.RowDefinitions>"
                           + Environment.NewLine + "            <RowDefinition Height=\"XXX\" />"
                           + Environment.NewLine + "            <RowDefinition Height=\"*\" />"
                           + Environment.NewLine + "            <RowDefinition Height=\"Auto\" />"
                           + Environment.NewLine + "            <RowDefinition Height=\"*\" />"
                           + Environment.NewLine + "        </Grid.RowDefinitions>"
                           + Environment.NewLine + ""
                           + Environment.NewLine + "        <Grid Grid.Row=\"2\">"
                           + Environment.NewLine + "            <!-- content -->"
                           + Environment.NewLine + "        </Grid>"
                           + Environment.NewLine + ""
                           + Environment.NewLine + "        <TextBlock Text=\"Footer\" Grid.Row=\"3\" />"
                           + Environment.NewLine + "        <TextBlock Text=\"OtherFooter\" Grid.Row=\"3\" />"
                           + Environment.NewLine + "    </Grid>"
                           + Environment.NewLine + "</Page>";

            var tag = new InsertRowDefinitionTag(new Span(0, 0), new FakeTextSnapshot(), "testfile.xaml", DefaultTestLogger.Create())
            {
                XamlTag      = "<RowDefinition Height=\"XXX\" />",
                InsertPoint  = original.IndexOf("☆", StringComparison.Ordinal),
                GridStartPos = 12,
            };

            var actual = InsertRowDefinitionAction.GetPreviewText(
                original.Replace("☆", string.Empty),
                InsertRowDefinitionAction.GetReplacements(1, 3),
                null,
                tag);

            StringAssert.AreEqual(expected, actual);
        }
示例#2
0
        public void CreatePreviewCorrectly_Row1()
        {
            var original = "<Page>"
                           + Environment.NewLine + "    <Grid>"
                           + Environment.NewLine + "        <Grid.RowDefinitions>"
                           + Environment.NewLine + "            <RowDefinition Height=\"*\" />"
                           + Environment.NewLine + "            ☆<RowDefinition Height=\"Auto\" />"
                           + Environment.NewLine + "            <RowDefinition Height=\"*\" />"
                           + Environment.NewLine + "        </Grid.RowDefinitions>"
                           + Environment.NewLine + ""
                           + Environment.NewLine + "        <TextBlock Text=\"Footer\" Grid.Row=\"2\" />"
                           + Environment.NewLine + "    </Grid>"
                           + Environment.NewLine + "</Page>";

            var expected = "<Page>"
                           + Environment.NewLine + "    <Grid>"
                           + Environment.NewLine + "        <Grid.RowDefinitions>"
                           + Environment.NewLine + "            <RowDefinition Height=\"*\" />"
                           + Environment.NewLine + "            <RowDefinition Height=\"XXX\" />"
                           + Environment.NewLine + "            <RowDefinition Height=\"Auto\" />"
                           + Environment.NewLine + "            <RowDefinition Height=\"*\" />"
                           + Environment.NewLine + "        </Grid.RowDefinitions>"
                           + Environment.NewLine + ""
                           + Environment.NewLine + "        <TextBlock Text=\"Footer\" Grid.Row=\"3\" />"
                           + Environment.NewLine + "    </Grid>"
                           + Environment.NewLine + "</Page>";

            var tag = new InsertRowDefinitionTag(new Span(0, 0), new FakeTextSnapshot())
            {
                XamlTag      = "<RowDefinition Height=\"XXX\" />",
                InsertPoint  = original.IndexOf("☆", StringComparison.Ordinal),
                GridStartPos = 12,
            };

            var actual = InsertRowDefinitionAction.GetPreviewText(
                original.Replace("☆", string.Empty),
                InsertRowDefinitionAction.GetReplacements(1, 3),
                null,
                tag);

            StringAssert.AreEqual(expected, actual);
        }
示例#3
0
        public override void Process(string fileName, int offset, string xamlElement, string linePadding, ITextSnapshot snapshot, TagList tags, List <TagSuppression> suppressions = null)
        {
            const string gridOpenSpace    = "<Grid ";
            const string gridOpenComplete = "<Grid>";

            var endOfOpening    = xamlElement.IndexOf(">", StringComparison.Ordinal) + 1;
            var firstNestedGrid = xamlElement.FirstIndexOf(gridOpenSpace, gridOpenComplete);

            var rowDefPos = xamlElement.IndexOf("<Grid.RowDefinitions", StringComparison.Ordinal);
            var colDefPos = xamlElement.IndexOf("<Grid.ColumnDefinitions", StringComparison.Ordinal);

            var gridIsSelfClosing = XamlElementProcessor.IsSelfClosing(xamlElement);

            var hasRowDef = false;

            if (rowDefPos > 0)
            {
                hasRowDef = firstNestedGrid <= 0 || rowDefPos < firstNestedGrid;
            }

            var hasColDef = false;

            if (colDefPos > 0)
            {
                hasColDef = firstNestedGrid <= 0 || colDefPos < firstNestedGrid;
            }

            var leftPad = linePadding.Contains("\t") ? linePadding + "\t" : linePadding + "    ";

            var rowDefsClosingPos = -1;

            if (!hasRowDef)
            {
                var tag = new AddRowDefinitionsTag(new Span(offset, endOfOpening), snapshot, fileName, this.Logger)
                {
                    InsertPosition     = offset + endOfOpening,
                    LeftPad            = leftPad,
                    GridNeedsExpanding = gridIsSelfClosing,
                };
                tags.TryAdd(tag, xamlElement, suppressions);

                rowDefsClosingPos = xamlElement.IndexOf(">", StringComparison.Ordinal);
            }
            else
            {
                rowDefsClosingPos = xamlElement.IndexOf("</Grid.RowDefinitions", StringComparison.Ordinal);
            }

            var colDefsClosingPos = -1;

            if (!hasColDef)
            {
                var tag = new AddColumnDefinitionsTag(new Span(offset, endOfOpening), snapshot, fileName, this.Logger)
                {
                    InsertPosition     = offset + endOfOpening,
                    LeftPad            = leftPad,
                    GridNeedsExpanding = gridIsSelfClosing,
                };
                tags.TryAdd(tag, xamlElement, suppressions);

                colDefsClosingPos = xamlElement.IndexOf(">", StringComparison.Ordinal);
            }
            else
            {
                colDefsClosingPos = xamlElement.IndexOf("</Grid.ColumnDefinitions", StringComparison.Ordinal);
            }

            if (!hasRowDef && !hasColDef)
            {
                var tag = new AddRowAndColumnDefinitionsTag(new Span(offset, endOfOpening), snapshot, fileName, this.Logger)
                {
                    InsertPosition     = offset + endOfOpening,
                    LeftPad            = leftPad,
                    GridNeedsExpanding = gridIsSelfClosing,
                };
                tags.TryAdd(tag, xamlElement, suppressions);
            }

            const string rowDefStart = "<RowDefinition";

            var rowDefsCount = 0;

            var toAdd = new List <InsertRowDefinitionTag>();

            var rowDefIndex = xamlElement.IndexOf(rowDefStart, StringComparison.Ordinal);

            while (rowDefIndex >= 0)
            {
                var endPos = xamlElement.IndexOf('>', rowDefIndex);

                var tag = new InsertRowDefinitionTag(new Span(offset + rowDefIndex, endPos - rowDefIndex + 1), snapshot, fileName, this.Logger)
                {
                    RowId        = rowDefsCount,
                    GridStartPos = offset,
                    GridLength   = xamlElement.Length,
                    XamlTag      = xamlElement.Substring(rowDefIndex, endPos - rowDefIndex + 1),
                    InsertPoint  = offset + rowDefIndex,
                };

                rowDefsCount += 1;

                toAdd.Add(tag);

                rowDefIndex = xamlElement.IndexOf(rowDefStart, endPos, StringComparison.Ordinal);
            }

            foreach (var tag in toAdd)
            {
                tag.RowCount = rowDefsCount;
                tags.TryAdd(tag, xamlElement, suppressions);
            }

            const string colDef = "<ColumnDefinition";

            var colDefsCount = 0;

            var colDefIndex = xamlElement.IndexOf(colDef, StringComparison.Ordinal);

            while (colDefIndex > -1)
            {
                colDefsCount += 1;

                colDefIndex = xamlElement.IndexOf(colDef, colDefIndex + 1, StringComparison.Ordinal);
            }

            const string rowDefUse = "Grid.Row=\"";
            const string colDefUse = "Grid.Column=\"";

            int highestAssignedRow = -1;
            int highestAssignedCol = -1;

            var undefinedTags = new List <MissingDefinitionTag>();

            var nextDefUseIndex = xamlElement.FirstIndexOf(rowDefUse, colDefUse);
            var defUseOffset    = 0;

            while (nextDefUseIndex > 0)
            {
                defUseOffset += nextDefUseIndex;

                if (nextDefUseIndex > endOfOpening)
                {
                    if (!xamlElement.InComment(defUseOffset))
                    {
                        // Get assigned value
                        if (xamlElement.Substring(defUseOffset).StartsWith(rowDefUse))
                        {
                            var valueStartPos = defUseOffset + rowDefUse.Length;
                            var closePos      = xamlElement.IndexOf("\"", valueStartPos, StringComparison.Ordinal);

                            var assignedStr = xamlElement.Substring(valueStartPos, closePos - valueStartPos);

                            if (int.TryParse(assignedStr, out int assignedInt))
                            {
                                if (assignedInt > 0 && assignedInt >= rowDefsCount)
                                {
                                    undefinedTags.Add(new MissingRowDefinitionTag(
                                                          new Span(offset + defUseOffset, closePos - defUseOffset + 1),
                                                          snapshot,
                                                          fileName,
                                                          this.Logger)
                                    {
                                        AssignedInt        = assignedInt,
                                        Description        = StringRes.UI_XamlAnalysisMissingRowDefinitionDescription.WithParams(assignedInt),
                                        ExistingDefsCount  = rowDefsCount,
                                        HasSomeDefinitions = hasRowDef,
                                        InsertPosition     = offset + rowDefsClosingPos,
                                        LeftPad            = leftPad,
                                    });
                                }

                                if (assignedInt > highestAssignedRow)
                                {
                                    highestAssignedRow = assignedInt;
                                }
                            }
                        }
                        else if (xamlElement.Substring(defUseOffset).StartsWith(colDefUse))
                        {
                            var valueStartPos = defUseOffset + colDefUse.Length;
                            var closePos      = xamlElement.IndexOf("\"", valueStartPos, StringComparison.Ordinal);

                            var assignedStr = xamlElement.Substring(valueStartPos, closePos - valueStartPos);

                            if (int.TryParse(assignedStr, out int assignedInt))
                            {
                                if (assignedInt > 0 && assignedInt >= colDefsCount)
                                {
                                    undefinedTags.Add(new MissingColumnDefinitionTag(
                                                          new Span(offset + defUseOffset, closePos - defUseOffset + 1),
                                                          snapshot,
                                                          fileName,
                                                          this.Logger)
                                    {
                                        AssignedInt        = assignedInt,
                                        Description        = StringRes.UI_XamlAnalysisMissingColumnDefinitionDescription.WithParams(assignedInt),
                                        ExistingDefsCount  = colDefsCount,
                                        HasSomeDefinitions = hasColDef,
                                        InsertPosition     = offset + colDefsClosingPos,
                                        LeftPad            = leftPad,
                                    });
                                }

                                if (assignedInt > highestAssignedCol)
                                {
                                    highestAssignedCol = assignedInt;
                                }
                            }
                        }
                    }
                }

                nextDefUseIndex = xamlElement.Substring(defUseOffset + 1).FirstIndexOf(colDefUse, rowDefUse) + 1;
            }

            foreach (var undefinedTag in undefinedTags)
            {
                undefinedTag.TotalDefsRequired = undefinedTag is MissingRowDefinitionTag ? highestAssignedRow
                                                                                         : highestAssignedCol;
                tags.TryAdd(undefinedTag, xamlElement, suppressions);
            }

            const string rowSpanUse = "Grid.RowSpan=\"";
            const string colSpanUse = "Grid.ColumnSpan=\"";

            var nextSpanUseIndex = xamlElement.FirstIndexOf(rowSpanUse, colSpanUse);
            var spanUseOffset    = 0;

            while (nextSpanUseIndex > 0)
            {
                spanUseOffset += nextSpanUseIndex;

                if (nextSpanUseIndex > endOfOpening)
                {
                    if (!xamlElement.InComment(spanUseOffset))
                    {
                        if (xamlElement.Substring(spanUseOffset).StartsWith(rowSpanUse))
                        {
                            var valueStartPos = spanUseOffset + rowSpanUse.Length;
                            var closePos      = xamlElement.IndexOf("\"", valueStartPos, StringComparison.Ordinal);

                            var assignedStr = xamlElement.Substring(valueStartPos, closePos - valueStartPos);

                            if (int.TryParse(assignedStr, out int assignedInt))
                            {
                                var element = XamlElementProcessor.GetSubElementAtPosition(this.ProjectType, fileName, snapshot, xamlElement, spanUseOffset, this.Logger);

                                var row = 0;
                                if (this.TryGetAttribute(element, "Grid.Row", AttributeType.InlineOrElement, out _, out _, out _, out string rowStr))
                                {
                                    row = int.Parse(rowStr);
                                }

                                if (assignedInt > 1 && assignedInt - 1 + row >= rowDefsCount)
                                {
                                    var rowTag = new RowSpanOverflowTag(
                                        new Span(offset + spanUseOffset, closePos - spanUseOffset + 1),
                                        snapshot,
                                        fileName,
                                        this.Logger)
                                    {
                                        TotalDefsRequired  = assignedInt + row - 1,
                                        Description        = StringRes.UI_XamlAnalysisRowSpanOverflowDescription,
                                        ExistingDefsCount  = rowDefsCount,
                                        HasSomeDefinitions = hasRowDef,
                                        InsertPosition     = offset + rowDefsClosingPos,
                                        LeftPad            = leftPad,
                                    };

                                    tags.TryAdd(rowTag, xamlElement, suppressions);
                                }
                            }
                        }
                        else if (xamlElement.Substring(spanUseOffset).StartsWith(colSpanUse))
                        {
                            var valueStartPos = spanUseOffset + colSpanUse.Length;
                            var closePos      = xamlElement.IndexOf("\"", valueStartPos, StringComparison.Ordinal);

                            var assignedStr = xamlElement.Substring(valueStartPos, closePos - valueStartPos);

                            if (int.TryParse(assignedStr, out int assignedInt))
                            {
                                var element = XamlElementProcessor.GetSubElementAtPosition(this.ProjectType, fileName, snapshot, xamlElement, spanUseOffset, this.Logger);

                                var gridCol = 0;
                                if (this.TryGetAttribute(element, "Grid.Column", AttributeType.InlineOrElement, out _, out _, out _, out string colStr))
                                {
                                    gridCol = int.Parse(colStr);
                                }

                                if (assignedInt > 1 && assignedInt - 1 + gridCol >= colDefsCount)
                                {
                                    var colTag = new ColumnSpanOverflowTag(
                                        new Span(offset + spanUseOffset, closePos - spanUseOffset + 1),
                                        snapshot,
                                        fileName,
                                        this.Logger)
                                    {
                                        TotalDefsRequired  = assignedInt - 1 + gridCol,
                                        Description        = StringRes.UI_XamlAnalysisColumnSpanOverflowDescription,
                                        ExistingDefsCount  = colDefsCount,
                                        HasSomeDefinitions = hasColDef,
                                        InsertPosition     = offset + colDefsClosingPos,
                                        LeftPad            = leftPad,
                                    };

                                    tags.TryAdd(colTag, xamlElement, suppressions);
                                }
                            }
                        }
                    }
                }

                nextSpanUseIndex = xamlElement.Substring(spanUseOffset + 1).FirstIndexOf(colSpanUse, rowSpanUse) + 1;
            }
        }
 private InsertRowDefinitionAction(string file, InsertRowDefinitionTag tag)
     : base(file)
 {
     this.tag         = tag;
     this.DisplayText = StringRes.UI_InsertNewDefinitionForRow.WithParams(this.tag.RowId);
 }
        public void RealWorldExample()
        {
            var original = ""
                           + Environment.NewLine + "<Window"
                           + Environment.NewLine + "    x:Class=\"RxtWpfDemo.MainWindow\""
                           + Environment.NewLine + "    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\""
                           + Environment.NewLine + "    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\""
                           + Environment.NewLine + "    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\""
                           + Environment.NewLine + "    xmlns:local=\"clr-namespace:RxtWpfDemo\""
                           + Environment.NewLine + "    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\""
                           + Environment.NewLine + "    Title=\"MainWindow\""
                           + Environment.NewLine + "    Width=\"800\""
                           + Environment.NewLine + "    Height=\"450\""
                           + Environment.NewLine + "    mc:Ignorable=\"d\">"
                           + Environment.NewLine + "    <Grid>"
                           + Environment.NewLine + "        <Grid.RowDefinitions>"
                           + Environment.NewLine + "            <RowDefinition />"
                           + Environment.NewLine + "            ☆<RowDefinition Height=\"*\" />"
                           + Environment.NewLine + "            <RowDefinition />"
                           + Environment.NewLine + "            <RowDefinition />"
                           + Environment.NewLine + "            <RowDefinition />"
                           + Environment.NewLine + "        </Grid.RowDefinitions>"
                           + Environment.NewLine + ""
                           + Environment.NewLine + "        <TextBlock Text=\"hello\" />"
                           + Environment.NewLine + ""
                           + Environment.NewLine + "        <TextBlock Text=\"world\" />"
                           + Environment.NewLine + ""
                           + Environment.NewLine + ""
                           + Environment.NewLine + "        <TextBlock Grid.Row=\"2\" Text=\"line 3\" />"
                           + Environment.NewLine + ""
                           + Environment.NewLine + "        <Grid>"
                           + Environment.NewLine + "            <TextBlock Text=\"hello world\" />"
                           + Environment.NewLine + "        </Grid>"
                           + Environment.NewLine + ""
                           + Environment.NewLine + "        <Button Grid.Row=\"1\" Content=\"click here\" />"
                           + Environment.NewLine + ""
                           + Environment.NewLine + "    </Grid>"
                           + Environment.NewLine + "</Window>";

            var expected = ""
                           + Environment.NewLine + "<Window"
                           + Environment.NewLine + "    x:Class=\"RxtWpfDemo.MainWindow\""
                           + Environment.NewLine + "    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\""
                           + Environment.NewLine + "    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\""
                           + Environment.NewLine + "    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\""
                           + Environment.NewLine + "    xmlns:local=\"clr-namespace:RxtWpfDemo\""
                           + Environment.NewLine + "    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\""
                           + Environment.NewLine + "    Title=\"MainWindow\""
                           + Environment.NewLine + "    Width=\"800\""
                           + Environment.NewLine + "    Height=\"450\""
                           + Environment.NewLine + "    mc:Ignorable=\"d\">"
                           + Environment.NewLine + "    <Grid>"
                           + Environment.NewLine + "        <Grid.RowDefinitions>"
                           + Environment.NewLine + "            <RowDefinition />"
                           + Environment.NewLine + "            <RowDefinition Height=\"XXX\" />"
                           + Environment.NewLine + "            <RowDefinition Height=\"*\" />"
                           + Environment.NewLine + "            <RowDefinition />"
                           + Environment.NewLine + "            <RowDefinition />"
                           + Environment.NewLine + "            <RowDefinition />"
                           + Environment.NewLine + "        </Grid.RowDefinitions>"
                           + Environment.NewLine + ""
                           + Environment.NewLine + "        <TextBlock Text=\"hello\" />"
                           + Environment.NewLine + ""
                           + Environment.NewLine + "        <TextBlock Text=\"world\" />"
                           + Environment.NewLine + ""
                           + Environment.NewLine + ""
                           + Environment.NewLine + "        <TextBlock Grid.Row=\"3\" Text=\"line 3\" />"
                           + Environment.NewLine + ""
                           + Environment.NewLine + "        <Grid>"
                           + Environment.NewLine + "            <TextBlock Text=\"hello world\" />"
                           + Environment.NewLine + "        </Grid>"
                           + Environment.NewLine + ""
                           + Environment.NewLine + "        <Button Grid.Row=\"2\" Content=\"click here\" />"
                           + Environment.NewLine + ""
                           + Environment.NewLine + "    </Grid>"
                           + Environment.NewLine + "</Window>";

            var tag = new InsertRowDefinitionTag(new Span(0, 0), new FakeTextSnapshot(), "testfile.xaml", DefaultTestLogger.Create())
            {
                XamlTag      = "<RowDefinition Height=\"XXX\" />",
                InsertPoint  = original.IndexOf("☆", StringComparison.Ordinal),
                GridStartPos = 451,
            };

            var actual = InsertRowDefinitionAction.GetPreviewText(
                original.Replace("☆", string.Empty),
                InsertRowDefinitionAction.GetReplacements(1, 5),
                null,
                tag);

            StringAssert.AreEqual(expected, actual);
        }
        public void CreatePreviewCorrectly_WithNestedGrid_AndExclusions()
        {
            var original = "<Page>"
                           + Environment.NewLine + "    <Grid>"
                           + Environment.NewLine + "        <Grid.RowDefinitions>"
                           + Environment.NewLine + "            ☆<RowDefinition Height=\"*\" />"
                           + Environment.NewLine + "            <RowDefinition Height=\"Auto\" />"
                           + Environment.NewLine + "            <RowDefinition Height=\"*\" />"
                           + Environment.NewLine + "        </Grid.RowDefinitions>"
                           + Environment.NewLine + ""
                           + Environment.NewLine + "        <Grid Grid.Row=\"1\">"
                           + Environment.NewLine + "            <RowDefinition Height=\"*\" />"
                           + Environment.NewLine + "            <RowDefinition Height=\"*\" />"
                           + Environment.NewLine + "            <RowDefinition Height=\"*\" />"
                           + Environment.NewLine + "            <RowDefinition Height=\"*\" />"
                           + Environment.NewLine + ""
                           + Environment.NewLine + "            <TextBlock Tex=\"Excluded\" Grid.Row=\"2\" />"
                           + Environment.NewLine + "        </Grid>"
                           + Environment.NewLine + ""
                           + Environment.NewLine + "        <TextBlock Text=\"Footer\" Grid.Row=\"2\" />"
                           + Environment.NewLine + "    </Grid>"
                           + Environment.NewLine + "</Page>";

            var expected = "<Page>"
                           + Environment.NewLine + "    <Grid>"
                           + Environment.NewLine + "        <Grid.RowDefinitions>"
                           + Environment.NewLine + "            <RowDefinition Height=\"XXX\" />"
                           + Environment.NewLine + "            <RowDefinition Height=\"*\" />"
                           + Environment.NewLine + "            <RowDefinition Height=\"Auto\" />"
                           + Environment.NewLine + "            <RowDefinition Height=\"*\" />"
                           + Environment.NewLine + "        </Grid.RowDefinitions>"
                           + Environment.NewLine + ""
                           + Environment.NewLine + "        <Grid Grid.Row=\"2\">"
                           + Environment.NewLine + "            <RowDefinition Height=\"*\" />"
                           + Environment.NewLine + "            <RowDefinition Height=\"*\" />"
                           + Environment.NewLine + "            <RowDefinition Height=\"*\" />"
                           + Environment.NewLine + "            <RowDefinition Height=\"*\" />"
                           + Environment.NewLine + ""
                           + Environment.NewLine + "            <TextBlock Tex=\"Excluded\" Grid.Row=\"2\" />"
                           + Environment.NewLine + "        </Grid>"
                           + Environment.NewLine + ""
                           + Environment.NewLine + "        <TextBlock Text=\"Footer\" Grid.Row=\"3\" />"
                           + Environment.NewLine + "    </Grid>"
                           + Environment.NewLine + "</Page>";

            var tag = new InsertRowDefinitionTag(new Span(0, 0), new FakeTextSnapshot(), "testfile.xaml", DefaultTestLogger.Create())
            {
                XamlTag      = "<RowDefinition Height=\"XXX\" />",
                InsertPoint  = original.IndexOf("☆", StringComparison.Ordinal),
                GridStartPos = 12,
            };

            var actualXaml = original.Replace("☆", string.Empty);

            // Get the position of the first grid and use it to find exclusions
            var exclusionGridPos = actualXaml.IndexOf("<Grid>", StringComparison.Ordinal);
            var exclusions       = InsertRowDefinitionAction.GetExclusions(actualXaml.Substring(exclusionGridPos));

            var actual = InsertRowDefinitionAction.GetPreviewText(
                actualXaml,
                InsertRowDefinitionAction.GetReplacements(1, 3),
                exclusions,
                tag);

            StringAssert.AreEqual(expected, actual);
        }