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.
- checksums.yaml +7 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +75 -0
- data/CONTRIBUTING.md +123 -0
- data/LICENSE +21 -0
- data/README.md +257 -0
- data/Rakefile +11 -0
- data/bin/konpeito +6 -0
- data/konpeito.gemspec +43 -0
- data/lib/konpeito/ast/typed_ast.rb +620 -0
- data/lib/konpeito/ast/visitor.rb +78 -0
- data/lib/konpeito/cache/cache_manager.rb +230 -0
- data/lib/konpeito/cache/dependency_graph.rb +192 -0
- data/lib/konpeito/cache.rb +8 -0
- data/lib/konpeito/cli/base_command.rb +187 -0
- data/lib/konpeito/cli/build_command.rb +220 -0
- data/lib/konpeito/cli/check_command.rb +104 -0
- data/lib/konpeito/cli/config.rb +231 -0
- data/lib/konpeito/cli/deps_command.rb +128 -0
- data/lib/konpeito/cli/doctor_command.rb +340 -0
- data/lib/konpeito/cli/fmt_command.rb +199 -0
- data/lib/konpeito/cli/init_command.rb +312 -0
- data/lib/konpeito/cli/lsp_command.rb +40 -0
- data/lib/konpeito/cli/run_command.rb +150 -0
- data/lib/konpeito/cli/test_command.rb +248 -0
- data/lib/konpeito/cli/watch_command.rb +212 -0
- data/lib/konpeito/cli.rb +301 -0
- data/lib/konpeito/codegen/builtin_methods.rb +229 -0
- data/lib/konpeito/codegen/cruby_backend.rb +1090 -0
- data/lib/konpeito/codegen/debug_info.rb +352 -0
- data/lib/konpeito/codegen/inliner.rb +486 -0
- data/lib/konpeito/codegen/jvm_backend.rb +197 -0
- data/lib/konpeito/codegen/jvm_generator.rb +13412 -0
- data/lib/konpeito/codegen/llvm_generator.rb +13191 -0
- data/lib/konpeito/codegen/loop_optimizer.rb +363 -0
- data/lib/konpeito/codegen/monomorphizer.rb +359 -0
- data/lib/konpeito/codegen/profile_runtime.c +341 -0
- data/lib/konpeito/codegen/profiler.rb +99 -0
- data/lib/konpeito/compiler.rb +592 -0
- data/lib/konpeito/dependency_resolver.rb +296 -0
- data/lib/konpeito/diagnostics/collector.rb +127 -0
- data/lib/konpeito/diagnostics/diagnostic.rb +237 -0
- data/lib/konpeito/diagnostics/renderer.rb +144 -0
- data/lib/konpeito/formatter/formatter.rb +1214 -0
- data/lib/konpeito/hir/builder.rb +7167 -0
- data/lib/konpeito/hir/nodes.rb +2465 -0
- data/lib/konpeito/lsp/document_manager.rb +820 -0
- data/lib/konpeito/lsp/server.rb +183 -0
- data/lib/konpeito/lsp/transport.rb +38 -0
- data/lib/konpeito/parser/prism_adapter.rb +65 -0
- data/lib/konpeito/platform.rb +103 -0
- data/lib/konpeito/profile/report.rb +136 -0
- data/lib/konpeito/rbs_inline/preprocessor.rb +199 -0
- data/lib/konpeito/stdlib/compression/compression.rb +72 -0
- data/lib/konpeito/stdlib/compression/compression.rbs +60 -0
- data/lib/konpeito/stdlib/compression/compression_native.c +415 -0
- data/lib/konpeito/stdlib/compression/extconf.rb +19 -0
- data/lib/konpeito/stdlib/crypto/crypto.rb +85 -0
- data/lib/konpeito/stdlib/crypto/crypto.rbs +74 -0
- data/lib/konpeito/stdlib/crypto/crypto_native.c +312 -0
- data/lib/konpeito/stdlib/crypto/extconf.rb +40 -0
- data/lib/konpeito/stdlib/http/extconf.rb +19 -0
- data/lib/konpeito/stdlib/http/http.rb +125 -0
- data/lib/konpeito/stdlib/http/http.rbs +57 -0
- data/lib/konpeito/stdlib/http/http_native.c +440 -0
- data/lib/konpeito/stdlib/json/extconf.rb +17 -0
- data/lib/konpeito/stdlib/json/json.rb +44 -0
- data/lib/konpeito/stdlib/json/json.rbs +33 -0
- data/lib/konpeito/stdlib/json/json_native.c +286 -0
- data/lib/konpeito/stdlib/ui/extconf.rb +216 -0
- data/lib/konpeito/stdlib/ui/konpeito_ui_native.cpp +1625 -0
- data/lib/konpeito/stdlib/ui/konpeito_ui_native.h +162 -0
- data/lib/konpeito/stdlib/ui/ui.rb +318 -0
- data/lib/konpeito/stdlib/ui/ui.rbs +247 -0
- data/lib/konpeito/type_checker/annotation_parser.rb +67 -0
- data/lib/konpeito/type_checker/hm_inferrer.rb +2565 -0
- data/lib/konpeito/type_checker/inferrer.rb +565 -0
- data/lib/konpeito/type_checker/rbs_loader.rb +1621 -0
- data/lib/konpeito/type_checker/type_resolver.rb +276 -0
- data/lib/konpeito/type_checker/types.rb +1434 -0
- data/lib/konpeito/type_checker/unification.rb +323 -0
- data/lib/konpeito/ui/animation/animated_state.rb +80 -0
- data/lib/konpeito/ui/animation/easing.rb +59 -0
- data/lib/konpeito/ui/animation/value_tween.rb +66 -0
- data/lib/konpeito/ui/app.rb +379 -0
- data/lib/konpeito/ui/box.rb +38 -0
- data/lib/konpeito/ui/castella.rb +70 -0
- data/lib/konpeito/ui/castella_native.rb +76 -0
- data/lib/konpeito/ui/chart/area_chart.rb +305 -0
- data/lib/konpeito/ui/chart/bar_chart.rb +288 -0
- data/lib/konpeito/ui/chart/base_chart.rb +210 -0
- data/lib/konpeito/ui/chart/chart_helpers.rb +79 -0
- data/lib/konpeito/ui/chart/gauge_chart.rb +171 -0
- data/lib/konpeito/ui/chart/heatmap_chart.rb +222 -0
- data/lib/konpeito/ui/chart/line_chart.rb +289 -0
- data/lib/konpeito/ui/chart/pie_chart.rb +219 -0
- data/lib/konpeito/ui/chart/scales.rb +77 -0
- data/lib/konpeito/ui/chart/scatter_chart.rb +303 -0
- data/lib/konpeito/ui/chart/stacked_bar_chart.rb +276 -0
- data/lib/konpeito/ui/column.rb +271 -0
- data/lib/konpeito/ui/core.rb +2199 -0
- data/lib/konpeito/ui/dsl.rb +443 -0
- data/lib/konpeito/ui/frame.rb +171 -0
- data/lib/konpeito/ui/frame_native.rb +494 -0
- data/lib/konpeito/ui/markdown/ast.rb +124 -0
- data/lib/konpeito/ui/markdown/mermaid/layout.rb +387 -0
- data/lib/konpeito/ui/markdown/mermaid/models.rb +232 -0
- data/lib/konpeito/ui/markdown/mermaid/parser.rb +519 -0
- data/lib/konpeito/ui/markdown/mermaid/renderer.rb +336 -0
- data/lib/konpeito/ui/markdown/parser.rb +805 -0
- data/lib/konpeito/ui/markdown/renderer.rb +639 -0
- data/lib/konpeito/ui/markdown/theme.rb +165 -0
- data/lib/konpeito/ui/render_node.rb +260 -0
- data/lib/konpeito/ui/row.rb +207 -0
- data/lib/konpeito/ui/spacer.rb +18 -0
- data/lib/konpeito/ui/style.rb +799 -0
- data/lib/konpeito/ui/theme.rb +563 -0
- data/lib/konpeito/ui/themes/material.rb +35 -0
- data/lib/konpeito/ui/themes/tokyo_night.rb +6 -0
- data/lib/konpeito/ui/widgets/button.rb +103 -0
- data/lib/konpeito/ui/widgets/calendar.rb +1034 -0
- data/lib/konpeito/ui/widgets/checkbox.rb +119 -0
- data/lib/konpeito/ui/widgets/container.rb +91 -0
- data/lib/konpeito/ui/widgets/data_table.rb +667 -0
- data/lib/konpeito/ui/widgets/divider.rb +29 -0
- data/lib/konpeito/ui/widgets/image.rb +105 -0
- data/lib/konpeito/ui/widgets/input.rb +485 -0
- data/lib/konpeito/ui/widgets/markdown.rb +57 -0
- data/lib/konpeito/ui/widgets/modal.rb +163 -0
- data/lib/konpeito/ui/widgets/multiline_input.rb +968 -0
- data/lib/konpeito/ui/widgets/multiline_text.rb +180 -0
- data/lib/konpeito/ui/widgets/net_image.rb +100 -0
- data/lib/konpeito/ui/widgets/progress_bar.rb +70 -0
- data/lib/konpeito/ui/widgets/radio_buttons.rb +93 -0
- data/lib/konpeito/ui/widgets/slider.rb +133 -0
- data/lib/konpeito/ui/widgets/switch.rb +84 -0
- data/lib/konpeito/ui/widgets/tabs.rb +157 -0
- data/lib/konpeito/ui/widgets/text.rb +110 -0
- data/lib/konpeito/ui/widgets/tree.rb +426 -0
- data/lib/konpeito/version.rb +5 -0
- data/lib/konpeito.rb +109 -0
- data/test_native_array.rb +172 -0
- data/test_native_array_class.rb +197 -0
- data/test_native_class.rb +151 -0
- data/tools/konpeito-asm/build.sh +65 -0
- data/tools/konpeito-asm/lib/asm-9.7.1.jar +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KArray.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KCompression.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KConditionVariable.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KCrypto.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KFile.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KHTTP.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KHash.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KJSON$Parser.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KJSON.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KMath.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KRactor.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KRactorPort.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KSizedQueue.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KThread.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KTime.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/RubyDispatch.class +0 -0
- data/tools/konpeito-asm/src/ClassIntrospector.java +312 -0
- data/tools/konpeito-asm/src/KonpeitoAssembler.java +659 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KArray.java +390 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KCompression.java +168 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KConditionVariable.java +48 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KCrypto.java +151 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KFile.java +100 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KHTTP.java +113 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KHash.java +228 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KJSON.java +405 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KMath.java +54 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KRactor.java +244 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KRactorPort.java +53 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KSizedQueue.java +49 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KThread.java +49 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KTime.java +53 -0
- data/tools/konpeito-asm/src/konpeito/runtime/RubyDispatch.java +416 -0
- metadata +267 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -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
|
+
}
|