Move ModulesInfoCreator to docs module

This commit is contained in:
aNNiMON 2023-12-10 18:16:42 +02:00 committed by Victor Melnik
parent b016096161
commit bfb21ecdbd
6 changed files with 180 additions and 162 deletions

View File

@ -1,3 +1,21 @@
plugins {
id 'java'
}
group = 'com.annimon'
version = '2.0-SNAPSHOT'
dependencies {
implementation project(":ownlang-core")
implementation project(":ownlang-parser")
implementation project(":ownlang-utils")
implementation project(":modules:main")
implementation project(":modules:canvasfx")
implementation project(":modules:server")
implementation "org.yaml:snakeyaml:${versions.snakeyaml}"
}
tasks.register('generateMarkdownModules') { tasks.register('generateMarkdownModules') {
group = "documentation" group = "documentation"
def ownlangExec = tasks.getByPath(':ownlang-desktop:ownlangExec') def ownlangExec = tasks.getByPath(':ownlang-desktop:ownlangExec')
@ -8,4 +26,13 @@ tasks.register('generateMarkdownModules') {
} }
} }
finalizedBy ownlangExec finalizedBy ownlangExec
}
tasks.register('generateModuleInfo', JavaExec) {
group = "documentation"
description = "Run sample program"
dependsOn classes
mainClass = 'com.annimon.ownlang.docs.ModulesInfoCreator'
classpath = sourceSets.main.runtimeClasspath
args 'server', 'okhttp'
} }

View File

@ -0,0 +1,80 @@
package com.annimon.ownlang.docs;
import com.annimon.ownlang.Version;
import com.annimon.ownlang.lib.MapValue;
import com.annimon.ownlang.lib.Types;
import com.annimon.ownlang.lib.Value;
import java.util.*;
import java.util.stream.Collectors;
public class ModuleInfo {
private final String name;
final List<String> functions;
final Map<String, Value> constants;
final List<String> types;
public ModuleInfo(String name) {
this.name = name;
functions = new ArrayList<>();
constants = new HashMap<>();
types = new ArrayList<>();
}
public List<Map<String, Object>> functions() {
return functions.stream().sorted()
.map(f -> {
final Map<String, Object> function = new LinkedHashMap<>();
function.put("name", f);
function.put("args", "");
function.put("desc", "");
function.put("desc_ru", "");
return function;
})
.collect(Collectors.toList());
}
public List<Map<String, Object>> constants() {
final List<Map<String, Object>> result = new ArrayList<>();
constants.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.forEach(entry -> {
final Value value = entry.getValue();
final Map<String, Object> constant = new LinkedHashMap<>();
constant.put("name", entry.getKey());
constant.put("type", value.type());
constant.put("typeName", Types.typeToString(value.type()));
if (value.type() == Types.MAP) {
String text = ((MapValue) value).getMap().entrySet().stream()
.sorted(Comparator.comparing(
e -> ((MapValue) value).size() > 16 ? e.getKey() : e.getValue()))
.map(Object::toString)
.collect(Collectors.joining(", ", "{", "}"));
constant.put("value", text);
} else {
constant.put("value", value.asString());
}
result.add(constant);
});
return result;
}
public Map<String, Object> info() {
final Map<String, Object> result = new LinkedHashMap<>();
result.put("name", name);
result.put("scope", "both");
result.put("since", "%d.%d.%d".formatted(Version.VERSION_MAJOR, Version.VERSION_MINOR, Version.VERSION_PATCH));
result.put("constants", constants());
result.put("functions", functions());
if (!types.isEmpty()) {
result.put("types", types.stream().sorted()
.map(s -> {
final Map<String, String> type = new HashMap<>();
type.put("name", s);
return type;
})
.toArray());
}
return result;
}
}

View File

@ -0,0 +1,73 @@
package com.annimon.ownlang.docs;
import com.annimon.ownlang.lib.ModuleLoader;
import com.annimon.ownlang.lib.Value;
import com.annimon.ownlang.modules.Module;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public final class ModulesInfoCreator {
public static void main(String[] args) {
if (args.length == 0) {
System.err.println("No modules provided.\nUsage: ModulesInfoCreator <module1> <module2> ...");
System.exit(1);
}
final Class<Module> clazz = Module.class; // get classloader for package
final List<ModuleInfo> moduleInfos = new ArrayList<>();
for (String moduleName : args) {
final Module module = ModuleLoader.load(moduleName);
final ModuleInfo moduleInfo = new ModuleInfo(moduleName);
moduleInfo.functions.addAll(module.functions().keySet());
moduleInfo.constants.putAll(module.constants());
moduleInfo.types.addAll(listValues(module.getClass()));
moduleInfos.add(moduleInfo);
}
printAsYaml(moduleInfos);
System.out.println("Total functions: " + moduleInfos.stream()
.mapToLong(m -> m.functions.size())
.sum()
);
System.out.println("Total constants: " + moduleInfos.stream()
.mapToLong(m -> m.constants.keySet().size())
.sum()
);
}
private static void printAsYaml(List<ModuleInfo> moduleInfos) {
DumperOptions options = new DumperOptions();
options.setIndent(2);
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
final List<Map<String, Object>> infos = new ArrayList<>();
for (ModuleInfo moduleInfo : moduleInfos) {
infos.add(moduleInfo.info());
}
System.out.println(new Yaml(options).dump(infos));
}
private static List<String> listValues(Class<?> moduleClass) {
return Arrays.stream(moduleClass.getDeclaredClasses())
.filter(clazz -> getAllInterfaces(clazz).stream().anyMatch(i -> i.equals(Value.class)))
.map(Class::getSimpleName)
.collect(Collectors.toList());
}
private static Set<Class<?>> getAllInterfaces(Class<?> clazz) {
if (clazz.getSuperclass() == null) {
return Collections.emptySet();
}
return Stream.concat(Arrays.stream(clazz.getInterfaces()), getAllInterfaces(clazz.getSuperclass()).stream())
.collect(Collectors.toSet());
}
}

View File

@ -7,8 +7,6 @@ version = '2.0-SNAPSHOT'
dependencies { dependencies {
api project(":ownlang-parser") api project(":ownlang-parser")
implementation "org.json:json:${versions.json}"
implementation "org.yaml:snakeyaml:${versions.snakeyaml}"
implementation "jline:jline:${versions.jline}" implementation "jline:jline:${versions.jline}"
testImplementation platform("org.junit:junit-bom:${versions.junit}") testImplementation platform("org.junit:junit-bom:${versions.junit}")

View File

@ -1,159 +0,0 @@
package com.annimon.ownlang.utils;
import com.annimon.ownlang.lib.*;
import com.annimon.ownlang.modules.Module;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.json.JSONArray;
import org.json.JSONObject;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
public final class ModulesInfoCreator {
private static final String MODULES_PATH = "src/main/java/com/annimon/ownlang/modules";
public static void main(String[] args)
throws ReflectiveOperationException {
final Class<Module> clazz = Module.class; // get classloader for package
final List<ModuleInfo> moduleInfos = new ArrayList<>();
String[] moduleNames = Optional.ofNullable(new File(MODULES_PATH).listFiles())
.stream()
.flatMap(Arrays::stream)
.filter(File::isDirectory)
.map(File::getName)
.toArray(String[]::new);
for (String moduleName : moduleNames) {
final Module module = ModuleLoader.load(moduleName);
final ModuleInfo moduleInfo = new ModuleInfo(moduleName);
moduleInfo.functions.addAll(module.functions().keySet());
moduleInfo.constants.putAll(module.constants());
moduleInfo.types.addAll(listValues(module.getClass()));
moduleInfos.add(moduleInfo);
}
// printAsJson(moduleInfos);
printAsYaml(moduleInfos);
System.out.println("Total modules: " + moduleInfos.size());
System.out.println("Total functions: " + moduleInfos.stream()
.mapToLong(m -> m.functions.size())
.sum()
);
System.out.println("Total constants: " + moduleInfos.stream()
.mapToLong(m -> m.constants.keySet().size())
.sum()
);
}
private static void printAsJson(List<ModuleInfo> moduleInfos) {
final JSONArray modulesJson = new JSONArray();
for (ModuleInfo moduleInfo : moduleInfos) {
modulesJson.put(new JSONObject(moduleInfo.info()));
}
System.out.println(modulesJson.toString(2));
}
private static void printAsYaml(List<ModuleInfo> moduleInfos) {
DumperOptions options = new DumperOptions();
options.setIndent(2);
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
final List<Map<String, Object>> infos = new ArrayList<>();
for (ModuleInfo moduleInfo : moduleInfos) {
infos.add(moduleInfo.info());
}
System.out.println(new Yaml(options).dump(infos));
}
private static List<String> listValues(Class<?> moduleClass) {
return Arrays.stream(moduleClass.getDeclaredClasses())
.filter(clazz -> getAllInterfaces(clazz).stream().anyMatch(i -> i.equals(Value.class)))
.map(Class::getSimpleName)
.collect(Collectors.toList());
}
private static Set<Class<?>> getAllInterfaces(Class<?> clazz) {
if (clazz.getSuperclass() == null) {
return Collections.emptySet();
}
return Stream.concat(Arrays.stream(clazz.getInterfaces()), getAllInterfaces(clazz.getSuperclass()).stream())
.collect(Collectors.toSet());
}
static class ModuleInfo {
private final String name;
final List<String> functions;
final Map<String, Value> constants;
final List<String> types;
public ModuleInfo(String name) {
this.name = name;
functions = new ArrayList<>();
constants = new HashMap<>();
types = new ArrayList<>();
}
public List<Map<String, Object>> functions() {
return functions.stream().sorted()
.map(f -> {
final Map<String, Object> function = new LinkedHashMap<>();
function.put("name", f);
function.put("args", "");
function.put("desc", "");
function.put("desc_ru", "");
return function;
})
.collect(Collectors.toList());
}
public List<Map<String, Object>> constants() {
final List<Map<String, Object>> result = new ArrayList<>();
constants.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.forEach(entry -> {
final Value value = entry.getValue();
final Map<String, Object> constant = new LinkedHashMap<>();
constant.put("name", entry.getKey());
constant.put("type", value.type());
constant.put("typeName", Types.typeToString(value.type()));
if (value.type() == Types.MAP) {
String text = ((MapValue) value).getMap().entrySet().stream()
.sorted(Comparator.comparing(
e -> ((MapValue)value).size() > 16 ? e.getKey() : e.getValue()))
.map(Object::toString)
.collect(Collectors.joining(", ", "{", "}"));
constant.put("value", text);
} else {
constant.put("value", value.asString());
}
result.add(constant);
});
return result;
}
public Map<String, Object> info() {
final Map<String, Object> result = new LinkedHashMap<>();
result.put("name", name);
result.put("scope", "both");
result.put("constants", constants());
result.put("functions", functions());
if (!types.isEmpty()) {
result.put("types", types.stream().sorted()
.map(s -> {
final Map<String, String> type = new HashMap<>();
type.put("name", s);
return type;
})
.toArray());
}
return result;
}
}
}

View File

@ -9,7 +9,6 @@ import com.annimon.ownlang.parser.Parser;
import com.annimon.ownlang.parser.SourceLoader; import com.annimon.ownlang.parser.SourceLoader;
import com.annimon.ownlang.parser.Token; import com.annimon.ownlang.parser.Token;
import com.annimon.ownlang.parser.ast.Node; import com.annimon.ownlang.parser.ast.Node;
import com.annimon.ownlang.parser.ast.Statement;
import com.annimon.ownlang.parser.visitors.FunctionAdder; import com.annimon.ownlang.parser.visitors.FunctionAdder;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;