Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 35 additions & 25 deletions rewrite-csharp/csharp/OpenRewrite/CSharp/CSharpParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1180,27 +1180,27 @@ public override J VisitAttributeList(AttributeListSyntax node)
if (arg.NameEquals != null)
{
// Named argument with equals: b = c
var namePrefix = ExtractSpaceBefore(arg.NameEquals.Name.Identifier);
var argPrefix = ExtractSpaceBefore(arg.NameEquals.Name.Identifier);
_cursor = arg.NameEquals.Name.Identifier.Span.End;
var nameIdentifier = new Identifier(Guid.NewGuid(), namePrefix, Markers.Empty, [],
var nameIdentifier = new Identifier(Guid.NewGuid(), Space.Empty, Markers.Empty, [],
arg.NameEquals.Name.Identifier.Text, null, null);
var eqSpace = ExtractSpaceBefore(arg.NameEquals.EqualsToken);
_cursor = arg.NameEquals.EqualsToken.Span.End;
var valueExpr = (Expression)Visit(arg.Expression)!;
expr = new Assignment(Guid.NewGuid(), Space.Empty, Markers.Empty,
expr = new Assignment(Guid.NewGuid(), argPrefix, Markers.Empty,
nameIdentifier, new JLeftPadded<Expression>(eqSpace, valueExpr), null);
}
else if (arg.NameColon != null)
{
// Named argument with colon: error: true
var namePrefix = ExtractSpaceBefore(arg.NameColon.Name.Identifier);
var argPrefix = ExtractSpaceBefore(arg.NameColon.Name.Identifier);
_cursor = arg.NameColon.Name.Identifier.Span.End;
var nameIdentifier = new Identifier(Guid.NewGuid(), namePrefix, Markers.Empty, [],
var nameIdentifier = new Identifier(Guid.NewGuid(), Space.Empty, Markers.Empty, [],
arg.NameColon.Name.Identifier.Text, null, null);
var colonSpace = ExtractSpaceBefore(arg.NameColon.ColonToken);
_cursor = arg.NameColon.ColonToken.Span.End;
var valueExpr = (Expression)Visit(arg.Expression)!;
expr = new NamedExpression(Guid.NewGuid(), Space.Empty, Markers.Empty,
expr = new NamedExpression(Guid.NewGuid(), argPrefix, Markers.Empty,
new JRightPadded<Identifier>(nameIdentifier, colonSpace, Markers.Empty), valueExpr);
}
else
Expand Down Expand Up @@ -1274,7 +1274,10 @@ public override J VisitMethodDeclaration(MethodDeclarationSyntax node)
modifiers.Add(CreateModifier(modPrefix, mod));
}

// Parse return type
// Parse return type, hoisting its prefix to MethodDeclaration when attributes exist with no modifiers
Space hoistedReturnTypePrefix = Space.Empty;
if (attributeLists.Count > 0 && modifiers.Count == 0)
hoistedReturnTypePrefix = ExtractPrefix(node.ReturnType);
var returnType = VisitType(node.ReturnType);

// Parse explicit interface specifier if present (e.g., IFoo.Bar)
Expand Down Expand Up @@ -1400,7 +1403,9 @@ [new JRightPadded<Statement>(returnStmt, Space.Empty, Markers.Empty)],
if (node.ExpressionBody != null)
methodMarkers = methodMarkers.Add(new ExpressionBodied(Guid.NewGuid()));

var methodDeclPrefix = (attributeLists.Count > 0 || explicitInterfaceSpec != null) ? Space.Empty : prefix;
var methodDeclPrefix = attributeLists.Count > 0
? hoistedReturnTypePrefix
: explicitInterfaceSpec != null ? Space.Empty : prefix;
var methodDecl = new MethodDeclaration(
Guid.NewGuid(),
methodDeclPrefix,
Expand Down Expand Up @@ -2312,7 +2317,10 @@ private Statement ConvertParameter(ParameterSyntax node)
modifiers.Add(CreateModifier(modPrefix, mod));
}

// Parse the type
// Parse the type, hoisting its prefix to VariableDeclarations when attributes exist with no modifiers
Space hoistedTypePrefix = Space.Empty;
if (attributeLists.Count > 0 && modifiers.Count == 0 && node.Type != null)
hoistedTypePrefix = ExtractPrefix(node.Type);
TypeTree? typeExpr = null;
if (node.Type != null)
{
Expand Down Expand Up @@ -2359,7 +2367,7 @@ private Statement ConvertParameter(ParameterSyntax node)

var varDecl = new VariableDeclarations(
Guid.NewGuid(),
attributeLists.Count > 0 ? Space.Empty : prefix,
attributeLists.Count > 0 ? hoistedTypePrefix : prefix,
Markers.Empty,
[],
modifiers,
Expand Down Expand Up @@ -2820,6 +2828,9 @@ public override J VisitIsPatternExpression(IsPatternExpressionSyntax node)
/// </summary>
public override J VisitDeclarationPattern(DeclarationPatternSyntax node)
{
// Extract the prefix before the type and hoist it to the outer StatementExpression
var declPrefix = ExtractPrefix(node);

// Parse the type (e.g., int, string, MyClass)
var typeExpr = VisitType(node.Type);

Expand Down Expand Up @@ -2862,7 +2873,7 @@ public override J VisitDeclarationPattern(DeclarationPatternSyntax node)
// Wrap in StatementExpression so it implements Pattern
return new StatementExpression(
Guid.NewGuid(),
Space.Empty, // Prefix is handled by the case label itself
declPrefix,
Markers.Empty,
varDecl
);
Expand Down Expand Up @@ -2988,6 +2999,8 @@ public override J VisitPredefinedType(PredefinedTypeSyntax node)

public override J VisitBinaryPattern(BinaryPatternSyntax node)
{
var binaryPrefix = ExtractPrefix(node);

// Parse the left pattern, wrapping non-Expression results in StatementExpression
var leftJ = Visit(node.Left)!;
Expression left = leftJ is Expression leftExpr
Expand All @@ -3012,7 +3025,7 @@ public override J VisitBinaryPattern(BinaryPatternSyntax node)

return new CsBinary(
Guid.NewGuid(),
Space.Empty,
binaryPrefix,
Markers.Empty,
left,
new JLeftPadded<CsBinary.OperatorType>(operatorPrefix, operatorType),
Expand Down Expand Up @@ -5139,12 +5152,12 @@ public override J VisitTupleExpression(TupleExpressionSyntax node)
if (arg.NameColon != null)
{
// Named tuple element: name: value
var namePrefix = ExtractSpaceBefore(arg.NameColon.Name.Identifier);
var argPrefix = ExtractSpaceBefore(arg.NameColon.Name.Identifier);
_cursor = arg.NameColon.Name.Identifier.Span.End;

var nameIdentifier = new Identifier(
Guid.NewGuid(),
namePrefix,
Space.Empty,
Markers.Empty,
[],
arg.NameColon.Name.Identifier.Text,
Expand All @@ -5165,7 +5178,7 @@ public override J VisitTupleExpression(TupleExpressionSyntax node)

expr = new NamedExpression(
Guid.NewGuid(),
Space.Empty,
argPrefix,
Markers.Empty,
new JRightPadded<Identifier>(nameIdentifier, colonSpace, Markers.Empty),
value
Expand Down Expand Up @@ -7130,12 +7143,12 @@ private JContainer<Expression> ParseArgumentList(ArgumentListSyntax argList)
if (arg.NameColon != null)
{
// Named argument: name: value
var namePrefix = ExtractSpaceBefore(arg.NameColon.Name.Identifier);
var argPrefix = ExtractSpaceBefore(arg.NameColon.Name.Identifier);
_cursor = arg.NameColon.Name.Identifier.Span.End;

var nameIdentifier = new Identifier(
Guid.NewGuid(),
namePrefix,
Space.Empty,
Markers.Empty,
[],
arg.NameColon.Name.Identifier.Text,
Expand All @@ -7156,7 +7169,7 @@ private JContainer<Expression> ParseArgumentList(ArgumentListSyntax argList)

expr = new NamedExpression(
Guid.NewGuid(),
Space.Empty,
argPrefix,
Markers.Empty,
new JRightPadded<Identifier>(nameIdentifier, colonSpace, Markers.Empty),
value
Expand Down Expand Up @@ -8627,37 +8640,34 @@ private TypeTree VisitQualifiedName(QualifiedNameSyntax qualified, Space prefix)
Expression left;
if (qualified.Left is QualifiedNameSyntax leftQualified)
{
left = (Expression)VisitQualifiedName(leftQualified, prefix);
prefix = Space.Empty; // prefix was used by leftmost part
left = (Expression)VisitQualifiedName(leftQualified, Space.Empty);
}
else if (qualified.Left is IdentifierNameSyntax leftIdent)
{
_cursor = leftIdent.Identifier.Span.End;
left = new Identifier(
Guid.NewGuid(),
prefix,
Space.Empty,
Markers.Empty,
[],
leftIdent.Identifier.Text,
null,
null
);
prefix = Space.Empty;
}
else
{
// Fallback for other left types
_cursor = qualified.Left.Span.End;
left = new Identifier(
Guid.NewGuid(),
prefix,
Space.Empty,
Markers.Empty,
[],
qualified.Left.ToString(),
null,
null
);
prefix = Space.Empty;
}

// Get space before the dot
Expand All @@ -8683,7 +8693,7 @@ private TypeTree VisitQualifiedName(QualifiedNameSyntax qualified, Space prefix)

return new FieldAccess(
Guid.NewGuid(),
Space.Empty, // prefix was applied to leftmost
prefix,
Markers.Empty,
left,
new JLeftPadded<Identifier>(dotSpace, right),
Expand Down
4 changes: 2 additions & 2 deletions rewrite-csharp/csharp/OpenRewrite/CSharp/CSharpPrinter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3096,7 +3096,7 @@ public override J VisitLineDirective(LineDirective lineDirective, PrintOutputCap
/// <summary>
/// Called at the start of each visit method. Handles prefix space and markers.
/// </summary>
protected void BeforeSyntax(J j, PrintOutputCapture<P> p)
protected virtual void BeforeSyntax(J j, PrintOutputCapture<P> p)
{
BeforeSyntax(j.Prefix, j.Markers, p);
}
Expand Down Expand Up @@ -3124,7 +3124,7 @@ protected void BeforeSyntax(Space prefix, Markers markers, PrintOutputCapture<P>
/// <summary>
/// Called at the end of each visit method. Handles markers after syntax.
/// </summary>
protected void AfterSyntax(J j, PrintOutputCapture<P> p)
protected virtual void AfterSyntax(J j, PrintOutputCapture<P> p)
{
AfterSyntax(j.Markers, p);
}
Expand Down
4 changes: 2 additions & 2 deletions rewrite-csharp/csharp/OpenRewrite/Core/PrintOutputCapture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public PrintOutputCapture(T context, IMarkerPrinter markerPrinter)
MarkerPrinter = markerPrinter;
}

public PrintOutputCapture<T> Append(string? text)
public virtual PrintOutputCapture<T> Append(string? text)
{
if (text != null)
{
Expand All @@ -47,7 +47,7 @@ public PrintOutputCapture<T> Append(string? text)
return this;
}

public PrintOutputCapture<T> Append(char c)
public virtual PrintOutputCapture<T> Append(char c)
{
_output.Append(c);
return this;
Expand Down
Loading