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 @@ -72,6 +72,7 @@ static bool IsVoid(TypeSyntax typeSyntax)
if (declarationTypeToFix is null)
return default;

var syntaxGenerator = document.GetRequiredLanguageService<SyntaxGenerator>();
var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);
var returnedType = semanticModel.GetTypeInfo(returnedValue, cancellationToken).Type;

Expand All @@ -85,7 +86,8 @@ static bool IsVoid(TypeSyntax typeSyntax)

returnedType ??= semanticModel.Compilation.ObjectType;

TypeSyntax fixedDeclaration;
var fixedDeclaration = returnedType.GenerateTypeSyntax(allowVar: false);

if (isAsync)
{
var previousReturnType = semanticModel.GetTypeInfo(declarationTypeToFix, cancellationToken).Type;
Expand All @@ -112,11 +114,8 @@ static bool IsVoid(TypeSyntax typeSyntax)
if (taskType is null)
return default;

fixedDeclaration = taskType.Construct(returnedType).GenerateTypeSyntax(allowVar: false);
}
else
{
fixedDeclaration = returnedType.GenerateTypeSyntax(allowVar: false);
var taskTypeSyntax = taskType.GenerateTypeSyntax(allowVar: false);
fixedDeclaration = (TypeSyntax)syntaxGenerator.WithTypeArguments(taskTypeSyntax, fixedDeclaration);
}

fixedDeclaration = fixedDeclaration.WithAdditionalAnnotations(Simplifier.Annotation).WithTriviaFrom(declarationTypeToFix);
Expand Down
54 changes: 54 additions & 0 deletions src/Analyzers/CSharp/Tests/FixReturnType/FixReturnTypeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -460,4 +460,58 @@ async C M()
""",
ReferenceAssemblies = ReferenceAssemblies.Net.Net60
}.RunAsync();

[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/79630")]
public Task TestAnonymousTypeElement1()
=> VerifyCS.VerifyCodeFixAsync("""
class C
{
public void Method()
{
var v = new { A = 0, B = 1 };
var a = new[] { v };
{|CS0127:return|} v;
}
}
""", """
class C
{
public object Method()
{
var v = new { A = 0, B = 1 };
var a = new[] { v };
return v;
}
}
""");

[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/79630")]
public Task TestAnonymousTypeElement2()
=> VerifyCS.VerifyCodeFixAsync("""
using System.Threading.Tasks;

class C
{
public async Task Method()
{
await Task.CompletedTask;
var v = new { A = 0, B = 1 };
var a = new[] { v };
{|CS1997:return|} v;
}
}
""", """
using System.Threading.Tasks;

class C
{
public async Task<object> Method()
{
await Task.CompletedTask;
var v = new { A = 0, B = 1 };
var a = new[] { v };
return v;
}
}
""");
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,19 @@ namespace Microsoft.CodeAnalysis.CSharp.Extensions;

internal partial class ITypeSymbolExtensions
{
private sealed class TypeSyntaxGeneratorVisitor : SymbolVisitor<TypeSyntax>
private sealed class TypeSyntaxGeneratorVisitor(bool nameOnly) : SymbolVisitor<TypeSyntax>
{
private readonly bool _nameOnly;

private static readonly TypeSyntaxGeneratorVisitor NameOnlyInstance = new(nameOnly: true);
private static readonly TypeSyntaxGeneratorVisitor NotNameOnlyInstance = new(nameOnly: false);

private TypeSyntaxGeneratorVisitor(bool nameOnly)
=> _nameOnly = nameOnly;
private static readonly QualifiedNameSyntax SystemObjectType =
QualifiedName(
AliasQualifiedName(
CreateGlobalIdentifier(),
IdentifierName("System")),
IdentifierName("Object"));

private readonly bool _nameOnly = nameOnly;

public static TypeSyntaxGeneratorVisitor Create(bool nameOnly = false)
=> nameOnly ? NameOnlyInstance : NotNameOnlyInstance;
Expand Down Expand Up @@ -186,16 +190,12 @@ public TypeSyntax CreateSimpleTypeSyntax(INamedTypeSymbol symbol)
}

if (symbol.Name == string.Empty || symbol.IsAnonymousType)
{
return CreateSystemObject();
}
return SystemObjectType;

if (symbol.TypeParameters.Length == 0)
{
if (symbol.TypeKind == TypeKind.Error && symbol.Name == "var")
{
return CreateSystemObject();
}
return SystemObjectType;

return symbol.Name.ToIdentifierName();
}
Expand All @@ -210,13 +210,7 @@ public TypeSyntax CreateSimpleTypeSyntax(INamedTypeSymbol symbol)
}

public static QualifiedNameSyntax CreateSystemObject()
{
return QualifiedName(
AliasQualifiedName(
CreateGlobalIdentifier(),
IdentifierName("System")),
IdentifierName("Object"));
}
=> SystemObjectType;

private static IdentifierNameSyntax CreateGlobalIdentifier()
=> IdentifierName(GlobalKeyword);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,14 @@ private static TypeSyntax GenerateTypeSyntax(
var type = symbol as ITypeSymbol;
var containsAnonymousType = type != null && type.ContainsAnonymousType();

// something with an anonymous type can only be represented with 'var', regardless
// of what the user's preferences might be.
if (containsAnonymousType && allowVar)
{
// something with an anonymous type can only be represented with 'var', regardless
// of what the user's preferences might be.
return IdentifierName("var");
}

var syntax = containsAnonymousType
? TypeSyntaxGeneratorVisitor.CreateSystemObject()
: symbol.Accept(TypeSyntaxGeneratorVisitor.Create(nameSyntax))!
.WithAdditionalAnnotations(Simplifier.Annotation);
: symbol.Accept(TypeSyntaxGeneratorVisitor.Create(nameSyntax))!.WithAdditionalAnnotations(Simplifier.Annotation);

if (!allowVar)
syntax = syntax.WithAdditionalAnnotations(DoNotAllowVarAnnotation.Annotation);
Expand Down
Loading