roslynator
roslynator copied to clipboard
RR0064 (and probably others) don't respect .editorconfig rules
My solution has a .editorconfig file in its root with the following rules defined:
[*.{cs,vb}]
dotnet_naming_rule.private_members_with_underscore.symbols = private_fields
dotnet_naming_rule.private_members_with_underscore.style = prefix_underscore
dotnet_naming_rule.private_members_with_underscore.severity = suggestion
dotnet_naming_symbols.private_fields.applicable_kinds = field
dotnet_naming_symbols.private_fields.applicable_accessibilities = private
dotnet_naming_style.prefix_underscore.capitalization = camel_case
dotnet_naming_style.prefix_underscore.required_prefix = _
Performing a refactoring on a constructor parameter in that solution yields the following:

Roslynator's "Introduce and initialize field" refactoring (RR0064) wants to generate a field name that doesn't begin with an underscore (i.e. the .editorconfig rules are ignored), while Visual Studio's built-in refactoring "Create and initialize field" produces the correct field name In my opinion, Roslynator should behave the same as Visual Studio in respecting the .editorconfig rules.
I'm aware of the Roslynator option "Prefix field identifier with underscore" but to my knowledge that applies to all fields, and it would be unnecessary if the editorconfig rules were used.
I agree that Roslynator should work in compliance with editorconfig rules.
Unfortunately there is no API to access these editorconfig rules (at least none I know of).
Looking at the Roslyn PR that added support for .editorconfig, it seems that:
-
Every analyzer gets passed a
Microsoft.CodeAnalysis.Diagnostics.SyntaxNodeAnalysisContextthat has anOptionsproperty of typeMicrosoft.CodeAnalysis.Diagnostics.AnalyzerOptions. -
Then
Microsoft.CodeAnalysis.Diagnostics.AnalyzerHelperhas an extension methodGetDocumentOptionSetAsyncthat takes in aMicrosoft.CodeAnalysis.Diagnostics.AnalyzerOptionsand returns aValueTask<Microsoft.CodeAnalysis.Options.OptionSet>. -
Microsoft.CodeAnalysis.Options.OptionSethas aGetOptionmethod that allows you to ask for the value of a specific code style option. There is a predefined list of these options in various classes:Microsoft.CodeAnalysis.CodeStyle.CodeStyleOptionsMicrosoft.CodeAnalysis.CSharp.CodeStyle.CSharpCodeStyleOptionsMicrosoft.CodeAnalysis.CSharp.Formatting.CSharpFormattingOptionsMicrosoft.CodeAnalysis.Formatting.FormattingOptionsMicrosoft.CodeAnalysis.Simplification.SimplificationOptions
including ones that cover both the IDE and/or .editorconfig settings.
tl;dr: given a SyntaxNodeAnalysisContext instance context, and with the correct references and imports, you can write:
var optionSet = context.Options.GetDocumentOptionSetAsync(context.Node.SyntaxTree, context.CancellationToken).GetAwaiter().GetResult();
var option = optionSet.GetOption(CodeStyleOptions.<relevant-option-name>, <language>);
// do something with option.Value
The relevant one that covers this particular case (RR0064) seems to be SimplificationOptions.NamingPreferences, but unfortunately that's declared as internal, as is the Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyle.NamingStylePreferences option it returns. So maybe the naming stuff isn't ready for primetime, but you could implement the ones that are, in some of your other refactorers.
Regarding Editor config, if you could take a look at my comment on https://github.com/JosefPihrt/Roslynator/issues/427#issuecomment-445779308
@wiz0u I reopened it.
It's possible to set rule severity in .editorconfig now, but still not to configure them. Is this planned?
@marcospgp It possible to configure rules using editorconfig. Here is a list of currently supported values:
roslynator.max_line_length = <MAX_LINE_LENGTH>
roslynator.RCS0011.invert = true
roslynator.RCS0015.invert = true
roslynator.RCS0027.invert = true
roslynator.RCS0028.invert = true
roslynator.RCS0032.invert = true
roslynator.RCS0051.invert = true
roslynator.RCS0052.invert = true
roslynator.RCS1014.invert = true
roslynator.RCS1014.use_implicit_type_when_obvious = true
roslynator.RCS1016.invert = true
roslynator.RCS1016.use_block_body_when_declaration_is_multiline = true
roslynator.RCS1016.use_block_body_when_expression_is_multiline = true
roslynator.RCS1018.invert = true
roslynator.RCS1036.remove_empty_line_between_closing_brace_and_switch_section = true
roslynator.RCS1045.suppress_when_field_is_static = true
roslynator.RCS1050.invert = true
roslynator.RCS1051.do_not_parenthesize_single_token = true
roslynator.RCS1078.invert = true
roslynator.RCS1090.invert = true
roslynator.RCS1096.invert = true
roslynator.RCS1104.suppress_when_condition_is_inverted = true
roslynator.RCS1207.invert = true
roslynator.RCS1213.suppress_unity_script_methods = true
roslynator.RCS1246.suppress_when_expression_is_invocation = true
roslynator.RCS1248.invert = true
Awesome, was just checking back in to say that roslynator.max_line_length=80 worked. Thanks! Would be awesome if you could add this to the documentation here.
@marcospgp 9f460dd9fd24c777e8cb7d545c48b81079305283