提交 5fa64467 编写于 作者: C CyrusNajmabadi 提交者: GitHub

Merge pull request #17638 from CyrusNajmabadi/nullPropagateExpressionTrees

Don't offer ?. if it's going to be used in an Expression-Tree.
......@@ -338,5 +338,27 @@ void Foo()
}
class C { public void M(string s) { } }");
}
[WorkItem(17623, "https://github.com/dotnet/roslyn/issues/17623")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseNullPropagation)]
public async Task TestInExpressionTree()
{
await TestMissingInRegularAndScriptAsync(
@"
using System;
using System.Linq.Expressions;
class Program
{
void Main(string s)
{
Method<string>(t => [||]s != null ? s.ToString() : null); // works
}
public void Method<T>(Expression<Func<T, string>> functor)
{
}
}");
}
}
}
\ No newline at end of file
......@@ -67,7 +67,7 @@ private static Type[] GetNeutralAndCSharpAndVisualBasicTypes()
typeof(CodeAnalysis.CSharp.Rename.CSharpRenameConflictLanguageService),
typeof(CodeAnalysis.VisualBasic.Rename.VisualBasicRenameRewriterLanguageServiceFactory),
typeof(CodeAnalysis.CSharp.CSharpSemanticFactsServiceFactory),
typeof(CodeAnalysis.VisualBasic.VisualBasicSemanticFactsService),
typeof(CodeAnalysis.VisualBasic.VisualBasicSemanticFactsServiceFactory),
typeof(CodeAnalysis.CSharp.CodeGeneration.CSharpSyntaxGenerator),
typeof(CodeAnalysis.VisualBasic.CodeGeneration.VisualBasicSyntaxGenerator),
typeof(CSharp.LanguageServices.CSharpContentTypeLanguageService),
......@@ -89,8 +89,8 @@ private static Type[] GetNeutralAndCSharpAndVisualBasicTypes()
}
/// <summary>
/// Create fresh ExportProvider that doesnt share anything with others.
/// test can use this export provider to create all new MEF components not shared with others.
/// Create fresh ExportProvider that doesn't share anything with others. Tests can use this
/// export provider to create all new MEF components not shared with others.
/// </summary>
public static ExportProvider CreateExportProviderWithCSharpAndVisualBasic()
{
......@@ -98,8 +98,9 @@ public static ExportProvider CreateExportProviderWithCSharpAndVisualBasic()
}
/// <summary>
/// Create fresh ComposableCatalog that doesnt share anything with others.
/// everything under this catalog should have been created from scratch that doesnt share anything with others.
/// Create fresh ComposableCatalog that doest share anything with others. Everything under
/// this catalog should have been created from scratch that doesn't share anything with
/// others.
/// </summary>
public static ComposableCatalog CreateAssemblyCatalogWithCSharpAndVisualBasic()
{
......
......@@ -13,8 +13,6 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UseAutoProperty
Friend Class UseAutoPropertyAnalyzer
Inherits AbstractUseAutoPropertyAnalyzer(Of PropertyBlockSyntax, FieldDeclarationSyntax, ModifiedIdentifierSyntax, ExpressionSyntax)
Private ReadOnly _semanticFacts As New VisualBasicSemanticFactsService()
Protected Overrides Function SupportsReadOnlyProperties(compilation As Compilation) As Boolean
Return DirectCast(compilation, VisualBasicCompilation).LanguageVersion >= LanguageVersion.VisualBasic14
End Function
......@@ -146,7 +144,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UseAutoProperty
If node.Kind() = SyntaxKind.IdentifierName Then
Dim symbolInfo = semanticModel.GetSymbolInfo(node)
If field.Equals(symbolInfo.Symbol) Then
If _semanticFacts.IsWrittenTo(semanticModel, node, cancellationToken) Then
If VisualBasicSemanticFactsService.Instance.IsWrittenTo(semanticModel, node, cancellationToken) Then
Return True
End If
End If
......
......@@ -26,6 +26,9 @@ protected override bool ShouldAnalyze(ParseOptions options)
protected override ISyntaxFactsService GetSyntaxFactsService()
=> CSharpSyntaxFactsService.Instance;
protected override ISemanticFactsService GetSemanticFactsService()
=> CSharpSemanticFactsService.Instance;
protected override SyntaxKind GetSyntaxKindToAnalyze()
=> SyntaxKind.ConditionalExpression;
......
......@@ -37,15 +37,25 @@ protected AbstractUseNullPropagationDiagnosticAnalyzer()
public override DiagnosticAnalyzerCategory GetAnalyzerCategory() => DiagnosticAnalyzerCategory.SemanticDocumentAnalysis;
protected abstract TSyntaxKind GetSyntaxKindToAnalyze();
protected abstract ISyntaxFactsService GetSyntaxFactsService();
protected abstract bool IsEquals(TBinaryExpressionSyntax condition);
protected abstract bool IsNotEquals(TBinaryExpressionSyntax condition);
protected abstract bool ShouldAnalyze(ParseOptions options);
protected abstract ISyntaxFactsService GetSyntaxFactsService();
protected abstract ISemanticFactsService GetSemanticFactsService();
protected override void InitializeWorker(AnalysisContext context)
=> context.RegisterSyntaxNodeAction(AnalyzeSyntax, GetSyntaxKindToAnalyze());
{
context.RegisterCompilationStartAction(startContext =>
{
var expressionTypeOpt = startContext.Compilation.GetTypeByMetadataName("System.Linq.Expressions.Expression`1");
startContext.RegisterSyntaxNodeAction(
c => AnalyzeSyntax(c, expressionTypeOpt), GetSyntaxKindToAnalyze());
});
private void AnalyzeSyntax(SyntaxNodeAnalysisContext context)
}
private void AnalyzeSyntax(SyntaxNodeAnalysisContext context, INamedTypeSymbol expressionTypeOpt)
{
var conditionalExpression = (TConditionalExpressionSyntax)context.Node;
if (!ShouldAnalyze(conditionalExpression.SyntaxTree.Options))
......@@ -102,7 +112,7 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context)
return;
}
// Needs to be of the forme:
// Needs to be of the form:
// x == null ? null : ... or
// x != null ? ... : null;
if (isEquals && !syntaxFacts.IsNullLiteralExpression(whenTrueNode))
......@@ -124,6 +134,14 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context)
return;
}
// ?. is not available in expression-trees. Disallow the fix in that case.
var semanticFacts = GetSemanticFactsService();
var semanticModel = context.SemanticModel;
if (semanticFacts.IsInExpressionTree(semanticModel, conditionNode, expressionTypeOpt, cancellationToken))
{
return;
}
var locations = ImmutableArray.Create(
conditionalExpression.GetLocation(),
conditionPartToCheck.GetLocation(),
......@@ -162,26 +180,22 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context)
private static SyntaxNode Unwrap(ISyntaxFactsService syntaxFacts, SyntaxNode node)
{
var invocation = node as TInvocationExpression;
if (invocation != null)
if (node is TInvocationExpression invocation)
{
return syntaxFacts.GetExpressionOfInvocationExpression(invocation);
}
var memberAccess = node as TMemberAccessExpression;
if (memberAccess != null)
if (node is TMemberAccessExpression memberAccess)
{
return syntaxFacts.GetExpressionOfMemberAccessExpression(memberAccess);
}
var conditionalAccess = node as TConditionalAccessExpression;
if (conditionalAccess != null)
if (node is TConditionalAccessExpression conditionalAccess)
{
return syntaxFacts.GetExpressionOfConditionalAccessExpression(conditionalAccess);
}
var elementAccess = node as TElementAccessExpression;
if (elementAccess != null)
if (node is TElementAccessExpression elementAccess)
{
return syntaxFacts.GetExpressionOfElementAccessExpression(elementAccess);
}
......
......@@ -26,6 +26,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UseNullPropagation
Return VisualBasicSyntaxFactsService.Instance
End Function
Protected Overrides Function GetSemanticFactsService() As ISemanticFactsService
Return VisualBasicSemanticFactsService.instance
End Function
Protected Overrides Function GetSyntaxKindToAnalyze() As SyntaxKind
Return SyntaxKind.TernaryConditionalExpression
End Function
......
......@@ -4,16 +4,30 @@ Imports System.Collections.Immutable
Imports System.Composition
Imports System.Runtime.InteropServices
Imports System.Threading
Imports Microsoft.CodeAnalysis.Host
Imports Microsoft.CodeAnalysis.Host.Mef
Imports Microsoft.CodeAnalysis.LanguageServices
Imports Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic
<ExportLanguageService(GetType(ISemanticFactsService), LanguageNames.VisualBasic), [Shared]>
<ExportLanguageServiceFactory(GetType(ISemanticFactsService), LanguageNames.VisualBasic), [Shared]>
Friend Class VisualBasicSemanticFactsServiceFactory
Implements ILanguageServiceFactory
Public Function CreateLanguageService(languageServices As HostLanguageServices) As ILanguageService Implements ILanguageServiceFactory.CreateLanguageService
Return VisualBasicSemanticFactsService.Instance
End Function
End Class
Friend Class VisualBasicSemanticFactsService
Implements ISemanticFactsService
Public Shared ReadOnly Instance As New VisualBasicSemanticFactsService()
Private Sub New()
End Sub
Public ReadOnly Property SupportsImplicitInterfaceImplementation As Boolean Implements ISemanticFactsService.SupportsImplicitInterfaceImplementation
Get
Return False
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册