Skip to content

Commit 39fbf44

Browse files
Make extracted classes not be visitors
1 parent 5e6a975 commit 39fbf44

5 files changed

Lines changed: 98 additions & 89 deletions

File tree

CodeConverter/CSharp/ArgumentConverter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public ArgumentConverter(VisualBasicEqualityComparison visualBasicEqualityCompar
1919
TriviaConvertingExpressionVisitor = commonConversions.TriviaConvertingExpressionVisitor;
2020
}
2121

22-
public async Task<CSharpSyntaxNode> ConvertSimpleArgument(VBSyntax.SimpleArgumentSyntax node)
22+
public async Task<CSharpSyntaxNode> ConvertSimpleArgumentAsync(VBSyntax.SimpleArgumentSyntax node)
2323
{
2424
var argList = (VBasic.Syntax.ArgumentListSyntax)node.Parent;
2525
var invocation = argList.Parent;
@@ -264,7 +264,7 @@ bool TryGetDefaultParameterValueAttributeValue(IParameterSymbol p, out object de
264264
}
265265
}
266266

267-
private CSSyntax.ArgumentListSyntax CreateArgList(ISymbol invocationSymbol)
267+
public CSSyntax.ArgumentListSyntax CreateArgList(ISymbol invocationSymbol)
268268
{
269269
return CS.SyntaxFactory.ArgumentList(CS.SyntaxFactory.SeparatedList(
270270
GetAdditionalRequiredArgs(Array.Empty<VBSyntax.ArgumentSyntax>(), invocationSymbol))

CodeConverter/CSharp/ExpressionNodeVisitor.cs

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ internal partial class ExpressionNodeVisitor : VBasic.VisualBasicSyntaxVisitor<T
3636
private readonly VisualBasicNullableExpressionsConverter _visualBasicNullableTypesConverter;
3737
private readonly Dictionary<string, Stack<(SyntaxNode Scope, string TempName)>> _tempNameForAnonymousScope = new();
3838
private readonly HashSet<string> _generatedNames = new(StringComparer.OrdinalIgnoreCase);
39-
private readonly XmlExpressionNodeVisitor _xmlExpressionNodeVisitor;
39+
private readonly XmlExpressionConverter _xmlExpressionConverter;
4040
private readonly NameExpressionNodeVisitor _nameExpressionNodeVisitor;
4141
private readonly ArgumentConverter _argumentConverter;
4242

@@ -53,8 +53,8 @@ public ExpressionNodeVisitor(SemanticModel semanticModel,
5353
_typeContext = typeContext;
5454
_extraUsingDirectives = extraUsingDirectives;
5555
_argumentConverter = new ArgumentConverter(visualBasicEqualityComparison, typeContext, semanticModel, commonConversions);
56-
_xmlExpressionNodeVisitor = new XmlExpressionNodeVisitor(xmlImportContext, extraUsingDirectives, TriviaConvertingExpressionVisitor);
57-
_nameExpressionNodeVisitor = new NameExpressionNodeVisitor(semanticModel, _generatedNames, typeContext, extraUsingDirectives, _tempNameForAnonymousScope, _withBlockLhs, commonConversions, TriviaConvertingExpressionVisitor);
56+
_xmlExpressionConverter = new XmlExpressionConverter(xmlImportContext, extraUsingDirectives, TriviaConvertingExpressionVisitor);
57+
_nameExpressionNodeVisitor = new NameExpressionNodeVisitor(semanticModel, _generatedNames, typeContext, extraUsingDirectives, _tempNameForAnonymousScope, _withBlockLhs, commonConversions, _argumentConverter, TriviaConvertingExpressionVisitor);
5858
_visualBasicNullableTypesConverter = visualBasicNullableTypesConverter;
5959
_operatorConverter = VbOperatorConversion.Create(TriviaConvertingExpressionVisitor, semanticModel, visualBasicEqualityComparison, commonConversions.TypeConversionAnalyzer);
6060
// If this isn't needed, the assembly with Conversions may not be referenced, so this must be done lazily
@@ -90,27 +90,40 @@ private static IReadOnlyDictionary<ITypeSymbol, string> CreateConvertMethodsLook
9090

9191
public CommonConversions CommonConversions { get; }
9292

93-
public SemanticModel SemanticModel
94-
{
95-
get { return _semanticModel; }
96-
}
97-
98-
public ArgumentConverter ArgumentConverter
99-
{
100-
get { return _argumentConverter; }
101-
}
102-
10393
public override async Task<CSharpSyntaxNode> DefaultVisit(SyntaxNode node)
10494
{
105-
return await _xmlExpressionNodeVisitor.Visit(node);
106-
}
95+
throw new NotImplementedException(
96+
$"Conversion for {VBasic.VisualBasicExtensions.Kind(node)} not implemented, please report this issue")
97+
.WithNodeInformation(node);
98+
}
99+
100+
101+
public override Task<CSharpSyntaxNode> VisitMemberAccessExpression(VBSyntax.MemberAccessExpressionSyntax node) => _nameExpressionNodeVisitor.ConvertMemberAccessExpressionAsync(node);
102+
public override Task<CSharpSyntaxNode> VisitGlobalName(VBSyntax.GlobalNameSyntax node) => _nameExpressionNodeVisitor.ConvertGlobalNameAsync(node);
103+
public override Task<CSharpSyntaxNode> VisitMeExpression(VBSyntax.MeExpressionSyntax node) => _nameExpressionNodeVisitor.ConvertMeExpressionAsync(node);
104+
public override Task<CSharpSyntaxNode> VisitMyBaseExpression(VBSyntax.MyBaseExpressionSyntax node) => _nameExpressionNodeVisitor.ConvertMyBaseExpressionAsync(node);
105+
public override Task<CSharpSyntaxNode> VisitGenericName(VBSyntax.GenericNameSyntax node) => _nameExpressionNodeVisitor.ConvertGenericNameAsync(node);
106+
public override Task<CSharpSyntaxNode> VisitQualifiedName(VBSyntax.QualifiedNameSyntax node) => _nameExpressionNodeVisitor.ConvertQualifiedNameAsync(node);
107+
public override Task<CSharpSyntaxNode> VisitIdentifierName(VBSyntax.IdentifierNameSyntax node) => _nameExpressionNodeVisitor.ConvertIdentifierNameAsync(node);
108+
public override Task<CSharpSyntaxNode> VisitInvocationExpression(VBSyntax.InvocationExpressionSyntax node) => _nameExpressionNodeVisitor.ConvertInvocationExpressionAsync(node);
109+
public override Task<CSharpSyntaxNode> VisitXmlEmbeddedExpression(VBSyntax.XmlEmbeddedExpressionSyntax node) => _xmlExpressionConverter.ConvertXmlEmbeddedExpressionAsync(node);
110+
public override Task<CSharpSyntaxNode> VisitXmlDocument(VBasic.Syntax.XmlDocumentSyntax node) => _xmlExpressionConverter.ConvertXmlDocumentAsync(node);
111+
public override Task<CSharpSyntaxNode> VisitXmlElement(VBasic.Syntax.XmlElementSyntax node) => _xmlExpressionConverter.ConvertXmlElementAsync(node);
112+
public override Task<CSharpSyntaxNode> VisitXmlEmptyElement(VBSyntax.XmlEmptyElementSyntax node) => _xmlExpressionConverter.ConvertXmlEmptyElementAsync(node);
113+
public override Task<CSharpSyntaxNode> VisitXmlAttribute(VBSyntax.XmlAttributeSyntax node) => _xmlExpressionConverter.ConvertXmlAttributeAsync(node);
114+
public override Task<CSharpSyntaxNode> VisitXmlString(VBSyntax.XmlStringSyntax node) => _xmlExpressionConverter.ConvertXmlStringAsync(node);
115+
public override Task<CSharpSyntaxNode> VisitXmlText(VBSyntax.XmlTextSyntax node) => _xmlExpressionConverter.ConvertXmlTextAsync(node);
116+
public override Task<CSharpSyntaxNode> VisitXmlCDataSection(VBSyntax.XmlCDataSectionSyntax node) => _xmlExpressionConverter.ConvertXmlCDataSectionAsync(node);
117+
public override Task<CSharpSyntaxNode> VisitXmlMemberAccessExpression(VBSyntax.XmlMemberAccessExpressionSyntax node) => _xmlExpressionConverter.ConvertXmlMemberAccessExpressionAsync(node);
118+
public override Task<CSharpSyntaxNode> VisitXmlBracketedName(VBSyntax.XmlBracketedNameSyntax node) => _xmlExpressionConverter.ConvertXmlBracketedNameAsync(node);
119+
public override Task<CSharpSyntaxNode> VisitXmlName(VBSyntax.XmlNameSyntax node) => _xmlExpressionConverter.ConvertXmlNameAsync(node);
120+
public override async Task<CSharpSyntaxNode> VisitSimpleArgument(VBasic.Syntax.SimpleArgumentSyntax node) => await _argumentConverter.ConvertSimpleArgumentAsync(node);
107121

108122
public override async Task<CSharpSyntaxNode> VisitGetTypeExpression(VBasic.Syntax.GetTypeExpressionSyntax node)
109123
{
110124
return SyntaxFactory.TypeOfExpression(await node.Type.AcceptAsync<TypeSyntax>(TriviaConvertingExpressionVisitor));
111125
}
112126

113-
114127
public override async Task<CSharpSyntaxNode> VisitAwaitExpression(VBasic.Syntax.AwaitExpressionSyntax node)
115128
{
116129
return SyntaxFactory.AwaitExpression(await node.Expression.AcceptAsync<ExpressionSyntax>(TriviaConvertingExpressionVisitor));
@@ -235,17 +248,12 @@ public override async Task<CSharpSyntaxNode> VisitConditionalAccessExpression(VB
235248
public override async Task<CSharpSyntaxNode> VisitArgumentList(VBasic.Syntax.ArgumentListSyntax node)
236249
{
237250
if (node.Parent.IsKind(VBasic.SyntaxKind.Attribute)) {
238-
return CommonConversions.CreateAttributeArgumentList(await node.Arguments.SelectAsync(ArgumentConverter.ToAttributeArgumentAsync));
251+
return CommonConversions.CreateAttributeArgumentList(await node.Arguments.SelectAsync(_argumentConverter.ToAttributeArgumentAsync));
239252
}
240-
var argumentSyntaxes = await ArgumentConverter.ConvertArgumentsAsync(node);
253+
var argumentSyntaxes = await _argumentConverter.ConvertArgumentsAsync(node);
241254
return SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(argumentSyntaxes));
242255
}
243256

244-
public override async Task<CSharpSyntaxNode> VisitSimpleArgument(VBasic.Syntax.SimpleArgumentSyntax node)
245-
{
246-
return await ArgumentConverter.ConvertSimpleArgument(node);
247-
}
248-
249257
public override async Task<CSharpSyntaxNode> VisitNameOfExpression(VBasic.Syntax.NameOfExpressionSyntax node)
250258
{
251259
return SyntaxFactory.InvocationExpression(ValidSyntaxFactory.NameOf(), SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(await node.Argument.AcceptAsync<ExpressionSyntax>(TriviaConvertingExpressionVisitor)))));
@@ -283,7 +291,7 @@ public override async Task<CSharpSyntaxNode> VisitObjectCreationExpression(VBasi
283291
var objectCreationExpressionSyntax = SyntaxFactory.ObjectCreationExpression(
284292
await node.Type.AcceptAsync<TypeSyntax>(TriviaConvertingExpressionVisitor),
285293
// VB can omit empty arg lists:
286-
await ArgumentConverter.ConvertArgumentListOrEmptyAsync(node, node.ArgumentList),
294+
await _argumentConverter.ConvertArgumentListOrEmptyAsync(node, node.ArgumentList),
287295
null
288296
);
289297
async Task<InitializerExpressionSyntax> ConvertInitializer() => await node.Initializer.AcceptAsync<InitializerExpressionSyntax>(TriviaConvertingExpressionVisitor);

CodeConverter/CSharp/MethodBodyExecutableStatementVisitor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ public override async Task<SyntaxList<StatementSyntax>> VisitAssignmentStatement
210210
var lhs = await node.Left.AcceptAsync<ExpressionSyntax>(_expressionVisitor);
211211
var lOperation = _semanticModel.GetOperation(node.Left);
212212

213-
//Already dealt with by call to the same method in VisitInvocationExpression
213+
//Already dealt with by call to the same method in ConvertInvocationExpression
214214
var (parameterizedPropertyAccessMethod, _) = await CommonConversions.GetParameterizedPropertyAccessMethodAsync(lOperation);
215215
if (parameterizedPropertyAccessMethod != null) return SingleStatement(lhs);
216216
var rhs = await node.Right.AcceptAsync<ExpressionSyntax>(_expressionVisitor);

CodeConverter/CSharp/NameExpressionNodeVisitor.cs

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,24 @@
99
using static ICSharpCode.CodeConverter.CSharp.SemanticModelExtensions;
1010

1111
namespace ICSharpCode.CodeConverter.CSharp;
12-
internal class NameExpressionNodeVisitor : VBasic.VisualBasicSyntaxVisitor<Task<CSharpSyntaxNode>>
12+
13+
14+
internal class NameExpressionNodeVisitor
1315
{
1416
private readonly SemanticModel _semanticModel;
1517
private readonly HashSet<string> _generatedNames;
1618
private readonly ITypeContext _typeContext;
1719
private readonly HashSet<string> _extraUsingDirectives;
1820
private readonly Dictionary<string, Stack<(SyntaxNode Scope, string TempName)>> _tempNameForAnonymousScope;
1921
private readonly Stack<ExpressionSyntax> _withBlockLhs;
22+
private readonly ArgumentConverter _argumentConverter;
2023

2124
public CommonConversions CommonConversions { get; }
2225
public CommentConvertingVisitorWrapper TriviaConvertingExpressionVisitor { get; }
2326

2427
public NameExpressionNodeVisitor(SemanticModel semanticModel, HashSet<string> generatedNames, ITypeContext typeContext, HashSet<string> extraUsingDirectives,
2528
Dictionary<string, Stack<(SyntaxNode Scope, string TempName)>> tempNameForAnonymousScope, Stack<ExpressionSyntax> withBlockLhs, CommonConversions commonConversions,
29+
ArgumentConverter argumentConverter,
2630
CommentConvertingVisitorWrapper triviaConvertingExpressionVisitor)
2731
{
2832
_semanticModel = semanticModel;
@@ -31,11 +35,12 @@ public NameExpressionNodeVisitor(SemanticModel semanticModel, HashSet<string> ge
3135
_extraUsingDirectives = extraUsingDirectives;
3236
_tempNameForAnonymousScope = tempNameForAnonymousScope;
3337
_withBlockLhs = withBlockLhs;
38+
_argumentConverter = argumentConverter;
3439
CommonConversions = commonConversions;
3540
TriviaConvertingExpressionVisitor = triviaConvertingExpressionVisitor;
3641
}
3742

38-
public override async Task<CSharpSyntaxNode> VisitMemberAccessExpression(VBasic.Syntax.MemberAccessExpressionSyntax node)
43+
public async Task<CSharpSyntaxNode> ConvertMemberAccessExpressionAsync(VBasic.Syntax.MemberAccessExpressionSyntax node)
3944
{
4045
var nodeSymbol = _semanticModel.GetSymbolInfoInDocument<ISymbol>(node.Name);
4146

@@ -106,28 +111,28 @@ public override async Task<CSharpSyntaxNode> VisitMemberAccessExpression(VBasic.
106111
return await AdjustForImplicitInvocationAsync(node, memberAccessExpressionSyntax);
107112
}
108113

109-
public override async Task<CSharpSyntaxNode> VisitGlobalName(VBasic.Syntax.GlobalNameSyntax node)
114+
public async Task<CSharpSyntaxNode> ConvertGlobalNameAsync(VBasic.Syntax.GlobalNameSyntax node)
110115
{
111116
return ValidSyntaxFactory.IdentifierName(SyntaxFactory.Token(SyntaxKind.GlobalKeyword));
112117
}
113118

114-
public override async Task<CSharpSyntaxNode> VisitMeExpression(VBasic.Syntax.MeExpressionSyntax node)
119+
public async Task<CSharpSyntaxNode> ConvertMeExpressionAsync(VBasic.Syntax.MeExpressionSyntax node)
115120
{
116121
return SyntaxFactory.ThisExpression();
117122
}
118123

119-
public override async Task<CSharpSyntaxNode> VisitMyBaseExpression(VBasic.Syntax.MyBaseExpressionSyntax node)
124+
public async Task<CSharpSyntaxNode> ConvertMyBaseExpressionAsync(VBasic.Syntax.MyBaseExpressionSyntax node)
120125
{
121126
return SyntaxFactory.BaseExpression();
122127
}
123128

124-
public override async Task<CSharpSyntaxNode> VisitGenericName(VBasic.Syntax.GenericNameSyntax node)
129+
public async Task<CSharpSyntaxNode> ConvertGenericNameAsync(VBasic.Syntax.GenericNameSyntax node)
125130
{
126131
var symbol = _semanticModel.GetSymbolInfoInDocument<ISymbol>(node);
127132
var genericNameSyntax = await GenericNameAccountingForReducedParametersAsync(node, symbol);
128133
return await AdjustForImplicitInvocationAsync(node, genericNameSyntax);
129134
}
130-
public override async Task<CSharpSyntaxNode> VisitQualifiedName(VBasic.Syntax.QualifiedNameSyntax node)
135+
public async Task<CSharpSyntaxNode> ConvertQualifiedNameAsync(VBasic.Syntax.QualifiedNameSyntax node)
131136
{
132137
var symbol = _semanticModel.GetSymbolInfoInDocument<ITypeSymbol>(node);
133138
if (symbol != null) {
@@ -155,7 +160,7 @@ public override async Task<CSharpSyntaxNode> VisitQualifiedName(VBasic.Syntax.Qu
155160
}
156161

157162
/// <remarks>PERF: This is a hot code path, try to avoid using things like GetOperation except where needed.</remarks>
158-
public override async Task<CSharpSyntaxNode> VisitIdentifierName(VBasic.Syntax.IdentifierNameSyntax node)
163+
public async Task<CSharpSyntaxNode> ConvertIdentifierNameAsync(VBasic.Syntax.IdentifierNameSyntax node)
159164
{
160165
var identifier = SyntaxFactory.IdentifierName(CommonConversions.ConvertIdentifier(node.Identifier, node.GetAncestor<VBasic.Syntax.AttributeSyntax>() != null));
161166

@@ -189,7 +194,7 @@ public override async Task<CSharpSyntaxNode> VisitIdentifierName(VBasic.Syntax.I
189194

190195

191196

192-
public override async Task<CSharpSyntaxNode> VisitInvocationExpression(
197+
public async Task<CSharpSyntaxNode> ConvertInvocationExpressionAsync(
193198
VBasic.Syntax.InvocationExpressionSyntax node)
194199
{
195200
var invocationSymbol = _semanticModel.GetSymbolInfo(node).ExtractBestMatch<ISymbol>();
@@ -201,7 +206,7 @@ public override async Task<CSharpSyntaxNode> VisitInvocationExpression(
201206
try {
202207

203208
if (node.Expression is null) {
204-
var convertArgumentListOrEmptyAsync = await ConvertArgumentsAsync(node.ArgumentList);
209+
var convertArgumentListOrEmptyAsync = await _argumentConverter.ConvertArgumentsAsync(node.ArgumentList);
205210
return SyntaxFactory.ElementBindingExpression(SyntaxFactory.BracketedArgumentList(SyntaxFactory.SeparatedList(convertArgumentListOrEmptyAsync)));
206211
}
207212

@@ -273,7 +278,7 @@ private async Task<ExpressionSyntax> ConvertInvocationAsync(VBSyntax.InvocationE
273278
return convertedExpression; //Parameterless property access
274279
}
275280

276-
var convertedArgumentList = await ConvertArgumentListOrEmptyAsync(node, node.ArgumentList);
281+
var convertedArgumentList = await _argumentConverter.ConvertArgumentListOrEmptyAsync(node, node.ArgumentList);
277282

278283
if (IsElementAtOrDefaultInvocation(invocationSymbol, expressionSymbol)) {
279284
convertedExpression = GetElementAtOrDefaultExpression(expressionType, convertedExpression);
@@ -315,7 +320,7 @@ private async Task<ExpressionSyntax> CreateElementAccessAsync(VBSyntax.Invocatio
315320
var bracketedArgumentListSyntax = SyntaxFactory.BracketedArgumentList(args);
316321
if (expression is ElementBindingExpressionSyntax binding &&
317322
!binding.ArgumentList.Arguments.Any()) {
318-
// Special case where structure changes due to conditional access (See VisitMemberAccessExpression)
323+
// Special case where structure changes due to conditional access (See ConvertMemberAccessExpression)
319324
return binding.WithArgumentList(bracketedArgumentListSyntax);
320325
}
321326

@@ -360,7 +365,7 @@ private async Task<InvocationExpressionSyntax> TryConvertParameterizedPropertyAs
360365
var idToken = expr.DescendantTokens().Last(t => t.IsKind(SyntaxKind.IdentifierToken));
361366
expr = ReplaceRightmostIdentifierText(expr, idToken, overrideIdentifier);
362367

363-
var args = await ConvertArgumentListOrEmptyAsync(node, optionalArgumentList);
368+
var args = await _argumentConverter.ConvertArgumentListOrEmptyAsync(node, optionalArgumentList);
364369
if (extraArg != null) {
365370
var extraArgSyntax = SyntaxFactory.Argument(extraArg);
366371
var propertySymbol = ((IPropertyReferenceOperation)operation).Property;
@@ -620,8 +625,8 @@ private CSharpSyntaxNode AddEmptyArgumentListIfImplicit(SyntaxNode node, Express
620625
{
621626
if (_semanticModel.SyntaxTree != node.SyntaxTree) return id;
622627
return _semanticModel.GetOperation(node) switch {
623-
IInvocationOperation invocation => SyntaxFactory.InvocationExpression(id, CreateArgList(invocation.TargetMethod)),
624-
IPropertyReferenceOperation propReference when propReference.Property.Parameters.Any() => SyntaxFactory.InvocationExpression(id, CreateArgList(propReference.Property)),
628+
IInvocationOperation invocation => SyntaxFactory.InvocationExpression(id, _argumentConverter.CreateArgList(invocation.TargetMethod)),
629+
IPropertyReferenceOperation propReference when propReference.Property.Parameters.Any() => SyntaxFactory.InvocationExpression(id, _argumentConverter.CreateArgList(propReference.Property)),
625630
_ => id
626631
};
627632
}
@@ -645,7 +650,7 @@ private async Task<CSharpSyntaxNode> SubstituteVisualBasicMethodOrNullAsync(VBSy
645650
}
646651

647652
if (SimpleMethodReplacement.TryGet(symbol, out var methodReplacement) &&
648-
methodReplacement.ReplaceIfMatches(symbol, await ConvertArgumentsAsync(node.ArgumentList), false) is { } csExpression) {
653+
methodReplacement.ReplaceIfMatches(symbol, await _argumentConverter.ConvertArgumentsAsync(node.ArgumentList), false) is { } csExpression) {
649654
cSharpSyntaxNode = csExpression;
650655
}
651656

0 commit comments

Comments
 (0)