提交 5cf5afdc 编写于 作者: J Jason Malinowski

Move the nullable flow state shown from quick info into TokenInformation

This moves the fetching of the nullable state into the first part of
quick info, which is figuring out the data/model. The function to take
that model and convert it to the display information can now go static
since it's not relying on other indirection.
上级 a4fb66a3
......@@ -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)]
......
......@@ -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>
......
......@@ -2753,6 +2753,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>
......
......@@ -20,10 +20,16 @@ public struct TokenInformation
/// </summary>
public readonly bool ShowAwaitReturn;
public TokenInformation(ImmutableArray<ISymbol> symbols, bool showAwaitReturn = false)
/// <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;
}
}
}
......
......@@ -148,7 +148,7 @@ private static bool HasNoErrors(ImmutableArray<ISymbol> symbols)
return default;
}
protected async Task<QuickInfoItem> CreateContentAsync(
protected static async Task<QuickInfoItem> CreateContentAsync(
Workspace workspace,
SyntaxToken token,
SemanticModel semanticModel,
......@@ -211,7 +211,7 @@ void AddSection(string kind, ImmutableArray<TaggedText> 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<TaggedText> 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<TaggedText> 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<TaggedText> 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<ISyntaxFactsService>();
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<TaggedText> taggedParts)
if (symbols.Any())
{
var discardSymbols = (symbols.First() as ITypeParameterSymbol)?.TypeParameterKind == TypeParameterKind.Cref;
return (semanticModel, new TokenInformation(discardSymbols ? ImmutableArray<ISymbol>.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<ISymbol> 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
......
......@@ -2030,6 +2030,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>
......
......@@ -2030,6 +2030,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>
......
......@@ -2030,6 +2030,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>
......
......@@ -2030,6 +2030,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>
......
......@@ -2030,6 +2030,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>
......
......@@ -2030,6 +2030,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>
......
......@@ -2030,6 +2030,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>
......
......@@ -2030,6 +2030,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>
......
......@@ -2030,6 +2030,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>
......
......@@ -2030,6 +2030,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>
......
......@@ -2030,6 +2030,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>
......
......@@ -2030,6 +2030,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>
......
......@@ -2030,6 +2030,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>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册