-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #58075 from jmarolf/features/editorconfig-naming-s…
…tyle-support
- Loading branch information
Showing
69 changed files
with
5,256 additions
and
182 deletions.
There are no files selected for viewing
209 changes: 208 additions & 1 deletion
209
src/EditorFeatures/CSharpTest/EditorConfigSettings/Updater/SettingsUpdaterTests.cs
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
94 changes: 94 additions & 0 deletions
94
src/EditorFeatures/Core/EditorConfigSettings/Data/NamingStyleSetting.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
// 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 System; | ||
using System.Linq; | ||
using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; | ||
using Microsoft.CodeAnalysis.Editor.EditorConfigSettings.Updater; | ||
using Microsoft.CodeAnalysis.EditorConfig.Parsing.NamingStyles; | ||
using Microsoft.CodeAnalysis.NamingStyles; | ||
|
||
namespace Microsoft.CodeAnalysis.Editor.EditorConfigSettings.Data | ||
{ | ||
internal class NamingStyleSetting | ||
{ | ||
private NamingStyle[] _allStyles; | ||
private readonly NamingStyleSettingsUpdater? _settingsUpdater; | ||
|
||
public NamingStyleSetting( | ||
NamingRule namingRule, | ||
NamingStyle[] allStyles, | ||
NamingStyleSettingsUpdater settingsUpdater, | ||
string? fileName = null) | ||
{ | ||
Style = namingRule.NamingStyle; | ||
_allStyles = allStyles; | ||
Type = namingRule.SymbolSpecification; | ||
Severity = namingRule.EnforcementLevel; | ||
_settingsUpdater = settingsUpdater; | ||
Location = new SettingLocation(fileName is null ? LocationKind.VisualStudio : LocationKind.EditorConfig, fileName); | ||
} | ||
|
||
private NamingStyleSetting() | ||
{ | ||
_allStyles = Array.Empty<NamingStyle>(); | ||
} | ||
|
||
public event EventHandler<EventArgs>? SettingChanged; | ||
|
||
internal static NamingStyleSetting FromParseResult(NamingStyleOption namingStyleOption) | ||
{ | ||
return new NamingStyleSetting | ||
{ | ||
Style = namingStyleOption.NamingScheme.AsNamingStyle(), | ||
Type = namingStyleOption.ApplicableSymbolInfo.AsSymbolSpecification(), | ||
Severity = namingStyleOption.Severity, | ||
Location = new SettingLocation(LocationKind.EditorConfig, namingStyleOption.Section.FilePath) | ||
}; | ||
} | ||
|
||
internal NamingStyle Style { get; set; } | ||
internal SymbolSpecification? Type { get; set; } | ||
|
||
public string StyleName => Style.Name; | ||
public string[] AllStyles => _allStyles.Select(style => style.Name).ToArray(); | ||
public string TypeName => Type?.Name ?? string.Empty; | ||
public ReportDiagnostic Severity { get; private set; } | ||
public SettingLocation? Location { get; protected set; } | ||
|
||
private void OnSettingChanged((object, object?) setting) | ||
{ | ||
if (setting is (ReportDiagnostic severity, _)) | ||
{ | ||
Severity = severity; | ||
SettingChanged?.Invoke(this, EventArgs.Empty); | ||
} | ||
|
||
if (setting is (NamingStyle style, NamingStyle[] allStyles)) | ||
{ | ||
Style = style; | ||
_allStyles = allStyles; | ||
SettingChanged?.Invoke(this, EventArgs.Empty); | ||
} | ||
} | ||
|
||
internal void ChangeSeverity(ReportDiagnostic severity) | ||
{ | ||
if (Location is not null) | ||
{ | ||
Location = Location with { LocationKind = LocationKind.EditorConfig }; | ||
_settingsUpdater?.QueueUpdate((OnSettingChanged, this), severity); | ||
} | ||
} | ||
|
||
internal void ChangeStyle(int selectedIndex) | ||
{ | ||
if (selectedIndex > -1 && selectedIndex < _allStyles.Length && Location is not null) | ||
{ | ||
Location = Location with { LocationKind = LocationKind.EditorConfig }; | ||
_settingsUpdater?.QueueUpdate((OnSettingChanged, this), _allStyles[selectedIndex]); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
80 changes: 80 additions & 0 deletions
80
...atures/Core/EditorConfigSettings/DataProvider/NamingStyles/NamingStyleSettingsProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
// 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 System; | ||
using System.Linq; | ||
using System.Threading; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.Diagnostics; | ||
using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; | ||
using Microsoft.CodeAnalysis.Editor.EditorConfigSettings.Data; | ||
using Microsoft.CodeAnalysis.Editor.EditorConfigSettings.Extensions; | ||
using Microsoft.CodeAnalysis.Editor.EditorConfigSettings.Updater; | ||
using Microsoft.CodeAnalysis.Options; | ||
using Microsoft.CodeAnalysis.Shared.Extensions; | ||
using Microsoft.CodeAnalysis.Simplification; | ||
|
||
namespace Microsoft.CodeAnalysis.Editor.EditorConfigSettings.DataProvider.NamingStyles | ||
{ | ||
internal class NamingStyleSettingsProvider : SettingsProviderBase<NamingStyleSetting, NamingStyleSettingsUpdater, (Action<(object, object?)>, NamingStyleSetting), object> | ||
{ | ||
public NamingStyleSettingsProvider(string fileName, NamingStyleSettingsUpdater settingsUpdater, Workspace workspace) | ||
: base(fileName, settingsUpdater, workspace) | ||
{ | ||
Update(); | ||
} | ||
|
||
protected override void UpdateOptions(AnalyzerConfigOptions _, OptionSet optionSet) | ||
{ | ||
var solution = Workspace.CurrentSolution; | ||
var projects = solution.GetProjectsUnderEditorConfigFile(FileName); | ||
var project = projects.FirstOrDefault(); | ||
if (project is null) | ||
{ | ||
return; | ||
} | ||
|
||
var options = project.State.AnalyzerOptions; | ||
var document = project.Documents.FirstOrDefault(); | ||
if (document is null) | ||
{ | ||
return; | ||
} | ||
|
||
var sourceTree = document.GetRequiredSyntaxTreeSynchronously(default(CancellationToken)); | ||
if (options.TryGetEditorConfigOption(NamingStyleOptions.NamingPreferences, sourceTree, out NamingStylePreferences? namingPreferences) && | ||
namingPreferences is not null) | ||
{ | ||
AddNamingStylePreferences(namingPreferences, isInEditorConfig: true); | ||
} | ||
else | ||
{ | ||
namingPreferences = optionSet.GetOption(NamingStyleOptions.NamingPreferences, project.Language); | ||
if (namingPreferences is null) | ||
{ | ||
return; | ||
} | ||
|
||
AddNamingStylePreferences(namingPreferences, isInEditorConfig: false); | ||
} | ||
|
||
void AddNamingStylePreferences(NamingStylePreferences namingPreferences, bool isInEditorConfig) | ||
{ | ||
var namingRules = namingPreferences.NamingRules.Select(r => r.GetRule(namingPreferences)); | ||
var allStyles = namingPreferences.NamingStyles.DistinctBy(s => s.Name).ToArray(); | ||
var namingStyles = namingRules | ||
.Select(namingRule => | ||
{ | ||
var style = namingRule.NamingStyle; | ||
var type = namingRule.SymbolSpecification; | ||
return isInEditorConfig | ||
? new NamingStyleSetting(namingRule, allStyles, SettingsUpdater, FileName) | ||
: new NamingStyleSetting(namingRule, allStyles, SettingsUpdater); | ||
}); | ||
|
||
AddRange(namingStyles); | ||
} | ||
} | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
...Core/EditorConfigSettings/DataProvider/NamingStyles/NamingStyleSettingsProviderFactory.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// 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.Editor.EditorConfigSettings.Data; | ||
using Microsoft.CodeAnalysis.Editor.EditorConfigSettings.Updater; | ||
|
||
namespace Microsoft.CodeAnalysis.Editor.EditorConfigSettings.DataProvider.NamingStyles | ||
{ | ||
internal class NamingStyleSettingsProviderFactory : IWorkspaceSettingsProviderFactory<NamingStyleSetting> | ||
{ | ||
private readonly Workspace _workspace; | ||
|
||
public NamingStyleSettingsProviderFactory(Workspace workspace) => _workspace = workspace; | ||
|
||
public ISettingsProvider<NamingStyleSetting> GetForFile(string filePath) | ||
{ | ||
var updater = new NamingStyleSettingsUpdater(_workspace, filePath); | ||
return new NamingStyleSettingsProvider(filePath, updater, _workspace); | ||
} | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
...torConfigSettings/DataProvider/NamingStyles/NamingStyleSettingsWorkspaceServiceFactory.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// 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 System; | ||
using System.Composition; | ||
using Microsoft.CodeAnalysis.Editor.EditorConfigSettings.Data; | ||
using Microsoft.CodeAnalysis.Host; | ||
using Microsoft.CodeAnalysis.Host.Mef; | ||
|
||
namespace Microsoft.CodeAnalysis.Editor.EditorConfigSettings.DataProvider.NamingStyles | ||
{ | ||
[ExportWorkspaceServiceFactory(typeof(IWorkspaceSettingsProviderFactory<NamingStyleSetting>)), Shared] | ||
internal class NamingStyleSettingsWorkspaceServiceFactory : IWorkspaceServiceFactory | ||
{ | ||
[ImportingConstructor] | ||
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] | ||
public NamingStyleSettingsWorkspaceServiceFactory() | ||
{ | ||
} | ||
|
||
public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices) | ||
=> new NamingStyleSettingsProviderFactory(workspaceServices.Workspace); | ||
} | ||
} |
84 changes: 84 additions & 0 deletions
84
...ures/Core/EditorConfigSettings/Updater/NamingStyles/EditorConfigNamingStylesExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
// 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 System; | ||
using System.Collections.Immutable; | ||
using System.Diagnostics.CodeAnalysis; | ||
using System.Linq; | ||
using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; | ||
using Microsoft.CodeAnalysis.Editor.EditorConfigSettings.Data; | ||
using Microsoft.CodeAnalysis.EditorConfig.Parsing.NamingStyles; | ||
using Microsoft.CodeAnalysis.NamingStyles; | ||
|
||
namespace Microsoft.CodeAnalysis.Editor.EditorConfigSettings.Updater | ||
{ | ||
internal static class EditorConfigNamingStylesExtensions | ||
{ | ||
public static bool TryGetParseResultForRule( | ||
this EditorConfigNamingStyles editorConfigNamingStyles, | ||
NamingStyleSetting namingStyleSetting, | ||
[NotNullWhen(true)] out NamingStyleOption? namingStyleOption) | ||
{ | ||
namingStyleOption = null; | ||
foreach (var (option, optionAsNamingStyle) in editorConfigNamingStyles.Rules.AsNamingStyleSettings()) | ||
{ | ||
if (AreSameRule(optionAsNamingStyle, namingStyleSetting)) | ||
{ | ||
namingStyleOption = option; | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
|
||
static bool AreSameRule(NamingStyleSetting left, NamingStyleSetting right) | ||
=> left.Severity == right.Severity && | ||
AreSameSymbolSpec(left.Type, right.Type) && | ||
AreSameNamingStyle(left.Style, right.Style); | ||
|
||
static bool AreSameSymbolSpec(SymbolSpecification? left, SymbolSpecification? right) | ||
{ | ||
if (left is null && right is null) | ||
{ | ||
return true; | ||
} | ||
|
||
if (left is null || right is null) | ||
{ | ||
return false; | ||
} | ||
|
||
return left.ApplicableSymbolKindList.SequenceEqual(right!.ApplicableSymbolKindList) && | ||
left.ApplicableAccessibilityList.SequenceEqual(right.ApplicableAccessibilityList) && | ||
left.RequiredModifierList.SequenceEqual(right.RequiredModifierList); | ||
} | ||
|
||
static bool AreSameNamingStyle(NamingStyle left, NamingStyle right) | ||
=> left.Prefix == right.Prefix && | ||
left.Suffix == right.Suffix && | ||
left.WordSeparator == right.WordSeparator && | ||
left.CapitalizationScheme == right.CapitalizationScheme; | ||
} | ||
|
||
public static ImmutableArray<(NamingStyleOption namingStyleOption, NamingStyleSetting namingStyleSetting)> AsNamingStyleSettings(this ImmutableArray<NamingStyleOption> namingStyleOptions) | ||
=> namingStyleOptions.SelectAsArray(rule => (rule, NamingStyleSetting.FromParseResult(rule))); | ||
|
||
public static NamingStyle AsNamingStyle(this NamingScheme namingScheme) | ||
=> new( | ||
Guid.NewGuid(), | ||
namingScheme.OptionName, | ||
namingScheme.Prefix, | ||
namingScheme.Suffix, | ||
namingScheme.WordSeparator, | ||
namingScheme.Capitalization); | ||
|
||
public static SymbolSpecification AsSymbolSpecification(this ApplicableSymbolInfo applicableSymbolInfo) | ||
=> new( | ||
Guid.NewGuid(), | ||
applicableSymbolInfo.OptionName, | ||
applicableSymbolInfo.SymbolKinds, | ||
applicableSymbolInfo.Accessibilities, | ||
applicableSymbolInfo.Modifiers); | ||
} | ||
} |
Oops, something went wrong.