dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/
MIT License
18.9k stars 4.01k forks source link

CSharpSyntaxGenerator doesn't appear to simplify when generating an attribute on a local function #52039

Open agocke opened 3 years ago

agocke commented 3 years ago

I wrote the following code to add attributes to particular declarations

var editor = new SyntaxEditor (root, document.Project.Solution.Workspace);
var generator = editor.Generator;

var semanticModel = await document.GetSemanticModelAsync (cancellationToken).ConfigureAwait (false);
if (semanticModel is null) {
    return document;
}
var methodSymbol = (IMethodSymbol) semanticModel.GetDeclaredSymbol (methodDecl);
var name = semanticModel.GetSymbolInfo (targetNode).Symbol?.Name;
SyntaxNode[] attrArgs;
if (string.IsNullOrEmpty (name) || HasPublicAccessibility (methodSymbol)) {
    attrArgs = Array.Empty<SyntaxNode> ();
} else {
    attrArgs = new[] { generator.LiteralExpression ($"calls {name}") };
}

var newAttribute = generator
    .Attribute (generator.TypeExpression (requiresUnreferencedCodeSymbol), attrArgs)
    .WithAdditionalAnnotations (
        Simplifier.Annotation,
        Simplifier.AddImportsAnnotation);

editor.AddAttribute (methodDecl, newAttribute);

return document.WithSyntaxRoot (editor.GetChangedRoot ());

This generates an attribute correctly for local functions, but the type name is always fully qualified. Declaration forms that are not local functions appear to work correctly.

Youssef1313 commented 3 years ago

Similar (identical?) thing is done here:

https://github.com/dotnet/roslyn/blob/6da1274c9d24c2f90a48290394a951b23617f2a3/src/Features/Core/Portable/AddDebuggerDisplay/AbstractAddDebuggerDisplayCodeRefactoringProvider.cs#L150-L156

But it works as shown by the following test:

https://github.com/dotnet/roslyn/blob/6da1274c9d24c2f90a48290394a951b23617f2a3/src/EditorFeatures/CSharpTest/AddDebuggerDisplay/AddDebuggerDisplayTests.cs#L18-L34

I guess a repro may help.

agocke commented 3 years ago

You should be able to repro by passing a local function syntax as the target. I expect the DebuggerDisplay code would have the same problem, but you can't add debugger display on local functions regardless.

Youssef1313 commented 3 years ago

Oh so this is very specific to local functions? Will try to give it a look.

Youssef1313 commented 3 years ago

ImportAdder does add the using statement, but it's removed after ReduceAsync is called. Trying to dig more into this.

image

Youssef1313 commented 3 years ago

When using a normal method:

image


When using a local function:

image

The boundParent in the second case should have been BoundAttribute like in the first case.

(Issue should be assigned Area-Compilers instead)