提交 31b41866 编写于 作者: F Fred Silberberg 提交者: Julien Couvreur

Insert correct `WithNullableContext` binder into the binder chain to … (#41028)

* Insert correct `WithNullableContext` binder into the binder chain to ensure speculative models return correct information based on speuclation location.

* Refactor Nullable context options to rely on an enum instead of two bools.
Break out the BuckStopsHereBinder's code to allow sharing.
Fix binder ordering issue for TryGetSpeculativeSemanticModelForMethodBody.

* Make NullableContextState.State a byte for space.
上级 6c88df41
......@@ -5,7 +5,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.PooledObjects;
......@@ -223,14 +222,16 @@ internal virtual bool IsLabelsScopeBinder
/// </summary>
internal bool AreNullableAnnotationsEnabled(SyntaxTree syntaxTree, int position)
{
bool? fromTree = ((CSharpSyntaxTree)syntaxTree).GetNullableContextState(position).AnnotationsState;
Syntax.NullableContextState context = ((CSharpSyntaxTree)syntaxTree).GetNullableContextState(position);
if (fromTree != null)
return context.AnnotationsState switch
{
return fromTree.GetValueOrDefault();
}
return AreNullableAnnotationsGloballyEnabled();
Syntax.NullableContextState.State.Enabled => true,
Syntax.NullableContextState.State.Disabled => false,
Syntax.NullableContextState.State.ExplicitlyRestored => GetGlobalAnnotationState(),
Syntax.NullableContextState.State.Unknown => AreNullableAnnotationsGloballyEnabled(),
_ => throw ExceptionUtilities.UnexpectedValue(context.AnnotationsState)
};
}
internal bool AreNullableAnnotationsEnabled(SyntaxToken token)
......@@ -245,6 +246,23 @@ internal virtual bool AreNullableAnnotationsGloballyEnabled()
return Next.AreNullableAnnotationsGloballyEnabled();
}
protected bool GetGlobalAnnotationState()
{
switch (Compilation.Options.NullableContextOptions)
{
case NullableContextOptions.Enable:
case NullableContextOptions.Annotations:
return true;
case NullableContextOptions.Disable:
case NullableContextOptions.Warnings:
return false;
default:
throw ExceptionUtilities.UnexpectedValue(Compilation.Options.NullableContextOptions);
}
}
/// <summary>
/// Is the contained code within a member method body?
/// </summary>
......
......@@ -159,19 +159,7 @@ internal override TypeWithAnnotations GetIteratorElementType()
internal override bool AreNullableAnnotationsGloballyEnabled()
{
switch (Compilation.Options.NullableContextOptions)
{
case NullableContextOptions.Enable:
case NullableContextOptions.Annotations:
return true;
case NullableContextOptions.Disable:
case NullableContextOptions.Warnings:
return false;
default:
throw ExceptionUtilities.UnexpectedValue(Compilation.Options.NullableContextOptions);
}
return GetGlobalAnnotationState();
}
internal override Binder? GetBinder(SyntaxNode node)
......
......@@ -126,8 +126,14 @@ public static Diagnostic Filter(Diagnostic d, int warningLevelOption, NullableCo
bool isNullableFlowAnalysisWarning = ErrorFacts.NullableWarnings.Contains(id);
if (isNullableFlowAnalysisWarning)
{
var nullableWarningsGloballyEnabled = nullableOption == NullableContextOptions.Enable || nullableOption == NullableContextOptions.Warnings;
var nullableWarningsEnabled = tree?.GetNullableContextState(position).WarningsState ?? nullableWarningsGloballyEnabled;
Syntax.NullableContextState.State? warningsState = tree?.GetNullableContextState(position).WarningsState;
var nullableWarningsEnabled = warningsState switch
{
Syntax.NullableContextState.State.Enabled => true,
Syntax.NullableContextState.State.Disabled => false,
_ => nullableOption == NullableContextOptions.Enable || nullableOption == NullableContextOptions.Warnings
};
if (!nullableWarningsEnabled)
{
return ReportDiagnostic.Suppress;
......
......@@ -5084,13 +5084,13 @@ public sealed override NullableContext GetNullableContext(int position)
return context;
static NullableContext getFlag(bool? contextState, bool defaultEnableState, NullableContext inheritedFlag, NullableContext enableFlag) =>
static NullableContext getFlag(NullableContextState.State contextState, bool defaultEnableState, NullableContext inheritedFlag, NullableContext enableFlag) =>
contextState switch
{
null when defaultEnableState => (inheritedFlag | enableFlag),
null => inheritedFlag,
true => enableFlag,
false => NullableContext.Disabled
NullableContextState.State.Enabled => enableFlag,
NullableContextState.State.Disabled => NullableContext.Disabled,
_ when defaultEnableState => (inheritedFlag | enableFlag),
_ => inheritedFlag,
};
}
......
......@@ -198,7 +198,7 @@ internal override BoundExpression GetSpeculativelyBoundExpression(int position,
crefSymbols = default;
position = CheckAndAdjustPosition(position);
expression = SyntaxFactory.GetStandaloneExpression(expression);
binder = GetEnclosingBinder(position);
binder = GetSpeculativeBinder(position, expression, bindingOption);
var boundRoot = binder.BindExpression(expression, _ignoredDiagnostics);
ImmutableDictionary<Symbol, Symbol> ignored = null;
return (BoundExpression)NullableWalker.AnalyzeAndRewriteSpeculation(position, boundRoot, binder, GetSnapshotManager(), newSnapshots: out _, remappedSymbols: ref ignored);
......
......@@ -172,7 +172,8 @@ private bool GetSpeculativeSemanticModelForMethodBody(SyntaxTreeSemanticModel pa
Debug.Assert(binder != null);
var executablebinder = new ExecutableCodeBinder(body, methodSymbol, binder ?? this.RootBinder);
Binder executablebinder = new WithNullableContextBinder(SyntaxTree, position, binder ?? this.RootBinder);
executablebinder = new ExecutableCodeBinder(body, methodSymbol, executablebinder);
var blockBinder = executablebinder.GetBinder(body).WithAdditionalFlags(GetSemanticModelBinderFlags());
// We don't pass the snapshot manager along here, because we're speculating about an entirely new body and it should not
// be influenced by any existing code in the body.
......@@ -197,6 +198,7 @@ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticMode
}
var methodSymbol = (MethodSymbol)this.MemberSymbol;
binder = new WithNullableContextBinder(SyntaxTree, position, binder);
binder = new ExecutableCodeBinder(statement, methodSymbol, binder);
speculativeModel = CreateSpeculative(parentModel, methodSymbol, statement, binder, GetSnapshotManager(), GetRemappedSymbols(), position);
return true;
......@@ -214,6 +216,7 @@ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticMode
}
var methodSymbol = (MethodSymbol)this.MemberSymbol;
binder = new WithNullableContextBinder(SyntaxTree, position, binder);
binder = new ExecutableCodeBinder(expressionBody, methodSymbol, binder);
speculativeModel = CreateSpeculative(parentModel, methodSymbol, expressionBody, binder, position);
......@@ -228,6 +231,7 @@ internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticMode
if (binder != null)
{
var methodSymbol = (MethodSymbol)this.MemberSymbol;
binder = new WithNullableContextBinder(SyntaxTree, position, binder);
binder = new ExecutableCodeBinder(constructorInitializer, methodSymbol, binder);
speculativeModel = CreateSpeculative(parentModel, methodSymbol, constructorInitializer, binder, position);
return true;
......
......@@ -17,15 +17,23 @@ namespace Microsoft.CodeAnalysis.CSharp.Syntax
internal readonly struct NullableContextState
{
internal int Position { get; }
internal bool? WarningsState { get; }
internal bool? AnnotationsState { get; }
internal State WarningsState { get; }
internal State AnnotationsState { get; }
internal NullableContextState(int position, bool? warningsState, bool? annotationsState)
internal NullableContextState(int position, State warningsState, State annotationsState)
{
Position = position;
WarningsState = warningsState;
AnnotationsState = annotationsState;
}
internal enum State : byte
{
Unknown,
Disabled,
Enabled,
ExplicitlyRestored
}
}
internal sealed class NullableContextStateMap
{
......@@ -61,14 +69,14 @@ private static NullableContextState GetContextForFileStart(int position, bool is
{
// Generated files have an initial nullable context that is "disabled"
return isGeneratedCode
? new NullableContextState(position, warningsState: false, annotationsState: false)
: new NullableContextState(position, warningsState: null, annotationsState: null);
? new NullableContextState(position, warningsState: NullableContextState.State.Disabled, annotationsState: NullableContextState.State.Disabled)
: new NullableContextState(position, warningsState: NullableContextState.State.Unknown, annotationsState: NullableContextState.State.Unknown);
}
internal NullableContextState GetContextState(int position)
{
// PositionComparer only checks the position, not the states
var searchContext = new NullableContextState(position, default, default);
var searchContext = new NullableContextState(position, warningsState: NullableContextState.State.Unknown, annotationsState: NullableContextState.State.Unknown);
int index = _contexts.BinarySearch(searchContext, PositionComparer.Instance);
if (index < 0)
{
......@@ -97,7 +105,7 @@ internal bool HasNullableEnables()
{
foreach (var context in _contexts)
{
if (context.AnnotationsState == true || context.WarningsState == true)
if (context.AnnotationsState == NullableContextState.State.Enabled || context.WarningsState == NullableContextState.State.Enabled)
{
return true;
}
......@@ -124,12 +132,12 @@ private static ImmutableArray<NullableContextState> GetContexts(SyntaxTree tree,
}
var position = nn.Location.SourceSpan.End;
var setting = nn.SettingToken.Kind() switch
var setting = (nn.SettingToken.Kind()) switch
{
SyntaxKind.EnableKeyword => true,
SyntaxKind.DisableKeyword => false,
SyntaxKind.RestoreKeyword => (bool?)null,
var kind => throw ExceptionUtilities.UnexpectedValue(kind)
SyntaxKind.EnableKeyword => NullableContextState.State.Enabled,
SyntaxKind.DisableKeyword => NullableContextState.State.Disabled,
SyntaxKind.RestoreKeyword => NullableContextState.State.ExplicitlyRestored,
var kind => throw ExceptionUtilities.UnexpectedValue(kind),
};
var context = nn.TargetToken.Kind() switch
......
......@@ -3815,5 +3815,364 @@ void verify(DefaultExpressionSyntax expr, PublicNullableAnnotation expectedAnnot
Assert.Equal(expectedState, info.FlowState);
}
}
[Fact]
[WorkItem(40750, "https://github.com/dotnet/roslyn/issues/40750")]
public void SpeculativeSymbolInfo_OutVariableInDifferentContext_01()
{
var source =
@"#nullable enable
class C
{
void M(out C c2)
{
M(out global::C c);
c2 = c;
}
}";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
var tree = comp.SyntaxTrees[0];
var model = comp.GetSemanticModel(tree);
var type = tree.GetRoot().DescendantNodes().OfType<DeclarationExpressionSyntax>().Single().Type;
var statement = SyntaxFactory.ParseStatement(@"M(out C c);");
Assert.True(model.TryGetSpeculativeSemanticModel(type.SpanStart, statement, out var speculativeModel));
var type2 = statement.DescendantNodes().OfType<DeclarationExpressionSyntax>().Single().Type;
var symbol2 = speculativeModel.GetSymbolInfo(type2);
Assert.Equal(PublicNullableAnnotation.NotAnnotated, ((ITypeSymbol)symbol2.Symbol).NullableAnnotation);
}
[Fact]
[WorkItem(40750, "https://github.com/dotnet/roslyn/issues/40750")]
public void SpeculativeSymbolInfo_OutVariableInDifferentContext_02()
{
var source =
@"#nullable disable
class C
{
void M(out C c2)
{
M(out global::C c);
c2 = c;
}
}";
var comp = CreateCompilation(source, options: WithNonNullTypesTrue());
comp.VerifyDiagnostics();
var tree = comp.SyntaxTrees[0];
var model = comp.GetSemanticModel(tree);
var type = tree.GetRoot().DescendantNodes().OfType<DeclarationExpressionSyntax>().Single().Type;
var statement = SyntaxFactory.ParseStatement(@"M(out C c);");
Assert.True(model.TryGetSpeculativeSemanticModel(type.SpanStart, statement, out var speculativeModel));
var type2 = statement.DescendantNodes().OfType<DeclarationExpressionSyntax>().Single().Type;
var symbol2 = speculativeModel.GetSymbolInfo(type2);
Assert.Equal(PublicNullableAnnotation.None, ((ITypeSymbol)symbol2.Symbol).NullableAnnotation);
}
[Fact]
[WorkItem(40750, "https://github.com/dotnet/roslyn/issues/40750")]
public void SpeculativeSymbolInfo_OutVariableInDifferentContext_03()
{
var source =
@"#nullable enable
class C
{
void M(out C c2)
{
M(out global::C c);
c2 = c;
}
}";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
var tree = comp.SyntaxTrees[0];
var model = comp.GetSemanticModel(tree);
var type = tree.GetRoot().DescendantNodes().OfType<DeclarationExpressionSyntax>().Single().Type;
var statement = SyntaxFactory.ParseStatement(@"
#nullable disable
M(out C c);");
Assert.True(model.TryGetSpeculativeSemanticModel(type.SpanStart, statement, out var speculativeModel));
var type2 = statement.DescendantNodes().OfType<DeclarationExpressionSyntax>().Single().Type;
var symbol2 = speculativeModel.GetSymbolInfo(type2);
Assert.Equal(PublicNullableAnnotation.None, ((ITypeSymbol)symbol2.Symbol).NullableAnnotation);
}
[Fact]
[WorkItem(40750, "https://github.com/dotnet/roslyn/issues/40750")]
public void SpeculativeSymbolInfo_OutVariableInDifferentContext_04()
{
var source =
@"#nullable disable
class C
{
void M(out C c2)
{
M(out global::C c);
c2 = c;
}
}";
var comp = CreateCompilation(source, options: WithNonNullTypesTrue());
comp.VerifyDiagnostics();
var tree = comp.SyntaxTrees[0];
var model = comp.GetSemanticModel(tree);
var type = tree.GetRoot().DescendantNodes().OfType<DeclarationExpressionSyntax>().Single().Type;
var statement = SyntaxFactory.ParseStatement(@"
#nullable restore
M(out C c);");
Assert.True(model.TryGetSpeculativeSemanticModel(type.SpanStart, statement, out var speculativeModel));
var type2 = statement.DescendantNodes().OfType<DeclarationExpressionSyntax>().Single().Type;
var symbol2 = speculativeModel.GetSymbolInfo(type2);
Assert.Equal(PublicNullableAnnotation.NotAnnotated, ((ITypeSymbol)symbol2.Symbol).NullableAnnotation);
}
[Fact]
[WorkItem(40750, "https://github.com/dotnet/roslyn/issues/40750")]
public void SpeculativeSymbolInfo_OutVariableInDifferentContext_05()
{
var source =
@"#nullable disable annotations
class C
{
void M(out C c2)
{
M(out global::C c);
c2 = c;
}
}";
var comp = CreateCompilation(source, options: WithNonNullTypesTrue());
comp.VerifyDiagnostics();
var tree = comp.SyntaxTrees[0];
var model = comp.GetSemanticModel(tree);
var type = tree.GetRoot().DescendantNodes().OfType<DeclarationExpressionSyntax>().Single().Type;
var statement = SyntaxFactory.ParseStatement(@"
#nullable restore annotations
M(out C c);");
Assert.True(model.TryGetSpeculativeSemanticModel(type.SpanStart, statement, out var speculativeModel));
var type2 = statement.DescendantNodes().OfType<DeclarationExpressionSyntax>().Single().Type;
var symbol2 = speculativeModel.GetSymbolInfo(type2);
Assert.Equal(PublicNullableAnnotation.NotAnnotated, ((ITypeSymbol)symbol2.Symbol).NullableAnnotation);
}
[Fact]
[WorkItem(40750, "https://github.com/dotnet/roslyn/issues/40750")]
public void SpeculativeSymbolInfo_WholeBody_01()
{
var source =
@"#nullable enable
class C
{
void M(out C c2)
{
M(out global::C c);
c2 = c;
}
}";
var comp = CreateCompilation(source, options: WithNonNullTypesFalse());
comp.VerifyDiagnostics();
var tree = comp.SyntaxTrees[0];
var model = comp.GetSemanticModel(tree);
var type = tree.GetRoot().DescendantNodes().OfType<DeclarationExpressionSyntax>().Single().Type;
var methodDeclaration = (MethodDeclarationSyntax)SyntaxFactory.ParseMemberDeclaration(@"
void M2(out C c2)
{
M(out C c);
}");
Assert.True(model.TryGetSpeculativeSemanticModelForMethodBody(type.SpanStart, methodDeclaration, out var speculativeModel));
var type2 = methodDeclaration.DescendantNodes().OfType<DeclarationExpressionSyntax>().Single().Type;
var symbol2 = speculativeModel.GetSymbolInfo(type2);
Assert.Equal(PublicNullableAnnotation.NotAnnotated, ((ITypeSymbol)symbol2.Symbol).NullableAnnotation);
}
[Fact]
[WorkItem(40750, "https://github.com/dotnet/roslyn/issues/40750")]
public void SpeculativeSymbolInfo_WholeBody_02()
{
var source =
@"#nullable enable
class C
{
void M(out C c2)
{
M(out global::C c);
c2 = c;
}
}";
var comp = CreateCompilation(source, options: WithNonNullTypesFalse());
comp.VerifyDiagnostics();
var tree = comp.SyntaxTrees[0];
var model = comp.GetSemanticModel(tree);
var type = tree.GetRoot().DescendantNodes().OfType<DeclarationExpressionSyntax>().Single().Type;
var methodDeclaration = (MethodDeclarationSyntax)SyntaxFactory.ParseMemberDeclaration(@"
void M2(out C c2)
{
#nullable disable
M(out C c);
}");
Assert.True(model.TryGetSpeculativeSemanticModelForMethodBody(type.SpanStart, methodDeclaration, out var speculativeModel));
var type2 = methodDeclaration.DescendantNodes().OfType<DeclarationExpressionSyntax>().Single().Type;
var symbol2 = speculativeModel.GetSymbolInfo(type2);
Assert.Equal(PublicNullableAnnotation.None, ((ITypeSymbol)symbol2.Symbol).NullableAnnotation);
}
[Fact]
[WorkItem(40750, "https://github.com/dotnet/roslyn/issues/40750")]
public void SpeculativeSymbolInfo_ArrowExpression_01()
{
var source =
@"#nullable enable
class C
{
void M(out C c2)
{
M(out global::C c);
c2 = c;
}
}";
var comp = CreateCompilation(source, options: WithNonNullTypesFalse());
comp.VerifyDiagnostics();
var tree = comp.SyntaxTrees[0];
var model = comp.GetSemanticModel(tree);
var type = tree.GetRoot().DescendantNodes().OfType<DeclarationExpressionSyntax>().Single().Type;
var arrow = SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression(" M(out C c)"));
Assert.True(model.TryGetSpeculativeSemanticModel(type.SpanStart, arrow, out var speculativeModel));
var type2 = arrow.DescendantNodes().OfType<DeclarationExpressionSyntax>().Single().Type;
var symbol2 = speculativeModel.GetSymbolInfo(type2);
Assert.Equal(PublicNullableAnnotation.NotAnnotated, ((ITypeSymbol)symbol2.Symbol).NullableAnnotation);
}
[Fact]
[WorkItem(40750, "https://github.com/dotnet/roslyn/issues/40750")]
public void SpeculativeSymbolInfo_ArrowExpression_02()
{
var source =
@"#nullable enable
class C
{
void M(out C c2)
{
M(out global::C c);
c2 = c;
}
}";
var comp = CreateCompilation(source, options: WithNonNullTypesFalse());
comp.VerifyDiagnostics();
var tree = comp.SyntaxTrees[0];
var model = comp.GetSemanticModel(tree);
var type = tree.GetRoot().DescendantNodes().OfType<DeclarationExpressionSyntax>().Single().Type;
var arrow = SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression(@"
#nullable disable
M(out C c)"));
Assert.True(model.TryGetSpeculativeSemanticModel(type.SpanStart, arrow, out var speculativeModel));
var type2 = arrow.DescendantNodes().OfType<DeclarationExpressionSyntax>().Single().Type;
var symbol2 = speculativeModel.GetSymbolInfo(type2);
Assert.Equal(PublicNullableAnnotation.None, ((ITypeSymbol)symbol2.Symbol).NullableAnnotation);
}
[Fact]
[WorkItem(40750, "https://github.com/dotnet/roslyn/issues/40750")]
public void SpeculativeSymbolInfo_ConstructorInitializer_01()
{
var source =
@"#nullable enable
class C
{
C() : this("""") {}
C(string s) {}
string M(out C c2)
{
M(out global::C c);
c2 = c;
return """";
}
}";
var comp = CreateCompilation(source, options: WithNonNullTypesFalse());
comp.VerifyDiagnostics();
var tree = comp.SyntaxTrees[0];
var model = comp.GetSemanticModel(tree);
var initializer = tree.GetRoot().DescendantNodes().OfType<ConstructorInitializerSyntax>().Single();
var newInitializer = SyntaxFactory.ConstructorInitializer(SyntaxKind.ThisConstructorInitializer, SyntaxFactory.ParseArgumentList(@"(M(out C c))"));
Assert.True(model.TryGetSpeculativeSemanticModel(initializer.SpanStart, newInitializer, out var speculativeModel));
var type2 = newInitializer.DescendantNodes().OfType<DeclarationExpressionSyntax>().Single().Type;
var symbol2 = speculativeModel.GetSymbolInfo(type2);
Assert.Equal(PublicNullableAnnotation.NotAnnotated, ((ITypeSymbol)symbol2.Symbol).NullableAnnotation);
}
[Fact]
[WorkItem(40750, "https://github.com/dotnet/roslyn/issues/40750")]
public void SpeculativeSymbolInfo_ConstructorInitializer_02()
{
var source =
@"#nullable enable
class C
{
C() : this("""") {}
C(string s) {}
string M(out C c2)
{
M(out global::C c);
c2 = c;
return """";
}
}";
var comp = CreateCompilation(source, options: WithNonNullTypesFalse());
comp.VerifyDiagnostics();
var tree = comp.SyntaxTrees[0];
var model = comp.GetSemanticModel(tree);
var initializer = tree.GetRoot().DescendantNodes().OfType<ConstructorInitializerSyntax>().Single();
var newInitializer = SyntaxFactory.ConstructorInitializer(SyntaxKind.ThisConstructorInitializer, SyntaxFactory.ParseArgumentList(@"(
#nullable disable
M(out C c))"));
Assert.True(model.TryGetSpeculativeSemanticModel(initializer.SpanStart, newInitializer, out var speculativeModel));
var type2 = newInitializer.DescendantNodes().OfType<DeclarationExpressionSyntax>().Single().Type;
var symbol2 = speculativeModel.GetSymbolInfo(type2);
Assert.Equal(PublicNullableAnnotation.None, ((ITypeSymbol)symbol2.Symbol).NullableAnnotation);
}
[Fact]
[WorkItem(40750, "https://github.com/dotnet/roslyn/issues/40750"),
WorkItem(39993, "https://github.com/dotnet/roslyn/issues/39993")]
public void SpeculativeSymbolInfo_Expression()
{
var source =
@"#nullable enable
class C
{
void M(out C c2)
{
M(out global::C c);
c2 = c;
}
}";
var comp = CreateCompilation(source, options: WithNonNullTypesFalse());
comp.VerifyDiagnostics();
var tree = comp.SyntaxTrees[0];
var model = comp.GetSemanticModel(tree);
var initializer = tree.GetRoot().DescendantNodes().OfType<DeclarationExpressionSyntax>().Single();
var expression = SyntaxFactory.ParseExpression(@"M(out C c)");
var symbol2 = (IMethodSymbol)model.GetSpeculativeSymbolInfo(initializer.Position, expression, SpeculativeBindingOption.BindAsExpression).Symbol;
Assert.Equal(PublicNullableAnnotation.NotAnnotated, symbol2.Parameters.Single().Type.NullableAnnotation);
}
}
}
......@@ -2253,5 +2253,30 @@ static void M(bool c)
}}
}}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInlineDeclaration)]
public async Task InlineVariable_NullableEnable()
{
await TestInRegularAndScriptAsync(@"
#nullable enable
class C
{
void M(out C c2)
{
[|C|] c;
M(out c);
c2 = c;
}
}", @"
#nullable enable
class C
{
void M(out C c2)
{
M(out C c);
c2 = c;
}
}");
}
}
}
......@@ -1240,7 +1240,7 @@ class C
}", safe: true, useSymbolAnnotations);
}
[Theory(Skip = "https://github.com/dotnet/roslyn/issues/39641"), InlineData(true), InlineData(false)]
[Theory, InlineData(true), InlineData(false)]
[WorkItem(39641, "https://github.com/dotnet/roslyn/issues/39641")]
public async Task TestSafeWithMatchingSimpleNameInAllLocations(bool useSymbolAnnotations)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册