From d408a7ab4568cc093a2ae27bf66149767b387771 Mon Sep 17 00:00:00 2001 From: MASES Public Developers Team <94312179+masesdevelopers@users.noreply.github.com> Date: Tue, 14 May 2024 15:23:24 +0200 Subject: [PATCH] JNetReflector creates the Direct class which extends standard listeners (#395) * JNetReflector creates the Direct class which extends standard listeners * Added generation of side-by-side method to return direct listener --- src/net/JNetReflector/InternalConst.cs | 1 + src/net/JNetReflector/InternalExtensions.cs | 26 ++-- src/net/JNetReflector/InternalMethods.cs | 135 ++++++++++++++---- ...llPackageClassesStubClassListener.template | 27 +++- src/net/JNetReflector/Templates/Templates.cs | 2 + 5 files changed, 150 insertions(+), 41 deletions(-) diff --git a/src/net/JNetReflector/InternalConst.cs b/src/net/JNetReflector/InternalConst.cs index afbfc337cc..86f45aa03d 100644 --- a/src/net/JNetReflector/InternalConst.cs +++ b/src/net/JNetReflector/InternalConst.cs @@ -102,6 +102,7 @@ public static string VersionPlaceHolder() public const string PropertySuffix = "Property"; public const string MethodSuffix = "Method"; public const string DefaultMethodSuffix = "Default"; + public const string DirectMethodSuffix = "Direct"; public const string NamespaceSuffix = "Ns"; public const string MainClassPlaceHolder = ", MASES.JCOBridge.C2JBridge.IJVMBridgeMain"; public const string JVMBridgeException = "MASES.JCOBridge.C2JBridge.JVMBridgeException"; diff --git a/src/net/JNetReflector/InternalExtensions.cs b/src/net/JNetReflector/InternalExtensions.cs index 10e865be06..8c2ac58da2 100644 --- a/src/net/JNetReflector/InternalExtensions.cs +++ b/src/net/JNetReflector/InternalExtensions.cs @@ -80,11 +80,11 @@ public static bool CollapseWithClassOrNestedClass(this string entry, int nesting { if (classDefinition.JVMNestingLevels() == nestingLevel) // same level of requester { - collpase = entry == classDefinition.JVMNestedClassName(nestingLevel, null, false); + collpase = entry == classDefinition.JVMNestedClassName(nestingLevel, null, false, false); } else if (classDefinition.JVMNestingLevels() > nestingLevel) // more levels then requester { - collpase = entry == classDefinition.JVMNestedClassName(nestingLevel + 1, null, false); + collpase = entry == classDefinition.JVMNestedClassName(nestingLevel + 1, null, false, false); } } else @@ -1079,12 +1079,13 @@ public static bool IsJVMClass(this Class entry) return false; } - public static string JVMClassName(this Class entry, IList> genClause, bool usedInGenerics) + public static string JVMClassName(this Class entry, IList> genClause, bool usedInGenerics, bool isDirect) { - if (entry.IsJVMNestedClass()) return entry.JVMNestedClassName(entry.JVMNestingLevels(), genClause, usedInGenerics); + if (entry.IsJVMNestedClass()) return entry.JVMNestedClassName(entry.JVMNestingLevels(), genClause, usedInGenerics, isDirect); var cName = entry.SimpleName; cName = cName.Contains(SpecialNames.NestedClassSeparator) ? cName.Substring(0, cName.LastIndexOf(SpecialNames.NestedClassSeparator)) : cName; cName = cName.ConvertClassesInConflict(); + if (isDirect) cName += SpecialNames.DirectMethodSuffix; if (usedInGenerics) cName = entry.ApplyGenerics(genClause, usedInGenerics, cName); return cName; } @@ -1095,7 +1096,7 @@ public static string JVMMainClassName(this Class entry) return cName.Contains(SpecialNames.NestedClassSeparator) ? cName.Substring(0, cName.IndexOf(SpecialNames.NestedClassSeparator)) : cName; } - static string JVMNestedClassName(this Class entry, int nestingLevel, IList> genClause, bool usedInGenerics, bool onlyName = false) + static string JVMNestedClassName(this Class entry, int nestingLevel, IList> genClause, bool usedInGenerics, bool isDirect, bool onlyName = false) { var cName = entry.TypeName; if (cName.Contains(SpecialNames.NestedClassSeparator)) @@ -1104,6 +1105,7 @@ static string JVMNestedClassName(this Class entry, int nestingLevel, IList", innerName); } } @@ -1386,7 +1388,7 @@ public static string JVMBaseClassName(this Class entry, bool usedInGenerics, boo } catch { - string className = entry.JVMClassName(null, usedInGenerics); + string className = entry.JVMClassName(null, usedInGenerics, false); return string.Format("MASES.JCOBridge.C2JBridge.JVMBridgeBase<{0}>", className); } } @@ -1401,7 +1403,7 @@ public static string JVMBaseInterfaceName(this Class entry, bool usedInGenerics, public static string JVMInterfaceName(this Class entry, IList> genClause, bool usedInGenerics, bool fullyQualified) { - var cName = entry.JVMClassName(genClause, usedInGenerics); + var cName = entry.JVMClassName(genClause, usedInGenerics, false); cName = "I" + cName; if (fullyQualified) { @@ -1531,7 +1533,7 @@ public static bool IsSpecialClass(this Class entry) return true; } - string className = entry.JVMNestedClassName(entry.JVMNestingLevels(), null, true); + string className = entry.JVMNestedClassName(entry.JVMNestingLevels(), null, true, false); if (entry.IsJVMNestedClass() && SpecialNames.SpecialNumberedNames.Any((o) => className.StartsWith(o))) return true; @@ -2311,6 +2313,12 @@ public static bool IsReturnTypeAnException(this Method entry) return entry.ReturnType.IsJVMException(); } + public static bool IsReturnTypeAListener(this Method entry) + { + if (entry == null) throw new ArgumentNullException(nameof(entry)); + return entry.ReturnType.IsJVMListenerClass(); + } + public static string ReturnType(this Method entry, IList genArguments, IList> genClauses, string prefix, bool usedInGenerics, bool camel) { if (entry == null) throw new ArgumentNullException(nameof(entry)); diff --git a/src/net/JNetReflector/InternalMethods.cs b/src/net/JNetReflector/InternalMethods.cs index 52e09ebfbf..01492125ef 100644 --- a/src/net/JNetReflector/InternalMethods.cs +++ b/src/net/JNetReflector/InternalMethods.cs @@ -499,7 +499,7 @@ static string AnalyzeClasses(string jarOrModuleName, IEnumerable classDef .Replace(AllPackageClasses.NAMESPACE, jClass.Namespace(JNetReflectorCore.UseCamel)) .Replace(AllPackageClasses.CLASSES, singleFileBlockStr); - var clsName = jClass.JVMClassName(null, false); + var clsName = jClass.JVMClassName(null, false, false); var classPath = Path.Combine(JNetReflectorCore.DestinationCSharpClassPath, jClass.Namespace(JNetReflectorCore.UseCamel).Replace(SpecialNames.NamespaceSeparator, Path.DirectorySeparatorChar), $"{clsName}.cs"); WriteFile(classPath, fileContent); } @@ -706,8 +706,8 @@ static void PrepareSingleClass(this Class jClass, IReadOnlyDictionary>(), false)) - .Replace(AllPackageClasses.ClassStub.CLASS, jClass.JVMClassName(new List>(), isGeneric)) + .Replace(AllPackageClasses.ClassStub.JAVACLASS_DIRECT, jClass.JVMFullClassName()) + .Replace(AllPackageClasses.ClassStub.SIMPLECLASS, jClass.JVMClassName(new List>(), false, false)) + .Replace(AllPackageClasses.ClassStub.CLASS, jClass.JVMClassName(new List>(), isGeneric, false)) + .Replace(AllPackageClasses.ClassStub.CLASS_DIRECT, jClass.JVMClassName(new List>(), isGeneric, true)) .Replace(AllPackageClasses.ClassStub.HELP, jClass.JavadocHrefUrl(JNetReflectorCore.UseCamel)) .Replace(AllPackageClasses.ClassStub.BASECLASS, jClass.JVMBaseClassName(isGeneric, jClassIsListener, JNetReflectorCore.UseCamel) + (isMainClass ? SpecialNames.MainClassPlaceHolder : string.Empty)) .Replace(AllPackageClasses.ClassStub.WHERECLAUSES, jClass.WhereClauses(isGeneric, JNetReflectorCore.UseCamel)) @@ -796,7 +798,7 @@ static void PrepareSingleClass(this Class jClass, IReadOnlyDictionary>(), isGeneric)) + singleClassStr = singleClass.Replace(AllPackageClasses.ClassStub.CLASS, jClass.JVMClassName(new List>(), isGeneric, false)) .Replace(AllPackageClasses.ClassStub.INTERFACE_CONSTRAINT, !string.IsNullOrWhiteSpace(interfaceConstraint) ? " : " + interfaceConstraint : string.Empty) .Replace(AllPackageClasses.ClassStub.CONSTRUCTORS, constructorClassBlock) .Replace(AllPackageClasses.ClassStub.OPERATORS, operatorClassBlock) @@ -1707,55 +1709,107 @@ static string AnalyzeMethods(this Class classDefinition, IReadOnlyDictionary", - methodNameOrigin, - string.IsNullOrWhiteSpace(signature) ? string.Empty : $", \"{signature}\"", - executionParamsString.Length == 0 ? string.Empty : ", " + executionParamsString); + executionStub = string.Format(execFormat, + method.IsVoid() ? string.Empty : "return ", + execStub, + isVoidMethod || method.IsObjectReturnType(isGeneric, JNetReflectorCore.UseCamel) ? string.Empty : $"<{returnType}>", + methodNameOrigin, + string.IsNullOrWhiteSpace(signature) ? string.Empty : $", \"{signature}\"", + executionParamsString.Length == 0 ? string.Empty : ", " + executionParamsString); + if (isListenerReturnType) + { + string directNewClass = returnType; + var indexOfGenerics = returnType.IndexOf('<'); + if (indexOfGenerics > 0) + { + directNewClass = returnType.Insert(indexOfGenerics, SpecialNames.DirectMethodSuffix); + } + else + { + directNewClass = returnType + SpecialNames.DirectMethodSuffix; + } + + executionStubDirect = string.Format(execFormat, + method.IsVoid() ? string.Empty : "return ", + execStub, + isVoidMethod || method.IsObjectReturnType(isGeneric, JNetReflectorCore.UseCamel) ? string.Empty : $"<{directNewClass}, {returnType}>", + methodNameOrigin, + string.IsNullOrWhiteSpace(signature) ? string.Empty : $", \"{signature}\"", + executionParamsString.Length == 0 ? string.Empty : ", " + executionParamsString); + } } if (hasVarArg) { string executionStubWithVarArg = string.Empty; + string executionStubWithVarArgDirect = string.Empty; if (isReturnTypeException) { var execFormat = method.IsStatic() ? AllPackageClasses.ClassStub.MethodStub.STATIC_EXECUTION_FORMAT_EXCEPTION : AllPackageClasses.ClassStub.MethodStub.EXECUTION_FORMAT_EXCEPTION; - executionStubWithVarArg = string.Format(execFormat, execStub, - methodNameOrigin, - string.IsNullOrWhiteSpace(signature) ? string.Empty : $", \"{signature}\"", - (executionParamsString.Length == 0 ? string.Empty : ", ") - + executionParamsString + ", " + varArg.Name(), - returnType); + executionStubWithVarArg = string.Format(execFormat, + execStub, + methodNameOrigin, + string.IsNullOrWhiteSpace(signature) ? string.Empty : $", \"{signature}\"", + (executionParamsString.Length == 0 ? string.Empty : ", ") + + executionParamsString + ", " + varArg.Name(), + returnType); } else { var execFormat = method.IsStatic() ? AllPackageClasses.ClassStub.MethodStub.STATIC_EXECUTION_FORMAT : AllPackageClasses.ClassStub.MethodStub.EXECUTION_FORMAT; - executionStubWithVarArg = string.Format(execFormat, isVoidMethod ? string.Empty : "return ", - execStub, - isVoidMethod || method.IsObjectReturnType(isGeneric, JNetReflectorCore.UseCamel) ? string.Empty : $"<{returnType}>", - methodNameOrigin, - string.IsNullOrWhiteSpace(signature) ? string.Empty : $", \"{signature}\"", - (executionParamsString.Length == 0 ? string.Empty : ", ") - + executionParamsString + ", " + varArg.Name()); + executionStubWithVarArg = string.Format(execFormat, + isVoidMethod ? string.Empty : "return ", + execStub, + isVoidMethod || method.IsObjectReturnType(isGeneric, JNetReflectorCore.UseCamel) ? string.Empty : $"<{returnType}>", + methodNameOrigin, + string.IsNullOrWhiteSpace(signature) ? string.Empty : $", \"{signature}\"", + (executionParamsString.Length == 0 ? string.Empty : ", ") + + executionParamsString + ", " + varArg.Name()); + + if (isListenerReturnType) + { + string directNewClass = returnType; + var indexOfGenerics = returnType.IndexOf('<'); + if (indexOfGenerics > 0) + { + directNewClass = returnType.Insert(indexOfGenerics, SpecialNames.DirectMethodSuffix); + } + else + { + directNewClass = returnType + SpecialNames.DirectMethodSuffix; + } + + executionStubWithVarArgDirect = string.Format(execFormat, + isVoidMethod ? string.Empty : "return ", + execStub, + isVoidMethod || method.IsObjectReturnType(isGeneric, JNetReflectorCore.UseCamel) ? string.Empty : $"<{directNewClass}, {returnType}>", + methodNameOrigin, + string.IsNullOrWhiteSpace(signature) ? string.Empty : $", \"{signature}\"", + (executionParamsString.Length == 0 ? string.Empty : ", ") + + executionParamsString + ", " + varArg.Name()); + } } executionStub = $"if ({varArg.Name()}.Length == 0) {executionStub} else {executionStubWithVarArg}"; + executionStubDirect = $"if ({varArg.Name()}.Length == 0) {executionStubDirect} else {executionStubWithVarArgDirect}"; } ReportTrace(ReflectionTraceLevel.Debug, "Preparing method {0}", genString); @@ -1924,13 +1978,32 @@ static string AnalyzeMethods(this Class classDefinition, IReadOnlyDictionary /// Default constructor: even if the corresponding Java class does not have one, it is mandatory for JCOBridge /// - public ALLPACKAGE_CLASSES_STUB_SIMPLECLASS_PLACEHOLDER() { InitializeHandlers(); } + public ALLPACKAGE_CLASSES_STUB_SIMPLECLASS_PLACEHOLDER() { if (InitHandlers) InitializeHandlers(); } + /// + /// Enable/disable handlers initialization, default is + /// + protected virtual bool InitHandlers { get; } = true; ALLPACKAGE_CLASSES_STUB_LISTENER_CLASS_PLACEHOLDER // TODO: complete the class // ALLPACKAGE_CLASSES_STUB_NESTED_CLASSES_PLACEHOLDER } +#endregion + +#region ALLPACKAGE_CLASSES_STUB_CLASS_DIRECT_PLACEHOLDER +/// +/// Direct override of +/// +public partial class ALLPACKAGE_CLASSES_STUB_CLASS_DIRECT_PLACEHOLDER : ALLPACKAGE_CLASSES_STUB_CLASS_PLACEHOLDER +{ + /// + /// + /// + public override bool AutoInit => false; + + /// + protected override bool InitHandlers => false; + + /// + /// + /// + public override string BridgeClassName => "ALLPACKAGE_CLASSES_STUB_JAVACLASS_DIRECT_PLACEHOLDER"; +} #endregion \ No newline at end of file diff --git a/src/net/JNetReflector/Templates/Templates.cs b/src/net/JNetReflector/Templates/Templates.cs index 63da424e69..bdff90944e 100644 --- a/src/net/JNetReflector/Templates/Templates.cs +++ b/src/net/JNetReflector/Templates/Templates.cs @@ -120,6 +120,7 @@ public class ClassStub public const string HELP = "ALLPACKAGE_CLASSES_STUB_CLASS_HELP_PLACEHOLDER"; public const string SIMPLECLASS = "ALLPACKAGE_CLASSES_STUB_SIMPLECLASS_PLACEHOLDER"; public const string CLASS = "ALLPACKAGE_CLASSES_STUB_CLASS_PLACEHOLDER"; + public const string CLASS_DIRECT = "ALLPACKAGE_CLASSES_STUB_CLASS_DIRECT_PLACEHOLDER"; public const string LISTENER_CLASS = "ALLPACKAGE_CLASSES_STUB_LISTENER_CLASS_PLACEHOLDER"; public const string INTERFACE = "ALLPACKAGE_CLASSES_STUB_INTERFACE_PLACEHOLDER"; public const string INTERFACE_CONSTRAINT = "ALLPACKAGE_CLASSES_STUB_CLASS_INTERFACE_PLACEHOLDER"; @@ -127,6 +128,7 @@ public class ClassStub public const string BASEINTERFACE = "ALLPACKAGE_CLASSES_STUB_BASEINTERFACE_PLACEHOLDER"; public const string WHERECLAUSES = "ALLPACKAGE_CLASSES_STUB_WHERECLAUSES_PLACEHOLDER"; public const string JAVACLASS = "ALLPACKAGE_CLASSES_STUB_JAVACLASS_PLACEHOLDER"; + public const string JAVACLASS_DIRECT = "ALLPACKAGE_CLASSES_STUB_JAVACLASS_DIRECT_PLACEHOLDER"; public const string CONSTRUCTORS = "// ALLPACKAGE_CLASSES_STUB_CONSTRUCTORS_PLACEHOLDER"; public const string OPERATORS = "// ALLPACKAGE_CLASSES_STUB_OPERATORS_PLACEHOLDER"; public const string FIELDS = "// ALLPACKAGE_CLASSES_STUB_FIELDS_PLACEHOLDER";