diff --git a/src/net/JNetReflector/InternalExtensions.cs b/src/net/JNetReflector/InternalExtensions.cs index b7aa7666e2..a2e012652f 100644 --- a/src/net/JNetReflector/InternalExtensions.cs +++ b/src/net/JNetReflector/InternalExtensions.cs @@ -323,17 +323,36 @@ public static string AddClassNameToSignature(this string methodSignature, string return methodSignature; } - public static string SignatureFromGenericString(this IReadOnlyDictionary methodSignatures, Method entry) + public static string SignatureFromGenericString(this Method entry) { var filteredGenString = entry.GenericString.RemoveThrowsAndCleanupSignature(); - string signature = null; - if (!methodSignatures.TryGetValue(filteredGenString, out signature)) + string signature = SignatureFromGenericString(filteredGenString, entry.DeclaringClass); + if (signature == null) { ReflectionUtils.ReportTrace(ReflectionUtils.ReflectionTraceLevel.Critical, $"SignatureFromGenericString: signature not found for method {entry.Name} (Generic string: {entry.GenericString}) of class {entry.DeclaringClass.TypeName} using {filteredGenString} not found."); } return signature; } + static string SignatureFromGenericString(string filteredGenString, Class checkClass) + { + if (checkClass == null || checkClass.TypeName == "java.lang.Object") return null; + var methodSignatures = JNetReflectorHelper.SignatureForClass(checkClass); + string signature = null; + if (methodSignatures.TryGetValue(filteredGenString, out signature)) + { + return signature; + } + try + { + return SignatureFromGenericString(filteredGenString, checkClass.SuperClass); + } + catch + { + return null; + } + } + #endregion #region ZipArchiveEntry extension @@ -364,6 +383,12 @@ public static bool IsFolder(this ZipArchiveEntry entry) return false; } + public static bool IsClass(this ZipArchiveEntry entry) + { + if (entry.Name.Contains(SpecialNames.ClassExtension)) return true; + return false; + } + public static bool IsJVMNestedClass(this ZipArchiveEntry entry) { if (entry.Length != 0 @@ -1632,7 +1657,7 @@ public static bool IsSpecialClass(this Class entry) return true; } - string className = entry.JVMNestedClassName(entry.JVMNestingLevels(), null, true, false); + string className = entry.JVMNestedClassName(entry.JVMNestingLevels(), null, true, false, true); if (entry.IsJVMNestedClass() && SpecialNames.SpecialNumberedNames.Any((o) => className.StartsWith(o))) return true; diff --git a/src/net/JNetReflector/InternalMethods.cs b/src/net/JNetReflector/InternalMethods.cs index f14caff689..018267f424 100644 --- a/src/net/JNetReflector/InternalMethods.cs +++ b/src/net/JNetReflector/InternalMethods.cs @@ -201,6 +201,7 @@ public static void AnalyzeJar(string pathToJar, string javadocUrl, int javadocVe ReportTrace(ReflectionTraceLevel.Debug, "Entry {0}", entry.ToString()); if (entry.IsSpecialFolder()) continue; // do not reflect this folders if (entry.IsFolder()) continue; // do not reflect this folders + if (!entry.IsClass()) continue; // reflect only Java classes, this speed up next line avoiding too many excpetions var jClass = entry.JVMClass(); if (jClass != null && (jClass.IsJVMClass() || jClass.IsJVMNestedClass())) @@ -248,6 +249,25 @@ public static void AnalyzeNamespace(IDictionary>> items) { + if (JNetReflectorCore.PreferMethodWithSignature) + { + try + { + ParallelOptions po = new ParallelOptions(); + Console.CancelKeyPress += Console_CancelKeyPress; + CancellationTokenSource = new CancellationTokenSource(); + CancellationTokenSource.Token.ThrowIfCancellationRequested(); + po.CancellationToken = CancellationTokenSource.Token; + po.MaxDegreeOfParallelism = System.Environment.ProcessorCount; + Parallel.ForEach(items, po, ExtractSignatureParallel); + } + finally + { + CancellationTokenSource = null; + Console.CancelKeyPress -= Console_CancelKeyPress; + } + } + if (!JNetReflectorCore.AvoidParallelBuild) { try @@ -292,33 +312,43 @@ static void AnalyzeSubItemsParallel(KeyValuePair> items, string jarOrModuleName) + static void ExtractSignatureParallel(KeyValuePair>> items) { - var allPackageClasses = Template.GetTemplate(Template.AllPackageClassesTemplate); - - ReportTrace(ReflectionTraceLevel.Info, "Starting analysis for package {0}", package); - StringBuilder sb = new StringBuilder(); - - IDictionary> signaturesForClasses = null; - if (JNetReflectorCore.PreferMethodWithSignature) + try { List classes = new List(); - foreach (var entry in items) + foreach (var entry in items.Value) { classes.AddRange(entry.Value.Values); } - - signaturesForClasses = JNetReflectorHelper.ExtractJavaInfo(classes, JNetReflectorCore.CurrentClassPath, JNetReflectorCore.JavaPLocationPath); + JNetReflectorHelper.ExtractJavaInfo(classes, JNetReflectorCore.CurrentClassPath, JNetReflectorCore.JavaPLocationPath); + } + catch (OperationCanceledException) + { + throw; + } + catch (System.Exception e) + { + ReportTrace(ReflectionTraceLevel.Error, "Error in ExtractSignatureParallel for package {0}: {1}", items.Key, e.Message); + throw; } + } + + static void AnalyzeSubItems(string package, IDictionary> items, string jarOrModuleName) + { + var allPackageClasses = Template.GetTemplate(Template.AllPackageClassesTemplate); + + ReportTrace(ReflectionTraceLevel.Info, "Starting analysis for package {0}", package); + StringBuilder sb = new StringBuilder(); foreach (var entry in items) { - var classContent = AnalyzeClasses(jarOrModuleName, entry.Value.Values, signaturesForClasses); + var classContent = AnalyzeClasses(jarOrModuleName, entry.Value.Values); if (!string.IsNullOrEmpty(classContent)) { sb.AppendLine(classContent); @@ -364,7 +394,7 @@ static void AnalyzeSubItems(string package, IDictionary classDefinitions, IDictionary> signaturesForClasses) + static string AnalyzeClasses(string jarOrModuleName, IEnumerable classDefinitions) { ReportTrace(ReflectionTraceLevel.Info, "******************* AnalyzeClass {0} *******************", jarOrModuleName); @@ -441,12 +471,10 @@ static string AnalyzeClasses(string jarOrModuleName, IEnumerable classDef string subInterfaceStr; AnalyzeNestedClasses(nestedClasses, classDefinitions, out subClassStr, out nestedBlock, out subInterfaceStr); - IReadOnlyDictionary signatures = null; - signaturesForClasses?.TryGetValue(jClass, out signatures); string classBlock; string singleClassStr; string singleInterfaceStr; - jClass.PrepareSingleClass(signatures, classDefinitions, false, out classBlock, out singleClassStr, out singleInterfaceStr); + jClass.PrepareSingleClass(classDefinitions, false, out classBlock, out singleClassStr, out singleInterfaceStr); singleInterfaceStr = singleInterfaceStr.Replace(AllPackageClasses.ClassStub.NESTED_INTERFACES, string.IsNullOrWhiteSpace(subInterfaceStr) ? string.Empty : subInterfaceStr); singleInterfaceStr = singleInterfaceStr.AddTabLevel(1); @@ -475,7 +503,7 @@ static string AnalyzeClasses(string jarOrModuleName, IEnumerable classDef string singleInterfaceGenericStr; if (!JNetReflectorCore.AvoidCSharpGenericDefinition && jClass.IsJVMGenericClass() && !jClass.IsClassToAvoidInGenerics()) { - jClass.PrepareSingleClass(signatures, classDefinitions, true, out classGenericBlock, out singleClassGenericStr, out singleInterfaceGenericStr); + jClass.PrepareSingleClass(classDefinitions, true, out classGenericBlock, out singleClassGenericStr, out singleInterfaceGenericStr); singleClassGenericStr = singleClassGenericStr.Replace(AllPackageClasses.ClassStub.NESTED_CLASSES, string.Empty); singleInterfaceGenericStr = singleInterfaceGenericStr.Replace(AllPackageClasses.ClassStub.NESTED_INTERFACES, string.Empty); classGenericBlock = classGenericBlock.AddTabLevel(1); @@ -526,12 +554,6 @@ static void AnalyzeNestedClasses(IEnumerable nestedClasses, IEnumerable> signaturesForNestedClasses = null; - if (JNetReflectorCore.PreferMethodWithSignature) - { - signaturesForNestedClasses = JNetReflectorHelper.ExtractJavaInfo(nestedClasses, JNetReflectorCore.CurrentClassPath, JNetReflectorCore.JavaPLocationPath); - } - foreach (var entry in nestedClasses) { string innerNestedClassBlock = string.Empty; @@ -550,9 +572,7 @@ static void AnalyzeNestedClasses(IEnumerable nestedClasses, IEnumerable signatures = null; - signaturesForNestedClasses?.TryGetValue(entry, out signatures); - entry.PrepareSingleClass(signatures, classDefinitions, false, out nestedClassBlock, out singleNestedClassStr, out singleNestedInterfaceStr); + entry.PrepareSingleClass(classDefinitions, false, out nestedClassBlock, out singleNestedClassStr, out singleNestedInterfaceStr); nestedClassBlock = nestedClassBlock.Replace(AllPackageClasses.ClassStub.NESTED_CLASSES, string.IsNullOrWhiteSpace(innerNestedClassBlock) ? string.Empty : innerNestedClassBlock); singleNestedClassStr = singleNestedClassStr.Replace(AllPackageClasses.ClassStub.NESTED_CLASSES, string.IsNullOrWhiteSpace(innerSingleNestedClassStr) ? string.Empty : innerSingleNestedClassStr); singleNestedInterfaceStr = singleNestedInterfaceStr.Replace(AllPackageClasses.ClassStub.NESTED_INTERFACES, string.IsNullOrWhiteSpace(innerSingleNestedInterfaceStr) ? string.Empty : innerSingleNestedInterfaceStr); @@ -593,7 +613,7 @@ static void AnalyzeNestedClasses(IEnumerable nestedClasses, IEnumerable nestedClasses, IEnumerable signatures, IEnumerable classDefinitions, bool isGeneric, out string allPackagesClassBlock, out string singleClassStr, out string singleInterfaceStr) + static void PrepareSingleClass(this Class jClass, IEnumerable classDefinitions, bool isGeneric, out string allPackagesClassBlock, out string singleClassStr, out string singleInterfaceStr) { if (jClass.IsJNetInternalOrManuallyDeveloped()) { @@ -748,8 +768,8 @@ static void PrepareSingleClass(this Class jClass, IReadOnlyDictionary PrefilterMethods(this Class classDefinition, out bool isMai return prefilteredMethods; } - static string AnalyzeMethods(this Class classDefinition, IReadOnlyDictionary methodsToSignature, IEnumerable classDefinitions, IList prefilteredMethods, bool isGeneric, bool forInterface, bool forListener, bool isDirectListener, bool staticMethods) + static string AnalyzeMethods(this Class classDefinition, IEnumerable classDefinitions, IList prefilteredMethods, bool isGeneric, bool forInterface, bool forListener, bool isDirectListener, bool staticMethods) { ReportTrace(ReflectionTraceLevel.Info, "******************* Analyze Methods of {0} with static {1} *******************", classDefinition.GenericString, staticMethods); @@ -1423,7 +1443,7 @@ static string AnalyzeMethods(this Class classDefinition, IReadOnlyDictionary if comes from super interface public static bool IsFromSuperInterface(Method entry) => SExecute("isFromSuperInterface", entry); - public static IDictionary> ExtractJavaInfo(IEnumerable classes, string classPath, string javapFullPath = null) + static ConcurrentDictionary> signatureDict = new ConcurrentDictionary>(); + + public static IReadOnlyDictionary SignatureForClass(Class entry) + { + signatureDict.TryGetValue(entry.TypeName, out var signature); + return signature; + } + + public static void ExtractJavaInfo(IEnumerable classes, string classPath, string javapFullPath = null) { const int argumentLengthLimit = 32699; // from MSDN List localList = new List(classes); - var dict = new ConcurrentDictionary>(); string baseArgumentStr = string.IsNullOrWhiteSpace(classPath) ? string.Empty : $"-cp {classPath} " + "-s "; if (baseArgumentStr.Length > argumentLengthLimit) { @@ -174,7 +181,7 @@ public static IDictionary> ExtractJav { if (line.Contains("Compiled from")) { - if (classCounter != -1) { dict.TryAdd(toBeAnalyzed[classCounter], map); } + if (classCounter != -1) { signatureDict.TryAdd(toBeAnalyzed[classCounter].TypeName, map); } classCounter++; className = toBeAnalyzed[classCounter].Name; map = new Dictionary(); @@ -206,7 +213,7 @@ public static IDictionary> ExtractJav } while (cycleCounter < 100); #endif - dict.TryAdd(toBeAnalyzed[classCounter], map); + signatureDict.TryAdd(toBeAnalyzed[classCounter].TypeName, map); } catch { } finally @@ -214,8 +221,6 @@ public static IDictionary> ExtractJav if (!exited && !process.HasExited) try { process?.Kill(); } catch { } } } - - return dict; } public static IReadOnlyDictionary ExtractJavaInfo(Class clazz, string classPath, string javapFullPath = null)