From 06dce35cca00935509687efcd485cd7456a20f95 Mon Sep 17 00:00:00 2001 From: Joao Matos Date: Sun, 21 Feb 2021 02:55:15 +0000 Subject: [PATCH] Add initial Java parsing support. --- external/JavaParser/JavaParser/JavaAST.cs | 772 ++++++++++++++++++ .../JavaParser/JavaParser/JavaParser.csproj | 25 + external/JavaParser/JavaParser/Program.cs | 650 +++++++++++++++ 3 files changed, 1447 insertions(+) create mode 100644 external/JavaParser/JavaParser/JavaAST.cs create mode 100644 external/JavaParser/JavaParser/JavaParser.csproj create mode 100644 external/JavaParser/JavaParser/Program.cs diff --git a/external/JavaParser/JavaParser/JavaAST.cs b/external/JavaParser/JavaParser/JavaAST.cs new file mode 100644 index 00000000..ced09050 --- /dev/null +++ b/external/JavaParser/JavaParser/JavaAST.cs @@ -0,0 +1,772 @@ +// +// +// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do: +// +// using QuickType; +// +// var cppSharpAstJava = CppSharpAstJava.FromJson(jsonString); + +using Newtonsoft.Json.Linq; + +namespace JavaParser.AST +{ + using System; + using System.Collections.Generic; + + using System.Globalization; + using Newtonsoft.Json; + using Newtonsoft.Json.Converters; + + #region Base + + public partial class Range + { + [JsonProperty("beginLine")] + public long BeginLine { get; set; } + + [JsonProperty("beginColumn")] + public long BeginColumn { get; set; } + + [JsonProperty("endLine")] + public long EndLine { get; set; } + + [JsonProperty("endColumn")] + public long EndColumn { get; set; } + } + + public partial class TokenRange + { + [JsonProperty("beginToken")] + public Token BeginToken { get; set; } + + [JsonProperty("endToken")] + public Token EndToken { get; set; } + } + + public partial class Token + { + [JsonProperty("kind")] + public long Kind { get; set; } + + [JsonProperty("text")] + public string Text { get; set; } + } + + #endregion + + #region Nodes + + public partial class Node + { + [JsonProperty("!")] + public string Kind { get; set; } + + [JsonProperty("range")] + public Range Range { get; set; } + + [JsonProperty("tokenRange")] + public TokenRange TokenRange { get; set; } + + [JsonProperty("comment")] + public Comment Comment { get; set; } + } + + public partial class ArrayCreationLevel : Node + { + [JsonProperty("dimension")] + public Expression Dimension { get; set; } + + [JsonProperty("annotations")] + public AnnotationExpr[] Annotations { get; set; } + } + + public partial class CompilationUnit : Node + { + public string FileName { get; set; } + + [JsonProperty("imports")] + public ImportDeclaration[] Imports { get; set; } + + [JsonProperty("packageDeclaration")] + public PackageDeclaration PackageDeclaration { get; set; } + + [JsonProperty("types")] + public TypeDeclaration[] Types { get; set; } + } + + public partial class ImportDeclaration : Node + { + [JsonProperty("name")] + public Name Name; + + [JsonProperty("isStatic")] + public bool IsStatic; + + [JsonProperty("isAsterisk")] + public bool IsAsterisk; + } + + public partial class PackageDeclaration : Node + { + [JsonProperty("annotations")] + public AnnotationExpr[] Annotations { get; set; } + + [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] + public Name Name { get; set; } + } + + public partial class Modifier : Node + { + [JsonProperty("keyword")] + public string Keyword; + } + + #endregion + + #region Body + + public partial class BodyDeclaration : Node + { + [JsonProperty("annotations")] + public AnnotationExpr[] Annotations { get; set; } + } + + public partial class AnnotationDeclaration : TypeDeclaration + { + + } + + public partial class AnnotationMemberDeclaration : BodyDeclaration + { + [JsonProperty("modifiers")] + public Modifier[] Modifiers; + + [JsonProperty("type")] + public Type Type; + + [JsonProperty("name")] + public SimpleName Name; + + [JsonProperty("defaultValue")] + public Expression DefaultValue; + } + + public partial class TypeDeclaration : BodyDeclaration + { + [JsonProperty("name")] + public SimpleName Name { get; set; } + + [JsonProperty("modifiers")] + public Modifier[] Modifiers { get; set; } + + [JsonProperty("members")] + public BodyDeclaration[] Members { get; set; } + } + + public partial class ClassOrInterfaceDeclaration : TypeDeclaration + { + [JsonProperty("isInterface")] + public bool IsInterface { get; set; } + + [JsonProperty("typeParameters")] + public TypeParameter[] TypeParameters { get; set; } + + [JsonProperty("implementedTypes")] + public ClassOrInterfaceType[] ImplementedTypes { get; set; } + + [JsonProperty("extendedTypes")] + public ClassOrInterfaceType[] ExtendedTypes { get; set; } + } + + public partial class ConstructorDeclaration : CallableDeclaration + { + [JsonProperty("body")] + public BlockStmt Body; + } + + public partial class EnumDeclaration : TypeDeclaration + { + [JsonProperty("entries")] + public EnumConstantDeclaration[] Entries { get; set; } + } + + public partial class EnumConstantDeclaration : BodyDeclaration + { + [JsonProperty("name")] + public SimpleName Name { get; set; } + + [JsonProperty("arguments")] + public Expression[] Arguments { get; set; } + + [JsonProperty("classBody")] + public BodyDeclaration[] ClassBody { get; set; } + } + + public partial class FieldDeclaration : BodyDeclaration + { + [JsonProperty("modifiers")] + public Modifier[] Modifiers; + + [JsonProperty("variables")] + public VariableDeclarator[] Variables; + } + + public partial class InitializerDeclaration : BodyDeclaration + { + [JsonProperty("isStatic")] + public bool IsStatic; + + [JsonProperty("body")] + public BlockStmt Body; + } + + public partial class CallableDeclaration : BodyDeclaration + { + [JsonProperty("modifiers")] + public Modifier[] Modifiers; + + [JsonProperty("typeParameters")] + public TypeParameter[] TypeParameters; + + [JsonProperty("name")] + public SimpleName Name; + + [JsonProperty("parameters")] + public Parameter[] Parameters; + + [JsonProperty("thrownExceptions")] + public ReferenceType[] ThrownExceptions; + + //public ReceiverParameter receiverParameter; + } + + public partial class MethodDeclaration : CallableDeclaration + { + [JsonProperty("type")] + public Type Type; + + [JsonProperty("body")] + public BlockStmt Body; + } + + public partial class Parameter : Node + { + [JsonProperty("type")] + public Type Type; + + [JsonProperty("isVarArgs")] + public bool IsVarArgs; + + [JsonProperty("varArgsAnnotations")] + public AnnotationExpr[] VarArgsAnnotations; + + [JsonProperty("modifiers")] + public Modifier[] Modifiers; + + [JsonProperty("annotations")] + public AnnotationExpr[] Annotations; + + [JsonProperty("name")] + public SimpleName Name; + } + + public partial class VariableDeclarator : Node + { + [JsonProperty("name")] + public SimpleName Name; + + [JsonProperty("initializer")] + public Expression Initializer; + + [JsonProperty("type")] + public Type Type; + } + + #endregion + + #region Comments + + public partial class BlockComment : Comment + { + } + + public partial class Comment : Node + { + [JsonProperty("content")] + public string Content { get; set; } + } + + public partial class JavadocComment : Comment + { + } + + public partial class LineComment : Comment + { + } + + #endregion + + #region Types + + public partial class Type + { + [JsonProperty("annotations")] + public AnnotationExpr[] Annotations { get; set; } + } + + public partial class ArrayType : ReferenceType + { + [JsonProperty("componentType")] + public Type ComponentType { get; set; } + } + + public partial class ClassOrInterfaceType : ReferenceType + { + [JsonProperty("name")] + public SimpleName Name { get; set; } + + [JsonProperty("typeArguments")] + public Type[] TypeArguments { get; set; } + } + + public partial class PrimitiveType : Type + { + [JsonProperty("type")] + public string Type { get; set; } + } + + public partial class ReferenceType : Type + { + + } + + public partial class TypeParameter : ReferenceType + { + [JsonProperty("name")] + public SimpleName Name { get; set; } + + [JsonProperty("typeBound")] + public ClassOrInterfaceType[] TypeBound { get; set; } + } + + public partial class UnknownType : Type + { + + } + + public partial class VoidType : Type + { + + } + + public partial class WildcardType : Type + { + [JsonProperty("extendedType")] + public ReferenceType ExtendedType; + + [JsonProperty("superType")] + public ReferenceType SuperType; + } + + #endregion + + #region Expressions + + public partial class Expression : Node + { + + } + + public partial class AnnotationExpr : Expression + { + [JsonProperty("name")] + public Name Name; + } + + public partial class ArrayAccessExpr : Expression + { + [JsonProperty("name")] + public Expression Name; + + [JsonProperty("index")] + public Expression Index; + } + + + public partial class ArrayCreationExpr : Expression + { + [JsonProperty("levels")] + public ArrayCreationLevel[] Levels; + + [JsonProperty("elementType")] + public Type ElementType; + + [JsonProperty("initializer")] + public ArrayInitializerExpr Initializer; + } + + public partial class ArrayInitializerExpr : Expression + { + [JsonProperty("values")] + public Expression[] Values; + } + + public partial class BinaryExpr : Expression + { + } + + public partial class ClassExpr : Expression + { + [JsonProperty("type")] + public Type Type; + } + + public partial class DoubleLiteralExpr : LiteralStringValueExpr + { + } + + public partial class FieldAccessExpr : Expression + { + [JsonProperty("scope")] + public Expression Scope; + + [JsonProperty("typeArguments")] + public Type[] TypeArguments; + + [JsonProperty("name")] + public SimpleName Name; + } + + public partial class IntegerLiteralExpr : LiteralStringValueExpr + { + } + + public partial class LambdaExpr : Expression + { + [JsonProperty("parameters")] + public Parameter[] Parameters; + + [JsonProperty("isEnclosingParameters")] + public bool IsEnclosingParameters; + + [JsonProperty("body")] + public Statement Body; + } + + public partial class LiteralExpr : Expression + { + } + + public partial class LiteralStringValueExpr : LiteralExpr + { + [JsonProperty("value")] + public string Value; + } + + public partial class MarkerAnnotationExpr : AnnotationExpr + { + + } + + public partial class MemberValuePair : Node + { + [JsonProperty("name")] + public SimpleName Name; + + [JsonProperty("value")] + public Expression Value; + } + + public partial class MethodCallExpr : Expression + { + [JsonProperty("scope")] + public Expression Scope; + + [JsonProperty("typeArguments")] + public Type[] TypeArguments; + + [JsonProperty("name")] + public SimpleName Name; + + [JsonProperty("arguments")] + public Expression[] Arguments; + } + + public partial class NameExpr : Expression + { + [JsonProperty("name")] + public SimpleName Name; + } + + public partial class NormalAnnotationExpr : AnnotationExpr + { + [JsonProperty("pairs")] + public MemberValuePair[] Pairs; + } + + public partial class NullLiteralExpr : LiteralExpr + { + } + + public partial class ObjectCreationExpr : Expression + { + [JsonProperty("scope")] + public Expression Scope; + + [JsonProperty("type")] + public ClassOrInterfaceType Type; + + [JsonProperty("typeArguments")] + public Type[] TypeArguments; + + [JsonProperty("arguments")] + public Expression[] Arguments; + + [JsonProperty("anonymousClassBody")] + public BodyDeclaration[] AnonymousClassBody; + } + + public partial class StringLiteralExpr : LiteralStringValueExpr + { + } + + public partial class SimpleName : Node + { + [JsonProperty("identifier")] + public string Identifier { get; set; } + } + + public partial class SingleMemberAnnotationExpr : AnnotationExpr + { + [JsonProperty("memberValue")] + public Expression MemberValue; + } + + public partial class UnaryExpr : Expression + { + } + + public partial class Name : Node + { + [JsonProperty("identifier")] + public string Identifier { get; set; } + + [JsonProperty("qualifier")] + public Name Qualifier; + } + + #endregion + + #region Statements + + public class Statement + { + + } + + public class BlockStmt : Statement + { + [JsonProperty("statements")] + public Statement[] Statements; + } + + #endregion + + public partial class CompilationUnit + { + public static CompilationUnit FromJson(string json) => + JsonConvert.DeserializeObject(json, Converter.Settings); + } + + public static class Serialize + { + public static string ToJson(this CompilationUnit self) => + JsonConvert.SerializeObject(self, Converter.Settings); + } + + internal static class Converter + { + public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings + { + MetadataPropertyHandling = MetadataPropertyHandling.Ignore, + DateParseHandling = DateParseHandling.None, + Converters = + { + new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }, + new NodeConverter(), + new TypeConverter() + }, + }; + } + + internal class NodeConverter : JsonCreationConverter + { + protected override Node Create(System.Type objectType, JObject jObject) + { + switch (jObject["!"].ToString()) + { + case "com.github.javaparser.ast.ArrayCreationLevel": + return new ArrayCreationLevel(); + case "com.github.javaparser.ast.CompilationUnit": + return new CompilationUnit(); + case "com.github.javaparser.ast.ImportDeclaration": + return new ImportDeclaration(); + case "com.github.javaparser.ast.Modifier": + return new Modifier(); + case "com.github.javaparser.ast.PackageDeclaration": + return new PackageDeclaration(); + + case "com.github.javaparser.ast.body.AnnotationDeclaration": + return new AnnotationDeclaration(); + case "com.github.javaparser.ast.body.AnnotationMemberDeclaration": + return new AnnotationMemberDeclaration(); + case "com.github.javaparser.ast.body.ClassOrInterfaceDeclaration": + return new ClassOrInterfaceDeclaration(); + case "com.github.javaparser.ast.body.ConstructorDeclaration": + return new ConstructorDeclaration(); + case "com.github.javaparser.ast.body.FieldDeclaration": + return new FieldDeclaration(); + case "com.github.javaparser.ast.body.InitializerDeclaration": + return new InitializerDeclaration(); + case "com.github.javaparser.ast.body.EnumConstantDeclaration": + return new EnumConstantDeclaration(); + case "com.github.javaparser.ast.body.EnumDeclaration": + return new EnumDeclaration(); + case "com.github.javaparser.ast.body.MethodDeclaration": + return new MethodDeclaration(); + case "com.github.javaparser.ast.body.Parameter": + return new Parameter(); + case "com.github.javaparser.ast.body.VariableDeclarator": + return new VariableDeclarator(); + + case "com.github.javaparser.ast.comments.BlockComment": + return new BlockComment(); + case "com.github.javaparser.ast.comments.Comment": + return new Comment(); + case "com.github.javaparser.ast.comments.JavadocComment": + return new JavadocComment(); + case "com.github.javaparser.ast.comments.LineComment": + return new LineComment(); + + case "com.github.javaparser.ast.expr.AnnotationExpr": + return new AnnotationExpr(); + case "com.github.javaparser.ast.expr.ArrayAccessExpr": + return new ArrayAccessExpr(); + case "com.github.javaparser.ast.expr.ArrayCreationExpr": + return new ArrayCreationExpr(); + case "com.github.javaparser.ast.expr.ArrayInitializerExpr": + return new ArrayInitializerExpr(); + case "com.github.javaparser.ast.expr.BinaryExpr": + return new BinaryExpr(); + case "com.github.javaparser.ast.expr.ClassExpr": + return new ClassExpr(); + case "com.github.javaparser.ast.expr.DoubleLiteralExpr": + return new DoubleLiteralExpr(); + case "com.github.javaparser.ast.expr.FieldAccessExpr": + return new FieldAccessExpr(); + case "com.github.javaparser.ast.expr.IntegerLiteralExpr": + return new IntegerLiteralExpr(); + case "com.github.javaparser.ast.expr.LambdaExpr": + return new LambdaExpr(); + case "com.github.javaparser.ast.expr.LiteralExpr": + return new LiteralExpr(); + case "com.github.javaparser.ast.expr.LiteralStringValueExpr": + return new LiteralStringValueExpr(); + case "com.github.javaparser.ast.expr.MarkerAnnotationExpr": + return new MarkerAnnotationExpr(); + case "com.github.javaparser.ast.expr.MemberValuePair": + return new MemberValuePair(); + case "com.github.javaparser.ast.expr.MethodCallExpr": + return new MethodCallExpr(); + case "com.github.javaparser.ast.expr.NameExpr": + return new NameExpr(); + case "com.github.javaparser.ast.expr.NormalAnnotationExpr": + return new NormalAnnotationExpr(); + case "com.github.javaparser.ast.expr.NullLiteralExpr": + return new NullLiteralExpr(); + case "com.github.javaparser.ast.expr.Name": + return new Name(); + case "com.github.javaparser.ast.expr.ObjectCreationExpr": + return new ObjectCreationExpr(); + case "com.github.javaparser.ast.expr.SimpleName": + return new SimpleName(); + case "com.github.javaparser.ast.expr.SingleMemberAnnotationExpr": + return new SingleMemberAnnotationExpr(); + case "com.github.javaparser.ast.expr.StringLiteralExpr": + return new StringLiteralExpr(); + case "com.github.javaparser.ast.expr.UnaryExpr": + return new UnaryExpr(); + default: + throw new NotImplementedException($"Missing handler for: {jObject["!"]}"); + } + } + } + + internal class TypeConverter : JsonCreationConverter + { + protected override Type Create(System.Type objectType, JObject jObject) + { + switch (jObject["!"].ToString()) + { + case "com.github.javaparser.ast.type.ArrayType": + return new ArrayType(); + case "com.github.javaparser.ast.type.ClassOrInterfaceType": + return new ClassOrInterfaceType(); + case "com.github.javaparser.ast.type.PrimitiveType": + return new PrimitiveType(); + case "com.github.javaparser.ast.type.TypeParameter": + return new TypeParameter(); + case "com.github.javaparser.ast.type.UnknownType": + return new UnknownType(); + case "com.github.javaparser.ast.type.VoidType": + return new VoidType(); + case "com.github.javaparser.ast.type.WildcardType": + return new WildcardType(); + default: + throw new NotImplementedException($"Missing handler for: {jObject["!"]}"); + } + } + } + + internal abstract class JsonCreationConverter : JsonConverter + { + /// + /// Create an instance of objectType, based properties in the JSON object + /// + /// type of object expected + /// + /// contents of JSON object that will be deserialized + /// + /// + protected abstract T Create(System.Type objectType, JObject jObject); + + public override bool CanConvert(System.Type objectType) + { + return typeof(T).IsAssignableFrom(objectType); + } + + public override bool CanWrite => false; + + public override object ReadJson(JsonReader reader, + System.Type objectType, + object existingValue, + JsonSerializer serializer) + { + // Load JObject from stream + JObject jObject = JObject.Load(reader); + + // Create target object based on JObject + T target = Create(objectType, jObject); + + // Populate the object properties + serializer.Populate(jObject.CreateReader(), target); + + return target; + } + + public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + } +} diff --git a/external/JavaParser/JavaParser/JavaParser.csproj b/external/JavaParser/JavaParser/JavaParser.csproj new file mode 100644 index 00000000..a7ade0d4 --- /dev/null +++ b/external/JavaParser/JavaParser/JavaParser.csproj @@ -0,0 +1,25 @@ + + + + Exe + netcoreapp3.1 + + + + + ..\..\..\deps\ikvm\bin\Debug\netcoreapp3.1\IKVM.OpenJDK.Core.dll + + + ..\..\..\deps\ikvm\bin\Debug\netcoreapp3.1\IKVM.Runtime.dll + + + + + + + + + + + + diff --git a/external/JavaParser/JavaParser/Program.cs b/external/JavaParser/JavaParser/Program.cs new file mode 100644 index 00000000..e21aed3e --- /dev/null +++ b/external/JavaParser/JavaParser/Program.cs @@ -0,0 +1,650 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using CppSharp; +using CppSharp.AST; +using CppSharp.Generators; +using CppSharp.Parser; +using IKVM.Internal; +using ArrayType = CppSharp.AST.ArrayType; +using Parameter = CppSharp.AST.Parameter; +using PrimitiveType = CppSharp.AST.PrimitiveType; +using Type = CppSharp.AST.Type; + +namespace JavaParser.AST +{ + public class Options : DriverOptions + { + /// + /// The name of the library to be bound. + /// + public Module Module; + } + + public class JavaJarASTGenerator + { + public static Dictionary JavaClassFiles + = new Dictionary(); + + ASTContext ASTContext { get; set; } + Options Options { get; set; } + + public JavaJarASTGenerator(ASTContext context, Options options) + { + ASTContext = context; + Options = options; + } + + public TranslationUnit VisitClassFile(ClassFile classFile) + { + var unit = GetTranslationUnit(classFile); + + var components = classFile.Name.Split(".").ToArray(); + var namespaces = components.SkipLast(1).ToArray(); + + Namespace currentNamespace = unit; + bool flattenNamespaces = true; + if (!flattenNamespaces) + { + foreach (var @namespace in namespaces) + currentNamespace = currentNamespace.FindCreateNamespace(@namespace); + } + + DeclarationContext decl = classFile.IsEnum ? (DeclarationContext)VisitEnum(classFile) : + (DeclarationContext)VisitClass(classFile); + + decl.Namespace = currentNamespace; + currentNamespace.Declarations.Add(decl); + + return unit; + } + + public Enumeration VisitEnum(ClassFile classFile) + { + var components = classFile.Name.Split(".").ToArray(); + + var @class = new Enumeration + { + Name = components.Last(), + }; + + return @class; + } + + public static AccessSpecifier ConvertMethodAccess(ClassFile.Method method) + { + if (method.IsInternal) + return AccessSpecifier.Internal; + if (method.IsPrivate) + return AccessSpecifier.Private; + if (method.IsProtected) + return AccessSpecifier.Protected; + if (method.IsPublic) + return AccessSpecifier.Public; + + return AccessSpecifier.Public; + } + + public Class VisitClass(ClassFile classFile) + { + var components = classFile.Name.Split(".").ToArray(); + + var @class = new Class + { + Name = components.Last(), + Type = classFile.IsInterface ? ClassType.Interface : ClassType.RefType + }; + + foreach (var javaMethod in classFile.Methods) + { + var method = new Method + { + Name = javaMethod.Name, + Access = ConvertMethodAccess(javaMethod) + }; + + var (retType, paramTypes) = GetTypeFromMethodSig(javaMethod.Signature); + + method.ReturnType = new QualifiedType(retType); + + var paramIndex = 0; + foreach (var paramType in paramTypes) + { + var param = new CppSharp.AST.Parameter + { + Namespace = method, + QualifiedType = new QualifiedType(paramType) + }; + + if (javaMethod.MethodParameters != null) + if (paramIndex < javaMethod.MethodParameters.Length) + param.Name = javaMethod.MethodParameters[paramIndex].name; + + method.Parameters.Add(param); + paramIndex++; + } + + @class.Methods.Add(method); + } + + return @class; + } + + public static CppSharp.AST.PrimitiveType GetPrimitiveTypeFromJavaSig(char sig) + { + switch (sig) + { + case 'B': + return CppSharp.AST.PrimitiveType.Char; + case 'C': + return CppSharp.AST.PrimitiveType.WideChar; + case 'D': + return CppSharp.AST.PrimitiveType.Double; + case 'F': + return CppSharp.AST.PrimitiveType.Float; + case 'I': + return CppSharp.AST.PrimitiveType.Int; + case 'J': + return CppSharp.AST.PrimitiveType.Long; + case 'S': + return CppSharp.AST.PrimitiveType.Short; + case 'Z': + return CppSharp.AST.PrimitiveType.Bool; + case 'V': + return CppSharp.AST.PrimitiveType.Void; + default: + throw new NotImplementedException(); + } + } + + public static (CppSharp.AST.Type, List) GetTypeFromMethodSig(string sig) + { + var types = new List(); + + int i = 1; + while(sig[i] != ')') + types.Add(GetTypeFromSig(sig, ref i)); + i++; + + var retType = GetTypeFromSig(sig, ref i); + + return (retType, types); + } + + public static CppSharp.AST.TagType GetTagTypeFromSig(string sig, ref int index) + { + int pos = index; + index = sig.IndexOf(';', index) + 1; + var className = sig.Substring(pos, index - pos - 1); + var @class = new TagType(); + return @class; + } + + public static CppSharp.AST.Type GetTypeFromSig(string sig, ref int index) + { + var @char = sig[index++]; + switch(@char) + { + case 'B': + case 'C': + case 'D': + case 'F': + case 'I': + case 'J': + case 'S': + case 'Z': + case 'V': + return new BuiltinType(GetPrimitiveTypeFromJavaSig(@char)); + case 'L': + { + int pos = index; + index = sig.IndexOf(';', index) + 1; + var className = sig.Substring(pos, index - pos - 1); + var @class = new TagType(); + return @class; + } + case '[': + { + var rootArrayType = new CppSharp.AST.ArrayType + { + SizeType = CppSharp.AST.ArrayType.ArraySize.Variable + }; + var arrayType = rootArrayType; + + while(sig[index] == '[') + { + index++; + var newArrayType = new CppSharp.AST.ArrayType + { + SizeType = CppSharp.AST.ArrayType.ArraySize.Variable + }; + arrayType.QualifiedType = new QualifiedType(newArrayType); + arrayType = newArrayType; + } + + var innerType = GetTypeFromSig(sig, ref index); + arrayType.QualifiedType = new QualifiedType(innerType); + + return rootArrayType; + } + default: + throw new InvalidOperationException(sig.Substring(index)); + } + } + + TranslationUnit GetTranslationUnit(ClassFile classFile) + { + var unitName = Options.Module.LibraryName ?? Path.GetFileName (classFile.Name); + + var unit = ASTContext.TranslationUnits.Find(m => m.FileName.Equals(unitName)); + if (unit != null) + return unit; + + unit = ASTContext.FindOrCreateTranslationUnit(unitName); + unit.FilePath = unitName; + + JavaClassFiles[unit] = classFile; + + return unit; + } + } + + public class JavaJsonASTGenerator + { + ASTContext ASTContext { get; set; } + Options Options { get; set; } + + public JavaJsonASTGenerator(ASTContext context, Options options) + { + ASTContext = context; + Options = options; + } + + public TranslationUnit CurrentUnit; + + public void VisitCompilationUnits(List compilationUnits) + { + foreach (var unit in compilationUnits) + { + CurrentUnit = GetTranslationUnit(unit); + CurrentUnit.Module = Options.Module; + + foreach (var type in unit.Types) + { + var decl = VisitTypeDeclaration(type); + if (decl == null) + continue; + + decl.Namespace = CurrentUnit; + if (CurrentUnit.Declarations.All(d => d.Name != decl.Name)) + CurrentUnit.Declarations.Add(decl); + } + } + } + + public TranslationUnit GetTranslationUnit(CompilationUnit compilationUnit) + { + var unitName = Options.Module.LibraryName ?? Path.GetFileName (compilationUnit.FileName); + + var unit = ASTContext.TranslationUnits.Find(m => m.FileName.Equals(unitName)); + if (unit != null) + return unit; + + unit = ASTContext.FindOrCreateTranslationUnit(unitName); + unit.FilePath = unitName; + + return unit; + } + + public Declaration VisitTypeDeclaration(TypeDeclaration type) + { + switch (type) + { + case AnnotationDeclaration annotationDeclaration: + return null; + case ClassOrInterfaceDeclaration classOrInterfaceDeclaration: + return VisitClassOrInterfaceDeclaration(classOrInterfaceDeclaration); + case EnumDeclaration enumDeclaration: + return VisitEnumDeclaration(enumDeclaration); + default: + throw new NotImplementedException(); + } + } + + public Declaration VisitEnumDeclaration(EnumDeclaration enumDeclaration) + { + var @class = HandleTypeDeclaration(enumDeclaration); + if (!@class.IsIncomplete) + return @class; + + foreach (var entry in enumDeclaration.Entries) + { + + } + + @class.IsIncomplete = false; + + return @class; + } + + public Class VisitClassOrInterfaceDeclaration(ClassOrInterfaceDeclaration classOrInterfaceDeclaration) + { + var @class = HandleTypeDeclaration(classOrInterfaceDeclaration); + if (!@class.IsIncomplete) + return @class; + + @class.Type = classOrInterfaceDeclaration.IsInterface ? ClassType.Interface : ClassType.RefType; + @class.IsIncomplete = false; + + if (classOrInterfaceDeclaration.TypeParameters.Length > 0) + { + @class.IsDependent = true; + + foreach (var typeParam in classOrInterfaceDeclaration.TypeParameters) + { + var templateParam = new TypeTemplateParameter { Name = typeParam.Name.Identifier }; + if (typeParam.TypeBound.Length > 0) + templateParam.Constraint = ConvertType(typeParam.TypeBound.First()).ToString(); + + @class.TemplateParameters.Add(templateParam); + } + } + + foreach (var extendedType in classOrInterfaceDeclaration.ExtendedTypes) + { + var extendedClassType = ConvertType(extendedType); + @class.Bases.Add(new BaseClassSpecifier + { + Access = AccessSpecifier.Public, + IsVirtual = false, + Type = extendedClassType + }); + } +/* + foreach (var implementedType in classOrInterfaceDeclaration.ImplementedTypes) + { + var implementedClassType = ConvertType(implementedType); + @class.Bases.Add(new BaseClassSpecifier + { + Access = AccessSpecifier.Public, + IsVirtual = false, + Type = implementedClassType + }); + } +*/ + return @class; + } + + public Class HandleTypeDeclaration(TypeDeclaration typeDeclaration) + { + var @class = ASTContext.FindClass(typeDeclaration.Name.Identifier).FirstOrDefault(); + if (@class == null) + { + @class = new Class {Name = typeDeclaration.Name.Identifier, IsIncomplete = true}; + CurrentUnit.Declarations.Add(@class); + } + + if (!@class.IsIncomplete) + return @class; + + foreach (var member in typeDeclaration.Members) + { + var decl = VisitBodyDeclaration(member); + if (decl == null) + continue; + + decl.Namespace = @class; + + switch (decl) + { + case Method method: + @class.Methods.Add(method); + break; + case Field field: + @class.Fields.Add(field); + break; + default: + @class.Declarations.Add(decl); + break; + } + } + + return @class; + } + + public Declaration VisitBodyDeclaration(BodyDeclaration body) + { + switch (body) + { + case ClassOrInterfaceDeclaration classOrInterfaceDeclaration: + return VisitClassOrInterfaceDeclaration(classOrInterfaceDeclaration); + case ConstructorDeclaration constructorDeclaration: + return VisitCallableDeclaration(constructorDeclaration); + case EnumDeclaration enumDeclaration: + return VisitEnumDeclaration(enumDeclaration); + case InitializerDeclaration initializerDeclaration: + return VisitInitializerDeclaration(initializerDeclaration); + case FieldDeclaration fieldDeclaration: + return VisitFieldDeclaration(fieldDeclaration); + case MethodDeclaration methodDeclaration: + return VisitCallableDeclaration(methodDeclaration); + default: + throw new NotImplementedException(); + } + } + + private Declaration VisitInitializerDeclaration(InitializerDeclaration initializerDeclaration) + { + return null; + } + + public Declaration VisitFieldDeclaration(FieldDeclaration fieldDeclaration) + { + return null; + } + + public Method VisitCallableDeclaration(CallableDeclaration callableDeclaration) + { + var method = new Method + { + Name = callableDeclaration.Name.Identifier, + Access = AccessSpecifier.Internal + }; + + if (callableDeclaration is ConstructorDeclaration) + method.Kind = CXXMethodKind.Constructor; + + if (callableDeclaration.Modifiers.Length > 0) + method.Access = ConvertModifier(callableDeclaration.Modifiers); + + if (callableDeclaration is MethodDeclaration methodDecl) + method.ReturnType = new QualifiedType(ConvertType(methodDecl.Type)); + + foreach (var parameter in callableDeclaration.Parameters) + { + var paramType = ConvertType(parameter.Type); + var param = new CppSharp.AST.Parameter + { + Name = parameter.Name.Identifier, + Namespace = method, + QualifiedType = new QualifiedType(paramType) + }; + + method.Parameters.Add(@param); + } + + return method; + } + + public static CppSharp.AST.PrimitiveType ConvertToPrimitiveType(string type) + { + return type switch + { + "BOOLEAN" => CppSharp.AST.PrimitiveType.Bool, + "CHAR" => CppSharp.AST.PrimitiveType.Char, + "BYTE" => CppSharp.AST.PrimitiveType.UChar, + "SHORT" => CppSharp.AST.PrimitiveType.Short, + "INT" => CppSharp.AST.PrimitiveType.Int, + "LONG" => CppSharp.AST.PrimitiveType.Long, + "FLOAT" => CppSharp.AST.PrimitiveType.Float, + "DOUBLE" => CppSharp.AST.PrimitiveType.Double, + _ => throw new NotImplementedException() + }; + } + + public CppSharp.AST.Type ConvertType(Type type) + { + switch (type) + { + case ArrayType arrayType: + return new CppSharp.AST.ArrayType(new QualifiedType(ConvertType(arrayType.ComponentType))) + { + SizeType = CppSharp.AST.ArrayType.ArraySize.Variable + }; + case PrimitiveType primitiveType: + return new BuiltinType(ConvertToPrimitiveType(primitiveType.Type)); + case ClassOrInterfaceType classOrInterfaceType: + { + var @class = ASTContext.FindClass(classOrInterfaceType.Name.Identifier).FirstOrDefault(); + if (@class == null) + { + @class = new Class + { + Name = classOrInterfaceType.Name.Identifier, + Namespace = CurrentUnit, + IsIncomplete = true + }; + CurrentUnit.Declarations.Add(@class); + } + + if (classOrInterfaceType.TypeArguments == null || classOrInterfaceType.TypeArguments.Length == 0) + return new TagType(@class); + + return new TemplateSpecializationType + { + Arguments = classOrInterfaceType.TypeArguments.Select(ConvertType).Select(t => + new TemplateArgument + { + Kind = TemplateArgument.ArgumentKind.Type, + Type = new QualifiedType(t), + }).ToList(), + Desugared = new QualifiedType(new TagType(@class)), + Template = new ClassTemplate(@class) + }; + } + case VoidType voidType: + return new BuiltinType(CppSharp.AST.PrimitiveType.Void); + case WildcardType wildcardType: + { + return new TemplateSpecializationType(); + } + default: + throw new NotImplementedException(); + } + } + + public static AccessSpecifier ConvertModifier(Modifier[] modifiers) + { + foreach (var modifier in modifiers) + { + switch (modifier.Keyword) + { + case "PUBLIC": + return AccessSpecifier.Public; + case "PROTECTED": + return AccessSpecifier.Protected; + case "PRIVATE": + return AccessSpecifier.Private; + case "DEFAULT": + return AccessSpecifier.Internal; + } + } + + throw new NotImplementedException(); + } + } + + class Program + { + static void Main(string[] args) + { + var options = new Options + { + GeneratorKind = GeneratorKind.TypeScript, + OutputDir = "ts" + }; + + var module = new Module("runelite-api"); + options.Module = module; + options.Modules.Add(module); + + var driver = new Driver(options); + driver.Setup(); + driver.SetupTypeMaps(); + + driver.Context.ASTContext = new ASTContext(); + var astContext = driver.Context.ASTContext; + + //var jarAstGenerator = new JavaJarASTGenerator(astContext, options); + //var jarFile = "runelite-api-3.5.4.jar"; + //ReadJar(jarFile, astGenerator); + + var compilationUnits = ReadJSON(); + var jsonAstGenerator = new JavaJsonASTGenerator(astContext, options); + jsonAstGenerator.VisitCompilationUnits(compilationUnits); + + // Sort declarations alphabetically + var translationUnit = astContext.TranslationUnits.First(); + var decls = new List(translationUnit.Declarations); + decls = decls.OrderBy(d => d.Name).ToList(); + translationUnit.Declarations.Clear(); + translationUnit.Declarations.AddRange(decls); + + driver.ProcessCode(); + var outputs = driver.GenerateCode(); + driver.SaveCode(outputs); + } + + private static List ReadJSON() + { + var compilationUnits = new List(); + + var jsonDir = "/home/joao/dev/rs/flower/javaparser-gradle-sample/out"; + var jsonFiles = Directory.EnumerateFiles(jsonDir, "*.json", + SearchOption.AllDirectories); + + Parallel.ForEach(jsonFiles, (file) => + { + if (Path.GetFileNameWithoutExtension(file).StartsWith("class")) + return; + + var jsonText = File.ReadAllText(file); + var compilationUnit = CompilationUnit.FromJson(jsonText); + compilationUnit.FileName = Path.GetFileNameWithoutExtension(file); + compilationUnits.Add(compilationUnit); + }); + + return compilationUnits; + } + + private static void ReadJar(string jarFile, JavaJarASTGenerator jarAstGenerator) + { + // TODO: Read from jar file directly. + var classDir = @"/home/joao/dev/CppSharp/tests2/jar"; + foreach (var file in Directory.EnumerateFiles(classDir, "*.class", + SearchOption.AllDirectories)) + { + if (Path.GetFileNameWithoutExtension(file).StartsWith("class")) + continue; + + var data = File.ReadAllBytes(file); + var parseOptions = ClassFileParseOptions.RemoveAssertions; + var classFile = new ClassFile(data, 0, data.Length, file, parseOptions, null); + + jarAstGenerator.VisitClassFile(classFile); + } + } + } +} \ No newline at end of file