Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,9 @@ operation is not (IInvocationOperation or IObjectCreationOperation))
}

// Get the parent type declaration so that we can inspect its methods as well as check if we need to add the partial keyword.
// Skip extension blocks, as they can't be partial and can't contain generated regex members.
SyntaxNode? typeDeclarationOrCompilationUnit =
nodeToFix.Ancestors().OfType<TypeDeclarationSyntax>().FirstOrDefault() ??
nodeToFix.Ancestors().OfType<TypeDeclarationSyntax>().FirstOrDefault(t => t is not ExtensionBlockDeclarationSyntax) ??
await nodeToFix.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false);

// Calculate what name should be used for the generated static partial property.
Expand Down Expand Up @@ -210,7 +211,7 @@ where modifier.Kind() is SyntaxKind.PublicKeyword or SyntaxKind.PrivateKeyword o
SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)))));

var typeDeclarationOrCompilationUnit = nodeToFix.Ancestors().OfType<TypeDeclarationSyntax>().FirstOrDefault() ?? root;
var typeDeclarationOrCompilationUnit = nodeToFix.Ancestors().OfType<TypeDeclarationSyntax>().FirstOrDefault(t => t is not ExtensionBlockDeclarationSyntax) ?? root;

ImmutableArray<IArgumentOperation> operationArguments =
operation is IObjectCreationOperation objectCreation ?
Expand Down Expand Up @@ -255,7 +256,7 @@ operation is not (IInvocationOperation or IObjectCreationOperation))
SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)))));

var typeDeclarationOrCompilationUnit = nodeToFix.Ancestors().OfType<TypeDeclarationSyntax>().FirstOrDefault() ?? root;
var typeDeclarationOrCompilationUnit = nodeToFix.Ancestors().OfType<TypeDeclarationSyntax>().FirstOrDefault(t => t is not ExtensionBlockDeclarationSyntax) ?? root;

ImmutableArray<IArgumentOperation> operationArguments =
operation is IObjectCreationOperation objectCreation ?
Expand Down Expand Up @@ -342,7 +343,7 @@ private static Document TryAddNewMember(
var trackedRoot = root.TrackNodes(parent is null ? [nodeToFix] : [nodeToFix, parent]);

root = trackedRoot.ReplaceNodes(
trackedRoot.GetCurrentNode(nodeToFix)!.Ancestors().OfType<TypeDeclarationSyntax>(),
trackedRoot.GetCurrentNode(nodeToFix)!.Ancestors().OfType<TypeDeclarationSyntax>().Where(t => t is not ExtensionBlockDeclarationSyntax),
(_, typeDeclaration) =>
typeDeclaration.Modifiers.Any(m => m.IsKind(SyntaxKind.PartialKeyword)) ?
typeDeclaration :
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -969,6 +969,66 @@ public void Foo()
await VerifyCS.VerifyCodeFixAsync(test, fixedSource);
}

[Fact]
Comment thread
stephentoub marked this conversation as resolved.
public async Task CodeFixSupportsExtensionMembers_StaticInvocation()
{
string test = @"using System.Text.RegularExpressions;

static class Foo
{
extension(string value)
{
public bool Test() => [|Regex.IsMatch|](value, @""\d+"");
}
}
";
string fixedSource = @"using System.Text.RegularExpressions;

static partial class Foo
{
extension(string value)
{
public bool Test() => MyRegex.IsMatch(value);
}

[GeneratedRegex(@""\d+"")]
private static partial Regex MyRegex { get; }
}
";

await VerifyCS.VerifyCodeFixAsync(test, fixedSource);
}

[Fact]
public async Task CodeFixSupportsExtensionMembers_Constructor()
{
string test = @"using System.Text.RegularExpressions;

static class Foo
{
extension(string value)
{
public Regex GetRegex() => [|new Regex|](@""\d+"");
}
}
";
string fixedSource = @"using System.Text.RegularExpressions;

static partial class Foo
{
extension(string value)
{
public Regex GetRegex() => MyRegex;
}

[GeneratedRegex(@""\d+"")]
private static partial Regex MyRegex { get; }
}
";

await VerifyCS.VerifyCodeFixAsync(test, fixedSource);
}

[Theory]
[MemberData(nameof(InvocationTypes))]
public async Task NoDiagnosticForRegexOptionsNonBacktracking(InvocationType invocationType)
Expand Down
Loading