未验证 提交 88a07e7e 编写于 作者: S Sam Harwell 提交者: GitHub

Merge pull request #41627 from sharwell/get-option

Update GetOption to return the default option value
......@@ -2,11 +2,14 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Options;
using Roslyn.Utilities;
#if CODE_STYLE
using OptionSet = Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptions;
......@@ -22,20 +25,20 @@ internal abstract class AbstractBuiltInCodeStyleDiagnosticAnalyzer : AbstractCod
/// </summary>
/// <param name="diagnosticId">Diagnostic ID reported by this analyzer</param>
/// <param name="option">
/// Per-language option that can be used to configure the given diagnosticId.
/// Null, if there is no such unique option.
/// Per-language option that can be used to configure the given <paramref name="diagnosticId"/>.
/// <see langword="null"/>, if there is no such unique option.
/// </param>
/// <param name="title">Title for the diagnostic descriptor</param>
/// <param name="messageFormat">
/// Message for the diagnostic descriptor.
/// Null if the message is identical to the title.
/// <see langword="null"/> if the message is identical to the title.
/// </param>
/// <param name="configurable">Flag indicating if the reported diagnostics are configurable by the end users</param>
protected AbstractBuiltInCodeStyleDiagnosticAnalyzer(
string diagnosticId,
IPerLanguageOption option,
IPerLanguageOption? option,
LocalizableString title,
LocalizableString messageFormat = null,
LocalizableString? messageFormat = null,
bool configurable = true)
: base(diagnosticId, title, messageFormat, configurable)
{
......@@ -48,22 +51,22 @@ internal abstract class AbstractBuiltInCodeStyleDiagnosticAnalyzer : AbstractCod
/// </summary>
/// <param name="diagnosticId">Diagnostic ID reported by this analyzer</param>
/// <param name="option">
/// Language specific option that can be used to configure the given diagnosticId.
/// Null, if there is no such unique option.
/// Language specific option that can be used to configure the given <paramref name="diagnosticId"/>.
/// <see langword="null"/>, if there is no such unique option.
/// </param>
/// <param name="language">Language for the given language-specific <paramref name="option"/>.</param>
/// <param name="title">Title for the diagnostic descriptor</param>
/// <param name="messageFormat">
/// Message for the diagnostic descriptor.
/// Null if the message is identical to the title.
/// <see langword="null"/> if the message is identical to the title.
/// </param>
/// <param name="configurable">Flag indicating if the reported diagnostics are configurable by the end users</param>
protected AbstractBuiltInCodeStyleDiagnosticAnalyzer(
string diagnosticId,
ILanguageSpecificOption option,
ILanguageSpecificOption? option,
string language,
LocalizableString title,
LocalizableString messageFormat = null,
LocalizableString? messageFormat = null,
bool configurable = true)
: base(diagnosticId, title, messageFormat, configurable)
{
......@@ -88,11 +91,11 @@ internal abstract class AbstractBuiltInCodeStyleDiagnosticAnalyzer : AbstractCod
string diagnosticId,
ImmutableHashSet<IPerLanguageOption> options,
LocalizableString title,
LocalizableString messageFormat = null,
LocalizableString? messageFormat = null,
bool configurable = true)
: base(diagnosticId, title, messageFormat, configurable)
{
Debug.Assert(options != null);
RoslynDebug.Assert(options != null);
Debug.Assert(options.Count > 1);
AddDiagnosticIdToOptionMapping(diagnosticId, options);
}
......@@ -117,11 +120,11 @@ internal abstract class AbstractBuiltInCodeStyleDiagnosticAnalyzer : AbstractCod
ImmutableHashSet<ILanguageSpecificOption> options,
string language,
LocalizableString title,
LocalizableString messageFormat = null,
LocalizableString? messageFormat = null,
bool configurable = true)
: base(diagnosticId, title, messageFormat, configurable)
{
Debug.Assert(options != null);
RoslynDebug.Assert(options != null);
Debug.Assert(options.Count > 1);
AddDiagnosticIdToOptionMapping(diagnosticId, options, language);
}
......@@ -180,7 +183,7 @@ protected AbstractBuiltInCodeStyleDiagnosticAnalyzer(ImmutableArray<DiagnosticDe
{
}
private static void AddDiagnosticIdToOptionMapping(string diagnosticId, IPerLanguageOption option)
private static void AddDiagnosticIdToOptionMapping(string diagnosticId, IPerLanguageOption? option)
{
if (option != null)
{
......@@ -188,7 +191,7 @@ private static void AddDiagnosticIdToOptionMapping(string diagnosticId, IPerLang
}
}
private static void AddDiagnosticIdToOptionMapping(string diagnosticId, ILanguageSpecificOption option, string language)
private static void AddDiagnosticIdToOptionMapping(string diagnosticId, ILanguageSpecificOption? option, string language)
{
if (option != null)
{
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.Diagnostics;
......@@ -9,7 +11,7 @@ namespace Microsoft.CodeAnalysis.CodeStyle
{
internal abstract class AbstractCodeStyleDiagnosticAnalyzer : DiagnosticAnalyzer
{
protected readonly string DescriptorId;
protected readonly string? DescriptorId;
protected readonly DiagnosticDescriptor Descriptor;
......@@ -17,7 +19,7 @@ internal abstract class AbstractCodeStyleDiagnosticAnalyzer : DiagnosticAnalyzer
/// Diagnostic descriptor for code you want to fade out *and* want to have a smart-tag
/// appear for. This is the common descriptor for code that is being faded out
/// </summary>
protected readonly DiagnosticDescriptor UnnecessaryWithSuggestionDescriptor;
protected readonly DiagnosticDescriptor? UnnecessaryWithSuggestionDescriptor;
/// <summary>
/// Diagnostic descriptor for code you want to fade out and do *not* want to have a smart-tag
......@@ -31,7 +33,7 @@ internal abstract class AbstractCodeStyleDiagnosticAnalyzer : DiagnosticAnalyzer
/// same issue when they bring up the code action on that line. Using these two descriptors
/// helps ensure that there will not be useless code-action overload.
/// </summary>
protected readonly DiagnosticDescriptor UnnecessaryWithoutSuggestionDescriptor;
protected readonly DiagnosticDescriptor? UnnecessaryWithoutSuggestionDescriptor;
protected readonly LocalizableString _localizableTitle;
protected readonly LocalizableString _localizableMessageFormat;
......@@ -40,7 +42,7 @@ internal abstract class AbstractCodeStyleDiagnosticAnalyzer : DiagnosticAnalyzer
protected AbstractCodeStyleDiagnosticAnalyzer(
string descriptorId, LocalizableString title,
LocalizableString messageFormat = null,
LocalizableString? messageFormat = null,
bool configurable = true)
{
DescriptorId = descriptorId;
......@@ -48,8 +50,8 @@ internal abstract class AbstractCodeStyleDiagnosticAnalyzer : DiagnosticAnalyzer
_localizableMessageFormat = messageFormat ?? title;
_configurable = configurable;
Descriptor = CreateDescriptor();
UnnecessaryWithSuggestionDescriptor = CreateUnnecessaryDescriptor();
Descriptor = CreateDescriptorWithId(DescriptorId, _localizableTitle, _localizableMessageFormat);
UnnecessaryWithSuggestionDescriptor = CreateUnnecessaryDescriptor(DescriptorId);
UnnecessaryWithoutSuggestionDescriptor = CreateUnnecessaryDescriptor(descriptorId + "WithoutSuggestion");
SupportedDiagnostics = ImmutableArray.Create(
......@@ -59,10 +61,11 @@ internal abstract class AbstractCodeStyleDiagnosticAnalyzer : DiagnosticAnalyzer
protected AbstractCodeStyleDiagnosticAnalyzer(ImmutableArray<DiagnosticDescriptor> supportedDiagnostics)
{
SupportedDiagnostics = supportedDiagnostics;
}
protected DiagnosticDescriptor CreateUnnecessaryDescriptor()
=> CreateUnnecessaryDescriptor(DescriptorId);
Descriptor = SupportedDiagnostics[0];
_localizableTitle = Descriptor.Title;
_localizableMessageFormat = Descriptor.MessageFormat;
}
protected DiagnosticDescriptor CreateUnnecessaryDescriptor(string descriptorId)
=> CreateDescriptorWithId(
......@@ -71,19 +74,13 @@ protected DiagnosticDescriptor CreateUnnecessaryDescriptor(string descriptorId)
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; }
protected DiagnosticDescriptor CreateDescriptor(params string[] customTags)
=> CreateDescriptorWithId(DescriptorId, _localizableTitle, _localizableMessageFormat, customTags: customTags);
protected DiagnosticDescriptor CreateDescriptorWithTitle(LocalizableString title, params string[] customTags)
=> CreateDescriptorWithId(DescriptorId, title, title, customTags: customTags);
protected static DiagnosticDescriptor CreateDescriptorWithId(
string id,
LocalizableString title,
LocalizableString messageFormat,
bool isUnnecessary = false,
bool isConfigurable = true,
LocalizableString description = null,
LocalizableString? description = null,
params string[] customTags)
=> new DiagnosticDescriptor(
id, title, messageFormat,
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Immutable;
using Roslyn.Utilities;
......@@ -23,9 +25,9 @@ public abstract class DiagnosticAnalyzer
/// <param name="context"></param>
public abstract void Initialize(AnalysisContext context);
public sealed override bool Equals(object obj)
public sealed override bool Equals(object? obj)
{
return (object)this == obj;
return (object?)this == obj;
}
public sealed override int GetHashCode()
......
// 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;
namespace Roslyn.Utilities
{
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.GenericParameter)]
internal sealed class NonDefaultableAttribute : Attribute
{
}
}
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Immutable;
using System.Composition;
using Microsoft.CodeAnalysis.Options;
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Immutable;
using System.Composition;
using Microsoft.CodeAnalysis.Options;
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Immutable;
using System.Composition;
using Microsoft.CodeAnalysis.Options;
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Immutable;
using System.Composition;
using Microsoft.CodeAnalysis.Options;
......
......@@ -2,11 +2,12 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Immutable;
using System.Composition;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Options.Providers;
using Microsoft.CodeAnalysis.Utilities;
namespace Microsoft.CodeAnalysis.Editor.Shared.Options
{
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Generic;
#if DEBUG
using System.Diagnostics;
......@@ -100,7 +102,7 @@ internal abstract partial class AbstractAsynchronousTaggerProvider<TTag> : Foreg
#endif
}
internal IAccurateTagger<T> CreateTaggerWorker<T>(ITextView textViewOpt, ITextBuffer subjectBuffer) where T : ITag
internal IAccurateTagger<T>? CreateTaggerWorker<T>(ITextView textViewOpt, ITextBuffer subjectBuffer) where T : ITag
{
if (!subjectBuffer.GetFeatureOnOffOption(EditorComponentOnOffOptions.Tagger))
{
......@@ -252,11 +254,11 @@ private struct DiffResult
public NormalizedSnapshotSpanCollection Removed { get; }
public DiffResult(List<SnapshotSpan> added, List<SnapshotSpan> removed)
: this(added?.Count == 0 ? null : (IEnumerable<SnapshotSpan>)added, removed?.Count == 0 ? null : (IEnumerable<SnapshotSpan>)removed)
: this(added?.Count == 0 ? null : (IEnumerable<SnapshotSpan>?)added, removed?.Count == 0 ? null : (IEnumerable<SnapshotSpan>?)removed)
{
}
public DiffResult(IEnumerable<SnapshotSpan> added, IEnumerable<SnapshotSpan> removed)
public DiffResult(IEnumerable<SnapshotSpan>? added, IEnumerable<SnapshotSpan>? removed)
{
Added = added != null ? new NormalizedSnapshotSpanCollection(added) : NormalizedSnapshotSpanCollection.Empty;
Removed = removed != null ? new NormalizedSnapshotSpanCollection(removed) : NormalizedSnapshotSpanCollection.Empty;
......
......@@ -12,6 +12,7 @@
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.UseInferredMemberName;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.UseInferredMemberName
{
......@@ -61,6 +62,7 @@ private void ReportDiagnosticsIfNeeded(NameColonSyntax nameColon, SyntaxNodeAnal
properties: null));
// Also fade out the part of the name-colon syntax
RoslynDebug.AssertNotNull(UnnecessaryWithoutSuggestionDescriptor);
var fadeSpan = TextSpan.FromBounds(nameColon.Name.SpanStart, nameColon.ColonToken.Span.End);
context.ReportDiagnostic(
Diagnostic.Create(
......@@ -93,6 +95,7 @@ private void ReportDiagnosticsIfNeeded(NameEqualsSyntax nameEquals, SyntaxNodeAn
properties: null));
// Also fade out the part of the name-equals syntax
RoslynDebug.AssertNotNull(UnnecessaryWithoutSuggestionDescriptor);
var fadeSpan = TextSpan.FromBounds(nameEquals.Name.SpanStart, nameEquals.EqualsToken.Span.End);
context.ReportDiagnostic(
Diagnostic.Create(
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Generic;
using Microsoft.CodeAnalysis.Options;
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using Microsoft.CodeAnalysis.Options;
namespace Microsoft.CodeAnalysis.ExtractMethod
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using Microsoft.CodeAnalysis.Options;
namespace Microsoft.CodeAnalysis.GenerateConstructorFromMembers
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using Microsoft.CodeAnalysis.Options;
namespace Microsoft.CodeAnalysis.GenerateEqualsAndGetHashCodeFromMembers
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using Microsoft.CodeAnalysis.Options;
namespace Microsoft.CodeAnalysis.ImplementType
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Collections.Immutable;
using System.Threading;
......
......@@ -10,6 +10,7 @@
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.RemoveUnnecessaryCast
{
......@@ -65,6 +66,7 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context)
return null;
}
RoslynDebug.AssertNotNull(UnnecessaryWithSuggestionDescriptor);
return Diagnostic.Create(
UnnecessaryWithSuggestionDescriptor,
node.SyntaxTree.GetLocation(GetFadeSpan(node)),
......
using System;
// 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.
#nullable enable
using System;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.SolutionCrawler;
......
......@@ -13,6 +13,7 @@
using Microsoft.CodeAnalysis.QualifyMemberAccess;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.SimplifyThisOrMe
{
......@@ -96,12 +97,8 @@ private void AnalyzeNode(SyntaxNodeAnalysisContext context)
var severity = optionValue.Notification.Severity;
RoslynDebug.AssertNotNull(DescriptorId);
var descriptor = CreateUnnecessaryDescriptor(DescriptorId);
if (descriptor == null)
{
return;
}
var tree = model.SyntaxTree;
var builder = ImmutableDictionary.CreateBuilder<string, string>();
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using Microsoft.CodeAnalysis.Options;
namespace Microsoft.CodeAnalysis.Structure
......
......@@ -6,11 +6,11 @@
using System.Collections;
using System.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.UseCollectionInitializer
{
......@@ -148,9 +148,11 @@ private void AnalyzeNode(SyntaxNodeAnalysisContext context, INamedTypeSymbol ien
var location1 = Location.Create(syntaxTree, TextSpan.FromBounds(
match.SpanStart, arguments[0].SpanStart));
RoslynDebug.AssertNotNull(UnnecessaryWithSuggestionDescriptor);
context.ReportDiagnostic(Diagnostic.Create(
UnnecessaryWithSuggestionDescriptor, location1, additionalLocations: locations));
RoslynDebug.AssertNotNull(UnnecessaryWithoutSuggestionDescriptor);
context.ReportDiagnostic(Diagnostic.Create(
UnnecessaryWithoutSuggestionDescriptor,
Location.Create(syntaxTree, TextSpan.FromBounds(
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.Diagnostics;
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using Microsoft.CodeAnalysis.Options;
namespace Microsoft.CodeAnalysis.UseConditionalExpression
......
......@@ -11,6 +11,7 @@
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.UseObjectInitializer
{
......@@ -125,11 +126,13 @@ private void AnalyzeNode(SyntaxNodeAnalysisContext context)
var location1 = Location.Create(syntaxTree, TextSpan.FromBounds(
match.MemberAccessExpression.SpanStart, end));
RoslynDebug.AssertNotNull(UnnecessaryWithSuggestionDescriptor);
context.ReportDiagnostic(Diagnostic.Create(
UnnecessaryWithSuggestionDescriptor, location1, additionalLocations: locations));
if (match.Statement.Span.End > match.Initializer.FullSpan.End)
{
RoslynDebug.AssertNotNull(UnnecessaryWithoutSuggestionDescriptor);
context.ReportDiagnostic(Diagnostic.Create(
UnnecessaryWithoutSuggestionDescriptor,
Location.Create(syntaxTree, TextSpan.FromBounds(
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Immutable;
using System.Composition;
using Microsoft.CodeAnalysis.Options;
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using Microsoft.CodeAnalysis.Options;
namespace Microsoft.CodeAnalysis.ExternalAccess.FSharp.Completion
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.SolutionCrawler;
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using Microsoft.CodeAnalysis.Options;
namespace Microsoft.VisualStudio.LanguageServices.Implementation
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Immutable;
using System.Diagnostics;
using Microsoft.CodeAnalysis.Options;
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.Options;
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Immutable;
using System.Composition;
using Microsoft.CodeAnalysis.Options;
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
......@@ -20,10 +22,10 @@ internal static partial class EditorConfigNamingStyleParser
// TODO: revisit this cache. The assumption that the dictionary doesn't change in the exact instance is terribly fragile,
// and with the new .editorconfig support won't hold as well as we'd like: a single tree will have a stable instance but
// that won't necessarily be the same across files and projects.
private static readonly ConditionalWeakTable<IReadOnlyDictionary<string, string>, NamingStylePreferences> _cache = new ConditionalWeakTable<IReadOnlyDictionary<string, string>, NamingStylePreferences>();
private static readonly ConditionalWeakTable<IReadOnlyDictionary<string, string?>, NamingStylePreferences> _cache = new ConditionalWeakTable<IReadOnlyDictionary<string, string?>, NamingStylePreferences>();
private static readonly object _cacheLock = new object();
public static NamingStylePreferences GetNamingStylesFromDictionary(IReadOnlyDictionary<string, string> rawOptions)
public static NamingStylePreferences GetNamingStylesFromDictionary(IReadOnlyDictionary<string, string?> rawOptions)
{
if (_cache.TryGetValue(rawOptions, out var value))
{
......@@ -42,7 +44,7 @@ public static NamingStylePreferences GetNamingStylesFromDictionary(IReadOnlyDict
}
}
public static NamingStylePreferences ParseDictionary(IReadOnlyDictionary<string, string> allRawConventions)
public static NamingStylePreferences ParseDictionary(IReadOnlyDictionary<string, string?> allRawConventions)
{
var symbolSpecifications = ArrayBuilder<SymbolSpecification>.GetInstance();
var namingStyles = ArrayBuilder<NamingStyle>.GetInstance();
......@@ -127,14 +129,14 @@ public static NamingStylePreferences ParseDictionary(IReadOnlyDictionary<string,
}));
}
private static Dictionary<string, string> TrimDictionary(IReadOnlyDictionary<string, string> allRawConventions)
private static Dictionary<string, string?> TrimDictionary(IReadOnlyDictionary<string, string?> allRawConventions)
{
// Keys have been lowercased, but values have not. Because values here reference key
// names we need any comparisons to ignore case.
// For example, to make a naming style called "Pascal_Case_style" match up correctly
// with the key "dotnet_naming_style.pascal_case_style.capitalization", we have to
// ignore casing for that lookup.
var trimmedDictionary = new Dictionary<string, string>(allRawConventions.Count, AnalyzerConfigOptions.KeyComparer);
var trimmedDictionary = new Dictionary<string, string?>(allRawConventions.Count, AnalyzerConfigOptions.KeyComparer);
foreach (var item in allRawConventions)
{
var key = item.Key.Trim();
......@@ -145,7 +147,7 @@ public static NamingStylePreferences ParseDictionary(IReadOnlyDictionary<string,
return trimmedDictionary;
}
private static IEnumerable<string> GetRuleTitles(IReadOnlyDictionary<string, string> allRawConventions)
private static IEnumerable<string> GetRuleTitles(IReadOnlyDictionary<string, string?> allRawConventions)
=> (from kvp in allRawConventions
where kvp.Key.Trim().StartsWith("dotnet_naming_rule.", StringComparison.Ordinal)
let nameSplit = kvp.Key.Split('.')
......
......@@ -27,13 +27,11 @@ internal DocumentOptionSet(OptionSet backingOptionSet, string language)
_language = language;
}
[return: MaybeNull]
public override object GetOption(OptionKey optionKey)
public override object? GetOption(OptionKey optionKey)
{
return _backingOptionSet.GetOption(optionKey);
}
[return: MaybeNull]
public T GetOption<T>(PerLanguageOption<T> option)
{
return _backingOptionSet.GetOption(option, _language);
......
......@@ -11,6 +11,7 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.ErrorLogger;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Options.EditorConfig
{
......@@ -83,7 +84,7 @@ public bool TryGetDocumentOption(OptionKey option, out object? value)
try
{
return editorConfigPersistence.TryGetOption(_options, option.Option.Type, out value);
return editorConfigPersistence.TryGetOption(_options.AsNullable(), option.Option.Type, out value);
}
catch (Exception ex)
{
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using Microsoft.CodeAnalysis.CodeStyle;
......
......@@ -2,9 +2,12 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
#if CODE_STYLE
......@@ -21,7 +24,7 @@ internal sealed class EditorConfigStorageLocation<T> : OptionStorageLocation, IE
public string KeyName { get; }
private readonly Func<string, Type, Optional<T>> _parseValue;
private readonly Func<T, OptionSet, string> _getEditorConfigStringForValue;
private readonly Func<T, OptionSet, string?> _getEditorConfigStringForValue;
public EditorConfigStorageLocation(string keyName, Func<string, Optional<T>> parseValue, Func<T, string> getEditorConfigStringForValue)
: this(keyName, parseValue, (value, optionSet) => getEditorConfigStringForValue(value))
......@@ -56,9 +59,10 @@ public EditorConfigStorageLocation(string keyName, Func<string, Optional<T>> par
_getEditorConfigStringForValue = getEditorConfigStringForValue ?? throw new ArgumentNullException(nameof(getEditorConfigStringForValue));
}
public bool TryGetOption(IReadOnlyDictionary<string, string> rawOptions, Type type, out object result)
public bool TryGetOption(IReadOnlyDictionary<string, string?> rawOptions, Type type, out object? result)
{
if (rawOptions.TryGetValue(KeyName, out var value))
if (rawOptions.TryGetValue(KeyName, out var value)
&& value is object)
{
var ret = TryGetOption(value, type, out var typedResult);
result = typedResult;
......@@ -69,7 +73,7 @@ public bool TryGetOption(IReadOnlyDictionary<string, string> rawOptions, Type ty
return false;
}
internal bool TryGetOption(string value, Type type, out T result)
internal bool TryGetOption(string value, Type type, [MaybeNullWhen(false)] out T result)
{
var optionalValue = _parseValue(value, type);
if (optionalValue.HasValue)
......@@ -79,7 +83,7 @@ internal bool TryGetOption(string value, Type type, out T result)
}
else
{
result = default;
result = default!;
return false;
}
}
......@@ -95,7 +99,7 @@ public string GetEditorConfigString(T value, OptionSet optionSet)
return $"{KeyName} = {editorConfigStringForValue}";
}
string IEditorConfigStorageLocation2.GetEditorConfigString(object value, OptionSet optionSet)
=> GetEditorConfigString((T)value, optionSet);
string IEditorConfigStorageLocation2.GetEditorConfigString(object? value, OptionSet optionSet)
=> GetEditorConfigString((T)value!, optionSet);
}
}
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Collections.Generic;
......@@ -9,6 +11,6 @@ namespace Microsoft.CodeAnalysis.Options
{
internal interface IEditorConfigStorageLocation
{
bool TryGetOption(IReadOnlyDictionary<string, string> rawOptions, Type type, out object value);
bool TryGetOption(IReadOnlyDictionary<string, string?> rawOptions, Type type, out object? value);
}
}
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
#if CODE_STYLE
using OptionSet = Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptions;
#endif
......@@ -15,6 +17,6 @@ internal interface IEditorConfigStorageLocation2 : IEditorConfigStorageLocation
/// <summary>
/// Gets the editorconfig string representation for this storage location.
/// </summary>
string GetEditorConfigString(object value, OptionSet optionSet);
string GetEditorConfigString(object? value, OptionSet optionSet);
}
}
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
......@@ -12,7 +14,7 @@ namespace Microsoft.CodeAnalysis.Options
{
internal sealed class NamingStylePreferenceEditorConfigStorageLocation : OptionStorageLocation, IEditorConfigStorageLocation
{
public bool TryGetOption(IReadOnlyDictionary<string, string> rawOptions, Type type, out object result)
public bool TryGetOption(IReadOnlyDictionary<string, string?> rawOptions, Type type, out object result)
{
var tuple = ParseDictionary(rawOptions, type);
result = tuple.result;
......@@ -20,7 +22,7 @@ public bool TryGetOption(IReadOnlyDictionary<string, string> rawOptions, Type ty
}
private static (object result, bool succeeded) ParseDictionary(
IReadOnlyDictionary<string, string> allRawConventions, Type type)
IReadOnlyDictionary<string, string?> allRawConventions, Type type)
{
if (type == typeof(NamingStylePreferences))
{
......
......@@ -250,13 +250,11 @@ public SerializableOptionSet GetSerializableOptionsSnapshot(ImmutableHashSet<str
}
}
[return: MaybeNull]
public T GetOption<T>(Option<T> option)
{
return (T)GetOption(new OptionKey(option))!;
}
[return: MaybeNull]
public T GetOption<T>(PerLanguageOption<T> option, string? language)
{
return (T)GetOption(new OptionKey(option, language))!;
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
namespace Microsoft.CodeAnalysis.Options
{
/// <summary>
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
namespace Microsoft.CodeAnalysis.Options
{
/// <summary>
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
namespace Microsoft.CodeAnalysis.Options
{
/// <summary>
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
namespace Microsoft.CodeAnalysis.Options
......
......@@ -2,7 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using Roslyn.Utilities;
#if CODE_STYLE
using WorkspacesResources = Microsoft.CodeAnalysis.CodeStyleResources;
......@@ -10,12 +13,13 @@
namespace Microsoft.CodeAnalysis.Options
{
[NonDefaultable]
public readonly struct OptionKey : IEquatable<OptionKey>
{
public IOption Option { get; }
public string Language { get; }
public string? Language { get; }
public OptionKey(IOption option, string language = null)
public OptionKey(IOption option, string? language = null)
{
if (language != null && !option.IsPerLanguage)
{
......@@ -30,7 +34,7 @@ public OptionKey(IOption option, string language = null)
this.Language = language;
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return obj is OptionKey key &&
Equals(key);
......
......@@ -7,7 +7,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Microsoft.CodeAnalysis.Options
......@@ -24,23 +23,21 @@ public abstract partial class OptionSet
private ImmutableDictionary<string, AnalyzerConfigOptions> _lazyAnalyzerConfigOptions = s_emptyAnalyzerConfigOptions;
/// <summary>
/// Gets the value of the option.
/// Gets the value of the option, or the default value if not otherwise set.
/// </summary>
public abstract object? GetOption(OptionKey optionKey);
/// <summary>
/// Gets the value of the option.
/// Gets the value of the option, or the default value if not otherwise set.
/// </summary>
[return: MaybeNull]
public T GetOption<T>(Option<T> option)
{
return (T)GetOption(new OptionKey(option, language: null))!;
}
/// <summary>
/// Gets the value of the option.
/// Gets the value of the option, or the default value if not otherwise set.
/// </summary>
[return: MaybeNull]
public T GetOption<T>(PerLanguageOption<T> option, string? language)
{
return (T)GetOption(new OptionKey(option, language))!;
......@@ -54,7 +51,7 @@ public T GetOption<T>(PerLanguageOption<T> option, string? language)
/// <summary>
/// Creates a new <see cref="OptionSet" /> that contains the changed value.
/// </summary>
public OptionSet WithChangedOption<T>(Option<T> option, [MaybeNull] T value)
public OptionSet WithChangedOption<T>(Option<T> option, T value)
{
return WithChangedOption(new OptionKey(option), value);
}
......@@ -62,7 +59,7 @@ public OptionSet WithChangedOption<T>(Option<T> option, [MaybeNull] T value)
/// <summary>
/// Creates a new <see cref="OptionSet" /> that contains the changed value.
/// </summary>
public OptionSet WithChangedOption<T>(PerLanguageOption<T> option, string? language, [MaybeNull] T value)
public OptionSet WithChangedOption<T>(PerLanguageOption<T> option, string? language, T value)
{
return WithChangedOption(new OptionKey(option, language), value);
}
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
namespace Microsoft.CodeAnalysis.Options
{
/// <summary>
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Collections.Immutable;
......@@ -46,8 +48,9 @@ public class Option<T> : ILanguageSpecificOption
public ImmutableArray<OptionStorageLocation> StorageLocations { get; }
[Obsolete("Use a constructor that specifies an explicit default value.")]
public Option(string feature, string name)
: this(feature, name, default)
: this(feature, name, default!)
{
// This constructor forwards to the next one; it exists to maintain source-level compatibility with older callers.
}
......@@ -81,7 +84,7 @@ internal Option(string feature, OptionGroup group, string name, T defaultValue,
this.StorageLocations = storageLocations.ToImmutableArray();
}
object IOption.DefaultValue => this.DefaultValue;
object? IOption.DefaultValue => this.DefaultValue;
bool IOption.IsPerLanguage => false;
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Collections.Immutable;
......@@ -76,7 +78,7 @@ internal PerLanguageOption(string feature, OptionGroup group, string name, T def
this.StorageLocations = storageLocations.ToImmutableArray();
}
object IOption.DefaultValue => this.DefaultValue;
object? IOption.DefaultValue => this.DefaultValue;
bool IOption.IsPerLanguage => true;
......
using System;
using System.Collections.Generic;
using System.Text;
// 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.
#nullable enable
namespace Microsoft.CodeAnalysis.Options
{
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Immutable;
namespace Microsoft.CodeAnalysis.Options.Providers
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
namespace Microsoft.CodeAnalysis.Options
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using Microsoft.CodeAnalysis.Options;
namespace Microsoft.CodeAnalysis.Recommendations
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles;
using Microsoft.CodeAnalysis.Options;
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using Microsoft.CodeAnalysis.Options;
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using Microsoft.CodeAnalysis.Options;
namespace Microsoft.CodeAnalysis.SymbolSearch
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis.CodeStyle;
......@@ -81,10 +83,10 @@ public void TestParseEditorConfigAccessibilityModifiers(string args, int value,
var storageLocation = CodeStyleOptions.RequireAccessibilityModifiers.StorageLocations
.OfType<EditorConfigStorageLocation<CodeStyleOption<AccessibilityModifiersRequired>>>()
.Single();
var allRawConventions = new Dictionary<string, string> { { storageLocation.KeyName, args } };
var allRawConventions = new Dictionary<string, string?> { { storageLocation.KeyName, args } };
Assert.True(storageLocation.TryGetOption(allRawConventions, typeof(CodeStyleOption<AccessibilityModifiersRequired>), out var parsedCodeStyleOption));
var codeStyleOption = (CodeStyleOption<AccessibilityModifiersRequired>)parsedCodeStyleOption;
var codeStyleOption = (CodeStyleOption<AccessibilityModifiersRequired>)parsedCodeStyleOption!;
Assert.Equal((AccessibilityModifiersRequired)value, codeStyleOption.Value);
Assert.Equal(severity, codeStyleOption.Notification.Severity);
}
......@@ -103,10 +105,10 @@ public void TestParseEditorConfigEndOfLine(string configurationString, string ne
var storageLocation = FormattingOptions.NewLine.StorageLocations
.OfType<EditorConfigStorageLocation<string>>()
.Single();
var allRawConventions = new Dictionary<string, string> { { storageLocation.KeyName, configurationString } };
var allRawConventions = new Dictionary<string, string?> { { storageLocation.KeyName, configurationString } };
Assert.True(storageLocation.TryGetOption(allRawConventions, typeof(string), out var parsedNewLine));
Assert.Equal(newLine, (string)parsedNewLine);
Assert.Equal(newLine, (string?)parsedNewLine);
}
}
}
......@@ -2,6 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using Microsoft.CodeAnalysis.Options;
using Xunit;
......@@ -10,7 +13,8 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Options
public class OptionKeyTests
{
[Fact]
public void ToStringForOption()
[Obsolete]
public void ToStringForObsoleteOption()
{
var option = new Option<bool>("FooFeature", "BarName");
var optionKey = new OptionKey(option);
......@@ -20,6 +24,17 @@ public void ToStringForOption()
Assert.Equal("FooFeature - BarName", toStringResult);
}
[Fact]
public void ToStringForOption()
{
var option = new Option<bool>("FooFeature", "BarName", false);
var optionKey = new OptionKey(option);
var toStringResult = optionKey.ToString();
Assert.Equal("FooFeature - BarName", toStringResult);
}
[Fact]
public void ToStringForPerLanguageOption()
{
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Test.Utilities;
using Xunit;
......@@ -24,7 +26,7 @@ public void OptionWithNullOrWhitespace()
Assert.Throws<System.ArgumentException>(delegate
{
var option2 = new Option<bool>("Test Feature", null, false);
var option2 = new Option<bool>("Test Feature", null!, false);
});
Assert.Throws<System.ArgumentNullException>(delegate
......@@ -34,7 +36,7 @@ public void OptionWithNullOrWhitespace()
Assert.Throws<System.ArgumentNullException>(delegate
{
var option4 = new Option<bool>(null, "Test Name", false);
var option4 = new Option<bool>(null!, "Test Name", false);
});
}
......@@ -51,7 +53,7 @@ public void OptionPerLanguageOption()
Assert.Throws<System.ArgumentException>(delegate
{
var option2 = new PerLanguageOption<bool>("Test Feature", null, false);
var option2 = new PerLanguageOption<bool>("Test Feature", null!, false);
});
Assert.Throws<System.ArgumentNullException>(delegate
......@@ -61,7 +63,7 @@ public void OptionPerLanguageOption()
Assert.Throws<System.ArgumentNullException>(delegate
{
var option4 = new PerLanguageOption<bool>(null, "Test Name", false);
var option4 = new PerLanguageOption<bool>(null!, "Test Name", false);
});
var optionvalid = new PerLanguageOption<bool>("Test Feature", "Test Name", false);
......@@ -86,7 +88,7 @@ public void GettingOptionWithChangedOption()
var key = new OptionKey(option);
Assert.False(optionSet.GetOption(option));
optionSet = optionSet.WithChangedOption(key, true);
Assert.True((bool)optionSet.GetOption(key));
Assert.True((bool?)optionSet.GetOption(key));
}
[Fact, Trait(Traits.Feature, Traits.Features.Workspace)]
......@@ -102,10 +104,10 @@ public void GettingOptionWithoutChangedOption()
Assert.True(optionSet.GetOption(optionTrue));
var falseKey = new OptionKey(optionFalse);
Assert.False((bool)optionSet.GetOption(falseKey));
Assert.False((bool?)optionSet.GetOption(falseKey));
var trueKey = new OptionKey(optionTrue);
Assert.True((bool)optionSet.GetOption(trueKey));
Assert.True((bool?)optionSet.GetOption(trueKey));
}
[Fact, Trait(Traits.Feature, Traits.Features.Workspace)]
......@@ -129,7 +131,7 @@ public void GetKnownOptionsKey()
var optionSet = optionService.GetOptions();
var optionKey = new OptionKey(option);
var value = (bool)optionSet.GetOption(optionKey);
var value = (bool?)optionSet.GetOption(optionKey);
Assert.True(value);
}
......@@ -143,7 +145,7 @@ public void SetKnownOptions()
var optionKey = new OptionKey(option);
var newOptionSet = optionSet.WithChangedOption(optionKey, false);
optionService.SetOptions(newOptionSet);
var isOptionSet = (bool)optionService.GetOptions().GetOption(optionKey);
var isOptionSet = (bool?)optionService.GetOptions().GetOption(optionKey);
Assert.False(isOptionSet);
}
......
......@@ -14,6 +14,7 @@
<Compile Include="$(MSBuildThisFileDirectory)..\..\..\..\Compilers\Core\Portable\InternalUtilities\ExceptionUtilities.cs" Link="InternalUtilities\ExceptionUtilities.cs" />
<Compile Include="$(MSBuildThisFileDirectory)..\..\..\..\Compilers\Core\Portable\InternalUtilities\IReadOnlySet.cs" Link="InternalUtilities\IReadOnlySet.cs" />
<Compile Include="$(MSBuildThisFileDirectory)..\..\..\..\Compilers\Core\Portable\InternalUtilities\KeyValuePairUtil.cs" Link="InternalUtilities\KeyValuePairUtil.cs" />
<Compile Include="$(MSBuildThisFileDirectory)..\..\..\..\Compilers\Core\Portable\InternalUtilities\NonDefaultableAttribute.cs" Link="InternalUtilities\NonDefaultableAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)..\..\..\..\Compilers\Core\Portable\InternalUtilities\NullableAttributes.cs" Link="InternalUtilities\NullableAttributes.cs" />
<Compile Include="$(MSBuildThisFileDirectory)..\..\..\..\Compilers\Core\Portable\InternalUtilities\ReferenceEqualityComparer.cs" Link="InternalUtilities\ReferenceEqualityComparer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)..\..\..\..\Compilers\Core\Portable\InternalUtilities\RoslynString.cs" Link="InternalUtilities\RoslynString.cs" />
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using Microsoft.CodeAnalysis.Options;
namespace Microsoft.CodeAnalysis.Fading
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.Options;
......@@ -97,7 +99,7 @@ private static Optional<string> ParseEditorConfigEndOfLine(string endOfLineValue
=> s_parenthesesPreferenceMap.TryGetValue(endOfLineValue.Trim(), out var parsedOption) ? parsedOption : NewLine.DefaultValue;
private static string GetEndOfLineEditorConfigString(string option)
=> s_parenthesesPreferenceMap.TryGetKey(option, out var editorConfigString) ? editorConfigString : null;
=> s_parenthesesPreferenceMap.TryGetKey(option, out var editorConfigString) ? editorConfigString : "unset";
internal static Option<bool> AllowDisjointSpanMerging { get; } = CreateOption(OptionGroup.Default, nameof(AllowDisjointSpanMerging), defaultValue: false);
......
......@@ -32,5 +32,13 @@ public static IEnumerable<T> GetEnumerableMetadata<T>(this IReadOnlyDictionary<s
default: return SpecializedCollections.EmptyEnumerable<T>();
}
}
public static IReadOnlyDictionary<TKey, TValue?> AsNullable<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dictionary)
where TKey : notnull
where TValue : class
{
// this is a safe cast, even though the language doesn't allow the interface to be 'out TValue'
return dictionary!;
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册