diff --git a/CSharpToJavaScript.csproj b/CSharpToJavaScript.csproj
index 5b7b016d..d5572e43 100644
--- a/CSharpToJavaScript.csproj
+++ b/CSharpToJavaScript.csproj
@@ -6,7 +6,7 @@
net10.0
disable
enable
- True
+ False
TiLied
A library for translating/converting cs into js, using Roslyn.
https://tilied.github.io/CSTOJS_Pages/
diff --git a/CSharpToJavaScript/APIs/JS/GlobalObject.cs b/CSharpToJavaScript/APIs/JS/GlobalObject.cs
index 426758cb..81e0b013 100644
--- a/CSharpToJavaScript/APIs/JS/GlobalObject.cs
+++ b/CSharpToJavaScript/APIs/JS/GlobalObject.cs
@@ -43,7 +43,7 @@ public static bool InequalsStrict(dynamic left, dynamic right)
///
/// object.property
/// true for all cases except when the property is an own non-configurable property, in which case false is returned in non-strict mode.
- [Unary("delete ")]
+ [Unary("delete")]
public static bool Delete(dynamic arg)
{
return true;
@@ -57,7 +57,7 @@ public static bool Delete(dynamic arg)
///
/// expression
/// Undefined
- [Unary("void ")]
+ [Unary("void")]
public static Undefined Void(dynamic arg)
{
return new Undefined();
@@ -71,7 +71,7 @@ public static Undefined Void(dynamic arg)
///
/// An expression representing the object or primitive whose type is to be returned.
/// string
- [Unary("typeof ")]
+ [Unary("typeof")]
public static string TypeOf(object operand)
{
return string.Empty;
@@ -84,7 +84,7 @@ public static string TypeOf(object operand)
///
/// An expression representing the object or primitive whose type is to be returned.
/// string
- [Unary("typeof ")]
+ [Unary("typeof")]
public static string TypeOf(Func operand)
{
return string.Empty;
@@ -97,7 +97,7 @@ public static string TypeOf(Func operand)
///
/// An expression representing the object or primitive whose type is to be returned.
/// string
- [GenericUnary("typeof ")]
+ [GenericUnary("typeof")]
public static string TypeOf()
{
return string.Empty;
@@ -112,7 +112,7 @@ public static string TypeOf()
/// Constructor to test against.
/// The object to test.
/// bool
- [GenericBinary(" instanceof ")]
+ [GenericBinary("instanceof")]
public static bool InstanceOf(dynamic obj)
{
return true;
diff --git a/CSharpToJavaScript/CSTOJS.cs b/CSharpToJavaScript/CSTOJS.cs
index 68685446..5bc132db 100644
--- a/CSharpToJavaScript/CSTOJS.cs
+++ b/CSharpToJavaScript/CSTOJS.cs
@@ -6,6 +6,7 @@
using Microsoft.CodeAnalysis;
using System.Linq;
using CSharpToJavaScript.Utils;
+using System.Collections.Immutable;
namespace CSharpToJavaScript;
@@ -49,80 +50,81 @@ public static FileData[] Translate(FileData[] files, MetadataReference[]? refere
trees[0] = AddGlobalUsings(trees[0]);
+ CSharpCompilation compilation = CSharpCompilation
+ .Create("HelloWorld")
+ .AddReferences(references)
+ .AddSyntaxTrees(trees);
+
for (int i = 0; i < files.Length; i++)
{
if (files[i].OptionsForFile.TranslateFile == false)
continue;
- if (files[i].OptionsForFile.NormalizeWhitespace)
- trees[i] = trees[i].GetRoot().NormalizeWhitespace().SyntaxTree;
+ SemanticModel _model = compilation.GetSemanticModel(trees[i]);
- if (files[i].OptionsForFile.KeepBraceOnTheSameLine)
+ ImmutableArray diagnostics = _model.GetDiagnostics();
+ for (int j = 0; j < diagnostics.Length; j++)
{
- //Mostly deleted whitespaces, still TODO?
- SyntaxToken[] allBraces = trees[i].GetRoot().DescendantTokens().Where((e) => e.IsKind(SyntaxKind.OpenBraceToken)).ToArray();
-
- List allTriviaToDelete = new();
+ if (files[i].OptionsForFile.Debug)
+ Log.WarningLine(diagnostics[j].ToString());
- for (int j = 0; j < allBraces.Length; j++)
+ //Print an error if compilation fails.
+ if (diagnostics[j].Severity == DiagnosticSeverity.Error)
{
- if (allBraces[j].HasLeadingTrivia)
- {
- SyntaxTriviaList _lt = allBraces[j].LeadingTrivia;
- for (int y = 0; y < _lt.Count; y++)
- {
- allTriviaToDelete.Add(_lt[y]);
- }
- }
+ if (files[i].OptionsForFile.DisableCompilationErrors == false)
+ Log.ErrorLine(diagnostics[i].ToString());
}
- //Is this the right way to delete trivia?
- trees[i] = trees[i].GetRoot().ReplaceTrivia(allTriviaToDelete, (o, r) => SyntaxFactory.ElasticMarker).SyntaxTree;
+ }
- allBraces = trees[i].GetRoot().DescendantTokens().Where((e) => e.IsKind(SyntaxKind.OpenBraceToken)).ToArray();
+ SyntaxNode _root = trees[i].GetRoot();
- List allTriviaToReplace = new();
+ WithSemanticRewriter _withSemanticRewriter = new(_model, files[i].OptionsForFile);
+ WithoutSemanticRewriter _withoutSemanticRewriter = new(files[i].OptionsForFile);
+
+ StringBuilderWalker _stringBuilderWalker = new();
- for (int j = 0; j < allBraces.Length; j++)
- {
- SyntaxToken _token = allBraces[j].GetPreviousToken();
- if (_token.HasTrailingTrivia)
- {
- SyntaxTrivia _trivia = _token.TrailingTrivia.Where((e) => e.IsKind(SyntaxKind.EndOfLineTrivia)).FirstOrDefault();
- if (!_trivia.IsKind(SyntaxKind.None))
- {
- allTriviaToReplace.Add(_trivia);
- }
- }
- }
- trees[i] = trees[i].GetRoot().ReplaceTrivia(allTriviaToReplace, (o, r) => SyntaxFactory.Space).SyntaxTree;
- }
- }
+ SyntaxNode newRoot1 = _withSemanticRewriter.Visit(_root);
+ if (_root != newRoot1)
+ _root = newRoot1;
- CSharpCompilation compilation = CSharpCompilation
- .Create("HelloWorld")
- .AddReferences(references)
- .AddSyntaxTrees(trees);
+ _root = _root.ReplaceNodes(_withSemanticRewriter.ReplaceNodes.Keys, (o, r) =>
+ {
+ return _withSemanticRewriter.ReplaceNodes[o];
+ });
- for (int i = 0; i < files.Length; i++)
- {
- if (files[i].OptionsForFile.TranslateFile == false)
- continue;
+ if (files[i].OptionsForFile.Debug)
+ files[i].Debug_WithSemanticRewriter = _root.ToFullString();
- Walker _walker = new(files[i].OptionsForFile, compilation.GetSemanticModel(trees[i]));
+ SyntaxNode newRoot2 = _withoutSemanticRewriter.Visit(_root);
+ if (_root != newRoot2)
+ _root = newRoot2;
- _walker.JSSB.Append(files[i].OptionsForFile.AddSBAtTheTop);
+ if (files[i].OptionsForFile.Debug)
+ files[i].Debug_WithoutSemanticRewriter = _root.ToFullString();
+
+ if (files[i].OptionsForFile.NormalizeWhitespace)
+ _root = _root.NormalizeWhitespace();
- _walker.Visit(trees[i].GetRoot());
+ if (files[i].OptionsForFile.KeepBraceOnTheSameLine)
+ {
+ KeepBraceOnTheSameLineRewriter _keepBraceOnTheSameLineRewriter = new();
+
+ SyntaxNode newRoot3 = _keepBraceOnTheSameLineRewriter.Visit(_root);
+ if (_root != newRoot3)
+ _root = newRoot3;
+ }
- _walker.JSSB.Append(files[i].OptionsForFile.AddSBAtTheBottom);
+ _stringBuilderWalker.JSSB.Append(files[i].OptionsForFile.AddSBAtTheTop);
+ _stringBuilderWalker.Visit(_root);
+ _stringBuilderWalker.JSSB.Append(files[i].OptionsForFile.AddSBAtTheBottom);
- files[i].TranslatedStr = _walker.JSSB.ToString();
+ files[i].TranslatedStr = _stringBuilderWalker.JSSB.ToString();
}
return files;
}
- private static MetadataReference[] GetReferences(CSTOJSOptions options)
+ public static MetadataReference[] GetReferences(CSTOJSOptions options)
{
HashSet assemblyMetadata = new();
@@ -200,7 +202,7 @@ private static MetadataReference[] GetReferences(CSTOJSOptions options)
}
Log.InfoLine($"---");
}
-
+
MetadataReference[] references = new MetadataReference[assemblyMetadata.Count];
int i = 0;
foreach (MetadataReference metadata in assemblyMetadata)
@@ -218,11 +220,11 @@ private static MetadataReference[] GetReferences(CSTOJSOptions options)
}
Log.InfoLine($"+++");
}
-
+
return references;
}
- private static SyntaxTree AddGlobalUsings(SyntaxTree tree)
+ public static SyntaxTree AddGlobalUsings(SyntaxTree tree)
{
CompilationUnitSyntax root = tree.GetCompilationUnitRoot();
UsingDirectiveSyntax[] oldUsing = root.Usings.ToArray();
@@ -397,9 +399,20 @@ public class FileData
/// CS input string.
///
public string SourceStr { get; set; } = string.Empty;
-
+
///
/// JS translated string.
///
public string TranslatedStr { get; set; } = string.Empty;
-}
\ No newline at end of file
+
+
+ ///
+ /// Debug string.
+ ///
+ public string Debug_WithSemanticRewriter { get; set; } = string.Empty;
+
+ ///
+ /// Debug string.
+ ///
+ public string Debug_WithoutSemanticRewriter { get; set; } = string.Empty;
+}
diff --git a/CSharpToJavaScript/StringBuilderWalker.cs b/CSharpToJavaScript/StringBuilderWalker.cs
new file mode 100644
index 00000000..f3e13be7
--- /dev/null
+++ b/CSharpToJavaScript/StringBuilderWalker.cs
@@ -0,0 +1,725 @@
+using CSharpToJavaScript.Utils;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using System.Text;
+using System;
+
+namespace CSharpToJavaScript;
+
+internal class StringBuilderWalker : CSharpSyntaxWalker
+{
+ public StringBuilder JSSB { get; set; } = new(512);
+
+ public StringBuilderWalker() : base(SyntaxWalkerDepth.Trivia)
+ {
+
+ }
+
+#if DEBUG
+ public override void Visit(SyntaxNode? node)
+ {
+ if (node != null)
+ Log.InfoLine($"kind: {node.Kind()} \n\t{node.ToString()}");
+
+ base.Visit(node);
+ }
+#endif
+
+ public override void VisitTrivia(SyntaxTrivia trivia)
+ {
+ switch (trivia.Kind())
+ {
+ case SyntaxKind.SingleLineCommentTrivia:
+ {
+ string _full = trivia.ToString();
+
+ //special syntax.
+ //for writing js code //...\\
+ if (_full.EndsWith(@"\\"))
+ JSSB.Append(_full.AsSpan(2, _full.Length - 4));
+ else
+ JSSB.Append(_full);
+ return;
+ }
+ case SyntaxKind.MultiLineCommentTrivia:
+ case SyntaxKind.WhitespaceTrivia:
+ case SyntaxKind.EndOfLineTrivia:
+ case SyntaxKind.SkippedTokensTrivia:
+ {
+ string _full = trivia.ToFullString();
+ JSSB.Append(_full);
+ return;
+ }
+ // Todo? how? convert to jsdoc?
+ case SyntaxKind.SingleLineDocumentationCommentTrivia:
+ case SyntaxKind.MultiLineDocumentationCommentTrivia:
+ {
+ //JSSB.Append("/**");
+ string _full = trivia.ToFullString();
+ JSSB.Append(_full);
+ //JSSB.AppendLine("");
+ return;
+ }
+ default:
+ Log.ErrorLine($"Trivia : {trivia.Kind()}");
+ break;
+ }
+
+ base.VisitTrivia(trivia);
+ }
+
+ public override void VisitToken(SyntaxToken token)
+ {
+ switch (token.Kind())
+ {
+ //TODO?
+ case SyntaxKind.IdentifierToken:
+ {
+ VisitLeadingTrivia(token);
+
+ JSSB.Append(token.Text.Replace("DollarSign_", "$"));
+
+ VisitTrailingTrivia(token);
+ return;
+ }
+ case SyntaxKind.InKeyword:
+ case SyntaxKind.StaticKeyword:
+ case SyntaxKind.TrueKeyword:
+ case SyntaxKind.FalseKeyword:
+ case SyntaxKind.ReturnKeyword:
+ case SyntaxKind.ClassKeyword:
+ case SyntaxKind.OpenParenToken:
+ case SyntaxKind.CloseParenToken:
+ case SyntaxKind.SemicolonToken:
+ case SyntaxKind.CloseBraceToken:
+ case SyntaxKind.DotToken:
+ case SyntaxKind.EqualsToken:
+ case SyntaxKind.StringLiteralToken:
+ case SyntaxKind.ForKeyword:
+ case SyntaxKind.IfKeyword:
+ case SyntaxKind.GreaterThanEqualsToken:
+ case SyntaxKind.PlusPlusToken:
+ case SyntaxKind.PlusToken:
+ case SyntaxKind.LessThanToken:
+ case SyntaxKind.NumericLiteralToken:
+ case SyntaxKind.CommaToken:
+ case SyntaxKind.NewKeyword:
+ case SyntaxKind.ThisKeyword:
+ case SyntaxKind.MinusToken:
+ case SyntaxKind.MinusMinusToken:
+ case SyntaxKind.SlashToken:
+ case SyntaxKind.AsteriskToken:
+ case SyntaxKind.NullKeyword:
+ case SyntaxKind.BreakKeyword:
+ case SyntaxKind.CloseBracketToken:
+ case SyntaxKind.OpenBracketToken:
+ case SyntaxKind.EqualsGreaterThanToken:
+ case SyntaxKind.AwaitKeyword:
+ case SyntaxKind.AsyncKeyword:
+ case SyntaxKind.ElseKeyword:
+ case SyntaxKind.SwitchKeyword:
+ case SyntaxKind.CaseKeyword:
+ case SyntaxKind.ColonToken:
+ case SyntaxKind.DefaultKeyword:
+ case SyntaxKind.BarBarToken:
+ case SyntaxKind.ExclamationToken:
+ case SyntaxKind.ContinueKeyword:
+ case SyntaxKind.GreaterThanToken:
+ case SyntaxKind.AmpersandAmpersandToken:
+ case SyntaxKind.PlusEqualsToken:
+ case SyntaxKind.MinusEqualsToken:
+ case SyntaxKind.AsteriskEqualsToken:
+ case SyntaxKind.SlashEqualsToken:
+ case SyntaxKind.WhileKeyword:
+ case SyntaxKind.InterpolatedStringTextToken:
+ case SyntaxKind.QuestionToken:
+ case SyntaxKind.LessThanEqualsToken:
+ case SyntaxKind.ConstKeyword:
+ case SyntaxKind.PercentToken:
+ case SyntaxKind.QuestionQuestionToken:
+ case SyntaxKind.TildeToken:
+ case SyntaxKind.AmpersandToken:
+ case SyntaxKind.GreaterThanGreaterThanToken:
+ case SyntaxKind.LessThanLessThanToken:
+ case SyntaxKind.GreaterThanGreaterThanEqualsToken:
+ case SyntaxKind.LessThanLessThanEqualsToken:
+ case SyntaxKind.CaretEqualsToken:
+ case SyntaxKind.BarEqualsToken:
+ case SyntaxKind.AmpersandEqualsToken:
+ case SyntaxKind.BarToken:
+ case SyntaxKind.DoKeyword:
+ case SyntaxKind.ThrowStatement:
+ case SyntaxKind.CatchKeyword:
+ case SyntaxKind.TryKeyword:
+ case SyntaxKind.ThrowKeyword:
+ case SyntaxKind.FinallyKeyword:
+ case SyntaxKind.CaretToken:
+ case SyntaxKind.CharacterLiteralToken:
+ case SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
+ case SyntaxKind.PercentEqualsToken:
+ case SyntaxKind.QuestionQuestionEqualsToken:
+ case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
+ case SyntaxKind.TypeOfKeyword:
+ case SyntaxKind.ExclamationEqualsToken:
+ case SyntaxKind.EqualsEqualsToken:
+ case SyntaxKind.EndOfFileToken:
+ case SyntaxKind.OpenBraceToken:
+ {
+ VisitLeadingTrivia(token);
+
+ JSSB.Append(token.Text);
+
+ VisitTrailingTrivia(token);
+ return;
+ }
+ default:
+ Log.ErrorLine($"Token : {token.Kind()}");
+ break;
+ }
+
+ base.VisitToken(token);
+ }
+
+ public override void VisitCompilationUnit(CompilationUnitSyntax node)
+ {
+ ChildSyntaxList nodesAndTokens = node.ChildNodesAndTokens();
+
+ for (int i = 0; i < nodesAndTokens.Count; i++)
+ {
+ SyntaxNode? asNode = nodesAndTokens[i].AsNode();
+
+ if (asNode != null)
+ {
+ SyntaxKind kind = asNode.Kind();
+
+ switch (kind)
+ {
+ case SyntaxKind.ClassDeclaration:
+ VisitClassDeclaration((ClassDeclarationSyntax)asNode);
+ break;
+ case SyntaxKind.GlobalStatement:
+ VisitGlobalStatement((GlobalStatementSyntax)asNode);
+ break;
+ case SyntaxKind.NamespaceDeclaration:
+ VisitNamespaceDeclaration((NamespaceDeclarationSyntax)asNode);
+ break;
+ case SyntaxKind.FileScopedNamespaceDeclaration:
+ VisitFileScopedNamespaceDeclaration((FileScopedNamespaceDeclarationSyntax)asNode);
+ break;
+ default:
+ Log.ErrorLine($"asNode : {kind}\n|{asNode.ToFullString()}|");
+ break;
+ }
+ }
+ else
+ {
+ SyntaxToken asToken = nodesAndTokens[i].AsToken();
+ SyntaxKind kind = asToken.Kind();
+
+ switch (kind)
+ {
+ case SyntaxKind.EndOfFileToken:
+ VisitToken(asToken);
+ break;
+ default:
+ Log.ErrorLine($"asToken : {kind}");
+ break;
+ }
+ }
+ }
+ }
+ public override void VisitNamespaceDeclaration(NamespaceDeclarationSyntax node)
+ {
+ ChildSyntaxList nodesAndTokens = node.ChildNodesAndTokens();
+
+ for (int i = 0; i < nodesAndTokens.Count; i++)
+ {
+ SyntaxNode? asNode = nodesAndTokens[i].AsNode();
+
+ if (asNode != null)
+ {
+ SyntaxKind kind = asNode.Kind();
+
+ switch (kind)
+ {
+ case SyntaxKind.QualifiedName:
+ case SyntaxKind.IdentifierName:
+ break;
+ case SyntaxKind.ClassDeclaration:
+ VisitClassDeclaration((ClassDeclarationSyntax)asNode);
+ break;
+ case SyntaxKind.EnumDeclaration:
+ VisitEnumDeclaration((EnumDeclarationSyntax)asNode);
+ break;
+ case SyntaxKind.NamespaceDeclaration:
+ VisitNamespaceDeclaration((NamespaceDeclarationSyntax)asNode);
+ break;
+ default:
+ Log.ErrorLine($"asNode : {kind}\n|{asNode.ToFullString()}|");
+ break;
+ }
+ }
+ else
+ {
+ SyntaxToken asToken = nodesAndTokens[i].AsToken();
+ SyntaxKind kind = asToken.Kind();
+
+ switch (kind)
+ {
+ //Todo? make a scope??? {...}
+ //OpenBraceToken and CloseBraceToken
+ case SyntaxKind.OpenBraceToken:
+ case SyntaxKind.CloseBraceToken:
+ case SyntaxKind.NamespaceKeyword:
+ break;
+ default:
+ Log.ErrorLine($"asToken : {kind}");
+ break;
+ }
+ }
+ }
+ }
+ public override void VisitFileScopedNamespaceDeclaration(FileScopedNamespaceDeclarationSyntax node)
+ {
+ ChildSyntaxList nodesAndTokens = node.ChildNodesAndTokens();
+
+ for (int i = 0; i < nodesAndTokens.Count; i++)
+ {
+ SyntaxNode? asNode = nodesAndTokens[i].AsNode();
+
+ if (asNode != null)
+ {
+ SyntaxKind kind = asNode.Kind();
+
+ switch (kind)
+ {
+ case SyntaxKind.QualifiedName:
+ case SyntaxKind.IdentifierName:
+ break;
+ case SyntaxKind.ClassDeclaration:
+ VisitClassDeclaration((ClassDeclarationSyntax)asNode);
+ break;
+ case SyntaxKind.EnumDeclaration:
+ VisitEnumDeclaration((EnumDeclarationSyntax)asNode);
+ break;
+ case SyntaxKind.NamespaceDeclaration:
+ VisitNamespaceDeclaration((NamespaceDeclarationSyntax)asNode);
+ break;
+ default:
+ Log.ErrorLine($"asNode : {kind}\n|{asNode.ToFullString()}|");
+ break;
+ }
+ }
+ else
+ {
+ SyntaxToken asToken = nodesAndTokens[i].AsToken();
+ SyntaxKind kind = asToken.Kind();
+
+ switch (kind)
+ {
+ case SyntaxKind.SemicolonToken:
+ case SyntaxKind.NamespaceKeyword:
+ break;
+ default:
+ Log.ErrorLine($"asToken : {kind}");
+ break;
+ }
+ }
+ }
+ }
+
+ public override void VisitInvocationExpression(InvocationExpressionSyntax node)
+ {
+ if (node.Expression.HasAnnotation(BinaryAttribute.Annotation))
+ {
+ VisitArgument(node.ArgumentList.Arguments[0]);
+
+ if (!node.ArgumentList.Arguments[0].HasTrailingTrivia)
+ JSSB.Append(' ');
+
+ JSSB.Append(node.Expression.ToString());
+
+ VisitTrailingTrivia(node.ArgumentList.Arguments.GetSeparator(0));
+
+ VisitArgument(node.ArgumentList.Arguments[1]);
+ return;
+ }
+ if (node.Expression.HasAnnotation(UnaryAttribute.Annotation))
+ {
+ JSSB.Append(node.Expression.ToString());
+
+ if (!node.Expression.HasTrailingTrivia)
+ JSSB.Append(' ');
+
+ VisitArgument(node.ArgumentList.Arguments[0]);
+ return;
+ }
+ base.VisitInvocationExpression(node);
+ }
+ public override void VisitConstructorDeclaration(ConstructorDeclarationSyntax node)
+ {
+ if (!node.Identifier.HasAnnotation(WithoutSemanticRewriter.StaticConstructor))
+ base.VisitConstructorDeclaration(node);
+ else
+ {
+ ChildSyntaxList nodesAndTokens = node.ChildNodesAndTokens();
+
+ for (int i = 0; i < nodesAndTokens.Count; i++)
+ {
+ SyntaxNode? asNode = nodesAndTokens[i].AsNode();
+
+ if (asNode != null)
+ {
+ SyntaxKind kind = asNode.Kind();
+
+ switch (kind)
+ {
+ case SyntaxKind.ParameterList:
+ {
+ SyntaxTriviaList _syntaxTrivias = asNode.GetLeadingTrivia();
+ for (int _i = 0; _i < _syntaxTrivias.Count; _i++)
+ {
+ VisitTrivia(_syntaxTrivias[_i]);
+ }
+ _syntaxTrivias = asNode.GetTrailingTrivia();
+ for (int _i = 0; _i < _syntaxTrivias.Count; _i++)
+ {
+ VisitTrivia(_syntaxTrivias[_i]);
+ }
+ break;
+ }
+ case SyntaxKind.Block:
+ VisitBlock((BlockSyntax)asNode);
+ break;
+ default:
+ Log.ErrorLine($"asNode : {kind}\n|{asNode.ToFullString()}|");
+ break;
+ }
+ }
+ else
+ {
+ SyntaxToken asToken = nodesAndTokens[i].AsToken();
+ SyntaxKind kind = asToken.Kind();
+
+ switch (kind)
+ {
+ case SyntaxKind.IdentifierToken:
+ {
+ VisitToken(asToken);
+ break;
+ }
+ default:
+ Log.ErrorLine($"asToken : {kind}");
+
+ break;
+ }
+ }
+ }
+ }
+ }
+
+
+
+
+
+ //Can't do in "WithoutSemanticRewriter". Throws an error:
+ //An exception of type 'System.ArgumentException' occurred in Microsoft.CodeAnalysis.CSharp.dll but was not handled in user code: 'colonToken'
+ //Code:
+ /*
+ public override SyntaxNode? VisitBaseList(BaseListSyntax node)
+ {
+ node = (BaseListSyntax)base.VisitBaseList(node)!;
+
+ node = node.ReplaceToken(node.ColonToken, SyntaxFactory.Token(SyntaxKind.None));
+
+ return node;
+ }
+ */
+ public override void VisitBaseList(BaseListSyntax node)
+ {
+ ChildSyntaxList nodesAndTokens = node.ChildNodesAndTokens();
+
+ for (int i = 0; i < nodesAndTokens.Count; i++)
+ {
+ SyntaxNode? asNode = nodesAndTokens[i].AsNode();
+
+ if (asNode != null)
+ {
+ SyntaxKind kind = asNode.Kind();
+
+ switch (kind)
+ {
+ case SyntaxKind.SimpleBaseType:
+ VisitSimpleBaseType((SimpleBaseTypeSyntax)asNode);
+ break;
+ default:
+ Log.ErrorLine($"asNode : {kind}\n|{asNode.ToFullString()}|");
+ break;
+ }
+ }
+ else
+ {
+ SyntaxToken asToken = nodesAndTokens[i].AsToken();
+ SyntaxKind kind = asToken.Kind();
+
+ switch (kind)
+ {
+ case SyntaxKind.ColonToken:
+ {
+ VisitLeadingTrivia(asToken);
+ JSSB.Append("extends");
+ VisitTrailingTrivia(asToken);
+ break;
+ }
+ default:
+ Log.ErrorLine($"asToken : {kind}");
+ break;
+ }
+ }
+ }
+ }
+
+ //Can't replace a token. Same as VisitBaseList
+ //see "tokenInList"
+ //https://learn.microsoft.com/en-us/dotnet/api/microsoft.codeanalysis.syntaxnodeextensions.replacetoken?view=roslyn-dotnet-4.13.0#microsoft-codeanalysis-syntaxnodeextensions-replacetoken-1(-0-microsoft-codeanalysis-syntaxtoken-system-collections-generic-ienumerable((microsoft-codeanalysis-syntaxtoken)))
+ //"The token to be replaced. This must be a direct element of a SyntaxTokenList (such as a modifier in a list of modifiers), and a descendant of the root node. If the token is not part of a SyntaxTokenList, an InvalidOperationException will be thrown."
+ //But it throws a 'System.ArgumentException', not an 'InvalidOperationException':
+ //An exception of type 'System.ArgumentException' occurred in Microsoft.CodeAnalysis.CSharp.dll but was not handled in user code: 'stringStartToken'
+ //Code:
+ /*
+ public override SyntaxNode? VisitInterpolatedStringExpression(InterpolatedStringExpressionSyntax node)
+ {
+ node = (InterpolatedStringExpressionSyntax)base.VisitInterpolatedStringExpression(node)!;
+ node = node.ReplaceToken(node.StringStartToken, SyntaxFactory.Token(SyntaxKind.SingleQuoteToken));
+ node = node.ReplaceToken(node.StringEndToken, SyntaxFactory.Token(SyntaxKind.SingleQuoteToken));
+ return node;
+ }
+ */
+ public override void VisitInterpolatedStringExpression(InterpolatedStringExpressionSyntax node)
+ {
+ ChildSyntaxList nodesAndTokens = node.ChildNodesAndTokens();
+
+ for (int i = 0; i < nodesAndTokens.Count; i++)
+ {
+ SyntaxNode? asNode = nodesAndTokens[i].AsNode();
+
+ if (asNode != null)
+ {
+ SyntaxKind kind = asNode.Kind();
+
+ switch (kind)
+ {
+ case SyntaxKind.InterpolatedStringText:
+ VisitInterpolatedStringText((InterpolatedStringTextSyntax)asNode);
+ break;
+ case SyntaxKind.Interpolation:
+ {
+ JSSB.Append('$');
+ VisitInterpolation((InterpolationSyntax)asNode);
+ break;
+ }
+ default:
+ Log.ErrorLine($"asNode : {kind}\n|{asNode.ToFullString()}|");
+ break;
+ }
+ }
+ else
+ {
+ SyntaxToken asToken = nodesAndTokens[i].AsToken();
+ SyntaxKind kind = asToken.Kind();
+
+ switch (kind)
+ {
+ case SyntaxKind.InterpolatedStringStartToken:
+ case SyntaxKind.InterpolatedStringEndToken:
+ JSSB.Append('`');
+ break;
+ default:
+ Log.ErrorLine($"asToken : {kind}");
+ break;
+ }
+ }
+ }
+ }
+ public override void VisitInitializerExpression(InitializerExpressionSyntax node)
+ {
+ ChildSyntaxList nodesAndTokens = node.ChildNodesAndTokens();
+
+ for (int i = 0; i < nodesAndTokens.Count; i++)
+ {
+ SyntaxNode? asNode = nodesAndTokens[i].AsNode();
+
+ if (asNode != null)
+ {
+ SyntaxKind kind = asNode.Kind();
+
+ switch (kind)
+ {
+ case SyntaxKind.IdentifierName:
+ VisitIdentifierName((IdentifierNameSyntax)asNode);
+ break;
+ case SyntaxKind.ArgListExpression:
+ case SyntaxKind.NumericLiteralExpression:
+ case SyntaxKind.StringLiteralExpression:
+ case SyntaxKind.Utf8StringLiteralExpression:
+ case SyntaxKind.CharacterLiteralExpression:
+ case SyntaxKind.TrueLiteralExpression:
+ case SyntaxKind.FalseLiteralExpression:
+ case SyntaxKind.NullLiteralExpression:
+ case SyntaxKind.DefaultLiteralExpression:
+ VisitLiteralExpression((LiteralExpressionSyntax)asNode);
+ break;
+ case SyntaxKind.ObjectInitializerExpression:
+ case SyntaxKind.CollectionInitializerExpression:
+ case SyntaxKind.ArrayInitializerExpression:
+ case SyntaxKind.ComplexElementInitializerExpression:
+ case SyntaxKind.WithInitializerExpression:
+ VisitInitializerExpression((InitializerExpressionSyntax)asNode);
+ break;
+ case SyntaxKind.ObjectCreationExpression:
+ VisitObjectCreationExpression((ObjectCreationExpressionSyntax)asNode);
+ break;
+ case SyntaxKind.SimpleAssignmentExpression:
+ case SyntaxKind.AddAssignmentExpression:
+ case SyntaxKind.SubtractAssignmentExpression:
+ case SyntaxKind.MultiplyAssignmentExpression:
+ case SyntaxKind.DivideAssignmentExpression:
+ case SyntaxKind.ModuloAssignmentExpression:
+ case SyntaxKind.AndAssignmentExpression:
+ case SyntaxKind.ExclusiveOrAssignmentExpression:
+ case SyntaxKind.OrAssignmentExpression:
+ case SyntaxKind.LeftShiftAssignmentExpression:
+ case SyntaxKind.RightShiftAssignmentExpression:
+ case SyntaxKind.UnsignedRightShiftAssignmentExpression:
+ case SyntaxKind.CoalesceAssignmentExpression:
+ {
+ AssignmentExpressionSyntax _expr = (AssignmentExpressionSyntax)asNode;
+ Visit(_expr.Left);
+
+ VisitLeadingTrivia(_expr.OperatorToken);
+ JSSB.Append(':');
+ VisitTrailingTrivia(_expr.OperatorToken);
+
+ Visit(_expr.Right);
+ break;
+ }
+ default:
+ Log.ErrorLine($"asNode : {kind}\n|{asNode.ToFullString()}|");
+ break;
+ }
+ }
+ else
+ {
+ SyntaxToken asToken = nodesAndTokens[i].AsToken();
+ SyntaxKind kind = asToken.Kind();
+
+ switch (kind)
+ {
+ case SyntaxKind.OpenBraceToken:
+ case SyntaxKind.CloseBraceToken:
+ {
+ VisitToken(asToken);
+ break;
+ }
+ case SyntaxKind.CommaToken:
+ VisitToken(asToken);
+ break;
+ default:
+ Log.ErrorLine($"asToken : {kind}");
+
+ break;
+ }
+ }
+ }
+ }
+
+ //TODO?
+ //Try replace with "SyntaxFactory.InitializerExpression(SyntaxKind.ArrayInitializerExpression, SyntaxFactory.SeparatedList(enumMembers)))))))).WithTrailingTrivia(node.CloseBraceToken.TrailingTrivia);"
+ public override void VisitAnonymousObjectCreationExpression(AnonymousObjectCreationExpressionSyntax node)
+ {
+ ChildSyntaxList nodesAndTokens = node.ChildNodesAndTokens();
+
+ for (int i = 0; i < nodesAndTokens.Count; i++)
+ {
+ SyntaxNode? asNode = nodesAndTokens[i].AsNode();
+
+ if (asNode != null)
+ {
+ SyntaxKind kind = asNode.Kind();
+
+ switch (kind)
+ {
+ case SyntaxKind.AnonymousObjectMemberDeclarator:
+ VisitAnonymousObjectMemberDeclarator((AnonymousObjectMemberDeclaratorSyntax)asNode);
+ break;
+ default:
+ Log.ErrorLine($"asNode : {kind}\n|{asNode.ToFullString()}|");
+ break;
+ }
+ }
+ else
+ {
+ SyntaxToken asToken = nodesAndTokens[i].AsToken();
+ SyntaxKind kind = asToken.Kind();
+
+ switch (kind)
+ {
+ case SyntaxKind.CommaToken:
+ case SyntaxKind.OpenBraceToken:
+ case SyntaxKind.CloseBraceToken:
+ VisitToken(asToken);
+ break;
+ case SyntaxKind.NewKeyword:
+ break;
+ default:
+ Log.ErrorLine($"asToken : {kind}");
+ break;
+ }
+ }
+ }
+ }
+ public override void VisitNameEquals(NameEqualsSyntax node)
+ {
+ ChildSyntaxList nodesAndTokens = node.ChildNodesAndTokens();
+
+ for (int i = 0; i < nodesAndTokens.Count; i++)
+ {
+ SyntaxNode? asNode = nodesAndTokens[i].AsNode();
+
+ if (asNode != null)
+ {
+ SyntaxKind kind = asNode.Kind();
+
+ switch (kind)
+ {
+ case SyntaxKind.IdentifierName:
+ VisitIdentifierName((IdentifierNameSyntax)asNode);
+ break;
+ default:
+ Log.ErrorLine($"asNode : {kind}\n|{asNode.ToFullString()}|");
+ break;
+ }
+ }
+ else
+ {
+ SyntaxToken asToken = nodesAndTokens[i].AsToken();
+ SyntaxKind kind = asToken.Kind();
+
+ switch (kind)
+ {
+ case SyntaxKind.EqualsToken:
+ {
+ VisitLeadingTrivia(asToken);
+ JSSB.Append(':');
+ VisitTrailingTrivia(asToken);
+ break;
+ }
+ default:
+ Log.ErrorLine($"asToken : {kind}");
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/CSharpToJavaScript/Utils/Attributes.cs b/CSharpToJavaScript/Utils/Attributes.cs
index b7ad2ec2..3610e491 100644
--- a/CSharpToJavaScript/Utils/Attributes.cs
+++ b/CSharpToJavaScript/Utils/Attributes.cs
@@ -1,4 +1,5 @@
-using System;
+using Microsoft.CodeAnalysis;
+using System;
namespace CSharpToJavaScript.Utils;
@@ -76,6 +77,7 @@ public string Convert(string str)
[AttributeUsage(AttributeTargets.All)]
public class BinaryAttribute : Attribute
{
+ public static SyntaxAnnotation Annotation { get; } = new(nameof(BinaryAttribute));
public string Value { get; init; }
public BinaryAttribute(string value)
{
@@ -100,6 +102,7 @@ public GenericBinaryAttribute(string value)
[AttributeUsage(AttributeTargets.All)]
public class UnaryAttribute : Attribute
{
+ public static SyntaxAnnotation Annotation { get; } = new(nameof(UnaryAttribute));
public string Value { get; init; }
public UnaryAttribute(string value)
{
@@ -125,8 +128,8 @@ public GenericUnaryAttribute(string value)
[AttributeUsage(AttributeTargets.All)]
public class ToObjectAttribute : Attribute
{
-
+ public static SyntaxAnnotation Annotation { get; } = new(nameof(ToObjectAttribute));
}
[AttributeUsage(AttributeTargets.Method)]
-public class GenericAsArgument : Attribute { }
\ No newline at end of file
+public class GenericAsArgumentAttribute : Attribute { }
\ No newline at end of file
diff --git a/CSharpToJavaScript/Utils/NETAPI.cs b/CSharpToJavaScript/Utils/NETAPI.cs
index 6554b5cc..63bd18c5 100644
--- a/CSharpToJavaScript/Utils/NETAPI.cs
+++ b/CSharpToJavaScript/Utils/NETAPI.cs
@@ -6,7 +6,7 @@
internal class NETAPI
{
- private readonly TypeName[] _TypeNames = new TypeName[8];
+ private readonly TypeName[] _TypeNames = new TypeName[9];
public NETAPI()
{
@@ -38,6 +38,7 @@ public NETAPI()
_TypeNames[2].Name = nameof(System.Collections.Generic.List