- Notifications
You must be signed in to change notification settings - Fork4.1k
feat(formatter): Add configurable parameter wrapping for conditionals and method call chains#79377
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
base:main
Are you sure you want to change the base?
Conversation
- Add csharp_wrap_conditional_expressions EditorConfig option- Add csharp_indent_wrapped_conditional_expressions EditorConfig option- Update WrappingFormattingRule to handle binary expressions in conditionals- Update IndentBlockFormattingRule for conditional expression indentation- Update TokenBasedFormattingRule for new line operations at logical operatorsSupports wrapping at && and || operators in if, while, for, do-while statements and ternary operators.
…ctionality- Add tests for WrapConditionalExpressions option (enabled/disabled)- Add tests for IndentWrappedConditionalExpressions option- Cover if/while/for/do-while statements and ternary operators- Include nested conditions and complex parentheses scenarios- Test EditorConfig integration for both options- Add real-world code examples and edge cases
- Add WrapMethodCallChains and IndentWrappedMethodCallChains EditorConfig options- Update CSharpSyntaxFormattingOptions to include method call chain options- Implement method call chain wrapping logic in WrappingFormattingRule- Add method call chain newline operations in TokenBasedFormattingRule- Implement method call chain indentation in IndentBlockFormattingRule- Support two indentation modes: - Simple identifiers (e.g., 'data') indent by one level - Complex expressions (e.g., 'log.Entries') align to dot position- Enable configurable wrapping and alignment of method call chains like: obj.Method1().Method2().Method3() -> obj.Method1() .Method2() .Method3()Implements scenario 2 for configurable parameter wrapping feature.
- Add 30 comprehensive test cases covering various scenarios: - Basic method call chain wrapping and indentation - Complex chains with lambdas and nested calls - Chains with generic methods, static methods, and async methods - Chains with property access, indexers, and null conditional operators - Chains with LINQ queries, casting, and complex expressions - Simple identifiers vs complex expressions indentation behavior - EditorConfig integration tests - Edge cases with comments, assignments, and conditional operatorsTests verify both WrapMethodCallChains and IndentWrappedMethodCallChainsoptions work correctly in all scenarios.
I would not call tehes "conditional expressoins" , unless the goal is toonly do this for |
We don't call this "method call chains" in the existing wrapping feature, but instead call it "wrap call chains". See: roslyn/src/Features/Core/Portable/Wrapping/ChainedExpression/ChainedExpressionCodeActionComputer.cs Line 110 in3e2cadf
We should keep naming consistent. |
Looking at the impl, i'm concerned that this doesn't share code with the existing binary-expr or call-chain wrapping code. Which means you could potentially use these two features independently and get results that disagree with each otehr. like using hte wrapping code aciton, but then having teh formatter complain. we should unify these so they both use the same logic at the end of the day. |
I'd recommend looking at the existing wrapping providers, and the customization there. for example, we have support for things like:
etc. |
Another aspect thsi should support is the concept of 'wrapping only when line is long'. |
…portImplements configurable parameter wrapping for C# method declarations and calls with three new EditorConfig options:- csharp_wrap_parameters: enables/disables parameter wrapping- csharp_align_wrapped_parameters: aligns wrapped parameters with opening parenthesis- csharp_wrap_parameters_on_new_line: places first parameter on new lineSupports four formatting styles:- Basic wrapping with standard indentation- Wrap & align with opening parenthesis alignment- Wrap & align with first parameter on new line- Wrap with first parameter on new line (no alignment)Includes comprehensive test coverage and follows established patterns from conditional expression and method call chain wrapping.
… implementationFixes compilation error by replacing IsDescendantOfOrSelfWith calls with IsNodeWithinCondition helper method that uses DescendantNodesAndSelf().Contains() to check if a node is within a condition statement.
Wow, I wasn't expecting comments that quickly 😅 Thank you@CyrusNajmabadi - I'll take your feedback on board as I incrementally flesh this out before flagging it as ready for review |
Sounds good :) |
Based on dotnet team feedback, removed custom conditional wrapping logicand instead leverage existing binary expression and operator placementinfrastructure. This provides better consistency with the existingcodebase and follows established patterns.Changes:- Removed WrapConditionalExpressions and IndentWrappedConditionalExpressions options- Removed custom conditional expression wrapping logic from TokenBasedFormattingRule- Removed custom conditional expression wrapping logic from WrappingFormattingRule- Removed custom conditional expression alignment from IndentBlockFormattingRule- Retained parameter wrapping functionality which was the main goal
Based on dotnet team feedback to maintain consistency with existing binary expression infrastructure:- Remove outdated ConditionalWrappingTests.cs file- Remove references to WrapConditionalExpressions and IndentWrappedConditionalExpressions from IndentBlockFormattingRule.cs- Update comment in TokenBasedFormattingRule.cs to clarify conditional access operator (?) vs conditional expressions- Now fully integrated with existing binary expression wrapping infrastructure
The temp-example.md file was accidentally included in the previous commit and should not be in the repository.
Uh oh!
There was an error while loading.Please reload this page.
Based on dotnet team feedback, renamed method call chain wrapping options to use call_chain terminology for consistency with existing infrastructure:- WrapMethodCallChains WrapCallChains- IndentWrappedMethodCallChains IndentWrappedCallChains- csharp_wrap_method_call_chains csharp_wrap_call_chains- csharp_indent_wrapped_method_call_chains csharp_indent_wrapped_call_chainsUpdated all method names, variable names, and test files to use consistent call_chain terminology that aligns with the existing Features/Core/Portable/Wrapping/ChainedExpression infrastructure.
@dotnet-policy-service agree |
Remove custom parameter wrapping functionality that duplicatedexisting infrastructure in Features/Core/Portable/Wrapping/SeparatedSyntaxList.- Remove custom parameter wrapping options from CSharpFormattingOptions2- Remove custom parameter wrapping logic from formatting rules- Remove custom parameter wrapping test fileThe existing CSharpParameterWrapper and CSharpArgumentWrapper alreadyprovide comprehensive parameter wrapping with EditorConfig support.
The test file was testing custom parameter wrapping options that were removedin favor of the existing infrastructure in Features/Core/Portable/Wrapping/SeparatedSyntaxList.This resolves build errors with undefined parameter wrapping options.
This commit removes unnecessary whitespace in the IndentBlockFormattingRule, TokenBasedFormattingRule, and WrappingFormattingRule files to improve code readability and maintain consistency across the codebase.
…ing rulesThis commit removes unnecessary whitespace in CSharpFormattingOptions2, IndentBlockFormattingRule, and WrappingFormattingRule files to enhance code readability and maintain consistency across the codebase.
…and WrappingFormattingRuleThis commit cleans up whitespace in the IndentBlockFormattingRule and WrappingFormattingRule files to enhance code readability and maintain consistency across the codebase.
…ouble indentationThe AddCaseSectionIndentBlockOperation method was causing double indentationfor switch case blocks because AddSwitchIndentationOperation already handlesall switch section indentation. Removing the redundant operation fixes theformatting test failures where case blocks were over-indented by 4 spaces.
- Add three new EditorConfig options: * csharp_parameter_wrapping (do_not_wrap | wrap_long_parameters | wrap_every_parameter) * csharp_parameter_first_placement (same_line | new_line) * csharp_parameter_alignment (align_with_first | indent)- Define ParameterWrappingOptionsInternal, ParameterFirstPlacementOptionsInternal, and ParameterAlignmentOptionsInternal enums- Add EditorConfig parsing and serialization for the new options- Update CSharpSyntaxFormattingOptions to include parameter wrapping properties- Add options to CSharpFormattingOptions2 with proper EditorConfig integrationThis exposes the existing manual parameter wrapping functionality throughEditorConfig for automatic formatting, allowing teams to configure parameterwrapping behavior consistently across their codebase.
- Add TestAddParameterWrappingOptionAsync for csharp_parameter_wrapping- Add TestAddParameterFirstPlacementOptionAsync for csharp_parameter_first_placement- Add TestAddParameterAlignmentOptionAsync for csharp_parameter_alignment- Add TestUpdateParameterWrappingOptionAsync for updating existing options- Add TestAddMultipleParameterWrappingOptionsAsync for multiple options togetherThese tests verify that the new parameter wrapping EditorConfig options can be properly serialized, parsed, and updated through the SettingsUpdateHelper infrastructure.
- Add csharp_binary_expression_wrapping option (do_not_wrap | wrap_long_expressions | wrap_every_operator)- Add BinaryExpressionWrappingOptionsInternal enum for internal representation- Add parsing and serialization functions for EditorConfig integration- Update CSharpSyntaxFormattingOptions to include binary expression wrapping- Add comprehensive EditorConfig tests for binary expression wrapping optionsThis exposes the existing manual binary expression wrapping capabilities as automatic formatting behaviors that can be configured through .editorconfig files, matching the same pattern as parameter wrapping options.
- Add new formatting options to expected output in CSharpEditorConfigGeneratorTests- Update whitespace setting provider test to exclude advanced wrapping options- Fixes CI failures caused by new EditorConfig options being included in output
- Add csharp_parameter_wrapping to VS roaming profile storage- Add csharp_parameter_first_placement to VS roaming profile storage- Add csharp_parameter_alignment to VS roaming profile storageFixes VisualStudioOptionStorageTests failures by ensuring all new formatteroptions are properly registered with Visual Studio's settings persistence.
Made me check myself - took the wrong approach to resolving the last CI issue; will alter to be private options specifically for use in |
… API requirements- Remove WithPublicOption() calls from internal parameter wrapping options- Add parameter wrapping options to VS storage test exclusion list- Treat as EditorConfig-only options without public API surfaceThese options (csharp_binary_expression_wrapping, csharp_indent_wrapped_call_chains,csharp_parameter_alignment, csharp_parameter_first_placement, csharp_parameter_wrapping,csharp_wrap_call_chains) are intended for EditorConfig use only and do not requirepublic APIs or Visual Studio storage integration.Fixes VisualStudioOptionStorageTests failures without requiring API review process.
10ff5c1
to638b382
Compare…tionsRemove csharp_parameter_wrapping, csharp_parameter_first_placement, andcsharp_parameter_alignment from optionsWithoutStorage array since theseoptions now have Visual Studio storage as part of the parameter wrappingfeature implementation.Fixes CI test failures in VisualStudioOptionStorageTests.OptionHasStorageIfNecessary.
…-only- Remove Visual Studio storage registrations for parameter wrapping options- Add parameter wrapping options to test exclusion list for options without storage- Fixes CI test failures by following the established pattern for EditorConfig-only options
Azure Pipelines successfully started running 1 pipeline(s). |
Uh oh!
There was an error while loading.Please reload this page.
Addresses:#33872
📋Overview
This PR introduces a comprehensive set of EditorConfig-configurable formatting options for C# code wrapping behavior, significantly expanding developer control over code layout and readability.
✨New EditorConfig Options
Parameter Wrapping Configuration
csharp_parameter_wrapping
: Controls when method parameters should wrapdo_not_wrap
(default) - Keep parameters on same linewrap_long_parameters
- Wrap when line length exceeds limitwrap_every_parameter
- Always wrap each parameter to new linecsharp_parameter_first_placement
: Controls first parameter placement when wrappingsame_line
(default) - First parameter stays with method namenew_line
- First parameter moves to new linecsharp_parameter_alignment
: Controls wrapped parameter alignmentalign_with_first
(default) - Align subsequent parameters with first parameterindent
- Use standard indentation for wrapped parametersMethod Call Chain Wrapping
csharp_wrap_call_chains
: Enable/disable method call chain wrapping (boolean, default:false
)csharp_indent_wrapped_call_chains
: Control indentation of wrapped call chains (boolean, default:false
)Binary Expression Wrapping
csharp_binary_expression_wrapping
: Control binary operator wrapping behaviordo_not_wrap
(default) - Keep expressions on same linewrap_long_expressions
- Wrap when expressions exceed line lengthwrap_every_operator
- Wrap at every binary operator🏗️Implementation Details
🧪Test Coverage
📝Example Configurations
🔄Before/After Examples
Parameter Wrapping:
Call Chain Wrapping:
🚀Impact
This implementation provides a robust foundation for advanced code formatting customization while maintaining full backward compatibility and performance.
Add configurable parameter and method call chain wrapping
Fixes#33872
Summary
This PR implements configurable parameter wrapping and method call chain wrapping for the C# formatter, addressing two key formatting scenarios requested by the community in issue#33872.
Motivation
The current C# formatter lacks configurable options for wrapping parameters in conditional expressions and method call chains. This has been a long-standing community request (41 👍 reactions) for more granular control over code formatting, particularly for teams with specific style preferences.
Changes Made
New EditorConfig Options
Conditional Expression Wrapping:
csharp_wrap_conditional_expression
- Controls whether to wrap conditional expressionscsharp_indent_wrapped_conditional_expression
- Controls indentation behavior for wrapped conditionalsMethod Call Chain Wrapping:
csharp_wrap_method_call_chains
- Controls whether to wrap method call chainscsharp_indent_wrapped_method_call_chains
- Controls indentation behavior for wrapped chainsAll options default to
false
to maintain backward compatibility.Implementation Details
Files Modified:
CSharpFormattingOptions2.cs
- Added EditorConfig option definitionsCSharpSyntaxFormattingOptions.cs
- Added options to formatting structureWrappingFormattingRule.cs
- Added wrapping logic for both featuresTokenBasedFormattingRule.cs
- Added newline operationsIndentBlockFormattingRule.cs
- Added indentation logic with smart alignmentKey Features:
Before/After Examples
Conditional Expression Wrapping
Before:
After (wrapping enabled):
After (wrapping + indentation enabled):
Method Call Chain Wrapping
Before:
After (wrapping enabled):
After (smart indentation - simple identifier):
After (smart indentation - complex expression):
Testing
Added comprehensive test coverage:
Total:59 test cases ensuring robust functionality across diverse code patterns.
Backward Compatibility
false
, preserving existing formatting behaviorDesign Decisions
Smart Indentation: Method call chains use different indentation strategies:
data
) indent by one levellog.Entries
) align to the dot positionConsistent Patterns: Implementation follows the same architectural patterns used by existing conditional wrapping features for maintainability
EditorConfig Integration: Options are properly integrated with EditorConfig system for team-wide configuration
Related Issues