Initial commit
This commit is contained in:
		
						commit
						a683a58db2
					
				
					 11 changed files with 1474 additions and 0 deletions
				
			
		
							
								
								
									
										11
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,11 @@
 | 
				
			||||||
 | 
					# Files and directories created by pub.
 | 
				
			||||||
 | 
					.dart_tool/
 | 
				
			||||||
 | 
					.packages
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Conventional directory for build output.
 | 
				
			||||||
 | 
					build/
 | 
				
			||||||
 | 
					# Dart default executable location
 | 
				
			||||||
 | 
					bin/tdlib_gen.exe
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# tl files
 | 
				
			||||||
 | 
					*.tl
 | 
				
			||||||
							
								
								
									
										24
									
								
								.vscode/launch.json
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								.vscode/launch.json
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,24 @@
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						// Use IntelliSense to learn about possible attributes.
 | 
				
			||||||
 | 
						// Hover to view descriptions of existing attributes.
 | 
				
			||||||
 | 
						// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
 | 
				
			||||||
 | 
						"version": "0.2.0",
 | 
				
			||||||
 | 
						"configurations": [
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"name": "tdlib_gen",
 | 
				
			||||||
 | 
								"request": "launch",
 | 
				
			||||||
 | 
								"type": "dart",
 | 
				
			||||||
 | 
								"program": "bin/tdlib_gen.dart",
 | 
				
			||||||
 | 
								"args": [
 | 
				
			||||||
 | 
									"${workspaceFolder}/td_api.tl", 
 | 
				
			||||||
 | 
									"${workspaceFolder}/../tdlib_types/lib"
 | 
				
			||||||
 | 
								],
 | 
				
			||||||
 | 
								"windows": {
 | 
				
			||||||
 | 
									"args": [
 | 
				
			||||||
 | 
										"${workspaceFolder}/td_api.tl", 
 | 
				
			||||||
 | 
										"${workspaceFolder}\\..\\tdlib_types\\lib"
 | 
				
			||||||
 | 
									]
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										3
									
								
								CHANGELOG.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								CHANGELOG.md
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,3 @@
 | 
				
			||||||
 | 
					## 1.0.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Initial version.
 | 
				
			||||||
							
								
								
									
										1
									
								
								README.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								README.md
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					A simple command-line application.
 | 
				
			||||||
							
								
								
									
										16
									
								
								analysis_options.yaml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								analysis_options.yaml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,16 @@
 | 
				
			||||||
 | 
					# Defines a default set of lint rules enforced for projects at Google. For
 | 
				
			||||||
 | 
					# details and rationale, see
 | 
				
			||||||
 | 
					# https://github.com/dart-lang/pedantic#enabled-lints.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include: package:pedantic/analysis_options.yaml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# For lint rules and documentation, see http://dart-lang.github.io/linter/lints.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Uncomment to specify additional rules.
 | 
				
			||||||
 | 
					# linter:
 | 
				
			||||||
 | 
					#   rules:
 | 
				
			||||||
 | 
					#     - camel_case_types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# analyzer:
 | 
				
			||||||
 | 
					#   exclude:
 | 
				
			||||||
 | 
					#     - path/to/excluded/files/**
 | 
				
			||||||
							
								
								
									
										549
									
								
								bin/tdlib_gen.dart
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										549
									
								
								bin/tdlib_gen.dart
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,549 @@
 | 
				
			||||||
 | 
					import 'dart:io';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'tl_scheme.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:recase/recase.dart';
 | 
				
			||||||
 | 
					import 'package:path/path.dart' as path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Future<void> main(List<String> arguments) async {
 | 
				
			||||||
 | 
					  if (arguments.length != 2) {
 | 
				
			||||||
 | 
					    print('The program must be run with 2 arguments:');
 | 
				
			||||||
 | 
					    print('  path to .tl schema');
 | 
				
			||||||
 | 
					    print('  path to Dart project source folder');
 | 
				
			||||||
 | 
					    exit(1);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final schemeFileStr = arguments[0];
 | 
				
			||||||
 | 
					  final srcFolderStr = arguments[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (! await File.fromUri(Uri.file(schemeFileStr)).exists()) {
 | 
				
			||||||
 | 
					    print("Schema file $schemeFileStr doesn't exist");
 | 
				
			||||||
 | 
					    exit(1);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (! await Directory.fromUri(Uri.directory(srcFolderStr)).exists()) {
 | 
				
			||||||
 | 
					    print("Dart project source folder $srcFolderStr doesn't exist");
 | 
				
			||||||
 | 
					    exit(1);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  print('.tl schema folder: $schemeFileStr');
 | 
				
			||||||
 | 
					  print('Dart project source folder: $srcFolderStr');
 | 
				
			||||||
 | 
					  print('');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  print('Reading .tl schema file...');
 | 
				
			||||||
 | 
					  final schemeFileContents = await File.fromUri(Uri.file(schemeFileStr)).readAsString();
 | 
				
			||||||
 | 
					  print('Parsing .tl schema file...');
 | 
				
			||||||
 | 
					  final scheme = TlSchema.parse(schemeFileContents);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  print('Generating...');
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  final baseFile = File.fromUri(Uri.file(path.join(srcFolderStr, 'base.dart'))); 
 | 
				
			||||||
 | 
					  final abstractFile = File.fromUri(Uri.file(path.join(srcFolderStr, 'abstract.dart'))); 
 | 
				
			||||||
 | 
					  final objFile = File.fromUri(Uri.file(path.join(srcFolderStr, 'obj.dart'))); 
 | 
				
			||||||
 | 
					  final fnFile = File.fromUri(Uri.file(path.join(srcFolderStr, 'fn.dart'))); 
 | 
				
			||||||
 | 
					  await baseFile.writeAsString(makeBaseFile(scheme));
 | 
				
			||||||
 | 
					  await abstractFile.writeAsString(makeAbstractFile(scheme));
 | 
				
			||||||
 | 
					  await objFile.writeAsString(makeObjFile(scheme));
 | 
				
			||||||
 | 
					  await fnFile.writeAsString(makeFnFile(scheme));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  print('Done!');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					String findDartType(
 | 
				
			||||||
 | 
					  String type, 
 | 
				
			||||||
 | 
					  TlSchema scheme, 
 | 
				
			||||||
 | 
					  {String abstractPrefix = 'a.',
 | 
				
			||||||
 | 
					  String objectPrefix = 'o.',
 | 
				
			||||||
 | 
					  String functionPrefix = 'f.',
 | 
				
			||||||
 | 
					  bool noNullCheck = false}
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					  if (type.startsWith('vector<')) {
 | 
				
			||||||
 | 
					    final tmp1 = type.replaceFirst('vector<', '');
 | 
				
			||||||
 | 
					    final tmp2 = tmp1.substring(0, tmp1.length - 1);
 | 
				
			||||||
 | 
					    final innerType = findDartType(
 | 
				
			||||||
 | 
					      tmp2, 
 | 
				
			||||||
 | 
					      scheme,
 | 
				
			||||||
 | 
					      abstractPrefix: abstractPrefix,
 | 
				
			||||||
 | 
					      functionPrefix: functionPrefix,
 | 
				
			||||||
 | 
					      objectPrefix: objectPrefix,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    return 'List<$innerType>';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final predefined = {
 | 
				
			||||||
 | 
					    'double': 'double',
 | 
				
			||||||
 | 
					    'string': 'String',
 | 
				
			||||||
 | 
					    'int32': 'int',
 | 
				
			||||||
 | 
					    'int53': 'int',
 | 
				
			||||||
 | 
					    'int64': 'int',
 | 
				
			||||||
 | 
					    'bytes': 'Uint8List',
 | 
				
			||||||
 | 
					    'Bool': 'bool',
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (predefined.containsKey(type)) {
 | 
				
			||||||
 | 
					    return predefined[type]!;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final result = scheme.findType(type);
 | 
				
			||||||
 | 
					  if (result == null) {
 | 
				
			||||||
 | 
					    throw Exception("Couldn't find type: $type");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (result is TlSchemeAbstractClass) {
 | 
				
			||||||
 | 
					    final name = abstractPrefix + result.name.pascalCase;
 | 
				
			||||||
 | 
					    if (noNullCheck) {
 | 
				
			||||||
 | 
					      return name;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					      return '$name?';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else if (result is TlSchemeObject) {
 | 
				
			||||||
 | 
					    final name = objectPrefix + result.name.pascalCase;
 | 
				
			||||||
 | 
					    if (noNullCheck) {
 | 
				
			||||||
 | 
					      return name;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					      return '$name?';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else if (result is TlSchemeFunction) {
 | 
				
			||||||
 | 
					    final name = functionPrefix + result.name.pascalCase;
 | 
				
			||||||
 | 
					    if (noNullCheck) {
 | 
				
			||||||
 | 
					      return name;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					      return '$name?';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else {
 | 
				
			||||||
 | 
					    throw Exception('Unknown tl object: $result');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					String findToJsonHandling(
 | 
				
			||||||
 | 
					  String type, 
 | 
				
			||||||
 | 
					  String varName, 
 | 
				
			||||||
 | 
					  TlSchema scheme,
 | 
				
			||||||
 | 
					  ) {
 | 
				
			||||||
 | 
					  if (type.startsWith('vector<')) {
 | 
				
			||||||
 | 
					    final tmp1 = type.replaceFirst('vector<', '');
 | 
				
			||||||
 | 
					    final tmp2 = tmp1.substring(0, tmp1.length - 1);
 | 
				
			||||||
 | 
					    late String newVarName;
 | 
				
			||||||
 | 
					    if (varName.startsWith('_e')) {
 | 
				
			||||||
 | 
					      final num = int.parse(varName.substring(2));
 | 
				
			||||||
 | 
					      newVarName = '_e${num + 1}';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					      newVarName = '_e1';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    final innerHandling = findToJsonHandling(
 | 
				
			||||||
 | 
					      tmp2, 
 | 
				
			||||||
 | 
					      newVarName,
 | 
				
			||||||
 | 
					      scheme,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    return '$varName.map(($newVarName) => $innerHandling).toList(growable: false)';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final predefined = {
 | 
				
			||||||
 | 
					    'double': 'double',
 | 
				
			||||||
 | 
					    'string': 'String',
 | 
				
			||||||
 | 
					    'int32': 'int',
 | 
				
			||||||
 | 
					    'int53': 'int',
 | 
				
			||||||
 | 
					    'Bool': 'bool',
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  if (predefined.containsKey(type)) {
 | 
				
			||||||
 | 
					    return varName;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else if (type == 'int64') {
 | 
				
			||||||
 | 
					    return '$varName.toString()';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else if (type == 'bytes') {
 | 
				
			||||||
 | 
					    return 'base64.encode($varName)';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else {
 | 
				
			||||||
 | 
					    return '$varName?.toJson()';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					String findFromJsonHandling(
 | 
				
			||||||
 | 
					  String type, 
 | 
				
			||||||
 | 
					  String keyName, 
 | 
				
			||||||
 | 
					  TlSchema scheme,
 | 
				
			||||||
 | 
					  {String abstractPrefix = 'a.',
 | 
				
			||||||
 | 
					  String objectPrefix = 'o.',
 | 
				
			||||||
 | 
					  String functionPrefix = 'f.',
 | 
				
			||||||
 | 
					  String? varNameInsteadOfKeyName}
 | 
				
			||||||
 | 
					  ) {
 | 
				
			||||||
 | 
					  if (type.startsWith('vector<')) {
 | 
				
			||||||
 | 
					    final tmp1 = type.replaceFirst('vector<', '');
 | 
				
			||||||
 | 
					    final tmp2 = tmp1.substring(0, tmp1.length - 1);
 | 
				
			||||||
 | 
					    // final innerType = findDartType(tmp2, scheme, abstractPrefix: abstractPrefix, functionPrefix: functionPrefix, objectPrefix: objectPrefix);
 | 
				
			||||||
 | 
					    final innerHandler = findFromJsonHandling(
 | 
				
			||||||
 | 
					      tmp2,
 | 
				
			||||||
 | 
					      '', 
 | 
				
			||||||
 | 
					      scheme, 
 | 
				
			||||||
 | 
					      abstractPrefix: abstractPrefix,
 | 
				
			||||||
 | 
					      functionPrefix: functionPrefix,
 | 
				
			||||||
 | 
					      objectPrefix: objectPrefix,
 | 
				
			||||||
 | 
					      varNameInsteadOfKeyName: 'e',
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    return "(json['$keyName'] as List<dynamic>).map((e) => ($innerHandler)).toList(growable: false)";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final varAccess = varNameInsteadOfKeyName ?? "json['$keyName']";
 | 
				
			||||||
 | 
					  final predefined = {
 | 
				
			||||||
 | 
					    'double': 'double',
 | 
				
			||||||
 | 
					    'string': 'String',
 | 
				
			||||||
 | 
					    'int32': 'int',
 | 
				
			||||||
 | 
					    'int53': 'int',
 | 
				
			||||||
 | 
					    'Bool': 'bool',
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  if (predefined.containsKey(type)) {
 | 
				
			||||||
 | 
					    return '$varAccess as ${predefined[type]}';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else if (type == 'int64') {
 | 
				
			||||||
 | 
					    return 'int.parse($varAccess)';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else if (type == 'bytes') {
 | 
				
			||||||
 | 
					    return 'base64.decode($varAccess)';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else {
 | 
				
			||||||
 | 
					    return 'b.TdBase.fromJson($varAccess) as ${findDartType(type, scheme, abstractPrefix: abstractPrefix, functionPrefix: functionPrefix, objectPrefix: objectPrefix)}';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					String makeBaseFile(TlSchema scheme) {
 | 
				
			||||||
 | 
					  var result = r"""
 | 
				
			||||||
 | 
					import 'obj.dart' as o;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abstract class TdBase {
 | 
				
			||||||
 | 
					  Map<String, dynamic> toJson();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  String toString() {
 | 
				
			||||||
 | 
					    return 'td::TdBase()';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static TdBase? fromJson(Map<String, dynamic>? json) {
 | 
				
			||||||
 | 
					    if (json == null) {
 | 
				
			||||||
 | 
					      return null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    final type = json['@type'] as String;
 | 
				
			||||||
 | 
					    final constructors = {
 | 
				
			||||||
 | 
					""";
 | 
				
			||||||
 | 
					  for (final o in scheme.objects) {
 | 
				
			||||||
 | 
					    final normName = o.name.pascalCase;
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					      '${o.name}': (json) => o.$normName.fromJson(json),
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  result += '''
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    return constructors[type]!(json);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					  return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					String makeAbstractFile(TlSchema scheme) {
 | 
				
			||||||
 | 
					  var result = r"""
 | 
				
			||||||
 | 
					import 'dart:core' as dc show Error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'base.dart' as b;
 | 
				
			||||||
 | 
					import 'obj.dart' as o;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef Func1<T, TResult> = TResult Function(T);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MatchError extends dc.Error {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					""";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (final ac in scheme.abstractClasses) {
 | 
				
			||||||
 | 
					    final normName = ac.name.pascalCase;
 | 
				
			||||||
 | 
					    final implementors = scheme.objects.where((element) => element.baseType == ac.name).toList(growable: false);
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					/// ${ac.doc}
 | 
				
			||||||
 | 
					abstract class $normName extends b.TdBase {
 | 
				
			||||||
 | 
					  TResult match<TResult>({
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    for (final impl in implementors) {
 | 
				
			||||||
 | 
					      final iNormName = impl.name.pascalCase;
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					    Func1<o.$iNormName, TResult>? is$iNormName,
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					    Func1<$normName, TResult>? otherwise,
 | 
				
			||||||
 | 
					  }) {
 | 
				
			||||||
 | 
					    if (false) {} // ignore: dead_code
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    for (final impl in implementors) {
 | 
				
			||||||
 | 
					      final iNormName = impl.name.pascalCase;
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					    else if (this is o.$iNormName) {
 | 
				
			||||||
 | 
					      if (is$iNormName != null) {
 | 
				
			||||||
 | 
					        return is$iNormName(this as o.$iNormName);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      else if (otherwise != null) {
 | 
				
			||||||
 | 
					        return otherwise(this);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					    else if (otherwise != null) {
 | 
				
			||||||
 | 
					      otherwise(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (TResult == null.runtimeType) {
 | 
				
			||||||
 | 
					      return null as TResult;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    throw MatchError();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					String makeObjFile(TlSchema scheme) {
 | 
				
			||||||
 | 
					  var result = r"""
 | 
				
			||||||
 | 
					import 'dart:convert';
 | 
				
			||||||
 | 
					import 'dart:typed_data';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'base.dart' as b;
 | 
				
			||||||
 | 
					import 'abstract.dart' as a;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					""";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (final o in scheme.objects) {
 | 
				
			||||||
 | 
					    final normName = o.name.pascalCase;
 | 
				
			||||||
 | 
					    final baseName = findDartType(o.baseType, scheme, objectPrefix: '', noNullCheck: true);
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					/// ${o.doc}
 | 
				
			||||||
 | 
					class $normName extends $baseName {
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (final param in o.parameters) {
 | 
				
			||||||
 | 
					      final normParamName = param.name.camelCase;
 | 
				
			||||||
 | 
					      final paramType = findDartType(param.type, scheme, objectPrefix: '');
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					  /// ${param.doc}
 | 
				
			||||||
 | 
					  final $paramType $normParamName;
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Constructor
 | 
				
			||||||
 | 
					    if (o.parameters.isNotEmpty) {
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $normName({
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					      for (final param in o.parameters) {
 | 
				
			||||||
 | 
					        final normParamName = param.name.camelCase;
 | 
				
			||||||
 | 
					        result += '''
 | 
				
			||||||
 | 
					    required this.$normParamName,
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					  $normName();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // toString
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  String toString() {
 | 
				
			||||||
 | 
					    var s = 'td::$normName(';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Params
 | 
				
			||||||
 | 
					    final params = <String>[];
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    for (final param in o.parameters) {
 | 
				
			||||||
 | 
					      final normParamName = param.name.camelCase;
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					    params.add($normParamName.toString());
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					    s += params.join(', ');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    s += ')';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return s;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // toJson
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Map<String, dynamic> toJson() => {
 | 
				
			||||||
 | 
					    '@type': '${o.name}',
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    for (final param in o.parameters) {
 | 
				
			||||||
 | 
					      final normParamName = param.name.camelCase;
 | 
				
			||||||
 | 
					      final jsonHandling = findToJsonHandling(param.type, normParamName, scheme);
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					    '${param.name}': $jsonHandling,
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // fromJson
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					  factory $normName.fromJson(Map<String, dynamic> json) => $normName(
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    for (final param in o.parameters) {
 | 
				
			||||||
 | 
					      final normParamName = param.name.camelCase;
 | 
				
			||||||
 | 
					      final handle = findFromJsonHandling(param.type, param.name, scheme, objectPrefix: '');
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					    $normParamName: $handle,
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					String makeFnFile(TlSchema scheme) {
 | 
				
			||||||
 | 
					  var result = r"""
 | 
				
			||||||
 | 
					import 'dart:convert';
 | 
				
			||||||
 | 
					import 'dart:typed_data';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'base.dart' as b;
 | 
				
			||||||
 | 
					import 'abstract.dart' as a;
 | 
				
			||||||
 | 
					import 'obj.dart' as o;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abstract class TdFunction extends b.TdBase {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					""";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (final f in scheme.functions) {
 | 
				
			||||||
 | 
					    final normName = f.name.pascalCase;
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					/// ${f.doc}
 | 
				
			||||||
 | 
					class $normName extends TdFunction {
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Parameters
 | 
				
			||||||
 | 
					    for (final param in f.parameters) {
 | 
				
			||||||
 | 
					      final pNormName = param.name.camelCase;
 | 
				
			||||||
 | 
					      final pType = findDartType(param.type, scheme, functionPrefix: '');
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					  /// ${param.doc}
 | 
				
			||||||
 | 
					  final $pType $pNormName;
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Constructor
 | 
				
			||||||
 | 
					    if (f.parameters.isEmpty) {
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					  $normName();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $normName({
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					      for (final param in f.parameters) {
 | 
				
			||||||
 | 
					        final pNormName = param.name.camelCase;
 | 
				
			||||||
 | 
					        result += '''
 | 
				
			||||||
 | 
					    required this.$pNormName,
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // toString
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  String toString() {
 | 
				
			||||||
 | 
					    var s = 'td::$normName(';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Params
 | 
				
			||||||
 | 
					    final params = <String>[];
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    for (final param in f.parameters) {
 | 
				
			||||||
 | 
					      final normParamName = param.name.camelCase;
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					    params.add($normParamName.toString());
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					    s += params.join(', ');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    s += ')';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return s;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // toJson
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Map<String, dynamic> toJson() => {
 | 
				
			||||||
 | 
					    '@type': '${f.name}',
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    for (final param in f.parameters) {
 | 
				
			||||||
 | 
					      final pNormName = param.name.camelCase;
 | 
				
			||||||
 | 
					      final jsonHandling = findToJsonHandling(param.type, pNormName, scheme);
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					    '${param.name}': $jsonHandling,
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // fromJson
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					  factory $normName.fromJson(Map<String, dynamic> json) => $normName(
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    for (final param in f.parameters) {
 | 
				
			||||||
 | 
					      final normParamName = param.name.camelCase;
 | 
				
			||||||
 | 
					      final handle = findFromJsonHandling(param.type, param.name, scheme);
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					    $normParamName: $handle,
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										425
									
								
								bin/tdlib_gen.dart.backup
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										425
									
								
								bin/tdlib_gen.dart.backup
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,425 @@
 | 
				
			||||||
 | 
					import 'dart:io';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'tl_scheme.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:recase/recase.dart';
 | 
				
			||||||
 | 
					import 'package:path/path.dart' as path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Future<void> main(List<String> arguments) async {
 | 
				
			||||||
 | 
					  if (arguments.length != 2) {
 | 
				
			||||||
 | 
					    print('The program must be run with 2 arguments:');
 | 
				
			||||||
 | 
					    print('  path to .tl schema');
 | 
				
			||||||
 | 
					    print('  path to Dart project source folder');
 | 
				
			||||||
 | 
					    exit(1);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final schemeFileStr = arguments[0];
 | 
				
			||||||
 | 
					  final srcFolderStr = arguments[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (! await File.fromUri(Uri.file(schemeFileStr)).exists()) {
 | 
				
			||||||
 | 
					    print("Schema file $schemeFileStr doesn't exist");
 | 
				
			||||||
 | 
					    exit(1);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (! await Directory.fromUri(Uri.directory(srcFolderStr)).exists()) {
 | 
				
			||||||
 | 
					    print("Dart project source folder $srcFolderStr doesn't exist");
 | 
				
			||||||
 | 
					    exit(1);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  print('.tl schema folder: $schemeFileStr');
 | 
				
			||||||
 | 
					  print('Dart project source folder: $srcFolderStr');
 | 
				
			||||||
 | 
					  print('');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  print('Reading .tl schema file...');
 | 
				
			||||||
 | 
					  final schemeFileContents = await File.fromUri(Uri.file(schemeFileStr)).readAsString();
 | 
				
			||||||
 | 
					  print('Parsing .tl schema file...');
 | 
				
			||||||
 | 
					  final scheme = TlSchema.parse(schemeFileContents);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  print('Generating...');
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  final baseFile = File.fromUri(Uri.file(path.join(srcFolderStr, 'base.dart'))); 
 | 
				
			||||||
 | 
					  final abstractFile = File.fromUri(Uri.file(path.join(srcFolderStr, 'abstract.dart'))); 
 | 
				
			||||||
 | 
					  final objFile = File.fromUri(Uri.file(path.join(srcFolderStr, 'obj.dart'))); 
 | 
				
			||||||
 | 
					  final fnFile = File.fromUri(Uri.file(path.join(srcFolderStr, 'fn.dart'))); 
 | 
				
			||||||
 | 
					  await baseFile.writeAsString(makeBaseFile(scheme));
 | 
				
			||||||
 | 
					  await abstractFile.writeAsString(makeAbstractFile(scheme));
 | 
				
			||||||
 | 
					  await objFile.writeAsString(makeObjFile(scheme));
 | 
				
			||||||
 | 
					  await fnFile.writeAsString(makeFnFile(scheme));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  print('Done!');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					String findDartType(
 | 
				
			||||||
 | 
					  String type, 
 | 
				
			||||||
 | 
					  TlSchema scheme, 
 | 
				
			||||||
 | 
					  {String abstractPrefix = 'a.',
 | 
				
			||||||
 | 
					  String objectPrefix = 'o.',
 | 
				
			||||||
 | 
					  String functionPrefix = 'f.'}
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					  if (type.startsWith('vector<')) {
 | 
				
			||||||
 | 
					    final tmp1 = type.replaceFirst('vector<', '');
 | 
				
			||||||
 | 
					    final tmp2 = tmp1.substring(0, tmp1.length - 1);
 | 
				
			||||||
 | 
					    final innerType = findDartType(
 | 
				
			||||||
 | 
					      tmp2, 
 | 
				
			||||||
 | 
					      scheme,
 | 
				
			||||||
 | 
					      abstractPrefix: abstractPrefix,
 | 
				
			||||||
 | 
					      functionPrefix: functionPrefix,
 | 
				
			||||||
 | 
					      objectPrefix: objectPrefix,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    return 'List<$innerType>';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final predefined = {
 | 
				
			||||||
 | 
					    'double': 'double',
 | 
				
			||||||
 | 
					    'string': 'String',
 | 
				
			||||||
 | 
					    'int32': 'int',
 | 
				
			||||||
 | 
					    'int53': 'int',
 | 
				
			||||||
 | 
					    'int64': 'int',
 | 
				
			||||||
 | 
					    'bytes': 'Uint8List',
 | 
				
			||||||
 | 
					    'Bool': 'bool',
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (predefined.containsKey(type)) {
 | 
				
			||||||
 | 
					    return predefined[type]!;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final result = scheme.findType(type);
 | 
				
			||||||
 | 
					  if (result == null) {
 | 
				
			||||||
 | 
					    throw Exception("Couldn't find type: $type");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (result is TlSchemeAbstractClass) {
 | 
				
			||||||
 | 
					    return abstractPrefix + result.name.pascalCase;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else if (result is TlSchemeObject) {
 | 
				
			||||||
 | 
					    return objectPrefix + result.name.pascalCase;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else if (result is TlSchemeFunction) {
 | 
				
			||||||
 | 
					    return functionPrefix + result.name.pascalCase;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else {
 | 
				
			||||||
 | 
					    throw Exception('Unknown tl object: $result');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					String findToJsonHandling(
 | 
				
			||||||
 | 
					  String type, 
 | 
				
			||||||
 | 
					  String varName, 
 | 
				
			||||||
 | 
					  TlSchema scheme,
 | 
				
			||||||
 | 
					  ) {
 | 
				
			||||||
 | 
					  if (type.startsWith('vector<')) {
 | 
				
			||||||
 | 
					    final tmp1 = type.replaceFirst('vector<', '');
 | 
				
			||||||
 | 
					    final tmp2 = tmp1.substring(0, tmp1.length - 1);
 | 
				
			||||||
 | 
					    late String newVarName;
 | 
				
			||||||
 | 
					    if (varName.startsWith('_e')) {
 | 
				
			||||||
 | 
					      final num = int.parse(varName.substring(2));
 | 
				
			||||||
 | 
					      newVarName = '_e${num + 1}';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					      newVarName = '_e1';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    final innerHandling = findToJsonHandling(
 | 
				
			||||||
 | 
					      tmp2, 
 | 
				
			||||||
 | 
					      newVarName,
 | 
				
			||||||
 | 
					      scheme,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    return '$varName.map(($newVarName) => $innerHandling).toList(growable: false)';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final predefined = {
 | 
				
			||||||
 | 
					    'double': 'double',
 | 
				
			||||||
 | 
					    'string': 'String',
 | 
				
			||||||
 | 
					    'int32': 'int',
 | 
				
			||||||
 | 
					    'int53': 'int',
 | 
				
			||||||
 | 
					    'Bool': 'bool',
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  if (predefined.containsKey(type)) {
 | 
				
			||||||
 | 
					    return varName;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else if (type == 'int64') {
 | 
				
			||||||
 | 
					    return '$varName.toString()';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else if (type == 'bytes') {
 | 
				
			||||||
 | 
					    return 'base64.encode($varName)';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else {
 | 
				
			||||||
 | 
					    return '$varName.toJson()';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					String findFromJsonHandling(
 | 
				
			||||||
 | 
					  String type, 
 | 
				
			||||||
 | 
					  String keyName, 
 | 
				
			||||||
 | 
					  TlSchema scheme,
 | 
				
			||||||
 | 
					  {String abstractPrefix = 'a.',
 | 
				
			||||||
 | 
					  String objectPrefix = 'o.',
 | 
				
			||||||
 | 
					  String functionPrefix = 'f.'}
 | 
				
			||||||
 | 
					  ) {
 | 
				
			||||||
 | 
					  if (type.startsWith('vector<')) {
 | 
				
			||||||
 | 
					    final tmp1 = type.replaceFirst('vector<', '');
 | 
				
			||||||
 | 
					    final tmp2 = tmp1.substring(0, tmp1.length - 1);
 | 
				
			||||||
 | 
					    final innerType = findDartType(tmp2, scheme, abstractPrefix: abstractPrefix, functionPrefix: functionPrefix, objectPrefix: objectPrefix);
 | 
				
			||||||
 | 
					    return "(json['$keyName'] as List<dynamic>).map((e) => b.TdBase.fromJson(e) as $innerType).toList(growable: false)";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final predefined = {
 | 
				
			||||||
 | 
					    'double': 'double',
 | 
				
			||||||
 | 
					    'string': 'String',
 | 
				
			||||||
 | 
					    'int32': 'int',
 | 
				
			||||||
 | 
					    'int53': 'int',
 | 
				
			||||||
 | 
					    'Bool': 'bool',
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  if (predefined.containsKey(type)) {
 | 
				
			||||||
 | 
					    return "json['$keyName']";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else if (type == 'int64') {
 | 
				
			||||||
 | 
					    return "int.parse(json['$keyName'])";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else if (type == 'bytes') {
 | 
				
			||||||
 | 
					    return "base64.decode(json['$keyName'])";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else {
 | 
				
			||||||
 | 
					    return "b.TdBase.fromJson(json['$keyName']) as ${findDartType(type, scheme, abstractPrefix: abstractPrefix, functionPrefix: functionPrefix, objectPrefix: objectPrefix)}";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					String makeBaseFile(TlSchema scheme) {
 | 
				
			||||||
 | 
					  var result = r"""
 | 
				
			||||||
 | 
					import 'dart:convert';
 | 
				
			||||||
 | 
					import 'dart:typed_data';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'abstract.dart' as a;
 | 
				
			||||||
 | 
					import 'obj.dart' as o;
 | 
				
			||||||
 | 
					import 'fn.dart' as f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abstract class TdBase {
 | 
				
			||||||
 | 
					  Map<String, dynamic> toJson();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static TdBase fromJson(Map<String, dynamic> json) {
 | 
				
			||||||
 | 
					    final type = json['@type'] as String;
 | 
				
			||||||
 | 
					    if (false) {}
 | 
				
			||||||
 | 
					""";
 | 
				
			||||||
 | 
					  for (final o in scheme.objects) {
 | 
				
			||||||
 | 
					    final normName = o.name.pascalCase;
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					    else if (type == '${o.name}') {
 | 
				
			||||||
 | 
					      return o.$normName.fromJson(json);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  result += '''
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					      throw Exception('Unknown type: \$type');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					  return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					String makeAbstractFile(TlSchema scheme) {
 | 
				
			||||||
 | 
					  var result = r"""
 | 
				
			||||||
 | 
					import 'base.dart' as b;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					""";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (final ac in scheme.abstractClasses) {
 | 
				
			||||||
 | 
					    final normName = ac.name.pascalCase;
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					/// ${ac.doc}
 | 
				
			||||||
 | 
					abstract class $normName extends b.TdBase {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					String makeObjFile(TlSchema scheme) {
 | 
				
			||||||
 | 
					  var result = r"""
 | 
				
			||||||
 | 
					import 'dart:convert';
 | 
				
			||||||
 | 
					import 'dart:typed_data';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'base.dart' as b;
 | 
				
			||||||
 | 
					import 'abstract.dart' as a;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					""";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (final o in scheme.objects) {
 | 
				
			||||||
 | 
					    final normName = o.name.pascalCase;
 | 
				
			||||||
 | 
					    final baseName = findDartType(o.baseType, scheme, objectPrefix: '');
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					/// ${o.doc}
 | 
				
			||||||
 | 
					class $normName extends $baseName {
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (final param in o.parameters) {
 | 
				
			||||||
 | 
					      final normParamName = param.name.camelCase;
 | 
				
			||||||
 | 
					      final paramType = findDartType(param.type, scheme, objectPrefix: '');
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					  /// ${param.doc}
 | 
				
			||||||
 | 
					  final $paramType $normParamName;
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Constructor
 | 
				
			||||||
 | 
					    if (o.parameters.isNotEmpty) {
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $normName({
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					      for (final param in o.parameters) {
 | 
				
			||||||
 | 
					        final normParamName = param.name.camelCase;
 | 
				
			||||||
 | 
					        result += '''
 | 
				
			||||||
 | 
					    required this.$normParamName,
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					  $normName();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // toJson
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Map<String, dynamic> toJson() => {
 | 
				
			||||||
 | 
					    '@type': '${o.name}',
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    for (final param in o.parameters) {
 | 
				
			||||||
 | 
					      final normParamName = param.name.camelCase;
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					    '${param.name}': $normParamName,
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // fromJson
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					  factory $normName.fromJson(Map<String, dynamic> json) => $normName(
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    for (final param in o.parameters) {
 | 
				
			||||||
 | 
					      final normParamName = param.name.camelCase;
 | 
				
			||||||
 | 
					      final handle = findFromJsonHandling(param.type, param.name, scheme, objectPrefix: '');
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					    $normParamName: $handle,
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					String makeFnFile(TlSchema scheme) {
 | 
				
			||||||
 | 
					  var result = r"""
 | 
				
			||||||
 | 
					import 'dart:convert';
 | 
				
			||||||
 | 
					import 'dart:typed_data';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'base.dart' as b;
 | 
				
			||||||
 | 
					import 'abstract.dart' as a;
 | 
				
			||||||
 | 
					import 'obj.dart' as o;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abstract class TdFunction extends b.TdBase {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					""";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (final f in scheme.functions) {
 | 
				
			||||||
 | 
					    final normName = f.name.pascalCase;
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					/// ${f.doc}
 | 
				
			||||||
 | 
					class $normName extends TdFunction {
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Parameters
 | 
				
			||||||
 | 
					    for (final param in f.parameters) {
 | 
				
			||||||
 | 
					      final pNormName = param.name.camelCase;
 | 
				
			||||||
 | 
					      final pType = findDartType(param.type, scheme, functionPrefix: '');
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					  /// ${param.doc}
 | 
				
			||||||
 | 
					  final $pType $pNormName;
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Constructor
 | 
				
			||||||
 | 
					    if (f.parameters.isEmpty) {
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					  $normName();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $normName({
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					      for (final param in f.parameters) {
 | 
				
			||||||
 | 
					        final pNormName = param.name.camelCase;
 | 
				
			||||||
 | 
					        result += '''
 | 
				
			||||||
 | 
					    required this.$pNormName,
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // toJson
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Map<String, dynamic> toJson() => {
 | 
				
			||||||
 | 
					    '@type': '${f.name}',
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    for (final param in f.parameters) {
 | 
				
			||||||
 | 
					      final pNormName = param.name.camelCase;
 | 
				
			||||||
 | 
					      final jsonHandling = findToJsonHandling(param.type, pNormName, scheme);
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					    '${param.name}': $jsonHandling,
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // fromJson
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					  factory $normName.fromJson(Map<String, dynamic> json) => $normName(
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    for (final param in f.parameters) {
 | 
				
			||||||
 | 
					      final normParamName = param.name.camelCase;
 | 
				
			||||||
 | 
					      final handle = findFromJsonHandling(param.type, param.name, scheme);
 | 
				
			||||||
 | 
					      result += '''
 | 
				
			||||||
 | 
					    $normParamName: $handle,
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result += '''
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										266
									
								
								bin/tl_scheme.dart
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										266
									
								
								bin/tl_scheme.dart
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,266 @@
 | 
				
			||||||
 | 
					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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										139
									
								
								bin/tl_token.dart
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								bin/tl_token.dart
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,139 @@
 | 
				
			||||||
 | 
					abstract class TlToken {
 | 
				
			||||||
 | 
					  static Iterable<TlToken> tokenize(String file) sync* {
 | 
				
			||||||
 | 
					    var lastWasNone = false;
 | 
				
			||||||
 | 
					    for (final untrimmedLine in file.split(RegExp(r'[\r\n]'))) {
 | 
				
			||||||
 | 
					      final line = untrimmedLine.trim();
 | 
				
			||||||
 | 
					      if (line.isEmpty) {
 | 
				
			||||||
 | 
					        if (!lastWasNone) {
 | 
				
			||||||
 | 
					          yield TlTokenNone();
 | 
				
			||||||
 | 
					          lastWasNone = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        continue;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      else {
 | 
				
			||||||
 | 
					        lastWasNone = false;
 | 
				
			||||||
 | 
					        if (line.startsWith('//')) {
 | 
				
			||||||
 | 
					          // Comment
 | 
				
			||||||
 | 
					          if (!line.contains('@')) {
 | 
				
			||||||
 | 
					            yield TlTokenCommentLine(line);
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          // Skip to first @tag
 | 
				
			||||||
 | 
					          final interestLine = line.substring(line.indexOf('@'));
 | 
				
			||||||
 | 
					          for (final unTrimmedTaggedChunk in interestLine.split('@')) {
 | 
				
			||||||
 | 
					            final taggedChunk = unTrimmedTaggedChunk.trim();
 | 
				
			||||||
 | 
					            if (taggedChunk.isEmpty) {
 | 
				
			||||||
 | 
					              continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            final firstWs = taggedChunk.indexOf(RegExp(r'\s'));
 | 
				
			||||||
 | 
					            final tagName = taggedChunk.substring(0, firstWs);
 | 
				
			||||||
 | 
					            final tagValue = taggedChunk.substring(firstWs).trim();
 | 
				
			||||||
 | 
					            yield TlTokenCommentTag(name: tagName, value: tagValue);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (line == '---functions---') {
 | 
				
			||||||
 | 
					          yield TlTokenFunctionsDelimiter();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					          // class
 | 
				
			||||||
 | 
					          // Split by space
 | 
				
			||||||
 | 
					          final chunksIt = line.split(RegExp(r'\s+')).iterator;
 | 
				
			||||||
 | 
					          // First is name
 | 
				
			||||||
 | 
					          chunksIt.moveNext();
 | 
				
			||||||
 | 
					          final name = chunksIt.current;
 | 
				
			||||||
 | 
					          // Then there are parameters until =
 | 
				
			||||||
 | 
					          final parameters = <TlTokenClassParam>[];
 | 
				
			||||||
 | 
					          do {
 | 
				
			||||||
 | 
					            chunksIt.moveNext();
 | 
				
			||||||
 | 
					            if (chunksIt.current == '=') {
 | 
				
			||||||
 | 
					              break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            // Params are defined as name:type
 | 
				
			||||||
 | 
					            // Ignore oddities
 | 
				
			||||||
 | 
					            if (!chunksIt.current.contains(':')) {
 | 
				
			||||||
 | 
					              continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            final splitted = chunksIt.current.split(':');
 | 
				
			||||||
 | 
					            parameters.add(TlTokenClassParam(
 | 
				
			||||||
 | 
					              name: splitted[0], 
 | 
				
			||||||
 | 
					              type: splitted[1]
 | 
				
			||||||
 | 
					            ));
 | 
				
			||||||
 | 
					          } while (true);
 | 
				
			||||||
 | 
					          // Finally, there is the base type (abstract class)
 | 
				
			||||||
 | 
					          chunksIt.moveNext();
 | 
				
			||||||
 | 
					          String removeSemicolon(String input) {
 | 
				
			||||||
 | 
					            while (input.codeUnits.last == ';'.codeUnits[0]) {
 | 
				
			||||||
 | 
					              input = input.substring(0, input.length - 1);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return input;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          final baseType = removeSemicolon(chunksIt.current);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          yield TlTokenClassTag(
 | 
				
			||||||
 | 
					            name: name, 
 | 
				
			||||||
 | 
					            parameters: parameters, 
 | 
				
			||||||
 | 
					            baseType: baseType,
 | 
				
			||||||
 | 
					          );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					class TlTokenFunctionsDelimiter extends TlToken {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  String toString() {
 | 
				
			||||||
 | 
					    return 'TlToken: ---functions---';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					class TlTokenNone extends TlToken {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  String toString() {
 | 
				
			||||||
 | 
					    return 'TlToken.';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					class TlTokenCommentLine extends TlToken {
 | 
				
			||||||
 | 
					  /// The content of the comment including the leading slashes
 | 
				
			||||||
 | 
					  final String content;
 | 
				
			||||||
 | 
					  TlTokenCommentLine(this.content);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  String toString() {
 | 
				
			||||||
 | 
					    return 'TlToken: //$content';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					class TlTokenCommentTag extends TlToken {
 | 
				
			||||||
 | 
					  /// The name of the tag, excluding the ampersand: description
 | 
				
			||||||
 | 
					  final String name;
 | 
				
			||||||
 | 
					  /// The value of the tag: Provides ...
 | 
				
			||||||
 | 
					  final String value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  TlTokenCommentTag({required this.name, required this.value});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  String toString() {
 | 
				
			||||||
 | 
					    return 'TlToken: //@$name $value';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					class TlTokenClassTag extends TlToken {
 | 
				
			||||||
 | 
					  /// The name of the class
 | 
				
			||||||
 | 
					  final String name;
 | 
				
			||||||
 | 
					  final List<TlTokenClassParam> parameters;
 | 
				
			||||||
 | 
					  final String baseType;
 | 
				
			||||||
 | 
					  TlTokenClassTag({required this.name, required this.parameters, required this.baseType});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  String toString() {
 | 
				
			||||||
 | 
					    final params = parameters.join(', ');
 | 
				
			||||||
 | 
					    return 'TlToken: $name($params) = $baseType';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					class TlTokenClassParam {
 | 
				
			||||||
 | 
					  final String name;
 | 
				
			||||||
 | 
					  final String type;
 | 
				
			||||||
 | 
					  TlTokenClassParam({required this.name, required this.type});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  String toString() {
 | 
				
			||||||
 | 
					    return '$name:$type';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										26
									
								
								pubspec.lock
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								pubspec.lock
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,26 @@
 | 
				
			||||||
 | 
					# Generated by pub
 | 
				
			||||||
 | 
					# See https://dart.dev/tools/pub/glossary#lockfile
 | 
				
			||||||
 | 
					packages:
 | 
				
			||||||
 | 
					  path:
 | 
				
			||||||
 | 
					    dependency: "direct main"
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: path
 | 
				
			||||||
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "1.8.0"
 | 
				
			||||||
 | 
					  pedantic:
 | 
				
			||||||
 | 
					    dependency: "direct dev"
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: pedantic
 | 
				
			||||||
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "1.11.0"
 | 
				
			||||||
 | 
					  recase:
 | 
				
			||||||
 | 
					    dependency: "direct main"
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: recase
 | 
				
			||||||
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "4.0.0"
 | 
				
			||||||
 | 
					sdks:
 | 
				
			||||||
 | 
					  dart: ">=2.12.0 <3.0.0"
 | 
				
			||||||
							
								
								
									
										14
									
								
								pubspec.yaml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								pubspec.yaml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,14 @@
 | 
				
			||||||
 | 
					name: tdlib_gen
 | 
				
			||||||
 | 
					description: A simple command-line application.
 | 
				
			||||||
 | 
					version: 1.0.0
 | 
				
			||||||
 | 
					# homepage: https://www.example.com
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					environment:
 | 
				
			||||||
 | 
					  sdk: '>=2.12.0 <3.0.0'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dependencies:
 | 
				
			||||||
 | 
					  recase: ^4.0.0
 | 
				
			||||||
 | 
					  path: ^1.8.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dev_dependencies:
 | 
				
			||||||
 | 
					  pedantic: ^1.10.0
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue