Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code style to convert byte arrays to UTF8 strings #60647

Merged
merged 47 commits into from
May 3, 2022
Merged
Changes from 1 commit
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
e997bd4
Initial analyzer to report diagnostics for byte arrays that can be co…
davidwengier Apr 7, 2022
7a7e785
Add a code fix provider that doesn't work
davidwengier Apr 7, 2022
8ba815c
Move more to the analyzer since it has the constant values already an…
davidwengier Apr 8, 2022
a648a47
More tests
davidwengier Apr 8, 2022
dee8140
Ensure we only offer when we can generate a valid string
davidwengier Apr 8, 2022
0891597
Fix order
davidwengier Apr 9, 2022
ed33897
FIx correctness
davidwengier Apr 9, 2022
3748700
Fix attributes
davidwengier Apr 9, 2022
527c33f
Fix declarations
davidwengier Apr 9, 2022
693f225
Apply trivia directly to the token
davidwengier Apr 9, 2022
b40d389
Simplify array type check
davidwengier Apr 9, 2022
9a04491
Cleanup
davidwengier Apr 9, 2022
9ec2f4d
Fix diagnostic id tests
davidwengier Apr 9, 2022
2885ee3
Move
davidwengier Apr 9, 2022
35c7ceb
Report diagnostic at first token
davidwengier Apr 9, 2022
f02a6b9
Add some more specific tests for real byte arrays found around the place
davidwengier Apr 9, 2022
9193027
Add test for collection initializer edge case
davidwengier Apr 9, 2022
55053d7
Add test for using statement edge case
davidwengier Apr 9, 2022
c8932ed
Support implicit arrays in parameter arrays
davidwengier Apr 9, 2022
80b20ad
Correctness
davidwengier Apr 9, 2022
7dbacfe
Fix code cleanup
davidwengier Apr 10, 2022
c12468f
Fix argument list rewriting
davidwengier Apr 10, 2022
ea42b95
More parameter array cases
davidwengier Apr 10, 2022
d145d63
Merge remote-tracking branch 'upstream/main' into UseUTF8Strings
davidwengier Apr 10, 2022
ad88b8e
Fix API break
davidwengier Apr 10, 2022
017037a
Fix
davidwengier Apr 10, 2022
b8a66a7
Move UTF8 string creation to the code fix, and just validate in the a…
davidwengier Apr 11, 2022
1dc375b
Share code for escaping characters
davidwengier Apr 11, 2022
9a78ad2
Fix language version check
davidwengier Apr 11, 2022
28daf9d
PR Feedback
davidwengier Apr 11, 2022
69afe46
Fix editorconfig tests
davidwengier Apr 12, 2022
0cddacd
Show option in VS and editor config UI
davidwengier Apr 12, 2022
0648b7a
Fixes
davidwengier Apr 12, 2022
2e8d442
Rename - plural sounds better
davidwengier Apr 12, 2022
437e576
Update UseUTF8StringLiteralDiagnosticAnalyzer.cs
davidwengier Apr 12, 2022
374be8f
GitHub editor swallowed my whitespace
davidwengier Apr 12, 2022
96d9b7b
Typo
davidwengier Apr 12, 2022
fa6112e
UTF8 -> UTF-8 is string resources
davidwengier Apr 26, 2022
4d10c90
Remove intermediate array(s)
davidwengier Apr 26, 2022
2919e48
Validate syntax directly, and use properties to tell the code fix wha…
davidwengier Apr 26, 2022
f2f952b
Multidimensional arrays
davidwengier Apr 26, 2022
f6dc999
Fix xlf files
davidwengier Apr 26, 2022
90bff0f
Update string for consistency
davidwengier Apr 27, 2022
7f76fff
Update tests
davidwengier Apr 27, 2022
b498cf2
Reduce allocations
davidwengier Apr 27, 2022
24ddd14
PR feedback
davidwengier May 3, 2022
c5844b4
Merge remote-tracking branch 'upstream/main' into UseUTF8Strings
davidwengier May 3, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Initial analyzer to report diagnostics for byte arrays that can be co…
…nverted
davidwengier committed Apr 8, 2022
commit e997bd4e73407045ef809f8172918a36a2ec538a
1 change: 1 addition & 0 deletions src/Analyzers/CSharp/Analyzers/CSharpAnalyzers.projitems
Original file line number Diff line number Diff line change
@@ -124,6 +124,7 @@
<Compile Include="$(MSBuildThisFileDirectory)UsePatternMatching\CSharpUseNotPatternDiagnosticAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)UseSimpleUsingStatement\UseSimpleUsingStatementDiagnosticAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)UseThrowExpression\CSharpUseThrowExpressionDiagnosticAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)UseUTF8StringLiteral\UseUTF8StringLiteralDiagnosticAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ValidateFormatString\CSharpValidateFormatStringDiagnosticAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)NewLines\EmbeddedStatementPlacement\EmbeddedStatementPlacementDiagnosticAnalyzer.cs" />
</ItemGroup>
Original file line number Diff line number Diff line change
@@ -365,4 +365,10 @@
<data name="Convert_to_top_level_statements" xml:space="preserve">
<value>Convert to top-level statements</value>
</data>
<data name="Convert_to_UTF8_string_literal" xml:space="preserve">
<value>Convert to UTF8 string literal</value>
davidwengier marked this conversation as resolved.
Show resolved Hide resolved
</data>
<data name="Use_UTF8_string_literal" xml:space="preserve">
<value>Use UTF8 string literal</value>
davidwengier marked this conversation as resolved.
Show resolved Hide resolved
</data>
</root>
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Linq;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.CSharp.UseUTF8StringLiteral
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
internal sealed partial class UseUTF8StringLiteralDiagnosticAnalyzer : AbstractBuiltInCodeStyleDiagnosticAnalyzer
davidwengier marked this conversation as resolved.
Show resolved Hide resolved
{
public UseUTF8StringLiteralDiagnosticAnalyzer()
: base(IDEDiagnosticIds.UseUTF8StringLiteralDiagnosticId,
EnforceOnBuildValues.UseUTF8StringLiteral,
CSharpCodeStyleOptions.PreferUTF8StringLiteral,
LanguageNames.CSharp,
new LocalizableResourceString(nameof(CSharpAnalyzersResources.Convert_to_UTF8_string_literal), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)),
new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_UTF8_string_literal), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)))
{
}
davidwengier marked this conversation as resolved.
Show resolved Hide resolved

protected override void InitializeWorker(AnalysisContext context)
=> context.RegisterCompilationStartAction(context =>
{
if (context.Compilation.LanguageVersion() < LanguageVersion.Preview)
davidwengier marked this conversation as resolved.
Show resolved Hide resolved
return;

var expressionType = context.Compilation.GetTypeByMetadataName(typeof(System.Linq.Expressions.Expression<>).FullName!);

context.RegisterOperationAction(c => AnalyzeOperation(c, expressionType), OperationKind.ArrayCreation);
});

private void AnalyzeOperation(OperationAnalysisContext context, INamedTypeSymbol? expressionType)
{
var arrayCreationExpression = (IArrayCreationOperation)context.Operation;
davidwengier marked this conversation as resolved.
Show resolved Hide resolved

// Don't offer if the user doesn't want it
var option = context.GetOption(CSharpCodeStyleOptions.PreferUTF8StringLiteral);
if (!option.Value)
return;

// Only replace arrays with initializers
if (arrayCreationExpression.Initializer is null)
return;

var byteType = context.Compilation.GetSpecialType(SpecialType.System_Byte);
var elementType = (arrayCreationExpression.Type as IArrayTypeSymbol)?.ElementType;
if (!SymbolEqualityComparer.Default.Equals(elementType, byteType))
davidwengier marked this conversation as resolved.
Show resolved Hide resolved
return;

// UTF8 strings are not valid to use in attributes
davidwengier marked this conversation as resolved.
Show resolved Hide resolved
if (arrayCreationExpression.Syntax.Ancestors().OfType<AttributeSyntax>().Any())
return;

// All elements have to be literals
if (arrayCreationExpression.Initializer.ElementValues.Any(v => v.WalkDownConversion() is not ILiteralOperation))
return;

// Can't use a UTF8 string inside an expression tree.
var semanticModel = context.Operation.SemanticModel;
Contract.ThrowIfNull(semanticModel);
if (arrayCreationExpression.Syntax.IsInExpressionTree(semanticModel, expressionType, context.CancellationToken))
return;

context.ReportDiagnostic(
DiagnosticHelper.Create(Descriptor, arrayCreationExpression.Syntax.GetLocation(), option.Notification.Severity, additionalLocations: null, properties: null));
}

public override DiagnosticAnalyzerCategory GetAnalyzerCategory()
=> DiagnosticAnalyzerCategory.SemanticSpanAnalysis;
davidwengier marked this conversation as resolved.
Show resolved Hide resolved
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading