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); }
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); }
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); }