tdlib bindings generator for Dart
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

267 lines
7.4 KiB

3 years ago
import 'tl_token.dart';
class TlSchema {
final List<TlSchemeAbstractClass> abstractClasses;
final List<TlSchemeObject> objects;
final List<TlSchemeFunction> functions;
TlSchema({
required this.abstractClasses,
required this.objects,
required this.functions,
});
TlSchemeItem? findType(String type) {
TlSchemeItem? find(List<TlSchemeItem> list) {
for (final item in list) {
if (item.name == type) {
return item;
}
}
}
return find(abstractClasses) ?? find(objects) ?? find(functions);
}
factory TlSchema.parse(String file) {
var abstractClasses = <String, TlSchemeAbstractClass>{};
var objects = <String, TlSchemeObject>{};
var functions = <String, TlSchemeFunction>{};
var comments = <TlTokenCommentTag>[];
void finishBuilder(_TlSchemeItemBuilder builder) {
comments.clear();
if (builder is _TlSchemeAbstractClassBuilder) {
final ac = builder.build();
abstractClasses[ac.name] = ac;
}
else if (builder is _TlSchemeObjectBuilder) {
final obj = builder.build();
objects[obj.name] = obj;
if (!abstractClasses.containsKey(obj.baseType)) {
abstractClasses[obj.baseType] = TlSchemeAbstractClass(
name: obj.baseType,
doc: ''
);
}
}
else if (builder is _TlSchemeFunctionBuilder) {
final fn = builder.build();
functions[fn.name] = fn;
}
else {
throw Exception('Unknown builder: $builder');
}
}
var buildingFunctions = false;
_TlSchemeItemBuilder? builder;
for (final token in TlToken.tokenize(file)) {
if (token is TlTokenNone) {
if (builder != null) {
finishBuilder(builder);
}
builder = null;
}
else if (token is TlTokenFunctionsDelimiter) {
buildingFunctions = true;
}
else if (token is TlTokenCommentTag) {
if (token.name == 'class' && comments.isEmpty && builder == null) {
builder = _TlSchemeAbstractClassBuilder(
name: token.value,
);
}
else if (builder is _TlSchemeAbstractClassBuilder && token.name == 'description') {
builder.doc = token.value;
}
else {
comments.add(token);
}
}
else if (token is TlTokenClassTag) {
// Check for skippable
final skippable = [
'double',
'string',
'int32',
'int53',
'int64',
'bytes',
'boolFalse',
'boolTrue',
'vector',
];
if (skippable.contains(token.name)) {
comments.clear();
builder = null;
continue;
}
var typeDoc = '';
var paramDoc = <String, String>{};
for (final comment in comments) {
if (comment.name == 'description') {
typeDoc = comment.value;
}
else if (comment.name == 'param_description') {
paramDoc['description'] = comment.value;
}
else {
paramDoc[comment.name] = comment.value;
}
}
if (buildingFunctions) {
builder = _TlSchemeFunctionBuilder(
returnType: token.baseType,
name: token.name,
doc: typeDoc,
parameters: token.parameters.map((t) => _TlSchemeParamBuilder(
name: t.name,
type: t.type,
doc: paramDoc[t.name]!,
)).toList(growable: false),
);
}
else {
builder = _TlSchemeObjectBuilder(
baseType: token.baseType,
name: token.name,
doc: typeDoc,
parameters: token.parameters.map((t) => _TlSchemeParamBuilder(
name: t.name,
type: t.type,
doc: paramDoc[t.name]!,
)).toList(growable: false),
);
}
finishBuilder(builder);
builder = null;
}
}
return TlSchema(
abstractClasses: abstractClasses.values.toList(growable: false),
objects: objects.values.toList(growable: false),
functions: functions.values.toList(growable: false),
);
}
}
abstract class TlSchemeItem {
final String name;
final String doc;
TlSchemeItem({required this.name, required this.doc});
}
abstract class _TlSchemeItemBuilder<T extends TlSchemeItem> {
T build();
}
class TlSchemeAbstractClass extends TlSchemeItem {
TlSchemeAbstractClass({required String name, required String doc})
: super(name: name, doc: doc);
@override
String toString() {
return 'abstract $name';
}
}
class _TlSchemeAbstractClassBuilder extends _TlSchemeItemBuilder<TlSchemeAbstractClass> {
String name;
String doc;
_TlSchemeAbstractClassBuilder({this.name = '', this.doc = ''});
@override
TlSchemeAbstractClass build() => TlSchemeAbstractClass(name: name, doc: doc);
}
class TlSchemeObject extends TlSchemeItem {
final String baseType;
final List<TlSchemeParam> parameters;
TlSchemeObject({
required this.baseType,
required String name,
required String doc,
required this.parameters,
}) : super(name: name, doc: doc);
@override
String toString() {
return 'class $name(${parameters.join(', ')}) : $baseType';
}
}
class _TlSchemeObjectBuilder extends _TlSchemeItemBuilder<TlSchemeObject> {
String baseType;
String name;
String doc;
List<_TlSchemeParamBuilder> parameters;
_TlSchemeObjectBuilder({
this.baseType = '',
this.name = '',
this.doc = '',
this.parameters = const <_TlSchemeParamBuilder>[]
});
@override
TlSchemeObject build() => TlSchemeObject(
baseType: baseType,
name: name,
doc: doc,
parameters: parameters.map((b) => b.build()).toList(growable: false),
);
}
class TlSchemeFunction extends TlSchemeItem {
final String returnType;
final List<TlSchemeParam> parameters;
TlSchemeFunction({
required this.returnType,
required String name,
required String doc,
required this.parameters,
}) : super(name: name, doc: doc);
@override
String toString() {
return 'fn $name(${parameters.join(', ')}) -> $returnType';
}
}
class _TlSchemeFunctionBuilder extends _TlSchemeItemBuilder<TlSchemeFunction> {
String returnType;
String name;
String doc;
List<_TlSchemeParamBuilder> parameters;
_TlSchemeFunctionBuilder({
this.returnType = '',
this.name = '',
this.doc = '',
this.parameters = const <_TlSchemeParamBuilder>[]
});
@override
TlSchemeFunction build() => TlSchemeFunction(
returnType: returnType,
name: name,
doc: doc,
parameters: parameters.map((b) => b.build()).toList(growable: false),
);
}
class TlSchemeParam {
final String name;
final String type;
final String doc;
TlSchemeParam({required this.name, required this.type, required this.doc});
@override
String toString() {
return '$name: $type';
}
}
class _TlSchemeParamBuilder {
String name;
String type;
String doc;
_TlSchemeParamBuilder({this.name = '', this.type = '', this.doc = ''});
TlSchemeParam build() => TlSchemeParam(name: name, type: type, doc: doc);
}