Skip to content

Commit

Permalink
Merge pull request #1279 from sharwell/propagate-encoding
Browse files Browse the repository at this point in the history
Propagate encodings in SA1412
  • Loading branch information
sharwell committed Aug 25, 2015
2 parents a4427f0 + 4b004c5 commit 84c5811
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
{
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
Expand All @@ -23,12 +24,12 @@ public override Task<IEnumerable<Diagnostic>> GetAllDiagnosticsAsync(Project pro

public override Task<IEnumerable<Diagnostic>> GetDocumentDiagnosticsAsync(Document document, CancellationToken cancellationToken)
{
return Task.FromResult<IEnumerable<Diagnostic>>(this.diagnostics);
return Task.FromResult(this.diagnostics.Where(i => i.Location.GetLineSpan().Path == document.Name));
}

public override Task<IEnumerable<Diagnostic>> GetProjectDiagnosticsAsync(Project project, CancellationToken cancellationToken)
{
return Task.FromResult<IEnumerable<Diagnostic>>(this.diagnostics);
return Task.FromResult(this.diagnostics.Where(i => !i.Location.IsInSource));
}

internal static TestDiagnosticProvider Create(ImmutableArray<Diagnostic> diagnostics)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,11 @@ public async Task TestCodeFixAsync(int codepage)
var document = project.Documents.First();

// Create a diagnostic for the document to fix
var properties = ImmutableDictionary<string, string>.Empty.SetItem(SA1412StoreFilesAsUtf8.EncodingProperty, this.fileEncoding.WebName);
var diagnostic = Diagnostic.Create(
this.GetCSharpDiagnosticAnalyzers().First().SupportedDiagnostics.First(),
Location.Create(await document.GetSyntaxTreeAsync().ConfigureAwait(false), TextSpan.FromBounds(0, 0)));
Location.Create(await document.GetSyntaxTreeAsync().ConfigureAwait(false), TextSpan.FromBounds(0, 0)),
properties);

await codeFixer.RegisterCodeFixesAsync(new CodeFixContext(document, diagnostic, (ca, d) =>
{
Expand Down Expand Up @@ -161,9 +163,11 @@ private async Task TestFixAllAsync(int codepage, FixAllScope scope)
foreach (var document in project.Documents)
{
// Create a diagnostic for the document to fix
var properties = ImmutableDictionary<string, string>.Empty.SetItem(SA1412StoreFilesAsUtf8.EncodingProperty, (await document.GetTextAsync().ConfigureAwait(false)).Encoding.WebName);
var diagnostic = Diagnostic.Create(
descriptor,
Location.Create(await document.GetSyntaxTreeAsync().ConfigureAwait(false), TextSpan.FromBounds(0, 0)));
Location.Create(await document.GetSyntaxTreeAsync().ConfigureAwait(false), TextSpan.FromBounds(0, 0)),
properties);
diagnostics.Add(diagnostic);
}

Expand Down Expand Up @@ -225,9 +229,11 @@ private async Task TestFixAllWithMultipleEncodingsAsync(FixAllScope scope)
foreach (var document in project.Documents)
{
// Create a diagnostic for the document to fix
var properties = ImmutableDictionary<string, string>.Empty.SetItem(SA1412StoreFilesAsUtf8.EncodingProperty, (await document.GetTextAsync().ConfigureAwait(false)).Encoding.WebName);
var diagnostic = Diagnostic.Create(
descriptor,
Location.Create(await document.GetSyntaxTreeAsync().ConfigureAwait(false), TextSpan.FromBounds(0, 0)));
Location.Create(await document.GetSyntaxTreeAsync().ConfigureAwait(false), TextSpan.FromBounds(0, 0)),
properties);
diagnostics.Add(diagnostic);
}

Expand All @@ -246,7 +252,7 @@ private async Task TestFixAllWithMultipleEncodingsAsync(FixAllScope scope)
operation.Apply(workspace, CancellationToken.None);

// project should now have the "fixed document" in it.
// Because of limitations in roslyn the fixed document should
// Because of limitations in Roslyn the fixed document should
// have a different DocumentId then the broken document
project = workspace.CurrentSolution.Projects.First();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
using System.Collections.Immutable;
using System.Composition;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Helpers;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
Expand Down Expand Up @@ -32,7 +34,7 @@ public override FixAllProvider GetFixAllProvider()
}

/// <inheritdoc/>
public override async Task RegisterCodeFixesAsync(CodeFixContext context)
public override Task RegisterCodeFixesAsync(CodeFixContext context)
{
foreach (var diagnostic in context.Diagnostics)
{
Expand All @@ -41,30 +43,22 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
continue;
}

string usedEncoding = await GetEncodingNameForDocumentAsync(context.Document).ConfigureAwait(false);
string usedEncoding = diagnostic.Properties[SA1412StoreFilesAsUtf8.EncodingProperty];

context.RegisterCodeFix(
CodeAction.Create(
string.Format(MaintainabilityResources.SA1412CodeFix, usedEncoding),
token => GetTransformedSolutionAsync(context.Document),
equivalenceKey: await GetEquivalenceKeyForDocumentAsync(context.Document).ConfigureAwait(false)), diagnostic);
cancellationToken => GetTransformedSolutionAsync(context.Document, cancellationToken),
equivalenceKey: nameof(SA1412CodeFixProvider) + "." + usedEncoding),
diagnostic);
}
}

internal static async Task<string> GetEncodingNameForDocumentAsync(Document document)
{
return (await document.GetTextAsync().ConfigureAwait(false)).Encoding?.WebName ?? "<null>";
}

internal static async Task<string> GetEquivalenceKeyForDocumentAsync(Document document)
{
string usedEncoding = await GetEncodingNameForDocumentAsync(document).ConfigureAwait(false);
return nameof(SA1412CodeFixProvider) + "." + usedEncoding;
return SpecializedTasks.CompletedTask;
}

internal static async Task<Solution> GetTransformedSolutionAsync(Document document)
internal static async Task<Solution> GetTransformedSolutionAsync(Document document, CancellationToken cancellationToken)
{
SourceText text = await document.GetTextAsync().ConfigureAwait(false);
SourceText text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

string actualSourceText = text.ToString();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,27 @@ public override async Task<CodeAction> GetFixAsync(FixAllContext fixAllContext)
return null;
}

return CodeAction.Create(string.Format(MaintainabilityResources.SA1412CodeFix, await SA1412CodeFixProvider.GetEncodingNameForDocumentAsync(fixAllContext.Document).ConfigureAwait(false)), token => Task.FromResult(newSolution));
return CodeAction.Create(
string.Format(MaintainabilityResources.SA1412CodeFix, fixAllContext.CodeActionEquivalenceKey.Substring(fixAllContext.CodeActionEquivalenceKey.IndexOf('.') + 1)),
token => Task.FromResult(newSolution));
}

private static async Task<Solution> FixDocumentAsync(FixAllContext fixAllContext, Document document)
{
Solution solution = document.Project.Solution;
var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false);
if (diagnostics.Length == 0)
{
return solution;
}

if (diagnostics.Length == 0 || fixAllContext.CodeActionEquivalenceKey != await SA1412CodeFixProvider.GetEquivalenceKeyForDocumentAsync(document).ConfigureAwait(false))
string equivalenceKey = nameof(SA1412CodeFixProvider) + "." + diagnostics[0].Properties[SA1412StoreFilesAsUtf8.EncodingProperty];
if (fixAllContext.CodeActionEquivalenceKey != equivalenceKey)
{
return solution;
}

return await SA1412CodeFixProvider.GetTransformedSolutionAsync(document).ConfigureAwait(false);
return await SA1412CodeFixProvider.GetTransformedSolutionAsync(document, fixAllContext.CancellationToken).ConfigureAwait(false);
}

private static async Task<Solution> GetProjectFixesAsync(FixAllContext fixAllContext, Project project)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ public class SA1412StoreFilesAsUtf8 : DiagnosticAnalyzer

private static byte[] utf8Preamble = Encoding.UTF8.GetPreamble();

/// <summary>
/// Gets the key for the detected encoding name in the <see cref="Diagnostic.Properties"/> collection.
/// </summary>
/// <value>
/// The key for the detected encoding name in the <see cref="Diagnostic.Properties"/> collection.
/// </value>
public static string EncodingProperty { get; } = "Encoding";

/// <inheritdoc/>
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
{
Expand All @@ -58,7 +66,8 @@ private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context)

if (!IsUtf8Preamble(preamble))
{
context.ReportDiagnostic(Diagnostic.Create(Descriptor, Location.Create(context.Tree, TextSpan.FromBounds(0, 0))));
ImmutableDictionary<string, string> properties = ImmutableDictionary<string, string>.Empty.SetItem(EncodingProperty, context.Tree.Encoding?.WebName ?? "<null>");
context.ReportDiagnostic(Diagnostic.Create(Descriptor, Location.Create(context.Tree, TextSpan.FromBounds(0, 0)), properties));
}
}

Expand Down

0 comments on commit 84c5811

Please sign in to comment.