diff --git a/src/EditorFeatures/CSharpTest/CodeActions/GenerateType/GenerateTypeTests_Dialog.cs b/src/EditorFeatures/CSharpTest/CodeActions/GenerateType/GenerateTypeTests_Dialog.cs index 2da0b9dcaf527..8a6acfa346e29 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/GenerateType/GenerateTypeTests_Dialog.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/GenerateType/GenerateTypeTests_Dialog.cs @@ -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 +{ +} + +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] diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractUserDiagnosticTest_GenerateTypeDialog.cs b/src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractUserDiagnosticTest_GenerateTypeDialog.cs index 712b5060e3b07..45605d118ff13 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractUserDiagnosticTest_GenerateTypeDialog.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractUserDiagnosticTest_GenerateTypeDialog.cs @@ -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) diff --git a/src/EditorFeatures/VisualBasicTest/CodeActions/GenerateType/GenerateTypeTests_Dialog.vb b/src/EditorFeatures/VisualBasicTest/CodeActions/GenerateType/GenerateTypeTests_Dialog.vb index 9d71a41dfd401..f7f5e9bd1e3c5 100644 --- a/src/EditorFeatures/VisualBasicTest/CodeActions/GenerateType/GenerateTypeTests_Dialog.vb +++ b/src/EditorFeatures/VisualBasicTest/CodeActions/GenerateType/GenerateTypeTests_Dialog.vb @@ -1626,6 +1626,37 @@ typeName:="Bar", isMissing:=True) End Function + + + Public Async Function GenerateType_GenericBaseList() As Task + Await TestWithMockedGenerateTypeDialog( +initial:= +Imports System.Collections.Generic + +Structure S + Implements IEnumerable(Of [|$$NewType|]) + +End Structure +.NormalizedValue, +languageName:=LanguageNames.VisualBasic, +typeName:="NewType", +expected:= +Imports System.Collections.Generic + +Structure S + Implements IEnumerable(Of NewType) + +End Structure + +Public Class NewType +End Class +.NormalizedValue, +isNewFile:=False, +accessibility:=Accessibility.Public, +typeKind:=TypeKind.Class, +assertGenerateTypeDialogOptions:=New GenerateTypeDialogOptions(False, TypeKindOptions.AllOptions, False)) + End Function + #End Region #Region "Delegates" diff --git a/src/Features/CSharp/Portable/GenerateType/CSharpGenerateTypeService.cs b/src/Features/CSharp/Portable/GenerateType/CSharpGenerateTypeService.cs index 129b0945c52bf..468e73304c84f 100644 --- a/src/Features/CSharp/Portable/GenerateType/CSharpGenerateTypeService.cs +++ b/src/Features/CSharp/Portable/GenerateType/CSharpGenerateTypeService.cs @@ -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; diff --git a/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.CodeAction.cs b/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.CodeAction.cs index 6c3ca86fd1c93..e7872f4dae9d6 100644 --- a/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.CodeAction.cs +++ b/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.CodeAction.cs @@ -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; diff --git a/src/Features/VisualBasic/Portable/GenerateType/VisualBasicGenerateTypeService.vb b/src/Features/VisualBasic/Portable/GenerateType/VisualBasicGenerateTypeService.vb index ec54305a08db7..f0bf267e39a6f 100644 --- a/src/Features/VisualBasic/Portable/GenerateType/VisualBasicGenerateTypeService.vb +++ b/src/Features/VisualBasic/Portable/GenerateType/VisualBasicGenerateTypeService.vb @@ -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