Skip to content

Commit

Permalink
Added First Line Attributes Option, Resolves #4
Browse files Browse the repository at this point in the history
  • Loading branch information
Dave Grochocki committed Feb 18, 2016
1 parent aa0aac0 commit ec2f30e
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 2 deletions.
2 changes: 2 additions & 0 deletions Service/Options/IStylerOptions.cs
Expand Up @@ -15,6 +15,8 @@ public interface IStylerOptions

bool KeepFirstAttributeOnSameLine { get; set; }

string FirstLineAttributes { get; set; }

int MaxAttributeCharatersPerLine { get; set; }

int MaxAttributesPerLine { get; set; }
Expand Down
7 changes: 7 additions & 0 deletions Service/Options/StylerOptions.cs
Expand Up @@ -164,6 +164,13 @@ public string SerializedAttributeOrderingRuleGroups
}
}

[Category("Attribute Reordering")]
[DisplayName("First Line Attributes")]
[JsonProperty("FirstLineAttributes", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)]
[Description("Defines a list of attributes which should always appear on the same line as the element's start tag. Attribute reordering must be enabled for this setting to take effect.\r\n\r\nDefault Value: None")]
[DefaultValue("")]
public string FirstLineAttributes { get; set; }

[Category("Attribute Reordering")]
[DisplayName("Order Attributes By Name")]
[JsonProperty("OrderAttributesByName", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)]
Expand Down
1 change: 1 addition & 0 deletions Service/Options/defaultSettings.json
Expand Up @@ -20,6 +20,7 @@
"PageSource, PageIndex, Offset, Color, TargetName, Property, Value, StartPoint, EndPoint",
"mc:Ignorable, d:IsDataSource, d:LayoutOverrides, d:IsStaticText"
],
"FirstLineAttributes": "",
"OrderAttributesByName": true,
"PutEndingBracketOnNewLine": false,
"RemoveEndingTagOfEmptyElement": true,
Expand Down
41 changes: 39 additions & 2 deletions Service/StylerService.cs
Expand Up @@ -23,6 +23,8 @@ public class StylerService : XmlEscapingService

private IList<string> NewlineExemptionElementsList { get; set; }

private IList<string> FirstLineAttributes { get; set; }

private IList<string> NoNewLineMarkupExtensionsList { get; set; }

private AttributeOrderRules OrderRules { get; set; }
Expand Down Expand Up @@ -98,6 +100,7 @@ public static StylerService CreateInstance(IStylerOptions options)
{
var stylerServiceInstance = new StylerService { Options = options };
stylerServiceInstance.NewlineExemptionElementsList = stylerServiceInstance.Options.NewlineExemptionElements.ToList();
stylerServiceInstance.FirstLineAttributes = stylerServiceInstance.Options.FirstLineAttributes.ToList();
stylerServiceInstance.NoNewLineMarkupExtensionsList = stylerServiceInstance.Options.NoNewLineMarkupExtensions.ToList();
stylerServiceInstance.OrderRules = new AttributeOrderRules(options);
stylerServiceInstance.ElementProcessStatusStack.Clear();
Expand Down Expand Up @@ -278,6 +281,11 @@ private bool IsNoLineBreakElement(string elementName)
return this.NewlineExemptionElementsList.Contains<string>(elementName);
}

private bool IsFirstLineAttribute(string attributeName)
{
return this.FirstLineAttributes.Contains<string>(attributeName);
}

private void ProcessXMLRoot(XmlReader xmlReader, StringBuilder output)
{
output.Append("<?xml ").Append(xmlReader.Value.Trim()).Append(" ?>");
Expand Down Expand Up @@ -393,6 +401,7 @@ private void ProcessElement(XmlReader xmlReader, StringBuilder output)
bool isEmptyElement = xmlReader.IsEmptyElement;
bool hasPutEndingBracketOnNewLine = false;
var list = new List<AttributeInfo>(xmlReader.AttributeCount);
var firstLineList = new List<AttributeInfo>(xmlReader.AttributeCount);

if (xmlReader.HasAttributes)
{
Expand All @@ -401,7 +410,15 @@ private void ProcessElement(XmlReader xmlReader, StringBuilder output)
string attributeName = xmlReader.Name;
string attributeValue = xmlReader.Value;
AttributeOrderRule orderRule = OrderRules.GetRuleFor(attributeName);
list.Add(new AttributeInfo(attributeName, attributeValue, orderRule));

var attribute = new AttributeInfo(attributeName, attributeValue, orderRule);
list.Add(attribute);

// Maintain separate list of first line attributes.
if (this.Options.EnableAttributeReordering && this.IsFirstLineAttribute(attribute.Name))
{
firstLineList.Add(attribute);
}

// Check for xml:space as defined in http://www.w3.org/TR/2008/REC-xml-20081126/#sec-white-space
if (xmlReader.IsXmlSpaceAttribute())
Expand All @@ -413,6 +430,7 @@ private void ProcessElement(XmlReader xmlReader, StringBuilder output)
if (this.Options.EnableAttributeReordering)
{
list.Sort(AttributeInfoComparison);
firstLineList.Sort(AttributeInfoComparison);
}

currentIndentString = this.GetIndentString(xmlReader.Depth);
Expand Down Expand Up @@ -459,8 +477,27 @@ private void ProcessElement(XmlReader xmlReader, StringBuilder output)
int attributeCountInCurrentLineBuffer = 0;

AttributeInfo lastAttributeInfo = null;

// Process first line attributes.
string firstLine = String.Empty;
foreach (var attrInfo in firstLineList)
{
firstLine = $"{firstLine} {attrInfo.ToSingleLineString()}";
}

if (firstLine.Length > 0)
{
attributeLines.Add(firstLine);
}

foreach (AttributeInfo attrInfo in list)
{
// Skip attributes already added to first line.
if (firstLineList.Contains(attrInfo))
{
continue;
}

// Attributes with markup extension, always put on new line
if (attrInfo.IsMarkupExtension && this.Options.FormatMarkupExtension)
{
Expand Down Expand Up @@ -537,7 +574,7 @@ private void ProcessElement(XmlReader xmlReader, StringBuilder output)

for (int i = 0; i < attributeLines.Count; i++)
{
if ((i == 0) && this.Options.KeepFirstAttributeOnSameLine)
if ((i == 0) && (this.Options.KeepFirstAttributeOnSameLine || (firstLineList.Count > 0)))
{
output.Append(' ').Append(attributeLines[i].Trim());

Expand Down
1 change: 1 addition & 0 deletions UnitTests/Configurations/Default.json
Expand Up @@ -20,6 +20,7 @@
"PageSource, PageIndex, Offset, Color, TargetName, Property, Value, StartPoint, EndPoint",
"mc:Ignorable, d:IsDataSource, d:LayoutOverrides, d:IsStaticText"
],
"FirstLineAttributes": "",
"OrderAttributesByName": true,
"PutEndingBracketOnNewLine": false,
"RemoveEndingTagOfEmptyElement": true,
Expand Down
1 change: 1 addition & 0 deletions UnitTests/TestConfigurations/AllDifferent.json
Expand Up @@ -8,6 +8,7 @@
"SeparateByGroups": true,
"EnableAttributeReordering": false,
"AttributeOrderingRuleGroups": [ "x:Class" ],
"FirstLineAttributes": "x:Name",
"OrderAttributesByName": false,
"PutEndingBracketOnNewLine": true,
"RemoveEndingTagOfEmptyElement": false,
Expand Down
1 change: 1 addition & 0 deletions UnitTests/TestConfigurations/BadSetting.json
Expand Up @@ -20,6 +20,7 @@
"PageSource, PageIndex, Offset, Color, TargetName, Property, Value, StartPoint, EndPoint",
"mc:Ignorable, d:IsDataSource, d:LayoutOverrides, d:IsStaticText"
],
"FirstLineAttributes": "",
"OrderAttributesByName": true,
"PutEndingBracketOnNewLine": false,
"RemoveEndingTagOfEmptyElement": true,
Expand Down
1 change: 1 addition & 0 deletions UnitTests/TestConfigurations/Default.json
Expand Up @@ -20,6 +20,7 @@
"PageSource, PageIndex, Offset, Color, TargetName, Property, Value, StartPoint, EndPoint",
"mc:Ignorable, d:IsDataSource, d:LayoutOverrides, d:IsStaticText"
],
"FirstLineAttributes": "",
"OrderAttributesByName": true,
"PutEndingBracketOnNewLine": false,
"RemoveEndingTagOfEmptyElement": true,
Expand Down
22 changes: 22 additions & 0 deletions UnitTests/TestFiles/TestKeepSelectAttributesOnFirstLine.expected
@@ -0,0 +1,22 @@
<Window
x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Button x:Name="Test" Content="Button 1" />
<Button x:Name="Test2"
Background="Pink"
Content="Button 2" />
<Button Background="Red" Content="Button 3" />
<Button
Width="150"
Background="Orange"
Content="Button 4" />
<Button x:Key="Key5"
Background="Yellow"
Content="Button 5" />
<Button x:Key="Key6" x:Name="Test6"
Background="Blue"
Content="Button 6" />
</Grid>
</Window>
26 changes: 26 additions & 0 deletions UnitTests/TestFiles/TestKeepSelectAttributesOnFirstLine.testxaml
@@ -0,0 +1,26 @@
<Window
x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Button x:Name="Test" Content="Button 1" />
<Button
x:Name="Test2"
Background="Pink"
Content="Button 2" />
<Button Background="Red" Content="Button 3" />
<Button
Width="150"
Background="Orange"
Content="Button 4" />
<Button
x:Key="Key5"
Background="Yellow"
Content="Button 5" />
<Button
x:Name="Test6"
x:Key="Key6"
Background="Blue"
Content="Button 6" />
</Grid>
</Window>
11 changes: 11 additions & 0 deletions UnitTests/UnitTests.AttributeFormatting.cs
Expand Up @@ -20,6 +20,17 @@ public void TestAttributeThresholdHandling()
this.DoTest(stylerOptions);
}

[Test]
public void TestKeepSelectAttributesOnFirstLine()
{
var stylerOptions = new StylerOptions(config: this.defaultConfig)
{
FirstLineAttributes = "x:Name, x:Key"
};

this.DoTest(stylerOptions);
}

[Test]
public void TestAttributeOrderRuleGroupsOnSeparateLinesHandling()
{
Expand Down
6 changes: 6 additions & 0 deletions UnitTests/UnitTests.csproj
Expand Up @@ -167,6 +167,12 @@
<None Include="TestFiles\TestCommentHandling_3.expected">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="TestFiles\TestKeepSelectAttributesOnFirstLine.expected">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="TestFiles\TestKeepSelectAttributesOnFirstLine.testxaml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="TestFiles\TestWildcard.expected">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
Expand Down

0 comments on commit ec2f30e

Please sign in to comment.