From 1805949f612e7a9114cf88227164673719b443de Mon Sep 17 00:00:00 2001 From: birjuvachhani Date: Sat, 15 Feb 2020 22:28:29 +0530 Subject: [PATCH] :sparkles: implement proper logging Signed-off-by: birjuvachhani --- bin/main.dart | 43 +++++++--------- lib/spider.dart | 26 ++++++---- lib/src/dart_class_generator.dart | 77 ++++++++++++++++----------- lib/src/utils.dart | 86 ++++++++++++++++++------------- pubspec.yaml | 1 + 5 files changed, 135 insertions(+), 98 deletions(-) diff --git a/bin/main.dart b/bin/main.dart index e64a315..a41355d 100644 --- a/bin/main.dart +++ b/bin/main.dart @@ -20,19 +20,27 @@ import 'dart:io'; import 'package:args/args.dart'; +import 'package:logging/logging.dart'; import 'package:path/path.dart' as path; import 'package:spider/spider.dart'; import 'package:spider/src/help_manuals.dart'; +import 'package:spider/src/utils.dart'; import 'package:spider/src/version.dart'; -import 'package:yaml/yaml.dart'; /// Handles all the commands void main(List arguments) { + Logger.root.level = Level.INFO; // defaults to Level.INFO + Logger.root.onRecord.listen((record) { + if (record.level == Level.SEVERE) { + stderr.writeln('[${record.level.name}] ${record.message}'); + } else { + stdout.writeln('[${record.level.name}] ${record.message}'); + } + }); var pubspec_path = path.join(Directory.current.path, 'pubspec.yaml'); if (!File(pubspec_path).existsSync()) { - stderr.writeln( - 'Current directory is not flutter project.\nPlease execute this command in a flutter project root path.'); - exit(0); + exit_with('Current directory is not flutter project.\nPlease execute ' + 'this command in a flutter project root path.'); } exitCode = 0; @@ -50,7 +58,7 @@ void main(List arguments) { processCreateCommand(argResults.command); break; default: - stderr.writeln( + exit_with( 'No command found. Use Spider --help to see available commands'); } } @@ -72,9 +80,7 @@ void processArgs(List arguments) { /// prints library info read from pubspec file void printInfo() { - try { - final yaml = _loadPubspec(); - final info = ''' + final info = ''' SPIDER: A small dart command-line tool for generating dart references of assets from @@ -86,10 +92,7 @@ SPIDER: see spider --help for more available commands. '''; - stdout.writeln(info); - } catch (e) { - stderr.writeln('Unable to get info!'); - } + stdout.writeln(info); } /// prints library version @@ -97,14 +100,6 @@ void printVersion() { stdout.writeln(packageVersion); } -Map _loadPubspec() { - final pathToYaml = path.join( - path.dirname(path.dirname(Platform.script.toFilePath())), 'pubspec.yaml'); - final pubspecFile = File(pathToYaml); - Map yaml = loadYaml(pubspecFile.readAsStringSync()); - return yaml; -} - /// Parses command-line arguments and returns results ArgResults parseArguments(List arguments) { final createParser = ArgParser() @@ -131,8 +126,9 @@ ArgResults parseArguments(List arguments) { try { var result = parser.parse(arguments); return result; - } catch (e) { - stderr.writeln('Invalid command input. see spider --help for info.'); + } on Error catch (e) { + exit_with( + 'Invalid command input. see spider --help for info.', e.stackTrace); return null; } } @@ -144,8 +140,9 @@ void processBuildCommand(ArgResults command) { } else { var watch = command.arguments.contains('--watch'); var verbose = command.arguments.contains('--verbose'); + Logger.root.level = verbose ? Level.ALL : Level.INFO; final spider = Spider(Directory.current.path); - spider.build(watch, verbose: verbose); + spider.build(watch); } } diff --git a/lib/spider.dart b/lib/spider.dart index 00f8bdc..9d4f2ee 100644 --- a/lib/spider.dart +++ b/lib/spider.dart @@ -29,30 +29,36 @@ import 'src/utils.dart'; /// provides various functions to execute commands /// Responsible for triggering dart code generation class Spider { - final String _path; List groups; - Spider(this._path) : groups = parseConfig(_path); + Spider(String path) : groups = parseConfig(path); /// Triggers build /// [watch] determines if the directory should be watched for changes - void build(bool watch, {bool verbose = false}) { + void build( + bool watch, + ) { if (groups == null) { exit_with('No groups found in config file.'); } for (var group in groups) { - var generator = DartClassGenerator(group: group, verbose: verbose); + var generator = DartClassGenerator(group); generator.generate(watch); } } /// initializes config file (spider.yaml) in the root of the project static void createConfigs(bool isJson) { - var ext = isJson ? 'json' : 'yaml'; - var src = - path.join(path.dirname(path.dirname(Platform.script.toFilePath())), '/config.$ext'); - var dest = 'spider' + path.extension(src); - File(src).copySync(dest); - stdout.writeln('Configuration file created successfully.'); + try { + var ext = isJson ? 'json' : 'yaml'; + var src = path.join( + path.dirname(path.dirname(Platform.script.toFilePath())), + '/config.$ext'); + var dest = 'spider' + path.extension(src); + File(src).copySync(dest); + success('Configuration file created successfully.'); + } on Error catch (e) { + exit_with('Unable to create config file', e.stackTrace); + } } } diff --git a/lib/src/dart_class_generator.dart b/lib/src/dart_class_generator.dart index 56a7d48..3ebf29a 100644 --- a/lib/src/dart_class_generator.dart +++ b/lib/src/dart_class_generator.dart @@ -28,58 +28,77 @@ import 'utils.dart'; /// Generates dart class code using given data class DartClassGenerator { - bool verbose = false; final AssetGroup group; bool _processing = false; static final formatter = DartFormatter(); - DartClassGenerator({this.group, this.verbose = false}); + DartClassGenerator(this.group); /// generates dart class code and returns it as a single string void generate(bool watch) { if (watch) { + verbose('path ${group.path} is requested to be watched'); _watchDirectory(); } process(); } void process() { - var properties = createFileMap(); - var properties_strings = properties.keys.map((name) { - printVerbose(verbose, 'processing ${properties[name]}'); - var str = group.useStatic ? '\tstatic ' : '\t'; - str += group.useConst ? 'const ' : ''; - str += - 'String ${Formatter.formatName(name)} = \'${Formatter.formatPath(properties[name])}\';'; - return str; - }).toList(); - var dart_class = '''// Generated by spider on ${DateTime.now()} + try { + info('Processing path: ${group.path}'); + verbose('Creating file map from ${group.path}'); + var properties = createFileMap(); + verbose('File map created for path ${group.path}'); + var properties_strings = properties.keys.map((name) { + verbose('processing ${path.basename(properties[name])}'); + var str = group.useStatic ? '\tstatic ' : '\t'; + str += group.useConst ? 'const ' : ''; + str += + 'String ${Formatter.formatName(name)} = \'${Formatter.formatPath(properties[name])}\';'; + return str; + }).toList(); + verbose('Constructing dart class for ${group.className}'); + var dart_class = '''// Generated by spider on ${DateTime.now()} class ${group.className} { ${properties_strings.join('\n')} }'''; - writeToFile( - name: Formatter.formatFileName(group.fileName ?? group.className), - path: group.package, - content: formatter.format(dart_class)); - _processing = false; - stdout.writeln('Processed items: ${properties.length}'); + verbose('Writing class ${group.className} to file ${group.fileName}'); + writeToFile( + name: Formatter.formatFileName(group.fileName ?? group.className), + path: group.package, + content: formatter.format(dart_class)); + _processing = false; + success( + 'Processed items for class ${group.className}: ${properties.length}'); + } on Error catch (e) { + exit_with('Unable to process assets', e.stackTrace); + } } /// Creates map from files list of a [dir] where key is the file name without /// extension and value is the path of the file Map createFileMap() { - var dir = group.path; - var files = - Directory(dir).listSync().where((file) => _isValidFile(file)).toList(); + try { + var dir = group.path; + var files = Directory(dir).listSync().where((file) { + final valid = _isValidFile(file); + verbose( + 'Asset - ${path.basename(file.path)} is ${valid ? 'selected' : 'not selected'}'); + return valid; + }).toList(); - if (files.isEmpty) { - exit_with('Directory $dir does not contain any assets!'); + if (files.isEmpty) { + exit_with('Directory $dir does not contain any assets!'); + } + return { + for (var file in files) + path.basenameWithoutExtension(file.path): file.path + }; + } on Error catch (e) { + exit_with('Unable to create file map', e.stackTrace); + return null; } - return { - for (var file in files) - path.basenameWithoutExtension(file.path): file.path - }; } /// checks whether the file is valid file to be included or not @@ -93,9 +112,9 @@ ${properties_strings.join('\n')} /// Watches assets dir for file changes and rebuilds dart code void _watchDirectory() { - stdout.writeln('Watching for changes in directory ${group.path}...'); + info('Watching for changes in directory ${group.path}...'); Directory(group.path).watch(events: FileSystemEvent.all).listen((data) { - printVerbose(verbose, 'something changed...'); + verbose('something changed...'); if (!_processing) { _processing = true; Future.delayed(Duration(seconds: 1), () => process()); diff --git a/lib/src/utils.dart b/lib/src/utils.dart index f14f137..06bc7c7 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart @@ -20,6 +20,7 @@ import 'dart:convert'; import 'dart:io'; +import 'package:logging/logging.dart'; import 'package:path/path.dart' as p; import 'package:yaml/yaml.dart'; @@ -39,21 +40,15 @@ void writeToFile({String name, String path, String content}) { } var classFile = File(p.join(Constants.LIB_FOLDER, path, name)); classFile.writeAsStringSync(content); -} - -/// prints logs if the [verbose] flag is true -void printVerbose(bool verbose, String msg) { - if (verbose) { - stdout.writeln(msg); - } + verbose('File ${p.basename(classFile.path)} is written successfully'); } /// formats file extensions and adds preceding dot(.) if missing String formatExtension(String ext) => ext.startsWith('.') ? ext : '.' + ext; /// exits process with a message on command-line -void exit_with(String msg) { - stderr.writeln(msg); +void exit_with(String msg, [StackTrace stackTrace]) { + error(msg, stackTrace); exitCode = 2; exit(2); } @@ -72,54 +67,73 @@ List parseConfig(String path) { final jsonFile = file(p.join(path, 'spider.json')); var map; if (yamlFile != null) { + verbose('Loading configs from ${p.basename(yamlFile.path)}'); map = yamlToMap(yamlFile.path); } else if (jsonFile != null) { + verbose('Loading configs from ${p.basename(jsonFile.path)}'); map = json.decode(jsonFile.readAsStringSync()); } else { exit_with('Config not found. ' 'Create one using "spider create" command.'); } + verbose('Validating configs'); validateConfigs(map); var groups = []; + verbose('Creating asset groups'); map['groups']?.forEach((group) { groups.add(AssetGroup.fromJson(group)); }); return groups; - } catch (e) { - stderr.writeln(e); - exit_with('Unable to parse configs!'); + } on Error catch (e) { + exit_with('Unable to parse configs!', e.stackTrace); return null; } } /// validates the configs of the configuration file void validateConfigs(Map conf) { - final groups = conf['groups']; - if (groups == null) { - exit_with('No groups found in the config file.'); - } - if (groups.runtimeType != [].runtimeType) { - exit_with('Groups must be a list of configurations.'); - } - for (var group in groups) { - group.forEach((key, value) { - if (value == null) exit_with('$key cannot be null'); - }); - - if (group['path'] == null) { - exit_with('No path provided for one of the groups.'); - } - - if (File(group['path']).statSync().type != FileSystemEntityType.directory) { - exit_with('Path ${group['path']} must be a directory'); + try { + final groups = conf['groups']; + if (groups == null) { + exit_with('No groups found in the config file.'); } - - if (!Directory(group['path']).existsSync()) { - exit_with('${group['path']} does not exist'); + if (groups.runtimeType != [].runtimeType) { + exit_with('Groups must be a list of configurations.'); } - - if (group['class_name'] == null) { - exit_with('No class name provided for one of the groups.'); + for (var group in groups) { + group.forEach((key, value) { + if (value == null) exit_with('$key cannot be null'); + }); + + if (group['path'] == null) { + exit_with('No path provided for one of the groups.'); + } + + if (File(group['path']).statSync().type != + FileSystemEntityType.directory) { + exit_with('Path ${group['path']} must be a directory'); + } + + if (!Directory(group['path']).existsSync()) { + exit_with('${group['path']} does not exist'); + } + + if (group['class_name'] == null) { + exit_with('No class name provided for one of the groups.'); + } } + } on Error catch (e) { + exit_with('Configs Validation failed', e.stackTrace); } } + +void error(String msg, [StackTrace stackTrace]) => + Logger('Spider').log(Level('ERROR', 1100), msg, stackTrace); + +void info(String msg) => Logger('Spider').info(msg); + +void warning(String msg) => Logger('Spider').warning(msg); + +void verbose(String msg) => Logger('Spider').log(Level('DEBUG', 600), msg); + +void success(String msg) => Logger('Spider').log(Level('SUCCESS', 1050), msg); diff --git a/pubspec.yaml b/pubspec.yaml index 67d19a1..341934d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,6 +11,7 @@ dependencies: yaml: ^2.2.0 args: ^1.5.2 dart_style: ^1.3.3 + logging: ^0.11.4 dev_dependencies: build_runner: ^1.7.4