Skip to content

Commit 5c8966e

Browse files
committed
Fix: walk VB syntax tree in VbNameExprToCsExpr instead of ToString().Split('.')
Handle IdentifierNameSyntax, MemberAccessExpressionSyntax, and QualifiedNameSyntax (which appears for Global.X references in default value context). Also remove unnecessary Simplifier.Annotation since simplification is applied automatically in a second phase. https://claude.ai/code/session_01AkwUvu3XuCdj3D4axoX4UX
1 parent 8572669 commit 5c8966e

File tree

1 file changed

+26
-9
lines changed

1 file changed

+26
-9
lines changed

CodeConverter/CSharp/DeclarationNodeVisitor.cs

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using Microsoft.CodeAnalysis.CSharp;
55
using Microsoft.CodeAnalysis.CSharp.Syntax;
66
using Microsoft.CodeAnalysis.Editing;
7-
using Microsoft.CodeAnalysis.Simplification;
87
using static Microsoft.CodeAnalysis.VisualBasic.VisualBasicExtensions;
98
using ICSharpCode.CodeConverter.Util.FromRoslyn;
109
using ISymbolExtensions = ICSharpCode.CodeConverter.Util.ISymbolExtensions;
@@ -733,16 +732,34 @@ private static ExpressionSyntax BuildCharExpressionFromVbSyntax(VBSyntax.Express
733732
// For char literal expressions (e.g. "^"c), use the constant value directly
734733
if (defaultValueNode.IsKind(VBasic.SyntaxKind.CharacterLiteralExpression)) {
735734
var constant = semanticModel.GetConstantValue(defaultValueNode);
736-
if (constant.HasValue && constant.Value is char c) {
735+
if (constant.HasValue && constant.Value is char c)
737736
return CS.SyntaxFactory.LiteralExpression(CS.SyntaxKind.CharacterLiteralExpression, CS.SyntaxFactory.Literal(c));
738-
}
739737
}
740-
// For named constant references (e.g. DlM or Module.DlM), build a member access expression.
741-
// Strip VB's "Global." prefix (VB global namespace qualifier, has no C# identifier equivalent).
742-
// Annotate for simplification so Roslyn reduces e.g. TestModule.DlM → DlM within TestModule.
743-
var parts = defaultValueNode.ToString().Trim().Split('.');
744-
if (parts.Length > 1 && parts[0] == "Global") parts = parts.Skip(1).ToArray();
745-
return ValidSyntaxFactory.MemberAccess(parts).WithAdditionalAnnotations(Simplifier.Annotation);
738+
return VbNameExprToCsExpr(defaultValueNode);
739+
}
740+
741+
private static ExpressionSyntax VbNameExprToCsExpr(VBSyntax.ExpressionSyntax vbExpr)
742+
{
743+
switch (vbExpr) {
744+
case VBSyntax.IdentifierNameSyntax identifier:
745+
return CS.SyntaxFactory.IdentifierName(identifier.Identifier.Text);
746+
case VBSyntax.MemberAccessExpressionSyntax memberAccess:
747+
// Skip VB's "Global." qualifier — it's VB's global namespace prefix, has no direct C# identifier equivalent
748+
if (memberAccess.Expression.IsKind(VBasic.SyntaxKind.GlobalName))
749+
return CS.SyntaxFactory.IdentifierName(memberAccess.Name.Identifier.Text);
750+
return CS.SyntaxFactory.MemberAccessExpression(CS.SyntaxKind.SimpleMemberAccessExpression,
751+
VbNameExprToCsExpr(memberAccess.Expression),
752+
CS.SyntaxFactory.IdentifierName(memberAccess.Name.Identifier.Text));
753+
case VBSyntax.QualifiedNameSyntax qualifiedName:
754+
// Qualified names (e.g. Global.TestModule) appear in name/type context within default values
755+
if (qualifiedName.Left.IsKind(VBasic.SyntaxKind.GlobalName))
756+
return CS.SyntaxFactory.IdentifierName(qualifiedName.Right.Identifier.Text);
757+
return CS.SyntaxFactory.MemberAccessExpression(CS.SyntaxKind.SimpleMemberAccessExpression,
758+
VbNameExprToCsExpr(qualifiedName.Left),
759+
CS.SyntaxFactory.IdentifierName(qualifiedName.Right.Identifier.Text));
760+
default:
761+
throw new NotSupportedException($"Unexpected VB expression in char default value: {vbExpr}");
762+
}
746763
}
747764

748765
private static bool IsThisResumeLayoutInvocation(StatementSyntax s)

0 commit comments

Comments
 (0)