mirror of
https://github.com/aNNiMON/Own-Programming-Language-Tutorial.git
synced 2024-09-20 00:34:20 +03:00
Move ModulesInfoCreator to docs module
This commit is contained in:
parent
b016096161
commit
bfb21ecdbd
@ -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')
|
||||||
@ -9,3 +27,12 @@ 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'
|
||||||
|
}
|
80
docs/src/main/java/com/annimon/ownlang/docs/ModuleInfo.java
Normal file
80
docs/src/main/java/com/annimon/ownlang/docs/ModuleInfo.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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}")
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user