提交 307bc88b 编写于 作者: C Cyrus Najmabadi

Check for specific node shapes to walk to the right extract method parent.

上级 78a997e9
......@@ -6,6 +6,7 @@
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.LanguageServices;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.ExtractMethod;
......@@ -44,9 +45,22 @@ public override bool ContainingScopeHasAsyncKeyword()
var firstToken = GetFirstTokenInSelection();
var lastToken = GetLastTokenInSelection();
var scope = firstToken.GetCommonRoot(lastToken).GetAncestorOrThis<ExpressionSyntax>();
return scope.IsRightSideOfDotOrArrowOrColonColon()
? scope.Parent
: scope;
if (scope == null)
return null;
// If the selection ends up mapping to the name on the right in `x.y` or `x?.y`, then grab
// the full expr `x.y` or `x?.y` as the part to extract.
if (scope.Parent is MemberAccessExpressionSyntax memberAccess && memberAccess.Name == scope)
scope = (ExpressionSyntax)scope.Parent;
if (scope.Parent is MemberBindingExpressionSyntax memberBinding && memberBinding.Name == scope)
scope = (ExpressionSyntax)scope.Parent;
if (scope is MemberBindingExpressionSyntax || scope is ElementBindingExpressionSyntax)
scope = scope.GetParentConditionalAccessExpression();
return scope;
}
public override ITypeSymbol? GetContainingScopeType()
......
......@@ -25,11 +25,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
Protected Overrides Function CreateMethodName() As SyntaxToken
Dim methodName = "NewMethod"
Dim containingScope = CType(VBSelectionResult.GetContainingScope(), SyntaxNode)
Dim containingScope = VBSelectionResult.GetContainingScope()
methodName = GetMethodNameBasedOnExpression(methodName, containingScope)
Dim semanticModel = CType(SemanticDocument.SemanticModel, SemanticModel)
Dim semanticModel = SemanticDocument.SemanticModel
Dim nameGenerator = New UniqueNameGenerator(semanticModel)
Return SyntaxFactory.Identifier(
nameGenerator.CreateUniqueMethodName(containingScope, methodName))
......
......@@ -8,6 +8,7 @@ Imports Microsoft.CodeAnalysis.ExtractMethod
Imports Microsoft.CodeAnalysis.Options
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.CodeAnalysis.VisualBasic.LanguageServices
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
......@@ -94,7 +95,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
Return False
End If
Dim node = CType(Me.GetContainingScope(), SyntaxNode)
Dim node = Me.GetContainingScope()
If TypeOf node Is MethodBlockBaseSyntax Then
Dim methodBlock = DirectCast(node, MethodBlockBaseSyntax)
If methodBlock.BlockStatement IsNot Nothing Then
......@@ -120,18 +121,35 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
If SelectionInExpression Then
Dim last = GetLastTokenInSelection()
Dim expression = first.GetCommonRoot(last).GetAncestorOrThis(Of ExpressionSyntax)()
Return If(expression.IsRightSideOfDotOrBang(),
expression.Parent,
expression)
End If
Dim scope = first.GetCommonRoot(last).GetAncestorOrThis(Of ExpressionSyntax)()
Contract.ThrowIfNull(scope, "Should always find an expression given that SelectionInExpression was true")
' If the selection ends up mapping to the name on the right in `x.y` Or `x?.y`, then grab
' the full expr `x.y` Or `x?.y` as the part to extract.
Dim memberAccess = TryCast(scope.Parent, MemberAccessExpressionSyntax)
If memberAccess?.Name Is scope Then
If memberAccess.Expression Is Nothing Then
' .y or
' x?.y
scope = If(memberAccess.GetParentConditionalAccessExpression(), DirectCast(memberAccess, ExpressionSyntax))
End If
End If
' it contains statements
Return first.GetAncestors(Of SyntaxNode).FirstOrDefault(Function(n) TypeOf n Is MethodBlockBaseSyntax OrElse TypeOf n Is LambdaExpressionSyntax)
Dim invocation = TryCast(scope, InvocationExpressionSyntax)
If invocation IsNot Nothing AndAlso invocation.Expression Is Nothing Then
' x?(y)
scope = invocation.GetParentConditionalAccessExpression()
End If
Return scope
Else
' it contains statements
Return first.GetAncestors(Of SyntaxNode).FirstOrDefault(Function(n) TypeOf n Is MethodBlockBaseSyntax OrElse TypeOf n Is LambdaExpressionSyntax)
End If
End Function
Public Overrides Function GetContainingScopeType() As ITypeSymbol
Dim node = CType(Me.GetContainingScope(), SyntaxNode)
Dim node = Me.GetContainingScope()
Dim semanticModel = Me.SemanticDocument.SemanticModel
' special case for collection initializer and explicit cast
......@@ -289,11 +307,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod
' Contract.ThrowIfFalse(last.IsParentKind(SyntaxKind.GlobalStatement))
' Contract.ThrowIfFalse(last.Parent.IsParentKind(SyntaxKind.CompilationUnit))
' Return last.Parent.Parent
throw ExceptionUtilities.Unreachable
Throw ExceptionUtilities.Unreachable
End Function
Public Function IsUnderModuleBlock() As Boolean
Dim currentScope = CType(GetContainingScope(), SyntaxNode)
Dim currentScope = GetContainingScope()
Dim types = currentScope.GetAncestors(Of TypeBlockSyntax)()
Return types.Any(Function(t) t.BlockStatement.Kind = SyntaxKind.ModuleStatement)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册