提交 964d1801 编写于 作者: P Petr Houška

Fix ConvertLocalFuncToMethod not available when selection is used.

上级 d680432e
......@@ -550,6 +550,54 @@ void M()
return null;
}}
}}
}}");
}
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertLocalFunctionToMethod)]
public async Task TestWholeMethodSelectionPositon()
{
await TestAsync("[|C LocalFunction(C c)");
await TestMissingAsync("C LocalFunction(C c)[|");
async Task TestAsync(string signature)
{
await TestInRegularAndScriptAsync(
$@"class C
{{
void M()
{{
{signature}
{{
return null;
}}|]
}}
}}",
@"class C
{
void M()
{
}
private static C LocalFunction(C c)
{
return null;
}
}");
}
async Task TestMissingAsync(string signature)
{
await this.TestMissingAsync(
$@"class C
{{
void M()
{{
{signature}
{{
return null;
}}|]
}}
}}");
}
}
......
......@@ -42,15 +42,18 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte
var cancellationToken = context.CancellationToken;
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var identifier = await root.SyntaxTree.GetTouchingTokenAsync(context.Span.Start,
token => token.Parent.IsKind(SyntaxKind.LocalFunctionStatement), cancellationToken).ConfigureAwait(false);
var identifier = context.Span.IsEmpty
? await root.SyntaxTree.GetTouchingTokenAsync(context.Span.Start, token => token.Parent.IsKind(SyntaxKind.LocalFunctionStatement), cancellationToken).ConfigureAwait(false)
: await root.SyntaxTree.GetLeftmostTokenInSpanAsync(context.Span, token => token.Parent.IsKind(SyntaxKind.LocalFunctionStatement), cancellationToken).ConfigureAwait(false);
if (identifier == default)
{
return;
}
if (context.Span.Length > 0 &&
context.Span != identifier.Span)
(context.Span != identifier.Span && context.Span != identifier.Parent.Span)) // either local function's identifier Token or the whole function's span
{
return;
}
......
......@@ -72,6 +72,46 @@ public static bool IsScript(this SyntaxTree syntaxTree)
return default;
}
/// <summary>
/// Returns the first Token that passes <paramref name="predicate"/> within supplied <paramref name="span"/>.
/// </summary>
public static async Task<SyntaxToken> GetLeftmostTokenInSpanAsync(
this SyntaxTree syntaxTree,
TextSpan span,
Predicate<SyntaxToken> predicate,
CancellationToken cancellationToken,
bool findInsideTrivia = false,
bool includeSkipped = true,
bool includeDirectives = false,
bool includeDocumentationComments = false)
{
Contract.ThrowIfNull(syntaxTree);
if (span.Start >= syntaxTree.Length)
{
return default;
}
var root = await syntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false);
var token = root.FindToken(span.Start, findInsideTrivia);
while (!predicate(token))
{
if (token.FullSpan.End >= syntaxTree.Length)
{
// SyntaxKind = None
return default;
}
token = root.FindTokenOnRightOfPosition(
token.FullSpan.End,
includeSkipped, includeDirectives, includeDocumentationComments);
}
return token;
}
public static bool IsEntirelyHidden(this SyntaxTree tree, TextSpan span, CancellationToken cancellationToken)
{
if (!tree.HasHiddenRegions())
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册