Initial commit
This commit is contained in:
227
lib/dataclasses.dart
Normal file
227
lib/dataclasses.dart
Normal file
@@ -0,0 +1,227 @@
|
||||
import "dart:io";
|
||||
|
||||
import "package:build/build.dart";
|
||||
import "package:yaml/yaml.dart";
|
||||
|
||||
String joinString(List<String> strings, String sep) {
|
||||
String joined = "";
|
||||
|
||||
for (final str in strings) {
|
||||
joined += "$str$sep";
|
||||
}
|
||||
|
||||
return joined;
|
||||
}
|
||||
|
||||
String _getAttributeType(dynamic data) {
|
||||
if (data is String) {
|
||||
return data;
|
||||
}
|
||||
|
||||
return (data as YamlMap)["type"]!;
|
||||
}
|
||||
|
||||
bool _getAttributeDeserialise(dynamic data) {
|
||||
if (data is YamlMap) {
|
||||
return data["deserialise"] ?? false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
String _generateAttributes(YamlMap data) {
|
||||
if (data["attributes"] == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
List<String> attrs = [];
|
||||
data["attributes"].forEach((key, value) {
|
||||
final type_ = _getAttributeType(value);
|
||||
assert(!type_.endsWith(" "));
|
||||
attrs.add("\tfinal $type_ $key;");
|
||||
});
|
||||
|
||||
final joined = joinString(attrs, "\n");
|
||||
return joined.substring(0, joined.length - 1);
|
||||
}
|
||||
|
||||
String _generateInitializers(YamlMap data) {
|
||||
if (data["attributes"] == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
List<String> attrs = [];
|
||||
data["attributes"].forEach((key, value) {
|
||||
final type_ = _getAttributeType(value);
|
||||
final defaultValue = value is YamlMap
|
||||
? value["default"]
|
||||
: null;
|
||||
final defaultString = defaultValue != null
|
||||
? " = const $defaultValue"
|
||||
: "";
|
||||
final isRequired = !type_.endsWith("?") && defaultValue == null;
|
||||
final requiredString = isRequired ? "required " : "";
|
||||
|
||||
attrs.add("\t\t${requiredString}this.$key$defaultString,");
|
||||
});
|
||||
|
||||
final joined = joinString(attrs, "\n");
|
||||
return joined.substring(0, joined.length - 1);
|
||||
}
|
||||
|
||||
String _generateToJson(YamlMap data) {
|
||||
String json = '''
|
||||
\t@override
|
||||
\tMap<String, dynamic> toJson() => {\n
|
||||
''';
|
||||
|
||||
if (data["attributes"] != null) {
|
||||
data["attributes"].forEach((key, _) {
|
||||
json += "\t\t\"$key\": $key,\n";
|
||||
});
|
||||
}
|
||||
|
||||
json += '''
|
||||
\t\t"type": "${data["name"]!}"
|
||||
\t};\n
|
||||
''';
|
||||
return json;
|
||||
}
|
||||
|
||||
String _generateFromJson(YamlMap data) {
|
||||
final name = data["name"]!;
|
||||
String json = "\tstatic $name fromJson(Map<String, dynamic> json) => $name(";
|
||||
|
||||
if (data["attributes"] != null) {
|
||||
json += "\n";
|
||||
data["attributes"].forEach((key, value) {
|
||||
final type_ = _getAttributeType(value);
|
||||
if (type_.startsWith("List<")) {
|
||||
final exp = RegExp(r"List\<(.*?)\>");
|
||||
final listType = exp.firstMatch(type_)!.group(1)!;
|
||||
|
||||
final suffix = type_.endsWith("?") ? " ?? []" : "!";
|
||||
String attr = '(json["$key"]$suffix)';
|
||||
if (_getAttributeDeserialise(value)) {
|
||||
attr += ".map((item) => $listType.fromJson(item))";
|
||||
}
|
||||
|
||||
json += "\t\t$key: List<$listType>.from($attr),\n";
|
||||
} else {
|
||||
if (_getAttributeDeserialise(value)) {
|
||||
if (type_.endsWith("?")) {
|
||||
final attrTypeNoNull = type_.substring(0, type_.length - 1);
|
||||
json += '\t\t$key: json["$key"] != null ? $attrTypeNoNull.fromJson(json["$key"]) : null,\n';
|
||||
} else {
|
||||
json += '\t\t$key: $type_.fromJson(json["$key"]!),\n';
|
||||
}
|
||||
} else {
|
||||
final nullString = type_.endsWith("?")
|
||||
? "" : "!";
|
||||
json += '\t\t$key: json["$key"]$nullString,\n';
|
||||
}
|
||||
}
|
||||
});
|
||||
json += "\t);";
|
||||
} else {
|
||||
json += ");";
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
String generateClassFromData(YamlMap data) {
|
||||
String impls = "";
|
||||
for (final impl in data["implements"]) {
|
||||
impls += "$impl, ";
|
||||
}
|
||||
final constructor = data["attributes"] != null
|
||||
? '''
|
||||
\t${data["name"]!}({
|
||||
${_generateInitializers(data)}
|
||||
\t});
|
||||
'''
|
||||
: '\t${data["name"]!}();';
|
||||
return '''
|
||||
class ${data["name"]!} extends ${data["extends"]} implements ${impls.substring(0, impls.length - 2)} {
|
||||
${_generateAttributes(data)}
|
||||
$constructor
|
||||
|
||||
\t// JSON Stuff
|
||||
${_generateToJson(data)}
|
||||
${_generateFromJson(data)}
|
||||
}
|
||||
|
||||
''';
|
||||
}
|
||||
|
||||
String _generateBuilder(String name, String baseClass, YamlList classes) {
|
||||
String func = '''
|
||||
$baseClass? get${name}FromJson(Map<String, dynamic> json) {
|
||||
\tswitch(json["type"]!) {
|
||||
''';
|
||||
|
||||
for (final class_ in classes) {
|
||||
final name = class_["name"]!;
|
||||
func += '\t\tcase "$name": return $name.fromJson(json);\n';
|
||||
}
|
||||
|
||||
func += "\t\tdefault: return null;\n";
|
||||
func += "\t}\n}";
|
||||
return func;
|
||||
}
|
||||
|
||||
String generateFileFromData(YamlMap data) {
|
||||
String file = '''
|
||||
//// AUTO-GENERATED by build_runner ////
|
||||
/// DO NOT EDIT BY HAND
|
||||
part of "${data["partof"]!}";
|
||||
|
||||
''';
|
||||
|
||||
data["classes"].forEach((attributes) {
|
||||
file += generateClassFromData(attributes);
|
||||
});
|
||||
if (data["generate_builder"]) {
|
||||
file += "\n\n";
|
||||
file += _generateBuilder(
|
||||
data["builder_name"],
|
||||
data["builder_baseclass"],
|
||||
data["classes"]
|
||||
);
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
class DataClassBuilder implements Builder {
|
||||
@override
|
||||
Future build(BuildStep step) async {
|
||||
final file = File(step.inputId.path);
|
||||
final data = loadYaml(await file.readAsString());
|
||||
|
||||
for (final asset in step.allowedOutputs) {
|
||||
if (asset.path.endsWith("commands.moxxy.dart")) {
|
||||
await step.writeAsString(
|
||||
asset,
|
||||
generateFileFromData(data["files"]["commands"]!)
|
||||
);
|
||||
} else if (asset.path.endsWith("events.moxxy.dart")) {
|
||||
await step.writeAsString(
|
||||
asset,
|
||||
generateFileFromData(data["files"]["events"]!)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
final buildExtensions = const {
|
||||
"data_classes.yaml": [
|
||||
"shared/commands.moxxy.dart",
|
||||
"shared/events.moxxy.dart"
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
Builder dataClassBuilder(BuilderOptions options) => DataClassBuilder();
|
||||
93
lib/licenses.dart
Normal file
93
lib/licenses.dart
Normal file
@@ -0,0 +1,93 @@
|
||||
import "dart:io";
|
||||
|
||||
import "package:build/build.dart";
|
||||
import "package:dart_pubspec_licenses/dart_pubspec_licenses.dart";
|
||||
import "package:yaml/yaml.dart";
|
||||
|
||||
final googleBSD1 = [
|
||||
"Redistribution and use in source and binary forms, with or without",
|
||||
"modification, are permitted provided that the following conditions are",
|
||||
"met:"
|
||||
];
|
||||
final googleBSD2 = [
|
||||
"Redistribution and use in source and binary forms, with or without modification,"
|
||||
"are permitted provided that the following conditions are met:"
|
||||
];
|
||||
|
||||
/// Google's provided BSD-3-Clause does not contain the fact that it is a
|
||||
/// BSD-3-Clause license, so handle that one explicitly.
|
||||
bool matchesGoogleBSD3(String text) {
|
||||
return googleBSD1.every(text.contains) || googleBSD2.every(text.contains);
|
||||
}
|
||||
|
||||
/// uuid has a weirdly formatted MIT.
|
||||
bool matchesMIT(String text) {
|
||||
return [
|
||||
'Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:',
|
||||
"MIT"
|
||||
].any(text.contains) && !text.contains("GNU GENERAL PUBLIC LICENSE");
|
||||
}
|
||||
|
||||
String _licenseFromText(String? text) {
|
||||
if (text == null) {
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
if (text.contains("Apache-2.0") || (text.contains("Apache License") && text.contains("Version 2.0"))) {
|
||||
return "Apache-2.0";
|
||||
} else if (["BSD-3-Clause", "BSD 3-Clause"].any(text.contains) || matchesGoogleBSD3(text)) {
|
||||
return "BSD-3-Clause";
|
||||
} else if (matchesMIT(text)) {
|
||||
return "MIT";
|
||||
} else if (text.contains("GNU GENERAL PUBLIC LICENSE") && text.contains("Version 3")) {
|
||||
return "GPL3";
|
||||
} else {
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
class LicenseBuilder implements Builder {
|
||||
@override
|
||||
Future build(BuildStep step) async {
|
||||
final info = await generateLicenseInfo(
|
||||
pubspecLockPath: "./pubspec.lock"
|
||||
);
|
||||
|
||||
String fileContent = '''
|
||||
//// AUTO-GENERATED by build_runner ////
|
||||
/// DO NOT EDIT BY HAND
|
||||
part of "licenses.dart";
|
||||
|
||||
const List<Library> usedLibraryList = [
|
||||
''';
|
||||
for (final pkg in info) {
|
||||
if (!pkg.isDirectDependency) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final license = _licenseFromText(pkg.license);
|
||||
if (license == "Unknown") {
|
||||
print("Failed to guess license for ${pkg.name}");
|
||||
}
|
||||
|
||||
fileContent += '\tLibrary(name: "${pkg.name}", license: "$license", url: "${pkg.homepage}"),\n';
|
||||
}
|
||||
|
||||
final file = File("pubspec.yaml");
|
||||
final data = loadYaml(await file.readAsString());
|
||||
for (final extra in data["extra_licenses"]) {
|
||||
fileContent += '\tLibrary(name: "${extra["name"]!}", license: "${extra["license"]!}", url: "${extra["url"]!}"),\n';
|
||||
}
|
||||
|
||||
fileContent += "];";
|
||||
|
||||
await step.writeAsString(step.allowedOutputs.first, fileContent);
|
||||
}
|
||||
|
||||
@override
|
||||
final buildExtensions = const {
|
||||
"pubspec.yaml": [ "lib/ui/pages/settings/licenses.moxxy.dart" ]
|
||||
};
|
||||
}
|
||||
|
||||
Builder licenseBuilder(BuilderOptions _) => LicenseBuilder();
|
||||
Reference in New Issue
Block a user