diff --git a/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs b/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs
index 0518d806ad4feb5e6996b62c1ac283ee173103c1..39e813c6a55501e116099ff8461b39f98c40e244 100644
--- a/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs
+++ b/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs
@@ -6416,7 +6416,7 @@ void N(string? s)
}
}",
MainDescription($"({FeaturesResources.parameter}) string? s"),
- NullabilityAnalysis(string.Format(CSharpFeaturesResources._0_may_be_null_here, "s")));
+ NullabilityAnalysis(string.Format(FeaturesResources._0_may_be_null_here, "s")));
}
[Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)]
@@ -6434,7 +6434,7 @@ void N(string? s)
}
}",
MainDescription($"({FeaturesResources.parameter}) string? s"),
- NullabilityAnalysis(string.Format(CSharpFeaturesResources._0_is_not_null_here, "s")));
+ NullabilityAnalysis(string.Format(FeaturesResources._0_is_not_null_here, "s")));
}
[Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)]
@@ -6453,7 +6453,7 @@ void N()
}
}",
MainDescription($"({FeaturesResources.field}) string? X.s"),
- NullabilityAnalysis(string.Format(CSharpFeaturesResources._0_may_be_null_here, "s")));
+ NullabilityAnalysis(string.Format(FeaturesResources._0_may_be_null_here, "s")));
}
[Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)]
@@ -6473,7 +6473,7 @@ void N()
}
}",
MainDescription($"({FeaturesResources.field}) string? X.s"),
- NullabilityAnalysis(string.Format(CSharpFeaturesResources._0_is_not_null_here, "s")));
+ NullabilityAnalysis(string.Format(FeaturesResources._0_is_not_null_here, "s")));
}
[Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)]
@@ -6492,7 +6492,7 @@ void N()
}
}",
MainDescription("string? X.S { get; set; }"),
- NullabilityAnalysis(string.Format(CSharpFeaturesResources._0_may_be_null_here, "S")));
+ NullabilityAnalysis(string.Format(FeaturesResources._0_may_be_null_here, "S")));
}
[Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)]
@@ -6512,7 +6512,7 @@ void N()
}
}",
MainDescription("string? X.S { get; set; }"),
- NullabilityAnalysis(string.Format(CSharpFeaturesResources._0_is_not_null_here, "S")));
+ NullabilityAnalysis(string.Format(FeaturesResources._0_is_not_null_here, "S")));
}
[Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)]
@@ -6536,7 +6536,7 @@ void N()
}
}",
MainDescription($"({FeaturesResources.local_variable}) string? s"),
- NullabilityAnalysis(string.Format(CSharpFeaturesResources._0_may_be_null_here, "s")));
+ NullabilityAnalysis(string.Format(FeaturesResources._0_may_be_null_here, "s")));
}
[Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)]
@@ -6560,7 +6560,7 @@ void N()
}
}",
MainDescription($"({FeaturesResources.local_variable}) string? s"),
- NullabilityAnalysis(string.Format(CSharpFeaturesResources._0_is_not_null_here, "s")));
+ NullabilityAnalysis(string.Format(FeaturesResources._0_is_not_null_here, "s")));
}
[Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)]
@@ -6580,7 +6580,7 @@ void N()
}
}",
MainDescription($"({FeaturesResources.local_variable}) string? s"),
- NullabilityAnalysis(string.Format(CSharpFeaturesResources._0_may_be_null_here, "s")));
+ NullabilityAnalysis(string.Format(FeaturesResources._0_may_be_null_here, "s")));
}
[Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)]
@@ -6600,7 +6600,7 @@ void N()
}
}",
MainDescription($"({FeaturesResources.local_variable}) string? s"),
- NullabilityAnalysis(string.Format(CSharpFeaturesResources._0_is_not_null_here, "s")));
+ NullabilityAnalysis(string.Format(FeaturesResources._0_is_not_null_here, "s")));
}
[Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)]
@@ -6658,7 +6658,7 @@ void N()
}
}",
MainDescription($"({FeaturesResources.local_variable}) string s"),
- NullabilityAnalysis(string.Format(CSharpFeaturesResources._0_is_not_null_here, "s")));
+ NullabilityAnalysis(string.Format(FeaturesResources._0_is_not_null_here, "s")));
}
[Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)]
diff --git a/src/Features/CSharp/Portable/CSharpFeaturesResources.resx b/src/Features/CSharp/Portable/CSharpFeaturesResources.resx
index 5158c6b331a84a5e2ba2040dae9e8d4298d73238..660ecb85318304556236081e8c807e321a873b37 100644
--- a/src/Features/CSharp/Portable/CSharpFeaturesResources.resx
+++ b/src/Features/CSharp/Portable/CSharpFeaturesResources.resx
@@ -574,12 +574,6 @@
Make 'ref struct'{Locked="ref"}{Locked="struct"} "ref" and "struct" are C# keywords and should not be localized.
-
- '{0}' is not null here.
-
-
- '{0}' may be null here.
-
Assign 'out' parameters{Locked="out"} "out" is a C# keyword and should not be localized.
diff --git a/src/Features/CSharp/Portable/QuickInfo/CSharpSemanticQuickInfoProvider.cs b/src/Features/CSharp/Portable/QuickInfo/CSharpSemanticQuickInfoProvider.cs
index d1a707646bff302046e18e2528a09325ffb8215b..044912f97b9a2ef8e3a5c77911649e948bf750e7 100644
--- a/src/Features/CSharp/Portable/QuickInfo/CSharpSemanticQuickInfoProvider.cs
+++ b/src/Features/CSharp/Portable/QuickInfo/CSharpSemanticQuickInfoProvider.cs
@@ -4,15 +4,13 @@
#nullable enable
-using System.Collections.Immutable;
+using System;
using System.Composition;
+using System.Diagnostics.CodeAnalysis;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Extensions;
-using Microsoft.CodeAnalysis.LanguageServices;
-using Microsoft.CodeAnalysis.QuickInfo;
-using System.Diagnostics.CodeAnalysis;
-using System;
using Microsoft.CodeAnalysis.Host.Mef;
+using Microsoft.CodeAnalysis.QuickInfo;
namespace Microsoft.CodeAnalysis.CSharp.QuickInfo
{
@@ -66,37 +64,28 @@ protected override bool GetBindableNodeForTokenIndicatingPossibleIndexerAccess(S
protected override bool ShouldCheckPreviousToken(SyntaxToken token)
=> !token.Parent.IsKind(SyntaxKind.XmlCrefAttribute);
- protected override ImmutableArray TryGetNullabilityAnalysis(Workspace workspace, SemanticModel semanticModel, SyntaxToken token, CancellationToken cancellationToken)
+ protected override NullableFlowState GetNullabilityAnalysis(Workspace workspace, SemanticModel semanticModel, ISymbol symbol, SyntaxNode node, CancellationToken cancellationToken)
{
// Anything less than C# 8 we just won't show anything, even if the compiler could theoretically give analysis
- var parseOptions = (CSharpParseOptions)token.SyntaxTree!.Options;
+ var parseOptions = (CSharpParseOptions)semanticModel.SyntaxTree!.Options;
if (parseOptions.LanguageVersion < LanguageVersion.CSharp8)
{
- return default;
+ return NullableFlowState.None;
}
// If the user doesn't have nullable enabled, don't show anything. For now we're not trying to be more precise if the user has just annotations or just
// warnings. If the user has annotations off then things that are oblivious might become non-null (which is a lie) and if the user has warnings off then
// that probably implies they're not actually trying to know if their code is correct. We can revisit this if we have specific user scenarios.
- var nullableContext = semanticModel.GetNullableContext(token.SpanStart);
+ var nullableContext = semanticModel.GetNullableContext(node.SpanStart);
if (!nullableContext.WarningsEnabled() || !nullableContext.AnnotationsEnabled())
{
- return default;
- }
-
- var syntaxFacts = workspace.Services.GetLanguageServices(semanticModel.Language).GetRequiredService();
- var bindableParent = syntaxFacts.TryGetBindableParent(token);
- var symbolInfo = bindableParent != null ? semanticModel.GetSymbolInfo(bindableParent, cancellationToken) : default;
-
- if (symbolInfo.Symbol == null || string.IsNullOrEmpty(symbolInfo.Symbol.Name))
- {
- return default;
+ return NullableFlowState.None;
}
// Although GetTypeInfo can return nullability for uses of all sorts of things, it's not always useful for quick info.
// For example, if you have a call to a method with a nullable return, the fact it can be null is already captured
// in the return type shown -- there's no flow analysis information there.
- switch (symbolInfo.Symbol)
+ switch (symbol)
{
// Ignore constant values for nullability flow state
case IFieldSymbol { HasConstantValue: true }: return default;
@@ -114,7 +103,7 @@ protected override ImmutableArray TryGetNullabilityAnalysis(Workspac
return default;
}
- var typeInfo = bindableParent != null ? semanticModel.GetTypeInfo(bindableParent, cancellationToken) : default;
+ var typeInfo = semanticModel.GetTypeInfo(node, cancellationToken);
// Nullability is a reference type only feature, value types can use
// something like "int?" to be nullable but that ends up encasing as
@@ -125,25 +114,7 @@ protected override ImmutableArray TryGetNullabilityAnalysis(Workspac
return default;
}
- string? messageTemplate = null;
-
- if (typeInfo.Nullability.FlowState == NullableFlowState.NotNull)
- {
- messageTemplate = CSharpFeaturesResources._0_is_not_null_here;
- }
- else if (typeInfo.Nullability.FlowState == NullableFlowState.MaybeNull)
- {
- messageTemplate = CSharpFeaturesResources._0_may_be_null_here;
- }
-
- if (messageTemplate != null)
- {
- return ImmutableArray.Create(new TaggedText(TextTags.Text, string.Format(messageTemplate, symbolInfo.Symbol.Name)));
- }
- else
- {
- return default;
- }
+ return typeInfo.Nullability.FlowState;
}
}
}
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.cs.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.cs.xlf
index ba30201576c77496e1c9b68e8489e9db40e9c891..d0d897ddea2d4fe60baf1785c724119b4a44bd40 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.cs.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.cs.xlf
@@ -192,16 +192,6 @@
Warning: Inlining temporary variable may change code meaning.
-
- '{0}' is not null here.
- {0} tady není null.
-
-
-
- '{0}' may be null here.
- {0} tady může být null.
-
- asynchronous foreach statementasynchronní příkaz foreach
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.de.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.de.xlf
index 4a7b194567149898c4b985dfbd6c33f31de659b2..89d5435e78f849bd043a9bf1ae8bb8cd1c57f653 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.de.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.de.xlf
@@ -192,16 +192,6 @@
Warning: Inlining temporary variable may change code meaning.
-
- '{0}' is not null here.
- "{0}" ist hier nicht NULL.
-
-
-
- '{0}' may be null here.
- "{0}" darf hier NULL sein.
-
- asynchronous foreach statementasynchrone foreach-Anweisung
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.es.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.es.xlf
index 4b6a0754218ab17482d5e733522ebd4f208087a3..08543f5dfffc0b5387bfcac621b4c6b0f8d8f9d1 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.es.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.es.xlf
@@ -192,16 +192,6 @@
Warning: Inlining temporary variable may change code meaning.
-
- '{0}' is not null here.
- "{0}" no es NULL aquí.
-
-
-
- '{0}' may be null here.
- "{0}" puede ser NULL aquí.
-
- asynchronous foreach statementinstrucción foreach asincrónica
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.fr.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.fr.xlf
index 3cb937f8604239f2d088364ad08413c21c7076f4..f9f264f8abb0c60f062f04408e9c30cc6d8bc961 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.fr.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.fr.xlf
@@ -192,16 +192,6 @@
Warning: Inlining temporary variable may change code meaning.
-
- '{0}' is not null here.
- '{0}' n'a pas une valeur null ici.
-
-
-
- '{0}' may be null here.
- '{0}' a peut-être une valeur null ici.
-
- asynchronous foreach statementinstruction foreach asynchrone
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.it.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.it.xlf
index 0b7e8bc921e06eed46ebe4a765da7b7fbce61dfa..87de8e4d96caf364fc1caacf88b3436a1b94e8e3 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.it.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.it.xlf
@@ -192,16 +192,6 @@
Warning: Inlining temporary variable may change code meaning.
-
- '{0}' is not null here.
- '{0}' non è Null in questo punto.
-
-
-
- '{0}' may be null here.
- '{0}' può essere Null in questo punto.
-
- asynchronous foreach statementistruzione foreach asincrona
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ja.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ja.xlf
index 9768da58b06f952ece8cb7b7ea56a2012759c030..b29a57f61b8137aff2651c5ffb1ac738e435d235 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ja.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ja.xlf
@@ -192,16 +192,6 @@
Warning: Inlining temporary variable may change code meaning.
-
- '{0}' is not null here.
- ここでは、'{0}' は null ではありません。
-
-
-
- '{0}' may be null here.
- ここでは、'{0}' は null である可能性があります。
-
- asynchronous foreach statement非同期の foreach ステートメント
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ko.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ko.xlf
index 2f729533f0d0697be0f81971ea11dd0460ba8d08..a322722b068a13be9e3c9564bb93f03798d6e23f 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ko.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ko.xlf
@@ -192,16 +192,6 @@
Warning: Inlining temporary variable may change code meaning.
-
- '{0}' is not null here.
- '{0}'은(는) 여기에서 null이 아닙니다.
-
-
-
- '{0}' may be null here.
- '{0}'은(는) 여기에서 null일 수 있습니다.
-
- asynchronous foreach statement비동기 foreach 문
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pl.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pl.xlf
index c28041bfb803c95907862739cb322e197f084662..05559e9ab8afb2c084c18a5e58e2f4768b063743 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pl.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pl.xlf
@@ -192,16 +192,6 @@
Warning: Inlining temporary variable may change code meaning.
-
- '{0}' is not null here.
- Element „{0}” nie ma wartości null w tym miejscu.
-
-
-
- '{0}' may be null here.
- Element „{0}” może mieć wartość null w tym miejscu.
-
- asynchronous foreach statementasynchroniczna instrukcja foreach
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pt-BR.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pt-BR.xlf
index 717d77e91c908f8734510070da4d2570f6389b9f..dcf8daa97cf655f173a3fcc78a05c8f7409c229a 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pt-BR.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.pt-BR.xlf
@@ -192,16 +192,6 @@
Warning: Inlining temporary variable may change code meaning.
-
- '{0}' is not null here.
- '{0}' não é nulo aqui.
-
-
-
- '{0}' may be null here.
- '{0}' pode ser nulo aqui.
-
- asynchronous foreach statementinstrução foreach assíncrona
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ru.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ru.xlf
index 78a80e68eca0b9e496583e8fad7494af7a5d4fe1..b00e83f453e5c283e87b47b09b36731ca898c16b 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ru.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.ru.xlf
@@ -192,16 +192,6 @@
Warning: Inlining temporary variable may change code meaning.
-
- '{0}' is not null here.
- Здесь "{0}" имеет значение, отличное от NULL.
-
-
-
- '{0}' may be null here.
- Здесь "{0}" может иметь значение NULL.
-
- asynchronous foreach statementасинхронная инструкция foreach
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.tr.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.tr.xlf
index 07287de23aca3864479c9f1ddfa5642965deb868..1453666c69bf60e526e7d5a330468a5109726d7c 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.tr.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.tr.xlf
@@ -192,16 +192,6 @@
Warning: Inlining temporary variable may change code meaning.
-
- '{0}' is not null here.
- '{0}' burada null değil.
-
-
-
- '{0}' may be null here.
- '{0}' burada null olabilir.
-
- asynchronous foreach statementzaman uyumsuz foreach deyimi
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hans.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hans.xlf
index 371372589c18b7a82c46c783df5ece7e50fb1835..ffa89212cfbfd4e47a1c0468ffd6f541c7623ddb 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hans.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hans.xlf
@@ -192,16 +192,6 @@
Warning: Inlining temporary variable may change code meaning.
-
- '{0}' is not null here.
- “{0}”在此处不为 null。
-
-
-
- '{0}' may be null here.
- “{0}”可能在此处为 null。
-
- asynchronous foreach statement异步 foreach 语句
diff --git a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hant.xlf b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hant.xlf
index 05e2290af1d0de603d5bd3ef6bc8008d29183bb4..d899cca981e447533bb98bf6fd3497db5f88e13e 100644
--- a/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hant.xlf
+++ b/src/Features/CSharp/Portable/xlf/CSharpFeaturesResources.zh-Hant.xlf
@@ -192,16 +192,6 @@
Warning: Inlining temporary variable may change code meaning.
-
- '{0}' is not null here.
- '{0}' 在此不是 null。
-
-
-
- '{0}' may be null here.
- '{0}' 在此可能為 null。
-
- asynchronous foreach statement非同步 foreach 陳述式
diff --git a/src/Features/Core/Portable/FeaturesResources.resx b/src/Features/Core/Portable/FeaturesResources.resx
index a9544541d748cedcd6623383f869387702e4c440..2f4f934dc39b0bbe05a3f385753a8c77b13c32b5 100644
--- a/src/Features/Core/Portable/FeaturesResources.resx
+++ b/src/Features/Core/Portable/FeaturesResources.resx
@@ -2753,6 +2753,12 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
'{0}' cannot be null or whitespace
+
+ '{0}' is not null here.
+
+
+ '{0}' may be null here.
+
<infer>
diff --git a/src/Features/Core/Portable/QuickInfo/CommonSemanticQuickInfoProvider.TokenInfo.cs b/src/Features/Core/Portable/QuickInfo/CommonSemanticQuickInfoProvider.TokenInfo.cs
index a871113503bb240df7c0c5ed1721b348669b503d..19093500ac10f545a70951e2edce08b85d6e09cc 100644
--- a/src/Features/Core/Portable/QuickInfo/CommonSemanticQuickInfoProvider.TokenInfo.cs
+++ b/src/Features/Core/Portable/QuickInfo/CommonSemanticQuickInfoProvider.TokenInfo.cs
@@ -20,10 +20,16 @@ public struct TokenInformation
///
public readonly bool ShowAwaitReturn;
- public TokenInformation(ImmutableArray symbols, bool showAwaitReturn = false)
+ ///
+ /// The nullable flow state to show in Quick Info; will be to show nothing.
+ ///
+ public readonly NullableFlowState NullableFlowState;
+
+ public TokenInformation(ImmutableArray symbols, bool showAwaitReturn = false, NullableFlowState nullableFlowState = NullableFlowState.None)
{
Symbols = symbols;
ShowAwaitReturn = showAwaitReturn;
+ NullableFlowState = nullableFlowState;
}
}
}
diff --git a/src/Features/Core/Portable/QuickInfo/CommonSemanticQuickInfoProvider.cs b/src/Features/Core/Portable/QuickInfo/CommonSemanticQuickInfoProvider.cs
index 6ce3ea578dfef64b9b99fff37f718b4e89369b89..fdc137d7aadb57a18f10203e4f8cfa744728e96b 100644
--- a/src/Features/Core/Portable/QuickInfo/CommonSemanticQuickInfoProvider.cs
+++ b/src/Features/Core/Portable/QuickInfo/CommonSemanticQuickInfoProvider.cs
@@ -148,7 +148,7 @@ private static bool HasNoErrors(ImmutableArray symbols)
return default;
}
- protected async Task CreateContentAsync(
+ protected static async Task CreateContentAsync(
Workspace workspace,
SyntaxToken token,
SemanticModel semanticModel,
@@ -211,7 +211,7 @@ void AddSection(string kind, ImmutableArray taggedParts)
// if generating quick info for an attribute, bind to the class instead of the constructor
if (syntaxFactsService.IsAttributeName(token.Parent) &&
- documentedSymbol?.ContainingType?.IsAttribute() == true)
+ documentedSymbol.ContainingType?.IsAttribute() == true)
{
documentedSymbol = documentedSymbol.ContainingType;
}
@@ -284,10 +284,16 @@ void AddSection(string kind, ImmutableArray taggedParts)
usageTextBuilder.AddRange(awaitableUsageText);
}
- var nullableAnalysis = TryGetNullabilityAnalysis(workspace, semanticModel, token, cancellationToken);
- if (!nullableAnalysis.IsDefaultOrEmpty)
+ var nullableMessage = tokenInformation.NullableFlowState switch
{
- AddSection(QuickInfoSectionKinds.NullabilityAnalysis, nullableAnalysis);
+ NullableFlowState.MaybeNull => string.Format(FeaturesResources._0_may_be_null_here, documentedSymbol.Name),
+ NullableFlowState.NotNull => string.Format(FeaturesResources._0_is_not_null_here, documentedSymbol.Name),
+ _ => null
+ };
+
+ if (nullableMessage != null)
+ {
+ AddSection(QuickInfoSectionKinds.NullabilityAnalysis, ImmutableArray.Create(new TaggedText(TextTags.Text, nullableMessage)));
}
if (supportedPlatforms != null)
@@ -426,13 +432,12 @@ void AddSection(string kind, ImmutableArray taggedParts)
protected abstract bool GetBindableNodeForTokenIndicatingLambda(SyntaxToken token, [NotNullWhen(returnValue: true)] out SyntaxNode? found);
protected abstract bool GetBindableNodeForTokenIndicatingPossibleIndexerAccess(SyntaxToken token, [NotNullWhen(returnValue: true)] out SyntaxNode? found);
- protected virtual ImmutableArray TryGetNullabilityAnalysis(Workspace workspace, SemanticModel semanticModel, SyntaxToken token, CancellationToken cancellationToken) => default;
+ protected virtual NullableFlowState GetNullabilityAnalysis(Workspace workspace, SemanticModel semanticModel, ISymbol symbol, SyntaxNode node, CancellationToken cancellationToken) => NullableFlowState.None;
private async Task<(SemanticModel semanticModel, TokenInformation tokenInformation)> BindTokenAsync(
Document document, SyntaxToken token, CancellationToken cancellationToken)
{
var syntaxFacts = document.GetRequiredLanguageService();
- var isAwait = syntaxFacts.IsAwaitKeyword(token);
var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);
var enclosingType = semanticModel.GetEnclosingNamedType(token.SpanStart, cancellationToken);
@@ -451,8 +456,14 @@ void AddSection(string kind, ImmutableArray taggedParts)
if (symbols.Any())
{
- var discardSymbols = (symbols.First() as ITypeParameterSymbol)?.TypeParameterKind == TypeParameterKind.Cref;
- return (semanticModel, new TokenInformation(discardSymbols ? ImmutableArray.Empty : symbols, isAwait));
+ var firstSymbol = symbols.First();
+ var isAwait = syntaxFacts.IsAwaitKeyword(token);
+ var nullableFlowState = NullableFlowState.None;
+ if (bindableParent != null)
+ {
+ nullableFlowState = GetNullabilityAnalysis(document.Project.Solution.Workspace, semanticModel, firstSymbol, bindableParent, cancellationToken);
+ }
+ return (semanticModel, new TokenInformation(symbols, isAwait, nullableFlowState));
}
// Couldn't bind the token to specific symbols. If it's an operator, see if we can at
@@ -491,7 +502,18 @@ private ImmutableArray GetSymbolsFromToken(SyntaxToken token, Workspace
}
private static bool IsOk([NotNullWhen(returnValue: true)] ISymbol? symbol)
- => symbol != null && !symbol.IsErrorType();
+ {
+ if (symbol == null)
+ return false;
+
+ if (symbol.IsErrorType())
+ return false;
+
+ if (symbol is ITypeParameterSymbol { TypeParameterKind: TypeParameterKind.Cref })
+ return false;
+
+ return true;
+ }
private static bool IsAccessible(ISymbol symbol, INamedTypeSymbol? within)
=> within == null
diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf
index 06646dc71641986069bc5a51d2d8f0f38fbd1723..dfc231c55815513712315b149b1dccce371cdb1a 100644
--- a/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf
+++ b/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf
@@ -2030,6 +2030,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
'{0}' cannot be null or whitespace
+
+ '{0}' is not null here.
+ '{0}' is not null here.
+
+
+
+ '{0}' may be null here.
+ '{0}' may be null here.
+
+ 10,000,000ths of a second10,000,000ths of a second
diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf
index 5a83cc19dc860e276685760c71779b68a0e6bf90..a149b4ad8bfd1ef11f59887900d04c2186e1468f 100644
--- a/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf
+++ b/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf
@@ -2030,6 +2030,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
'{0}' cannot be null or whitespace
+
+ '{0}' is not null here.
+ '{0}' is not null here.
+
+
+
+ '{0}' may be null here.
+ '{0}' may be null here.
+
+ 10,000,000ths of a second10,000,000ths of a second
diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf
index b7709da738e9c63945862a94b6908f470ab36a2e..953dce19ca9f806553f98a0aad466cc02092ebe4 100644
--- a/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf
+++ b/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf
@@ -2030,6 +2030,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
'{0}' cannot be null or whitespace
+
+ '{0}' is not null here.
+ '{0}' is not null here.
+
+
+
+ '{0}' may be null here.
+ '{0}' may be null here.
+
+ 10,000,000ths of a second10,000,000ths of a second
diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf
index f669a05cdc1e8c5df23ff7c5731d0773a194c7e9..ac4cad737a5e9fdcf4ac29c5ba188ae95a59ac08 100644
--- a/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf
+++ b/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf
@@ -2030,6 +2030,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
'{0}' cannot be null or whitespace
+
+ '{0}' is not null here.
+ '{0}' is not null here.
+
+
+
+ '{0}' may be null here.
+ '{0}' may be null here.
+
+ 10,000,000ths of a second10,000,000ths of a second
diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf
index 1cfa08ab600b310909dcc6caa20c414609cca11d..5f6c68b8d10dc2f29bd5e92f525adeb01ec13877 100644
--- a/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf
+++ b/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf
@@ -2030,6 +2030,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
'{0}' cannot be null or whitespace
+
+ '{0}' is not null here.
+ '{0}' is not null here.
+
+
+
+ '{0}' may be null here.
+ '{0}' may be null here.
+
+ 10,000,000ths of a second10,000,000ths of a second
diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf
index 22f40a93f761521ef61c83a4fcf6029a6598a291..00f051284456f96e5e2e29207d5e44adcfb8696c 100644
--- a/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf
+++ b/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf
@@ -2030,6 +2030,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
'{0}' cannot be null or whitespace
+
+ '{0}' is not null here.
+ '{0}' is not null here.
+
+
+
+ '{0}' may be null here.
+ '{0}' may be null here.
+
+ 10,000,000ths of a second10,000,000ths of a second
diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf
index 9325807e90fcdbad28316f9467c5383e2a80b9bc..2270ea15cc31bd55ae6bf39194a02976daee7879 100644
--- a/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf
+++ b/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf
@@ -2030,6 +2030,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
'{0}' cannot be null or whitespace
+
+ '{0}' is not null here.
+ '{0}' is not null here.
+
+
+
+ '{0}' may be null here.
+ '{0}' may be null here.
+
+ 10,000,000ths of a second10,000,000ths of a second
diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf
index 6a3b7810889566f28fbe999dff204051ecef8360..b7d181d6808aa46ce3dbb24bd79addb1e6b2c639 100644
--- a/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf
+++ b/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf
@@ -2030,6 +2030,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
'{0}' cannot be null or whitespace
+
+ '{0}' is not null here.
+ '{0}' is not null here.
+
+
+
+ '{0}' may be null here.
+ '{0}' may be null here.
+
+ 10,000,000ths of a second10,000,000ths of a second
diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf
index 24af010c8b2705cf74a710c92e39444985a052d3..035b63c66fb99a09a6586af0f86835cf95ed8070 100644
--- a/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf
+++ b/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf
@@ -2030,6 +2030,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
'{0}' cannot be null or whitespace
+
+ '{0}' is not null here.
+ '{0}' is not null here.
+
+
+
+ '{0}' may be null here.
+ '{0}' may be null here.
+
+ 10,000,000ths of a second10,000,000ths of a second
diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf
index b2fcd5e1386c2712df0aa8c15f566d2cb6c3cf73..dd76a04e96c389cb49d3a8d75dca6f1a862f9c30 100644
--- a/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf
+++ b/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf
@@ -2030,6 +2030,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
'{0}' cannot be null or whitespace
+
+ '{0}' is not null here.
+ '{0}' is not null here.
+
+
+
+ '{0}' may be null here.
+ '{0}' may be null here.
+
+ 10,000,000ths of a second10,000,000ths of a second
diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf
index 272f25d04e2508a84088dae221135aedfc59d8d5..5b7fbc203421e42eeefa7a79b8828c59865f429a 100644
--- a/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf
+++ b/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf
@@ -2030,6 +2030,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
'{0}' cannot be null or whitespace
+
+ '{0}' is not null here.
+ '{0}' is not null here.
+
+
+
+ '{0}' may be null here.
+ '{0}' may be null here.
+
+ 10,000,000ths of a second10,000,000ths of a second
diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf
index c2e4ea3a2ee2575530106204b1336e5c226ad1f7..e00b5fdbaaea2733299692a491a83e8058abeb35 100644
--- a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf
+++ b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf
@@ -2030,6 +2030,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
'{0}' cannot be null or whitespace
+
+ '{0}' is not null here.
+ '{0}' is not null here.
+
+
+
+ '{0}' may be null here.
+ '{0}' may be null here.
+
+ 10,000,000ths of a second10,000,000ths of a second
diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf
index e7ecef827e7dc37d3f25e2c44e0ae7c11fff54a0..ce6cd136b32c17b4a13d6d4c4d5ae6131bfef548 100644
--- a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf
+++ b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf
@@ -2030,6 +2030,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
'{0}' cannot be null or whitespace
+
+ '{0}' is not null here.
+ '{0}' is not null here.
+
+
+
+ '{0}' may be null here.
+ '{0}' may be null here.
+
+ 10,000,000ths of a second10,000,000ths of a second