diff --git a/.editorconfig b/.editorconfig
index f9ecc06957..8e329bae64 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -6,6 +6,12 @@ root = true
[*]
indent_style = space
+[*.xml]
+indent_size = 2
+
+[Analyzers.xml]
+trim_trailing_whitespace = false
+
# Code files
[*.{cs,csx}]
indent_size = 4
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index f3c90a08ef..ae7e800a61 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -71,7 +71,7 @@ jobs:
../wordb/data/tech.acronyms.txt
build_core_and_testing:
- if: github.ref_type != 'tag' || startsWith(github.ref_name, 'v')
+ if: github.ref_type != 'tag' || startsWith(github.ref_name, 'v')
needs: pre_build
runs-on: ubuntu-24.04
env:
@@ -90,7 +90,7 @@ jobs:
path: src/_nupkg/*nupkg
build_analyzers:
- if: github.ref_type != 'tag' || startsWith(github.ref_name, 'v')
+ if: github.ref_type != 'tag' || startsWith(github.ref_name, 'v')
needs: pre_build
runs-on: ubuntu-24.04
env:
@@ -123,7 +123,7 @@ jobs:
path: src/${{ matrix.component.name }}.CodeFixes/bin/Release/*.*nupkg
build_refactorings:
- if: github.ref_type != 'tag' || startsWith(github.ref_name, 'v')
+ if: github.ref_type != 'tag' || startsWith(github.ref_name, 'v')
needs: pre_build
runs-on: ubuntu-24.04
env:
@@ -144,7 +144,7 @@ jobs:
path: src/Refactorings/bin/Release/*.*nupkg
build_code_fixes:
- if: github.ref_type != 'tag' || startsWith(github.ref_name, 'v')
+ if: github.ref_type != 'tag' || startsWith(github.ref_name, 'v')
needs: pre_build
runs-on: ubuntu-24.04
env:
@@ -165,7 +165,7 @@ jobs:
path: src/CodeFixes/bin/Release/*.*nupkg
build_vs_extension:
- if: github.ref_type != 'tag' || startsWith(github.ref_name, 'v')
+ if: github.ref_type != 'tag' || startsWith(github.ref_name, 'v')
needs: pre_build
runs-on: windows-latest
env:
@@ -199,7 +199,7 @@ jobs:
delete-merged: true
build_vs_code_extension:
- if: github.ref_type != 'tag' || startsWith(github.ref_name, 'v')
+ if: github.ref_type != 'tag' || startsWith(github.ref_name, 'v')
needs: [ pre_build, build_analyzers ]
runs-on: ubuntu-24.04
env:
@@ -209,6 +209,9 @@ jobs:
working-directory: src/VisualStudioCode
steps:
- uses: actions/checkout@v4
+ - uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: 9.0.301
- run: dotnet restore
- run: dotnet build --no-restore
- run: |
@@ -263,7 +266,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
- dotnet-version: 9.0.101
+ dotnet-version: 9.0.301
- run: dotnet restore
- run: dotnet build --no-restore
- run: dotnet pack --no-build
diff --git a/.gitignore b/.gitignore
index aa3419f5f5..a5ec2da68c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -140,7 +140,7 @@ publish/
*.[Pp]ublish.xml
*.azurePubxml
-# TODO: Un-comment the next line if you do not want to checkin
+# TODO: Un-comment the next line if you do not want to checkin
# your web deploy settings because they may include unencrypted
# passwords
#*.pubxml
@@ -244,4 +244,7 @@ ModelManifest.xml
# FAKE - F# Make
.fake/
-.DS_Store
\ No newline at end of file
+.DS_Store
+
+# JetBrains Rider setting files
+.idea/
diff --git a/src/Analyzers.xml b/src/Analyzers.xml
index 072001d577..f2ff360b3e 100644
--- a/src/Analyzers.xml
+++ b/src/Analyzers.xml
@@ -7819,6 +7819,46 @@ string s = """
+
+ RCS1269
+ FixBracketFormattingOfList
+ Fix bracket formatting of a list
+ Fix bracket formatting of {0}
+ Info
+ false
+
+
+
+
+ This analyzer:
+ * adds new line after an opening bracket of argument/parameter lists and similar lists
+ * adds new line before a closing bracket of argument/parameter lists and similar lists
+ * aligns the closing bracket with the block containing its opening bracket
+ The analyzer works only for multi-line declarations.
+
+
+
+
+
+
+
+
+
+
+
+
RCS9001
UsePatternMatching
diff --git a/src/CSharp/DetermineParameterTypeHelper.cs b/src/CSharp/DetermineParameterTypeHelper.cs
index 85ed539cf6..dabed05fee 100644
--- a/src/CSharp/DetermineParameterTypeHelper.cs
+++ b/src/CSharp/DetermineParameterTypeHelper.cs
@@ -45,7 +45,7 @@ public static ImmutableArray DetermineParameterTypes(
if (typeSymbol?.IsErrorType() == false)
{
- (typeSymbols ??= new HashSet()).Add(typeSymbol);
+ (typeSymbols ??= new HashSet(SymbolEqualityComparer.Default)).Add(typeSymbol);
}
}
diff --git a/src/Common/CSharp/CodeStyle/TargetBracesStyle.cs b/src/Common/CSharp/CodeStyle/TargetBracesStyle.cs
new file mode 100644
index 0000000000..5c6ee146b9
--- /dev/null
+++ b/src/Common/CSharp/CodeStyle/TargetBracesStyle.cs
@@ -0,0 +1,14 @@
+// Copyright (c) .NET Foundation and Contributors. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+
+namespace Roslynator.CSharp.CodeStyle;
+
+[Flags]
+public enum TargetBracesStyle
+{
+ None,
+ Opening,
+ Closing,
+ Both = Opening | Closing,
+}
diff --git a/src/Common/CSharp/Extensions/CodeStyleExtensions.cs b/src/Common/CSharp/Extensions/CodeStyleExtensions.cs
index 48fafdc967..eb853672f2 100644
--- a/src/Common/CSharp/Extensions/CodeStyleExtensions.cs
+++ b/src/Common/CSharp/Extensions/CodeStyleExtensions.cs
@@ -656,6 +656,30 @@ public static NewLinePosition GetNullConditionalOperatorNewLinePosition(this Syn
return context.GetConfigOptions().GetNullConditionalOperatorNewLinePosition(defaultValue);
}
+ public static TargetBracesStyle GetTargetBracesStyle(this SyntaxNodeAnalysisContext context)
+ => context.GetConfigOptions().GetTargetBracesStyle();
+
+ public static TargetBracesStyle GetTargetBracesStyle(this AnalyzerConfigOptions configOptions)
+ {
+ if (ConfigOptions.TryGetValue(configOptions, ConfigOptions.TargetBracesStyle, out string rawValue))
+ {
+ if (string.Equals(rawValue, ConfigOptionValues.TargetBracesStyle_Both, StringComparison.OrdinalIgnoreCase))
+ {
+ return TargetBracesStyle.Both;
+ }
+ else if (string.Equals(rawValue, ConfigOptionValues.TargetBracesStyle_Closing, StringComparison.OrdinalIgnoreCase))
+ {
+ return TargetBracesStyle.Closing;
+ }
+ else if (string.Equals(rawValue, ConfigOptionValues.TargetBracesStyle_Opening, StringComparison.OrdinalIgnoreCase))
+ {
+ return TargetBracesStyle.Opening;
+ }
+ }
+
+ return TargetBracesStyle.None;
+ }
+
private static bool TryGetNewLinePosition(
AnalyzerConfigOptions configOptions,
ConfigOptionDescriptor option,
diff --git a/src/Common/CSharp/SyntaxTriviaAnalysis.cs b/src/Common/CSharp/SyntaxTriviaAnalysis.cs
index e995ce2e8b..5bc1fedd42 100644
--- a/src/Common/CSharp/SyntaxTriviaAnalysis.cs
+++ b/src/Common/CSharp/SyntaxTriviaAnalysis.cs
@@ -111,6 +111,9 @@ public static IndentationAnalysis AnalyzeIndentation(SyntaxNode node, AnalyzerCo
}
public static SyntaxTrivia DetermineIndentation(SyntaxNodeOrToken nodeOrToken, CancellationToken cancellationToken = default)
+ => DetermineIndentation(nodeOrToken, true, cancellationToken);
+
+ public static SyntaxTrivia DetermineIndentation(SyntaxNodeOrToken nodeOrToken, bool searchInAccessors, CancellationToken cancellationToken = default)
{
SyntaxTree tree = nodeOrToken.SyntaxTree;
@@ -171,7 +174,7 @@ public static SyntaxTrivia DetermineIndentation(SyntaxNodeOrToken nodeOrToken, C
}
}
- if (!IsMemberDeclarationOrStatementOrAccessorDeclaration(node))
+ if (searchInAccessors && !IsMemberDeclarationOrStatementOrAccessorDeclaration(node))
{
node = node.Parent;
diff --git a/src/Common/ConfigOptionKeys.Generated.cs b/src/Common/ConfigOptionKeys.Generated.cs
index d03c51daff..b5b25046a3 100644
--- a/src/Common/ConfigOptionKeys.Generated.cs
+++ b/src/Common/ConfigOptionKeys.Generated.cs
@@ -37,6 +37,7 @@ internal static partial class ConfigOptionKeys
public const string PrefixFieldIdentifierWithUnderscore = "roslynator_prefix_field_identifier_with_underscore";
public const string SuppressUnityScriptMethods = "roslynator_suppress_unity_script_methods";
public const string TabLength = "roslynator_tab_length";
+ public const string TargetBracesStyle = "roslynator_target_braces_style";
public const string TrailingCommaStyle = "roslynator_trailing_comma_style";
public const string UnityCodeAnalysisEnabled = "roslynator_unity_code_analysis.enabled";
public const string UseAnonymousFunctionOrMethodGroup = "roslynator_use_anonymous_function_or_method_group";
diff --git a/src/Common/ConfigOptionValues.Generated.cs b/src/Common/ConfigOptionValues.Generated.cs
index 06ae33fb45..ee449d1350 100644
--- a/src/Common/ConfigOptionValues.Generated.cs
+++ b/src/Common/ConfigOptionValues.Generated.cs
@@ -52,6 +52,10 @@ internal static partial class ConfigOptionValues
public const string ObjectCreationTypeStyle_Explicit = "explicit";
public const string ObjectCreationTypeStyle_Implicit = "implicit";
public const string ObjectCreationTypeStyle_ImplicitWhenTypeIsObvious = "implicit_when_type_is_obvious";
+ public const string TargetBracesStyle_None = "none";
+ public const string TargetBracesStyle_Opening = "opening";
+ public const string TargetBracesStyle_Closing = "closing";
+ public const string TargetBracesStyle_Both = "both";
public const string TrailingCommaStyle_Include = "include";
public const string TrailingCommaStyle_Omit = "omit";
public const string TrailingCommaStyle_OmitWhenSingleLine = "omit_when_single_line";
diff --git a/src/Common/ConfigOptions.Generated.cs b/src/Common/ConfigOptions.Generated.cs
index 556a34bd13..95e6066949 100644
--- a/src/Common/ConfigOptions.Generated.cs
+++ b/src/Common/ConfigOptions.Generated.cs
@@ -196,6 +196,12 @@ public static partial class ConfigOptions
defaultValuePlaceholder: "",
description: "A number of spaces that are equivalent to a tab character");
+ public static readonly ConfigOptionDescriptor TargetBracesStyle = new(
+ key: ConfigOptionKeys.TargetBracesStyle,
+ defaultValue: "none",
+ defaultValuePlaceholder: "both|closing|none|opening",
+ description: "Define which braces should be used as a target of the code fix");
+
public static readonly ConfigOptionDescriptor TrailingCommaStyle = new(
key: ConfigOptionKeys.TrailingCommaStyle,
defaultValue: null,
diff --git a/src/Common/DiagnosticIdentifiers.Generated.cs b/src/Common/DiagnosticIdentifiers.Generated.cs
index 7d6e59085e..3f811ce922 100644
--- a/src/Common/DiagnosticIdentifiers.Generated.cs
+++ b/src/Common/DiagnosticIdentifiers.Generated.cs
@@ -280,5 +280,6 @@ public static partial class DiagnosticIdentifiers
public const string UseRawStringLiteral = "RCS1266";
public const string UseStringInterpolationInsteadOfStringConcat = "RCS1267";
public const string SimplifyNumericComparison = "RCS1268";
+ public const string FixBracketFormattingOfList = "RCS1269";
}
}
\ No newline at end of file
diff --git a/src/Common/DiagnosticRules.Generated.cs b/src/Common/DiagnosticRules.Generated.cs
index 0b631ac6fb..e9f72ec0e6 100644
--- a/src/Common/DiagnosticRules.Generated.cs
+++ b/src/Common/DiagnosticRules.Generated.cs
@@ -3323,5 +3323,17 @@ public static partial class DiagnosticRules
helpLinkUri: DiagnosticIdentifiers.SimplifyNumericComparison,
customTags: []);
+ /// RCS1269
+ public static readonly DiagnosticDescriptor FixBracketFormattingOfList = DiagnosticDescriptorFactory.Create(
+ id: DiagnosticIdentifiers.FixBracketFormattingOfList,
+ title: "Fix bracket formatting of a list",
+ messageFormat: "Fix bracket formatting of {0}",
+ category: DiagnosticCategories.Roslynator,
+ defaultSeverity: DiagnosticSeverity.Info,
+ isEnabledByDefault: false,
+ description: null,
+ helpLinkUri: DiagnosticIdentifiers.FixBracketFormattingOfList,
+ customTags: []);
+
}
}
\ No newline at end of file
diff --git a/src/ConfigOptions.xml b/src/ConfigOptions.xml
index 7e43508098..cb70170eee 100644
--- a/src/ConfigOptions.xml
+++ b/src/ConfigOptions.xml
@@ -237,6 +237,15 @@
when_type_is_obvious
+