konpeito 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-version +1 -0
  3. data/CHANGELOG.md +75 -0
  4. data/CONTRIBUTING.md +123 -0
  5. data/LICENSE +21 -0
  6. data/README.md +257 -0
  7. data/Rakefile +11 -0
  8. data/bin/konpeito +6 -0
  9. data/konpeito.gemspec +43 -0
  10. data/lib/konpeito/ast/typed_ast.rb +620 -0
  11. data/lib/konpeito/ast/visitor.rb +78 -0
  12. data/lib/konpeito/cache/cache_manager.rb +230 -0
  13. data/lib/konpeito/cache/dependency_graph.rb +192 -0
  14. data/lib/konpeito/cache.rb +8 -0
  15. data/lib/konpeito/cli/base_command.rb +187 -0
  16. data/lib/konpeito/cli/build_command.rb +220 -0
  17. data/lib/konpeito/cli/check_command.rb +104 -0
  18. data/lib/konpeito/cli/config.rb +231 -0
  19. data/lib/konpeito/cli/deps_command.rb +128 -0
  20. data/lib/konpeito/cli/doctor_command.rb +340 -0
  21. data/lib/konpeito/cli/fmt_command.rb +199 -0
  22. data/lib/konpeito/cli/init_command.rb +312 -0
  23. data/lib/konpeito/cli/lsp_command.rb +40 -0
  24. data/lib/konpeito/cli/run_command.rb +150 -0
  25. data/lib/konpeito/cli/test_command.rb +248 -0
  26. data/lib/konpeito/cli/watch_command.rb +212 -0
  27. data/lib/konpeito/cli.rb +301 -0
  28. data/lib/konpeito/codegen/builtin_methods.rb +229 -0
  29. data/lib/konpeito/codegen/cruby_backend.rb +1090 -0
  30. data/lib/konpeito/codegen/debug_info.rb +352 -0
  31. data/lib/konpeito/codegen/inliner.rb +486 -0
  32. data/lib/konpeito/codegen/jvm_backend.rb +197 -0
  33. data/lib/konpeito/codegen/jvm_generator.rb +13412 -0
  34. data/lib/konpeito/codegen/llvm_generator.rb +13191 -0
  35. data/lib/konpeito/codegen/loop_optimizer.rb +363 -0
  36. data/lib/konpeito/codegen/monomorphizer.rb +359 -0
  37. data/lib/konpeito/codegen/profile_runtime.c +341 -0
  38. data/lib/konpeito/codegen/profiler.rb +99 -0
  39. data/lib/konpeito/compiler.rb +592 -0
  40. data/lib/konpeito/dependency_resolver.rb +296 -0
  41. data/lib/konpeito/diagnostics/collector.rb +127 -0
  42. data/lib/konpeito/diagnostics/diagnostic.rb +237 -0
  43. data/lib/konpeito/diagnostics/renderer.rb +144 -0
  44. data/lib/konpeito/formatter/formatter.rb +1214 -0
  45. data/lib/konpeito/hir/builder.rb +7167 -0
  46. data/lib/konpeito/hir/nodes.rb +2465 -0
  47. data/lib/konpeito/lsp/document_manager.rb +820 -0
  48. data/lib/konpeito/lsp/server.rb +183 -0
  49. data/lib/konpeito/lsp/transport.rb +38 -0
  50. data/lib/konpeito/parser/prism_adapter.rb +65 -0
  51. data/lib/konpeito/platform.rb +103 -0
  52. data/lib/konpeito/profile/report.rb +136 -0
  53. data/lib/konpeito/rbs_inline/preprocessor.rb +199 -0
  54. data/lib/konpeito/stdlib/compression/compression.rb +72 -0
  55. data/lib/konpeito/stdlib/compression/compression.rbs +60 -0
  56. data/lib/konpeito/stdlib/compression/compression_native.c +415 -0
  57. data/lib/konpeito/stdlib/compression/extconf.rb +19 -0
  58. data/lib/konpeito/stdlib/crypto/crypto.rb +85 -0
  59. data/lib/konpeito/stdlib/crypto/crypto.rbs +74 -0
  60. data/lib/konpeito/stdlib/crypto/crypto_native.c +312 -0
  61. data/lib/konpeito/stdlib/crypto/extconf.rb +40 -0
  62. data/lib/konpeito/stdlib/http/extconf.rb +19 -0
  63. data/lib/konpeito/stdlib/http/http.rb +125 -0
  64. data/lib/konpeito/stdlib/http/http.rbs +57 -0
  65. data/lib/konpeito/stdlib/http/http_native.c +440 -0
  66. data/lib/konpeito/stdlib/json/extconf.rb +17 -0
  67. data/lib/konpeito/stdlib/json/json.rb +44 -0
  68. data/lib/konpeito/stdlib/json/json.rbs +33 -0
  69. data/lib/konpeito/stdlib/json/json_native.c +286 -0
  70. data/lib/konpeito/stdlib/ui/extconf.rb +216 -0
  71. data/lib/konpeito/stdlib/ui/konpeito_ui_native.cpp +1625 -0
  72. data/lib/konpeito/stdlib/ui/konpeito_ui_native.h +162 -0
  73. data/lib/konpeito/stdlib/ui/ui.rb +318 -0
  74. data/lib/konpeito/stdlib/ui/ui.rbs +247 -0
  75. data/lib/konpeito/type_checker/annotation_parser.rb +67 -0
  76. data/lib/konpeito/type_checker/hm_inferrer.rb +2565 -0
  77. data/lib/konpeito/type_checker/inferrer.rb +565 -0
  78. data/lib/konpeito/type_checker/rbs_loader.rb +1621 -0
  79. data/lib/konpeito/type_checker/type_resolver.rb +276 -0
  80. data/lib/konpeito/type_checker/types.rb +1434 -0
  81. data/lib/konpeito/type_checker/unification.rb +323 -0
  82. data/lib/konpeito/ui/animation/animated_state.rb +80 -0
  83. data/lib/konpeito/ui/animation/easing.rb +59 -0
  84. data/lib/konpeito/ui/animation/value_tween.rb +66 -0
  85. data/lib/konpeito/ui/app.rb +379 -0
  86. data/lib/konpeito/ui/box.rb +38 -0
  87. data/lib/konpeito/ui/castella.rb +70 -0
  88. data/lib/konpeito/ui/castella_native.rb +76 -0
  89. data/lib/konpeito/ui/chart/area_chart.rb +305 -0
  90. data/lib/konpeito/ui/chart/bar_chart.rb +288 -0
  91. data/lib/konpeito/ui/chart/base_chart.rb +210 -0
  92. data/lib/konpeito/ui/chart/chart_helpers.rb +79 -0
  93. data/lib/konpeito/ui/chart/gauge_chart.rb +171 -0
  94. data/lib/konpeito/ui/chart/heatmap_chart.rb +222 -0
  95. data/lib/konpeito/ui/chart/line_chart.rb +289 -0
  96. data/lib/konpeito/ui/chart/pie_chart.rb +219 -0
  97. data/lib/konpeito/ui/chart/scales.rb +77 -0
  98. data/lib/konpeito/ui/chart/scatter_chart.rb +303 -0
  99. data/lib/konpeito/ui/chart/stacked_bar_chart.rb +276 -0
  100. data/lib/konpeito/ui/column.rb +271 -0
  101. data/lib/konpeito/ui/core.rb +2199 -0
  102. data/lib/konpeito/ui/dsl.rb +443 -0
  103. data/lib/konpeito/ui/frame.rb +171 -0
  104. data/lib/konpeito/ui/frame_native.rb +494 -0
  105. data/lib/konpeito/ui/markdown/ast.rb +124 -0
  106. data/lib/konpeito/ui/markdown/mermaid/layout.rb +387 -0
  107. data/lib/konpeito/ui/markdown/mermaid/models.rb +232 -0
  108. data/lib/konpeito/ui/markdown/mermaid/parser.rb +519 -0
  109. data/lib/konpeito/ui/markdown/mermaid/renderer.rb +336 -0
  110. data/lib/konpeito/ui/markdown/parser.rb +805 -0
  111. data/lib/konpeito/ui/markdown/renderer.rb +639 -0
  112. data/lib/konpeito/ui/markdown/theme.rb +165 -0
  113. data/lib/konpeito/ui/render_node.rb +260 -0
  114. data/lib/konpeito/ui/row.rb +207 -0
  115. data/lib/konpeito/ui/spacer.rb +18 -0
  116. data/lib/konpeito/ui/style.rb +799 -0
  117. data/lib/konpeito/ui/theme.rb +563 -0
  118. data/lib/konpeito/ui/themes/material.rb +35 -0
  119. data/lib/konpeito/ui/themes/tokyo_night.rb +6 -0
  120. data/lib/konpeito/ui/widgets/button.rb +103 -0
  121. data/lib/konpeito/ui/widgets/calendar.rb +1034 -0
  122. data/lib/konpeito/ui/widgets/checkbox.rb +119 -0
  123. data/lib/konpeito/ui/widgets/container.rb +91 -0
  124. data/lib/konpeito/ui/widgets/data_table.rb +667 -0
  125. data/lib/konpeito/ui/widgets/divider.rb +29 -0
  126. data/lib/konpeito/ui/widgets/image.rb +105 -0
  127. data/lib/konpeito/ui/widgets/input.rb +485 -0
  128. data/lib/konpeito/ui/widgets/markdown.rb +57 -0
  129. data/lib/konpeito/ui/widgets/modal.rb +163 -0
  130. data/lib/konpeito/ui/widgets/multiline_input.rb +968 -0
  131. data/lib/konpeito/ui/widgets/multiline_text.rb +180 -0
  132. data/lib/konpeito/ui/widgets/net_image.rb +100 -0
  133. data/lib/konpeito/ui/widgets/progress_bar.rb +70 -0
  134. data/lib/konpeito/ui/widgets/radio_buttons.rb +93 -0
  135. data/lib/konpeito/ui/widgets/slider.rb +133 -0
  136. data/lib/konpeito/ui/widgets/switch.rb +84 -0
  137. data/lib/konpeito/ui/widgets/tabs.rb +157 -0
  138. data/lib/konpeito/ui/widgets/text.rb +110 -0
  139. data/lib/konpeito/ui/widgets/tree.rb +426 -0
  140. data/lib/konpeito/version.rb +5 -0
  141. data/lib/konpeito.rb +109 -0
  142. data/test_native_array.rb +172 -0
  143. data/test_native_array_class.rb +197 -0
  144. data/test_native_class.rb +151 -0
  145. data/tools/konpeito-asm/build.sh +65 -0
  146. data/tools/konpeito-asm/lib/asm-9.7.1.jar +0 -0
  147. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KArray.class +0 -0
  148. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KCompression.class +0 -0
  149. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KConditionVariable.class +0 -0
  150. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KCrypto.class +0 -0
  151. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KFile.class +0 -0
  152. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KHTTP.class +0 -0
  153. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KHash.class +0 -0
  154. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KJSON$Parser.class +0 -0
  155. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KJSON.class +0 -0
  156. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KMath.class +0 -0
  157. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KRactor.class +0 -0
  158. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KRactorPort.class +0 -0
  159. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KSizedQueue.class +0 -0
  160. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KThread.class +0 -0
  161. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KTime.class +0 -0
  162. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/RubyDispatch.class +0 -0
  163. data/tools/konpeito-asm/src/ClassIntrospector.java +312 -0
  164. data/tools/konpeito-asm/src/KonpeitoAssembler.java +659 -0
  165. data/tools/konpeito-asm/src/konpeito/runtime/KArray.java +390 -0
  166. data/tools/konpeito-asm/src/konpeito/runtime/KCompression.java +168 -0
  167. data/tools/konpeito-asm/src/konpeito/runtime/KConditionVariable.java +48 -0
  168. data/tools/konpeito-asm/src/konpeito/runtime/KCrypto.java +151 -0
  169. data/tools/konpeito-asm/src/konpeito/runtime/KFile.java +100 -0
  170. data/tools/konpeito-asm/src/konpeito/runtime/KHTTP.java +113 -0
  171. data/tools/konpeito-asm/src/konpeito/runtime/KHash.java +228 -0
  172. data/tools/konpeito-asm/src/konpeito/runtime/KJSON.java +405 -0
  173. data/tools/konpeito-asm/src/konpeito/runtime/KMath.java +54 -0
  174. data/tools/konpeito-asm/src/konpeito/runtime/KRactor.java +244 -0
  175. data/tools/konpeito-asm/src/konpeito/runtime/KRactorPort.java +53 -0
  176. data/tools/konpeito-asm/src/konpeito/runtime/KSizedQueue.java +49 -0
  177. data/tools/konpeito-asm/src/konpeito/runtime/KThread.java +49 -0
  178. data/tools/konpeito-asm/src/konpeito/runtime/KTime.java +53 -0
  179. data/tools/konpeito-asm/src/konpeito/runtime/RubyDispatch.java +416 -0
  180. metadata +267 -0
@@ -0,0 +1,312 @@
1
+ package com.konpeito.asm;
2
+
3
+ import org.objectweb.asm.*;
4
+ import java.io.*;
5
+ import java.nio.file.*;
6
+ import java.util.*;
7
+ import java.util.jar.*;
8
+
9
+ /**
10
+ * ClassIntrospector: Reads .class files from classpath using ASM ClassReader
11
+ * and outputs method signatures as JSON.
12
+ *
13
+ * Usage: java -jar konpeito-asm.jar --introspect
14
+ *
15
+ * Reads JSON request from stdin:
16
+ * { "classpath": "path1:path2:...", "classes": ["com/example/Foo", ...] }
17
+ *
18
+ * Writes JSON response to stdout with method descriptors, constructors,
19
+ * inner classes, and SAM interface detection.
20
+ */
21
+ public class ClassIntrospector {
22
+
23
+ public static void run() throws Exception {
24
+ // Read JSON request from stdin
25
+ String json;
26
+ try (var reader = new BufferedReader(new InputStreamReader(System.in))) {
27
+ var sb = new StringBuilder();
28
+ String line;
29
+ while ((line = reader.readLine()) != null) {
30
+ sb.append(line).append('\n');
31
+ }
32
+ json = sb.toString();
33
+ }
34
+
35
+ var parser = new KonpeitoAssembler.JsonParser(json);
36
+ var request = parser.parseObject();
37
+
38
+ String classpath = (String) request.get("classpath");
39
+ @SuppressWarnings("unchecked")
40
+ List<Object> classNames = (List<Object>) request.get("classes");
41
+
42
+ if (classpath == null || classNames == null) {
43
+ System.err.println("Error: request must have 'classpath' and 'classes' keys");
44
+ System.exit(1);
45
+ }
46
+
47
+ var introspector = new ClassIntrospector();
48
+ var result = introspector.introspect(classpath, classNames);
49
+
50
+ // Output JSON
51
+ System.out.println(result);
52
+ }
53
+
54
+ /**
55
+ * Introspect the given classes from the classpath.
56
+ */
57
+ public String introspect(String classpath, List<Object> classNames) throws Exception {
58
+ // Build classpath entries
59
+ List<Path> entries = new ArrayList<>();
60
+ for (String entry : classpath.split(":")) {
61
+ Path p = Path.of(entry.trim());
62
+ if (Files.exists(p)) {
63
+ entries.add(p);
64
+ }
65
+ }
66
+
67
+ // Collect results
68
+ Map<String, ClassInfo> results = new LinkedHashMap<>();
69
+
70
+ for (Object nameObj : classNames) {
71
+ String className = (String) nameObj;
72
+ byte[] classBytes = findClassBytes(entries, className);
73
+ if (classBytes != null) {
74
+ ClassInfo info = analyzeClass(classBytes);
75
+ results.put(className, info);
76
+
77
+ // Also introspect inner classes referenced by this class
78
+ for (String innerName : info.innerClassNames) {
79
+ if (!results.containsKey(innerName)) {
80
+ byte[] innerBytes = findClassBytes(entries, innerName);
81
+ if (innerBytes != null) {
82
+ ClassInfo innerInfo = analyzeClass(innerBytes);
83
+ // Store inner class info within the parent
84
+ info.innerClasses.put(innerName, innerInfo);
85
+ }
86
+ }
87
+ }
88
+ }
89
+ }
90
+
91
+ return toJson(results);
92
+ }
93
+
94
+ /**
95
+ * Find .class bytes from classpath entries (JAR files or directories).
96
+ */
97
+ private byte[] findClassBytes(List<Path> entries, String className) throws Exception {
98
+ String classFilePath = className + ".class";
99
+
100
+ for (Path entry : entries) {
101
+ if (Files.isDirectory(entry)) {
102
+ // Directory: look for className.class
103
+ Path classFile = entry.resolve(classFilePath);
104
+ if (Files.exists(classFile)) {
105
+ return Files.readAllBytes(classFile);
106
+ }
107
+ } else if (entry.toString().endsWith(".jar")) {
108
+ // JAR file: look inside
109
+ try (JarFile jar = new JarFile(entry.toFile())) {
110
+ JarEntry jarEntry = jar.getJarEntry(classFilePath);
111
+ if (jarEntry != null) {
112
+ try (InputStream is = jar.getInputStream(jarEntry)) {
113
+ return is.readAllBytes();
114
+ }
115
+ }
116
+ }
117
+ }
118
+ }
119
+ return null;
120
+ }
121
+
122
+ /**
123
+ * Analyze a single .class file using ASM ClassReader.
124
+ */
125
+ private ClassInfo analyzeClass(byte[] classBytes) {
126
+ ClassInfo info = new ClassInfo();
127
+ ClassReader reader = new ClassReader(classBytes);
128
+
129
+ reader.accept(new ClassVisitor(Opcodes.ASM9) {
130
+ @Override
131
+ public void visit(int version, int access, String name, String signature,
132
+ String superName, String[] interfaces) {
133
+ info.isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
134
+ if (interfaces != null) {
135
+ info.interfaces.addAll(Arrays.asList(interfaces));
136
+ }
137
+ }
138
+
139
+ @Override
140
+ public void visitInnerClass(String name, String outerName, String innerName, int access) {
141
+ // Track inner classes that belong to the class being analyzed
142
+ if (outerName != null) {
143
+ info.innerClassNames.add(name);
144
+ }
145
+ }
146
+
147
+ @Override
148
+ public FieldVisitor visitField(int access, String name, String descriptor,
149
+ String signature, Object value) {
150
+ // Only public, non-synthetic fields
151
+ if ((access & Opcodes.ACC_PUBLIC) == 0) return null;
152
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) return null;
153
+
154
+ if ((access & Opcodes.ACC_STATIC) != 0) {
155
+ info.staticFields.put(name, descriptor);
156
+ } else {
157
+ info.fields.put(name, descriptor);
158
+ }
159
+ return null;
160
+ }
161
+
162
+ @Override
163
+ public MethodVisitor visitMethod(int access, String name, String descriptor,
164
+ String signature, String[] exceptions) {
165
+ // Only public methods
166
+ if ((access & Opcodes.ACC_PUBLIC) == 0) return null;
167
+
168
+ // Skip bridge/synthetic methods
169
+ if ((access & Opcodes.ACC_BRIDGE) != 0) return null;
170
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) return null;
171
+
172
+ if (name.equals("<init>")) {
173
+ // Constructor
174
+ info.constructorDescriptor = descriptor;
175
+ } else if (name.equals("<clinit>")) {
176
+ // Class initializer - skip
177
+ } else if ((access & Opcodes.ACC_STATIC) != 0) {
178
+ // Static method
179
+ info.staticMethods.put(name, descriptor);
180
+ } else if ((access & Opcodes.ACC_ABSTRACT) != 0) {
181
+ // Abstract method (for SAM interface detection)
182
+ info.abstractMethods.put(name, descriptor);
183
+ info.methods.put(name, descriptor);
184
+ } else {
185
+ // Instance method
186
+ info.methods.put(name, descriptor);
187
+ }
188
+
189
+ return null;
190
+ }
191
+ }, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
192
+
193
+ return info;
194
+ }
195
+
196
+ /**
197
+ * Convert results to JSON string.
198
+ */
199
+ private String toJson(Map<String, ClassInfo> results) {
200
+ var sb = new StringBuilder();
201
+ sb.append("{\"classes\":{");
202
+
203
+ boolean firstClass = true;
204
+ for (var entry : results.entrySet()) {
205
+ if (!firstClass) sb.append(",");
206
+ firstClass = false;
207
+
208
+ sb.append("\"").append(escapeJson(entry.getKey())).append("\":");
209
+ classInfoToJson(sb, entry.getValue());
210
+ }
211
+
212
+ sb.append("}}");
213
+ return sb.toString();
214
+ }
215
+
216
+ private void classInfoToJson(StringBuilder sb, ClassInfo info) {
217
+ sb.append("{");
218
+
219
+ // methods
220
+ sb.append("\"methods\":{");
221
+ methodMapToJson(sb, info.methods);
222
+ sb.append("},");
223
+
224
+ // static_methods
225
+ sb.append("\"static_methods\":{");
226
+ methodMapToJson(sb, info.staticMethods);
227
+ sb.append("},");
228
+
229
+ // constructor
230
+ if (info.constructorDescriptor != null) {
231
+ sb.append("\"constructor\":{\"descriptor\":\"")
232
+ .append(escapeJson(info.constructorDescriptor)).append("\"},");
233
+ } else {
234
+ sb.append("\"constructor\":null,");
235
+ }
236
+
237
+ // is_interface
238
+ sb.append("\"is_interface\":").append(info.isInterface).append(",");
239
+
240
+ // interfaces
241
+ sb.append("\"interfaces\":[");
242
+ boolean first = true;
243
+ for (String iface : info.interfaces) {
244
+ if (!first) sb.append(",");
245
+ first = false;
246
+ sb.append("\"").append(escapeJson(iface)).append("\"");
247
+ }
248
+ sb.append("],");
249
+
250
+ // abstract_methods (for SAM detection)
251
+ sb.append("\"abstract_methods\":{");
252
+ methodMapToJson(sb, info.abstractMethods);
253
+ sb.append("},");
254
+
255
+ // fields
256
+ sb.append("\"fields\":{");
257
+ methodMapToJson(sb, info.fields);
258
+ sb.append("},");
259
+
260
+ // static_fields
261
+ sb.append("\"static_fields\":{");
262
+ methodMapToJson(sb, info.staticFields);
263
+ sb.append("},");
264
+
265
+ // inner_classes
266
+ sb.append("\"inner_classes\":{");
267
+ boolean firstInner = true;
268
+ for (var innerEntry : info.innerClasses.entrySet()) {
269
+ if (!firstInner) sb.append(",");
270
+ firstInner = false;
271
+ sb.append("\"").append(escapeJson(innerEntry.getKey())).append("\":");
272
+ classInfoToJson(sb, innerEntry.getValue());
273
+ }
274
+ sb.append("}");
275
+
276
+ sb.append("}");
277
+ }
278
+
279
+ private void methodMapToJson(StringBuilder sb, Map<String, String> methods) {
280
+ boolean first = true;
281
+ for (var entry : methods.entrySet()) {
282
+ if (!first) sb.append(",");
283
+ first = false;
284
+ sb.append("\"").append(escapeJson(entry.getKey())).append("\":")
285
+ .append("{\"descriptor\":\"").append(escapeJson(entry.getValue())).append("\"}");
286
+ }
287
+ }
288
+
289
+ private String escapeJson(String s) {
290
+ return s.replace("\\", "\\\\")
291
+ .replace("\"", "\\\"")
292
+ .replace("\n", "\\n")
293
+ .replace("\r", "\\r")
294
+ .replace("\t", "\\t");
295
+ }
296
+
297
+ /**
298
+ * Internal class to hold introspection results for a single class.
299
+ */
300
+ static class ClassInfo {
301
+ Map<String, String> methods = new LinkedHashMap<>();
302
+ Map<String, String> staticMethods = new LinkedHashMap<>();
303
+ Map<String, String> abstractMethods = new LinkedHashMap<>();
304
+ Map<String, String> fields = new LinkedHashMap<>();
305
+ Map<String, String> staticFields = new LinkedHashMap<>();
306
+ String constructorDescriptor = null;
307
+ boolean isInterface = false;
308
+ List<String> interfaces = new ArrayList<>();
309
+ List<String> innerClassNames = new ArrayList<>();
310
+ Map<String, ClassInfo> innerClasses = new LinkedHashMap<>();
311
+ }
312
+ }