Skip to content

Commit 1ee64dd

Browse files
committed
Added support for a new "ToObject" attribute.
1 parent e56501a commit 1ee64dd

File tree

1 file changed

+166
-62
lines changed

1 file changed

+166
-62
lines changed

CSharpToJavaScript/Walker.cs

Lines changed: 166 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,6 @@ namespace CSharpToJavaScript;
1717
//https://roslynquoter.azurewebsites.net/
1818
//https://sourceroslyn.io/
1919
//https://sharplab.io/
20-
//
21-
//Annotations are interesting, but because everything is immutable...
22-
//I don't think it is faster than the current approach.
23-
//https://joshvarty.com/2015/09/18/learn-roslyn-now-part-13-keeping-track-of-syntax-nodes-with-syntax-annotations/
24-
//
25-
//NOTE for me: Read about DocumentEditor!
26-
//https://joshvarty.wordpress.com/2015/08/18/learn-roslyn-now-part-12-the-documenteditor/
27-
//Should I do it in two phases??? First one, change c# code. The second one translate as-is to js...
28-
//Also see roslyn source!
29-
//https://github.com/dotnet/roslyn
30-
//"this" is IDE0009
31-
//https://learn.microsoft.com/ru-ru/dotnet/fundamentals/code-analysis/style-rules/ide0003-ide0009
32-
//https://github.com/dotnet/roslyn/blob/main/src/VisualStudio/Core/Def/CodeCleanup/CommonCodeCleanUpFixerDiagnosticIds.cs#L20
33-
//https://github.com/dotnet/roslyn/blob/main/src/Analyzers/Core/Analyzers/QualifyMemberAccess/AbstractQualifyMemberAccessDiagnosticAnalyzer.cs
34-
//Read and think about it!
35-
//
36-
//also f#??? vb??? test)
3720

3821
internal class Walker : CSharpSyntaxWalker
3922
{
@@ -58,7 +41,7 @@ internal class Walker : CSharpSyntaxWalker
5841
private bool _IgnoreTailingDot = false;
5942
private bool _GlobalStatement = false;
6043
private bool _ThisIsUsed = false;
61-
44+
private bool _IsArrayInitializer = false;
6245
private int _EnumMembers = 0;
6346

6447
private string[] _AttributeDatasForInvocation = new string[2];
@@ -2320,8 +2303,12 @@ public override void VisitArrayCreationExpression(ArrayCreationExpressionSyntax
23202303
break;
23212304
}
23222305
case SyntaxKind.ArrayInitializerExpression:
2323-
VisitInitializerExpression((InitializerExpressionSyntax)asNode);
2324-
break;
2306+
{
2307+
_IsArrayInitializer = true;
2308+
VisitInitializerExpression((InitializerExpressionSyntax)asNode);
2309+
_IsArrayInitializer = false;
2310+
break;
2311+
}
23252312
default:
23262313
Log.ErrorLine($"asNode : {kind}\n|{asNode.ToFullString()}|");
23272314
break;
@@ -2528,6 +2515,32 @@ public override void VisitInitializerExpression(InitializerExpressionSyntax node
25282515
case SyntaxKind.ObjectCreationExpression:
25292516
VisitObjectCreationExpression((ObjectCreationExpressionSyntax)asNode);
25302517
break;
2518+
case SyntaxKind.SimpleAssignmentExpression:
2519+
case SyntaxKind.AddAssignmentExpression:
2520+
case SyntaxKind.SubtractAssignmentExpression:
2521+
case SyntaxKind.MultiplyAssignmentExpression:
2522+
case SyntaxKind.DivideAssignmentExpression:
2523+
case SyntaxKind.ModuloAssignmentExpression:
2524+
case SyntaxKind.AndAssignmentExpression:
2525+
case SyntaxKind.ExclusiveOrAssignmentExpression:
2526+
case SyntaxKind.OrAssignmentExpression:
2527+
case SyntaxKind.LeftShiftAssignmentExpression:
2528+
case SyntaxKind.RightShiftAssignmentExpression:
2529+
case SyntaxKind.UnsignedRightShiftAssignmentExpression:
2530+
case SyntaxKind.CoalesceAssignmentExpression:
2531+
{
2532+
//TODO?
2533+
//Ignore if _IsArrayInitializer is true?
2534+
AssignmentExpressionSyntax _expr = (AssignmentExpressionSyntax)asNode;
2535+
Visit(_expr.Left);
2536+
2537+
VisitLeadingTrivia(_expr.OperatorToken);
2538+
JSSB.Append(':');
2539+
VisitTrailingTrivia(_expr.OperatorToken);
2540+
2541+
Visit(_expr.Right);
2542+
break;
2543+
}
25312544
default:
25322545
Log.ErrorLine($"asNode : {kind}\n|{asNode.ToFullString()}|");
25332546
break;
@@ -2542,16 +2555,30 @@ public override void VisitInitializerExpression(InitializerExpressionSyntax node
25422555
{
25432556
case SyntaxKind.OpenBraceToken:
25442557
{
2545-
VisitLeadingTrivia(asToken);
2546-
JSSB.Append('(');
2547-
VisitTrailingTrivia(asToken);
2558+
if (_IsArrayInitializer)
2559+
{
2560+
VisitLeadingTrivia(asToken);
2561+
JSSB.Append('(');
2562+
VisitTrailingTrivia(asToken);
2563+
}
2564+
else
2565+
{
2566+
//TODO formating?
2567+
//Ignore leading trivia?
2568+
VisitToken(asToken);
2569+
}
25482570
break;
25492571
}
25502572
case SyntaxKind.CloseBraceToken:
25512573
{
2552-
VisitLeadingTrivia(asToken);
2553-
JSSB.Append(')');
2554-
VisitTrailingTrivia(asToken);
2574+
if (_IsArrayInitializer)
2575+
{
2576+
VisitLeadingTrivia(asToken);
2577+
JSSB.Append(')');
2578+
VisitTrailingTrivia(asToken);
2579+
}
2580+
else
2581+
VisitToken(asToken);
25552582
break;
25562583
}
25572584
case SyntaxKind.CommaToken:
@@ -3222,53 +3249,130 @@ where e.IsKind(SyntaxKind.IdentifierToken)
32223249
public override void VisitObjectCreationExpression(ObjectCreationExpressionSyntax node)
32233250
{
32243251
ChildSyntaxList nodesAndTokens = node.ChildNodesAndTokens();
3252+
bool translateAsObject = false;
32253253

3226-
for (int i = 0; i < nodesAndTokens.Count; i++)
3227-
{
3228-
SyntaxNode? asNode = nodesAndTokens[i].AsNode();
3254+
SymbolInfo? symbolInfo = null;
32293255

3230-
if (asNode != null)
3256+
if (_SNPropertyType != null)
3257+
symbolInfo = _Model.GetSymbolInfo(_SNPropertyType);
3258+
else
3259+
symbolInfo = _Model.GetSymbolInfo(nodesAndTokens[1].AsNode());
3260+
3261+
ISymbol? symbol = null;
3262+
3263+
if (symbolInfo?.CandidateSymbols.Length >= 1)
3264+
symbol = symbolInfo?.CandidateSymbols[0];
3265+
else
3266+
symbol = symbolInfo?.Symbol;
3267+
3268+
if (symbol != null)
3269+
{
3270+
AttributeData[] attributeData = symbol.GetAttributes().ToArray();
3271+
for (int i = 0; i < attributeData.Length; i++)
32313272
{
3232-
SyntaxKind kind = asNode.Kind();
3273+
if (attributeData[i].ToString().EndsWith(nameof(ToObjectAttribute)))
3274+
{
3275+
translateAsObject = true;
3276+
break;
3277+
}
3278+
}
3279+
}
3280+
if (translateAsObject)
3281+
{
3282+
for (int i = 0; i < nodesAndTokens.Count; i++)
3283+
{
3284+
SyntaxNode? asNode = nodesAndTokens[i].AsNode();
32333285

3234-
switch (kind)
3286+
if (asNode != null)
32353287
{
3236-
case SyntaxKind.ObjectInitializerExpression:
3237-
{
3238-
Log.WarningLine($"'ObjectInitializerExpression' Ignored! Please use constructor for '{nodesAndTokens[1].ToString()}'");
3239-
//Todo? How? JS does not have object initializer...
3288+
SyntaxKind kind = asNode.Kind();
3289+
3290+
switch (kind)
3291+
{
3292+
case SyntaxKind.ObjectInitializerExpression:
3293+
VisitInitializerExpression((InitializerExpressionSyntax)asNode);
32403294
break;
3241-
}
3242-
case SyntaxKind.ArgumentList:
3243-
VisitArgumentList((ArgumentListSyntax)asNode);
3244-
break;
3245-
case SyntaxKind.PredefinedType:
3246-
VisitPredefinedType((PredefinedTypeSyntax)asNode);
3247-
break;
3248-
case SyntaxKind.IdentifierName:
3249-
VisitIdentifierName((IdentifierNameSyntax)asNode);
3250-
break;
3251-
case SyntaxKind.GenericName:
3252-
VisitGenericName((GenericNameSyntax)asNode);
3253-
break;
3254-
default:
3255-
Log.ErrorLine($"asNode : {kind}\n|{asNode.ToFullString()}|");
3256-
break;
3295+
case SyntaxKind.ArgumentList:
3296+
{
3297+
SyntaxTriviaList _syntaxTrivias = asNode.GetTrailingTrivia();
3298+
3299+
//Ignore the first one!
3300+
//we keep trailing trivia with "="
3301+
//example cs:
3302+
//MutationObserverInit a =|1|new MutationObserverInit()|2|{...
3303+
//example js:
3304+
//let a =|1|{...
3305+
//We keep |1| one but ignore |2| otherwise, we get double whitespace
3306+
//if there is a new line, for example |3|=newline, then:
3307+
//let a =|1||3|
3308+
//{...
3309+
if (_syntaxTrivias.Count > 1)
3310+
{
3311+
for (int _i = 1; _i < _syntaxTrivias.Count; _i++)
3312+
{
3313+
VisitTrivia(_syntaxTrivias[_i]);
3314+
}
3315+
}
3316+
break;
3317+
}
3318+
case SyntaxKind.IdentifierName:
3319+
break;
3320+
default:
3321+
Log.ErrorLine($"translateAsObject: asNode: {kind}\n|{asNode.ToFullString()}|");
3322+
break;
3323+
}
32573324
}
32583325
}
3259-
else
3326+
}
3327+
else
3328+
{
3329+
for (int i = 0; i < nodesAndTokens.Count; i++)
32603330
{
3261-
SyntaxToken asToken = nodesAndTokens[i].AsToken();
3262-
SyntaxKind kind = asToken.Kind();
3331+
SyntaxNode? asNode = nodesAndTokens[i].AsNode();
32633332

3264-
switch (kind)
3333+
if (asNode != null)
32653334
{
3266-
case SyntaxKind.NewKeyword:
3267-
VisitToken(asToken);
3268-
break;
3269-
default:
3270-
Log.ErrorLine($"asToken : {kind}");
3271-
break;
3335+
SyntaxKind kind = asNode.Kind();
3336+
3337+
switch (kind)
3338+
{
3339+
case SyntaxKind.ObjectInitializerExpression:
3340+
{
3341+
Log.WarningLine($"'ObjectInitializerExpression' Ignored! Please use constructor for '{nodesAndTokens[1].ToString()}'");
3342+
//Todo? How? JS does not have object initializer...
3343+
break;
3344+
}
3345+
case SyntaxKind.ArgumentList:
3346+
VisitArgumentList((ArgumentListSyntax)asNode);
3347+
break;
3348+
case SyntaxKind.PredefinedType:
3349+
VisitPredefinedType((PredefinedTypeSyntax)asNode);
3350+
break;
3351+
case SyntaxKind.IdentifierName:
3352+
VisitIdentifierName((IdentifierNameSyntax)asNode);
3353+
break;
3354+
case SyntaxKind.GenericName:
3355+
VisitGenericName((GenericNameSyntax)asNode);
3356+
break;
3357+
default:
3358+
Log.ErrorLine($"asNode : {kind}\n|{asNode.ToFullString()}|");
3359+
break;
3360+
}
3361+
}
3362+
else
3363+
{
3364+
SyntaxToken asToken = nodesAndTokens[i].AsToken();
3365+
SyntaxKind kind = asToken.Kind();
3366+
3367+
switch (kind)
3368+
{
3369+
case SyntaxKind.NewKeyword:
3370+
VisitToken(asToken);
3371+
break;
3372+
default:
3373+
Log.ErrorLine($"asToken : {kind}");
3374+
break;
3375+
}
32723376
}
32733377
}
32743378
}

0 commit comments

Comments
 (0)