Skip to content

Commit

Permalink
Merge pull request #63378 from Youssef1313/issues/63280
Browse files Browse the repository at this point in the history
Fix generate type dialog invoked on type argument in a base list
  • Loading branch information
CyrusNajmabadi authored Oct 30, 2024
2 parents 308cda3 + 5743730 commit a26b144
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2271,6 +2271,104 @@ public struct Bar
isNewFile: false,
assertGenerateTypeDialogOptions: new GenerateTypeDialogOptions(false, TypeKindOptions.Class | TypeKindOptions.Structure, false));
}

[Fact, WorkItem(63280, "https://github.com/dotnet/roslyn/issues/63280")]
public async Task GenerateType_GenericBaseList()
{
await TestWithMockedGenerateTypeDialog(
initial: @"
using System.Collections.Generic;
struct C : IEnumerable<[|$$NewType|]>
{
}",
languageName: LanguageNames.CSharp,
typeName: "NewType",
expected: @"
using System.Collections.Generic;
struct C : IEnumerable<NewType>
{
}
public class NewType
{
}",
accessibility: Accessibility.Public,
typeKind: TypeKind.Class,
isNewFile: false,
assertGenerateTypeDialogOptions: new GenerateTypeDialogOptions(false, TypeKindOptions.AllOptions, false));
}

[Fact]
public async Task GenerateType_QualifiedBaseList()
{
await TestWithMockedGenerateTypeDialog(
initial: @"
using System.Collections.Generic;
struct C : A.B.[|$$INewType|]
{
}
namespace A.B
{
}",
languageName: LanguageNames.CSharp,
typeName: "INewType",
expected: @"
using System.Collections.Generic;
struct C : A.B.INewType
{
}
namespace A.B
{
public interface INewType
{
}
}",
accessibility: Accessibility.Public,
typeKind: TypeKind.Interface,
isNewFile: false,
assertGenerateTypeDialogOptions: new GenerateTypeDialogOptions(false, TypeKindOptions.Interface, false));
}

[Fact]
public async Task GenerateType_AliasQualifiedBaseList()
{
await TestWithMockedGenerateTypeDialog(
initial: @"
using System.Collections.Generic;
struct C : global::A.B.[|$$INewType|]
{
}
namespace A.B
{
}",
languageName: LanguageNames.CSharp,
typeName: "INewType",
expected: @"
using System.Collections.Generic;
struct C : global::A.B.INewType
{
}
namespace A.B
{
public interface INewType
{
}
}",
accessibility: Accessibility.Public,
typeKind: TypeKind.Interface,
isNewFile: false,
assertGenerateTypeDialogOptions: new GenerateTypeDialogOptions(false, TypeKindOptions.Interface, false));
}
#endregion
#region Delegates
[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,9 @@ await TestOperationsAsync(testState.Workspace, expectedTextWithUsings, operation

if (assertGenerateTypeDialogOptions != null)
{
Assert.True(assertGenerateTypeDialogOptions.IsPublicOnlyAccessibility == generateTypeDialogOptions.IsPublicOnlyAccessibility);
Assert.True(assertGenerateTypeDialogOptions.TypeKindOptions == generateTypeDialogOptions.TypeKindOptions);
Assert.True(assertGenerateTypeDialogOptions.IsAttribute == generateTypeDialogOptions.IsAttribute);
Assert.Equal(assertGenerateTypeDialogOptions.IsPublicOnlyAccessibility, generateTypeDialogOptions.IsPublicOnlyAccessibility);
Assert.Equal(assertGenerateTypeDialogOptions.TypeKindOptions, generateTypeDialogOptions.TypeKindOptions);
Assert.Equal(assertGenerateTypeDialogOptions.IsAttribute, generateTypeDialogOptions.IsAttribute);
}

if (assertTypeKindPresent != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1626,6 +1626,37 @@ typeName:="Bar",
isMissing:=True)
End Function

<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateType)>
<WorkItem(63280, "https://github.com/dotnet/roslyn/issues/63280")>
Public Async Function GenerateType_GenericBaseList() As Task
Await TestWithMockedGenerateTypeDialog(
initial:=<Text>
Imports System.Collections.Generic

Structure S
Implements IEnumerable(Of [|$$NewType|])

End Structure
</Text>.NormalizedValue,
languageName:=LanguageNames.VisualBasic,
typeName:="NewType",
expected:=<Text>
Imports System.Collections.Generic

Structure S
Implements IEnumerable(Of NewType)

End Structure

Public Class NewType
End Class
</Text>.NormalizedValue,
isNewFile:=False,
accessibility:=Accessibility.Public,
typeKind:=TypeKind.Class,
assertGenerateTypeDialogOptions:=New GenerateTypeDialogOptions(False, TypeKindOptions.AllOptions, False))
End Function

#End Region
#Region "Delegates"
<Fact>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -664,23 +664,16 @@ internal override bool TryGetBaseList(ExpressionSyntax expression, out TypeKindO
return false;
}

var node = expression as SyntaxNode;

while (node != null)
if (expression.Parent is BaseTypeSyntax { Parent: BaseListSyntax baseList })
{
if (node is BaseListSyntax)
if (baseList.Parent.Kind() is SyntaxKind.InterfaceDeclaration or SyntaxKind.StructDeclaration or SyntaxKind.RecordStructDeclaration)
{
if (node.Parent.Kind() is SyntaxKind.InterfaceDeclaration or SyntaxKind.StructDeclaration or SyntaxKind.RecordStructDeclaration)
{
typeKindValue = TypeKindOptions.Interface;
return true;
}

typeKindValue = TypeKindOptions.BaseList;
typeKindValue = TypeKindOptions.Interface;
return true;
}

node = node.Parent;
typeKindValue = TypeKindOptions.BaseList;
return true;
}

return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,7 @@ private bool GetPredefinedTypeKindOption(State state, out TypeKindOptions typeKi
return true;
}

if (_service.TryGetBaseList(state.NameOrMemberAccessExpression, out var typeKindValue) ||
_service.TryGetBaseList(state.SimpleName, out typeKindValue))
if (_service.TryGetBaseList(state.NameOrMemberAccessExpression, out var typeKindValue))
{
typeKindValueFinal = typeKindValue;
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -539,23 +539,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.GenerateType
Return False
End If

Dim node As SyntaxNode = expression
While node IsNot Nothing
If TypeOf node Is InheritsStatementSyntax Then
If node.Parent IsNot Nothing AndAlso TypeOf node.Parent Is InterfaceBlockSyntax Then
typeKindValue = TypeKindOptions.Interface
Return True
End If

typeKindValue = TypeKindOptions.Class
Return True
ElseIf TypeOf node Is ImplementsStatementSyntax Then
If TypeOf expression.Parent Is InheritsStatementSyntax Then
If expression.Parent.Parent IsNot Nothing AndAlso TypeOf expression.Parent.Parent Is InterfaceBlockSyntax Then
typeKindValue = TypeKindOptions.Interface
Return True
End If

node = node.Parent
End While
typeKindValue = TypeKindOptions.Class
Return True
ElseIf TypeOf expression.Parent Is ImplementsStatementSyntax Then
typeKindValue = TypeKindOptions.Interface
Return True
End If

Return False
End Function
Expand Down

0 comments on commit a26b144

Please sign in to comment.