提交 f3435440 编写于 作者: C CyrusNajmabadi

Do not offer 'use throw expression' in expression trees.

上级 c752659a
......@@ -304,6 +304,31 @@ void M(string s)
if (s == null)
[|throw|] new ArgumentNullException(nameof(s));
}
}");
}
[WorkItem(16234, "https://github.com/dotnet/roslyn/issues/16234")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseThrowExpression)]
public async Task TestNotInExpressionTree()
{
await TestMissingAsync(
@"using System;
using System.Linq.Expressions;
class C
{
private string _s;
void Foo()
{
Expression<Action<string>> e = s =>
{
if (s == null)
[|throw|] new ArgumentNullException(nameof(s));
_s = s;
};
}
}");
}
}
......
......@@ -175,7 +175,7 @@ private void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context, INamedTypeSymb
return;
}
if (IsInExpressionTree(semanticModel, argumentExpression, expressionTypeOpt, cancellationToken))
if (argumentExpression.IsInExpressionTree(semanticModel, expressionTypeOpt, cancellationToken))
{
// out-vars are not allowed inside expression-trees. So don't offer to
// fix if we're inside one.
......@@ -234,28 +234,6 @@ private void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context, INamedTypeSymb
additionalLocations: allLocations));
}
private bool IsInExpressionTree(
SemanticModel semanticModel, SyntaxNode argumentExpression,
INamedTypeSymbol expressionTypeOpt, CancellationToken cancellationToken)
{
if (expressionTypeOpt != null)
{
for (var current = argumentExpression; current != null; current = current.Parent)
{
if (current.IsAnyLambda())
{
var typeInfo = semanticModel.GetTypeInfo(current, cancellationToken);
if (expressionTypeOpt.Equals(typeInfo.ConvertedType?.OriginalDefinition))
{
return true;
}
}
}
}
return false;
}
private bool WouldCauseDefiniteAssignmentErrors(
SemanticModel semanticModel, VariableDeclaratorSyntax localDeclarator,
BlockSyntax enclosingBlock, ISymbol outSymbol, CancellationToken cancellationToken)
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.UseThrowExpression;
......@@ -18,5 +19,8 @@ protected override bool IsSupported(ParseOptions options)
protected override ISyntaxFactsService GetSyntaxFactsService()
=> CSharpSyntaxFactsService.Instance;
protected override bool IsInExpressionTree(SyntaxNode node, SemanticModel semanticModel, INamedTypeSymbol expressionTypeOpt, CancellationToken cancellationToken)
=> node.IsInExpressionTree(semanticModel, expressionTypeOpt, cancellationToken);
}
}
\ No newline at end of file
......@@ -4,7 +4,6 @@
using System.Collections.Immutable;
using System.Reflection;
using System.Threading;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.LanguageServices;
......@@ -48,7 +47,7 @@ public DiagnosticAnalyzerCategory GetAnalyzerCategory()
public bool OpenFileOnly(Workspace workspace) => false;
private static MethodInfo s_registerOperationActionInfo =
typeof(AnalysisContext).GetTypeInfo().GetDeclaredMethod("RegisterOperationActionImmutableArrayInternal");
typeof(CompilationStartAnalysisContext).GetTypeInfo().GetDeclaredMethod("RegisterOperationActionImmutableArrayInternal");
private static MethodInfo s_getOperationInfo =
typeof(SemanticModel).GetTypeInfo().GetDeclaredMethod("GetOperationInternal");
......@@ -56,13 +55,19 @@ public DiagnosticAnalyzerCategory GetAnalyzerCategory()
protected abstract bool IsSupported(ParseOptions options);
protected override void InitializeWorker(AnalysisContext context)
=> s_registerOperationActionInfo.Invoke(context, new object[]
{
new Action<OperationAnalysisContext>(AnalyzeOperation),
ImmutableArray.Create(OperationKind.ThrowStatement)
});
{
context.RegisterCompilationStartAction(startContext =>
{
var expressionTypeOpt = startContext.Compilation.GetTypeByMetadataName("System.Linq.Expressions.Expression`1");
s_registerOperationActionInfo.Invoke(startContext, new object[]
{
new Action<OperationAnalysisContext>(operationContext => AnalyzeOperation(operationContext, expressionTypeOpt)),
ImmutableArray.Create(OperationKind.ThrowStatement)
});
});
}
private void AnalyzeOperation(OperationAnalysisContext context)
private void AnalyzeOperation(OperationAnalysisContext context, INamedTypeSymbol expressionTypeOpt)
{
var syntaxTree = context.Operation.Syntax.SyntaxTree;
if (!IsSupported(syntaxTree.Options))
......@@ -90,6 +95,11 @@ private void AnalyzeOperation(OperationAnalysisContext context)
var compilation = context.Compilation;
var semanticModel = compilation.GetSemanticModel(throwStatement.SyntaxTree);
if (IsInExpressionTree(throwStatement, semanticModel, expressionTypeOpt, cancellationToken))
{
return;
}
var ifOperation = GetContainingIfOperation(
semanticModel, throwOperation, cancellationToken);
......@@ -173,6 +183,10 @@ private void AnalyzeOperation(OperationAnalysisContext context)
}
}
protected abstract bool IsInExpressionTree(
SyntaxNode node, SemanticModel semanticModel,
INamedTypeSymbol expressionTypeOpt, CancellationToken cancellationToken);
protected abstract ISyntaxFactsService GetSyntaxFactsService();
private bool TryFindAssignmentExpression(
......
......@@ -1120,5 +1120,27 @@ public static ConditionalAccessExpressionSyntax GetInnerMostConditionalAccessExp
return result;
}
public static bool IsInExpressionTree(
this SyntaxNode node, SemanticModel semanticModel,
INamedTypeSymbol expressionTypeOpt, CancellationToken cancellationToken)
{
if (expressionTypeOpt != null)
{
for (var current = node; current != null; current = current.Parent)
{
if (current.IsAnyLambda())
{
var typeInfo = semanticModel.GetTypeInfo(current, cancellationToken);
if (expressionTypeOpt.Equals(typeInfo.ConvertedType?.OriginalDefinition))
{
return true;
}
}
}
}
return false;
}
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册