Skip to content
This repository was archived by the owner on Jul 12, 2022. It is now read-only.

Commit 519cd70

Browse files
author
Lakshmi Priya Sekar
committed
Fix bugs and incorporate code review feedback
1 parent eaf79a1 commit 519cd70

18 files changed

+214
-76
lines changed

src/CodeFormatter/CodeFormatter.csproj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
</ItemGroup>
106106
<ItemGroup>
107107
<None Include="App.config" />
108+
<None Include="IllegalHeaders.md" />
108109
<None Include="packages.config" />
109110
</ItemGroup>
110111
<ItemGroup>
@@ -117,8 +118,8 @@
117118
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
118119
Other similar extension points exist, see Microsoft.Common.targets.
119120
<Target Name="BeforeBuild">
120-
</Target>
121+
</Target> -->
121122
<Target Name="AfterBuild">
123+
<Copy SourceFiles="$(ProjectDir)IllegalHeaders.md" DestinationFolder="$(ProjectDir)$(OutDir)" ContinueOnError="true" />
122124
</Target>
123-
-->
124125
</Project>

src/CodeFormatter/IllegalHeaders.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
## Contains header comments that need to be removed from the start of file.
2+
3+
Copyright (c) Microsoft Corporation.
4+
<owner>
5+
</owner>
6+
==--==
7+
==++==
8+
<OWNER>
9+
</OWNER>

src/CodeFormatter/Program.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ private static int Main(string[] args)
3131

3232
Console.CancelKeyPress += delegate { cts.Cancel(); };
3333

34-
RunAsnc(solutionPath, ct).Wait(ct);
34+
RunAsync(solutionPath, ct).Wait(ct);
3535
Console.WriteLine("Completed formatting.");
3636
return 0;
3737
}
3838

39-
private static async Task RunAsnc(string solutionFilePath, CancellationToken cancellationToken)
39+
private static async Task RunAsync(string solutionFilePath, CancellationToken cancellationToken)
4040
{
4141
var workspace = MSBuildWorkspace.Create();
4242
await workspace.OpenSolutionAsync(solutionFilePath, cancellationToken);

src/Microsoft.DotNet.CodeFormatting/FormattingEngineImplementation.cs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,12 @@ public async Task<bool> RunAsync(Workspace workspace, CancellationToken cancella
3939
var shouldBeProcessed = await ShouldBeProcessedAsync(document);
4040
if (!shouldBeProcessed)
4141
continue;
42-
42+
43+
Console.WriteLine("Processing document: " + document.Name);
4344
var newDocument = await RewriteDocumentAsync(document, cancellationToken);
4445
hasChanges |= newDocument != document;
4546

4647
solution = newDocument.Project.Solution;
47-
48-
Console.WriteLine("Processed document: " + document.Name);
4948
}
5049

5150
if (workspace.TryApplyChanges(solution))
@@ -56,13 +55,6 @@ public async Task<bool> RunAsync(Workspace workspace, CancellationToken cancella
5655
return hasChanges;
5756
}
5857

59-
private static async Task SaveDocumentAsync(Document document, CancellationToken cancellationToken)
60-
{
61-
var text = await document.GetTextAsync(cancellationToken);
62-
using (var textWriter = new StreamWriter(document.FilePath))
63-
text.Write(textWriter, cancellationToken);
64-
}
65-
6658
private async Task<bool> ShouldBeProcessedAsync(Document document)
6759
{
6860
foreach (var filter in _filters)

src/Microsoft.DotNet.CodeFormatting/Microsoft.DotNet.CodeFormatting.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
<Compile Include="IFormattingFilter.cs" />
8484
<Compile Include="IFormattingRule.cs" />
8585
<Compile Include="Filters\IgnoreDesignerGeneratedCodeFilter.cs" />
86+
<Compile Include="RuleOrderAttribute.cs" />
8687
<Compile Include="Properties\AssemblyInfo.cs" />
8788
<Compile Include="IOrderMetadata.cs" />
8889
<Compile Include="Rules\HasCopyrightHeaderFormattingRule.cs" />
@@ -108,6 +109,5 @@
108109
<Target Name="BeforeBuild">
109110
</Target>
110111
<Target Name="AfterBuild">
111-
</Target>
112-
-->
112+
</Target>-->
113113
</Project>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.ComponentModel;
4+
using System.ComponentModel.Composition;
5+
using System.Linq;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
9+
namespace Microsoft.DotNet.CodeFormatting
10+
{
11+
[MetadataAttribute]
12+
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
13+
public sealed class RuleOrderAttribute : ExportAttribute
14+
{
15+
public RuleOrderAttribute(int order)
16+
: base(typeof(IFormattingRule))
17+
{
18+
Order = order;
19+
}
20+
21+
[DefaultValue(int.MaxValue)]
22+
public int Order { get; private set; }
23+
}
24+
}

src/Microsoft.DotNet.CodeFormatting/Rules/HasCopyrightHeaderFormattingRule.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212

1313
namespace Microsoft.DotNet.CodeFormatting.Rules
1414
{
15-
[Export(typeof(IFormattingRule))]
16-
[ExportMetadata("Order", 3)]
15+
[RuleOrder(3)]
1716
internal sealed class HasCopyrightHeaderFormattingRule : IFormattingRule
1817
{
1918
static readonly string[] CopyrightHeader =

src/Microsoft.DotNet.CodeFormatting/Rules/HasNewLineBeforeFirstNamespaceFormattingRule.cs

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@
1414

1515
namespace Microsoft.DotNet.CodeFormatting.Rules
1616
{
17-
[Export(typeof(IFormattingRule))]
18-
[ExportMetadata("Order", 6)]
17+
[RuleOrder(6)]
1918
internal sealed class HasNewLineBeforeFirstNamespaceFormattingRule : IFormattingRule
2019
{
2120
public async Task<Document> ProcessAsync(Document document, CancellationToken cancellationToken)
@@ -35,27 +34,28 @@ public async Task<Document> ProcessAsync(Document document, CancellationToken ca
3534
var trivia = firstNamespace.GetLeadingTrivia();
3635
if (SyntaxKind.EndOfLineTrivia == trivia.Last().CSharpKind())
3736
{
38-
newTrivia = GetCorrectedTrivia(trivia);
37+
newTrivia = GetLeadingTriviaWithEndNewLines(trivia);
3938
}
4039
else if (trivia.Last().HasStructure)
4140
{
42-
var previousTrivia = trivia.Take(trivia.Count - 1);
43-
newTrivia = GetCorrectedTrivia(previousTrivia).Concat(new[] { trivia.Last() });
41+
newTrivia = GetLeadingTriviaWithEndStructure(trivia);
4442
}
4543
else
4644
{
45+
// Add two new lines, previous element is a comment
4746
newTrivia = trivia.AddTwoNewLines();
4847
}
4948
}
5049
else
5150
{
51+
// Add a new line, previous element is a node
5252
newTrivia = newTrivia.AddNewLine();
5353
}
5454

5555
return document.WithSyntaxRoot(syntaxRoot.ReplaceNode(firstNamespace, firstNamespace.WithLeadingTrivia(newTrivia)));
5656
}
5757

58-
private IEnumerable<SyntaxTrivia> GetCorrectedTrivia(IEnumerable<SyntaxTrivia> trivia)
58+
private IEnumerable<SyntaxTrivia> GetLeadingTriviaWithEndNewLines(IEnumerable<SyntaxTrivia> trivia)
5959
{
6060
int index = trivia.Count() - 2;
6161
while (index >= 0)
@@ -67,15 +67,42 @@ private IEnumerable<SyntaxTrivia> GetCorrectedTrivia(IEnumerable<SyntaxTrivia> t
6767

6868
if (index < 0)
6969
{
70+
// Add a new line (previous element is a node)
7071
return trivia.Take(index + 1).AddNewLine();
7172
}
7273

7374
if (index >= 0 && trivia.ElementAt(index).HasStructure)
7475
{
75-
return trivia.Take(index + 1);
76+
// Insert new lines before the structured trivia
77+
return GetLeadingTriviaWithEndStructure(trivia.Take(index + 1));
7678
}
7779

80+
// Add two new lines after the last comment
7881
return trivia.Take(index + 1).AddTwoNewLines();
7982
}
83+
84+
private IEnumerable<SyntaxTrivia> GetLeadingTriviaWithEndStructure(IEnumerable<SyntaxTrivia> trivia)
85+
{
86+
int index = trivia.Count() - 1;
87+
while (index >= 0 && trivia.ElementAt(index).HasStructure)
88+
index--;
89+
90+
if (index < 0)
91+
{
92+
// Add a new line (previous element is a node) before the structure trivia list.
93+
return trivia.Take(0).AddNewLine().Concat(trivia);
94+
}
95+
96+
// Add two new lines (previous element is a comment) before the structure trivia list.
97+
if (SyntaxKind.EndOfLineTrivia != trivia.ElementAt(index).CSharpKind())
98+
return trivia.Take(index + 1).AddTwoNewLines().Concat(trivia.Skip(index + 1));
99+
100+
// Insert one new line before the structured trivia, previous element is new line
101+
if (SyntaxKind.EndOfLineTrivia != trivia.ElementAt(index - 1).CSharpKind())
102+
return trivia.Take(index + 1).AddNewLine().Concat(trivia.Skip(index + 1));
103+
104+
// Already has the right format
105+
return trivia;
106+
}
80107
}
81108
}

src/Microsoft.DotNet.CodeFormatting/Rules/HasNewLineBeforeFirstUsingFormattingRule.cs

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,55 +14,54 @@
1414

1515
namespace Microsoft.DotNet.CodeFormatting.Rules
1616
{
17-
[Export(typeof(IFormattingRule))]
18-
[ExportMetadata("Order", 5)]
17+
[RuleOrder(5)]
1918
internal sealed class HasNewLineBeforeFirstUsingFormattingRule : IFormattingRule
2019
{
21-
public async Task<Document> ProcessAsync(Document document, CancellationToken cancellationToken)
22-
{
23-
// Roslyn formatter doesn't format code in #if false as it's considered as DisabledTextTrivia. Will be removed after the bug is fixed.
24-
// Doing that manually here
25-
var preprocessorNames = document.DefinedProjectPreprocessorNames();
26-
var newDocument = await document.GetNewDocumentWithPreprocessorSymbols(preprocessorNames, cancellationToken);
27-
newDocument = await FormatUsingInDocument(newDocument, cancellationToken);
28-
29-
return await FormatUsingInDocument(newDocument.GetOriginalDocumentWithPreprocessorSymbols(preprocessorNames), cancellationToken);
30-
}
20+
private const string FormatError = "Could not format using";
3121

32-
public async Task<Document> FormatUsingInDocument(Document document, CancellationToken cancellationToken)
22+
public async Task<Document> ProcessAsync(Document document, CancellationToken cancellationToken)
3323
{
3424
var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken) as CSharpSyntaxNode;
3525
if (syntaxRoot == null)
3626
return document;
3727

3828
var firstUsing = syntaxRoot.DescendantNodesAndSelf().OfType<UsingDirectiveSyntax>().FirstOrDefault();
39-
IEnumerable<SyntaxTrivia> newTrivia = Enumerable.Empty<SyntaxTrivia>();
40-
4129
if (firstUsing == null)
4230
return document;
4331

32+
IEnumerable<SyntaxTrivia> newTrivia = Enumerable.Empty<SyntaxTrivia>();
33+
4434
if (firstUsing.HasLeadingTrivia)
4535
{
4636
var trivia = firstUsing.GetLeadingTrivia();
37+
var x = trivia.FirstOrDefault(t => t.CSharpKind() == SyntaxKind.DisabledTextTrivia && t.ToFullString().Contains("using"));
38+
var disabledUsingSpan = trivia.FirstOrDefault(t => t.CSharpKind() == SyntaxKind.DisabledTextTrivia && t.ToFullString().Contains("using")).Span;
39+
if (!disabledUsingSpan.IsEmpty)
40+
{
41+
var line = syntaxRoot.SyntaxTree.GetLineSpan(disabledUsingSpan, cancellationToken).StartLinePosition.Line + 1;
42+
FormatError.WriteConsoleError(line, document.Name);
43+
return document;
44+
}
45+
4746
if (SyntaxKind.EndOfLineTrivia == trivia.Last().CSharpKind())
4847
{
49-
newTrivia = GetCorrectedTrivia(trivia);
48+
newTrivia = GetLeadingTriviaWithEndNewLines(trivia);
5049
}
5150
else if (trivia.Last().HasStructure)
5251
{
53-
var previousTrivia = trivia.Take(trivia.Count - 1);
54-
newTrivia = GetCorrectedTrivia(previousTrivia).Concat(new[] { trivia.Last() });
52+
newTrivia = GetLeadingTriviaWithEndStructure(trivia);
5553
}
5654
else
5755
{
56+
// Add two new lines, previous element is a comment
5857
newTrivia = trivia.AddTwoNewLines();
5958
}
6059
}
6160

6261
return document.WithSyntaxRoot(syntaxRoot.ReplaceNode(firstUsing, firstUsing.WithLeadingTrivia(newTrivia)));
6362
}
6463

65-
private IEnumerable<SyntaxTrivia> GetCorrectedTrivia(IEnumerable<SyntaxTrivia> trivia)
64+
private IEnumerable<SyntaxTrivia> GetLeadingTriviaWithEndNewLines(IEnumerable<SyntaxTrivia> trivia)
6665
{
6766
int index = trivia.Count() - 2;
6867
while (index >= 0)
@@ -74,15 +73,42 @@ private IEnumerable<SyntaxTrivia> GetCorrectedTrivia(IEnumerable<SyntaxTrivia> t
7473

7574
if (index < 0)
7675
{
76+
// Return empty trivia, there is no previous element: start of file.
7777
return Enumerable.Empty<SyntaxTrivia>();
7878
}
7979

8080
if (trivia.ElementAt(index).HasStructure)
8181
{
82-
return trivia.Take(index + 1);
82+
// Insert new lines before the structured trivia
83+
return GetLeadingTriviaWithEndStructure(trivia.Take(index + 1));
8384
}
8485

86+
// Add two new lines, previous element is a comment
8587
return trivia.Take(index + 1).AddTwoNewLines();
8688
}
89+
90+
private IEnumerable<SyntaxTrivia> GetLeadingTriviaWithEndStructure(IEnumerable<SyntaxTrivia> trivia)
91+
{
92+
int index = trivia.Count() - 1;
93+
while (index >= 0 && trivia.ElementAt(index).HasStructure)
94+
index--;
95+
96+
if (index < 0)
97+
{
98+
// There is no element before the structured trivia
99+
return trivia;
100+
}
101+
102+
// Insert two new lines before the structured trivia, previous element is a comment
103+
if (SyntaxKind.EndOfLineTrivia != trivia.ElementAt(index).CSharpKind())
104+
return trivia.Take(index + 1).AddTwoNewLines().Concat(trivia.Skip(index + 1));
105+
106+
// Insert one new line before the structured trivia, previous element is new line
107+
if (SyntaxKind.EndOfLineTrivia != trivia.ElementAt(index - 1).CSharpKind())
108+
return trivia.Take(index + 1).AddNewLine().Concat(trivia.Skip(index + 1));
109+
110+
// Already has the right format
111+
return trivia;
112+
}
87113
}
88114
}

src/Microsoft.DotNet.CodeFormatting/Rules/HasNoIllegalHeadersFormattingRule.cs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,33 @@
44
using System.Collections.Generic;
55
using System.ComponentModel.Composition;
66
using System.Linq;
7+
using System.IO;
78
using System.Threading;
89
using System.Threading.Tasks;
910

1011
using Microsoft.CodeAnalysis;
1112
using Microsoft.CodeAnalysis.CSharp;
13+
using System.Reflection;
1214

1315
namespace Microsoft.DotNet.CodeFormatting.Rules
1416
{
15-
[Export(typeof(IFormattingRule))]
16-
[ExportMetadata("Order", 2)]
17+
[RuleOrder(2)]
1718
internal sealed class HasNoIllegalHeadersFormattingRule : IFormattingRule
1819
{
19-
private static string[] IllegalHeaders = {"Copyright (c) Microsoft Corporation.", "<owner>", "</owner>", "==--==", "==++==", "<OWNER>", "</OWNER>" };
2020
public async Task<Document> ProcessAsync(Document document, CancellationToken cancellationToken)
2121
{
22+
2223
var syntaxNode = await document.GetSyntaxRootAsync(cancellationToken) as CSharpSyntaxNode;
2324
if (syntaxNode == null)
2425
return document;
2526

2627
var leadingTrivia = syntaxNode.GetLeadingTrivia();
2728
IEnumerable<SyntaxTrivia> newTrivia = leadingTrivia;
29+
var illegalHeaders = GetIllegalHeaders();
2830

2931
foreach (var trivia in leadingTrivia)
3032
{
31-
if (IllegalHeaders.Any(trivia.ToFullString().Contains))
33+
if (illegalHeaders.Any(trivia.ToFullString().Contains))
3234
{
3335
newTrivia = newTrivia.Where(t => t.ToFullString() != trivia.ToFullString());
3436
}
@@ -39,5 +41,19 @@ public async Task<Document> ProcessAsync(Document document, CancellationToken ca
3941

4042
return document.WithSyntaxRoot(syntaxNode.WithLeadingTrivia(newTrivia));
4143
}
44+
45+
public static string[] GetIllegalHeaders()
46+
{
47+
var filePath = Path.Combine(
48+
Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(Assembly.GetExecutingAssembly().CodeBase).Path)),
49+
"IllegalHeaders.md");
50+
51+
if (!File.Exists(filePath))
52+
{
53+
return new string[] { };
54+
}
55+
56+
return File.ReadAllLines(filePath).Where(l => !l.StartsWith("##") && !l.Equals("")).ToArray();
57+
}
4258
}
4359
}

0 commit comments

Comments
 (0)