未验证 提交 ff86816d 编写于 作者: M msftbot[bot] 提交者: GitHub

Merge pull request #44655 from jasonmalinowski/quick-info-refactoring

Refactor some of Quick Info to prep for LSIF Quick Info support
......@@ -1345,7 +1345,7 @@ async Task UseAsync()
result = await lambda();
}
}";
await TestAsync(markup, MainDescription($"({CSharpFeaturesResources.awaitable}) {string.Format(FeaturesResources.Awaited_task_returns_0, "class System.Threading.Tasks.Task<TResult>")}"),
await TestAsync(markup, MainDescription(string.Format(FeaturesResources.Awaited_task_returns_0, $"({CSharpFeaturesResources.awaitable}) class System.Threading.Tasks.Task<TResult>")),
TypeParameterMap($"\r\nTResult {FeaturesResources.is_} int"));
}
......@@ -5230,7 +5230,7 @@ async Task<int[]> M()
awa$$it M();
}
}";
await TestAsync(markup, MainDescription("int[]"));
await TestAsync(markup, MainDescription(string.Format(FeaturesResources.Awaited_task_returns_0, "int[]")));
}
[WorkItem(1114300, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1114300")]
......@@ -5247,7 +5247,7 @@ async Task<dynamic> M()
awa$$it M();
}
}";
await TestAsync(markup, MainDescription("dynamic"));
await TestAsync(markup, MainDescription(string.Format(FeaturesResources.Awaited_task_returns_0, "dynamic")));
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
......@@ -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)]
......
......@@ -1897,7 +1897,7 @@ End Class
</Project>
</Workspace>.ToString()
Dim description = <File>&lt;<%= VBFeaturesResources.Awaitable %>&gt; <%= String.Format(FeaturesResources.Awaited_task_returns_0, "Class System.Threading.Tasks.Task(Of TResult)") %></File>.ConvertTestSourceTag()
Dim description = <File><%= String.Format(FeaturesResources.Awaited_task_returns_0, $"<{VBFeaturesResources.Awaitable}> Class System.Threading.Tasks.Task(Of TResult)") %></File>.ConvertTestSourceTag()
Await TestFromXmlAsync(markup, MainDescription(description), TypeParameterMap(vbCrLf & $"TResult {FeaturesResources.is_} Integer"))
End Function
......
......@@ -574,12 +574,6 @@
<value>Make 'ref struct'</value>
<comment>{Locked="ref"}{Locked="struct"} "ref" and "struct" are C# keywords and should not be localized.</comment>
</data>
<data name="_0_is_not_null_here" xml:space="preserve">
<value>'{0}' is not null here.</value>
</data>
<data name="_0_may_be_null_here" xml:space="preserve">
<value>'{0}' may be null here.</value>
</data>
<data name="Assign_out_parameters" xml:space="preserve">
<value>Assign 'out' parameters</value>
<comment>{Locked="out"} "out" is a C# keyword and should not be localized.</comment>
......
......@@ -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<TaggedText> 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<ISyntaxFactsService>();
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<TaggedText> 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<TaggedText> 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;
}
}
}
......@@ -192,16 +192,6 @@
<target state="new">Warning: Inlining temporary variable may change code meaning.</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="translated">{0} tady není null.</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="translated">{0} tady může být null.</target>
<note />
</trans-unit>
<trans-unit id="asynchronous_foreach_statement">
<source>asynchronous foreach statement</source>
<target state="translated">asynchronní příkaz foreach</target>
......
......@@ -192,16 +192,6 @@
<target state="new">Warning: Inlining temporary variable may change code meaning.</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="translated">"{0}" ist hier nicht NULL.</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="translated">"{0}" darf hier NULL sein.</target>
<note />
</trans-unit>
<trans-unit id="asynchronous_foreach_statement">
<source>asynchronous foreach statement</source>
<target state="translated">asynchrone foreach-Anweisung</target>
......
......@@ -192,16 +192,6 @@
<target state="new">Warning: Inlining temporary variable may change code meaning.</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="translated">"{0}" no es NULL aquí.</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="translated">"{0}" puede ser NULL aquí.</target>
<note />
</trans-unit>
<trans-unit id="asynchronous_foreach_statement">
<source>asynchronous foreach statement</source>
<target state="translated">instrucción foreach asincrónica</target>
......
......@@ -192,16 +192,6 @@
<target state="new">Warning: Inlining temporary variable may change code meaning.</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="translated">'{0}' n'a pas une valeur null ici.</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="translated">'{0}' a peut-être une valeur null ici.</target>
<note />
</trans-unit>
<trans-unit id="asynchronous_foreach_statement">
<source>asynchronous foreach statement</source>
<target state="translated">instruction foreach asynchrone</target>
......
......@@ -192,16 +192,6 @@
<target state="new">Warning: Inlining temporary variable may change code meaning.</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="translated">'{0}' non è Null in questo punto.</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="translated">'{0}' può essere Null in questo punto.</target>
<note />
</trans-unit>
<trans-unit id="asynchronous_foreach_statement">
<source>asynchronous foreach statement</source>
<target state="translated">istruzione foreach asincrona</target>
......
......@@ -192,16 +192,6 @@
<target state="new">Warning: Inlining temporary variable may change code meaning.</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="translated">ここでは、'{0}' は null ではありません。</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="translated">ここでは、'{0}' は null である可能性があります。</target>
<note />
</trans-unit>
<trans-unit id="asynchronous_foreach_statement">
<source>asynchronous foreach statement</source>
<target state="translated">非同期の foreach ステートメント</target>
......
......@@ -192,16 +192,6 @@
<target state="new">Warning: Inlining temporary variable may change code meaning.</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="translated">'{0}'은(는) 여기에서 null이 아닙니다.</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="translated">'{0}'은(는) 여기에서 null일 수 있습니다.</target>
<note />
</trans-unit>
<trans-unit id="asynchronous_foreach_statement">
<source>asynchronous foreach statement</source>
<target state="translated">비동기 foreach 문</target>
......
......@@ -192,16 +192,6 @@
<target state="new">Warning: Inlining temporary variable may change code meaning.</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="translated">Element „{0}” nie ma wartości null w tym miejscu.</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="translated">Element „{0}” może mieć wartość null w tym miejscu.</target>
<note />
</trans-unit>
<trans-unit id="asynchronous_foreach_statement">
<source>asynchronous foreach statement</source>
<target state="translated">asynchroniczna instrukcja foreach</target>
......
......@@ -192,16 +192,6 @@
<target state="new">Warning: Inlining temporary variable may change code meaning.</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="translated">'{0}' não é nulo aqui.</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="translated">'{0}' pode ser nulo aqui.</target>
<note />
</trans-unit>
<trans-unit id="asynchronous_foreach_statement">
<source>asynchronous foreach statement</source>
<target state="translated">instrução foreach assíncrona</target>
......
......@@ -192,16 +192,6 @@
<target state="new">Warning: Inlining temporary variable may change code meaning.</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="translated">Здесь "{0}" имеет значение, отличное от NULL.</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="translated">Здесь "{0}" может иметь значение NULL.</target>
<note />
</trans-unit>
<trans-unit id="asynchronous_foreach_statement">
<source>asynchronous foreach statement</source>
<target state="translated">асинхронная инструкция foreach</target>
......
......@@ -192,16 +192,6 @@
<target state="new">Warning: Inlining temporary variable may change code meaning.</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="translated">'{0}' burada null değil.</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="translated">'{0}' burada null olabilir.</target>
<note />
</trans-unit>
<trans-unit id="asynchronous_foreach_statement">
<source>asynchronous foreach statement</source>
<target state="translated">zaman uyumsuz foreach deyimi</target>
......
......@@ -192,16 +192,6 @@
<target state="new">Warning: Inlining temporary variable may change code meaning.</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="translated">“{0}”在此处不为 null。</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="translated">“{0}”可能在此处为 null。</target>
<note />
</trans-unit>
<trans-unit id="asynchronous_foreach_statement">
<source>asynchronous foreach statement</source>
<target state="translated">异步 foreach 语句</target>
......
......@@ -192,16 +192,6 @@
<target state="new">Warning: Inlining temporary variable may change code meaning.</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="translated">'{0}' 在此不是 null。</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="translated">'{0}' 在此可能為 null。</target>
<note />
</trans-unit>
<trans-unit id="asynchronous_foreach_statement">
<source>asynchronous foreach statement</source>
<target state="translated">非同步 foreach 陳述式</target>
......
......@@ -2750,6 +2750,12 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
<data name="_0_cannot_be_null_or_whitespace" xml:space="preserve">
<value>'{0}' cannot be null or whitespace</value>
</data>
<data name="_0_is_not_null_here" xml:space="preserve">
<value>'{0}' is not null here.</value>
</data>
<data name="_0_may_be_null_here" xml:space="preserve">
<value>'{0}' may be null here.</value>
</data>
<data name="ChangeSignature_NewParameterInferValue" xml:space="preserve">
<value>&lt;infer&gt;</value>
</data>
......
......@@ -283,7 +283,7 @@ private async Task AddDescriptionPartAsync(ISymbol symbol)
}
else
{
await AddDescriptionForNamedTypeAsync(namedType).ConfigureAwait(false);
AddDescriptionForNamedType(namedType);
}
}
else if (symbol is INamespaceSymbol namespaceSymbol)
......@@ -380,37 +380,14 @@ private void AddDescriptionForDynamicType()
PlainText(FeaturesResources.Represents_an_object_whose_operations_will_be_resolved_at_runtime));
}
private async Task AddDescriptionForNamedTypeAsync(INamedTypeSymbol symbol)
private void AddDescriptionForNamedType(INamedTypeSymbol symbol)
{
if (symbol.IsAwaitableNonDynamic(_semanticModel, _position))
{
AddAwaitablePrefix();
}
var token = await _semanticModel.SyntaxTree.GetTouchingTokenAsync(_position, CancellationToken).ConfigureAwait(false);
if (token != default)
{
var syntaxFactsService = Workspace.Services.GetLanguageServices(token.Language).GetService<ISyntaxFactsService>();
if (syntaxFactsService.IsAwaitKeyword(token))
{
if (symbol.SpecialType == SpecialType.System_Void)
{
AddToGroup(SymbolDescriptionGroups.MainDescription,
PlainText(FeaturesResources.Awaited_task_returns_no_value));
return;
}
AddAwaitSymbolDescription(symbol);
}
else
{
AddSymbolDescription(symbol);
}
}
else
{
AddSymbolDescription(symbol);
}
AddSymbolDescription(symbol);
if (!symbol.IsUnboundGenericType && !TypeArgumentsAndParametersAreSame(symbol))
{
......@@ -421,18 +398,6 @@ private async Task AddDescriptionForNamedTypeAsync(INamedTypeSymbol symbol)
}
}
private void AddAwaitSymbolDescription(INamedTypeSymbol symbol)
{
var defaultSymbol = "{0}";
var symbolIndex = FeaturesResources.Awaited_task_returns_0.IndexOf(defaultSymbol);
AddToGroup(SymbolDescriptionGroups.MainDescription,
PlainText(FeaturesResources.Awaited_task_returns_0.Substring(0, symbolIndex)));
AddSymbolDescription(symbol);
AddToGroup(SymbolDescriptionGroups.MainDescription,
PlainText(FeaturesResources.Awaited_task_returns_0.Substring(symbolIndex + defaultSymbol.Length)));
}
private void AddSymbolDescription(INamedTypeSymbol symbol)
{
if (symbol.TypeKind == TypeKind.Delegate)
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Immutable;
namespace Microsoft.CodeAnalysis.QuickInfo
{
internal abstract partial class CommonSemanticQuickInfoProvider
{
public struct TokenInformation
{
public readonly ImmutableArray<ISymbol> Symbols;
/// <summary>
/// True if this quick info came from hovering over an 'await' keyword, which we show the return
/// type of with special text.
/// </summary>
public readonly bool ShowAwaitReturn;
/// <summary>
/// The nullable flow state to show in Quick Info; will be <see cref="NullableFlowState.None"/> to show nothing.
/// </summary>
public readonly NullableFlowState NullableFlowState;
public TokenInformation(ImmutableArray<ISymbol> symbols, bool showAwaitReturn = false, NullableFlowState nullableFlowState = NullableFlowState.None)
{
Symbols = symbols;
ShowAwaitReturn = showAwaitReturn;
NullableFlowState = nullableFlowState;
}
}
}
}
......@@ -2040,6 +2040,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
<target state="new">'{0}' cannot be null or whitespace</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="new">'{0}' is not null here.</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="new">'{0}' may be null here.</target>
<note />
</trans-unit>
<trans-unit id="_10000000ths_of_a_second">
<source>10,000,000ths of a second</source>
<target state="new">10,000,000ths of a second</target>
......
......@@ -2040,6 +2040,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
<target state="new">'{0}' cannot be null or whitespace</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="new">'{0}' is not null here.</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="new">'{0}' may be null here.</target>
<note />
</trans-unit>
<trans-unit id="_10000000ths_of_a_second">
<source>10,000,000ths of a second</source>
<target state="new">10,000,000ths of a second</target>
......
......@@ -2040,6 +2040,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
<target state="new">'{0}' cannot be null or whitespace</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="new">'{0}' is not null here.</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="new">'{0}' may be null here.</target>
<note />
</trans-unit>
<trans-unit id="_10000000ths_of_a_second">
<source>10,000,000ths of a second</source>
<target state="new">10,000,000ths of a second</target>
......
......@@ -2040,6 +2040,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
<target state="new">'{0}' cannot be null or whitespace</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="new">'{0}' is not null here.</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="new">'{0}' may be null here.</target>
<note />
</trans-unit>
<trans-unit id="_10000000ths_of_a_second">
<source>10,000,000ths of a second</source>
<target state="new">10,000,000ths of a second</target>
......
......@@ -2040,6 +2040,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
<target state="new">'{0}' cannot be null or whitespace</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="new">'{0}' is not null here.</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="new">'{0}' may be null here.</target>
<note />
</trans-unit>
<trans-unit id="_10000000ths_of_a_second">
<source>10,000,000ths of a second</source>
<target state="new">10,000,000ths of a second</target>
......
......@@ -2040,6 +2040,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
<target state="new">'{0}' cannot be null or whitespace</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="new">'{0}' is not null here.</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="new">'{0}' may be null here.</target>
<note />
</trans-unit>
<trans-unit id="_10000000ths_of_a_second">
<source>10,000,000ths of a second</source>
<target state="new">10,000,000ths of a second</target>
......
......@@ -2040,6 +2040,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
<target state="new">'{0}' cannot be null or whitespace</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="new">'{0}' is not null here.</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="new">'{0}' may be null here.</target>
<note />
</trans-unit>
<trans-unit id="_10000000ths_of_a_second">
<source>10,000,000ths of a second</source>
<target state="new">10,000,000ths of a second</target>
......
......@@ -2040,6 +2040,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
<target state="new">'{0}' cannot be null or whitespace</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="new">'{0}' is not null here.</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="new">'{0}' may be null here.</target>
<note />
</trans-unit>
<trans-unit id="_10000000ths_of_a_second">
<source>10,000,000ths of a second</source>
<target state="new">10,000,000ths of a second</target>
......
......@@ -2040,6 +2040,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
<target state="new">'{0}' cannot be null or whitespace</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="new">'{0}' is not null here.</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="new">'{0}' may be null here.</target>
<note />
</trans-unit>
<trans-unit id="_10000000ths_of_a_second">
<source>10,000,000ths of a second</source>
<target state="new">10,000,000ths of a second</target>
......
......@@ -2040,6 +2040,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
<target state="new">'{0}' cannot be null or whitespace</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="new">'{0}' is not null here.</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="new">'{0}' may be null here.</target>
<note />
</trans-unit>
<trans-unit id="_10000000ths_of_a_second">
<source>10,000,000ths of a second</source>
<target state="new">10,000,000ths of a second</target>
......
......@@ -2040,6 +2040,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
<target state="new">'{0}' cannot be null or whitespace</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="new">'{0}' is not null here.</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="new">'{0}' may be null here.</target>
<note />
</trans-unit>
<trans-unit id="_10000000ths_of_a_second">
<source>10,000,000ths of a second</source>
<target state="new">10,000,000ths of a second</target>
......
......@@ -2040,6 +2040,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
<target state="new">'{0}' cannot be null or whitespace</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="new">'{0}' is not null here.</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="new">'{0}' may be null here.</target>
<note />
</trans-unit>
<trans-unit id="_10000000ths_of_a_second">
<source>10,000,000ths of a second</source>
<target state="new">10,000,000ths of a second</target>
......
......@@ -2040,6 +2040,16 @@ Zero-width positive lookbehind assertions are typically used at the beginning of
<target state="new">'{0}' cannot be null or whitespace</target>
<note />
</trans-unit>
<trans-unit id="_0_is_not_null_here">
<source>'{0}' is not null here.</source>
<target state="new">'{0}' is not null here.</target>
<note />
</trans-unit>
<trans-unit id="_0_may_be_null_here">
<source>'{0}' may be null here.</source>
<target state="new">'{0}' may be null here.</target>
<note />
</trans-unit>
<trans-unit id="_10000000ths_of_a_second">
<source>10,000,000ths of a second</source>
<target state="new">10,000,000ths of a second</target>
......
......@@ -121,7 +121,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.QuickInfo
Return False
End Function
Private Overloads Async Function BuildContentAsync(
Private Overloads Shared Async Function BuildContentAsync(
document As Document,
token As SyntaxToken,
declarators As SeparatedSyntaxList(Of VariableDeclaratorSyntax),
......@@ -134,7 +134,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.QuickInfo
Dim semantics = Await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(False)
Dim types = declarators.SelectMany(Function(d) d.Names).Select(
Function(n)
Function(n) As ISymbol
Dim symbol = semantics.GetDeclaredSymbol(n, cancellationToken)
If symbol Is Nothing Then
Return Nothing
......@@ -147,17 +147,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.QuickInfo
Else
Return Nothing
End If
End Function).WhereNotNull().Distinct().ToList()
End Function).WhereNotNull().Distinct().ToImmutableArray()
If types.Count = 0 Then
If types.Length = 0 Then
Return Nothing
End If
If types.Count > 1 Then
If types.Length > 1 Then
Return QuickInfoItem.Create(token.Span, sections:=ImmutableArray.Create(QuickInfoSection.Create(QuickInfoSectionKinds.Description, ImmutableArray.Create(New TaggedText(TextTags.Text, VBFeaturesResources.Multiple_Types)))))
End If
Return Await CreateContentAsync(document.Project.Solution.Workspace, token, semantics, types, supportedPlatforms:=Nothing, cancellationToken:=cancellationToken).ConfigureAwait(False)
Return Await CreateContentAsync(document.Project.Solution.Workspace, token, semantics, New TokenInformation(types), supportedPlatforms:=Nothing, cancellationToken:=cancellationToken).ConfigureAwait(False)
End Function
Private Shared Async Function BuildContentForIntrinsicOperatorAsync(document As Document,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册