Skip to content

Commit 074b1f3

Browse files
authored
Merge release/dev17.13 to main (#76387)
This is an automatically generated pull request from release/dev17.13 into main. Once all conflicts are resolved and all the tests pass, you are free to merge the pull request. 🐯 ## Troubleshooting conflicts ### Identify authors of changes which introduced merge conflicts Scroll to the bottom, then for each file containing conflicts copy its path into the following searches: - https://github.com/dotnet/roslyn/find/release/dev17.13 - https://github.com/dotnet/roslyn/find/main Usually the most recent change to a file between the two branches is considered to have introduced the conflicts, but sometimes it will be necessary to look for the conflicting lines and check the blame in each branch. Generally the author whose change introduced the conflicts should pull down this PR, fix the conflicts locally, then push up a commit resolving the conflicts. ### Resolve merge conflicts using your local repo Sometimes merge conflicts may be present on GitHub but merging locally will work without conflicts. This is due to differences between the merge algorithm used in local git versus the one used by GitHub. ``` bash git fetch --all git checkout -t upstream/merges/release/dev17.13-to-main git reset --hard upstream/main git merge upstream/release/dev17.13 # Fix merge conflicts git commit git push upstream merges/release/dev17.13-to-main --force ```
2 parents c07f28f + e5f5519 commit 074b1f3

File tree

18 files changed

+526
-124
lines changed

18 files changed

+526
-124
lines changed

azure-pipelines-official.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,11 @@ extends:
121121
displayName: Build and Test
122122

123123
jobs:
124-
- ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/release/dev17.12') }}:
124+
- ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/release/dev17.13') }}:
125125
- template: /eng/common/templates-official/job/onelocbuild.yml@self
126126
parameters:
127127
MirrorRepo: roslyn
128-
MirrorBranch: release/dev17.12
128+
MirrorBranch: release/dev17.13
129129
LclSource: lclFilesfromPackage
130130
LclPackageId: 'LCL-JUNO-PROD-ROSLYN'
131131

src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/EditorConfigNamingStyleParserTests.cs

Lines changed: 156 additions & 40 deletions
Large diffs are not rendered by default.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Collections.Generic;
7+
using System.Collections.Immutable;
8+
using System.Linq;
9+
using System.Xml.Linq;
10+
using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles;
11+
using Microsoft.CodeAnalysis.NamingStyles;
12+
13+
namespace Microsoft.CodeAnalysis.Test.Utilities;
14+
15+
internal static class NamingStyleTestUtilities
16+
{
17+
public static string Inspect(this NamingRule rule)
18+
=> $"{rule.NamingStyle.Inspect()} {rule.SymbolSpecification.Inspect()} {rule.EnforcementLevel}";
19+
20+
public static string Inspect(this NamingStyle style)
21+
=> $"{style.Name} prefix='{style.Prefix}' suffix='{style.Suffix}' separator='{style.WordSeparator}'";
22+
23+
public static string Inspect(this SymbolSpecification symbol)
24+
=> $"{symbol.Name} {Inspect(symbol.ApplicableSymbolKindList)} {Inspect(symbol.ApplicableAccessibilityList)} {Inspect(symbol.RequiredModifierList)}";
25+
26+
public static string Inspect<T>(ImmutableArray<T> items) where T : notnull
27+
=> string.Join(",", items.Select(item => item.ToString()));
28+
29+
public static string Inspect(this NamingStylePreferences preferences, string[]? excludeNodes = null)
30+
{
31+
var xml = preferences.CreateXElement();
32+
33+
// filter out insignificant elements:
34+
var elementsToRemove = new List<XElement>();
35+
foreach (var element in xml.DescendantsAndSelf())
36+
{
37+
if (excludeNodes != null && excludeNodes.Contains(element.Name.LocalName))
38+
{
39+
elementsToRemove.Add(element);
40+
}
41+
}
42+
43+
foreach (var element in elementsToRemove)
44+
{
45+
element.Remove();
46+
}
47+
48+
// replaces GUIDs with unique deterministic numbers:
49+
var ordinal = 0;
50+
var guidMap = new Dictionary<Guid, int>();
51+
foreach (var element in xml.DescendantsAndSelf())
52+
{
53+
foreach (var attribute in element.Attributes())
54+
{
55+
if (Guid.TryParse(attribute.Value, out var guid))
56+
{
57+
if (!guidMap.TryGetValue(guid, out var existingOrdinal))
58+
{
59+
existingOrdinal = ordinal++;
60+
guidMap.Add(guid, existingOrdinal);
61+
}
62+
63+
attribute.Value = existingOrdinal.ToString();
64+
}
65+
}
66+
}
67+
68+
return xml.ToString();
69+
}
70+
}

src/LanguageServer/Protocol/Features/Options/SolutionAnalyzerConfigOptionsUpdater.cs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
using System.Composition;
99
using System.Diagnostics;
1010
using System.Linq;
11-
using System.Threading;
1211
using Microsoft.CodeAnalysis;
1312
using Microsoft.CodeAnalysis.Diagnostics;
13+
using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles;
1414
using Microsoft.CodeAnalysis.ErrorReporting;
1515
using Microsoft.CodeAnalysis.Host;
1616
using Microsoft.CodeAnalysis.Host.Mef;
@@ -86,8 +86,21 @@ Solution UpdateOptions(Solution oldSolution)
8686

8787
// update changed values:
8888
var configName = key.Option.Definition.ConfigName;
89-
var configValue = key.Option.Definition.Serializer.Serialize(value);
90-
lazyBuilder[configName] = configValue;
89+
if (value is NamingStylePreferences preferences)
90+
{
91+
NamingStylePreferencesEditorConfigSerializer.WriteNamingStylePreferencesToEditorConfig(
92+
preferences.SymbolSpecifications,
93+
preferences.NamingStyles,
94+
preferences.NamingRules,
95+
language,
96+
entryWriter: (name, value) => lazyBuilder[name] = value,
97+
triviaWriter: null,
98+
setPrioritiesToPreserveOrder: true);
99+
}
100+
else
101+
{
102+
lazyBuilder[configName] = key.Option.Definition.Serializer.Serialize(value);
103+
}
91104
}
92105

93106
if (lazyBuilder != null)

src/LanguageServer/ProtocolUnitTests/Options/SolutionAnalyzerConfigOptionsUpdaterTests.cs

Lines changed: 155 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,17 @@
33
// See the LICENSE file in the project root for more information.
44

55
using System.Collections.Generic;
6+
using System.IO;
67
using System.Linq;
8+
using System.Threading;
9+
using Microsoft.CodeAnalysis.CodeStyle;
10+
using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles;
711
using Microsoft.CodeAnalysis.Formatting;
812
using Microsoft.CodeAnalysis.Host;
13+
using Microsoft.CodeAnalysis.Shared.Extensions;
914
using Microsoft.CodeAnalysis.Test.Utilities;
10-
using Roslyn.Utilities;
15+
using Microsoft.CodeAnalysis.UnitTests;
16+
using Roslyn.Test.Utilities;
1117
using Xunit;
1218

1319
namespace Microsoft.CodeAnalysis.Options.UnitTests;
@@ -95,6 +101,154 @@ void AssertOptionValue(IOption2 option, string language, string expectedValue)
95101
}
96102
}
97103

104+
[Fact]
105+
[WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/2297536")]
106+
public void FlowsNamingStylePreferencesToWorkspace()
107+
{
108+
using var workspace = CreateWorkspace();
109+
110+
var testProjectWithoutConfig = new TestHostProject(workspace, "proj_without_config", LanguageNames.CSharp);
111+
112+
testProjectWithoutConfig.AddDocument(new TestHostDocument("""
113+
class MyClass1;
114+
""",
115+
filePath: Path.Combine(TempRoot.Root, "proj_without_config", "test.cs")));
116+
117+
var testProjectWithConfig = new TestHostProject(workspace, "proj_with_config", LanguageNames.CSharp);
118+
119+
// explicitly specified style should override style specified in the fallback:
120+
testProjectWithConfig.AddAnalyzerConfigDocument(new TestHostDocument(
121+
"""
122+
[*.cs]
123+
dotnet_naming_rule.rule1.severity = warning
124+
dotnet_naming_rule.rule1.symbols = symbols1
125+
dotnet_naming_rule.rule1.style = style1
126+
127+
dotnet_naming_symbols.symbols1.applicable_kinds = class
128+
dotnet_naming_symbols.symbols1.applicable_accessibilities = *
129+
dotnet_naming_style.style1.capitalization = camel_case
130+
""",
131+
filePath: Path.Combine(TempRoot.Root, "proj_with_config", ".editorconfig")));
132+
133+
testProjectWithConfig.AddDocument(new TestHostDocument("""
134+
class MyClass2;
135+
""",
136+
filePath: Path.Combine(TempRoot.Root, "proj_with_config", "test.cs")));
137+
138+
workspace.AddTestProject(testProjectWithoutConfig);
139+
workspace.AddTestProject(testProjectWithConfig);
140+
141+
var globalOptions = workspace.GetService<IGlobalOptionService>();
142+
143+
var hostPeferences = OptionsTestHelpers.CreateNamingStylePreferences(
144+
([MethodKind.Ordinary], Capitalization.PascalCase, ReportDiagnostic.Error),
145+
([MethodKind.Ordinary, SymbolKind.Field], Capitalization.PascalCase, ReportDiagnostic.Error));
146+
147+
globalOptions.SetGlobalOption(NamingStyleOptions.NamingPreferences, LanguageNames.CSharp, hostPeferences);
148+
149+
Assert.True(workspace.CurrentSolution.FallbackAnalyzerOptions.TryGetValue(LanguageNames.CSharp, out var fallbackOptions));
150+
151+
// Note: rules are ordered but symbol and naming style specifications are not.
152+
AssertEx.Equal(
153+
hostPeferences.Rules.NamingRules.Select(r => r.Inspect()),
154+
fallbackOptions.GetNamingStylePreferences().Rules.NamingRules.Select(r => r.Inspect()));
155+
156+
var projectWithConfig = workspace.CurrentSolution.GetRequiredProject(testProjectWithConfig.Id);
157+
var treeWithConfig = projectWithConfig.Documents.Single().GetSyntaxTreeSynchronously(CancellationToken.None);
158+
Assert.NotNull(treeWithConfig);
159+
var documentOptions = projectWithConfig.HostAnalyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(treeWithConfig);
160+
161+
Assert.True(documentOptions.TryGetEditorConfigOption<NamingStylePreferences>(NamingStyleOptions.NamingPreferences, out var documentPreferences));
162+
Assert.NotNull(documentPreferences);
163+
164+
// Only naming styles specified in the editorconfig are present.
165+
// Host preferences are ignored. This behavior is consistent with VS 16.11.
166+
AssertEx.EqualOrDiff("""
167+
<NamingPreferencesInfo SerializationVersion="5">
168+
<SymbolSpecifications>
169+
<SymbolSpecification ID="0" Name="symbols1">
170+
<ApplicableSymbolKindList>
171+
<TypeKind>Class</TypeKind>
172+
</ApplicableSymbolKindList>
173+
<ApplicableAccessibilityList>
174+
<AccessibilityKind>NotApplicable</AccessibilityKind>
175+
<AccessibilityKind>Public</AccessibilityKind>
176+
<AccessibilityKind>Internal</AccessibilityKind>
177+
<AccessibilityKind>Private</AccessibilityKind>
178+
<AccessibilityKind>Protected</AccessibilityKind>
179+
<AccessibilityKind>ProtectedAndInternal</AccessibilityKind>
180+
<AccessibilityKind>ProtectedOrInternal</AccessibilityKind>
181+
</ApplicableAccessibilityList>
182+
<RequiredModifierList />
183+
</SymbolSpecification>
184+
</SymbolSpecifications>
185+
<NamingStyles>
186+
<NamingStyle ID="1" Name="style1" Prefix="" Suffix="" WordSeparator="" CapitalizationScheme="CamelCase" />
187+
</NamingStyles>
188+
<NamingRules>
189+
<SerializableNamingRule SymbolSpecificationID="0" NamingStyleID="1" EnforcementLevel="Warning" />
190+
</NamingRules>
191+
</NamingPreferencesInfo>
192+
""",
193+
documentPreferences.Inspect());
194+
195+
var projectWithoutConfig = workspace.CurrentSolution.GetRequiredProject(testProjectWithoutConfig.Id);
196+
var treeWithoutConfig = projectWithoutConfig.Documents.Single().GetSyntaxTreeSynchronously(CancellationToken.None);
197+
Assert.NotNull(treeWithoutConfig);
198+
documentOptions = projectWithoutConfig.HostAnalyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(treeWithoutConfig);
199+
200+
Assert.True(documentOptions.TryGetEditorConfigOption(NamingStyleOptions.NamingPreferences, out documentPreferences));
201+
Assert.NotNull(documentPreferences);
202+
203+
// Host preferences:
204+
AssertEx.EqualOrDiff("""
205+
<NamingPreferencesInfo SerializationVersion="5">
206+
<SymbolSpecifications>
207+
<SymbolSpecification ID="0" Name="symbols1">
208+
<ApplicableSymbolKindList>
209+
<MethodKind>Ordinary</MethodKind>
210+
<SymbolKind>Field</SymbolKind>
211+
</ApplicableSymbolKindList>
212+
<ApplicableAccessibilityList>
213+
<AccessibilityKind>NotApplicable</AccessibilityKind>
214+
<AccessibilityKind>Public</AccessibilityKind>
215+
<AccessibilityKind>Internal</AccessibilityKind>
216+
<AccessibilityKind>Private</AccessibilityKind>
217+
<AccessibilityKind>Protected</AccessibilityKind>
218+
<AccessibilityKind>ProtectedAndInternal</AccessibilityKind>
219+
<AccessibilityKind>ProtectedOrInternal</AccessibilityKind>
220+
</ApplicableAccessibilityList>
221+
<RequiredModifierList />
222+
</SymbolSpecification>
223+
<SymbolSpecification ID="1" Name="symbols0">
224+
<ApplicableSymbolKindList>
225+
<MethodKind>Ordinary</MethodKind>
226+
</ApplicableSymbolKindList>
227+
<ApplicableAccessibilityList>
228+
<AccessibilityKind>NotApplicable</AccessibilityKind>
229+
<AccessibilityKind>Public</AccessibilityKind>
230+
<AccessibilityKind>Internal</AccessibilityKind>
231+
<AccessibilityKind>Private</AccessibilityKind>
232+
<AccessibilityKind>Protected</AccessibilityKind>
233+
<AccessibilityKind>ProtectedAndInternal</AccessibilityKind>
234+
<AccessibilityKind>ProtectedOrInternal</AccessibilityKind>
235+
</ApplicableAccessibilityList>
236+
<RequiredModifierList />
237+
</SymbolSpecification>
238+
</SymbolSpecifications>
239+
<NamingStyles>
240+
<NamingStyle ID="2" Name="style1" Prefix="" Suffix="" WordSeparator="" CapitalizationScheme="PascalCase" />
241+
<NamingStyle ID="3" Name="style0" Prefix="" Suffix="" WordSeparator="" CapitalizationScheme="PascalCase" />
242+
</NamingStyles>
243+
<NamingRules>
244+
<SerializableNamingRule SymbolSpecificationID="1" NamingStyleID="3" EnforcementLevel="Error" />
245+
<SerializableNamingRule SymbolSpecificationID="0" NamingStyleID="2" EnforcementLevel="Error" />
246+
</NamingRules>
247+
</NamingPreferencesInfo>
248+
""",
249+
documentPreferences.Inspect());
250+
}
251+
98252
[Fact]
99253
public void IgnoresNonEditorConfigOptions()
100254
{

src/VisualStudio/Core/Test.Next/Options/VisualStudioOptionStorageTests.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,18 @@ public void LanguageSpecificOptionsHaveCorrectPrefix(string configName)
107107
return;
108108
}
109109

110-
if (!info.Option.Definition.IsEditorConfigOption)
110+
// TODO: https://github.com/dotnet/roslyn/issues/65787
111+
if (info.Option.Name is
112+
"csharp_format_on_return" or
113+
"csharp_format_on_typing" or
114+
"csharp_format_on_semicolon" or
115+
"csharp_format_on_close_brace" or
116+
"csharp_enable_inlay_hints_for_types" or
117+
"csharp_enable_inlay_hints_for_implicit_variable_types" or
118+
"csharp_enable_inlay_hints_for_lambda_parameter_types" or
119+
"csharp_enable_inlay_hints_for_implicit_object_creation" or
120+
"csharp_enable_inlay_hints_for_collection_expressions")
111121
{
112-
// TODO: remove condition once all options have config name https://github.com/dotnet/roslyn/issues/65787
113122
return;
114123
}
115124

src/Workspaces/CoreTestUtilities/Options/OptionsTestHelpers.cs

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System.Collections.Immutable;
1010
using Microsoft.CodeAnalysis.CodeStyle;
1111
using Microsoft.CodeAnalysis.CSharp.Formatting;
12+
using Microsoft.CodeAnalysis.Diagnostics;
1213
using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles;
1314
using Microsoft.CodeAnalysis.Formatting;
1415
using Microsoft.CodeAnalysis.NamingStyles;
@@ -147,33 +148,53 @@ private static object GetDifferentEnumValue(Type type, object defaultValue)
147148
}
148149

149150
public static NamingStylePreferences GetNonDefaultNamingStylePreference()
151+
=> CreateNamingStylePreferences(([TypeKind.Class], Capitalization.PascalCase, ReportDiagnostic.Error));
152+
153+
public static NamingStylePreferences CreateNamingStylePreferences(
154+
params (SymbolSpecification.SymbolKindOrTypeKind[], Capitalization capitalization, ReportDiagnostic severity)[] rules)
150155
{
151-
var symbolSpecification = new SymbolSpecification(
152-
Guid.NewGuid(),
153-
"Name",
154-
ImmutableArray.Create(new SymbolSpecification.SymbolKindOrTypeKind(TypeKind.Class)),
155-
accessibilityList: default,
156-
modifiers: default);
157-
158-
var namingStyle = new NamingStyle(
159-
Guid.NewGuid(),
160-
capitalizationScheme: Capitalization.PascalCase,
161-
name: "Name",
162-
prefix: "",
163-
suffix: "",
164-
wordSeparator: "");
165-
166-
var namingRule = new SerializableNamingRule()
156+
var symbolSpecifications = new List<SymbolSpecification>();
157+
var namingStyles = new List<NamingStyle>();
158+
var namingRules = new List<SerializableNamingRule>();
159+
160+
foreach (var (kinds, capitalization, severity) in rules)
167161
{
168-
SymbolSpecificationID = symbolSpecification.ID,
169-
NamingStyleID = namingStyle.ID,
170-
EnforcementLevel = ReportDiagnostic.Error
171-
};
162+
var id = namingRules.Count;
163+
164+
var symbolSpecification = new SymbolSpecification(
165+
Guid.NewGuid(),
166+
name: $"symbols{id}",
167+
[.. kinds],
168+
accessibilityList: default,
169+
modifiers: default);
170+
171+
symbolSpecifications.Add(symbolSpecification);
172+
173+
var namingStyle = new NamingStyle(
174+
Guid.NewGuid(),
175+
capitalizationScheme: capitalization,
176+
name: $"style{id}",
177+
prefix: "",
178+
suffix: "",
179+
wordSeparator: "");
180+
181+
namingStyles.Add(namingStyle);
182+
183+
namingRules.Add(new SerializableNamingRule()
184+
{
185+
SymbolSpecificationID = symbolSpecification.ID,
186+
NamingStyleID = namingStyle.ID,
187+
EnforcementLevel = severity
188+
});
189+
}
172190

173191
return new NamingStylePreferences(
174-
ImmutableArray.Create(symbolSpecification),
175-
ImmutableArray.Create(namingStyle),
176-
ImmutableArray.Create(namingRule));
192+
[.. symbolSpecifications],
193+
[.. namingStyles],
194+
[.. namingRules]);
177195
}
196+
197+
public static NamingStylePreferences ParseNamingStylePreferences(Dictionary<string, string> options)
198+
=> EditorConfigNamingStyleParser.ParseDictionary(new DictionaryAnalyzerConfigOptions(options.ToImmutableDictionary()));
178199
}
179200
}

0 commit comments

Comments
 (0)