1. Fixed constructor calls in AstTransformer.cs by adding missing nestedTypes parameter 2. Fixed constructor calls in AstJsonSerializer.cs by adding logic to deserialize nestedTypes 3. Fixed constructor calls in AstBuilder.cs by adding empty nestedTypes lists and correct parameters 4. Fixed test files by updating ClassDeclaration constructors with proper parameters
1416 lines
68 KiB
C#
1416 lines
68 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
using MarketAlly.IronJava.Core.AST;
|
|
using MarketAlly.IronJava.Core.AST.Nodes;
|
|
using MarketAlly.IronJava.Core.AST.Visitors;
|
|
|
|
namespace MarketAlly.IronJava.Core.Serialization
|
|
{
|
|
/// <summary>
|
|
/// Provides JSON serialization for Java AST nodes.
|
|
/// </summary>
|
|
public class AstJsonSerializer
|
|
{
|
|
private readonly JsonSerializerOptions _options;
|
|
|
|
public AstJsonSerializer(bool indented = true)
|
|
{
|
|
_options = new JsonSerializerOptions
|
|
{
|
|
WriteIndented = indented,
|
|
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
|
Converters =
|
|
{
|
|
new JsonStringEnumConverter(),
|
|
new AstNodeConverterFactory()
|
|
}
|
|
};
|
|
}
|
|
|
|
public string Serialize(JavaNode node)
|
|
{
|
|
var visitor = new JsonSerializationVisitor();
|
|
var jsonNode = node.Accept(visitor);
|
|
return JsonSerializer.Serialize(jsonNode, _options);
|
|
}
|
|
|
|
public T? Deserialize<T>(string json) where T : JavaNode
|
|
{
|
|
using var document = JsonDocument.Parse(json);
|
|
var deserializer = new JsonDeserializationVisitor();
|
|
return deserializer.Deserialize(document.RootElement) as T;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Custom converter factory for AST nodes.
|
|
/// </summary>
|
|
internal class AstNodeConverterFactory : JsonConverterFactory
|
|
{
|
|
public override bool CanConvert(Type typeToConvert)
|
|
{
|
|
return typeof(JavaNode).IsAssignableFrom(typeToConvert);
|
|
}
|
|
|
|
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
|
|
{
|
|
return new AstNodeConverter();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Custom converter for AST nodes.
|
|
/// </summary>
|
|
internal class AstNodeConverter : JsonConverter<JavaNode>
|
|
{
|
|
public override JavaNode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
|
{
|
|
using var document = JsonDocument.ParseValue(ref reader);
|
|
var deserializer = new JsonDeserializationVisitor();
|
|
return deserializer.Deserialize(document.RootElement);
|
|
}
|
|
|
|
public override void Write(Utf8JsonWriter writer, JavaNode value, JsonSerializerOptions options)
|
|
{
|
|
var visitor = new JsonSerializationVisitor();
|
|
var jsonNode = value.Accept(visitor);
|
|
JsonSerializer.Serialize(writer, jsonNode, options);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Visitor that converts AST nodes to JSON-serializable dictionaries.
|
|
/// </summary>
|
|
internal class JsonSerializationVisitor : JavaVisitorBase<Dictionary<string, object?>>
|
|
{
|
|
protected override Dictionary<string, object?> DefaultVisit(JavaNode node)
|
|
{
|
|
var result = new Dictionary<string, object?>
|
|
{
|
|
["nodeType"] = node.GetType().Name,
|
|
["location"] = SerializeLocation(node.Location)
|
|
};
|
|
|
|
var children = node.Children.Select(child => child.Accept(this)).ToList();
|
|
if (children.Count > 0)
|
|
{
|
|
result["children"] = children;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private Dictionary<string, object> SerializeLocation(SourceRange location)
|
|
{
|
|
return new Dictionary<string, object>
|
|
{
|
|
["start"] = new Dictionary<string, object>
|
|
{
|
|
["line"] = location.Start.Line,
|
|
["column"] = location.Start.Column,
|
|
["position"] = location.Start.Position
|
|
},
|
|
["end"] = new Dictionary<string, object>
|
|
{
|
|
["line"] = location.End.Line,
|
|
["column"] = location.End.Column,
|
|
["position"] = location.End.Position
|
|
}
|
|
};
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitCompilationUnit(CompilationUnit node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["package"] = node.Package?.Accept(this);
|
|
result["imports"] = node.Imports.Select(i => i.Accept(this)).ToList();
|
|
result["types"] = node.Types.Select(t => t.Accept(this)).ToList();
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitPackageDeclaration(PackageDeclaration node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["packageName"] = node.PackageName;
|
|
result["annotations"] = SerializeAnnotations(node.Annotations);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitImportDeclaration(ImportDeclaration node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["importPath"] = node.ImportPath;
|
|
result["isStatic"] = node.IsStatic;
|
|
result["isWildcard"] = node.IsWildcard;
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitClassDeclaration(ClassDeclaration node)
|
|
{
|
|
var result = CreateTypeDeclarationBase(node);
|
|
result["superClass"] = node.SuperClass?.Accept(this);
|
|
result["interfaces"] = node.Interfaces.Select(i => i.Accept(this)).ToList();
|
|
result["members"] = node.Members.Select(m => m.Accept(this)).ToList();
|
|
result["isRecord"] = node.IsRecord;
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitInterfaceDeclaration(InterfaceDeclaration node)
|
|
{
|
|
var result = CreateTypeDeclarationBase(node);
|
|
result["extendedInterfaces"] = node.ExtendedInterfaces.Select(i => i.Accept(this)).ToList();
|
|
result["members"] = node.Members.Select(m => m.Accept(this)).ToList();
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitEnumDeclaration(EnumDeclaration node)
|
|
{
|
|
var result = CreateTypeDeclarationBase(node);
|
|
result["interfaces"] = node.Interfaces.Select(i => i.Accept(this)).ToList();
|
|
result["constants"] = node.Constants.Select(c => c.Accept(this)).ToList();
|
|
result["members"] = node.Members.Select(m => m.Accept(this)).ToList();
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitAnnotationDeclaration(AnnotationDeclaration node)
|
|
{
|
|
var result = CreateTypeDeclarationBase(node);
|
|
result["members"] = node.Members.Select(m => m.Accept(this)).ToList();
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitFieldDeclaration(FieldDeclaration node)
|
|
{
|
|
var result = CreateMemberDeclarationBase(node);
|
|
result["type"] = node.Type.Accept(this);
|
|
result["variables"] = node.Variables.Select(v => v.Accept(this)).ToList();
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitMethodDeclaration(MethodDeclaration node)
|
|
{
|
|
var result = CreateMemberDeclarationBase(node);
|
|
result["name"] = node.Name;
|
|
result["returnType"] = node.ReturnType?.Accept(this);
|
|
result["typeParameters"] = SerializeTypeParameters(node.TypeParameters);
|
|
result["parameters"] = node.Parameters.Select(p => p.Accept(this)).ToList();
|
|
result["throws"] = node.Throws.Select(t => t.Accept(this)).ToList();
|
|
result["body"] = node.Body?.Accept(this);
|
|
result["isConstructor"] = node.IsConstructor;
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitParameter(Parameter node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["type"] = node.Type.Accept(this);
|
|
result["name"] = node.Name;
|
|
result["isVarArgs"] = node.IsVarArgs;
|
|
result["isFinal"] = node.IsFinal;
|
|
result["annotations"] = SerializeAnnotations(node.Annotations);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitVariableDeclarator(VariableDeclarator node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["name"] = node.Name;
|
|
result["arrayDimensions"] = node.ArrayDimensions;
|
|
result["initializer"] = node.Initializer?.Accept(this);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitPrimitiveType(PrimitiveType node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["kind"] = node.Kind.ToString();
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitClassOrInterfaceType(ClassOrInterfaceType node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["name"] = node.Name;
|
|
result["scope"] = node.Scope?.Accept(this);
|
|
result["typeArguments"] = node.TypeArguments.Select(t => t.Accept(this)).ToList();
|
|
result["annotations"] = SerializeAnnotations(node.Annotations);
|
|
result["fullName"] = node.FullName;
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitArrayType(ArrayType node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["elementType"] = node.ElementType.Accept(this);
|
|
result["dimensions"] = node.Dimensions;
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitTypeParameter(TypeParameter node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["name"] = node.Name;
|
|
result["bounds"] = node.Bounds.Select(b => b.Accept(this)).ToList();
|
|
result["annotations"] = SerializeAnnotations(node.Annotations);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitLiteralExpression(LiteralExpression node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["value"] = node.Value;
|
|
result["kind"] = node.Kind.ToString();
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitIdentifierExpression(IdentifierExpression node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["name"] = node.Name;
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitBinaryExpression(BinaryExpression node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["left"] = node.Left.Accept(this);
|
|
result["operator"] = node.Operator.ToString();
|
|
result["right"] = node.Right.Accept(this);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitUnaryExpression(UnaryExpression node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["operator"] = node.Operator.ToString();
|
|
result["operand"] = node.Operand.Accept(this);
|
|
result["isPrefix"] = node.IsPrefix;
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitMethodCallExpression(MethodCallExpression node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["target"] = node.Target?.Accept(this);
|
|
result["methodName"] = node.MethodName;
|
|
result["typeArguments"] = node.TypeArguments.Select(t => t.Accept(this)).ToList();
|
|
result["arguments"] = node.Arguments.Select(a => a.Accept(this)).ToList();
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitFieldAccessExpression(FieldAccessExpression node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["target"] = node.Target.Accept(this);
|
|
result["fieldName"] = node.FieldName;
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitBlockStatement(BlockStatement node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["statements"] = node.Statements.Select(s => s.Accept(this)).ToList();
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitIfStatement(IfStatement node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["condition"] = node.Condition.Accept(this);
|
|
result["thenStatement"] = node.ThenStatement.Accept(this);
|
|
result["elseStatement"] = node.ElseStatement?.Accept(this);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitWhileStatement(WhileStatement node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["condition"] = node.Condition.Accept(this);
|
|
result["body"] = node.Body.Accept(this);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitForStatement(ForStatement node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["initializers"] = node.Initializers.Select(i => i.Accept(this)).ToList();
|
|
result["condition"] = node.Condition?.Accept(this);
|
|
result["updates"] = node.Updates.Select(u => u.Accept(this)).ToList();
|
|
result["body"] = node.Body.Accept(this);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitReturnStatement(ReturnStatement node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["value"] = node.Value?.Accept(this);
|
|
return result;
|
|
}
|
|
|
|
// Helper methods
|
|
|
|
private Dictionary<string, object?> CreateBaseNode(JavaNode node)
|
|
{
|
|
return new Dictionary<string, object?>
|
|
{
|
|
["nodeType"] = node.GetType().Name,
|
|
["location"] = SerializeLocation(node.Location)
|
|
};
|
|
}
|
|
|
|
private Dictionary<string, object?> CreateTypeDeclarationBase(TypeDeclaration node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["name"] = node.Name;
|
|
result["modifiers"] = SerializeModifiers(node.Modifiers);
|
|
result["annotations"] = SerializeAnnotations(node.Annotations);
|
|
result["typeParameters"] = SerializeTypeParameters(node.TypeParameters);
|
|
result["javaDoc"] = node.JavaDoc?.Accept(this);
|
|
return result;
|
|
}
|
|
|
|
private Dictionary<string, object?> CreateMemberDeclarationBase(MemberDeclaration node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["modifiers"] = SerializeModifiers(node.Modifiers);
|
|
result["annotations"] = SerializeAnnotations(node.Annotations);
|
|
result["javaDoc"] = node.JavaDoc?.Accept(this);
|
|
return result;
|
|
}
|
|
|
|
private List<string> SerializeModifiers(Modifiers modifiers)
|
|
{
|
|
var result = new List<string>();
|
|
foreach (Modifiers value in Enum.GetValues<Modifiers>())
|
|
{
|
|
if (value != Modifiers.None && modifiers.HasFlag(value))
|
|
{
|
|
result.Add(value.ToString().ToLowerInvariant());
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private List<Dictionary<string, object?>> SerializeAnnotations(IReadOnlyList<Annotation> annotations)
|
|
{
|
|
return annotations.Select(a => a.Accept(this)).ToList();
|
|
}
|
|
|
|
private List<Dictionary<string, object?>> SerializeTypeParameters(IReadOnlyList<TypeParameter> typeParameters)
|
|
{
|
|
return typeParameters.Select(tp => tp.Accept(this)).ToList();
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitAnnotation(Annotation node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["type"] = node.Type.Accept(this);
|
|
result["arguments"] = node.Arguments.Select(a => a.Accept(this)).ToList();
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitJavaDoc(JavaDoc node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["content"] = node.Content;
|
|
result["tags"] = node.Tags.Select(t => new Dictionary<string, object?>
|
|
{
|
|
["name"] = t.Name,
|
|
["parameter"] = t.Parameter,
|
|
["description"] = t.Description
|
|
}).ToList();
|
|
return result;
|
|
}
|
|
|
|
// Implement remaining visit methods...
|
|
// (For brevity, showing pattern - all other node types follow similar structure)
|
|
|
|
public override Dictionary<string, object?> VisitThisExpression(ThisExpression node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["qualifier"] = node.Qualifier?.Accept(this);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitNewExpression(NewExpression node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["type"] = node.Type.Accept(this);
|
|
result["arguments"] = node.Arguments.Select(a => a.Accept(this)).ToList();
|
|
result["anonymousClassBody"] = node.AnonymousClassBody?.Accept(this);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitLambdaExpression(LambdaExpression node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["parameters"] = node.Parameters.Select(p => p.Accept(this)).ToList();
|
|
result["body"] = node.Body.Accept(this);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitLambdaParameter(LambdaParameter node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["name"] = node.Name;
|
|
result["type"] = node.Type?.Accept(this);
|
|
result["isFinal"] = node.IsFinal;
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitTryStatement(TryStatement node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["resources"] = node.Resources.Select(r => r.Accept(this)).ToList();
|
|
result["body"] = node.Body.Accept(this);
|
|
result["catchClauses"] = node.CatchClauses.Select(c => c.Accept(this)).ToList();
|
|
result["finallyBlock"] = node.FinallyBlock?.Accept(this);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitResourceDeclaration(ResourceDeclaration node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["type"] = node.Type.Accept(this);
|
|
result["name"] = node.Name;
|
|
result["initializer"] = node.Initializer.Accept(this);
|
|
result["isFinal"] = node.IsFinal;
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitEnumConstant(EnumConstant node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["name"] = node.Name;
|
|
result["arguments"] = node.Arguments.Select(a => a.Accept(this)).ToList();
|
|
result["body"] = node.Body?.Accept(this);
|
|
result["annotations"] = SerializeAnnotations(node.Annotations);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitAnnotationMember(AnnotationMember node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["name"] = node.Name;
|
|
result["type"] = node.Type.Accept(this);
|
|
result["defaultValue"] = node.DefaultValue?.Accept(this);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitSuperExpression(SuperExpression node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["qualifier"] = node.Qualifier?.Accept(this);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitConditionalExpression(ConditionalExpression node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["condition"] = node.Condition.Accept(this);
|
|
result["thenExpression"] = node.ThenExpression.Accept(this);
|
|
result["elseExpression"] = node.ElseExpression.Accept(this);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitArrayAccessExpression(ArrayAccessExpression node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["array"] = node.Array.Accept(this);
|
|
result["index"] = node.Index.Accept(this);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitCastExpression(CastExpression node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["type"] = node.Type.Accept(this);
|
|
result["expression"] = node.Expression.Accept(this);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitInstanceOfExpression(InstanceOfExpression node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["expression"] = node.Expression.Accept(this);
|
|
result["type"] = node.Type.Accept(this);
|
|
result["patternVariable"] = node.PatternVariable;
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitNewArrayExpression(NewArrayExpression node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["elementType"] = node.ElementType.Accept(this);
|
|
result["dimensions"] = node.Dimensions.Select(d => d.Accept(this)).ToList();
|
|
result["initializer"] = node.Initializer?.Accept(this);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitArrayInitializer(ArrayInitializer node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["elements"] = node.Elements.Select(e => e.Accept(this)).ToList();
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitMethodReferenceExpression(MethodReferenceExpression node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["target"] = node.Target.Accept(this);
|
|
result["methodName"] = node.MethodName;
|
|
result["typeArguments"] = node.TypeArguments.Select(t => t.Accept(this)).ToList();
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitClassLiteralExpression(ClassLiteralExpression node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["type"] = node.Type.Accept(this);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitLocalVariableStatement(LocalVariableStatement node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["type"] = node.Type.Accept(this);
|
|
result["variables"] = node.Variables.Select(v => v.Accept(this)).ToList();
|
|
result["isFinal"] = node.IsFinal;
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitExpressionStatement(ExpressionStatement node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["expression"] = node.Expression.Accept(this);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitDoWhileStatement(DoWhileStatement node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["body"] = node.Body.Accept(this);
|
|
result["condition"] = node.Condition.Accept(this);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitForEachStatement(ForEachStatement node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["variableType"] = node.VariableType.Accept(this);
|
|
result["variableName"] = node.VariableName;
|
|
result["iterable"] = node.Iterable.Accept(this);
|
|
result["body"] = node.Body.Accept(this);
|
|
result["isFinal"] = node.IsFinal;
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitSwitchStatement(SwitchStatement node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["selector"] = node.Selector.Accept(this);
|
|
result["cases"] = node.Cases.Select(c => c.Accept(this)).ToList();
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitSwitchCase(SwitchCase node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["labels"] = node.Labels.Select(l => l.Accept(this)).ToList();
|
|
result["statements"] = node.Statements.Select(s => s.Accept(this)).ToList();
|
|
result["isDefault"] = node.IsDefault;
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitBreakStatement(BreakStatement node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["label"] = node.Label;
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitContinueStatement(ContinueStatement node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["label"] = node.Label;
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitThrowStatement(ThrowStatement node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["exception"] = node.Exception.Accept(this);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitCatchClause(CatchClause node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["exceptionTypes"] = node.ExceptionTypes.Select(t => t.Accept(this)).ToList();
|
|
result["variableName"] = node.VariableName;
|
|
result["body"] = node.Body.Accept(this);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitSynchronizedStatement(SynchronizedStatement node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["lock"] = node.Lock.Accept(this);
|
|
result["body"] = node.Body.Accept(this);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitLabeledStatement(LabeledStatement node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["label"] = node.Label;
|
|
result["statement"] = node.Statement.Accept(this);
|
|
return result;
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitEmptyStatement(EmptyStatement node)
|
|
{
|
|
return CreateBaseNode(node);
|
|
}
|
|
|
|
public override Dictionary<string, object?> VisitAssertStatement(AssertStatement node)
|
|
{
|
|
var result = CreateBaseNode(node);
|
|
result["condition"] = node.Condition.Accept(this);
|
|
result["message"] = node.Message?.Accept(this);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Visitor that deserializes JSON to AST nodes.
|
|
/// </summary>
|
|
internal class JsonDeserializationVisitor
|
|
{
|
|
public JavaNode Deserialize(JsonElement element)
|
|
{
|
|
if (!element.TryGetProperty("nodeType", out var nodeTypeElement))
|
|
{
|
|
throw new JsonException("Missing nodeType property");
|
|
}
|
|
|
|
var nodeType = nodeTypeElement.GetString() ?? throw new JsonException("nodeType is null");
|
|
var location = DeserializeLocation(element.GetProperty("location"));
|
|
|
|
return nodeType switch
|
|
{
|
|
"CompilationUnit" => DeserializeCompilationUnit(element, location),
|
|
"PackageDeclaration" => DeserializePackageDeclaration(element, location),
|
|
"ImportDeclaration" => DeserializeImportDeclaration(element, location),
|
|
"ClassDeclaration" => DeserializeClassDeclaration(element, location),
|
|
"InterfaceDeclaration" => DeserializeInterfaceDeclaration(element, location),
|
|
"EnumDeclaration" => DeserializeEnumDeclaration(element, location),
|
|
"AnnotationDeclaration" => DeserializeAnnotationDeclaration(element, location),
|
|
"FieldDeclaration" => DeserializeFieldDeclaration(element, location),
|
|
"MethodDeclaration" => DeserializeMethodDeclaration(element, location),
|
|
"Parameter" => DeserializeParameter(element, location),
|
|
"VariableDeclarator" => DeserializeVariableDeclarator(element, location),
|
|
"PrimitiveType" => DeserializePrimitiveType(element, location),
|
|
"ClassOrInterfaceType" => DeserializeClassOrInterfaceType(element, location),
|
|
"ArrayType" => DeserializeArrayType(element, location),
|
|
"TypeParameter" => DeserializeTypeParameter(element, location),
|
|
"LiteralExpression" => DeserializeLiteralExpression(element, location),
|
|
"IdentifierExpression" => DeserializeIdentifierExpression(element, location),
|
|
"BinaryExpression" => DeserializeBinaryExpression(element, location),
|
|
"UnaryExpression" => DeserializeUnaryExpression(element, location),
|
|
"MethodCallExpression" => DeserializeMethodCallExpression(element, location),
|
|
"FieldAccessExpression" => DeserializeFieldAccessExpression(element, location),
|
|
"BlockStatement" => DeserializeBlockStatement(element, location),
|
|
"IfStatement" => DeserializeIfStatement(element, location),
|
|
"WhileStatement" => DeserializeWhileStatement(element, location),
|
|
"ForStatement" => DeserializeForStatement(element, location),
|
|
"ReturnStatement" => DeserializeReturnStatement(element, location),
|
|
"ThisExpression" => DeserializeThisExpression(element, location),
|
|
"NewExpression" => DeserializeNewExpression(element, location),
|
|
"LambdaExpression" => DeserializeLambdaExpression(element, location),
|
|
"TryStatement" => DeserializeTryStatement(element, location),
|
|
"Annotation" => DeserializeAnnotation(element, location),
|
|
"JavaDoc" => DeserializeJavaDoc(element, location),
|
|
"EnumConstant" => DeserializeEnumConstant(element, location),
|
|
"AnnotationMember" => DeserializeAnnotationMember(element, location),
|
|
"SuperExpression" => DeserializeSuperExpression(element, location),
|
|
"ConditionalExpression" => DeserializeConditionalExpression(element, location),
|
|
"ArrayAccessExpression" => DeserializeArrayAccessExpression(element, location),
|
|
"CastExpression" => DeserializeCastExpression(element, location),
|
|
"InstanceOfExpression" => DeserializeInstanceOfExpression(element, location),
|
|
"NewArrayExpression" => DeserializeNewArrayExpression(element, location),
|
|
"ArrayInitializer" => DeserializeArrayInitializer(element, location),
|
|
"MethodReferenceExpression" => DeserializeMethodReferenceExpression(element, location),
|
|
"ClassLiteralExpression" => DeserializeClassLiteralExpression(element, location),
|
|
"LocalVariableStatement" => DeserializeLocalVariableStatement(element, location),
|
|
"ExpressionStatement" => DeserializeExpressionStatement(element, location),
|
|
"DoWhileStatement" => DeserializeDoWhileStatement(element, location),
|
|
"ForEachStatement" => DeserializeForEachStatement(element, location),
|
|
"SwitchStatement" => DeserializeSwitchStatement(element, location),
|
|
"BreakStatement" => DeserializeBreakStatement(element, location),
|
|
"ContinueStatement" => DeserializeContinueStatement(element, location),
|
|
"ThrowStatement" => DeserializeThrowStatement(element, location),
|
|
"SynchronizedStatement" => DeserializeSynchronizedStatement(element, location),
|
|
"LabeledStatement" => DeserializeLabeledStatement(element, location),
|
|
"EmptyStatement" => DeserializeEmptyStatement(element, location),
|
|
"AssertStatement" => DeserializeAssertStatement(element, location),
|
|
"CatchClause" => DeserializeCatchClause(element, location),
|
|
"SwitchCase" => DeserializeSwitchCase(element, location),
|
|
"ResourceDeclaration" => DeserializeResourceDeclaration(element, location),
|
|
"LambdaParameter" => DeserializeLambdaParameter(element, location),
|
|
_ => throw new JsonException($"Unknown node type: {nodeType}")
|
|
};
|
|
}
|
|
|
|
private SourceRange DeserializeLocation(JsonElement element)
|
|
{
|
|
var start = element.GetProperty("start");
|
|
var end = element.GetProperty("end");
|
|
|
|
return new SourceRange(
|
|
new SourceLocation(
|
|
start.GetProperty("line").GetInt32(),
|
|
start.GetProperty("column").GetInt32(),
|
|
start.GetProperty("position").GetInt32(),
|
|
0
|
|
),
|
|
new SourceLocation(
|
|
end.GetProperty("line").GetInt32(),
|
|
end.GetProperty("column").GetInt32(),
|
|
end.GetProperty("position").GetInt32(),
|
|
0
|
|
)
|
|
);
|
|
}
|
|
|
|
private CompilationUnit DeserializeCompilationUnit(JsonElement element, SourceRange location)
|
|
{
|
|
var package = element.TryGetProperty("package", out var packageEl) && packageEl.ValueKind != JsonValueKind.Null
|
|
? Deserialize(packageEl) as PackageDeclaration
|
|
: null;
|
|
|
|
var imports = DeserializeList<ImportDeclaration>(element.GetProperty("imports"));
|
|
var types = DeserializeList<TypeDeclaration>(element.GetProperty("types"));
|
|
|
|
return new CompilationUnit(location, package, imports, types);
|
|
}
|
|
|
|
private PackageDeclaration DeserializePackageDeclaration(JsonElement element, SourceRange location)
|
|
{
|
|
var packageName = element.GetProperty("packageName").GetString() ?? throw new JsonException("packageName is null");
|
|
var annotations = DeserializeAnnotations(element.GetProperty("annotations"));
|
|
return new PackageDeclaration(location, packageName, annotations);
|
|
}
|
|
|
|
private ImportDeclaration DeserializeImportDeclaration(JsonElement element, SourceRange location)
|
|
{
|
|
var importPath = element.GetProperty("importPath").GetString() ?? throw new JsonException("importPath is null");
|
|
var isStatic = element.GetProperty("isStatic").GetBoolean();
|
|
var isWildcard = element.GetProperty("isWildcard").GetBoolean();
|
|
return new ImportDeclaration(location, importPath, isStatic, isWildcard);
|
|
}
|
|
|
|
private ClassDeclaration DeserializeClassDeclaration(JsonElement element, SourceRange location)
|
|
{
|
|
var name = element.GetProperty("name").GetString() ?? throw new JsonException("name is null");
|
|
var modifiers = DeserializeModifiers(element.GetProperty("modifiers"));
|
|
var annotations = DeserializeAnnotations(element.GetProperty("annotations"));
|
|
var typeParameters = DeserializeList<TypeParameter>(element.GetProperty("typeParameters"));
|
|
var javaDoc = element.TryGetProperty("javaDoc", out var javaDocEl) && javaDocEl.ValueKind != JsonValueKind.Null
|
|
? Deserialize(javaDocEl) as JavaDoc
|
|
: null;
|
|
|
|
var superClass = element.TryGetProperty("superClass", out var superClassEl) && superClassEl.ValueKind != JsonValueKind.Null
|
|
? Deserialize(superClassEl) as ClassOrInterfaceType
|
|
: null;
|
|
|
|
var interfaces = DeserializeList<ClassOrInterfaceType>(element.GetProperty("interfaces"));
|
|
var members = DeserializeList<MemberDeclaration>(element.GetProperty("members"));
|
|
var nestedTypes = DeserializeList<TypeDeclaration>(element.GetProperty("nestedTypes"));
|
|
var isRecord = element.GetProperty("isRecord").GetBoolean();
|
|
|
|
return new ClassDeclaration(location, name, modifiers, annotations, typeParameters, superClass, interfaces, members, nestedTypes, javaDoc, isRecord);
|
|
}
|
|
|
|
private InterfaceDeclaration DeserializeInterfaceDeclaration(JsonElement element, SourceRange location)
|
|
{
|
|
var name = element.GetProperty("name").GetString() ?? throw new JsonException("name is null");
|
|
var modifiers = DeserializeModifiers(element.GetProperty("modifiers"));
|
|
var annotations = DeserializeAnnotations(element.GetProperty("annotations"));
|
|
var typeParameters = DeserializeList<TypeParameter>(element.GetProperty("typeParameters"));
|
|
var javaDoc = element.TryGetProperty("javaDoc", out var javaDocEl) && javaDocEl.ValueKind != JsonValueKind.Null
|
|
? Deserialize(javaDocEl) as JavaDoc
|
|
: null;
|
|
|
|
var extendedInterfaces = DeserializeList<ClassOrInterfaceType>(element.GetProperty("extendedInterfaces"));
|
|
var members = DeserializeList<MemberDeclaration>(element.GetProperty("members"));
|
|
var nestedTypes = DeserializeList<TypeDeclaration>(element.GetProperty("nestedTypes"));
|
|
|
|
return new InterfaceDeclaration(location, name, modifiers, annotations, typeParameters, extendedInterfaces, members, nestedTypes, javaDoc);
|
|
}
|
|
|
|
private EnumDeclaration DeserializeEnumDeclaration(JsonElement element, SourceRange location)
|
|
{
|
|
var name = element.GetProperty("name").GetString() ?? throw new JsonException("name is null");
|
|
var modifiers = DeserializeModifiers(element.GetProperty("modifiers"));
|
|
var annotations = DeserializeAnnotations(element.GetProperty("annotations"));
|
|
var javaDoc = element.TryGetProperty("javaDoc", out var javaDocEl) && javaDocEl.ValueKind != JsonValueKind.Null
|
|
? Deserialize(javaDocEl) as JavaDoc
|
|
: null;
|
|
|
|
var interfaces = DeserializeList<ClassOrInterfaceType>(element.GetProperty("interfaces"));
|
|
var constants = DeserializeList<EnumConstant>(element.GetProperty("constants"));
|
|
var members = DeserializeList<MemberDeclaration>(element.GetProperty("members"));
|
|
var nestedTypes = DeserializeList<TypeDeclaration>(element.GetProperty("nestedTypes"));
|
|
|
|
return new EnumDeclaration(location, name, modifiers, annotations, interfaces, constants, members, nestedTypes, javaDoc);
|
|
}
|
|
|
|
private AnnotationDeclaration DeserializeAnnotationDeclaration(JsonElement element, SourceRange location)
|
|
{
|
|
var name = element.GetProperty("name").GetString() ?? throw new JsonException("name is null");
|
|
var modifiers = DeserializeModifiers(element.GetProperty("modifiers"));
|
|
var annotations = DeserializeAnnotations(element.GetProperty("annotations"));
|
|
var javaDoc = element.TryGetProperty("javaDoc", out var javaDocEl) && javaDocEl.ValueKind != JsonValueKind.Null
|
|
? Deserialize(javaDocEl) as JavaDoc
|
|
: null;
|
|
|
|
var members = DeserializeList<AnnotationMember>(element.GetProperty("members"));
|
|
var nestedTypes = DeserializeList<TypeDeclaration>(element.GetProperty("nestedTypes"));
|
|
|
|
return new AnnotationDeclaration(location, name, modifiers, annotations, members, nestedTypes, javaDoc);
|
|
}
|
|
|
|
private FieldDeclaration DeserializeFieldDeclaration(JsonElement element, SourceRange location)
|
|
{
|
|
var modifiers = DeserializeModifiers(element.GetProperty("modifiers"));
|
|
var annotations = DeserializeAnnotations(element.GetProperty("annotations"));
|
|
var javaDoc = element.TryGetProperty("javaDoc", out var javaDocEl) && javaDocEl.ValueKind != JsonValueKind.Null
|
|
? Deserialize(javaDocEl) as JavaDoc
|
|
: null;
|
|
|
|
var type = Deserialize(element.GetProperty("type")) as TypeReference ?? throw new JsonException("type is not TypeReference");
|
|
var variables = DeserializeList<VariableDeclarator>(element.GetProperty("variables"));
|
|
|
|
return new FieldDeclaration(location, modifiers, annotations, type, variables, javaDoc);
|
|
}
|
|
|
|
private MethodDeclaration DeserializeMethodDeclaration(JsonElement element, SourceRange location)
|
|
{
|
|
var modifiers = DeserializeModifiers(element.GetProperty("modifiers"));
|
|
var annotations = DeserializeAnnotations(element.GetProperty("annotations"));
|
|
var javaDoc = element.TryGetProperty("javaDoc", out var javaDocEl) && javaDocEl.ValueKind != JsonValueKind.Null
|
|
? Deserialize(javaDocEl) as JavaDoc
|
|
: null;
|
|
|
|
var name = element.GetProperty("name").GetString() ?? throw new JsonException("name is null");
|
|
var returnType = element.TryGetProperty("returnType", out var returnTypeEl) && returnTypeEl.ValueKind != JsonValueKind.Null
|
|
? Deserialize(returnTypeEl) as TypeReference
|
|
: null;
|
|
|
|
var typeParameters = DeserializeList<TypeParameter>(element.GetProperty("typeParameters"));
|
|
var parameters = DeserializeList<Parameter>(element.GetProperty("parameters"));
|
|
var throws = DeserializeList<ClassOrInterfaceType>(element.GetProperty("throws"));
|
|
var body = element.TryGetProperty("body", out var bodyEl) && bodyEl.ValueKind != JsonValueKind.Null
|
|
? Deserialize(bodyEl) as BlockStatement
|
|
: null;
|
|
|
|
var isConstructor = element.GetProperty("isConstructor").GetBoolean();
|
|
|
|
return new MethodDeclaration(location, name, modifiers, annotations, returnType, typeParameters, parameters, throws, body, javaDoc, isConstructor);
|
|
}
|
|
|
|
private Parameter DeserializeParameter(JsonElement element, SourceRange location)
|
|
{
|
|
var type = Deserialize(element.GetProperty("type")) as TypeReference ?? throw new JsonException("type is not TypeReference");
|
|
var name = element.GetProperty("name").GetString() ?? throw new JsonException("name is null");
|
|
var isVarArgs = element.GetProperty("isVarArgs").GetBoolean();
|
|
var isFinal = element.GetProperty("isFinal").GetBoolean();
|
|
var annotations = DeserializeAnnotations(element.GetProperty("annotations"));
|
|
|
|
return new Parameter(location, type, name, isVarArgs, isFinal, annotations);
|
|
}
|
|
|
|
private VariableDeclarator DeserializeVariableDeclarator(JsonElement element, SourceRange location)
|
|
{
|
|
var name = element.GetProperty("name").GetString() ?? throw new JsonException("name is null");
|
|
var arrayDimensions = element.GetProperty("arrayDimensions").GetInt32();
|
|
var initializer = element.TryGetProperty("initializer", out var initializerEl) && initializerEl.ValueKind != JsonValueKind.Null
|
|
? Deserialize(initializerEl) as Expression
|
|
: null;
|
|
|
|
return new VariableDeclarator(location, name, arrayDimensions, initializer);
|
|
}
|
|
|
|
private PrimitiveType DeserializePrimitiveType(JsonElement element, SourceRange location)
|
|
{
|
|
var kindStr = element.GetProperty("kind").GetString() ?? throw new JsonException("kind is null");
|
|
var kind = Enum.Parse<PrimitiveTypeKind>(kindStr);
|
|
return new PrimitiveType(location, kind);
|
|
}
|
|
|
|
private ClassOrInterfaceType DeserializeClassOrInterfaceType(JsonElement element, SourceRange location)
|
|
{
|
|
var name = element.GetProperty("name").GetString() ?? throw new JsonException("name is null");
|
|
var scope = element.TryGetProperty("scope", out var scopeEl) && scopeEl.ValueKind != JsonValueKind.Null
|
|
? Deserialize(scopeEl) as ClassOrInterfaceType
|
|
: null;
|
|
|
|
var typeArguments = DeserializeList<TypeArgument>(element.GetProperty("typeArguments"));
|
|
var annotations = DeserializeAnnotations(element.GetProperty("annotations"));
|
|
|
|
return new ClassOrInterfaceType(location, name, scope, typeArguments, annotations);
|
|
}
|
|
|
|
private ArrayType DeserializeArrayType(JsonElement element, SourceRange location)
|
|
{
|
|
var elementType = Deserialize(element.GetProperty("elementType")) as TypeReference ?? throw new JsonException("elementType is not TypeReference");
|
|
var dimensions = element.GetProperty("dimensions").GetInt32();
|
|
return new ArrayType(location, elementType, dimensions);
|
|
}
|
|
|
|
private TypeParameter DeserializeTypeParameter(JsonElement element, SourceRange location)
|
|
{
|
|
var name = element.GetProperty("name").GetString() ?? throw new JsonException("name is null");
|
|
var bounds = DeserializeList<TypeReference>(element.GetProperty("bounds"));
|
|
var annotations = DeserializeAnnotations(element.GetProperty("annotations"));
|
|
return new TypeParameter(location, name, bounds, annotations);
|
|
}
|
|
|
|
private LiteralExpression DeserializeLiteralExpression(JsonElement element, SourceRange location)
|
|
{
|
|
var value = element.GetProperty("value");
|
|
var kindStr = element.GetProperty("kind").GetString() ?? throw new JsonException("kind is null");
|
|
var kind = Enum.Parse<LiteralKind>(kindStr);
|
|
|
|
object? literalValue = kind switch
|
|
{
|
|
LiteralKind.Integer => value.GetInt32(),
|
|
LiteralKind.Long => value.GetInt64(),
|
|
LiteralKind.Float => value.GetSingle(),
|
|
LiteralKind.Double => value.GetDouble(),
|
|
LiteralKind.Boolean => value.GetBoolean(),
|
|
LiteralKind.Character => value.GetString()?.FirstOrDefault(),
|
|
LiteralKind.String => value.GetString(),
|
|
LiteralKind.Null => null,
|
|
_ => throw new JsonException($"Unknown literal kind: {kind}")
|
|
};
|
|
|
|
return new LiteralExpression(location, literalValue, kind);
|
|
}
|
|
|
|
private IdentifierExpression DeserializeIdentifierExpression(JsonElement element, SourceRange location)
|
|
{
|
|
var name = element.GetProperty("name").GetString() ?? throw new JsonException("name is null");
|
|
return new IdentifierExpression(location, name);
|
|
}
|
|
|
|
private BinaryExpression DeserializeBinaryExpression(JsonElement element, SourceRange location)
|
|
{
|
|
var left = Deserialize(element.GetProperty("left")) as Expression ?? throw new JsonException("left is not Expression");
|
|
var operatorStr = element.GetProperty("operator").GetString() ?? throw new JsonException("operator is null");
|
|
var @operator = Enum.Parse<BinaryOperator>(operatorStr);
|
|
var right = Deserialize(element.GetProperty("right")) as Expression ?? throw new JsonException("right is not Expression");
|
|
|
|
return new BinaryExpression(location, left, @operator, right);
|
|
}
|
|
|
|
private UnaryExpression DeserializeUnaryExpression(JsonElement element, SourceRange location)
|
|
{
|
|
var operatorStr = element.GetProperty("operator").GetString() ?? throw new JsonException("operator is null");
|
|
var @operator = Enum.Parse<UnaryOperator>(operatorStr);
|
|
var operand = Deserialize(element.GetProperty("operand")) as Expression ?? throw new JsonException("operand is not Expression");
|
|
var isPrefix = element.GetProperty("isPrefix").GetBoolean();
|
|
|
|
return new UnaryExpression(location, @operator, operand, isPrefix);
|
|
}
|
|
|
|
private MethodCallExpression DeserializeMethodCallExpression(JsonElement element, SourceRange location)
|
|
{
|
|
var target = element.TryGetProperty("target", out var targetEl) && targetEl.ValueKind != JsonValueKind.Null
|
|
? Deserialize(targetEl) as Expression
|
|
: null;
|
|
|
|
var methodName = element.GetProperty("methodName").GetString() ?? throw new JsonException("methodName is null");
|
|
var typeArguments = DeserializeList<TypeArgument>(element.GetProperty("typeArguments"));
|
|
var arguments = DeserializeList<Expression>(element.GetProperty("arguments"));
|
|
|
|
return new MethodCallExpression(location, target, methodName, typeArguments, arguments);
|
|
}
|
|
|
|
private FieldAccessExpression DeserializeFieldAccessExpression(JsonElement element, SourceRange location)
|
|
{
|
|
var target = Deserialize(element.GetProperty("target")) as Expression ?? throw new JsonException("target is not Expression");
|
|
var fieldName = element.GetProperty("fieldName").GetString() ?? throw new JsonException("fieldName is null");
|
|
return new FieldAccessExpression(location, target, fieldName);
|
|
}
|
|
|
|
private BlockStatement DeserializeBlockStatement(JsonElement element, SourceRange location)
|
|
{
|
|
var statements = DeserializeList<Statement>(element.GetProperty("statements"));
|
|
return new BlockStatement(location, statements);
|
|
}
|
|
|
|
private IfStatement DeserializeIfStatement(JsonElement element, SourceRange location)
|
|
{
|
|
var condition = Deserialize(element.GetProperty("condition")) as Expression ?? throw new JsonException("condition is not Expression");
|
|
var thenStatement = Deserialize(element.GetProperty("thenStatement")) as Statement ?? throw new JsonException("thenStatement is not Statement");
|
|
var elseStatement = element.TryGetProperty("elseStatement", out var elseEl) && elseEl.ValueKind != JsonValueKind.Null
|
|
? Deserialize(elseEl) as Statement
|
|
: null;
|
|
|
|
return new IfStatement(location, condition, thenStatement, elseStatement);
|
|
}
|
|
|
|
private WhileStatement DeserializeWhileStatement(JsonElement element, SourceRange location)
|
|
{
|
|
var condition = Deserialize(element.GetProperty("condition")) as Expression ?? throw new JsonException("condition is not Expression");
|
|
var body = Deserialize(element.GetProperty("body")) as Statement ?? throw new JsonException("body is not Statement");
|
|
return new WhileStatement(location, condition, body);
|
|
}
|
|
|
|
private ForStatement DeserializeForStatement(JsonElement element, SourceRange location)
|
|
{
|
|
var initializers = DeserializeList<Statement>(element.GetProperty("initializers"));
|
|
var condition = element.TryGetProperty("condition", out var conditionEl) && conditionEl.ValueKind != JsonValueKind.Null
|
|
? Deserialize(conditionEl) as Expression
|
|
: null;
|
|
var updates = DeserializeList<Expression>(element.GetProperty("updates"));
|
|
var body = Deserialize(element.GetProperty("body")) as Statement ?? throw new JsonException("body is not Statement");
|
|
|
|
return new ForStatement(location, initializers, condition, updates, body);
|
|
}
|
|
|
|
private ReturnStatement DeserializeReturnStatement(JsonElement element, SourceRange location)
|
|
{
|
|
var value = element.TryGetProperty("value", out var valueEl) && valueEl.ValueKind != JsonValueKind.Null
|
|
? Deserialize(valueEl) as Expression
|
|
: null;
|
|
return new ReturnStatement(location, value);
|
|
}
|
|
|
|
private ThisExpression DeserializeThisExpression(JsonElement element, SourceRange location)
|
|
{
|
|
var qualifier = element.TryGetProperty("qualifier", out var qualifierEl) && qualifierEl.ValueKind != JsonValueKind.Null
|
|
? Deserialize(qualifierEl) as Expression
|
|
: null;
|
|
return new ThisExpression(location, qualifier);
|
|
}
|
|
|
|
private NewExpression DeserializeNewExpression(JsonElement element, SourceRange location)
|
|
{
|
|
var type = Deserialize(element.GetProperty("type")) as ClassOrInterfaceType ?? throw new JsonException("type is not ClassOrInterfaceType");
|
|
var arguments = DeserializeList<Expression>(element.GetProperty("arguments"));
|
|
var anonymousClassBody = element.TryGetProperty("anonymousClassBody", out var bodyEl) && bodyEl.ValueKind != JsonValueKind.Null
|
|
? Deserialize(bodyEl) as ClassDeclaration
|
|
: null;
|
|
|
|
return new NewExpression(location, type, arguments, anonymousClassBody);
|
|
}
|
|
|
|
private LambdaExpression DeserializeLambdaExpression(JsonElement element, SourceRange location)
|
|
{
|
|
var parameters = DeserializeList<LambdaParameter>(element.GetProperty("parameters"));
|
|
var body = Deserialize(element.GetProperty("body")) ?? throw new JsonException("body is null");
|
|
return new LambdaExpression(location, parameters, body);
|
|
}
|
|
|
|
private TryStatement DeserializeTryStatement(JsonElement element, SourceRange location)
|
|
{
|
|
var resources = DeserializeList<ResourceDeclaration>(element.GetProperty("resources"));
|
|
var body = Deserialize(element.GetProperty("body")) as BlockStatement ?? throw new JsonException("body is not BlockStatement");
|
|
var catchClauses = DeserializeList<CatchClause>(element.GetProperty("catchClauses"));
|
|
var finallyBlock = element.TryGetProperty("finallyBlock", out var finallyEl) && finallyEl.ValueKind != JsonValueKind.Null
|
|
? Deserialize(finallyEl) as BlockStatement
|
|
: null;
|
|
|
|
return new TryStatement(location, resources, body, catchClauses, finallyBlock);
|
|
}
|
|
|
|
private Annotation DeserializeAnnotation(JsonElement element, SourceRange location)
|
|
{
|
|
var type = Deserialize(element.GetProperty("type")) as ClassOrInterfaceType ?? throw new JsonException("type is not ClassOrInterfaceType");
|
|
var arguments = DeserializeList<AnnotationArgument>(element.GetProperty("arguments"));
|
|
return new Annotation(location, type, arguments);
|
|
}
|
|
|
|
private JavaDoc DeserializeJavaDoc(JsonElement element, SourceRange location)
|
|
{
|
|
var content = element.GetProperty("content").GetString() ?? throw new JsonException("content is null");
|
|
var tags = element.GetProperty("tags").EnumerateArray().Select(tagEl =>
|
|
{
|
|
var name = tagEl.GetProperty("name").GetString() ?? "";
|
|
var parameter = tagEl.TryGetProperty("parameter", out var paramEl) ? paramEl.GetString() : null;
|
|
var description = tagEl.TryGetProperty("description", out var descEl) ? descEl.GetString() : null;
|
|
return new JavaDocTag(name, parameter, description ?? "");
|
|
}).ToList();
|
|
|
|
return new JavaDoc(location, content, tags);
|
|
}
|
|
|
|
private List<T> DeserializeList<T>(JsonElement element) where T : JavaNode
|
|
{
|
|
return element.EnumerateArray()
|
|
.Select(item => Deserialize(item))
|
|
.OfType<T>()
|
|
.ToList();
|
|
}
|
|
|
|
private List<Annotation> DeserializeAnnotations(JsonElement element)
|
|
{
|
|
return element.EnumerateArray()
|
|
.Select(item => Deserialize(item) as Annotation)
|
|
.Where(ann => ann != null)
|
|
.Cast<Annotation>()
|
|
.ToList();
|
|
}
|
|
|
|
private Modifiers DeserializeModifiers(JsonElement element)
|
|
{
|
|
var modifiers = Modifiers.None;
|
|
foreach (var modifierStr in element.EnumerateArray())
|
|
{
|
|
var str = modifierStr.GetString();
|
|
if (str != null && Enum.TryParse<Modifiers>(str, true, out var modifier))
|
|
{
|
|
modifiers |= modifier;
|
|
}
|
|
}
|
|
return modifiers;
|
|
}
|
|
|
|
// Additional node deserializers
|
|
|
|
private EnumConstant DeserializeEnumConstant(JsonElement element, SourceRange location)
|
|
{
|
|
var name = element.GetProperty("name").GetString() ?? throw new JsonException("name is null");
|
|
var arguments = DeserializeList<Expression>(element.GetProperty("arguments"));
|
|
var body = element.TryGetProperty("body", out var bodyEl) && bodyEl.ValueKind != JsonValueKind.Null
|
|
? Deserialize(bodyEl) as ClassDeclaration
|
|
: null;
|
|
var annotations = DeserializeAnnotations(element.GetProperty("annotations"));
|
|
|
|
return new EnumConstant(location, name, annotations, arguments, body);
|
|
}
|
|
|
|
private AnnotationMember DeserializeAnnotationMember(JsonElement element, SourceRange location)
|
|
{
|
|
var name = element.GetProperty("name").GetString() ?? throw new JsonException("name is null");
|
|
var type = Deserialize(element.GetProperty("type")) as TypeReference ?? throw new JsonException("type is not TypeReference");
|
|
var defaultValue = element.TryGetProperty("defaultValue", out var defaultEl) && defaultEl.ValueKind != JsonValueKind.Null
|
|
? Deserialize(defaultEl) as Expression
|
|
: null;
|
|
|
|
return new AnnotationMember(location, name, type, defaultValue);
|
|
}
|
|
|
|
private SuperExpression DeserializeSuperExpression(JsonElement element, SourceRange location)
|
|
{
|
|
var qualifier = element.TryGetProperty("qualifier", out var qualifierEl) && qualifierEl.ValueKind != JsonValueKind.Null
|
|
? Deserialize(qualifierEl) as Expression
|
|
: null;
|
|
return new SuperExpression(location, qualifier);
|
|
}
|
|
|
|
private ConditionalExpression DeserializeConditionalExpression(JsonElement element, SourceRange location)
|
|
{
|
|
var condition = Deserialize(element.GetProperty("condition")) as Expression ?? throw new JsonException("condition is not Expression");
|
|
var thenExpression = Deserialize(element.GetProperty("thenExpression")) as Expression ?? throw new JsonException("thenExpression is not Expression");
|
|
var elseExpression = Deserialize(element.GetProperty("elseExpression")) as Expression ?? throw new JsonException("elseExpression is not Expression");
|
|
|
|
return new ConditionalExpression(location, condition, thenExpression, elseExpression);
|
|
}
|
|
|
|
private ArrayAccessExpression DeserializeArrayAccessExpression(JsonElement element, SourceRange location)
|
|
{
|
|
var array = Deserialize(element.GetProperty("array")) as Expression ?? throw new JsonException("array is not Expression");
|
|
var index = Deserialize(element.GetProperty("index")) as Expression ?? throw new JsonException("index is not Expression");
|
|
|
|
return new ArrayAccessExpression(location, array, index);
|
|
}
|
|
|
|
private CastExpression DeserializeCastExpression(JsonElement element, SourceRange location)
|
|
{
|
|
var type = Deserialize(element.GetProperty("type")) as TypeReference ?? throw new JsonException("type is not TypeReference");
|
|
var expression = Deserialize(element.GetProperty("expression")) as Expression ?? throw new JsonException("expression is not Expression");
|
|
|
|
return new CastExpression(location, type, expression);
|
|
}
|
|
|
|
private InstanceOfExpression DeserializeInstanceOfExpression(JsonElement element, SourceRange location)
|
|
{
|
|
var expression = Deserialize(element.GetProperty("expression")) as Expression ?? throw new JsonException("expression is not Expression");
|
|
var type = Deserialize(element.GetProperty("type")) as TypeReference ?? throw new JsonException("type is not TypeReference");
|
|
var patternVariable = element.TryGetProperty("patternVariable", out var patternEl) && patternEl.ValueKind != JsonValueKind.Null
|
|
? patternEl.GetString()
|
|
: null;
|
|
|
|
return new InstanceOfExpression(location, expression, type, patternVariable);
|
|
}
|
|
|
|
private NewArrayExpression DeserializeNewArrayExpression(JsonElement element, SourceRange location)
|
|
{
|
|
var elementType = Deserialize(element.GetProperty("elementType")) as TypeReference ?? throw new JsonException("elementType is not TypeReference");
|
|
var dimensions = DeserializeList<Expression>(element.GetProperty("dimensions"));
|
|
var initializer = element.TryGetProperty("initializer", out var initEl) && initEl.ValueKind != JsonValueKind.Null
|
|
? Deserialize(initEl) as ArrayInitializer
|
|
: null;
|
|
|
|
return new NewArrayExpression(location, elementType, dimensions, initializer);
|
|
}
|
|
|
|
private ArrayInitializer DeserializeArrayInitializer(JsonElement element, SourceRange location)
|
|
{
|
|
var elements = DeserializeList<Expression>(element.GetProperty("elements"));
|
|
return new ArrayInitializer(location, elements);
|
|
}
|
|
|
|
private MethodReferenceExpression DeserializeMethodReferenceExpression(JsonElement element, SourceRange location)
|
|
{
|
|
var target = Deserialize(element.GetProperty("target")) as Expression ?? throw new JsonException("target is not Expression");
|
|
var methodName = element.GetProperty("methodName").GetString() ?? throw new JsonException("methodName is null");
|
|
var typeArguments = DeserializeList<TypeArgument>(element.GetProperty("typeArguments"));
|
|
|
|
return new MethodReferenceExpression(location, target, methodName, typeArguments);
|
|
}
|
|
|
|
private ClassLiteralExpression DeserializeClassLiteralExpression(JsonElement element, SourceRange location)
|
|
{
|
|
var type = Deserialize(element.GetProperty("type")) as TypeReference ?? throw new JsonException("type is not TypeReference");
|
|
return new ClassLiteralExpression(location, type);
|
|
}
|
|
|
|
private LocalVariableStatement DeserializeLocalVariableStatement(JsonElement element, SourceRange location)
|
|
{
|
|
var type = Deserialize(element.GetProperty("type")) as TypeReference ?? throw new JsonException("type is not TypeReference");
|
|
var variables = DeserializeList<VariableDeclarator>(element.GetProperty("variables"));
|
|
var isFinal = element.GetProperty("isFinal").GetBoolean();
|
|
|
|
return new LocalVariableStatement(location, type, variables, isFinal);
|
|
}
|
|
|
|
private ExpressionStatement DeserializeExpressionStatement(JsonElement element, SourceRange location)
|
|
{
|
|
var expression = Deserialize(element.GetProperty("expression")) as Expression ?? throw new JsonException("expression is not Expression");
|
|
return new ExpressionStatement(location, expression);
|
|
}
|
|
|
|
private DoWhileStatement DeserializeDoWhileStatement(JsonElement element, SourceRange location)
|
|
{
|
|
var body = Deserialize(element.GetProperty("body")) as Statement ?? throw new JsonException("body is not Statement");
|
|
var condition = Deserialize(element.GetProperty("condition")) as Expression ?? throw new JsonException("condition is not Expression");
|
|
|
|
return new DoWhileStatement(location, body, condition);
|
|
}
|
|
|
|
private ForEachStatement DeserializeForEachStatement(JsonElement element, SourceRange location)
|
|
{
|
|
var variableType = Deserialize(element.GetProperty("variableType")) as TypeReference ?? throw new JsonException("variableType is not TypeReference");
|
|
var variableName = element.GetProperty("variableName").GetString() ?? throw new JsonException("variableName is null");
|
|
var iterable = Deserialize(element.GetProperty("iterable")) as Expression ?? throw new JsonException("iterable is not Expression");
|
|
var body = Deserialize(element.GetProperty("body")) as Statement ?? throw new JsonException("body is not Statement");
|
|
var isFinal = element.GetProperty("isFinal").GetBoolean();
|
|
|
|
return new ForEachStatement(location, variableType, variableName, iterable, body, isFinal);
|
|
}
|
|
|
|
private SwitchStatement DeserializeSwitchStatement(JsonElement element, SourceRange location)
|
|
{
|
|
var expression = Deserialize(element.GetProperty("selector")) as Expression ?? throw new JsonException("selector is not Expression");
|
|
var cases = DeserializeList<SwitchCase>(element.GetProperty("cases"));
|
|
|
|
return new SwitchStatement(location, expression, cases);
|
|
}
|
|
|
|
private SwitchCase DeserializeSwitchCase(JsonElement element, SourceRange location)
|
|
{
|
|
var labels = DeserializeList<Expression>(element.GetProperty("labels"));
|
|
var statements = DeserializeList<Statement>(element.GetProperty("statements"));
|
|
var isDefault = element.GetProperty("isDefault").GetBoolean();
|
|
|
|
return new SwitchCase(location, labels, statements, isDefault);
|
|
}
|
|
|
|
private BreakStatement DeserializeBreakStatement(JsonElement element, SourceRange location)
|
|
{
|
|
var label = element.TryGetProperty("label", out var labelEl) ? labelEl.GetString() : null;
|
|
return new BreakStatement(location, label);
|
|
}
|
|
|
|
private ContinueStatement DeserializeContinueStatement(JsonElement element, SourceRange location)
|
|
{
|
|
var label = element.TryGetProperty("label", out var labelEl) ? labelEl.GetString() : null;
|
|
return new ContinueStatement(location, label);
|
|
}
|
|
|
|
private ThrowStatement DeserializeThrowStatement(JsonElement element, SourceRange location)
|
|
{
|
|
var expression = Deserialize(element.GetProperty("exception")) as Expression ?? throw new JsonException("exception is not Expression");
|
|
return new ThrowStatement(location, expression);
|
|
}
|
|
|
|
private CatchClause DeserializeCatchClause(JsonElement element, SourceRange location)
|
|
{
|
|
var exceptionTypes = DeserializeList<TypeReference>(element.GetProperty("exceptionTypes"));
|
|
var variableName = element.GetProperty("variableName").GetString() ?? throw new JsonException("variableName is null");
|
|
var body = Deserialize(element.GetProperty("body")) as BlockStatement ?? throw new JsonException("body is not BlockStatement");
|
|
|
|
return new CatchClause(location, exceptionTypes, variableName, body);
|
|
}
|
|
|
|
private SynchronizedStatement DeserializeSynchronizedStatement(JsonElement element, SourceRange location)
|
|
{
|
|
var expression = Deserialize(element.GetProperty("lock")) as Expression ?? throw new JsonException("lock is not Expression");
|
|
var body = Deserialize(element.GetProperty("body")) as BlockStatement ?? throw new JsonException("body is not BlockStatement");
|
|
|
|
return new SynchronizedStatement(location, expression, body);
|
|
}
|
|
|
|
private LabeledStatement DeserializeLabeledStatement(JsonElement element, SourceRange location)
|
|
{
|
|
var label = element.GetProperty("label").GetString() ?? throw new JsonException("label is null");
|
|
var statement = Deserialize(element.GetProperty("statement")) as Statement ?? throw new JsonException("statement is not Statement");
|
|
|
|
return new LabeledStatement(location, label, statement);
|
|
}
|
|
|
|
private EmptyStatement DeserializeEmptyStatement(JsonElement element, SourceRange location)
|
|
{
|
|
return new EmptyStatement(location);
|
|
}
|
|
|
|
private AssertStatement DeserializeAssertStatement(JsonElement element, SourceRange location)
|
|
{
|
|
var condition = Deserialize(element.GetProperty("condition")) as Expression ?? throw new JsonException("condition is not Expression");
|
|
var message = element.TryGetProperty("message", out var msgEl) && msgEl.ValueKind != JsonValueKind.Null
|
|
? Deserialize(msgEl) as Expression
|
|
: null;
|
|
|
|
return new AssertStatement(location, condition, message);
|
|
}
|
|
|
|
private ResourceDeclaration DeserializeResourceDeclaration(JsonElement element, SourceRange location)
|
|
{
|
|
var type = Deserialize(element.GetProperty("type")) as TypeReference ?? throw new JsonException("type is not TypeReference");
|
|
var name = element.GetProperty("name").GetString() ?? throw new JsonException("name is null");
|
|
var initializer = Deserialize(element.GetProperty("initializer")) as Expression ?? throw new JsonException("initializer is not Expression");
|
|
var isFinal = element.GetProperty("isFinal").GetBoolean();
|
|
|
|
return new ResourceDeclaration(location, type, name, initializer, isFinal);
|
|
}
|
|
|
|
private LambdaParameter DeserializeLambdaParameter(JsonElement element, SourceRange location)
|
|
{
|
|
var name = element.GetProperty("name").GetString() ?? throw new JsonException("name is null");
|
|
var type = element.TryGetProperty("type", out var typeEl) && typeEl.ValueKind != JsonValueKind.Null
|
|
? Deserialize(typeEl) as TypeReference
|
|
: null;
|
|
var isFinal = element.GetProperty("isFinal").GetBoolean();
|
|
|
|
return new LambdaParameter(location, name, type, isFinal);
|
|
}
|
|
}
|
|
} |