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

Simplifier options #60174

Merged
merged 14 commits into from
Apr 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions eng/config/BannedSymbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,7 @@ M:Microsoft.CodeAnalysis.Formatting.Formatter.Format(Microsoft.CodeAnalysis.Synt
M:Microsoft.CodeAnalysis.Formatting.Formatter.GetFormattedTextChanges(Microsoft.CodeAnalysis.SyntaxNode,Microsoft.CodeAnalysis.Workspace,Microsoft.CodeAnalysis.Options.OptionSet,System.Threading.CancellationToken); Use overload with SyntaxFormattingOptions instead
M:Microsoft.CodeAnalysis.Formatting.Formatter.GetFormattedTextChanges(Microsoft.CodeAnalysis.SyntaxNode,Microsoft.CodeAnalysis.Text.TextSpan,Microsoft.CodeAnalysis.Workspace,Microsoft.CodeAnalysis.Options.OptionSet,System.Threading.CancellationToken); Use overload with SyntaxFormattingOptions instead
M:Microsoft.CodeAnalysis.Formatting.Formatter.GetFormattedTextChanges(Microsoft.CodeAnalysis.SyntaxNode,System.Collections.Generic.IEnumerable{Microsoft.CodeAnalysis.Text.TextSpan},Microsoft.CodeAnalysis.Workspace,Microsoft.CodeAnalysis.Options.OptionSet,System.Threading.CancellationToken); Use overload with SyntaxFormattingOptions instead
M:Microsoft.CodeAnalysis.Simplification.Simplifier.ReduceAsync(Microsoft.CodeAnalysis.Document,Microsoft.CodeAnalysis.Options.OptionSet,System.Threading.CancellationToken); Use overload that takes SimplifierOptions
M:Microsoft.CodeAnalysis.Simplification.Simplifier.ReduceAsync(Microsoft.CodeAnalysis.Document,Microsoft.CodeAnalysis.SyntaxAnnotation,Microsoft.CodeAnalysis.Options.OptionSet,System.Threading.CancellationToken); Use overload that takes SimplifierOptions
M:Microsoft.CodeAnalysis.Simplification.Simplifier.ReduceAsync(Microsoft.CodeAnalysis.Document,Microsoft.CodeAnalysis.Text.TextSpan,Microsoft.CodeAnalysis.Options.OptionSet,System.Threading.CancellationToken); Use overload that takes SimplifierOptions
M:Microsoft.CodeAnalysis.Simplification.Simplifier.ReduceAsync(Microsoft.CodeAnalysis.Document,System.Collections.Generic.IEnumerable{Microsoft.CodeAnalysis.Text.TextSpan},Microsoft.CodeAnalysis.Options.OptionSet,System.Threading.CancellationToken); Use overload that takes SimplifierOptions
1 change: 1 addition & 0 deletions src/Analyzers/CSharp/Analyzers/CSharpAnalyzers.projitems
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
<Compile Include="$(MSBuildThisFileDirectory)PopulateSwitch\CSharpPopulateSwitchStatementDiagnosticAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)RemoveUnreachableCode\CSharpRemoveUnreachableCodeDiagnosticAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)RemoveUnreachableCode\RemoveUnreachableCodeHelpers.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Simplification\CSharpSimplifierOptionsFactory.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SimplifyBooleanExpression\CSharpSimplifyConditionalDiagnosticAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SimplifyInterpolation\CSharpSimplifyInterpolationHelpers.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SimplifyInterpolation\CSharpSimplifyInterpolationDiagnosticAnalyzer.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Simplification;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.QualifyMemberAccess;
Expand All @@ -13,11 +14,14 @@ namespace Microsoft.CodeAnalysis.CSharp.QualifyMemberAccess
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
internal sealed class CSharpQualifyMemberAccessDiagnosticAnalyzer
: AbstractQualifyMemberAccessDiagnosticAnalyzer<SyntaxKind, ExpressionSyntax, SimpleNameSyntax>
: AbstractQualifyMemberAccessDiagnosticAnalyzer<SyntaxKind, ExpressionSyntax, SimpleNameSyntax, CSharpSimplifierOptions>
{
protected override string GetLanguageName()
=> LanguageNames.CSharp;

protected override CSharpSimplifierOptions GetSimplifierOptions(AnalyzerOptions options, SyntaxTree syntaxTree)
=> options.GetCSharpSimplifierOptions(syntaxTree);

protected override bool IsAlreadyQualifiedMemberAccess(ExpressionSyntax node)
=> node.IsKind(SyntaxKind.ThisExpression);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// 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 Microsoft.CodeAnalysis.Diagnostics;

namespace Microsoft.CodeAnalysis.CSharp.Simplification;

internal static class CSharpSimplifierOptionsFactory
{
internal static CSharpSimplifierOptions GetCSharpSimplifierOptions(this AnalyzerOptions options, SyntaxTree syntaxTree)
{
var configOptions = options.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree);
var ideOptions = options.GetIdeOptions();

return CSharpSimplifierOptions.Create(configOptions, (CSharpSimplifierOptions?)ideOptions.SimplifierOptions);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Simplification;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Utilities;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.CodeAnalysis.Simplification;

namespace Microsoft.CodeAnalysis.CSharp.UseImplicitObjectCreation
{
Expand Down Expand Up @@ -44,7 +46,6 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context)
if (syntaxTree.Options.LanguageVersion() < LanguageVersion.CSharp9)
return;

var optionSet = options.GetAnalyzerOptionSet(syntaxTree, cancellationToken);
var styleOption = options.GetOption(CSharpCodeStyleOptions.ImplicitObjectCreationWhenTypeIsApparent, syntaxTree, cancellationToken);
if (!styleOption.Value)
{
Expand Down Expand Up @@ -73,11 +74,15 @@ objectCreation.Parent.Parent.Parent is VariableDeclarationSyntax variableDeclara
typeNode = variableDeclaration.Type;

var helper = CSharpUseImplicitTypeHelper.Instance;
if (helper.ShouldAnalyzeVariableDeclaration(variableDeclaration, cancellationToken) &&
helper.AnalyzeTypeName(typeNode, semanticModel, optionSet, cancellationToken).IsStylePreferred)
if (helper.ShouldAnalyzeVariableDeclaration(variableDeclaration, cancellationToken))
{
// this is a case where the user would prefer 'var'. don't offer to use an implicit object here.
return;
var simplifierOptions = context.Options.GetCSharpSimplifierOptions(syntaxTree);

if (helper.AnalyzeTypeName(typeNode, semanticModel, simplifierOptions, cancellationToken).IsStylePreferred)
{
// this is a case where the user would prefer 'var'. don't offer to use an implicit object here.
return;
}
}
}
else if (objectCreation.Parent.IsKind(SyntaxKind.ArrowExpressionClause))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Simplification;
using Microsoft.CodeAnalysis.CSharp.Utilities;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Options;
Expand Down Expand Up @@ -52,10 +53,8 @@ protected override void InitializeWorker(AnalysisContext context)
private void HandleVariableDeclaration(SyntaxNodeAnalysisContext context)
{
var declarationStatement = context.Node;
var options = context.Options;
var syntaxTree = context.Node.SyntaxTree;
var cancellationToken = context.CancellationToken;
var optionSet = options.GetAnalyzerOptionSet(syntaxTree, cancellationToken);

var semanticModel = context.SemanticModel;
var declaredType = Helper.FindAnalyzableType(declarationStatement, semanticModel, cancellationToken);
Expand All @@ -64,8 +63,10 @@ private void HandleVariableDeclaration(SyntaxNodeAnalysisContext context)
return;
}

var simplifierOptions = context.Options.GetCSharpSimplifierOptions(syntaxTree);

var typeStyle = Helper.AnalyzeTypeName(
declaredType, semanticModel, optionSet, cancellationToken);
declaredType, semanticModel, simplifierOptions, cancellationToken);
if (!typeStyle.IsStylePreferred || !typeStyle.CanConvert())
{
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Simplification;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Formatting;
Expand Down Expand Up @@ -65,14 +66,17 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)

#if CODE_STYLE
var options = document.Project.AnalyzerOptions.GetAnalyzerOptionSet(syntaxRoot.SyntaxTree, cancellationToken);
var simplifierOptions = CSharpSimplifierOptions.Create(options, fallbackOptions: null);
#else
var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
var simplifierOptions = await SimplifierOptions.FromDocumentAsync(document, fallbackOptions: context.Options(document.Project.LanguageServices).SimplifierOptions, cancellationToken).ConfigureAwait(false);
#endif
var codeStyleOption = options.GetOption(CSharpCodeStyleOptions.PreferredUsingDirectivePlacement);

// Read the preferred placement option and verify if it can be applied to this code file.
// There are cases where we will not be able to fix the diagnostic and the user will need to resolve
// it manually.
var (placement, preferPreservation) = DeterminePlacement(compilationUnit, options);
var (placement, preferPreservation) = DeterminePlacement(compilationUnit, codeStyleOption);
if (preferPreservation)
return;

Expand All @@ -81,24 +85,22 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
context.RegisterCodeFix(
CodeAction.Create(
CSharpAnalyzersResources.Move_misplaced_using_directives,
token => GetTransformedDocumentAsync(document, compilationUnit, GetAllUsingDirectives(compilationUnit), placement, token),
token => GetTransformedDocumentAsync(document, compilationUnit, GetAllUsingDirectives(compilationUnit), placement, simplifierOptions, token),
nameof(CSharpAnalyzersResources.Move_misplaced_using_directives)),
diagnostic);
}
}

internal static async Task<Document> TransformDocumentIfRequiredAsync(Document document, CancellationToken cancellationToken)
internal static async Task<Document> TransformDocumentIfRequiredAsync(
Document document,
SimplifierOptions simplifierOptions,
CodeStyleOption2<AddImportPlacement> importPlacementStyleOption,
CancellationToken cancellationToken)
{
var syntaxRoot = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var compilationUnit = (CompilationUnitSyntax)syntaxRoot;

#if CODE_STYLE
var options = document.Project.AnalyzerOptions.GetAnalyzerOptionSet(syntaxRoot.SyntaxTree, cancellationToken);
#else
var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
#endif

var (placement, preferPreservation) = DeterminePlacement(compilationUnit, options);
var (placement, preferPreservation) = DeterminePlacement(compilationUnit, importPlacementStyleOption);
if (preferPreservation)
{
return document;
Expand All @@ -112,7 +114,7 @@ internal static async Task<Document> TransformDocumentIfRequiredAsync(Document d
return document;
}

return await GetTransformedDocumentAsync(document, compilationUnit, allUsingDirectives, placement, cancellationToken).ConfigureAwait(false);
return await GetTransformedDocumentAsync(document, compilationUnit, allUsingDirectives, placement, simplifierOptions, cancellationToken).ConfigureAwait(false);
}

private static ImmutableList<UsingDirectiveSyntax> GetAllUsingDirectives(CompilationUnitSyntax compilationUnit)
Expand All @@ -127,6 +129,7 @@ private static async Task<Document> GetTransformedDocumentAsync(
CompilationUnitSyntax compilationUnit,
IEnumerable<UsingDirectiveSyntax> allUsingDirectives,
AddImportPlacement placement,
SimplifierOptions simplifierOptions,
CancellationToken cancellationToken)
{
var bannerService = document.GetRequiredLanguageService<IFileBannerFactsService>();
Expand All @@ -149,8 +152,13 @@ private static async Task<Document> GetTransformedDocumentAsync(
var newDocument = document.WithSyntaxRoot(newCompilationUnitWithHeader);

// Simplify usings now that they have been moved and are in the proper context.
var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
return await Simplifier.ReduceAsync(newDocument, Simplifier.Annotation, options, cancellationToken).ConfigureAwait(false);
#if CODE_STYLE
#pragma warning disable RS0030 // Do not used banned APIs
return await Simplifier.ReduceAsync(newDocument, Simplifier.Annotation, optionSet: null, cancellationToken).ConfigureAwait(false);
#pragma warning restore
#else
return await Simplifier.ReduceAsync(newDocument, Simplifier.Annotation, simplifierOptions, cancellationToken).ConfigureAwait(false);
#endif
}

private static async Task<CompilationUnitSyntax> ExpandUsingDirectivesAsync(Document document, CompilationUnitSyntax containerNode, IEnumerable<UsingDirectiveSyntax> allUsingDirectives, CancellationToken cancellationToken)
Expand Down Expand Up @@ -360,12 +368,10 @@ private static TSyntaxNode EnsureLeadingBlankLineBeforeFirstMember<TSyntaxNode>(
return node.ReplaceNode(firstMember, newFirstMember);
}

private static (AddImportPlacement placement, bool preferPreservation) DeterminePlacement(CompilationUnitSyntax compilationUnit, OptionSet options)
private static (AddImportPlacement placement, bool preferPreservation) DeterminePlacement(CompilationUnitSyntax compilationUnit, CodeStyleOption2<AddImportPlacement> styleOption)
{
var codeStyleOption = options.GetOption(CSharpCodeStyleOptions.PreferredUsingDirectivePlacement);

var placement = codeStyleOption.Value;
var preferPreservation = codeStyleOption.Notification == NotificationOption2.None;
var placement = styleOption.Value;
var preferPreservation = styleOption.Notification == NotificationOption2.None;

if (preferPreservation || placement == AddImportPlacement.OutsideNamespace)
return (placement, preferPreservation);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,8 @@

using System.Runtime.Serialization;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Options;
using Roslyn.Utilities;
using Microsoft.CodeAnalysis.Simplification;

#if CODE_STYLE
using TOption = Microsoft.CodeAnalysis.Options.IOption2;
Expand All @@ -27,7 +23,8 @@ internal readonly record struct IdeAnalyzerOptions(
[property: DataMember(Order = 3)] bool ReportInvalidPlaceholdersInStringDotFormatCalls = true,
[property: DataMember(Order = 4)] bool ReportInvalidRegexPatterns = true,
[property: DataMember(Order = 5)] bool ReportInvalidJsonPatterns = true,
[property: DataMember(Order = 6)] bool DetectAndOfferEditorFeaturesForProbableJsonStrings = true)
[property: DataMember(Order = 6)] bool DetectAndOfferEditorFeaturesForProbableJsonStrings = true,
[property: DataMember(Order = 7)] SimplifierOptions? SimplifierOptions = null)
{
public IdeAnalyzerOptions()
: this(CrashOnAnalyzerException: false)
Expand Down
Loading