diff --git a/src/CodeStyle/Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj b/src/CodeStyle/Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj index 5a85fcbdd0abb..53bc8c8dc1a39 100644 --- a/src/CodeStyle/Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj +++ b/src/CodeStyle/Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj @@ -27,12 +27,14 @@ + + diff --git a/src/Compilers/Core/MSBuildTask/Microsoft.Build.Tasks.CodeAnalysis.csproj b/src/Compilers/Core/MSBuildTask/Microsoft.Build.Tasks.CodeAnalysis.csproj index 0efb1b2363aae..36b716e8cb01b 100644 --- a/src/Compilers/Core/MSBuildTask/Microsoft.Build.Tasks.CodeAnalysis.csproj +++ b/src/Compilers/Core/MSBuildTask/Microsoft.Build.Tasks.CodeAnalysis.csproj @@ -39,8 +39,10 @@ + + True diff --git a/src/Compilers/Core/Portable/Collections/ArrayBuilderExtensions.cs b/src/Compilers/Core/Portable/Collections/ArrayBuilderExtensions.cs index 9163eaa0a7f60..b87904c71a651 100644 --- a/src/Compilers/Core/Portable/Collections/ArrayBuilderExtensions.cs +++ b/src/Compilers/Core/Portable/Collections/ArrayBuilderExtensions.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Immutable; using Microsoft.CodeAnalysis.PooledObjects; @@ -134,7 +136,7 @@ public static ImmutableArray SelectAsArray(this A } } - public static void AddOptional(this ArrayBuilder builder, T item) + public static void AddOptional(this ArrayBuilder builder, T? item) where T : class { if (item != null) @@ -163,9 +165,9 @@ public static T Peek(this ArrayBuilder builder) return builder[builder.Count - 1]; } - public static ImmutableArray ToImmutableOrEmptyAndFree(this ArrayBuilder builderOpt) + public static ImmutableArray ToImmutableOrEmptyAndFree(this ArrayBuilder? builder) { - return builderOpt?.ToImmutableAndFree() ?? ImmutableArray.Empty; + return builder?.ToImmutableAndFree() ?? ImmutableArray.Empty; } public static void AddIfNotNull(this ArrayBuilder builder, T? value) @@ -177,7 +179,7 @@ public static void AddIfNotNull(this ArrayBuilder builder, T? value) } } - public static void AddIfNotNull(this ArrayBuilder builder, T value) + public static void AddIfNotNull(this ArrayBuilder builder, T? value) where T : class { if (value != null) @@ -186,6 +188,7 @@ public static void AddIfNotNull(this ArrayBuilder builder, T value) } } +#nullable disable public static void FreeAll(this ArrayBuilder builder, Func> getNested) { foreach (var item in builder) @@ -194,5 +197,6 @@ public static void FreeAll(this ArrayBuilder builder, Func element) // as JIT does not know if the write goes to a stack or a heap location. // Assigning to Value directly easily avoids all this redundancy. - public static ArrayElement[] MakeElementArray(T[] items) + [return: NotNullIfNotNull(parameterName: "items")] + public static ArrayElement[]? MakeElementArray(T[]? items) { if (items == null) { @@ -41,7 +45,8 @@ public static ArrayElement[] MakeElementArray(T[] items) return array; } - public static T[] MakeArray(ArrayElement[] items) + [return: NotNullIfNotNull(parameterName: "items")] + public static T[]? MakeArray(ArrayElement[]? items) { if (items == null) { diff --git a/src/Compilers/Core/Portable/Collections/Boxes.cs b/src/Compilers/Core/Portable/Collections/Boxes.cs index f116799df0d32..e96e930dabc0a 100644 --- a/src/Compilers/Core/Portable/Collections/Boxes.cs +++ b/src/Compilers/Core/Portable/Collections/Boxes.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; namespace Microsoft.CodeAnalysis @@ -21,7 +23,7 @@ internal static class Boxes public static readonly object BoxedDoubleZero = 0.0; public static readonly object BoxedDecimalZero = 0m; - private static readonly object[] s_boxedAsciiChars = new object[128]; + private static readonly object?[] s_boxedAsciiChars = new object?[128]; public static object Box(bool b) { diff --git a/src/Compilers/Core/Portable/Collections/ByteSequenceComparer.cs b/src/Compilers/Core/Portable/Collections/ByteSequenceComparer.cs index b3180b9ae077b..2d030dfd742f6 100644 --- a/src/Compilers/Core/Portable/Collections/ByteSequenceComparer.cs +++ b/src/Compilers/Core/Portable/Collections/ByteSequenceComparer.cs @@ -1,9 +1,12 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; @@ -41,7 +44,7 @@ internal static bool Equals(ImmutableArray x, ImmutableArray y) return true; } - internal static bool Equals(byte[] left, int leftStart, byte[] right, int rightStart, int length) + internal static bool Equals(byte[]? left, int leftStart, byte[]? right, int rightStart, int length) { if (left == null || right == null) { @@ -64,7 +67,7 @@ internal static bool Equals(byte[] left, int leftStart, byte[] right, int rightS return true; } - internal static bool Equals(byte[] left, byte[] right) + internal static bool Equals(byte[]? left, byte[]? right) { if (ReferenceEquals(left, right)) { @@ -91,7 +94,7 @@ internal static bool Equals(byte[] left, byte[] right) internal static int GetHashCode(byte[] x) { - Debug.Assert(x != null); + RoslynDebug.Assert(x != null); return Hash.GetFNVHashCode(x); } @@ -101,7 +104,7 @@ internal static int GetHashCode(ImmutableArray x) return Hash.GetFNVHashCode(x); } - bool IEqualityComparer.Equals(byte[] x, byte[] y) + bool IEqualityComparer.Equals(byte[]? x, byte[]? y) { return Equals(x, y); } diff --git a/src/Compilers/Core/Portable/Collections/CachingDictionary.cs b/src/Compilers/Core/Portable/Collections/CachingDictionary.cs index c0d94d17afa33..26557fbd859ab 100644 --- a/src/Compilers/Core/Portable/Collections/CachingDictionary.cs +++ b/src/Compilers/Core/Portable/Collections/CachingDictionary.cs @@ -1,10 +1,13 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Threading; using Microsoft.CodeAnalysis.PooledObjects; @@ -25,6 +28,7 @@ namespace Microsoft.CodeAnalysis.Collections /// Thread safe. /// internal class CachingDictionary + where TKey : notnull { private readonly Func> _getElementsOfKey; private readonly Func, HashSet> _getKeys; @@ -34,7 +38,7 @@ internal class CachingDictionary // or something frozen (usually a regular Dictionary). The frozen Dictionary is used only once the collection // is fully populated. This is a memory optimization so that we don't hold onto relatively ConcurrentDictionary // instances once the cache is fully populated. - private IDictionary> _map; + private IDictionary>? _map; // This is a special sentinel value that is placed inside the map to indicate that a key was looked // up, but not found. @@ -142,7 +146,7 @@ private IDictionary> CreateDictionaryForFullyPopu private ImmutableArray GetOrCreateValue(TKey key) { ImmutableArray elements; - ConcurrentDictionary> concurrentMap; + ConcurrentDictionary>? concurrentMap; // Check if we're fully populated before trying to retrieve the elements. If we are // and we don't get any elements back, then we don't have to go any further. @@ -197,7 +201,7 @@ private ImmutableArray AddToConcurrentMap(ConcurrentDictionary /// The map to test. /// true if the map is fully populated. - private static bool IsNotFullyPopulatedMap(IDictionary> existingMap) + private static bool IsNotFullyPopulatedMap([NotNullWhen(returnValue: false)] IDictionary>? existingMap) { return existingMap == null || existingMap is ConcurrentDictionary>; } @@ -207,7 +211,7 @@ private static bool IsNotFullyPopulatedMap(IDictionary /// The existing map which may be null or a ConcurrentDictionary. /// - private IDictionary> CreateFullyPopulatedMap(IDictionary> existingMap) + private IDictionary> CreateFullyPopulatedMap(IDictionary>? existingMap) { Debug.Assert(IsNotFullyPopulatedMap(existingMap)); @@ -250,7 +254,7 @@ private IDictionary> CreateFullyPopulatedMap(IDic /// private IDictionary> EnsureFullyPopulated() { - IDictionary> fullyPopulatedMap = null; + IDictionary>? fullyPopulatedMap = null; var currentMap = _map; while (IsNotFullyPopulatedMap(currentMap)) diff --git a/src/Compilers/Core/Portable/Collections/ConsListExtensions.cs b/src/Compilers/Core/Portable/Collections/ConsListExtensions.cs index 91eafacb1eec6..b38f872b6643e 100644 --- a/src/Compilers/Core/Portable/Collections/ConsListExtensions.cs +++ b/src/Compilers/Core/Portable/Collections/ConsListExtensions.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; @@ -10,7 +12,7 @@ namespace Microsoft.CodeAnalysis /// internal static class ConsListExtensions { - public static ConsList Prepend(this ConsList list, T head) + public static ConsList Prepend(this ConsList? list, T head) { return new ConsList(head, list ?? ConsList.Empty); } diff --git a/src/Compilers/Core/Portable/Collections/HashSetExtensions.cs b/src/Compilers/Core/Portable/Collections/HashSetExtensions.cs index 52b721789a0dc..7e47f5ad0bdf9 100644 --- a/src/Compilers/Core/Portable/Collections/HashSetExtensions.cs +++ b/src/Compilers/Core/Portable/Collections/HashSetExtensions.cs @@ -1,17 +1,21 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.CodeAnalysis { internal static class HashSetExtensions { - internal static bool IsNullOrEmpty(this HashSet hashSet) + internal static bool IsNullOrEmpty([NotNullWhen(returnValue: false)] this HashSet? hashSet) { return hashSet == null || hashSet.Count == 0; } - internal static bool InitializeAndAdd(ref HashSet hashSet, T item) where T : class + internal static bool InitializeAndAdd([NotNullIfNotNull(parameterName: "item"), NotNullWhen(returnValue: true)] ref HashSet? hashSet, [NotNullWhen(returnValue: true)] T? item) + where T : class { if (item is null) { diff --git a/src/Compilers/Core/Portable/Collections/IOrderedReadOnlySet.cs b/src/Compilers/Core/Portable/Collections/IOrderedReadOnlySet.cs index 4adb4530f1506..72c8df9ae1666 100644 --- a/src/Compilers/Core/Portable/Collections/IOrderedReadOnlySet.cs +++ b/src/Compilers/Core/Portable/Collections/IOrderedReadOnlySet.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Collections.Generic; using Roslyn.Utilities; diff --git a/src/Compilers/Core/Portable/Collections/ImmutableArrayExtensions.cs b/src/Compilers/Core/Portable/Collections/ImmutableArrayExtensions.cs index e7a575337fd72..b61429abf7984 100644 --- a/src/Compilers/Core/Portable/Collections/ImmutableArrayExtensions.cs +++ b/src/Compilers/Core/Portable/Collections/ImmutableArrayExtensions.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Generic; using System.Collections.Immutable; @@ -36,7 +38,7 @@ public static ImmutableArray AsImmutable(this IEnumerable items) /// The sequence to convert. /// An immutable copy of the contents of the sequence. /// If the sequence is null, this will return an empty array. - public static ImmutableArray AsImmutableOrEmpty(this IEnumerable items) + public static ImmutableArray AsImmutableOrEmpty(this IEnumerable? items) { if (items == null) { @@ -53,7 +55,7 @@ public static ImmutableArray AsImmutableOrEmpty(this IEnumerable items) /// The sequence to convert. /// An immutable copy of the contents of the sequence. /// If the sequence is null, this will return the default (null) array. - public static ImmutableArray AsImmutableOrNull(this IEnumerable items) + public static ImmutableArray AsImmutableOrNull(this IEnumerable? items) { if (items == null) { @@ -82,7 +84,7 @@ public static ImmutableArray AsImmutable(this T[] items) /// The sequence to convert /// /// If the sequence is null, this will return the default (null) array. - public static ImmutableArray AsImmutableOrNull(this T[] items) + public static ImmutableArray AsImmutableOrNull(this T[]? items) { if (items == null) { @@ -98,7 +100,7 @@ public static ImmutableArray AsImmutableOrNull(this T[] items) /// /// The sequence to convert /// If the array is null, this will return an empty immutable array. - public static ImmutableArray AsImmutableOrEmpty(this T[] items) + public static ImmutableArray AsImmutableOrEmpty(this T[]? items) { if (items == null) { @@ -260,7 +262,7 @@ public static ImmutableArray WhereAsArray(this ImmutableArray array, Fu { Debug.Assert(!array.IsDefault); - ArrayBuilder builder = null; + ArrayBuilder? builder = null; bool none = true; bool all = true; @@ -391,7 +393,7 @@ public static ImmutableArray NullToEmpty(this ImmutableArray array) /// Returns an array of distinct elements, preserving the order in the original array. /// If the array has no duplicates, the original array is returned. The original array must not be null. /// - public static ImmutableArray Distinct(this ImmutableArray array, IEqualityComparer comparer = null) + public static ImmutableArray Distinct(this ImmutableArray array, IEqualityComparer? comparer = null) { Debug.Assert(!array.IsDefault); @@ -448,7 +450,8 @@ internal static ImmutableArray ConditionallyDeOrder(this ImmutableArray internal static ImmutableArray Flatten( this Dictionary> dictionary, - IComparer comparer = null) + IComparer? comparer = null) + where TKey : notnull { if (dictionary.Count == 0) { @@ -525,7 +528,7 @@ public static int Count(this ImmutableArray items, Func predicate return count; } - internal static Dictionary> ToDictionary(this ImmutableArray items, Func keySelector, IEqualityComparer comparer = null) + internal static Dictionary> ToDictionary(this ImmutableArray items, Func keySelector, IEqualityComparer? comparer = null) { if (items.Length == 1) { diff --git a/src/Compilers/Core/Portable/Collections/KeyedStack.cs b/src/Compilers/Core/Portable/Collections/KeyedStack.cs index 0f7be09dc0805..c3e7299390dab 100644 --- a/src/Compilers/Core/Portable/Collections/KeyedStack.cs +++ b/src/Compilers/Core/Portable/Collections/KeyedStack.cs @@ -1,7 +1,10 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -10,12 +13,13 @@ namespace Microsoft.CodeAnalysis.Collections { internal class KeyedStack + where T : notnull { private readonly Dictionary> _dict = new Dictionary>(); public void Push(T key, R value) { - Stack store; + Stack? store; if (!_dict.TryGetValue(key, out store)) { store = new Stack(); @@ -25,16 +29,16 @@ public void Push(T key, R value) store.Push(value); } - public bool TryPop(T key, out R value) + public bool TryPop(T key, [MaybeNullWhen(returnValue: false)] out R value) { - Stack store; + Stack? store; if (_dict.TryGetValue(key, out store) && store.Count > 0) { value = store.Pop(); return true; } - value = default(R); + value = default(R)!; return false; } } diff --git a/src/Compilers/Core/Portable/Collections/StaticCast.cs b/src/Compilers/Core/Portable/Collections/StaticCast.cs index 2cfb6fce8b981..ce3d40d07bf4a 100644 --- a/src/Compilers/Core/Portable/Collections/StaticCast.cs +++ b/src/Compilers/Core/Portable/Collections/StaticCast.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Collections.Immutable; namespace Microsoft.CodeAnalysis diff --git a/src/Compilers/Core/Portable/Compilation/XmlReferenceResolver.cs b/src/Compilers/Core/Portable/Compilation/XmlReferenceResolver.cs index 3c2047e66d105..9f9d6cd6a67d6 100644 --- a/src/Compilers/Core/Portable/Compilation/XmlReferenceResolver.cs +++ b/src/Compilers/Core/Portable/Compilation/XmlReferenceResolver.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.IO; @@ -14,7 +16,7 @@ protected XmlReferenceResolver() { } - public abstract override bool Equals(object other); + public abstract override bool Equals(object? other); public abstract override int GetHashCode(); /// @@ -23,7 +25,7 @@ protected XmlReferenceResolver() /// The reference path to resolve. May be absolute or relative path. /// Path of the source file that contains the (may also be relative), or null if not available. /// Path to the XML artifact, or null if the file can't be resolved. - public abstract string ResolveReference(string path, string baseFilePath); + public abstract string? ResolveReference(string path, string? baseFilePath); /// /// Opens a that allows reading the content of the specified file. diff --git a/src/Compilers/Core/Portable/DocumentationMode.cs b/src/Compilers/Core/Portable/DocumentationMode.cs index 0e644b4fae11c..40eb83140b897 100644 --- a/src/Compilers/Core/Portable/DocumentationMode.cs +++ b/src/Compilers/Core/Portable/DocumentationMode.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis diff --git a/src/Compilers/Core/Portable/IVTConclusion.cs b/src/Compilers/Core/Portable/IVTConclusion.cs index 84cbb8e366696..ed65fa6e76f8a 100644 --- a/src/Compilers/Core/Portable/IVTConclusion.cs +++ b/src/Compilers/Core/Portable/IVTConclusion.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Collections.Immutable; namespace Microsoft.CodeAnalysis diff --git a/src/Compilers/Core/Portable/InternalUtilities/ArrayExtensions.cs b/src/Compilers/Core/Portable/InternalUtilities/ArrayExtensions.cs index 617f50c70bce9..57c595b66dc8c 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/ArrayExtensions.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/ArrayExtensions.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Diagnostics; diff --git a/src/Compilers/Core/Portable/InternalUtilities/AssemblyIdentityUtils.cs b/src/Compilers/Core/Portable/InternalUtilities/AssemblyIdentityUtils.cs index 31aef7ba6a0b8..affcbd177130b 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/AssemblyIdentityUtils.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/AssemblyIdentityUtils.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Immutable; using System.Reflection; @@ -12,7 +14,7 @@ namespace Microsoft.CodeAnalysis { internal static class AssemblyIdentityUtils { - public static AssemblyIdentity TryGetAssemblyIdentity(string filePath) + public static AssemblyIdentity? TryGetAssemblyIdentity(string filePath) { try { @@ -27,7 +29,7 @@ public static AssemblyIdentity TryGetAssemblyIdentity(string filePath) Version version = assemblyDefinition.Version; StringHandle cultureHandle = assemblyDefinition.Culture; - string cultureName = (!cultureHandle.IsNil) ? metadataReader.GetString(cultureHandle) : null; + string? cultureName = (!cultureHandle.IsNil) ? metadataReader.GetString(cultureHandle) : null; AssemblyFlags flags = assemblyDefinition.Flags; bool hasPublicKey = (flags & AssemblyFlags.PublicKey) != 0; diff --git a/src/Compilers/Core/Portable/InternalUtilities/BitArithmeticUtilities.cs b/src/Compilers/Core/Portable/InternalUtilities/BitArithmeticUtilities.cs index c620827158c75..65cce23989431 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/BitArithmeticUtilities.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/BitArithmeticUtilities.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Diagnostics; namespace Roslyn.Utilities diff --git a/src/Compilers/Core/Portable/InternalUtilities/CharMemoryEqualityComparer.cs b/src/Compilers/Core/Portable/InternalUtilities/CharMemoryEqualityComparer.cs index 5c73939926077..0ae0a69548819 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/CharMemoryEqualityComparer.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/CharMemoryEqualityComparer.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Generic; diff --git a/src/Compilers/Core/Portable/InternalUtilities/CommandLineUtilities.cs b/src/Compilers/Core/Portable/InternalUtilities/CommandLineUtilities.cs index 5a8b91e08a959..8f2be002494bb 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/CommandLineUtilities.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/CommandLineUtilities.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Collections.Generic; using System.Text; diff --git a/src/Compilers/Core/Portable/InternalUtilities/CompilerOptionParseUtilities.cs b/src/Compilers/Core/Portable/InternalUtilities/CompilerOptionParseUtilities.cs index 0a6b572d9df0b..ae3a1d439bad7 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/CompilerOptionParseUtilities.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/CompilerOptionParseUtilities.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Generic; @@ -11,9 +13,9 @@ internal static class CompilerOptionParseUtilities /// Parse the value provided to an MSBuild Feature option into a list of entries. This will /// leave name=value in their raw form. /// - public static IList ParseFeatureFromMSBuild(string features) + public static IList ParseFeatureFromMSBuild(string? features) { - if (string.IsNullOrEmpty(features)) + if (RoslynString.IsNullOrEmpty(features)) { return new List(capacity: 0); } diff --git a/src/Compilers/Core/Portable/InternalUtilities/ConcurrentDictionaryExtensions.cs b/src/Compilers/Core/Portable/InternalUtilities/ConcurrentDictionaryExtensions.cs index 5aa1679ef05c2..9cddc596d154d 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/ConcurrentDictionaryExtensions.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/ConcurrentDictionaryExtensions.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Collections.Concurrent; namespace Roslyn.Utilities @@ -13,6 +15,7 @@ internal static class ConcurrentDictionaryExtensions /// If unsure about adding unique items use APIs such as TryAdd, GetOrAdd, etc... /// public static void Add(this ConcurrentDictionary dict, K key, V value) + where K : notnull { if (!dict.TryAdd(key, value)) { diff --git a/src/Compilers/Core/Portable/InternalUtilities/ConcurrentLruCache.cs b/src/Compilers/Core/Portable/InternalUtilities/ConcurrentLruCache.cs index 45c6043d6cdf5..92b3bcf53d1f5 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/ConcurrentLruCache.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/ConcurrentLruCache.cs @@ -1,8 +1,11 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.CodeAnalysis.InternalUtilities { @@ -11,6 +14,8 @@ namespace Microsoft.CodeAnalysis.InternalUtilities /// Thread-safe. /// internal class ConcurrentLruCache + where K : notnull + where V : notnull { private readonly int _capacity; @@ -157,7 +162,7 @@ public V this[K key] } } - public bool TryGetValue(K key, out V value) + public bool TryGetValue(K key, [MaybeNullWhen(returnValue: false)] out V value) { lock (_lockObject) { @@ -168,7 +173,7 @@ public bool TryGetValue(K key, out V value) /// /// Doesn't lock. /// - public bool UnsafeTryGetValue(K key, out V value) + public bool UnsafeTryGetValue(K key, [MaybeNullWhen(returnValue: false)] out V value) { if (_cache.TryGetValue(key, out var result)) { @@ -178,7 +183,7 @@ public bool UnsafeTryGetValue(K key, out V value) } else { - value = default; + value = default!; return false; } } diff --git a/src/Compilers/Core/Portable/InternalUtilities/ConcurrentSet.cs b/src/Compilers/Core/Portable/InternalUtilities/ConcurrentSet.cs index 302b46a49a41e..c471c4a667e16 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/ConcurrentSet.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/ConcurrentSet.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections; using System.Collections.Concurrent; @@ -13,6 +15,7 @@ namespace Roslyn.Utilities /// [DebuggerDisplay("Count = {Count}")] internal sealed class ConcurrentSet : ICollection + where T : notnull { /// /// The default concurrency level is 2. That means the collection can cope with up to two @@ -82,7 +85,7 @@ public bool Add(T value) return _dictionary.TryAdd(value, 0); } - public void AddRange(IEnumerable values) + public void AddRange(IEnumerable? values) { if (values != null) { diff --git a/src/Compilers/Core/Portable/InternalUtilities/ConsList`1.cs b/src/Compilers/Core/Portable/InternalUtilities/ConsList`1.cs index 4358b91d97237..8646de6ec59ab 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/ConsList`1.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/ConsList`1.cs @@ -1,9 +1,12 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Text; namespace Roslyn.Utilities @@ -15,11 +18,13 @@ internal class ConsList : IEnumerable { public static readonly ConsList Empty = new ConsList(); + [AllowNull, MaybeNull] private readonly T _head; - private readonly ConsList _tail; + private readonly ConsList? _tail; internal struct Enumerator : IEnumerator { + [AllowNull, MaybeNull] private T _current; private ConsList _tail; @@ -34,7 +39,9 @@ public T Current get { Debug.Assert(_tail != null); - return _current; + + // This never returns null after a proper call to `MoveNext` returned true. + return _current!; } } @@ -45,7 +52,9 @@ public bool MoveNext() if (newTail != null) { - _current = currentTail._head; + // Suppress false positive CS8717 reported for MaybeNull assignment to AllowNull + // https://github.com/dotnet/roslyn/issues/38926 + _current = currentTail._head!; _tail = newTail; return true; } @@ -58,7 +67,7 @@ public void Dispose() { } - object IEnumerator.Current + object? IEnumerator.Current { get { @@ -92,7 +101,7 @@ public T Head get { Debug.Assert(this != Empty); - return _head; + return _head!; } } @@ -102,6 +111,7 @@ public ConsList Tail get { Debug.Assert(this != Empty); + RoslynDebug.Assert(_tail is object); return _tail; } } @@ -142,7 +152,7 @@ public override string ToString() result.Append(", "); } - result.Append(list._head); + result.Append(list.Head); any = true; } diff --git a/src/Compilers/Core/Portable/InternalUtilities/DecimalUtilities.cs b/src/Compilers/Core/Portable/InternalUtilities/DecimalUtilities.cs index 9e77c6735c1c4..62fc285951fde 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/DecimalUtilities.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/DecimalUtilities.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + namespace Roslyn.Utilities { internal static class DecimalUtilities diff --git a/src/Compilers/Core/Portable/InternalUtilities/DocumentationCommentXmlNames.cs b/src/Compilers/Core/Portable/InternalUtilities/DocumentationCommentXmlNames.cs index 4b33c0b00aeae..e1e5c481a584b 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/DocumentationCommentXmlNames.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/DocumentationCommentXmlNames.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; namespace Roslyn.Utilities diff --git a/src/Compilers/Core/Portable/InternalUtilities/EmptyComparer.cs b/src/Compilers/Core/Portable/InternalUtilities/EmptyComparer.cs index 3e829ccd756be..0acd13fae8639 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/EmptyComparer.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/EmptyComparer.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Collections.Generic; using System.Diagnostics; using System.Runtime.CompilerServices; @@ -18,7 +20,7 @@ private EmptyComparer() { } - bool IEqualityComparer.Equals(object a, object b) + bool IEqualityComparer.Equals(object? a, object? b) { Debug.Assert(false, "Are we using empty comparer with nonempty dictionary?"); return false; diff --git a/src/Compilers/Core/Portable/InternalUtilities/EncodingExtensions.cs b/src/Compilers/Core/Portable/InternalUtilities/EncodingExtensions.cs index 6cee005bf7711..2665342517c6a 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/EncodingExtensions.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/EncodingExtensions.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using Microsoft.CodeAnalysis; using System; using System.Diagnostics; diff --git a/src/Compilers/Core/Portable/InternalUtilities/EnumField.cs b/src/Compilers/Core/Portable/InternalUtilities/EnumField.cs index ab7c230e022c0..0a8fe5690a2b3 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/EnumField.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/EnumField.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Collections.Generic; using System.Diagnostics; using Microsoft.CodeAnalysis.PooledObjects; @@ -14,11 +16,11 @@ internal readonly struct EnumField public readonly string Name; public readonly ulong Value; - public readonly object IdentityOpt; + public readonly object? IdentityOpt; - public EnumField(string name, ulong value, object identityOpt = null) + public EnumField(string name, ulong value, object? identityOpt = null) { - Debug.Assert(name != null); + RoslynDebug.Assert(name != null); this.Name = name; this.Value = value; this.IdentityOpt = identityOpt; diff --git a/src/Compilers/Core/Portable/InternalUtilities/EnumUtilties.cs b/src/Compilers/Core/Portable/InternalUtilities/EnumUtilties.cs index 10b11e0387224..34199eea3e63a 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/EnumUtilties.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/EnumUtilties.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Diagnostics; using System.Reflection; @@ -16,7 +18,7 @@ internal static class EnumUtilities /// internal static ulong ConvertEnumUnderlyingTypeToUInt64(object value, SpecialType specialType) { - Debug.Assert(value != null); + RoslynDebug.Assert(value != null); Debug.Assert(value.GetType().GetTypeInfo().IsPrimitive); unchecked diff --git a/src/Compilers/Core/Portable/InternalUtilities/EnumerableExtensions.cs b/src/Compilers/Core/Portable/InternalUtilities/EnumerableExtensions.cs index 8e9c8be436d71..01b9a78f9431d 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/EnumerableExtensions.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/EnumerableExtensions.cs @@ -1,14 +1,18 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections; using System.Collections.Generic; using System.Collections.Immutable; using System.Collections.ObjectModel; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.PooledObjects; +using Roslyn.Utilities; namespace Roslyn.Utilities { @@ -75,7 +79,7 @@ private static IEnumerable ConcatWorker(this IEnumerable source, T valu yield return value; } - public static bool SetEquals(this IEnumerable source1, IEnumerable source2, IEqualityComparer comparer) + public static bool SetEquals(this IEnumerable source1, IEnumerable source2, IEqualityComparer? comparer) { if (source1 == null) { @@ -105,7 +109,7 @@ public static bool SetEquals(this IEnumerable source1, IEnumerable sour return source1.ToSet().SetEquals(source2); } - public static ISet ToSet(this IEnumerable source, IEqualityComparer comparer) + public static ISet ToSet(this IEnumerable source, IEqualityComparer? comparer) { if (source == null) { @@ -144,7 +148,7 @@ public static ISet ToSet(this IEnumerable source) throw new ArgumentNullException(nameof(source)); } - return source.Cast().FirstOrDefault(v => predicate(v.Value)); + return source.Cast().FirstOrDefault(v => predicate(v!.Value)); } public static T? LastOrNullable(this IEnumerable source) @@ -227,7 +231,7 @@ public static bool IsEmpty(this List source) private static readonly Func s_notNullTest = x => x != null; - public static IEnumerable WhereNotNull(this IEnumerable source) + public static IEnumerable WhereNotNull(this IEnumerable source) where T : class { if (source == null) @@ -235,13 +239,13 @@ public static IEnumerable WhereNotNull(this IEnumerable source) return SpecializedCollections.EmptyEnumerable(); } - return source.Where((Func)s_notNullTest); + return source.Where((Func)s_notNullTest)!; } public static T[] AsArray(this IEnumerable source) => source as T[] ?? source.ToArray(); - public static ImmutableArray SelectAsArray(this IEnumerable source, Func selector) + public static ImmutableArray SelectAsArray(this IEnumerable? source, Func selector) { if (source == null) { @@ -282,7 +286,7 @@ public static IEnumerable Flatten(this IEnumerable> sequenc return sequence.SelectMany(s => s); } - public static IOrderedEnumerable OrderBy(this IEnumerable source, IComparer comparer) + public static IOrderedEnumerable OrderBy(this IEnumerable source, IComparer? comparer) { return source.OrderBy(Functions.Identity, comparer); } @@ -297,7 +301,7 @@ public static IOrderedEnumerable Order(this IEnumerable source) where T return source.OrderBy(Comparisons.Comparer); } - public static IOrderedEnumerable ThenBy(this IOrderedEnumerable source, IComparer comparer) + public static IOrderedEnumerable ThenBy(this IOrderedEnumerable source, IComparer? comparer) { return source.ThenBy(Functions.Identity, comparer); } @@ -364,7 +368,8 @@ public static IComparer ToComparer(this Comparison comparison) return Comparer.Create(comparison); } - public static ImmutableDictionary ToImmutableDictionaryOrEmpty(this IEnumerable> items) + public static ImmutableDictionary ToImmutableDictionaryOrEmpty(this IEnumerable>? items) + where K : notnull { if (items == null) { @@ -374,7 +379,8 @@ public static ImmutableDictionary ToImmutableDictionaryOrEmpty(this return ImmutableDictionary.CreateRange(items); } - public static ImmutableDictionary ToImmutableDictionaryOrEmpty(this IEnumerable> items, IEqualityComparer keyComparer) + public static ImmutableDictionary ToImmutableDictionaryOrEmpty(this IEnumerable>? items, IEqualityComparer? keyComparer) + where K : notnull { if (items == null) { @@ -384,6 +390,7 @@ public static ImmutableDictionary ToImmutableDictionaryOrEmpty(this return ImmutableDictionary.CreateRange(keyComparer, items); } +#nullable disable // Transpose doesn't handle empty arrays. Needs to be updated as appropriate. internal static IList> Transpose(this IEnumerable> data) { #if DEBUG @@ -436,9 +443,11 @@ private static IEnumerable> TransposeInternal(this IEnumerable> ToDictionary(this IEnumerable data, Func keySelector, IEqualityComparer comparer = null) + internal static Dictionary> ToDictionary(this IEnumerable data, Func keySelector, IEqualityComparer? comparer = null) + where K : notnull { var dictionary = new Dictionary>(comparer); var groups = data.GroupBy(keySelector, comparer); @@ -456,11 +465,12 @@ internal static Dictionary> ToDictionary(this IEnumer /// Returns the only element of specified sequence if it has exactly one, and default(TSource) otherwise. /// Unlike doesn't throw if there is more than one element in the sequence. /// - internal static TSource AsSingleton(this IEnumerable source) + [return: MaybeNull] + internal static TSource AsSingleton(this IEnumerable? source) { if (source == null) { - return default; + return default!; } if (source is IList list) @@ -471,13 +481,13 @@ internal static TSource AsSingleton(this IEnumerable source) using IEnumerator e = source.GetEnumerator(); if (!e.MoveNext()) { - return default; + return default!; } TSource result = e.Current; if (e.MoveNext()) { - return default; + return default!; } return result; @@ -513,9 +523,9 @@ namespace System.Linq /// internal static class EnumerableExtensions { - public static bool SequenceEqual(this IEnumerable first, IEnumerable second, Func comparer) + public static bool SequenceEqual(this IEnumerable? first, IEnumerable? second, Func comparer) { - Debug.Assert(comparer != null); + RoslynDebug.Assert(comparer != null); if (first == second) { diff --git a/src/Compilers/Core/Portable/InternalUtilities/ExceptionUtilities.cs b/src/Compilers/Core/Portable/InternalUtilities/ExceptionUtilities.cs index e56e46726e725..49073fadb4de7 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/ExceptionUtilities.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/ExceptionUtilities.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Diagnostics; @@ -12,7 +14,7 @@ internal static class ExceptionUtilities /// /// The unexpected value. /// The , which should be thrown by the caller. - internal static Exception UnexpectedValue(object o) + internal static Exception UnexpectedValue(object? o) { string output = string.Format("Unexpected value '{0}' of type '{1}'", o, (o != null) ? o.GetType().FullName : ""); Debug.Assert(false, output); diff --git a/src/Compilers/Core/Portable/InternalUtilities/FailFast.cs b/src/Compilers/Core/Portable/InternalUtilities/FailFast.cs index 00ef07a4c4392..1e91708401926 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/FailFast.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/FailFast.cs @@ -1,13 +1,17 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.CodeAnalysis { internal static class FailFast { [DebuggerHidden] + [DoesNotReturn] internal static void OnFatalException(Exception exception) { // EDMAURER Now using the managed API to fail fast so as to default @@ -40,7 +44,7 @@ internal static void OnFatalException(Exception exception) /// An optional message to be recorded in the dump in case of failure. Can be null. [Conditional("DEBUG")] [DebuggerHidden] - internal static void Assert(bool condition, string message = null) + internal static void Assert([DoesNotReturnIf(false)] bool condition, string? message = null) { if (condition) { diff --git a/src/Compilers/Core/Portable/InternalUtilities/FatalError.cs b/src/Compilers/Core/Portable/InternalUtilities/FatalError.cs index 7417b5cdd733e..34fb03a536c4b 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/FatalError.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/FatalError.cs @@ -1,7 +1,10 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; #if COMPILERCORE namespace Microsoft.CodeAnalysis @@ -11,17 +14,18 @@ namespace Microsoft.CodeAnalysis.ErrorReporting { internal static class FatalError { - private static Action s_fatalHandler; - private static Action s_nonFatalHandler; + private static Action? s_fatalHandler; + private static Action? s_nonFatalHandler; - private static Exception s_reportedException; - private static string s_reportedExceptionMessage; + private static Exception? s_reportedException; + private static string? s_reportedExceptionMessage; /// /// Set by the host to a fail fast trigger, /// if the host desires to crash the process on a fatal exception. /// - public static Action Handler + [DisallowNull] + public static Action? Handler { get { @@ -42,7 +46,8 @@ public static Action Handler /// Set by the host to a fail fast trigger, /// if the host desires to NOT crash the process on a non fatal exception. /// - public static Action NonFatalHandler + [DisallowNull] + public static Action? NonFatalHandler { get { @@ -62,7 +67,7 @@ public static Action NonFatalHandler // Same as setting the Handler property except that it avoids the assert. This is useful in // test code which needs to verify the handler is called in specific cases and will continually // overwrite this value. - public static void OverwriteHandler(Action value) + public static void OverwriteHandler(Action? value) { s_fatalHandler = value; } @@ -175,7 +180,7 @@ public static bool ReportWithoutCrashUnlessCanceledAndPropagate(Exception except private static readonly object s_reportedMarker = new object(); - private static void Report(Exception exception, Action handler) + private static void Report(Exception exception, Action? handler) { // hold onto last exception to make investigation easier s_reportedException = exception; diff --git a/src/Compilers/Core/Portable/InternalUtilities/FileNameUtilities.cs b/src/Compilers/Core/Portable/InternalUtilities/FileNameUtilities.cs index 2ce4012d0ed2a..f8e61a033908c 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/FileNameUtilities.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/FileNameUtilities.cs @@ -1,5 +1,9 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + +using System.Diagnostics.CodeAnalysis; + namespace Roslyn.Utilities { /// @@ -24,7 +28,7 @@ internal static class FileNameUtilities /// /// True if is a simple file name, false if it is null or includes a directory specification. /// - internal static bool IsFileName(string path) + internal static bool IsFileName([NotNullWhen(returnValue: true)] string? path) { return IndexOfFileName(path) == 0; } @@ -36,7 +40,7 @@ internal static bool IsFileName(string path) /// Returns 0 for path ".goo". /// Returns -1 for path "goo.". /// - private static int IndexOfExtension(string path) + private static int IndexOfExtension(string? path) { if (path == null) { @@ -75,7 +79,8 @@ private static int IndexOfExtension(string path) /// The same functionality as but doesn't throw an exception /// if there are invalid characters in the path. /// - internal static string GetExtension(string path) + [return: NotNullIfNotNull(parameterName: "path")] + internal static string? GetExtension(string? path) { if (path == null) { @@ -93,7 +98,8 @@ internal static string GetExtension(string path) /// Returns "goo" for path "goo.". /// Returns "goo.." for path "goo...". /// - private static string RemoveExtension(string path) + [return: NotNullIfNotNull(parameterName: "path")] + private static string? RemoveExtension(string? path) { if (path == null) { @@ -125,7 +131,8 @@ private static string RemoveExtension(string path) /// If path does not end with an extension, the new extension is appended to the path. /// If extension is null, equivalent to . /// - internal static string ChangeExtension(string path, string extension) + [return: NotNullIfNotNull(parameterName: "path")] + internal static string? ChangeExtension(string? path, string? extension) { if (path == null) { @@ -150,7 +157,7 @@ internal static string ChangeExtension(string path, string extension) /// Returns the position in given path where the file name starts. /// /// -1 if path is null. - internal static int IndexOfFileName(string path) + internal static int IndexOfFileName(string? path) { if (path == null) { @@ -173,10 +180,11 @@ internal static int IndexOfFileName(string path) /// Get file name from path. /// /// Unlike doesn't check for invalid path characters. - internal static string GetFileName(string path, bool includeExtension = true) + [return: NotNullIfNotNull(parameterName: "path")] + internal static string? GetFileName(string? path, bool includeExtension = true) { int fileNameStart = IndexOfFileName(path); - var fileName = (fileNameStart <= 0) ? path : path.Substring(fileNameStart); + var fileName = (fileNameStart <= 0) ? path : path!.Substring(fileNameStart); return includeExtension ? fileName : RemoveExtension(fileName); } } diff --git a/src/Compilers/Core/Portable/InternalUtilities/GeneratedCodeUtilities.cs b/src/Compilers/Core/Portable/InternalUtilities/GeneratedCodeUtilities.cs index 6eec73adce334..e051ab8ceca06 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/GeneratedCodeUtilities.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/GeneratedCodeUtilities.cs @@ -1,8 +1,9 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; -using System.Diagnostics; -using System.Linq; +using System.Diagnostics.CodeAnalysis; using System.Threading; using Microsoft.CodeAnalysis; @@ -15,8 +16,8 @@ internal static class GeneratedCodeUtilities internal static bool IsGeneratedSymbolWithGeneratedCodeAttribute( ISymbol symbol, INamedTypeSymbol generatedCodeAttribute) { - Debug.Assert(symbol != null); - Debug.Assert(generatedCodeAttribute != null); + RoslynDebug.Assert(symbol != null); + RoslynDebug.Assert(generatedCodeAttribute != null); // Don't check this for namespaces. Namespaces cannot have attributes on them. And, // currently, calling DeclaringSyntaxReferences on an INamespaceSymbol is more expensive @@ -49,7 +50,7 @@ internal static bool IsGeneratedCode( BeginsWithAutoGeneratedComment(tree, isComment, cancellationToken); } - private static bool IsGeneratedCodeFile(string filePath) + private static bool IsGeneratedCodeFile([NotNullWhen(returnValue: true)] string? filePath) { if (!string.IsNullOrEmpty(filePath)) { diff --git a/src/Compilers/Core/Portable/InternalUtilities/Hash.cs b/src/Compilers/Core/Portable/InternalUtilities/Hash.cs index 6afd920c0a562..87ea875ac25b4 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/Hash.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/Hash.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Generic; using System.Collections.Immutable; @@ -28,7 +30,7 @@ internal static int Combine(bool newKeyPart, int currentKey) /// unnecessary boxing operations. Unfortunately, we can't constrain /// T to "non-enum", so we'll use a more restrictive constraint. /// - internal static int Combine(T newKeyPart, int currentKey) where T : class + internal static int Combine(T newKeyPart, int currentKey) where T : class? { int hash = unchecked(currentKey * (int)0xA5555529); @@ -40,7 +42,7 @@ internal static int Combine(T newKeyPart, int currentKey) where T : class return hash; } - internal static int CombineValues(IEnumerable values, int maxItemsToHash = int.MaxValue) + internal static int CombineValues(IEnumerable? values, int maxItemsToHash = int.MaxValue) { if (values == null) { @@ -66,7 +68,7 @@ internal static int CombineValues(IEnumerable values, int maxItemsToHash = return hashCode; } - internal static int CombineValues(T[] values, int maxItemsToHash = int.MaxValue) + internal static int CombineValues(T[]? values, int maxItemsToHash = int.MaxValue) { if (values == null) { @@ -116,7 +118,7 @@ internal static int CombineValues(ImmutableArray values, int maxItemsToHas return hashCode; } - internal static int CombineValues(IEnumerable values, StringComparer stringComparer, int maxItemsToHash = int.MaxValue) + internal static int CombineValues(IEnumerable? values, StringComparer stringComparer, int maxItemsToHash = int.MaxValue) { if (values == null) { diff --git a/src/Compilers/Core/Portable/InternalUtilities/IReadOnlySet.cs b/src/Compilers/Core/Portable/InternalUtilities/IReadOnlySet.cs index 8e6be9b3ffda2..6689db4bf37c2 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/IReadOnlySet.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/IReadOnlySet.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + namespace Roslyn.Utilities { internal interface IReadOnlySet diff --git a/src/Compilers/Core/Portable/InternalUtilities/ISetExtensions.cs b/src/Compilers/Core/Portable/InternalUtilities/ISetExtensions.cs index 197ed59a81b7b..4a4b9f7c099e4 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/ISetExtensions.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/ISetExtensions.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Collections.Generic; using System.Collections.Immutable; diff --git a/src/Compilers/Core/Portable/InternalUtilities/ImmutableArrayExtensions.cs b/src/Compilers/Core/Portable/InternalUtilities/ImmutableArrayExtensions.cs index a3c11633eb4f1..9cbdb2baf564b 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/ImmutableArrayExtensions.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/ImmutableArrayExtensions.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Generic; using System.Collections.Immutable; @@ -8,7 +10,7 @@ namespace Roslyn.Utilities { internal static class ImmutableArrayExtensions { - internal static ImmutableArray ToImmutableArrayOrEmpty(this IEnumerable items) + internal static ImmutableArray ToImmutableArrayOrEmpty(this IEnumerable? items) => items == null ? ImmutableArray.Empty : ImmutableArray.CreateRange(items); internal static ImmutableArray ToImmutableArrayOrEmpty(this ImmutableArray items) @@ -43,7 +45,7 @@ internal static int BinarySearch(this ImmutableArray return ~low; } - internal static ImmutableArray CastDown(this ImmutableArray array) where TDerived : class, TOriginal + internal static ImmutableArray CastDown(this ImmutableArray array) where TDerived : class?, TOriginal { return array.CastArray(); } diff --git a/src/Compilers/Core/Portable/InternalUtilities/ImmutableListExtensions.cs b/src/Compilers/Core/Portable/InternalUtilities/ImmutableListExtensions.cs index 60785f50f5661..a670691d8d9b7 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/ImmutableListExtensions.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/ImmutableListExtensions.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Collections.Generic; using System.Collections.Immutable; @@ -7,7 +9,7 @@ namespace Roslyn.Utilities { internal static class ImmutableListExtensions { - internal static ImmutableList ToImmutableListOrEmpty(this T[] items) + internal static ImmutableList ToImmutableListOrEmpty(this T[]? items) { if (items == null) { @@ -17,7 +19,7 @@ internal static ImmutableList ToImmutableListOrEmpty(this T[] items) return ImmutableList.Create(items); } - internal static ImmutableList ToImmutableListOrEmpty(this IEnumerable items) + internal static ImmutableList ToImmutableListOrEmpty(this IEnumerable? items) { if (items == null) { diff --git a/src/Compilers/Core/Portable/InternalUtilities/ImmutableSetWithInsertionOrder`1.cs b/src/Compilers/Core/Portable/InternalUtilities/ImmutableSetWithInsertionOrder`1.cs index 6b124ec981f7c..aeacbde247e58 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/ImmutableSetWithInsertionOrder`1.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/ImmutableSetWithInsertionOrder`1.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; +#nullable enable + using System.Collections; using System.Collections.Generic; using System.Collections.Immutable; @@ -9,6 +10,7 @@ namespace Roslyn.Utilities { internal sealed class ImmutableSetWithInsertionOrder : IEnumerable + where T : notnull { public static readonly ImmutableSetWithInsertionOrder Empty = new ImmutableSetWithInsertionOrder(ImmutableDictionary.Create(), 0u); diff --git a/src/Compilers/Core/Portable/InternalUtilities/IncrementalHashExtensions.cs b/src/Compilers/Core/Portable/InternalUtilities/IncrementalHashExtensions.cs index 6f986d287c394..d346e509d58a1 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/IncrementalHashExtensions.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/IncrementalHashExtensions.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Generic; using System.Reflection.Metadata; diff --git a/src/Compilers/Core/Portable/InternalUtilities/InterlockedOperations.cs b/src/Compilers/Core/Portable/InternalUtilities/InterlockedOperations.cs index 669e172fae9e3..7dc21177a769e 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/InterlockedOperations.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/InterlockedOperations.cs @@ -1,7 +1,10 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Threading; namespace Roslyn.Utilities @@ -18,9 +21,9 @@ internal static class InterlockedOperations /// The new value referenced by . Note that this is /// nearly always more useful than the usual return from /// because it saves another read to . - public static T Initialize(ref T target, T value) where T : class + public static T Initialize([NotNull] ref T? target, T value) where T : class { - Debug.Assert((object)value != null); + RoslynDebug.Assert((object?)value != null); return Interlocked.CompareExchange(ref target, value, null) ?? value; } @@ -36,11 +39,12 @@ public static T Initialize(ref T target, T value) where T : class /// The new value referenced by . Note that this is /// nearly always more useful than the usual return from /// because it saves another read to . - public static T Initialize(ref T target, T initializedValue, T uninitializedValue) where T : class + [return: NotNullIfNotNull(parameterName: "initializedValue")] + public static T Initialize(ref T target, T initializedValue, T uninitializedValue) where T : class? { - Debug.Assert((object)initializedValue != uninitializedValue); + Debug.Assert((object?)initializedValue != uninitializedValue); T oldValue = Interlocked.CompareExchange(ref target, initializedValue, uninitializedValue); - return (object)oldValue == uninitializedValue ? initializedValue : oldValue; + return (object?)oldValue == uninitializedValue ? initializedValue : oldValue; } /// diff --git a/src/Compilers/Core/Portable/InternalUtilities/JsonWriter.cs b/src/Compilers/Core/Portable/InternalUtilities/JsonWriter.cs index 6d5540fc64bfd..ecb24e225d196 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/JsonWriter.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/JsonWriter.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Diagnostics; using System.Globalization; @@ -163,12 +165,12 @@ public void Dispose() // // https://github.com/dotnet/corefx/blob/master/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JavaScriptString.cs // - private static string EscapeString(string value) + private static string EscapeString(string? value) { - PooledStringBuilder pooledBuilder = null; - StringBuilder b = null; + PooledStringBuilder? pooledBuilder = null; + StringBuilder? b = null; - if (string.IsNullOrEmpty(value)) + if (RoslynString.IsNullOrEmpty(value)) { return string.Empty; } @@ -183,7 +185,7 @@ private static string EscapeString(string value) { if (b == null) { - Debug.Assert(pooledBuilder == null); + RoslynDebug.Assert(pooledBuilder == null); pooledBuilder = PooledStringBuilder.GetInstance(); b = pooledBuilder.Builder; } @@ -195,26 +197,24 @@ private static string EscapeString(string value) startIndex = i + 1; count = 0; - } - switch (c) - { - case '\"': - b.Append("\\\""); - break; - case '\\': - b.Append("\\\\"); - break; - default: - if (ShouldAppendAsUnicode(c)) - { + switch (c) + { + case '\"': + b.Append("\\\""); + break; + case '\\': + b.Append("\\\\"); + break; + default: + Debug.Assert(ShouldAppendAsUnicode(c)); AppendCharAsUnicode(b, c); - } - else - { - count++; - } - break; + break; + } + } + else + { + count++; } } @@ -222,6 +222,10 @@ private static string EscapeString(string value) { return value; } + else + { + RoslynDebug.Assert(pooledBuilder is object); + } if (count > 0) { diff --git a/src/Compilers/Core/Portable/InternalUtilities/KeyValuePairUtil.cs b/src/Compilers/Core/Portable/InternalUtilities/KeyValuePairUtil.cs index 0acebc1bceb79..b5cdc0ba33425 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/KeyValuePairUtil.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/KeyValuePairUtil.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Collections.Generic; namespace Roslyn.Utilities diff --git a/src/Compilers/Core/Portable/InternalUtilities/LittleEndianReader.cs b/src/Compilers/Core/Portable/InternalUtilities/LittleEndianReader.cs index 25bcd87e227e2..4a4f7ed3bea0b 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/LittleEndianReader.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/LittleEndianReader.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using Roslyn.Utilities; using static System.Buffers.Binary.BinaryPrimitives; diff --git a/src/Compilers/Core/Portable/InternalUtilities/NoThrowStreamDisposer.cs b/src/Compilers/Core/Portable/InternalUtilities/NoThrowStreamDisposer.cs index ec1287e6a767a..36cb331825b22 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/NoThrowStreamDisposer.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/NoThrowStreamDisposer.cs @@ -1,7 +1,8 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; -using System.Diagnostics; using System.IO; using Microsoft.CodeAnalysis; @@ -32,7 +33,7 @@ public bool HasFailedToDispose { get { - Debug.Assert(_failed != null); + RoslynDebug.Assert(_failed != null); return _failed.GetValueOrDefault(); } } @@ -52,7 +53,7 @@ public NoThrowStreamDisposer( public void Dispose() { - Debug.Assert(_failed == null); + RoslynDebug.Assert(_failed == null); try { Stream.Dispose(); diff --git a/src/Compilers/Core/Portable/InternalUtilities/OneOrMany.cs b/src/Compilers/Core/Portable/InternalUtilities/OneOrMany.cs index 05d0e31ada442..aab3ea7baf348 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/OneOrMany.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/OneOrMany.cs @@ -1,10 +1,13 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Immutable; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace Roslyn.Utilities { @@ -15,7 +18,9 @@ namespace Roslyn.Utilities /// Used when a collection usually contains a single item but sometimes might contain multiple. /// internal struct OneOrMany + where T : notnull { + [AllowNull, MaybeNull] private readonly T _one; private readonly ImmutableArray _many; @@ -81,7 +86,7 @@ public OneOrMany Add(T one) public bool Contains(T item) { - Debug.Assert(item != null); + RoslynDebug.Assert(item != null); if (Count == 1) { return item.Equals(_one); @@ -156,11 +161,13 @@ public T Current internal static class OneOrMany { public static OneOrMany Create(T one) + where T : notnull { return new OneOrMany(one); } public static OneOrMany Create(ImmutableArray many) + where T : notnull { return new OneOrMany(many); } diff --git a/src/Compilers/Core/Portable/InternalUtilities/OrderedMultiDictionary.cs b/src/Compilers/Core/Portable/InternalUtilities/OrderedMultiDictionary.cs index 44be7b79917e2..cb1c3497749e5 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/OrderedMultiDictionary.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/OrderedMultiDictionary.cs @@ -1,14 +1,15 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; +#nullable enable + using System.Collections; using System.Collections.Generic; -using System.Diagnostics; namespace Roslyn.Utilities { // Note that this is not threadsafe for concurrent reading and writing. internal sealed class OrderedMultiDictionary : IEnumerable>> + where K : notnull { private readonly Dictionary> _dictionary; private readonly List _keys; diff --git a/src/Compilers/Core/Portable/InternalUtilities/PerformanceSensitiveAttribute.cs b/src/Compilers/Core/Portable/InternalUtilities/PerformanceSensitiveAttribute.cs index 2ddaf5107c1ac..837ed367fae75 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/PerformanceSensitiveAttribute.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/PerformanceSensitiveAttribute.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Generic; using System.Diagnostics; @@ -40,7 +42,7 @@ public string Uri /// constraint. This property supports documenting constraints which cannot be described in terms of other /// constraint properties. /// - public string Constraint + public string? Constraint { get; set; diff --git a/src/Compilers/Core/Portable/InternalUtilities/PlatformInformation.cs b/src/Compilers/Core/Portable/InternalUtilities/PlatformInformation.cs index 3bb8759e1ac99..c0ffeb3a9b650 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/PlatformInformation.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/PlatformInformation.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.IO; diff --git a/src/Compilers/Core/Portable/InternalUtilities/ReaderWriterLockSlimExtensions.cs b/src/Compilers/Core/Portable/InternalUtilities/ReaderWriterLockSlimExtensions.cs index 6c43f9b17330b..c621104b5da77 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/ReaderWriterLockSlimExtensions.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/ReaderWriterLockSlimExtensions.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Diagnostics; using System.Threading; diff --git a/src/Compilers/Core/Portable/InternalUtilities/ReferenceEqualityComparer.cs b/src/Compilers/Core/Portable/InternalUtilities/ReferenceEqualityComparer.cs index e41b866880a20..7cdf77b3dd51d 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/ReferenceEqualityComparer.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/ReferenceEqualityComparer.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Collections.Generic; using System.Runtime.CompilerServices; @@ -16,7 +18,7 @@ private ReferenceEqualityComparer() { } - bool IEqualityComparer.Equals(object a, object b) + bool IEqualityComparer.Equals(object? a, object? b) { return a == b; } diff --git a/src/Compilers/Core/Portable/InternalUtilities/ReflectionUtilities.cs b/src/Compilers/Core/Portable/InternalUtilities/ReflectionUtilities.cs index 4aadf112dfc3f..95279fe7acdf3 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/ReflectionUtilities.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/ReflectionUtilities.cs @@ -1,8 +1,11 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.ExceptionServices; @@ -12,7 +15,7 @@ internal static class ReflectionUtilities { private static readonly Type Missing = typeof(void); - public static Type TryGetType(string assemblyQualifiedName) + public static Type? TryGetType(string assemblyQualifiedName) { try { @@ -25,7 +28,7 @@ public static Type TryGetType(string assemblyQualifiedName) } } - public static Type TryGetType(ref Type lazyType, string assemblyQualifiedName) + public static Type? TryGetType([NotNull] ref Type? lazyType, string assemblyQualifiedName) { if (lazyType == null) { @@ -39,7 +42,7 @@ public static Type TryGetType(ref Type lazyType, string assemblyQualifiedName) /// Find a instance by first probing the contract name and then the name as it /// would exist in mscorlib. This helps satisfy both the CoreCLR and Desktop scenarios. /// - public static Type GetTypeFromEither(string contractName, string desktopName) + public static Type? GetTypeFromEither(string contractName, string desktopName) { var type = TryGetType(contractName); @@ -51,7 +54,7 @@ public static Type GetTypeFromEither(string contractName, string desktopName) return type; } - public static Type GetTypeFromEither(ref Type lazyType, string contractName, string desktopName) + public static Type? GetTypeFromEither([NotNull] ref Type? lazyType, string contractName, string desktopName) { if (lazyType == null) { @@ -61,7 +64,7 @@ public static Type GetTypeFromEither(ref Type lazyType, string contractName, str return (lazyType == Missing) ? null : lazyType; } - public static T FindItem(IEnumerable collection, params Type[] paramTypes) + public static T? FindItem(IEnumerable collection, params Type[] paramTypes) where T : MethodBase { foreach (var current in collection) @@ -91,31 +94,33 @@ public static T FindItem(IEnumerable collection, params Type[] paramTypes) return null; } - internal static MethodInfo GetDeclaredMethod(this TypeInfo typeInfo, string name, params Type[] paramTypes) + internal static MethodInfo? GetDeclaredMethod(this TypeInfo typeInfo, string name, params Type[] paramTypes) { return FindItem(typeInfo.GetDeclaredMethods(name), paramTypes); } - internal static ConstructorInfo GetDeclaredConstructor(this TypeInfo typeInfo, params Type[] paramTypes) + internal static ConstructorInfo? GetDeclaredConstructor(this TypeInfo typeInfo, params Type[] paramTypes) { return FindItem(typeInfo.DeclaredConstructors, paramTypes); } - public static T CreateDelegate(this MethodInfo methodInfo) + public static T? CreateDelegate(this MethodInfo? methodInfo) + where T : Delegate { if (methodInfo == null) { - return default; + return null; } - return (T)(object)methodInfo.CreateDelegate(typeof(T)); + return (T)methodInfo.CreateDelegate(typeof(T)); } - public static T InvokeConstructor(this ConstructorInfo constructorInfo, params object[] args) + [return: MaybeNull] + public static T InvokeConstructor(this ConstructorInfo? constructorInfo, params object[] args) { if (constructorInfo == null) { - return default; + return default!; } try @@ -126,13 +131,13 @@ public static T InvokeConstructor(this ConstructorInfo constructorInfo, param { ExceptionDispatchInfo.Capture(e.InnerException).Throw(); Debug.Assert(false, "Unreachable"); - return default; + return default!; } } - public static object InvokeConstructor(this ConstructorInfo constructorInfo, params object[] args) + public static object? InvokeConstructor(this ConstructorInfo constructorInfo, params object[] args) { - return constructorInfo.InvokeConstructor(args); + return constructorInfo.InvokeConstructor(args); } public static T Invoke(this MethodInfo methodInfo, object obj, params object[] args) diff --git a/src/Compilers/Core/Portable/InternalUtilities/RoslynString.cs b/src/Compilers/Core/Portable/InternalUtilities/RoslynString.cs new file mode 100644 index 0000000000000..000f0a9d4bab8 --- /dev/null +++ b/src/Compilers/Core/Portable/InternalUtilities/RoslynString.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +#nullable enable + +using System.Diagnostics.CodeAnalysis; + +namespace Roslyn.Utilities +{ + internal static class RoslynString + { + /// + public static bool IsNullOrEmpty([NotNullWhen(returnValue: false)] string? value) + => string.IsNullOrEmpty(value); + } +} diff --git a/src/Compilers/Core/Portable/InternalUtilities/SemaphoreSlimExtensions.cs b/src/Compilers/Core/Portable/InternalUtilities/SemaphoreSlimExtensions.cs index fc789735c6f25..ab58bab1592a1 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/SemaphoreSlimExtensions.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/SemaphoreSlimExtensions.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Threading; using System.Threading.Tasks; diff --git a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.Collection.cs b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.Collection.cs index 9a98ce4937073..187ab63bb8fac 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.Collection.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.Collection.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Generic; diff --git a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.Dictionary.cs b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.Dictionary.cs index 056f1317df29e..79a88141f0734 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.Dictionary.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.Dictionary.cs @@ -1,7 +1,10 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace Roslyn.Utilities { @@ -10,6 +13,7 @@ internal partial class SpecializedCollections private partial class Empty { internal class Dictionary : Collection>, IDictionary, IReadOnlyDictionary + where TKey : notnull { public static readonly new Dictionary Instance = new Dictionary(); @@ -43,9 +47,9 @@ public bool Remove(TKey key) throw new NotSupportedException(); } - public bool TryGetValue(TKey key, out TValue value) + public bool TryGetValue(TKey key, [MaybeNullWhen(returnValue: false)] out TValue value) { - value = default; + value = default!; return false; } diff --git a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.Enumerable.cs b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.Enumerable.cs index cd88c66fd008c..de1186dd6361c 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.Enumerable.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.Enumerable.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Collections.Generic; namespace Roslyn.Utilities diff --git a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.Enumerator.cs b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.Enumerator.cs index 092e336f0e30a..c9e768051694f 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.Enumerator.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.Enumerator.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections; @@ -17,7 +19,7 @@ protected Enumerator() { } - public object Current => throw new InvalidOperationException(); + public object? Current => throw new InvalidOperationException(); public bool MoveNext() { diff --git a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.Enumerator`1.cs b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.Enumerator`1.cs index c4ad9ab6112d9..020cd5d155f70 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.Enumerator`1.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.Enumerator`1.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Generic; diff --git a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.List.cs b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.List.cs index 9097dc426d050..1652d828e6d72 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.List.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.List.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Generic; diff --git a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.Set.cs b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.Set.cs index 1242db8b84504..53c9f4daaef63 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.Set.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.Set.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Generic; diff --git a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.cs b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.cs index ebe6e33c4af1d..fb4d8235ae913 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Empty.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + namespace Roslyn.Utilities { internal partial class SpecializedCollections diff --git a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.ReadOnly.Collection.cs b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.ReadOnly.Collection.cs index c498301cb4f18..4dd37b0cc6efd 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.ReadOnly.Collection.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.ReadOnly.Collection.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Generic; diff --git a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.ReadOnly.Enumerable`1.cs b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.ReadOnly.Enumerable`1.cs index 3a82b14691c36..3085f1ef8fe40 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.ReadOnly.Enumerable`1.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.ReadOnly.Enumerable`1.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Collections; namespace Roslyn.Utilities diff --git a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.ReadOnly.Enumerable`2.cs b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.ReadOnly.Enumerable`2.cs index 8a7d92ea88c37..042f80b978ce9 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.ReadOnly.Enumerable`2.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.ReadOnly.Enumerable`2.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Collections.Generic; namespace Roslyn.Utilities diff --git a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.ReadOnly.Set.cs b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.ReadOnly.Set.cs index 38fef536146c6..e270bca3b729a 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.ReadOnly.Set.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.ReadOnly.Set.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Generic; diff --git a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Singleton.Collection`1.cs b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Singleton.Collection`1.cs index 2bebc1af5d56d..08b337b70ed42 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Singleton.Collection`1.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Singleton.Collection`1.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections; using System.Collections.Generic; diff --git a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Singleton.Enumerator`1.cs b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Singleton.Enumerator`1.cs index 5fec89afa093a..62638b95bc30e 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Singleton.Enumerator`1.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Singleton.Enumerator`1.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Collections; using System.Collections.Generic; @@ -22,7 +24,7 @@ public Enumerator(T value) public T Current => _loneValue; - object IEnumerator.Current => _loneValue; + object? IEnumerator.Current => _loneValue; public void Dispose() { diff --git a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Symbol.cs b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Symbol.cs index 6cd145cba5447..b66562da5d16d 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Symbol.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.Symbol.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Diagnostics; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.PooledObjects; diff --git a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.cs b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.cs index 11a079a739d7d..6f7e582f3b9ad 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/SpecializedCollections.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Collections.Generic; namespace Roslyn.Utilities @@ -42,11 +44,13 @@ public static IReadOnlySet EmptyReadOnlySet() } public static IDictionary EmptyDictionary() + where TKey : notnull { return Empty.Dictionary.Instance; } public static IReadOnlyDictionary EmptyReadOnlyDictionary() + where TKey : notnull { return Empty.Dictionary.Instance; } @@ -76,21 +80,21 @@ public static IEnumerable ReadOnlyEnumerable(IEnumerable values) return new ReadOnly.Enumerable, T>(values); } - public static ICollection ReadOnlyCollection(ICollection collection) + public static ICollection ReadOnlyCollection(ICollection? collection) { return collection == null || collection.Count == 0 ? EmptyCollection() : new ReadOnly.Collection, T>(collection); } - public static ISet ReadOnlySet(ISet set) + public static ISet ReadOnlySet(ISet? set) { return set == null || set.Count == 0 ? EmptySet() : new ReadOnly.Set, T>(set); } - public static IReadOnlySet StronglyTypedReadOnlySet(ISet set) + public static IReadOnlySet StronglyTypedReadOnlySet(ISet? set) { return set == null || set.Count == 0 ? EmptyReadOnlySet() diff --git a/src/Compilers/Core/Portable/InternalUtilities/StackGuard.cs b/src/Compilers/Core/Portable/InternalUtilities/StackGuard.cs index cc60fa306184c..1c710c23d6a4f 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/StackGuard.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/StackGuard.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Diagnostics; using System.Runtime.CompilerServices; diff --git a/src/Compilers/Core/Portable/InternalUtilities/StreamExtensions.cs b/src/Compilers/Core/Portable/InternalUtilities/StreamExtensions.cs index d4e0da9b9b072..c48eeca8c644c 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/StreamExtensions.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/StreamExtensions.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Diagnostics; using System.IO; diff --git a/src/Compilers/Core/Portable/InternalUtilities/StringExtensions.cs b/src/Compilers/Core/Portable/InternalUtilities/StringExtensions.cs index 3794eef772139..426e52a8d6c45 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/StringExtensions.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/StringExtensions.cs @@ -1,9 +1,12 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace Roslyn.Utilities { @@ -24,7 +27,7 @@ internal static string GetNumeral(int number) return (number < numerals.Length) ? numerals[number] : number.ToString(); } - public static string Join(this IEnumerable source, string separator) + public static string Join(this IEnumerable source, string separator) { if (source == null) { @@ -52,28 +55,31 @@ public static bool LooksLikeTypeParameterName(this string name) private static readonly Func s_toLower = char.ToLower; private static readonly Func s_toUpper = char.ToUpper; - public static string ToPascalCase( - this string shortName, + [return: NotNullIfNotNull(parameterName: "shortName")] + public static string? ToPascalCase( + this string? shortName, bool trimLeadingTypePrefix = true) { return ConvertCase(shortName, trimLeadingTypePrefix, s_toUpper); } - public static string ToCamelCase( - this string shortName, + [return: NotNullIfNotNull(parameterName: "shortName")] + public static string? ToCamelCase( + this string? shortName, bool trimLeadingTypePrefix = true) { return ConvertCase(shortName, trimLeadingTypePrefix, s_toLower); } - private static string ConvertCase( - this string shortName, + [return: NotNullIfNotNull(parameterName: "shortName")] + private static string? ConvertCase( + this string? shortName, bool trimLeadingTypePrefix, Func convert) { // Special case the common .NET pattern of "IGoo" as a type name. In this case we // want to generate "goo" as the parameter name. - if (!string.IsNullOrEmpty(shortName)) + if (!RoslynString.IsNullOrEmpty(shortName)) { if (trimLeadingTypePrefix && (shortName.LooksLikeInterfaceName() || shortName.LooksLikeTypeParameterName())) { @@ -89,17 +95,17 @@ private static string ConvertCase( return shortName; } - internal static bool IsValidClrTypeName(this string name) + internal static bool IsValidClrTypeName([NotNullWhen(returnValue: true)] this string? name) { - return !string.IsNullOrEmpty(name) && name.IndexOf('\0') == -1; + return !RoslynString.IsNullOrEmpty(name) && name.IndexOf('\0') == -1; } /// /// Checks if the given name is a sequence of valid CLR names separated by a dot. /// - internal static bool IsValidClrNamespaceName(this string name) + internal static bool IsValidClrNamespaceName([NotNullWhen(returnValue: true)] this string? name) { - if (string.IsNullOrEmpty(name)) + if (RoslynString.IsNullOrEmpty(name)) { return false; } @@ -124,7 +130,7 @@ internal static string GetWithSingleAttributeSuffix( this string name, bool isCaseSensitive) { - string cleaned = name; + string? cleaned = name; while ((cleaned = GetWithoutAttributeSuffix(cleaned, isCaseSensitive)) != null) { name = cleaned; @@ -135,12 +141,12 @@ internal static string GetWithSingleAttributeSuffix( internal static bool TryGetWithoutAttributeSuffix( this string name, - out string result) + [NotNullWhen(returnValue: true)] out string? result) { return TryGetWithoutAttributeSuffix(name, isCaseSensitive: true, result: out result); } - internal static string GetWithoutAttributeSuffix( + internal static string? GetWithoutAttributeSuffix( this string name, bool isCaseSensitive) { @@ -150,7 +156,7 @@ internal static string GetWithoutAttributeSuffix( internal static bool TryGetWithoutAttributeSuffix( this string name, bool isCaseSensitive, - out string result) + [NotNullWhen(returnValue: true)] out string? result) { if (name.HasAttributeSuffix(isCaseSensitive)) { diff --git a/src/Compilers/Core/Portable/InternalUtilities/StringOrdinalComparer.cs b/src/Compilers/Core/Portable/InternalUtilities/StringOrdinalComparer.cs index a1bcf1d388c75..fbae28f6fbc2e 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/StringOrdinalComparer.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/StringOrdinalComparer.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Collections.Generic; using System.Runtime.CompilerServices; @@ -20,12 +22,12 @@ private StringOrdinalComparer() { } - bool IEqualityComparer.Equals(string a, string b) + bool IEqualityComparer.Equals(string? a, string? b) { return StringOrdinalComparer.Equals(a, b); } - public static bool Equals(string a, string b) + public static bool Equals(string? a, string? b) { // this is fast enough return string.Equals(a, b); diff --git a/src/Compilers/Core/Portable/InternalUtilities/SuppressUnmanagedCodeSecurityAttribute.cs b/src/Compilers/Core/Portable/InternalUtilities/SuppressUnmanagedCodeSecurityAttribute.cs index f748045928114..6f8b90dd076ea 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/SuppressUnmanagedCodeSecurityAttribute.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/SuppressUnmanagedCodeSecurityAttribute.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + namespace System.Security { // The attribute is not portable, but is needed to improve perf of interop calls on desktop. diff --git a/src/Compilers/Core/Portable/InternalUtilities/TextChangeRangeExtensions.cs b/src/Compilers/Core/Portable/InternalUtilities/TextChangeRangeExtensions.cs index 125a8cb5fd525..d30425d64e6b0 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/TextChangeRangeExtensions.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/TextChangeRangeExtensions.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Collections.Generic; using System.Linq; using Microsoft.CodeAnalysis.Text; diff --git a/src/Compilers/Core/Portable/InternalUtilities/ThreadSafeFlagOperations.cs b/src/Compilers/Core/Portable/InternalUtilities/ThreadSafeFlagOperations.cs index 6d65666b7ce64..a421c5439f76c 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/ThreadSafeFlagOperations.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/ThreadSafeFlagOperations.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Threading; namespace Roslyn.Utilities diff --git a/src/Compilers/Core/Portable/InternalUtilities/ThreeState.cs b/src/Compilers/Core/Portable/InternalUtilities/ThreeState.cs index e093b2a3f1e5e..c1d4c15972d38 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/ThreeState.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/ThreeState.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Diagnostics; namespace Microsoft.CodeAnalysis diff --git a/src/Compilers/Core/Portable/InternalUtilities/UICultureUtilities.cs b/src/Compilers/Core/Portable/InternalUtilities/UICultureUtilities.cs index 00523165f2834..dcc658b076b75 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/UICultureUtilities.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/UICultureUtilities.cs @@ -1,6 +1,9 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Reflection; @@ -10,9 +13,9 @@ internal static class UICultureUtilities { // TODO (DevDiv 1117307): Replace with CultureInfo.CurrentUICulture.set when available. private const string currentUICultureName = "CurrentUICulture"; - private readonly static Action s_setCurrentUICulture; + private readonly static Action? s_setCurrentUICulture; - private static bool TryGetCurrentUICultureSetter(out Action setter) + private static bool TryGetCurrentUICultureSetter([NotNullWhen(returnValue: true)] out Action? setter) { const string cultureInfoTypeName = "System.Globalization.CultureInfo"; const string cultureInfoTypeNameGlobalization = cultureInfoTypeName + ", System.Globalization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"; @@ -20,14 +23,14 @@ private static bool TryGetCurrentUICultureSetter(out Action setter) try { var type = Type.GetType(cultureInfoTypeNameGlobalization) ?? typeof(object).GetTypeInfo().Assembly.GetType(cultureInfoTypeName); - if ((object)type == null) + if ((object?)type == null) { setter = null; return false; } var currentUICultureSetter = type.GetTypeInfo().GetDeclaredProperty(currentUICultureName)?.SetMethod; - if ((object)currentUICultureSetter == null || !currentUICultureSetter.IsStatic || currentUICultureSetter.ContainsGenericParameters || currentUICultureSetter.ReturnType != typeof(void)) + if ((object?)currentUICultureSetter == null || !currentUICultureSetter.IsStatic || currentUICultureSetter.ContainsGenericParameters || currentUICultureSetter.ReturnType != typeof(void)) { setter = null; return false; @@ -50,7 +53,7 @@ private static bool TryGetCurrentUICultureSetter(out Action setter) } } - private static bool TryGetCurrentThreadUICultureSetter(out Action setter) + private static bool TryGetCurrentThreadUICultureSetter([NotNullWhen(returnValue: true)] out Action? setter) { const string threadTypeName = "System.Threading.Thread"; const string currentThreadName = "CurrentThread"; @@ -66,14 +69,14 @@ private static bool TryGetCurrentThreadUICultureSetter(out Action s var typeInfo = type.GetTypeInfo(); var currentThreadGetter = typeInfo.GetDeclaredProperty(currentThreadName)?.GetMethod; - if ((object)currentThreadGetter == null || !currentThreadGetter.IsStatic || currentThreadGetter.ContainsGenericParameters || currentThreadGetter.ReturnType != type || currentThreadGetter.GetParameters().Length != 0) + if ((object?)currentThreadGetter == null || !currentThreadGetter.IsStatic || currentThreadGetter.ContainsGenericParameters || currentThreadGetter.ReturnType != type || currentThreadGetter.GetParameters().Length != 0) { setter = null; return false; } var currentUICultureSetter = typeInfo.GetDeclaredProperty(currentUICultureName)?.SetMethod; - if ((object)currentUICultureSetter == null || currentUICultureSetter.IsStatic || currentUICultureSetter.ContainsGenericParameters || currentUICultureSetter.ReturnType != typeof(void)) + if ((object?)currentUICultureSetter == null || currentUICultureSetter.IsStatic || currentUICultureSetter.ContainsGenericParameters || currentUICultureSetter.ReturnType != typeof(void)) { setter = null; return false; diff --git a/src/Compilers/Core/Portable/InternalUtilities/UnicodeCharacterUtilities.cs b/src/Compilers/Core/Portable/InternalUtilities/UnicodeCharacterUtilities.cs index 70baaa492e46b..364fa2a8e6a28 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/UnicodeCharacterUtilities.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/UnicodeCharacterUtilities.cs @@ -1,5 +1,8 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + +using System.Diagnostics.CodeAnalysis; using System.Globalization; namespace Roslyn.Utilities @@ -85,9 +88,9 @@ public static bool IsIdentifierPartCharacter(char ch) /// /// Check that the name is a valid Unicode identifier. /// - public static bool IsValidIdentifier(string name) + public static bool IsValidIdentifier([NotNullWhen(returnValue: true)] string? name) { - if (string.IsNullOrEmpty(name)) + if (RoslynString.IsNullOrEmpty(name)) { return false; } diff --git a/src/Compilers/Core/Portable/InternalUtilities/WeakReferenceExtensions.cs b/src/Compilers/Core/Portable/InternalUtilities/WeakReferenceExtensions.cs index b1e0dd4206830..147a199e13d9d 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/WeakReferenceExtensions.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/WeakReferenceExtensions.cs @@ -1,19 +1,23 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; +using System.Diagnostics.CodeAnalysis; namespace Roslyn.Utilities { // Helpers that are missing from Dev11 implementation: internal static class WeakReferenceExtensions { - public static T GetTarget(this WeakReference reference) where T : class + [return: MaybeNull] + public static T GetTarget(this WeakReference reference) where T : class? { reference.TryGetTarget(out var target); return target; } - public static bool IsNull(this WeakReference reference) where T : class + public static bool IsNull(this WeakReference reference) where T : class? { return !reference.TryGetTarget(out var target); } diff --git a/src/Compilers/Core/Portable/InternalUtilities/XmlUtilities.cs b/src/Compilers/Core/Portable/InternalUtilities/XmlUtilities.cs index 6ee0c03f6f1fd..e4f146d96c90f 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/XmlUtilities.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/XmlUtilities.cs @@ -1,12 +1,13 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Xml; using System.Xml.Linq; -using System.Reflection; namespace Roslyn.Utilities { @@ -64,7 +65,7 @@ private static void CopyAnnotations(XObject source, XObject target) } } - internal static XElement[] TrySelectElements(XNode node, string xpath, out string errorMessage, out bool invalidXPath) + internal static XElement[]? TrySelectElements(XNode node, string xpath, out string? errorMessage, out bool invalidXPath) { errorMessage = null; invalidXPath = false; diff --git a/src/Compilers/Core/Portable/MemberDescriptor.cs b/src/Compilers/Core/Portable/MemberDescriptor.cs index 28dc5e0bac9d7..2c654dc76da00 100644 --- a/src/Compilers/Core/Portable/MemberDescriptor.cs +++ b/src/Compilers/Core/Portable/MemberDescriptor.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using Roslyn.Utilities; using System; using System.Collections.Immutable; @@ -44,7 +46,7 @@ internal struct MemberDescriptor /// public readonly short DeclaringTypeId; - public string DeclaringTypeMetadataName + public string? DeclaringTypeMetadataName { get { diff --git a/src/Compilers/Core/Portable/Operations/Operation.cs b/src/Compilers/Core/Portable/Operations/Operation.cs index 6c91ae9d9a8f6..607ca67a815c9 100644 --- a/src/Compilers/Core/Portable/Operations/Operation.cs +++ b/src/Compilers/Core/Portable/Operations/Operation.cs @@ -147,7 +147,9 @@ protected void SetParentOperation(IOperation parent) ((Operation)parent).OwningSemanticModel == null || OwningSemanticModel == null); // make sure given parent and one we already have is same if we have one already - Debug.Assert(result == s_unset || result == parent); + // This assert is violated in the presence of threading races, tracked by https://github.com/dotnet/roslyn/issues/35818 + // As it's occasionally hitting in test runs, we're commenting out the assert pending fix. + //Debug.Assert(result == s_unset || result == parent); } public static T SetParentOperation(T operation, IOperation parent) where T : IOperation diff --git a/src/Compilers/Core/Portable/OutputKind.cs b/src/Compilers/Core/Portable/OutputKind.cs index 927b0bc9e714b..70d0a46fe2c80 100644 --- a/src/Compilers/Core/Portable/OutputKind.cs +++ b/src/Compilers/Core/Portable/OutputKind.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using Microsoft.CodeAnalysis.Text; using System; using Roslyn.Utilities; diff --git a/src/Compilers/Core/Portable/SourceCodeKind.cs b/src/Compilers/Core/Portable/SourceCodeKind.cs index a32e5aff28195..99828e95593ef 100644 --- a/src/Compilers/Core/Portable/SourceCodeKind.cs +++ b/src/Compilers/Core/Portable/SourceCodeKind.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.ComponentModel; using Microsoft.CodeAnalysis.Text; diff --git a/src/Compilers/Core/Portable/SpecialMember.cs b/src/Compilers/Core/Portable/SpecialMember.cs index d182c41200c81..34d3e811c2c9c 100644 --- a/src/Compilers/Core/Portable/SpecialMember.cs +++ b/src/Compilers/Core/Portable/SpecialMember.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + namespace Microsoft.CodeAnalysis { // members of special types diff --git a/src/Compilers/Core/Portable/SpecialType.cs b/src/Compilers/Core/Portable/SpecialType.cs index a8385a11d5afe..e672c83af3ef5 100644 --- a/src/Compilers/Core/Portable/SpecialType.cs +++ b/src/Compilers/Core/Portable/SpecialType.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Collections; using System.Collections.Generic; diff --git a/src/Compilers/Core/Portable/SpecialTypes.cs b/src/Compilers/Core/Portable/SpecialTypes.cs index 9e0fae427e1dc..b6b3933c1bd4a 100644 --- a/src/Compilers/Core/Portable/SpecialTypes.cs +++ b/src/Compilers/Core/Portable/SpecialTypes.cs @@ -1,8 +1,10 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Collections.Generic; using System.Diagnostics; -using Microsoft.CodeAnalysis.Text; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis { @@ -14,7 +16,7 @@ internal static class SpecialTypes /// that we could use ids to index into the array /// /// - private static readonly string[] s_emittedNames = new string[] + private static readonly string?[] s_emittedNames = new string?[] { // The following things should be in sync: // 1) SpecialType enum @@ -81,8 +83,10 @@ static SpecialTypes() for (i = 1; i < s_emittedNames.Length; i++) { - Debug.Assert(s_emittedNames[i].IndexOf('+') < 0); // Compilers aren't prepared to lookup for a nested special type. - s_nameToTypeIdMap.Add(s_emittedNames[i], (SpecialType)i); + string? name = s_emittedNames[i]; + RoslynDebug.Assert(name is object); + Debug.Assert(name.IndexOf('+') < 0); // Compilers aren't prepared to lookup for a nested special type. + s_nameToTypeIdMap.Add(name, (SpecialType)i); } s_typeIdToTypeCodeMap = new Microsoft.Cci.PrimitiveTypeCode[(int)SpecialType.Count + 1]; @@ -137,7 +141,7 @@ static SpecialTypes() /// /// Gets the name of the special type as it would appear in metadata. /// - public static string GetMetadataName(this SpecialType id) + public static string? GetMetadataName(this SpecialType id) { return s_emittedNames[(int)id]; } diff --git a/src/Compilers/Core/Portable/SynthesizedLocalKind.cs b/src/Compilers/Core/Portable/SynthesizedLocalKind.cs index 4260aaf95315c..9c68fb96ae770 100644 --- a/src/Compilers/Core/Portable/SynthesizedLocalKind.cs +++ b/src/Compilers/Core/Portable/SynthesizedLocalKind.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Reflection.Metadata; using Microsoft.CodeAnalysis.Emit; diff --git a/src/Compilers/Core/Portable/WellKnownMember.cs b/src/Compilers/Core/Portable/WellKnownMember.cs index a8ac7605a21ce..71c06a8b6e622 100644 --- a/src/Compilers/Core/Portable/WellKnownMember.cs +++ b/src/Compilers/Core/Portable/WellKnownMember.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + namespace Microsoft.CodeAnalysis { // Members of well known types diff --git a/src/Compilers/Core/Portable/WellKnownMembers.cs b/src/Compilers/Core/Portable/WellKnownMembers.cs index a2a4c4e2317a4..efb11d1673245 100644 --- a/src/Compilers/Core/Portable/WellKnownMembers.cs +++ b/src/Compilers/Core/Portable/WellKnownMembers.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Collections.Immutable; using System.Reflection.Metadata; using Microsoft.CodeAnalysis.RuntimeMembers; diff --git a/src/Compilers/Core/Portable/WellKnownTypes.cs b/src/Compilers/Core/Portable/WellKnownTypes.cs index 30990f2dc688d..37c70dde93f0b 100644 --- a/src/Compilers/Core/Portable/WellKnownTypes.cs +++ b/src/Compilers/Core/Portable/WellKnownTypes.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System.Collections.Generic; using System.Diagnostics; using Microsoft.CodeAnalysis.Text; diff --git a/src/Compilers/Core/Portable/XmlFileResolver.cs b/src/Compilers/Core/Portable/XmlFileResolver.cs index 378505c47ff60..344487a2e24f5 100644 --- a/src/Compilers/Core/Portable/XmlFileResolver.cs +++ b/src/Compilers/Core/Portable/XmlFileResolver.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; using System.Diagnostics; using System.IO; @@ -14,9 +16,9 @@ public class XmlFileResolver : XmlReferenceResolver { public static XmlFileResolver Default { get; } = new XmlFileResolver(baseDirectory: null); - private readonly string _baseDirectory; + private readonly string? _baseDirectory; - public XmlFileResolver(string baseDirectory) + public XmlFileResolver(string? baseDirectory) { if (baseDirectory != null && PathUtilities.GetPathKind(baseDirectory) != PathKind.Absolute) { @@ -26,7 +28,7 @@ public XmlFileResolver(string baseDirectory) _baseDirectory = baseDirectory; } - public string BaseDirectory + public string? BaseDirectory { get { return _baseDirectory; } } @@ -43,7 +45,7 @@ public string BaseDirectory /// If is relative is used as the base path of . /// /// Normalized XML document file path or null if not found. - public override string ResolveReference(string path, string baseFilePath) + public override string? ResolveReference(string path, string? baseFilePath) { // Dev11: first look relative to the directory containing the file with the element (baseFilepath) // and then look in the base directory (i.e. current working directory of the compiler). @@ -79,12 +81,12 @@ public override Stream OpenRead(string resolvedPath) return FileUtilities.OpenRead(resolvedPath); } - protected virtual bool FileExists(string resolvedPath) + protected virtual bool FileExists(string? resolvedPath) { return File.Exists(resolvedPath); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { // Explicitly check that we're not comparing against a derived type if (obj == null || GetType() != obj.GetType()) diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceAssemblySymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceAssemblySymbol.vb index 3fad0ed476a1c..107d9ed576384 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceAssemblySymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceAssemblySymbol.vb @@ -262,7 +262,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols End If End If - ' CONSIDER Handling badly targetted assembly attributes from netmodules + ' CONSIDER Handling badly targeted assembly attributes from netmodules 'If (attributeUsage.ValidTargets And AttributeTargets.Assembly) = 0 Then ' If Not attribute.HasErrors Then ' 'Error and skip diff --git a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb index 1b576b49a433a..13dcf68477c23 100644 --- a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb +++ b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb @@ -9392,7 +9392,7 @@ End Class" ' and info diagnostic is logged with programmatic suppression information. Dim suppressor = New DiagnosticSuppressorForId("BC40008") - ' Diagnostic '{0}: {1}' was programmatically suppressed by a DiagnosticSuppressor with suppresion ID '{2}' and justification '{3}' + ' Diagnostic '{0}: {1}' was programmatically suppressed by a DiagnosticSuppressor with suppression ID '{2}' and justification '{3}' Dim suppressionMessage = String.Format(CodeAnalysisResources.SuppressionDiagnosticDescriptorMessage, suppressor.SuppressionDescriptor.SuppressedDiagnosticId, New VBDiagnostic(ErrorFactory.ErrorInfo(ERRID.WRN_UseOfObsoleteSymbolNoMessage1, "C"), Location.None).GetMessage(CultureInfo.InvariantCulture), @@ -9450,7 +9450,7 @@ End Class" Assert.DoesNotContain($"warning BC40008", output, StringComparison.Ordinal) Assert.DoesNotContain($"error BC40008", output, StringComparison.Ordinal) - ' Diagnostic '{0}: {1}' was programmatically suppressed by a DiagnosticSuppressor with suppresion ID '{2}' and justification '{3}' + ' Diagnostic '{0}: {1}' was programmatically suppressed by a DiagnosticSuppressor with suppression ID '{2}' and justification '{3}' Dim suppressionMessage = String.Format(CodeAnalysisResources.SuppressionDiagnosticDescriptorMessage, suppressor.SuppressionDescriptor.SuppressedDiagnosticId, New VBDiagnostic(ErrorFactory.ErrorInfo(ERRID.WRN_UseOfObsoleteSymbolNoMessage1, "C"), Location.None).GetMessage(CultureInfo.InvariantCulture), @@ -9510,7 +9510,7 @@ End Class" ' and info diagnostic is logged with programmatic suppression information. Dim suppressor = New DiagnosticSuppressorForId(analyzer.Descriptor.Id) - ' Diagnostic '{0}: {1}' was programmatically suppressed by a DiagnosticSuppressor with suppresion ID '{2}' and justification '{3}' + ' Diagnostic '{0}: {1}' was programmatically suppressed by a DiagnosticSuppressor with suppression ID '{2}' and justification '{3}' Dim suppressionMessage = String.Format(CodeAnalysisResources.SuppressionDiagnosticDescriptorMessage, suppressor.SuppressionDescriptor.SuppressedDiagnosticId, analyzer.Descriptor.MessageFormat, diff --git a/src/Compilers/VisualBasic/Test/Semantic/Compilation/GetSemanticInfoBrokenCodeTests.vb b/src/Compilers/VisualBasic/Test/Semantic/Compilation/GetSemanticInfoBrokenCodeTests.vb index c75455cedf7ff..468b131a9273e 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/Compilation/GetSemanticInfoBrokenCodeTests.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/Compilation/GetSemanticInfoBrokenCodeTests.vb @@ -321,7 +321,7 @@ End Module ) End Sub @@ -2519,52 +2519,52 @@ Class C End Sub public overrides Sub Test1(x As double(,)) - System.Console.WriteLine("Overriden 1") + System.Console.WriteLine("Overridden 1") End Sub public overrides Sub Test2(x As double(,)) - System.Console.WriteLine("Overriden 2") + System.Console.WriteLine("Overridden 2") End Sub public overrides Sub Test3(x As double(,)) - System.Console.WriteLine("Overriden 3") + System.Console.WriteLine("Overridden 3") End Sub public overrides Sub Test4(x As double(,)) - System.Console.WriteLine("Overriden 4") + System.Console.WriteLine("Overridden 4") End Sub public overrides Sub Test5(x As double(,)) - System.Console.WriteLine("Overriden 5") + System.Console.WriteLine("Overridden 5") End Sub public overrides Sub Test6(x As double(,)) - System.Console.WriteLine("Overriden 6") + System.Console.WriteLine("Overridden 6") End Sub public overrides Sub Test7(x As double(,)) - System.Console.WriteLine("Overriden 7") + System.Console.WriteLine("Overridden 7") End Sub public overrides Sub Test8(x As double(,)) - System.Console.WriteLine("Overriden 8") + System.Console.WriteLine("Overridden 8") End Sub public overrides Sub Test9(x As double(,)) - System.Console.WriteLine("Overriden 9") + System.Console.WriteLine("Overridden 9") End Sub public overrides Sub Test10(x As double(,)) - System.Console.WriteLine("Overriden 10") + System.Console.WriteLine("Overridden 10") End Sub public overrides Sub Test11(x As double(,)) - System.Console.WriteLine("Overriden 11") + System.Console.WriteLine("Overridden 11") End Sub public overrides Sub Test12(x As double(,)) - System.Console.WriteLine("Overriden 12") + System.Console.WriteLine("Overridden 12") End Sub public overrides Sub Test13(x As double(,)) - System.Console.WriteLine("Overriden 13") + System.Console.WriteLine("Overridden 13") End Sub public overrides Sub Test14(x As double(,)) - System.Console.WriteLine("Overriden 14") + System.Console.WriteLine("Overridden 14") End Sub public overrides Sub Test15(x As double(,)) - System.Console.WriteLine("Overriden 15") + System.Console.WriteLine("Overridden 15") End Sub public overrides Sub Test16(x As double(,)) - System.Console.WriteLine("Overriden 16") + System.Console.WriteLine("Overridden 16") End Sub End Class @@ -2588,22 +2588,22 @@ Test13 Test14 Test15 Test16 -Overriden 1 -Overriden 2 -Overriden 3 -Overriden 4 -Overriden 5 -Overriden 6 -Overriden 7 -Overriden 8 -Overriden 9 -Overriden 10 -Overriden 11 -Overriden 12 -Overriden 13 -Overriden 14 -Overriden 15 -Overriden 16 +Overridden 1 +Overridden 2 +Overridden 3 +Overridden 4 +Overridden 5 +Overridden 6 +Overridden 7 +Overridden 8 +Overridden 9 +Overridden 10 +Overridden 11 +Overridden 12 +Overridden 13 +Overridden 14 +Overridden 15 +Overridden 16 ]]>) End Sub diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/CustomModifiersTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/CustomModifiersTests.vb index 2717c69772df5..8f60103a6d412 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/CustomModifiersTests.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/CustomModifiersTests.vb @@ -267,7 +267,7 @@ Class CL3 Inherits CL2 Overrides Sub Test(x as Integer) - System.Console.WriteLine("Overriden") + System.Console.WriteLine("Overridden") End Sub End Class ]]> @@ -287,7 +287,7 @@ End Class Assert.True(withoutModifiers.IsSameTypeIgnoringAll(withModifiers)) Assert.NotEqual(withoutModifiers, withModifiers) - CompileAndVerify(compilation, expectedOutput:="Overriden") + CompileAndVerify(compilation, expectedOutput:="Overridden") End Sub @@ -345,7 +345,7 @@ Class CL3 Inherits CL2 Overrides Sub Test(ByRef x as Integer) - System.Console.WriteLine("Overriden") + System.Console.WriteLine("Overridden") End Sub End Class ]]> @@ -358,7 +358,7 @@ End Class Dim test = cl3.GetMember(Of MethodSymbol)("Test") Assert.Equal("Sub CL3.Test(ByRef x As System.Int32 modopt(System.Runtime.CompilerServices.IsConst) modopt(System.Runtime.CompilerServices.IsLong))", test.ToTestDisplayString()) - CompileAndVerify(compilation, expectedOutput:="Overriden") + CompileAndVerify(compilation, expectedOutput:="Overridden") End Sub @@ -416,7 +416,7 @@ Class CL3 Inherits CL2 Overrides Sub Test(ByRef x as Integer) - System.Console.WriteLine("Overriden") + System.Console.WriteLine("Overridden") End Sub End Class ]]> @@ -429,7 +429,7 @@ End Class Dim test = cl3.GetMember(Of MethodSymbol)("Test") Assert.Equal("Sub CL3.Test(ByRef modopt(System.Runtime.CompilerServices.IsConst) x As System.Int32 modopt(System.Runtime.CompilerServices.IsLong))", test.ToTestDisplayString()) - CompileAndVerify(compilation, expectedOutput:="Overriden") + CompileAndVerify(compilation, expectedOutput:="Overridden") End Sub @@ -487,7 +487,7 @@ Class CL3 Inherits CL2 Overrides Sub Test(ByRef x as Integer) - System.Console.WriteLine("Overriden") + System.Console.WriteLine("Overridden") End Sub End Class ]]> @@ -500,7 +500,7 @@ End Class Dim test = cl3.GetMember(Of MethodSymbol)("Test") Assert.Equal("Sub CL3.Test(ByRef x As System.Int32 modopt(System.Runtime.CompilerServices.IsLong))", test.ToTestDisplayString()) - CompileAndVerify(compilation, expectedOutput:="Overriden") + CompileAndVerify(compilation, expectedOutput:="Overridden") End Sub @@ -558,7 +558,7 @@ Class CL3 Inherits CL2 Overrides Sub Test(ByRef x as Integer) - System.Console.WriteLine("Overriden") + System.Console.WriteLine("Overridden") End Sub End Class ]]> @@ -571,7 +571,7 @@ End Class Dim test = cl3.GetMember(Of MethodSymbol)("Test") Assert.Equal("Sub CL3.Test(ByRef modopt(System.Runtime.CompilerServices.IsConst) x As System.Int32 modopt(System.Runtime.CompilerServices.IsVolatile) modopt(System.Runtime.CompilerServices.IsLong))", test.ToTestDisplayString()) - CompileAndVerify(compilation, expectedOutput:="Overriden") + CompileAndVerify(compilation, expectedOutput:="Overridden") End Sub @@ -1030,10 +1030,10 @@ Class CL3 Overrides Property Test As Integer Get - System.Console.WriteLine("Get Overriden") + System.Console.WriteLine("Get Overridden") End Get Set - System.Console.WriteLine("Set Overriden") + System.Console.WriteLine("Set Overridden") End Set End Property End Class @@ -1049,8 +1049,8 @@ End Class Assert.Equal("Function CL3.get_Test() As System.Int32 modopt(System.Runtime.CompilerServices.IsConst) modopt(System.Runtime.CompilerServices.IsLong)", test.GetMethod.ToTestDisplayString()) Assert.Equal("Sub CL3.set_Test(Value As System.Int32 modopt(System.Runtime.CompilerServices.IsConst) modopt(System.Runtime.CompilerServices.IsLong))", test.SetMethod.ToTestDisplayString()) - CompileAndVerify(compilation, expectedOutput:="Set Overriden -Get Overriden") + CompileAndVerify(compilation, expectedOutput:="Set Overridden +Get Overridden") End Sub @@ -1108,7 +1108,7 @@ Class CL3 Inherits CL2 Overrides Sub Test(x as Integer()) - System.Console.WriteLine("Overriden") + System.Console.WriteLine("Overridden") End Sub End Class ]]> @@ -1121,7 +1121,7 @@ End Class Dim test = cl3.GetMember(Of MethodSymbol)("Test") Assert.Equal("Sub CL3.Test(x As System.Int32 modopt(System.Runtime.CompilerServices.IsConst) modopt(System.Runtime.CompilerServices.IsLong) ())", test.ToTestDisplayString()) - CompileAndVerify(compilation, expectedOutput:="Overriden") + CompileAndVerify(compilation, expectedOutput:="Overridden") End Sub @@ -1714,7 +1714,7 @@ Class CL3 Inherits CL2 Overrides Function Test(x as System.Func(Of Integer, Integer), y as Integer) As Integer - System.Console.WriteLine("Overriden") + System.Console.WriteLine("Overridden") return x(y) End Function End Class @@ -1727,9 +1727,9 @@ End Class CompileAndVerify(compilation, expectedOutput:="Test 1 Test 2 -Overriden +Overridden Test 3 -Overriden +Overridden Test 4 MyDelegate Test 5 @@ -1780,7 +1780,7 @@ class Test11 Inherits Test1 public overrides Sub Test(c As Integer(,)) - System.Console.WriteLine("Overriden") + System.Console.WriteLine("Overridden") End Sub End Class ]]> @@ -1790,7 +1790,7 @@ End Class Dim compilation = CreateCompilationWithCustomILSource(vbSource, ilSource, options:=TestOptions.ReleaseExe) CompileAndVerify(compilation, expectedOutput:="Test -Overriden") +Overridden") End Sub @@ -1851,7 +1851,7 @@ class CL3 Inherits CL2 public overrides Sub Test(c As Integer) - System.Console.WriteLine("Overriden") + System.Console.WriteLine("Overridden") end Sub End Class ]]> @@ -1861,7 +1861,7 @@ End Class Dim compilation = CreateCompilationWithCustomILSource(vbSource, ilSource, options:=TestOptions.ReleaseExe) CompileAndVerify(compilation, expectedOutput:="Test -Overriden") +Overridden") End Sub @@ -1922,7 +1922,7 @@ class CL3 Inherits CL2 public overrides Sub Test(c As Integer) - System.Console.WriteLine("Overriden") + System.Console.WriteLine("Overridden") end Sub End Class ]]> @@ -1932,7 +1932,7 @@ End Class Dim compilation = CreateCompilationWithCustomILSource(vbSource, ilSource, options:=TestOptions.ReleaseExe) CompileAndVerify(compilation, expectedOutput:="Test -Overriden") +Overridden") End Sub @@ -1994,7 +1994,7 @@ class CL3 Inherits CL2 public overrides Function Test(c As Integer) As Integer() - System.Console.WriteLine("Overriden") + System.Console.WriteLine("Overridden") return Nothing end Function End Class @@ -2005,7 +2005,7 @@ End Class Dim compilation = CreateCompilationWithCustomILSource(vbSource, ilSource, options:=TestOptions.ReleaseExe) CompileAndVerify(compilation, expectedOutput:="Test -Overriden") +Overridden") End Sub @@ -2024,7 +2024,7 @@ class CL2 Inherits CL1 public overrides Function Test(Of U As Structure)(c As System.ValueType) As System.ValueType - System.Console.WriteLine("Overriden") + System.Console.WriteLine("Overridden") return c end Function End Class @@ -2041,7 +2041,7 @@ End Class Assert.Equal("Function CL2.Test(Of U)(c As System.ValueType modopt(System.Runtime.CompilerServices.IsBoxed) modopt(System.Nullable(Of U))) As System.ValueType modopt(System.Runtime.CompilerServices.IsBoxed) modopt(System.Nullable(Of U))", test.ToTestDisplayString()) Assert.Equal("Function CL1.Test(Of T)(x As System.ValueType modopt(System.Runtime.CompilerServices.IsBoxed) modopt(System.Nullable(Of T))) As System.ValueType modopt(System.Runtime.CompilerServices.IsBoxed) modopt(System.Nullable(Of T))", test.OverriddenMethod.ToTestDisplayString()) - CompileAndVerify(compilation, expectedOutput:="Overriden") + CompileAndVerify(compilation, expectedOutput:="Overridden") End Sub diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/WinMdEventTest.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/WinMdEventTest.vb index e83b9b06fcdea..1b9c50b2845c6 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/WinMdEventTest.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/WinMdEventTest.vb @@ -134,7 +134,7 @@ End Class Public Sub New() - ' The following two libraries are shrinked code pulled from + ' The following two libraries are shrunk code pulled from ' corresponding files in the csharp5 legacy tests Dim eventLibSrc = diff --git a/src/EditorFeatures/CSharpTest/SignatureHelp/InitializerExpressionSignatureHelpProviderTests.cs b/src/EditorFeatures/CSharpTest/SignatureHelp/InitializerExpressionSignatureHelpProviderTests.cs new file mode 100644 index 0000000000000..1df8cca71dd02 --- /dev/null +++ b/src/EditorFeatures/CSharpTest/SignatureHelp/InitializerExpressionSignatureHelpProviderTests.cs @@ -0,0 +1,218 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.SignatureHelp; +using Microsoft.CodeAnalysis.Editor.UnitTests.SignatureHelp; +using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; +using Microsoft.CodeAnalysis.SignatureHelp; +using Microsoft.CodeAnalysis.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.SignatureHelp +{ + public class InitializerExpressionSignatureHelpProviderTests : AbstractCSharpSignatureHelpProviderTests + { + public InitializerExpressionSignatureHelpProviderTests(CSharpTestWorkspaceFixture workspaceFixture) : base(workspaceFixture) + { + } + + internal override ISignatureHelpProvider CreateSignatureHelpProvider() + => new InitializerExpressionSignatureHelpProvider(); + + [Fact, Trait(Traits.Feature, Traits.Features.SignatureHelp)] + public async Task WithSingleParamAddMethods() + { + var markup = @" +using System.Collections.Generic; + +class C +{ + void Goo() + { + new List { { $$ + } +}"; + + var expectedOrderedItems = new List(); + expectedOrderedItems.Add(new SignatureHelpTestItem("void List.Add(int item)", currentParameterIndex: 0)); + + await TestAsync(markup, expectedOrderedItems); + } + + [Fact, Trait(Traits.Feature, Traits.Features.SignatureHelp)] + public async Task ForMultiParamAddMethods() + { + var markup = @" +using System.Collections.Generic; + +class C +{ + void Goo() + { + new Dictionary { { $$ + } +}"; + + var expectedOrderedItems = new List(); + expectedOrderedItems.Add(new SignatureHelpTestItem("void Dictionary.Add(int key, string value)", currentParameterIndex: 0)); + + await TestAsync(markup, expectedOrderedItems); + } + + [Fact, Trait(Traits.Feature, Traits.Features.SignatureHelp)] + public async Task ForSecondParam() + { + var markup = @" +using System.Collections.Generic; + +class C +{ + void Goo() + { + new Dictionary { { 0, $$ + } +}"; + + var expectedOrderedItems = new List(); + expectedOrderedItems.Add(new SignatureHelpTestItem("void Dictionary.Add(int key, string value)", currentParameterIndex: 1)); + + await TestAsync(markup, expectedOrderedItems); + } + + [Fact, Trait(Traits.Feature, Traits.Features.SignatureHelp)] + public async Task ForNestedCollectionInitializer() + { + var markup = @" +using System.Collections.Generic; + +class Bar +{ + public Dictionary D; +} + +class C +{ + void Goo() + { + new Bar { D = { { $$ + } +}"; + + var expectedOrderedItems = new List(); + expectedOrderedItems.Add(new SignatureHelpTestItem("void Dictionary.Add(int key, string value)", currentParameterIndex: 0)); + + await TestAsync(markup, expectedOrderedItems); + } + + [Fact, Trait(Traits.Feature, Traits.Features.SignatureHelp)] + public async Task WithoutClosingBraces() + { + var markup = @" +using System.Collections.Generic; + +class Bar +{ + public Dictionary D; +} + +class C +{ + void Goo() + { + new Bar { D = { { $$ +"; + + var expectedOrderedItems = new List(); + expectedOrderedItems.Add(new SignatureHelpTestItem("void Dictionary.Add(int key, string value)", currentParameterIndex: 0)); + + await TestAsync(markup, expectedOrderedItems); + } + + [Fact, Trait(Traits.Feature, Traits.Features.SignatureHelp)] + public async Task WithMultipleAddMethods() + { + var markup = @" +using System.Collections; + +class Bar : IEnumerable +{ + public void Add(int i) { } + public void Add(int i, string s) { } + public void Add(int i, string s, bool b) { } +} + +class C +{ + void Goo() + { + new Bar { { $$ +"; + + var expectedOrderedItems = new List(); + expectedOrderedItems.Add(new SignatureHelpTestItem("void Bar.Add(int i)", currentParameterIndex: 0)); + expectedOrderedItems.Add(new SignatureHelpTestItem("void Bar.Add(int i, string s)", currentParameterIndex: 0, isSelected: true)); + expectedOrderedItems.Add(new SignatureHelpTestItem("void Bar.Add(int i, string s, bool b)", currentParameterIndex: 0)); + + await TestAsync(markup, expectedOrderedItems); + } + + [Fact, Trait(Traits.Feature, Traits.Features.SignatureHelp)] + public async Task DoesNotImplementIEnumerable() + { + var markup = @" +using System.Collections; + +class Bar +{ + public void Add(int i) { } + public void Add(int i, string s) { } + public void Add(int i, string s, bool b) { } +} + +class C +{ + void Goo() + { + new Bar { { $$ +"; + + var expectedOrderedItems = new List(); + + await TestAsync(markup, expectedOrderedItems); + } + + [Fact, Trait(Traits.Feature, Traits.Features.SignatureHelp)] + public async Task WithExtensionAddMethods() + { + var markup = @" +using System.Collections; + +class Bar : IEnumerable +{ +} + +static class Extensions +{ + public static void Add(this Bar b, int i) { } + public static void Add(this Bar b, int i, string s) { } + public static void Add(this Bar b, int i, string s, bool b) { } +} + +class C +{ + void Goo() + { + new Bar { { $$ +"; + + var expectedOrderedItems = new List(); + expectedOrderedItems.Add(new SignatureHelpTestItem($"({CSharpFeaturesResources.extension}) void Bar.Add(int i)", currentParameterIndex: 0)); + expectedOrderedItems.Add(new SignatureHelpTestItem($"({CSharpFeaturesResources.extension}) void Bar.Add(int i, string s)", currentParameterIndex: 0, isSelected: true)); + expectedOrderedItems.Add(new SignatureHelpTestItem($"({CSharpFeaturesResources.extension}) void Bar.Add(int i, string s, bool b)", currentParameterIndex: 0)); + + await TestAsync(markup, expectedOrderedItems, sourceCodeKind: SourceCodeKind.Regular); + } + } +} diff --git a/src/EditorFeatures/Test2/GoToDefinition/GoToDefinitionTests.vb b/src/EditorFeatures/Test2/GoToDefinition/GoToDefinitionTests.vb index 3a69ecdb96aaf..8873e3281aecc 100644 --- a/src/EditorFeatures/Test2/GoToDefinition/GoToDefinitionTests.vb +++ b/src/EditorFeatures/Test2/GoToDefinition/GoToDefinitionTests.vb @@ -1018,7 +1018,7 @@ namespace System Dim workspace = - + class Program { diff --git a/src/EditorFeatures/Test2/Simplification/TypeInferenceSimplifierTests.vb b/src/EditorFeatures/Test2/Simplification/TypeInferenceSimplifierTests.vb index 5ea9a237aaf8d..a9754a9ca7652 100644 --- a/src/EditorFeatures/Test2/Simplification/TypeInferenceSimplifierTests.vb +++ b/src/EditorFeatures/Test2/Simplification/TypeInferenceSimplifierTests.vb @@ -19,7 +19,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Simplification End Class Class B Inherits C - Public Shared Funtion Goo() As Integer + Public Shared Function Goo() As Integer End Function End Class Module Program @@ -48,7 +48,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Simplification End Class Class B Inherits C - Public Shared Funtion Goo() As Integer + Public Shared Function Goo() As Integer End Function End Class Module Program diff --git a/src/EditorFeatures/TestUtilities/SignatureHelp/AbstractSignatureHelpProviderTests.cs b/src/EditorFeatures/TestUtilities/SignatureHelp/AbstractSignatureHelpProviderTests.cs index ff75dfbbe0dff..34bc3dc602dcb 100644 --- a/src/EditorFeatures/TestUtilities/SignatureHelp/AbstractSignatureHelpProviderTests.cs +++ b/src/EditorFeatures/TestUtilities/SignatureHelp/AbstractSignatureHelpProviderTests.cs @@ -182,7 +182,7 @@ private async Task VerifyCurrentParameterNameWorkerAsync(string markup, string e } private void CompareAndAssertCollectionsAndCurrentParameter( - IEnumerable expectedTestItems, SignatureHelpItems actualSignatureHelpItems, ISignatureHelpProvider signatureHelpProvider, Document document, int cursorPosition) + IEnumerable expectedTestItems, SignatureHelpItems actualSignatureHelpItems) { Assert.Equal(expectedTestItems.Count(), actualSignatureHelpItems.Items.Count()); @@ -191,22 +191,14 @@ private void CompareAndAssertCollectionsAndCurrentParameter( CompareSigHelpItemsAndCurrentPosition( actualSignatureHelpItems, actualSignatureHelpItems.Items.ElementAt(i), - expectedTestItems.ElementAt(i), - signatureHelpProvider, - document, - cursorPosition, - actualSignatureHelpItems.ApplicableSpan); + expectedTestItems.ElementAt(i)); } } private void CompareSigHelpItemsAndCurrentPosition( SignatureHelpItems items, SignatureHelpItem actualSignatureHelpItem, - SignatureHelpTestItem expectedTestItem, - ISignatureHelpProvider signatureHelpProvider, - Document document, - int cursorPosition, - TextSpan applicableSpan) + SignatureHelpTestItem expectedTestItem) { var currentParameterIndex = -1; if (expectedTestItem.CurrentParameterIndex != null) @@ -347,31 +339,30 @@ private async Task TestSignatureHelpInSameProjectHelperAsync(string sourceCode, protected async Task VerifyItemWithReferenceWorkerAsync(string xmlString, IEnumerable expectedOrderedItems, bool hideAdvancedMembers) { - using (var testWorkspace = TestWorkspace.Create(xmlString)) - { - var cursorPosition = testWorkspace.Documents.First(d => d.Name == "SourceDocument").CursorPosition.Value; - var documentId = testWorkspace.Documents.First(d => d.Name == "SourceDocument").Id; - var document = testWorkspace.CurrentSolution.GetDocument(documentId); - var code = (await document.GetTextAsync()).ToString(); + using var testWorkspace = TestWorkspace.Create(xmlString); - testWorkspace.Options = testWorkspace.Options.WithChangedOption(CompletionOptions.HideAdvancedMembers, document.Project.Language, hideAdvancedMembers); + var cursorPosition = testWorkspace.Documents.First(d => d.Name == "SourceDocument").CursorPosition.Value; + var documentId = testWorkspace.Documents.First(d => d.Name == "SourceDocument").Id; + var document = testWorkspace.CurrentSolution.GetDocument(documentId); + var code = (await document.GetTextAsync()).ToString(); - IList textSpans = null; + testWorkspace.Options = testWorkspace.Options.WithChangedOption(CompletionOptions.HideAdvancedMembers, document.Project.Language, hideAdvancedMembers); - var selectedSpans = testWorkspace.Documents.First(d => d.Name == "SourceDocument").SelectedSpans; - if (selectedSpans.Any()) - { - textSpans = selectedSpans; - } + IList textSpans = null; - TextSpan? textSpan = null; - if (textSpans != null && textSpans.Any()) - { - textSpan = textSpans.First(); - } + var selectedSpans = testWorkspace.Documents.First(d => d.Name == "SourceDocument").SelectedSpans; + if (selectedSpans.Any()) + { + textSpans = selectedSpans; + } - await TestSignatureHelpWorkerSharedAsync(code, cursorPosition, SourceCodeKind.Regular, document, textSpan, expectedOrderedItems); + TextSpan? textSpan = null; + if (textSpans != null && textSpans.Any()) + { + textSpan = textSpans.First(); } + + await TestSignatureHelpWorkerSharedAsync(code, cursorPosition, SourceCodeKind.Regular, document, textSpan, expectedOrderedItems); } private async Task TestSignatureHelpWorkerSharedAsync( @@ -416,7 +407,7 @@ private async Task TestSignatureHelpWorkerSharedAsync( if (expectedOrderedItemsOrNull != null) { - CompareAndAssertCollectionsAndCurrentParameter(expectedOrderedItemsOrNull, items, signatureHelpProvider, document, cursorPosition); + CompareAndAssertCollectionsAndCurrentParameter(expectedOrderedItemsOrNull, items); CompareSelectedIndex(expectedOrderedItemsOrNull, items.SelectedItemIndex); } } @@ -464,29 +455,28 @@ protected async Task TestSignatureHelpWithMscorlib45Async( ", sourceLanguage, SecurityElement.Escape(markup)); - using (var testWorkspace = TestWorkspace.Create(xmlString)) - { - var cursorPosition = testWorkspace.Documents.Single(d => d.Name == "SourceDocument").CursorPosition.Value; - var documentId = testWorkspace.Documents.Where(d => d.Name == "SourceDocument").Single().Id; - var document = testWorkspace.CurrentSolution.GetDocument(documentId); - var code = (await document.GetTextAsync()).ToString(); + using var testWorkspace = TestWorkspace.Create(xmlString); - IList textSpans = null; + var cursorPosition = testWorkspace.Documents.Single(d => d.Name == "SourceDocument").CursorPosition.Value; + var documentId = testWorkspace.Documents.Where(d => d.Name == "SourceDocument").Single().Id; + var document = testWorkspace.CurrentSolution.GetDocument(documentId); + var code = (await document.GetTextAsync()).ToString(); - var selectedSpans = testWorkspace.Documents.Single(d => d.Name == "SourceDocument").SelectedSpans; - if (selectedSpans.Any()) - { - textSpans = selectedSpans; - } + IList textSpans = null; - TextSpan? textSpan = null; - if (textSpans != null && textSpans.Any()) - { - textSpan = textSpans.First(); - } + var selectedSpans = testWorkspace.Documents.Single(d => d.Name == "SourceDocument").SelectedSpans; + if (selectedSpans.Any()) + { + textSpans = selectedSpans; + } - await TestSignatureHelpWorkerSharedAsync(code, cursorPosition, SourceCodeKind.Regular, document, textSpan, expectedOrderedItems); + TextSpan? textSpan = null; + if (textSpans != null && textSpans.Any()) + { + textSpan = textSpans.First(); } + + await TestSignatureHelpWorkerSharedAsync(code, cursorPosition, SourceCodeKind.Regular, document, textSpan, expectedOrderedItems); } } } diff --git a/src/EditorFeatures/VisualBasicTest/SignatureHelp/CollectionInitializerSignatureHelpProviderTests.vb b/src/EditorFeatures/VisualBasicTest/SignatureHelp/CollectionInitializerSignatureHelpProviderTests.vb new file mode 100644 index 0000000000000..87fcd5bc849a2 --- /dev/null +++ b/src/EditorFeatures/VisualBasicTest/SignatureHelp/CollectionInitializerSignatureHelpProviderTests.vb @@ -0,0 +1,174 @@ +' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +Imports Microsoft.CodeAnalysis.Editor.UnitTests.SignatureHelp +Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces +Imports Microsoft.CodeAnalysis.SignatureHelp +Imports Microsoft.CodeAnalysis.VisualBasic.SignatureHelp + +Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.SignatureHelp + Public Class CollectionInitializerSignatureHelpProviderTests + Inherits AbstractVisualBasicSignatureHelpProviderTests + + Public Sub New(workspaceFixture As VisualBasicTestWorkspaceFixture) + MyBase.New(workspaceFixture) + End Sub + + Friend Overrides Function CreateSignatureHelpProvider() As ISignatureHelpProvider + Return New CollectionInitializerSignatureHelpProvider() + End Function + + + Public Async Function ForSingleParamAddMethods() As Task + Dim markup = " +imports System.Collections.Generic + +class C + sub Goo() + dim a = new List(of integer) from { { $$ + end sub +end class" + + Dim expectedOrderedItems = New List(Of SignatureHelpTestItem)() + expectedOrderedItems.Add(New SignatureHelpTestItem("List(Of Integer).Add(item As Integer)", currentParameterIndex:=0)) + + Await TestAsync(markup, expectedOrderedItems) + End Function + + + Public Async Function ForMultiParamAddMethods() As Task + Dim markup = " +imports System.Collections.Generic + +class C + sub Goo() + dim a = new Dictionary(of integer, string) from { { $$ + end sub +end class" + + Dim expectedOrderedItems = New List(Of SignatureHelpTestItem)() + expectedOrderedItems.Add(New SignatureHelpTestItem("Dictionary(Of Integer, String).Add(key As Integer, value As String)", currentParameterIndex:=0)) + + Await TestAsync(markup, expectedOrderedItems) + End Function + + + Public Async Function ForSecondParam() As Task + Dim markup = " +imports System.Collections.Generic + +class C + sub Goo() + dim a = new Dictionary(of integer, string) from { { 0, $$ + end sub +end class" + + Dim expectedOrderedItems = New List(Of SignatureHelpTestItem)() + expectedOrderedItems.Add(New SignatureHelpTestItem("Dictionary(Of Integer, String).Add(key As Integer, value As String)", currentParameterIndex:=1)) + + Await TestAsync(markup, expectedOrderedItems) + End Function + + + Public Async Function WithoutClosingConstructs() As Task + Dim markup = " +imports System.Collections.Generic + +class C + sub Goo() + dim a = new Dictionary(of integer, string) from { { 0, $$ +" + + Dim expectedOrderedItems = New List(Of SignatureHelpTestItem)() + expectedOrderedItems.Add(New SignatureHelpTestItem("Dictionary(Of Integer, String).Add(key As Integer, value As String)", currentParameterIndex:=1)) + + Await TestAsync(markup, expectedOrderedItems) + End Function + + + Public Async Function WithMultipleAddMethods() As Task + Dim markup = " +imports System.Collections + +class Bar + implements IEnumerable + + public sub Add(i as integer) + end sub + public sub Add(i as integer, s as string) + end sub + public sub Add(i as integer, s as string, b as boolean) + end sub +end class + +class C + sub Goo() + dim as = new Bar from { { $$ +" + + Dim expectedOrderedItems = New List(Of SignatureHelpTestItem)() + expectedOrderedItems.Add(New SignatureHelpTestItem("Bar.Add(i As Integer)", currentParameterIndex:=0)) + expectedOrderedItems.Add(New SignatureHelpTestItem("Bar.Add(i As Integer, s As String)", currentParameterIndex:=0, isSelected:=True)) + expectedOrderedItems.Add(New SignatureHelpTestItem("Bar.Add(i As Integer, s As String, b As Boolean)", currentParameterIndex:=0)) + + Await TestAsync(markup, expectedOrderedItems) + End Function + + + Public Async Function DoesNotImplementIEnumerable() As Task + Dim markup = " +imports System.Collections + +class Bar + public sub Add(i as integer) + end sub + public sub Add(i as integer, s as string) + end sub + public sub Add(i as integer, s as string, b as boolean) + end sub +end class + +class C + sub Goo() + dim as = new Bar from { { $$ +" + + Dim expectedOrderedItems = New List(Of SignatureHelpTestItem)() + + Await TestAsync(markup, expectedOrderedItems) + End Function + + + Public Async Function WithExtensionAddMethods() As Task + Dim markup = " +imports System.Collections + +class Bar + implements IEnumerable +end class + +module Extensions + + public sub Add(b as bar, i as integer) + end sub + + public sub Add(b as bar, i as integer, s as string) + end sub + + public sub Add(b as bar, i as integer, s as string, b as boolean) + end sub +end module + +class C + sub Goo() + dim a = new Bar from { { $$ +" + + Dim expectedOrderedItems = New List(Of SignatureHelpTestItem)() + expectedOrderedItems.Add(New SignatureHelpTestItem($"<{VBFeaturesResources.Extension}> Extensions.Add(i As Integer)", currentParameterIndex:=0)) + expectedOrderedItems.Add(New SignatureHelpTestItem($"<{VBFeaturesResources.Extension}> Extensions.Add(i As Integer, s As String)", currentParameterIndex:=0, isSelected:=True)) + expectedOrderedItems.Add(New SignatureHelpTestItem($"<{VBFeaturesResources.Extension}> Extensions.Add(i As Integer, s As String, b As Boolean)", currentParameterIndex:=0)) + + Await TestAsync(markup, expectedOrderedItems, sourceCodeKind:=SourceCodeKind.Regular) + End Function + End Class +End Namespace diff --git a/src/ExpressionEvaluator/CSharp/Source/ResultProvider/NetFX20/CSharpResultProvider.NetFX20.csproj b/src/ExpressionEvaluator/CSharp/Source/ResultProvider/NetFX20/CSharpResultProvider.NetFX20.csproj index d414297a1c4c9..f7a4e41c525be 100644 --- a/src/ExpressionEvaluator/CSharp/Source/ResultProvider/NetFX20/CSharpResultProvider.NetFX20.csproj +++ b/src/ExpressionEvaluator/CSharp/Source/ResultProvider/NetFX20/CSharpResultProvider.NetFX20.csproj @@ -10,6 +10,9 @@ partial + + Compiler\Parser\RoslynString.cs + Compiler\Parser\UnicodeCharacterUtilities.cs diff --git a/src/ExpressionEvaluator/CSharp/Source/ResultProvider/Portable/Microsoft.CodeAnalysis.CSharp.ResultProvider.csproj b/src/ExpressionEvaluator/CSharp/Source/ResultProvider/Portable/Microsoft.CodeAnalysis.CSharp.ResultProvider.csproj index 262a93cd0ea86..d722c6d871030 100644 --- a/src/ExpressionEvaluator/CSharp/Source/ResultProvider/Portable/Microsoft.CodeAnalysis.CSharp.ResultProvider.csproj +++ b/src/ExpressionEvaluator/CSharp/Source/ResultProvider/Portable/Microsoft.CodeAnalysis.CSharp.ResultProvider.csproj @@ -10,6 +10,9 @@ partial + + Compiler\Parser\RoslynString.cs + Compiler\Parser\UnicodeCharacterUtilities.cs diff --git a/src/ExpressionEvaluator/Core/Source/FunctionResolver/Microsoft.CodeAnalysis.FunctionResolver.csproj b/src/ExpressionEvaluator/Core/Source/FunctionResolver/Microsoft.CodeAnalysis.FunctionResolver.csproj index 7b45e52e5c825..50ab8f0a8db8f 100644 --- a/src/ExpressionEvaluator/Core/Source/FunctionResolver/Microsoft.CodeAnalysis.FunctionResolver.csproj +++ b/src/ExpressionEvaluator/Core/Source/FunctionResolver/Microsoft.CodeAnalysis.FunctionResolver.csproj @@ -22,6 +22,12 @@ Compiler\WellKnownMemberNames.cs + + Compiler\NullableAttributes.cs + + + Compiler\RoslynString.cs + Compiler\UnicodeCharacterUtilities.cs diff --git a/src/ExpressionEvaluator/Core/Source/ResultProvider/NetFX20/ResultProvider.NetFX20.csproj b/src/ExpressionEvaluator/Core/Source/ResultProvider/NetFX20/ResultProvider.NetFX20.csproj index 33e88570249bc..977477107bfe7 100644 --- a/src/ExpressionEvaluator/Core/Source/ResultProvider/NetFX20/ResultProvider.NetFX20.csproj +++ b/src/ExpressionEvaluator/Core/Source/ResultProvider/NetFX20/ResultProvider.NetFX20.csproj @@ -18,6 +18,9 @@ Compiler\Collections\PooledStringBuilder.cs + + Compiler\InternalUtilities\Debug.cs + Compiler\InternalUtilities\FailFast.cs @@ -30,6 +33,9 @@ Compiler\InternalUtilities\ExceptionUtilities.cs + + Compiler\InternalUtilities\NullableAttributes.cs + Compiler\InternalUtilities\ObjectPool`1.cs diff --git a/src/ExpressionEvaluator/Core/Source/ResultProvider/Portable/Microsoft.CodeAnalysis.ResultProvider.csproj b/src/ExpressionEvaluator/Core/Source/ResultProvider/Portable/Microsoft.CodeAnalysis.ResultProvider.csproj index 264186335019f..ce71fd807d091 100644 --- a/src/ExpressionEvaluator/Core/Source/ResultProvider/Portable/Microsoft.CodeAnalysis.ResultProvider.csproj +++ b/src/ExpressionEvaluator/Core/Source/ResultProvider/Portable/Microsoft.CodeAnalysis.ResultProvider.csproj @@ -16,6 +16,9 @@ Compiler\Collections\PooledStringBuilder.cs + + Compiler\InternalUtilities\Debug.cs + Compiler\InternalUtilities\FailFast.cs @@ -28,6 +31,9 @@ Compiler\InternalUtilities\ExceptionUtilities.cs + + Compiler\InternalUtilities\NullableAttributes.cs + Compiler\InternalUtilities\ReflectionUtilities.cs diff --git a/src/ExpressionEvaluator/Core/Source/ResultProvider/SystemHelpers.cs b/src/ExpressionEvaluator/Core/Source/ResultProvider/SystemHelpers.cs index c2b8d864cce98..f469f782019f6 100644 --- a/src/ExpressionEvaluator/Core/Source/ResultProvider/SystemHelpers.cs +++ b/src/ExpressionEvaluator/Core/Source/ResultProvider/SystemHelpers.cs @@ -7,7 +7,13 @@ namespace System.Diagnostics internal static class Debug { [Conditional("DEBUG")] - public static void Assert(bool condition, string message = null) + public static void Assert(bool condition) + { + Assert(condition, null); + } + + [Conditional("DEBUG")] + public static void Assert(bool condition, string message) { if (!condition) { diff --git a/src/ExpressionEvaluator/Core/Test/ResultProvider/Microsoft.CodeAnalysis.ResultProvider.Utilities.csproj b/src/ExpressionEvaluator/Core/Test/ResultProvider/Microsoft.CodeAnalysis.ResultProvider.Utilities.csproj index 61c8fc3a07c51..e2d52e1b7b0fa 100644 --- a/src/ExpressionEvaluator/Core/Test/ResultProvider/Microsoft.CodeAnalysis.ResultProvider.Utilities.csproj +++ b/src/ExpressionEvaluator/Core/Test/ResultProvider/Microsoft.CodeAnalysis.ResultProvider.Utilities.csproj @@ -27,6 +27,9 @@ Compiler\Collections\PooledStringBuilder.cs + + Compiler\InternalUtilities\Debug.cs + Compiler\InternalUtilities\FailFast.cs @@ -39,6 +42,9 @@ Compiler\InternalUtilities\ExceptionUtilities.cs + + Compiler\InternalUtilities\NullableAttributes.cs + Compiler\InternalUtilities\ReflectionUtilities.cs diff --git a/src/Features/CSharp/Portable/SignatureHelp/AbstractOrdinaryMethodSignatureHelpProvider.cs b/src/Features/CSharp/Portable/SignatureHelp/AbstractOrdinaryMethodSignatureHelpProvider.cs new file mode 100644 index 0000000000000..7de4d16c15716 --- /dev/null +++ b/src/Features/CSharp/Portable/SignatureHelp/AbstractOrdinaryMethodSignatureHelpProvider.cs @@ -0,0 +1,81 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using Microsoft.CodeAnalysis.DocumentationComments; +using Microsoft.CodeAnalysis.LanguageServices; +using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.SignatureHelp; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.CSharp.SignatureHelp +{ + internal abstract class AbstractOrdinaryMethodSignatureHelpProvider : AbstractCSharpSignatureHelpProvider + { + protected SignatureHelpItem ConvertMethodGroupMethod( + Document document, + IMethodSymbol method, + int position, + SemanticModel semanticModel, + CancellationToken cancellationToken) + { + var anonymousTypeDisplayService = document.GetLanguageService(); + var documentationCommentFormattingService = document.GetLanguageService(); + var symbolDisplayService = document.GetLanguageService(); + + return CreateItem( + method, semanticModel, position, + symbolDisplayService, anonymousTypeDisplayService, + method.IsParams(), + c => method.OriginalDefinition.GetDocumentationParts(semanticModel, position, documentationCommentFormattingService, c).Concat(GetAwaitableUsage(method, semanticModel, position)), + GetMethodGroupPreambleParts(method, semanticModel, position), + GetSeparatorParts(), + GetMethodGroupPostambleParts(method), + method.Parameters.Select(p => Convert(p, semanticModel, position, documentationCommentFormattingService, cancellationToken)).ToList()); + } + + private IList GetMethodGroupPreambleParts( + IMethodSymbol method, + SemanticModel semanticModel, + int position) + { + var result = new List(); + + var awaitable = method.GetOriginalUnreducedDefinition().IsAwaitableNonDynamic(semanticModel, position); + var extension = method.GetOriginalUnreducedDefinition().IsExtensionMethod(); + + if (awaitable && extension) + { + result.Add(Punctuation(SyntaxKind.OpenParenToken)); + result.Add(Text(CSharpFeaturesResources.awaitable)); + result.Add(Punctuation(SyntaxKind.CommaToken)); + result.Add(Text(CSharpFeaturesResources.extension)); + result.Add(Punctuation(SyntaxKind.CloseParenToken)); + result.Add(Space()); + } + else if (awaitable) + { + result.Add(Punctuation(SyntaxKind.OpenParenToken)); + result.Add(Text(CSharpFeaturesResources.awaitable)); + result.Add(Punctuation(SyntaxKind.CloseParenToken)); + result.Add(Space()); + } + else if (extension) + { + result.Add(Punctuation(SyntaxKind.OpenParenToken)); + result.Add(Text(CSharpFeaturesResources.extension)); + result.Add(Punctuation(SyntaxKind.CloseParenToken)); + result.Add(Space()); + } + + result.AddRange(method.ToMinimalDisplayParts(semanticModel, position, MinimallyQualifiedWithoutParametersFormat)); + result.Add(Punctuation(SyntaxKind.OpenParenToken)); + + return result; + } + + private IList GetMethodGroupPostambleParts(IMethodSymbol method) + => SpecializedCollections.SingletonList(Punctuation(SyntaxKind.CloseParenToken)); + } +} diff --git a/src/Features/CSharp/Portable/SignatureHelp/InitializerExpressionSignatureHelpProvider.cs b/src/Features/CSharp/Portable/SignatureHelp/InitializerExpressionSignatureHelpProvider.cs new file mode 100644 index 0000000000000..598e77023820b --- /dev/null +++ b/src/Features/CSharp/Portable/SignatureHelp/InitializerExpressionSignatureHelpProvider.cs @@ -0,0 +1,78 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Composition; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.LanguageServices; +using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.SignatureHelp; +using Microsoft.CodeAnalysis.Text; + +namespace Microsoft.CodeAnalysis.CSharp.SignatureHelp +{ + [ExportSignatureHelpProvider(nameof(InitializerExpressionSignatureHelpProvider), LanguageNames.CSharp), Shared] + internal partial class InitializerExpressionSignatureHelpProvider : AbstractOrdinaryMethodSignatureHelpProvider + { + public override bool IsTriggerCharacter(char ch) + => ch == '{' || ch == ','; + + public override bool IsRetriggerCharacter(char ch) + => ch == '}'; + + private bool TryGetInitializerExpression(SyntaxNode root, int position, ISyntaxFactsService syntaxFacts, SignatureHelpTriggerReason triggerReason, CancellationToken cancellationToken, out InitializerExpressionSyntax expression) + => CommonSignatureHelpUtilities.TryGetSyntax(root, position, syntaxFacts, triggerReason, IsTriggerToken, IsInitializerExpressionToken, cancellationToken, out expression) && + expression != null; + + private bool IsTriggerToken(SyntaxToken token) + => !token.IsKind(SyntaxKind.None) && + token.ValueText.Length == 1 && + IsTriggerCharacter(token.ValueText[0]) && + token.Parent is InitializerExpressionSyntax; + + private static bool IsInitializerExpressionToken(InitializerExpressionSyntax expression, SyntaxToken token) + => expression.Span.Contains(token.SpanStart) && token != expression.CloseBraceToken; + + protected override async Task GetItemsWorkerAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken) + { + var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + if (!TryGetInitializerExpression(root, position, document.GetLanguageService(), triggerInfo.TriggerReason, cancellationToken, out var initializerExpression)) + { + return null; + } + + var addMethods = await CommonSignatureHelpUtilities.GetCollectionInitializerAddMethodsAsync( + document, initializerExpression, cancellationToken).ConfigureAwait(false); + if (addMethods.IsDefaultOrEmpty) + { + return null; + } + + var textSpan = SignatureHelpUtilities.GetSignatureHelpSpan(initializerExpression); + var syntaxFacts = document.GetLanguageService(); + + var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); + return CreateCollectionInitializerSignatureHelpItems(addMethods.Select(s => + ConvertMethodGroupMethod(document, s, initializerExpression.OpenBraceToken.SpanStart, semanticModel, cancellationToken)).ToList(), + textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken)); + } + + public override SignatureHelpState GetCurrentArgumentState(SyntaxNode root, int position, ISyntaxFactsService syntaxFacts, TextSpan currentSpan, CancellationToken cancellationToken) + { + if (TryGetInitializerExpression( + root, + position, + syntaxFacts, + SignatureHelpTriggerReason.InvokeSignatureHelpCommand, + cancellationToken, + out var expression) && + currentSpan.Start == SignatureHelpUtilities.GetSignatureHelpSpan(expression).Start) + { + return SignatureHelpUtilities.GetSignatureHelpState(expression, position); + } + + return null; + } + } +} diff --git a/src/Features/CSharp/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.cs b/src/Features/CSharp/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.cs index 8c4a4f1272d66..9695dde3bf0f9 100644 --- a/src/Features/CSharp/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.cs +++ b/src/Features/CSharp/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.cs @@ -7,7 +7,6 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Extensions; -using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.DocumentationComments; using Microsoft.CodeAnalysis.LanguageServices; @@ -18,7 +17,7 @@ namespace Microsoft.CodeAnalysis.CSharp.SignatureHelp { [ExportSignatureHelpProvider("InvocationExpressionSignatureHelpProvider", LanguageNames.CSharp), Shared] - internal partial class InvocationExpressionSignatureHelpProvider : AbstractCSharpSignatureHelpProvider + internal partial class InvocationExpressionSignatureHelpProvider : AbstractOrdinaryMethodSignatureHelpProvider { [ImportingConstructor] public InvocationExpressionSignatureHelpProvider() @@ -99,8 +98,8 @@ protected override async Task GetItemsWorkerAsync(Document d if (methodGroup.Any()) { - var (items, selectedItem) = - GetMethodGroupItemsAndSelection(invocationExpression, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormattingService, within, methodGroup, symbolInfo, cancellationToken); + var (items, selectedItem) = GetMethodGroupItemsAndSelection( + document, invocationExpression, semanticModel, within, methodGroup, symbolInfo, cancellationToken); return CreateSignatureHelpItems( items, diff --git a/src/Features/CSharp/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider_MethodGroup.cs b/src/Features/CSharp/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider_MethodGroup.cs index 11547b2454fb9..665fedc8771dd 100644 --- a/src/Features/CSharp/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider_MethodGroup.cs +++ b/src/Features/CSharp/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider_MethodGroup.cs @@ -4,10 +4,7 @@ using System.Linq; using System.Threading; using Microsoft.CodeAnalysis.CSharp.Extensions; -using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.DocumentationComments; -using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.SignatureHelp; using Roslyn.Utilities; @@ -17,11 +14,9 @@ namespace Microsoft.CodeAnalysis.CSharp.SignatureHelp internal partial class InvocationExpressionSignatureHelpProvider { private (IList, int?) GetMethodGroupItemsAndSelection( + Document document, InvocationExpressionSyntax invocationExpression, SemanticModel semanticModel, - ISymbolDisplayService symbolDisplayService, - IAnonymousTypeDisplayService anonymousTypeDisplayService, - IDocumentationCommentFormattingService documentationCommentFormattingService, ISymbol within, IEnumerable methodGroup, SymbolInfo currentSymbol, @@ -70,7 +65,7 @@ internal partial class InvocationExpressionSignatureHelpProvider accessibleMethods = accessibleMethods.Where(m => !IsHiddenByOtherMethod(m, methodSet)).ToImmutableArrayOrEmpty(); return (accessibleMethods.Select(m => - ConvertMethodGroupMethod(m, invocationExpression, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormattingService, cancellationToken)).ToList(), + ConvertMethodGroupMethod(document, m, invocationExpression.SpanStart, semanticModel, cancellationToken)).ToList(), TryGetSelectedIndex(accessibleMethods, currentSymbol)); } @@ -96,73 +91,5 @@ private bool IsHiddenBy(IMethodSymbol method1, IMethodSymbol method2) // constructed method is hidden by the unconstructed one. return method2.IsMoreSpecificThan(method1) == true; } - - private SignatureHelpItem ConvertMethodGroupMethod( - IMethodSymbol method, - InvocationExpressionSyntax invocationExpression, - SemanticModel semanticModel, - ISymbolDisplayService symbolDisplayService, - IAnonymousTypeDisplayService anonymousTypeDisplayService, - IDocumentationCommentFormattingService documentationCommentFormattingService, - CancellationToken cancellationToken) - { - var position = invocationExpression.SpanStart; - var item = CreateItem( - method, semanticModel, position, - symbolDisplayService, anonymousTypeDisplayService, - method.IsParams(), - c => method.OriginalDefinition.GetDocumentationParts(semanticModel, position, documentationCommentFormattingService, c).Concat(GetAwaitableUsage(method, semanticModel, position)), - GetMethodGroupPreambleParts(method, semanticModel, position), - GetSeparatorParts(), - GetMethodGroupPostambleParts(method), - method.Parameters.Select(p => Convert(p, semanticModel, position, documentationCommentFormattingService, cancellationToken)).ToList()); - return item; - } - - private IList GetMethodGroupPreambleParts( - IMethodSymbol method, - SemanticModel semanticModel, - int position) - { - var result = new List(); - - var awaitable = method.GetOriginalUnreducedDefinition().IsAwaitableNonDynamic(semanticModel, position); - var extension = method.GetOriginalUnreducedDefinition().IsExtensionMethod(); - - if (awaitable && extension) - { - result.Add(Punctuation(SyntaxKind.OpenParenToken)); - result.Add(Text(CSharpFeaturesResources.awaitable)); - result.Add(Punctuation(SyntaxKind.CommaToken)); - result.Add(Text(CSharpFeaturesResources.extension)); - result.Add(Punctuation(SyntaxKind.CloseParenToken)); - result.Add(Space()); - } - else if (awaitable) - { - result.Add(Punctuation(SyntaxKind.OpenParenToken)); - result.Add(Text(CSharpFeaturesResources.awaitable)); - result.Add(Punctuation(SyntaxKind.CloseParenToken)); - result.Add(Space()); - } - else if (extension) - { - result.Add(Punctuation(SyntaxKind.OpenParenToken)); - result.Add(Text(CSharpFeaturesResources.extension)); - result.Add(Punctuation(SyntaxKind.CloseParenToken)); - result.Add(Space()); - } - - result.AddRange(method.ToMinimalDisplayParts(semanticModel, position, MinimallyQualifiedWithoutParametersFormat)); - result.Add(Punctuation(SyntaxKind.OpenParenToken)); - - return result; - } - - private IList GetMethodGroupPostambleParts(IMethodSymbol method) - { - return SpecializedCollections.SingletonList( - Punctuation(SyntaxKind.CloseParenToken)); - } } } diff --git a/src/Features/CSharp/Portable/SignatureHelp/SignatureHelpUtilities.cs b/src/Features/CSharp/Portable/SignatureHelp/SignatureHelpUtilities.cs index de71e21bebab7..c468ae3979035 100644 --- a/src/Features/CSharp/Portable/SignatureHelp/SignatureHelpUtilities.cs +++ b/src/Features/CSharp/Portable/SignatureHelp/SignatureHelpUtilities.cs @@ -15,16 +15,20 @@ internal static class SignatureHelpUtilities { private static readonly Func s_getBaseArgumentListOpenToken = list => list.GetOpenToken(); private static readonly Func s_getTypeArgumentListOpenToken = list => list.LessThanToken; + private static readonly Func s_getInitializerExpressionOpenToken = e => e.OpenBraceToken; private static readonly Func s_getAttributeArgumentListOpenToken = list => list.OpenParenToken; private static readonly Func s_getBaseArgumentListCloseToken = list => list.GetCloseToken(); private static readonly Func s_getTypeArgumentListCloseToken = list => list.GreaterThanToken; + private static readonly Func s_getInitializerExpressionCloseToken = e => e.CloseBraceToken; private static readonly Func s_getAttributeArgumentListCloseToken = list => list.CloseParenToken; private static readonly Func> s_getBaseArgumentListArgumentsWithSeparators = list => list.Arguments.GetWithSeparators(); private static readonly Func> s_getTypeArgumentListArgumentsWithSeparators = list => list.Arguments.GetWithSeparators(); + private static readonly Func> s_getInitializerExpressionArgumentsWithSeparators = + e => e.Expressions.GetWithSeparators(); private static readonly Func> s_getAttributeArgumentListArgumentsWithSeparators = list => list.Arguments.GetWithSeparators(); @@ -32,6 +36,8 @@ internal static class SignatureHelpUtilities list => list.Arguments.Select(argument => argument.NameColon?.Name.Identifier.ValueText); private static readonly Func> s_getTypeArgumentListNames = list => list.Arguments.Select(a => (string)null); + private static readonly Func> s_getInitializerExpressionNames = + e => e.Expressions.Select(a => (string)null); private static readonly Func> s_getAttributeArgumentListNames = list => list.Arguments.Select( argument => argument.NameColon != null @@ -58,6 +64,16 @@ internal static SignatureHelpState GetSignatureHelpState(TypeArgumentListSyntax s_getTypeArgumentListNames); } + internal static SignatureHelpState GetSignatureHelpState(InitializerExpressionSyntax argumentList, int position) + { + return CommonSignatureHelpUtilities.GetSignatureHelpState( + argumentList, position, + s_getInitializerExpressionOpenToken, + s_getInitializerExpressionCloseToken, + s_getInitializerExpressionArgumentsWithSeparators, + s_getInitializerExpressionNames); + } + internal static SignatureHelpState GetSignatureHelpState(AttributeArgumentListSyntax argumentList, int position) { return CommonSignatureHelpUtilities.GetSignatureHelpState( @@ -78,6 +94,9 @@ internal static TextSpan GetSignatureHelpSpan(TypeArgumentListSyntax argumentLis return CommonSignatureHelpUtilities.GetSignatureHelpSpan(argumentList, s_getTypeArgumentListCloseToken); } + internal static TextSpan GetSignatureHelpSpan(InitializerExpressionSyntax initializer) + => CommonSignatureHelpUtilities.GetSignatureHelpSpan(initializer, initializer.SpanStart, s_getInitializerExpressionCloseToken); + internal static TextSpan GetSignatureHelpSpan(AttributeArgumentListSyntax argumentList) { return CommonSignatureHelpUtilities.GetSignatureHelpSpan(argumentList, s_getAttributeArgumentListCloseToken); diff --git a/src/Features/Core/Portable/SignatureHelp/AbstractSignatureHelpProvider.cs b/src/Features/Core/Portable/SignatureHelp/AbstractSignatureHelpProvider.cs index 613aec1599005..6a51c82609b3f 100644 --- a/src/Features/Core/Portable/SignatureHelp/AbstractSignatureHelpProvider.cs +++ b/src/Features/Core/Portable/SignatureHelp/AbstractSignatureHelpProvider.cs @@ -51,10 +51,41 @@ protected static SignatureHelpItems CreateSignatureHelpItems( return null; } + if (selectedItem < 0) + { + selectedItem = null; + } + (items, selectedItem) = Filter(items, state.ArgumentNames, selectedItem); return new SignatureHelpItems(items, applicableSpan, state.ArgumentIndex, state.ArgumentCount, state.ArgumentName, selectedItem); } + protected static SignatureHelpItems CreateCollectionInitializerSignatureHelpItems( + IList items, TextSpan applicableSpan, SignatureHelpState state) + { + // We will have added all the accessible '.Add' methods that take at least one + // arguments. However, in general the one-arg Add method is the least likely for the + // user to invoke. For example, say there is: + // + // new JObject { { $$ } } + // + // Technically, the user could be calling the `.Add(object)` overload in this case. + // However, normally in that case, they would just supply the value directly like so: + // + // new JObject { new JProperty(...), new JProperty(...) } + // + // So, it's a strong signal when they're inside another `{ $$ }` that they want to call + // the .Add methods that take multiple args, like so: + // + // new JObject { { propName, propValue }, { propName, propValue } } + // + // So, we include all the .Add methods, but we prefer selecting the first that has + // at least two parameters. + return CreateSignatureHelpItems( + items, applicableSpan, state, items.IndexOf(i => i.Parameters.Length >= 2)); + } + + private static (IList items, int? selectedItem) Filter(IList items, IEnumerable parameterNames, int? selectedItem) { if (parameterNames == null) diff --git a/src/Features/Core/Portable/SignatureHelp/CommonSignatureHelpUtilities.cs b/src/Features/Core/Portable/SignatureHelp/CommonSignatureHelpUtilities.cs index e98f4205ecaff..a3d1e377f5060 100644 --- a/src/Features/Core/Portable/SignatureHelp/CommonSignatureHelpUtilities.cs +++ b/src/Features/Core/Portable/SignatureHelp/CommonSignatureHelpUtilities.cs @@ -1,10 +1,14 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Threading; +using System.Threading.Tasks; using Microsoft.CodeAnalysis.LanguageServices; +using Microsoft.CodeAnalysis.Operations; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; @@ -143,5 +147,48 @@ internal static bool TryGetSyntax( expression = null; return false; } + + public static async Task> GetCollectionInitializerAddMethodsAsync( + Document document, SyntaxNode initializer, CancellationToken cancellationToken) + { + if (initializer == null || initializer.Parent == null) + { + return default; + } + + var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); + var compilation = semanticModel.Compilation; + var ienumerableType = compilation.GetTypeByMetadataName(typeof(IEnumerable).FullName); + if (ienumerableType == null) + { + return default; + } + + // get the regular signature help items + var parentOperation = semanticModel.GetOperation(initializer.Parent, cancellationToken) as IObjectOrCollectionInitializerOperation; + var parentType = parentOperation?.Type; + if (parentType == null) + { + return default; + } + + if (!parentType.AllInterfaces.Contains(ienumerableType)) + { + return default; + } + + var position = initializer.SpanStart; + var addSymbols = semanticModel.LookupSymbols( + position, parentType, WellKnownMemberNames.CollectionInitializerAddMethodName, includeReducedExtensionMethods: true); + + var symbolDisplayService = document.GetLanguageService(); + var addMethods = addSymbols.OfType() + .Where(m => m.Parameters.Length >= 1) + .ToImmutableArray() + .FilterToVisibleAndBrowsableSymbols(document.ShouldHideAdvancedMembers(), semanticModel.Compilation) + .Sort(symbolDisplayService, semanticModel, position); + + return addMethods; + } } } diff --git a/src/Features/VisualBasic/Portable/EditAndContinue/VisualBasicEditAndContinueAnalyzer.vb b/src/Features/VisualBasic/Portable/EditAndContinue/VisualBasicEditAndContinueAnalyzer.vb index 97018d1ef6586..142d83a4b754c 100644 --- a/src/Features/VisualBasic/Portable/EditAndContinue/VisualBasicEditAndContinueAnalyzer.vb +++ b/src/Features/VisualBasic/Portable/EditAndContinue/VisualBasicEditAndContinueAnalyzer.vb @@ -454,7 +454,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue ' Function(a) [|[|Function(b)|] a + b|] ' There are 2 active statements, one spanning the the body of the outer lambda and ' the other on the nested lambda's header. - ' Find the parent whose span starts at the same position but it's lenght is at least as long as the active span's length. + ' Find the parent whose span starts at the same position but it's length is at least as long as the active span's length. While node.Span.Length < span.Length AndAlso node.Parent.SpanStart = position node = node.Parent partnerOpt = partnerOpt?.Parent diff --git a/src/Features/VisualBasic/Portable/OrderModifiers/VisualBasicOrderModifiersDiagnosticAnalyzer.vb b/src/Features/VisualBasic/Portable/OrderModifiers/VisualBasicOrderModifiersDiagnosticAnalyzer.vb index b62c06bbda26d..2f8ef90403a26 100644 --- a/src/Features/VisualBasic/Portable/OrderModifiers/VisualBasicOrderModifiersDiagnosticAnalyzer.vb +++ b/src/Features/VisualBasic/Portable/OrderModifiers/VisualBasicOrderModifiersDiagnosticAnalyzer.vb @@ -42,7 +42,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.OrderModifiers If modifiers.Count >= 2 Then ' We'll see modifiers twice in some circumstances. First, on a VB block ' construct, and then on the VB begin statement for that block. In order - ' to not double report, only check the statement that teh modifier actually + ' to not double report, only check the statement that the modifier actually ' belongs to. Return modifiers.First().Parent Is statement End If diff --git a/src/Features/VisualBasic/Portable/SignatureHelp/AbstractOrdinaryMethodSignatureHelpProvider.vb b/src/Features/VisualBasic/Portable/SignatureHelp/AbstractOrdinaryMethodSignatureHelpProvider.vb new file mode 100644 index 0000000000000..41eb20c24785d --- /dev/null +++ b/src/Features/VisualBasic/Portable/SignatureHelp/AbstractOrdinaryMethodSignatureHelpProvider.vb @@ -0,0 +1,85 @@ +' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +Imports System.Threading +Imports Microsoft.CodeAnalysis.DocumentationComments +Imports Microsoft.CodeAnalysis.LanguageServices +Imports Microsoft.CodeAnalysis.SignatureHelp + +Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp + friend MustInherit class AbstractOrdinaryMethodSignatureHelpProvider + inherits AbstractVisualBasicSignatureHelpProvider + + Protected Function ConvertMemberGroupMember(document As Document, + member As ISymbol, + position As Integer, + semanticModel As SemanticModel, + cancellationToken As CancellationToken) As SignatureHelpItem + + Dim anonymousTypeDisplayService = document.GetLanguageService(Of IAnonymousTypeDisplayService)() + Dim documentationCommentFormattingService = document.GetLanguageService(Of IDocumentationCommentFormattingService)() + Dim symbolDisplayService = document.GetLanguageService(Of ISymbolDisplayService)() + + Return CreateItem( + member, semanticModel, position, + symbolDisplayService, anonymousTypeDisplayService, + member.IsParams(), + Function(c) member.GetDocumentationParts(semanticModel, position, documentationCommentFormattingService, c).Concat(GetAwaitableDescription(member, semanticModel, position).ToTaggedText()), + GetMemberGroupPreambleParts(member, semanticModel, position), + GetSeparatorParts(), + GetMemberGroupPostambleParts(member, semanticModel, position), + member.GetParameters().Select(Function(p) Convert(p, semanticModel, position, documentationCommentFormattingService, cancellationToken)).ToList()) + End Function + + Private Function GetAwaitableDescription(member As ISymbol, semanticModel As SemanticModel, position As Integer) As IList(Of SymbolDisplayPart) + If member.IsAwaitableNonDynamic(semanticModel, position) Then + Return member.ToAwaitableParts(SyntaxFacts.GetText(SyntaxKind.AwaitKeyword), "r", semanticModel, position) + End If + + Return SpecializedCollections.EmptyList(Of SymbolDisplayPart) + End Function + + Private Function GetMemberGroupPreambleParts(symbol As ISymbol, semanticModel As SemanticModel, position As Integer) As IList(Of SymbolDisplayPart) + Dim result = New List(Of SymbolDisplayPart)() + + AddExtensionPreamble(symbol, result) + + result.AddRange(symbol.ContainingType.ToMinimalDisplayParts(semanticModel, position)) + result.Add(Punctuation(SyntaxKind.DotToken)) + + Dim format = MinimallyQualifiedWithoutParametersFormat + format = format.RemoveMemberOptions(SymbolDisplayMemberOptions.IncludeType Or SymbolDisplayMemberOptions.IncludeContainingType) + format = format.RemoveKindOptions(SymbolDisplayKindOptions.IncludeMemberKeyword) + format = format.WithMiscellaneousOptions(format.MiscellaneousOptions And (Not SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers)) + + result.AddRange(symbol.ToMinimalDisplayParts(semanticModel, position, format)) + result.Add(Punctuation(SyntaxKind.OpenParenToken)) + Return result + End Function + + Private Function GetMemberGroupPostambleParts(symbol As ISymbol, + semanticModel As SemanticModel, + position As Integer) As IList(Of SymbolDisplayPart) + Dim parts = New List(Of SymbolDisplayPart) + parts.Add(Punctuation(SyntaxKind.CloseParenToken)) + + If TypeOf symbol Is IMethodSymbol Then + Dim method = DirectCast(symbol, IMethodSymbol) + If Not method.ReturnsVoid Then + parts.Add(Space()) + parts.Add(Keyword(SyntaxKind.AsKeyword)) + parts.Add(Space()) + parts.AddRange(method.ReturnType.ToMinimalDisplayParts(semanticModel, position)) + End If + ElseIf TypeOf symbol Is IPropertySymbol Then + Dim [property] = DirectCast(symbol, IPropertySymbol) + + parts.Add(Space()) + parts.Add(Keyword(SyntaxKind.AsKeyword)) + parts.Add(Space()) + parts.AddRange([property].Type.ToMinimalDisplayParts(semanticModel, position)) + End If + + Return parts + End Function + End Class +End Namespace diff --git a/src/Features/VisualBasic/Portable/SignatureHelp/AbstractSignatureHelpProvider.vb b/src/Features/VisualBasic/Portable/SignatureHelp/AbstractVisualBasicSignatureHelpProvider.vb similarity index 100% rename from src/Features/VisualBasic/Portable/SignatureHelp/AbstractSignatureHelpProvider.vb rename to src/Features/VisualBasic/Portable/SignatureHelp/AbstractVisualBasicSignatureHelpProvider.vb diff --git a/src/Features/VisualBasic/Portable/SignatureHelp/CollectionInitializerSignatureHelpProvider.vb b/src/Features/VisualBasic/Portable/SignatureHelp/CollectionInitializerSignatureHelpProvider.vb new file mode 100644 index 0000000000000..964b6e1552dc4 --- /dev/null +++ b/src/Features/VisualBasic/Portable/SignatureHelp/CollectionInitializerSignatureHelpProvider.vb @@ -0,0 +1,79 @@ +' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +Imports System.Composition +Imports System.Runtime.InteropServices +Imports System.Threading +Imports Microsoft.CodeAnalysis.LanguageServices +Imports Microsoft.CodeAnalysis.SignatureHelp +Imports Microsoft.CodeAnalysis.Text +Imports Microsoft.CodeAnalysis.VisualBasic.Syntax + +Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp + + Partial Friend Class CollectionInitializerSignatureHelpProvider + Inherits AbstractOrdinaryMethodSignatureHelpProvider + + Public Overrides Function IsTriggerCharacter(ch As Char) As Boolean + Return ch = "{"c OrElse ch = ","c + End Function + + Public Overrides Function IsRetriggerCharacter(ch As Char) As Boolean + Return ch = "}"c + End Function + + Private Function TryGetInitializerExpression(root As SyntaxNode, position As Integer, syntaxFacts As ISyntaxFactsService, triggerReason As SignatureHelpTriggerReason, cancellationToken As CancellationToken, ByRef expression As CollectionInitializerSyntax) As Boolean + Return CommonSignatureHelpUtilities.TryGetSyntax(root, position, syntaxFacts, triggerReason, AddressOf IsTriggerToken, AddressOf IsInitializerExpressionToken, cancellationToken, expression) AndAlso + expression IsNot Nothing + End Function + + Private Function IsTriggerToken(token As SyntaxToken) As Boolean + Return Not token.IsKind(SyntaxKind.None) AndAlso + token.ValueText.Length = 1 AndAlso + IsTriggerCharacter(token.ValueText(0)) AndAlso + TypeOf token.Parent Is CollectionInitializerSyntax + End Function + + Private Shared Function IsInitializerExpressionToken(expression As CollectionInitializerSyntax, token As SyntaxToken) As Boolean + Return expression.Span.Contains(token.SpanStart) AndAlso token <> expression.CloseBraceToken + End Function + + Protected Overrides Async Function GetItemsWorkerAsync(document As Document, position As Integer, triggerInfo As SignatureHelpTriggerInfo, cancellationToken As CancellationToken) As Task(Of SignatureHelpItems) + Dim root = Await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(False) + Dim collectionInitializer As CollectionInitializerSyntax = Nothing + If Not TryGetInitializerExpression(root, position, document.GetLanguageService(Of ISyntaxFactsService)(), triggerInfo.TriggerReason, cancellationToken, collectionInitializer) Then + Return Nothing + End If + + Dim addMethods = Await CommonSignatureHelpUtilities.GetCollectionInitializerAddMethodsAsync( + document, collectionInitializer.Parent, cancellationToken).ConfigureAwait(False) + If addMethods.IsDefaultOrEmpty Then + Return Nothing + End If + + Dim textSpan = GetSignatureHelpSpan(collectionInitializer) + Dim syntaxFacts = document.GetLanguageService(Of ISyntaxFactsService)() + + Dim semanticModel = Await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(False) + Return CreateCollectionInitializerSignatureHelpItems( + addMethods.Select(Function(s) ConvertMemberGroupMember(document, s, collectionInitializer.OpenBraceToken.SpanStart, semanticModel, cancellationToken)).ToList(), + textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken)) + End Function + + Public Overrides Function GetCurrentArgumentState(root As SyntaxNode, position As Integer, syntaxFacts As ISyntaxFactsService, currentSpan As TextSpan, cancellationToken As CancellationToken) As SignatureHelpState + Dim expression As CollectionInitializerSyntax = Nothing + If TryGetInitializerExpression( + root, + position, + syntaxFacts, + SignatureHelpTriggerReason.InvokeSignatureHelpCommand, + cancellationToken, + expression) AndAlso + currentSpan.Start = GetSignatureHelpSpan(expression).Start Then + Return GetSignatureHelpState(expression, position) + End If + + Return Nothing + End Function + End Class + +End Namespace diff --git a/src/Features/VisualBasic/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.MemberGroup.vb b/src/Features/VisualBasic/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.MemberGroup.vb index b25ab50523db7..324c4e4b13035 100644 --- a/src/Features/VisualBasic/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.MemberGroup.vb +++ b/src/Features/VisualBasic/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.MemberGroup.vb @@ -10,11 +10,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp Partial Friend Class InvocationExpressionSignatureHelpProvider - Private Function GetMemberGroupItems(invocationExpression As InvocationExpressionSyntax, + Private Function GetMemberGroupItems(document As Document, + invocationExpression As InvocationExpressionSyntax, semanticModel As SemanticModel, - symbolDisplayService As ISymbolDisplayService, - anonymousTypeDisplayService As IAnonymousTypeDisplayService, - documentationCommentFormattingService As IDocumentationCommentFormattingService, within As ISymbol, memberGroup As IEnumerable(Of ISymbol), cancellationToken As CancellationToken) As IEnumerable(Of SignatureHelpItem) @@ -39,80 +37,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp Return SpecializedCollections.EmptyEnumerable(Of SignatureHelpItem)() End If - Return accessibleMembers.[Select]( - Function(s) ConvertMemberGroupMember(s, invocationExpression, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormattingService, cancellationToken)) - End Function - - Private Function ConvertMemberGroupMember(member As ISymbol, - invocationExpression As InvocationExpressionSyntax, - semanticModel As SemanticModel, - symbolDisplayService As ISymbolDisplayService, - anonymousTypeDisplayService As IAnonymousTypeDisplayService, - documentationCommentFormattingService As IDocumentationCommentFormattingService, - cancellationToken As CancellationToken) As SignatureHelpItem - Dim position = invocationExpression.SpanStart - Dim item = CreateItem( - member, semanticModel, position, - symbolDisplayService, anonymousTypeDisplayService, - member.IsParams(), - Function(c) member.GetDocumentationParts(semanticModel, position, documentationCommentFormattingService, c).Concat(GetAwaitableDescription(member, semanticModel, position).ToTaggedText()), - GetMemberGroupPreambleParts(member, semanticModel, position), - GetSeparatorParts(), - GetMemberGroupPostambleParts(member, semanticModel, position), - member.GetParameters().Select(Function(p) Convert(p, semanticModel, position, documentationCommentFormattingService, cancellationToken)).ToList()) - Return item - End Function - - Private Function GetAwaitableDescription(member As ISymbol, semanticModel As SemanticModel, position As Integer) As IList(Of SymbolDisplayPart) - If member.IsAwaitableNonDynamic(semanticModel, position) Then - Return member.ToAwaitableParts(SyntaxFacts.GetText(SyntaxKind.AwaitKeyword), "r", semanticModel, position) - End If - - Return SpecializedCollections.EmptyList(Of SymbolDisplayPart) - End Function - - Private Function GetMemberGroupPreambleParts(symbol As ISymbol, semanticModel As SemanticModel, position As Integer) As IList(Of SymbolDisplayPart) - Dim result = New List(Of SymbolDisplayPart)() - - AddExtensionPreamble(symbol, result) - - result.AddRange(symbol.ContainingType.ToMinimalDisplayParts(semanticModel, position)) - result.Add(Punctuation(SyntaxKind.DotToken)) - - Dim format = MinimallyQualifiedWithoutParametersFormat - format = format.RemoveMemberOptions(SymbolDisplayMemberOptions.IncludeType Or SymbolDisplayMemberOptions.IncludeContainingType) - format = format.RemoveKindOptions(SymbolDisplayKindOptions.IncludeMemberKeyword) - format = format.WithMiscellaneousOptions(format.MiscellaneousOptions And (Not SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers)) - - result.AddRange(symbol.ToMinimalDisplayParts(semanticModel, position, format)) - result.Add(Punctuation(SyntaxKind.OpenParenToken)) - Return result - End Function - - Private Function GetMemberGroupPostambleParts(symbol As ISymbol, - semanticModel As SemanticModel, - position As Integer) As IList(Of SymbolDisplayPart) - Dim parts = New List(Of SymbolDisplayPart) - parts.Add(Punctuation(SyntaxKind.CloseParenToken)) - - If TypeOf symbol Is IMethodSymbol Then - Dim method = DirectCast(symbol, IMethodSymbol) - If Not method.ReturnsVoid Then - parts.Add(Space()) - parts.Add(Keyword(SyntaxKind.AsKeyword)) - parts.Add(Space()) - parts.AddRange(method.ReturnType.ToMinimalDisplayParts(semanticModel, position)) - End If - ElseIf TypeOf symbol Is IPropertySymbol Then - Dim [property] = DirectCast(symbol, IPropertySymbol) - - parts.Add(Space()) - parts.Add(Keyword(SyntaxKind.AsKeyword)) - parts.Add(Space()) - parts.AddRange([property].Type.ToMinimalDisplayParts(semanticModel, position)) - End If - - Return parts + Return accessibleMembers.Select( + Function(s) ConvertMemberGroupMember(document, s, invocationExpression.SpanStart, semanticModel, cancellationToken)) End Function End Class End Namespace diff --git a/src/Features/VisualBasic/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.vb b/src/Features/VisualBasic/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.vb index b162a59d21f11..cbc4e3ba41675 100644 --- a/src/Features/VisualBasic/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.vb +++ b/src/Features/VisualBasic/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider.vb @@ -14,7 +14,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp Partial Friend Class InvocationExpressionSignatureHelpProvider - Inherits AbstractVisualBasicSignatureHelpProvider + Inherits AbstractOrdinaryMethodSignatureHelpProvider Public Sub New() @@ -78,7 +78,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp invocationExpression.Expression) ' get the regular signature help items - Dim symbolDisplayService = document.GetLanguageService(Of ISymbolDisplayService)() Dim memberGroup = semanticModel.GetMemberGroup(targetExpression, cancellationToken). FilterToVisibleAndBrowsableSymbolsAndNotUnsafeSymbols(document.ShouldHideAdvancedMembers(), semanticModel.Compilation) @@ -96,6 +95,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp memberGroup = memberGroup.WhereAsArray(Function(m) Not m.Equals(enclosingSymbol)) End If + Dim symbolDisplayService = document.GetLanguageService(Of ISymbolDisplayService)() memberGroup = memberGroup.Sort(symbolDisplayService, semanticModel, invocationExpression.SpanStart) Dim typeInfo = semanticModel.GetTypeInfo(targetExpression, cancellationToken) @@ -115,7 +115,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp Dim items = New List(Of SignatureHelpItem) If memberGroup.Count > 0 Then - items.AddRange(GetMemberGroupItems(invocationExpression, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormattingService, within, memberGroup, cancellationToken)) + items.AddRange(GetMemberGroupItems(document, invocationExpression, semanticModel, within, memberGroup, cancellationToken)) End If If expressionType.IsDelegateType() Then diff --git a/src/Features/VisualBasic/Portable/SignatureHelp/SignatureHelpUtilities.vb b/src/Features/VisualBasic/Portable/SignatureHelp/SignatureHelpUtilities.vb index c4f8a349cf0f7..ffa2eca273509 100644 --- a/src/Features/VisualBasic/Portable/SignatureHelp/SignatureHelpUtilities.vb +++ b/src/Features/VisualBasic/Portable/SignatureHelp/SignatureHelpUtilities.vb @@ -9,6 +9,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp Friend Module SignatureHelpUtilities Private ReadOnly s_getArgumentListOpenToken As Func(Of ArgumentListSyntax, SyntaxToken) = Function(list) list.OpenParenToken Private ReadOnly s_getTypeArgumentListOpenToken As Func(Of TypeArgumentListSyntax, SyntaxToken) = Function(list) list.OpenParenToken + Private ReadOnly s_getCollectionInitializerOpenToken As Func(Of CollectionInitializerSyntax, SyntaxToken) = Function(i) i.OpenBraceToken Private ReadOnly s_getArgumentListCloseToken As Func(Of ArgumentListSyntax, SyntaxToken) = Function(list) @@ -27,9 +28,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp End Function Private ReadOnly s_getTypeArgumentListCloseToken As Func(Of TypeArgumentListSyntax, SyntaxToken) = Function(list) list.CloseParenToken + Private ReadOnly s_getCollectionInitializerCloseToken As Func(Of CollectionInitializerSyntax, SyntaxToken) = Function(i) i.CloseBraceToken - Private ReadOnly s_getArgumentListArgumentsWithSeparators As Func(Of ArgumentListSyntax, IEnumerable(Of SyntaxNodeOrToken)) = Function(list) list.Arguments.GetWithSeparators().AsEnumerable().[Select](Function(t) CType(t, SyntaxNodeOrToken)) - Private ReadOnly s_getTypeArgumentListArgumentsWithSeparators As Func(Of TypeArgumentListSyntax, IEnumerable(Of SyntaxNodeOrToken)) = Function(list) list.Arguments.GetWithSeparators().AsEnumerable().[Select](Function(t) CType(t, SyntaxNodeOrToken)) + Private ReadOnly s_getArgumentListArgumentsWithSeparators As Func(Of ArgumentListSyntax, IEnumerable(Of SyntaxNodeOrToken)) = Function(list) list.Arguments.GetWithSeparators() + Private ReadOnly s_getTypeArgumentListArgumentsWithSeparators As Func(Of TypeArgumentListSyntax, IEnumerable(Of SyntaxNodeOrToken)) = Function(list) list.Arguments.GetWithSeparators() + Private ReadOnly s_getCollectionInitializerArgumentsWithSeparators As Func(Of CollectionInitializerSyntax, IEnumerable(Of SyntaxNodeOrToken)) = Function(i) i.Initializers.GetWithSeparators() Private ReadOnly s_getArgumentListNames As Func(Of ArgumentListSyntax, IEnumerable(Of String)) = Function(list) list.Arguments.Select(Function(a) @@ -41,6 +44,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp End Function) Private ReadOnly s_getTypeArgumentListNames As Func(Of TypeArgumentListSyntax, IEnumerable(Of String)) = Function(list) list.Arguments.Select(Function(a) DirectCast(Nothing, String)) + Private ReadOnly s_getCollectionInitializerNames As Func(Of CollectionInitializerSyntax, IEnumerable(Of String)) = Function(i) i.Initializers.Select(Function(a) DirectCast(Nothing, String)) Friend Function GetSignatureHelpSpan(argumentList As ArgumentListSyntax) As TextSpan Return CommonSignatureHelpUtilities.GetSignatureHelpSpan(argumentList, s_getArgumentListCloseToken) @@ -54,8 +58,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp Return CommonSignatureHelpUtilities.GetSignatureHelpSpan(argumentList, s_getTypeArgumentListCloseToken) End Function - Friend Function GetSignatureHelpState(argumentList As ArgumentListSyntax, position As Integer) As SignatureHelpState + Friend Function GetSignatureHelpSpan(initializer As CollectionInitializerSyntax) As TextSpan + Return CommonSignatureHelpUtilities.GetSignatureHelpSpan(initializer, initializer.SpanStart, s_getCollectionInitializerCloseToken) + End Function + Friend Function GetSignatureHelpState(argumentList As ArgumentListSyntax, position As Integer) As SignatureHelpState Return CommonSignatureHelpUtilities.GetSignatureHelpState( argumentList, position, @@ -75,6 +82,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp s_getTypeArgumentListNames) End Function + Friend Function GetSignatureHelpState(initializer As CollectionInitializerSyntax, position As Integer) As SignatureHelpState + Return CommonSignatureHelpUtilities.GetSignatureHelpState( + initializer, + position, + s_getCollectionInitializerOpenToken, + s_getCollectionInitializerCloseToken, + s_getCollectionInitializerArgumentsWithSeparators, + s_getCollectionInitializerNames) + End Function End Module End Namespace diff --git a/src/VisualStudio/Core/Test/CodeModel/VisualBasic/CodeAccessorFunctionTests.vb b/src/VisualStudio/Core/Test/CodeModel/VisualBasic/CodeAccessorFunctionTests.vb index 2909ce4507d8e..af7e071243be2 100644 --- a/src/VisualStudio/Core/Test/CodeModel/VisualBasic/CodeAccessorFunctionTests.vb +++ b/src/VisualStudio/Core/Test/CodeModel/VisualBasic/CodeAccessorFunctionTests.vb @@ -509,7 +509,7 @@ Public Class C1 End Event -End Clas +End Class TestFunctionKind(code, EnvDTE80.vsCMFunction2.vsCMFunctionAddHandler) @@ -536,7 +536,7 @@ Public Class C1 End Event -End Clas +End Class TestFunctionKind(code, EnvDTE80.vsCMFunction2.vsCMFunctionRemoveHandler) @@ -563,7 +563,7 @@ Public Class C1 End Event -End Clas +End Class TestFunctionKind(code, EnvDTE80.vsCMFunction2.vsCMFunctionRaiseEvent) diff --git a/src/VisualStudio/Core/Test/CodeModel/VisualBasic/CodeFunctionTests.vb b/src/VisualStudio/Core/Test/CodeModel/VisualBasic/CodeFunctionTests.vb index f14249aa2c7d4..88fd0193d2c14 100644 --- a/src/VisualStudio/Core/Test/CodeModel/VisualBasic/CodeFunctionTests.vb +++ b/src/VisualStudio/Core/Test/CodeModel/VisualBasic/CodeFunctionTests.vb @@ -727,7 +727,7 @@ Public Class C1 Public Sub $$New() End Sub -End Clas +End Class TestFunctionKind(code, EnvDTE.vsCMFunction.vsCMFunctionConstructor) @@ -743,7 +743,7 @@ Public Class C1 MyBase.Finalize() End Sub -End Clas +End Class TestFunctionKind(code, EnvDTE.vsCMFunction.vsCMFunctionDestructor) @@ -758,7 +758,7 @@ Public Class C1 Private Sub $$M() End Sub -End Clas +End Class TestFunctionKind(code, EnvDTE.vsCMFunction.vsCMFunctionSub) @@ -773,7 +773,7 @@ Public Class C1 Private Function $$M() As Integer End Sub -End Clas +End Class TestFunctionKind(code, EnvDTE.vsCMFunction.vsCMFunctionFunction) @@ -787,7 +787,7 @@ Public Class C1 Private Declare Sub $$MethodB Lib "MyDll.dll" () -End Clas +End Class TestFunctionKind(code, EnvDTE.vsCMFunction.vsCMFunctionSub) @@ -801,7 +801,7 @@ Public Class C1 Private Declare Function $$MethodC Lib "MyDll.dll" () As Integer -End Clas +End Class TestFunctionKind(code, EnvDTE.vsCMFunction.vsCMFunctionFunction) diff --git a/src/VisualStudio/Core/Test/Venus/DocumentServiceTests.vb b/src/VisualStudio/Core/Test/Venus/DocumentServiceTests.vb index f4561f742c8e7..0d3b369ac1154 100644 --- a/src/VisualStudio/Core/Test/Venus/DocumentServiceTests.vb +++ b/src/VisualStudio/Core/Test/Venus/DocumentServiceTests.vb @@ -92,7 +92,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.Venus ' contained document supports both document modification and diagnostics ' soon, contained document will be only used to support old venus and razor but not new razor - ' which will use thier own implementation of these services + ' which will use their own implementation of these services Assert.True(documentOperations.CanApplyChange) Assert.True(documentOperations.SupportDiagnostics) diff --git a/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj b/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj index a5d4e693a60fd..12232a9c32e4b 100644 --- a/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj +++ b/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj @@ -75,6 +75,9 @@ InternalUtilities\ConsList`1.cs + + InternalUtilities\Debug.cs + InternalUtilities\DecimalUtilities.cs @@ -141,6 +144,9 @@ InternalUtilities\ReferenceEqualityComparer.cs + + InternalUtilities\RoslynString.cs + InternalUtilities\SemaphoreSlimExtensions.cs diff --git a/src/Workspaces/VisualBasic/Portable/Execution/VisualBasicOptionsSerializationService.vb b/src/Workspaces/VisualBasic/Portable/Execution/VisualBasicOptionsSerializationService.vb index d4c0ffc1c8e49..e7cf625be7b8c 100644 --- a/src/Workspaces/VisualBasic/Portable/Execution/VisualBasicOptionsSerializationService.vb +++ b/src/Workspaces/VisualBasic/Portable/Execution/VisualBasicOptionsSerializationService.vb @@ -30,7 +30,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Execution writer.WriteBoolean(vbOptions.OptionCompareText) writer.WriteBoolean(vbOptions.EmbedVbCoreRuntime) - ' save parse option for embeded types - My types + ' save parse option for embedded types - My types writer.WriteBoolean(vbOptions.ParseOptions IsNot Nothing) If vbOptions.ParseOptions IsNot Nothing Then WriteTo(vbOptions.ParseOptions, writer, cancellationToken) diff --git a/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicTypeInferenceService.TypeInferrer.vb b/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicTypeInferenceService.TypeInferrer.vb index 41636eff45199..aeb3c16675c7d 100644 --- a/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicTypeInferenceService.TypeInferrer.vb +++ b/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicTypeInferenceService.TypeInferrer.vb @@ -862,7 +862,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ' ' await goo.ConfigureAwait() ' - ' then we can figure out what 'goo' should be based on teh await + ' then we can figure out what 'goo' should be based on the await ' context. If expressionOpt Is memberAccessExpression.Expression Then Return InferTypeForExpressionOfMemberAccessExpression(memberAccessExpression)