Skip to content

Commit

Permalink
Merge pull request icsharpcode#1069 from icsharpcode/issue/1062
Browse files Browse the repository at this point in the history
Issue/1062
  • Loading branch information
GrahamTheCoder authored Dec 21, 2023
2 parents ee8e18f + 970410d commit 3284c3d
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 103 deletions.
1 change: 0 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
* Constant chars are converted to constant strings where needed
* Select case for a mixture of strings and characters converts correctly [#1062](https://github.com/icsharpcode/CodeConverter/issues/1062)


### C# -> VB


Expand Down
43 changes: 3 additions & 40 deletions CodeConverter/CSharp/DeclarationNodeVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -818,7 +818,7 @@ private void AddRemainingInterfaceDeclarations(MethodDeclarationSyntax method, S
GetMethodId(interfaceImplement.Name) :
SetMethodId(interfaceImplement.Name));
var interfaceMethodDeclParams = new MethodDeclarationParameters(attributes, filteredModifiers,
method.ReturnType, method.TypeParameterList, MakeOptionalParametersRequired(method.ParameterList), method.ConstraintClauses, clause, identifier);
method.ReturnType, method.TypeParameterList, method.ParameterList, method.ConstraintClauses, clause, identifier);

AddInterfaceMemberDeclarations(interfaceImplement, additionalDeclarations, interfaceMethodDeclParams);
});
Expand Down Expand Up @@ -1173,12 +1173,10 @@ public override async Task<CSharpSyntaxNode> VisitMethodStatement(VBSyntax.Metho
directlyConvertedCsIdentifier = hasExplicitInterfaceImplementation ? directlyConvertedCsIdentifier : CommonConversions.ConvertIdentifier(node.Identifier);

if (hasExplicitInterfaceImplementation) {

var requiredParameterList = MakeOptionalParametersRequired(parameterList);
var delegatingClause = GetDelegatingClause(directlyConvertedCsIdentifier, requiredParameterList, false);
var delegatingClause = GetDelegatingClause(directlyConvertedCsIdentifier, parameterList, false);
var explicitInterfaceModifiers = convertedModifiers.RemoveWhere(m => m.IsCsMemberVisibility() || m.IsKind(CSSyntaxKind.VirtualKeyword, CSSyntaxKind.AbstractKeyword) || m.IsKind(CSSyntaxKind.OverrideKeyword, CSSyntaxKind.NewKeyword));

var interfaceDeclParams = new MethodDeclarationParameters(attributes, explicitInterfaceModifiers, returnType, typeParameters, requiredParameterList, constraints, delegatingClause);
var interfaceDeclParams = new MethodDeclarationParameters(attributes, explicitInterfaceModifiers, returnType, typeParameters, parameterList, constraints, delegatingClause);
AddInterfaceMemberDeclarations(declaredSymbol.ExplicitInterfaceImplementations, additionalDeclarations, interfaceDeclParams);
}

Expand Down Expand Up @@ -1273,41 +1271,6 @@ private void AddMemberDeclaration(ICollection<MemberDeclarationSyntax> additiona
additionalDeclarations.Add(declaration);
}


private static ParameterListSyntax MakeOptionalParametersRequired(ParameterListSyntax parameterList)
{
if (parameterList == null) return null;

var nonOptionalParameters = parameterList.Parameters.Select(ConvertOptionalParameter);

var separatedSyntaxList = SyntaxFactory.SeparatedList(nonOptionalParameters);
var newParameterList = parameterList.WithParameters(separatedSyntaxList);
return newParameterList;
}

private static ParameterSyntax ConvertOptionalParameter(ParameterSyntax parameter)
{
var optionalAttributes = new List<string> { nameof(OptionalAttribute).GetAttributeIdentifier(),
nameof(DefaultParameterValueAttribute).GetAttributeIdentifier() };

var attrListsToRemove = parameter.AttributeLists.SingleOrDefault(aList => aList.Attributes
.All(a =>
{
string attrIdentifier = string.Empty;

if (a.Name is IdentifierNameSyntax identifierNameSyntax) {
attrIdentifier = identifierNameSyntax.Identifier.Text;
} else if (a.Name is AliasQualifiedNameSyntax aliasQualifiedNameSyntax) {
attrIdentifier = aliasQualifiedNameSyntax.Alias.Identifier.Text;
}

return optionalAttributes.Contains(attrIdentifier);
}));

var newAttrLists = parameter.AttributeLists.Remove(attrListsToRemove);
return parameter.WithDefault(null).WithAttributeLists(newAttrLists);
}

private static ArrowExpressionClauseSyntax GetDelegatingClause(SyntaxToken csIdentifier,
ParameterListSyntax parameterList, bool isSetAccessor)
{
Expand Down
2 changes: 1 addition & 1 deletion CodeConverter/CSharp/OperationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public static bool IsAssignableExpression(this IOperation operation)
case OperationKind.DynamicMemberReference:
return true;

//Just documenting since it's the only one mentioning reference that can't be assigned to AFAIK
//Just documenting since it's the only one mentioning reference that can't necessarily be assigned to AFAIK
case OperationKind.PropertyReference:
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion Tests/CSharp/ExpressionTests/ByRefTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ private int ExplicitFunc([Optional, DefaultParameterValue("""")] ref string str)
return 5;
}
int IFoo.ExplicitFunc(ref string str) => ExplicitFunc(ref str);
int IFoo.ExplicitFunc([Optional, DefaultParameterValue("""")] ref string str) => ExplicitFunc(ref str);
}");
}

Expand Down
255 changes: 199 additions & 56 deletions Tests/CSharp/MemberTests/MemberTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2211,6 +2211,205 @@ public partial class FooBar : IFoo, IBar
}");
}

[Fact]
public async Task ExplicitInterfaceImplementationRequiredMethodParameters_749_Async()
{
await TestConversionVisualBasicToCSharpAsync(
@"
Public Interface IFoo
Function DoFooBar(ByRef str As String, i As Integer) As Integer
End Interface
Public Interface IBar
Function DoFooBar(ByRef str As String, i As Integer) As Integer
End Interface
Public Class FooBar
Implements IFoo, IBar
Function Foo(ByRef str As String, i As Integer) As Integer Implements IFoo.DoFooBar
Return 4
End Function
Function Bar(ByRef str As String, i As Integer) As Integer Implements IBar.DoFooBar
Return 2
End Function
End Class", @"
public partial interface IFoo
{
int DoFooBar(ref string str, int i);
}
public partial interface IBar
{
int DoFooBar(ref string str, int i);
}
public partial class FooBar : IFoo, IBar
{
public int Foo(ref string str, int i)
{
return 4;
}
int IFoo.DoFooBar(ref string str, int i) => Foo(ref str, i);
public int Bar(ref string str, int i)
{
return 2;
}
int IBar.DoFooBar(ref string str, int i) => Bar(ref str, i);
}
");
}

[Fact]
public async Task ExplicitInterfaceImplementationOptionalParameters_1062_Async()
{
await TestConversionVisualBasicToCSharpAsync(
@"
Public Interface InterfaceWithOptionalParameters
Sub S(Optional i As Integer = 0)
End Interface
Public Class ImplInterfaceWithOptionalParameters : Implements InterfaceWithOptionalParameters
Public Sub InterfaceWithOptionalParameters_S(Optional i As Integer = 0) Implements InterfaceWithOptionalParameters.S
End Sub
End Class", @"
public partial interface InterfaceWithOptionalParameters
{
void S(int i = 0);
}
public partial class ImplInterfaceWithOptionalParameters : InterfaceWithOptionalParameters
{
public void InterfaceWithOptionalParameters_S(int i = 0)
{
}
void InterfaceWithOptionalParameters.S(int i = 0) => InterfaceWithOptionalParameters_S(i);
}
");
}


[Fact]
public async Task ExplicitInterfaceImplementationOptionalParametersAsync()
{
await TestConversionVisualBasicToCSharpAsync(
@"Public Interface IFoo
Property ExplicitProp(Optional str As String = """") As Integer
Function ExplicitFunc(Optional str2 As String = """", Optional i2 As Integer = 1) As Integer
End Interface
Public Class Foo
Implements IFoo
Private Function ExplicitFunc(Optional str As String = """", Optional i2 As Integer = 1) As Integer Implements IFoo.ExplicitFunc
Return 5
End Function
Private Property ExplicitProp(Optional str As String = """") As Integer Implements IFoo.ExplicitProp
Get
Return 5
End Get
Set(value As Integer)
End Set
End Property
End Class", @"
public partial interface IFoo
{
int get_ExplicitProp(string str = """");
void set_ExplicitProp(string str = """", int value = default);
int ExplicitFunc(string str2 = """", int i2 = 1);
}
public partial class Foo : IFoo
{
private int ExplicitFunc(string str = """", int i2 = 1)
{
return 5;
}
int IFoo.ExplicitFunc(string str = """", int i2 = 1) => ExplicitFunc(str, i2);
private int get_ExplicitProp(string str = """")
{
return 5;
}
private void set_ExplicitProp(string str = """", int value = default)
{
}
int IFoo.get_ExplicitProp(string str = """") => get_ExplicitProp(str);
void IFoo.set_ExplicitProp(string str = """", int value = default) => set_ExplicitProp(str, value);
}
");
}


[Fact]
public async Task ExplicitInterfaceImplementationOptionalMethodParameters_749_Async()
{
await TestConversionVisualBasicToCSharpAsync(
@"
Public Interface IFoo
Function DoFooBar(ByRef str As String, Optional i As Integer = 4) As Integer
End Interface
Public Interface IBar
Function DoFooBar(ByRef str As String, Optional i As Integer = 8) As Integer
End Interface
Public Class FooBar
Implements IFoo, IBar
Function Foo(ByRef str As String, Optional i As Integer = 4) As Integer Implements IFoo.DoFooBar
Return 4
End Function
Function Bar(ByRef str As String, Optional i As Integer = 8) As Integer Implements IBar.DoFooBar
Return 2
End Function
End Class", @"
public partial interface IFoo
{
int DoFooBar(ref string str, int i = 4);
}
public partial interface IBar
{
int DoFooBar(ref string str, int i = 8);
}
public partial class FooBar : IFoo, IBar
{
public int Foo(ref string str, int i = 4)
{
return 4;
}
int IFoo.DoFooBar(ref string str, int i = 4) => Foo(ref str, i);
public int Bar(ref string str, int i = 8)
{
return 2;
}
int IBar.DoFooBar(ref string str, int i = 8) => Bar(ref str, i);
}
");
}

[Fact]
public async Task RenamedInterfaceMethodFullyQualifiedAsync()
{
Expand Down Expand Up @@ -3506,62 +3705,6 @@ private void set_ExplicitProp(string str, int value)
}");
}

[Fact]
public async Task ExplicitInterfaceImplementationOptionalParametersAsync()
{
await TestConversionVisualBasicToCSharpAsync(
@"Public Interface IFoo
Property ExplicitProp(Optional str As String = """") As Integer
Function ExplicitFunc(Optional str2 As String = """", Optional i2 As Integer = 1) As Integer
End Interface
Public Class Foo
Implements IFoo
Private Function ExplicitFunc(Optional str As String = """", Optional i2 As Integer = 1) As Integer Implements IFoo.ExplicitFunc
Return 5
End Function
Private Property ExplicitProp(Optional str As String = """") As Integer Implements IFoo.ExplicitProp
Get
Return 5
End Get
Set(value As Integer)
End Set
End Property
End Class", @"
public partial interface IFoo
{
int get_ExplicitProp(string str = """");
void set_ExplicitProp(string str = """", int value = default);
int ExplicitFunc(string str2 = """", int i2 = 1);
}
public partial class Foo : IFoo
{
private int ExplicitFunc(string str = """", int i2 = 1)
{
return 5;
}
int IFoo.ExplicitFunc(string str, int i2) => ExplicitFunc(str, i2);
private int get_ExplicitProp(string str = """")
{
return 5;
}
private void set_ExplicitProp(string str = """", int value = default)
{
}
int IFoo.get_ExplicitProp(string str) => get_ExplicitProp(str);
void IFoo.set_ExplicitProp(string str, int value) => set_ExplicitProp(str, value);
}
");
}

/// <summary>
///
/// </summary>
Expand Down
8 changes: 4 additions & 4 deletions Tests/CSharp/MemberTests/PropertyMemberTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -525,8 +525,8 @@ internal void set_Prop2(int x = 1, int y = 2, int value = default)
{
}
int IFoo.get_Prop(int x, int y) => get_Prop2(x, y);
void IFoo.set_Prop(int x, int y, int value) => set_Prop2(x, y, value);
int IFoo.get_Prop(int x = 1, int y = 2) => get_Prop2(x, y);
void IFoo.set_Prop(int x = 1, int y = 2, int value = default) => set_Prop2(x, y, value);
public void TestGet()
{
Expand Down Expand Up @@ -615,8 +615,8 @@ internal void set_Prop2(int x = 1, int y = 2, int z = 3, int value = default)
{
}
int IFoo.get_Prop(int x, int y, int z) => get_Prop2(x, y, z);
void IFoo.set_Prop(int x, int y, int z, int value) => set_Prop2(x, y, z, value);
int IFoo.get_Prop(int x = 1, int y = 2, int z = 3) => get_Prop2(x, y, z);
void IFoo.set_Prop(int x = 1, int y = 2, int z = 3, int value = default) => set_Prop2(x, y, z, value);
public void TestGet()
{
Expand Down

0 comments on commit 3284c3d

Please sign in to comment.