提交 24b7163f 编写于 作者: J Julien Couvreur 提交者: GitHub

NullReferenceException in CheckFeatureAvailability which Discard and SpeculativeSemanticModel

Cherry-picking #17544 to the dev15.2 branch.

Conflicts:
	src/Compilers/CSharp/Test/Semantic/Semantics/OutVarTests.cs
......@@ -1223,7 +1223,7 @@ private static bool FallBackOnDiscard(IdentifierNameSyntax node, DiagnosticBag d
bool isDiscard = containingDeconstruction != null || IsOutVarDiscardIdentifier(node);
if (isDiscard)
{
CheckFeatureAvailability(node.Location, MessageID.IDS_FeatureTuples, diagnostics);
CheckFeatureAvailability(node, MessageID.IDS_FeatureTuples, diagnostics);
}
return isDiscard;
......
......@@ -1350,7 +1350,7 @@ private bool TryBindNameofOperator(InvocationExpressionSyntax node, DiagnosticBa
private BoundExpression BindNameofOperatorInternal(InvocationExpressionSyntax node, DiagnosticBag diagnostics)
{
CheckFeatureAvailability(node.GetLocation(), MessageID.IDS_FeatureNameof, diagnostics);
CheckFeatureAvailability(node, MessageID.IDS_FeatureNameof, diagnostics);
var argument = node.ArgumentList.Arguments[0].Expression;
string name = "";
// We relax the instance-vs-static requirement for top-level member access expressions by creating a NameofBinder binder.
......
......@@ -189,8 +189,7 @@ private Symbol BindTypeOrAlias(TypeSyntax syntax, DiagnosticBag diagnostics, out
if (isVar)
{
// GetLocation() so that it also works in speculative contexts.
CheckFeatureAvailability(syntax.GetLocation(), MessageID.IDS_FeatureImplicitLocal, diagnostics);
CheckFeatureAvailability(syntax, MessageID.IDS_FeatureImplicitLocal, diagnostics);
}
return symbol;
......@@ -2067,22 +2066,19 @@ private AssemblySymbol GetForwardedToAssembly(string fullName, int arity, out bo
return null;
}
internal static void CheckFeatureAvailability(Location location, MessageID feature, DiagnosticBag diagnostics)
internal static void CheckFeatureAvailability(SyntaxNode syntax, MessageID feature, DiagnosticBag diagnostics, Location locationOpt = null)
{
var options = (CSharpParseOptions)location.SourceTree.Options;
var options = (CSharpParseOptions)syntax.SyntaxTree.Options;
if (options.IsFeatureEnabled(feature))
{
return;
}
var location = locationOpt ?? syntax.GetLocation();
string requiredFeature = feature.RequiredFeature();
if (requiredFeature != null)
{
if (!options.IsFeatureEnabled(feature))
{
diagnostics.Add(ErrorCode.ERR_FeatureIsExperimental, location, feature.Localize(), requiredFeature);
}
diagnostics.Add(ErrorCode.ERR_FeatureIsExperimental, location, feature.Localize(), requiredFeature);
return;
}
......
......@@ -438,8 +438,7 @@ private BoundExpression BindSwitchExpression(DiagnosticBag diagnostics)
// time, so it doesn't really matter.
if (switchGoverningType.SpecialType == SpecialType.System_Boolean)
{
// GetLocation() so that it also works in speculative contexts.
CheckFeatureAvailability(node.GetLocation(), MessageID.IDS_FeatureSwitchOnBool, diagnostics);
CheckFeatureAvailability(node, MessageID.IDS_FeatureSwitchOnBool, diagnostics);
}
return switchExpression;
......
......@@ -183,10 +183,11 @@ internal sealed class SourcePropertySymbol : PropertySymbol, IAttributeTargetSym
if (notRegularProperty)
{
Binder.CheckFeatureAvailability(location,
isReadOnly ? MessageID.IDS_FeatureReadonlyAutoImplementedProperties :
MessageID.IDS_FeatureAutoImplementedProperties,
diagnostics);
Binder.CheckFeatureAvailability(
syntax,
isReadOnly ? MessageID.IDS_FeatureReadonlyAutoImplementedProperties : MessageID.IDS_FeatureAutoImplementedProperties,
diagnostics,
location);
}
}
......
......@@ -31456,6 +31456,37 @@ public static void Main(string[] args)
var symbol = (ILocalSymbol)model.GetDeclaredSymbol(decl.Designation);
Assert.Equal("System.Int32", symbol.Type.ToTestDisplayString());
}
[Fact]
[WorkItem(388744, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=388744")]
public void SpeculativeSemanticModelWithOutDiscard()
{
var source =
@"class C
{
static void F()
{
C.G(out _);
}
static void G(out object o)
{
o = null;
}
}";
var comp = CreateCompilationWithMscorlib(source);
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
var identifierBefore = GetReferences(tree, "G").Single();
Assert.Equal(tree, identifierBefore.Location.SourceTree);
var statementBefore = identifierBefore.Ancestors().OfType<StatementSyntax>().First();
var statementAfter = SyntaxFactory.ParseStatement(@"G(out _);");
bool success = model.TryGetSpeculativeSemanticModel(statementBefore.SpanStart, statementAfter, out model);
Assert.True(success);
var identifierAfter = statementAfter.DescendantNodes().OfType<IdentifierNameSyntax>().Single(id => id.Identifier.ValueText == "G");
Assert.Null(identifierAfter.Location.SourceTree);
var info = model.GetSymbolInfo(identifierAfter);
Assert.Equal("void C.G(out System.Object o)", info.Symbol.ToTestDisplayString());
}
}
internal static class OutVarTestsExtensions
......@@ -6,6 +6,7 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.CodeFixes.SimplifyTypeNames;
using Microsoft.CodeAnalysis.CSharp.Diagnostics.SimplifyTypeNames;
using Microsoft.CodeAnalysis.Diagnostics;
......@@ -3765,6 +3766,66 @@ void M()
diagnosticSeverity: DiagnosticSeverity.Warning);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSimplifyTypeNames)]
[WorkItem(388744, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=388744")]
public async Task SimplifyTypeNameWithOutDiscard()
{
await TestAsync(
@"class C
{
static void F()
{
[|C.G|](out _);
}
static void G(out object o)
{
o = null;
}
}",
@"class C
{
static void F()
{
G(out _);
}
static void G(out object o)
{
o = null;
}
}",
parseOptions: CSharpParseOptions.Default);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSimplifyTypeNames)]
[WorkItem(388744, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=388744")]
public async Task SimplifyTypeNameWithOutDiscard_FeatureDisabled()
{
await TestAsync(
@"class C
{
static void F()
{
[|C.G|](out _);
}
static void G(out object o)
{
o = null;
}
}",
@"class C
{
static void F()
{
G(out _);
}
static void G(out object o)
{
o = null;
}
}",
parseOptions: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp6));
}
private async Task TestWithPredefinedTypeOptionsAsync(string code, string expected, int index = 0)
{
await TestAsync(code, expected, index, options: PreferIntrinsicTypeEverywhere);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册