提交 f99769df 编写于 作者: C CyrusNajmabadi

Add VB support for implementing IEquatable.

上级 3caae3d0
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeRefactorings;
......@@ -16,6 +14,8 @@
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.GenerateEqualsAndGetHashCodeFromMembers
{
using static GenerateEqualsAndGetHashCodeFromMembersCodeRefactoringProvider;
public class GenerateEqualsAndGetHashCodeFromMembersTests : AbstractCSharpCodeActionTest
{
protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspace workspace, TestParameters parameters)
......@@ -1003,27 +1003,10 @@ public override bool Equals(object obj)
}
}",
chosenSymbols: null,
optionsCallback: options => EnableOptions(options, generateOperators: true),
optionsCallback: options => EnableOption(options, GenerateOperatorsId),
ignoreTrivia: false);
}
private void EnableOptions(
ImmutableArray<PickMembersOption> options,
bool generateOperators = false, bool implementIEquatable = false)
{
var option = options.FirstOrDefault(i => i.Id == GenerateEqualsAndGetHashCodeFromMembersCodeRefactoringProvider.GenerateOperatorsId);
if (option != null)
{
option.Value = generateOperators;
}
option = options.FirstOrDefault(i => i.Id == GenerateEqualsAndGetHashCodeFromMembersCodeRefactoringProvider.ImplementIEquatableId);
if (option != null)
{
option.Value = implementIEquatable;
}
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateEqualsAndGetHashCode)]
public async Task TestGenerateOperators2()
{
......@@ -1057,7 +1040,7 @@ public override bool Equals(object obj)
=> !(program1 == program2);
}",
chosenSymbols: null,
optionsCallback: options => EnableOptions(options, generateOperators: true),
optionsCallback: options => EnableOption(options, GenerateOperatorsId),
parameters: new TestParameters(
options: Option(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CodeStyleOptions.TrueWithNoneEnforcement)));
}
......@@ -1093,7 +1076,7 @@ public override bool Equals(object obj)
public static bool operator ==(Program program1, Program program2) => true;
}",
chosenSymbols: null,
optionsCallback: options => Assert.Null(options.FirstOrDefault(i => i.Id == GenerateEqualsAndGetHashCodeFromMembersCodeRefactoringProvider.GenerateOperatorsId)),
optionsCallback: options => Assert.Null(options.FirstOrDefault(i => i.Id == GenerateOperatorsId)),
ignoreTrivia: false);
}
......@@ -1138,12 +1121,12 @@ public override bool Equals(object obj)
}
}",
chosenSymbols: null,
optionsCallback: options => EnableOptions(options, generateOperators: true),
optionsCallback: options => EnableOption(options, GenerateOperatorsId),
ignoreTrivia: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateEqualsAndGetHashCode)]
public async Task TestImplementIEqutable1()
public async Task TestImplementIEquatable1()
{
await TestWithPickMembersDialogAsync(
@"
......@@ -1172,12 +1155,12 @@ public bool Equals(Program other)
}
}",
chosenSymbols: null,
optionsCallback: options => EnableOptions(options, implementIEquatable: true),
optionsCallback: options => EnableOption(options, ImplementIEquatableId),
ignoreTrivia: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateEqualsAndGetHashCode)]
public async Task TestImplementIEqutable2()
public async Task TestImplementIEquatable2()
{
await TestWithPickMembersDialogAsync(
@"
......@@ -1207,12 +1190,12 @@ public bool Equals(Program other)
}
}",
chosenSymbols: null,
optionsCallback: options => EnableOptions(options, implementIEquatable: true),
optionsCallback: options => EnableOption(options, ImplementIEquatableId),
ignoreTrivia: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateEqualsAndGetHashCode)]
public async Task TestImplementIEqutable3()
public async Task TestImplementIEquatable3()
{
await TestWithPickMembersDialogAsync(
@"
......@@ -1238,7 +1221,7 @@ public override bool Equals(object obj)
}
}",
chosenSymbols: null,
optionsCallback: options => Assert.Null(options.FirstOrDefault(i => i.Id == GenerateEqualsAndGetHashCodeFromMembersCodeRefactoringProvider.ImplementIEquatableId)),
optionsCallback: options => Assert.Null(options.FirstOrDefault(i => i.Id == ImplementIEquatableId)),
ignoreTrivia: false);
}
}
......
......@@ -141,6 +141,25 @@ private class TestPickMembersService : IPickMembersService
}
}
internal void EnableOptions(
ImmutableArray<PickMembersOption> options,
params string[] ids)
{
foreach (var id in ids)
{
EnableOption(options, id);
}
}
internal void EnableOption(ImmutableArray<PickMembersOption> options, string id)
{
var option = options.FirstOrDefault(o => o.Id == id);
if (option != null)
{
option.Value = true;
}
}
internal Task TestWithPickMembersDialogAsync(
string initialMarkup,
string expectedMarkup,
......
......@@ -9,6 +9,9 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.GenerateConstructo
Public Class GenerateEqualsAndGetHashCodeFromMembersTests
Inherits AbstractVisualBasicCodeActionTest
Private Const GenerateOperatorsId = GenerateEqualsAndGetHashCodeFromMembersCodeRefactoringProvider.GenerateOperatorsId
Private Const ImplementIEquatableId = GenerateEqualsAndGetHashCodeFromMembersCodeRefactoringProvider.ImplementIEquatableId
Protected Overrides Function CreateCodeRefactoringProvider(workspace As Workspace, parameters As TestParameters) As CodeRefactoringProvider
Return New GenerateEqualsAndGetHashCodeFromMembersCodeRefactoringProvider(
DirectCast(parameters.fixProviderData, IPickMembersService))
......@@ -127,7 +130,7 @@ Class Program
End Operator
End Class",
chosenSymbols:=Nothing,
optionsCallback:=Sub(options) options(0).Value = True)
optionsCallback:=Sub(options) EnableOption(options, GenerateOperatorsId))
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateEqualsAndGetHashCode)>
......@@ -161,7 +164,7 @@ Class Program
End Operator
End Class",
chosenSymbols:=Nothing,
optionsCallback:=Sub(Options) Assert.Empty(Options))
optionsCallback:=Sub(Options) Assert.Null(Options.FirstOrDefault(Function(o) o.Id = GenerateOperatorsId)))
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateEqualsAndGetHashCode)>
......@@ -198,7 +201,70 @@ Structure Program
End Operator
End Structure",
chosenSymbols:=Nothing,
optionsCallback:=Sub(options) options(0).Value = True,
optionsCallback:=Sub(options) EnableOption(options, GenerateOperatorsId),
ignoreTrivia:=False)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateEqualsAndGetHashCode)>
Public Async Function TestImplementIEquatable1() As Task
Await TestWithPickMembersDialogAsync(
"
imports System.Collections.Generic
structure Program
public s as string
[||]
end structure",
"
imports System.Collections.Generic
structure Program
Implements System.IEquatable(Of Program)
public s as string
Public Overrides Function Equals(obj As Object) As Boolean
Return (TypeOf obj Is Program) AndAlso Equals(DirectCast(obj, Program))
End Function
Public Function Equals(other As Program) As Boolean Implements System.IEquatable(Of Program).Equals
Return s = other.s
End Function
end structure",
chosenSymbols:=Nothing,
optionsCallback:=Sub(Options) EnableOption(Options, ImplementIEquatableId),
ignoreTrivia:=False)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateEqualsAndGetHashCode)>
Public Async Function TestImplementIEquatable2() As Task
Await TestWithPickMembersDialogAsync(
"
imports System.Collections.Generic
class Program
public s as string
[||]
end class",
"
imports System.Collections.Generic
class Program
Implements System.IEquatable(Of Program)
public s as string
Public Overrides Function Equals(obj As Object) As Boolean
Return Equals(TryCast(obj, Program))
End Function
Public Function Equals(other As Program) As Boolean Implements System.IEquatable(Of Program).Equals
Return other IsNot Nothing AndAlso
s = other.s
End Function
end class",
chosenSymbols:=Nothing,
optionsCallback:=Sub(Options) EnableOption(Options, ImplementIEquatableId),
ignoreTrivia:=False)
End Function
End Class
......
......@@ -22,6 +22,8 @@ internal class CSharpSyntaxGenerator : SyntaxGenerator
{
internal override SyntaxTrivia CarriageReturnLineFeed => SyntaxFactory.CarriageReturnLineFeed;
internal override bool RequiresExplicitImplementationForInterfaceMembers => false;
internal override SyntaxTrivia EndOfLine(string text)
=> SyntaxFactory.EndOfLine(text);
......
......@@ -31,6 +31,7 @@ public abstract class SyntaxGenerator : ILanguageService
public static SyntaxRemoveOptions DefaultRemoveOptions = SyntaxRemoveOptions.KeepUnbalancedDirectives | SyntaxRemoveOptions.AddElasticMarker;
internal abstract SyntaxTrivia CarriageReturnLineFeed { get; }
internal abstract bool RequiresExplicitImplementationForInterfaceMembers { get; }
internal abstract SyntaxTrivia EndOfLine(string text);
......
......@@ -62,17 +62,27 @@ public static IMethodSymbol CreateEqualsMethod(this Compilation compilation, Imm
factory, compilation, containingType, symbols, cancellationToken);
statements = statements.SelectAsArray(s => s.WithAdditionalAnnotations(statementAnnotation));
return CodeGenerationSymbolFactory.CreateMethodSymbol(
attributes: default(ImmutableArray<AttributeData>),
accessibility: Accessibility.Public,
modifiers: new DeclarationModifiers(),
returnType: compilation.GetSpecialType(SpecialType.System_Boolean),
returnsByRef: false,
explicitInterfaceSymbol: null,
name: EqualsName,
typeParameters: default(ImmutableArray<ITypeParameterSymbol>),
parameters: ImmutableArray.Create(CodeGenerationSymbolFactory.CreateParameterSymbol(containingType, OtherName)),
statements: statements);
var equatableType = compilation.GetTypeByMetadataName(typeof(IEquatable<>).FullName);
var constructed = equatableType.Construct(containingType);
var methodSymbol = constructed.GetMembers(EqualsName)
.OfType<IMethodSymbol>()
.Single(m => containingType.Equals(m.Parameters.FirstOrDefault()?.Type));
if (factory.RequiresExplicitImplementationForInterfaceMembers)
{
return CodeGenerationSymbolFactory.CreateMethodSymbol(
methodSymbol,
modifiers: new DeclarationModifiers(),
explicitInterfaceSymbol: methodSymbol,
statements: statements);
}
else
{
return CodeGenerationSymbolFactory.CreateMethodSymbol(
methodSymbol,
modifiers: new DeclarationModifiers(),
statements: statements);
}
}
private static ImmutableArray<SyntaxNode> CreateEqualsMethodStatements(
......
......@@ -15,11 +15,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
Public Shared ReadOnly Instance As SyntaxGenerator = New VisualBasicSyntaxGenerator()
Friend Overrides ReadOnly Property CarriageReturnLineFeed As SyntaxTrivia
Get
Return SyntaxFactory.CarriageReturnLineFeed
End Get
End Property
Friend Overrides ReadOnly Property CarriageReturnLineFeed As SyntaxTrivia = SyntaxFactory.CarriageReturnLineFeed
Friend Overrides ReadOnly Property RequiresExplicitImplementationForInterfaceMembers As Boolean = True
Friend Overrides Function EndOfLine(text As String) As SyntaxTrivia
Return SyntaxFactory.EndOfLine(text)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册