[jnigen] Use `package:cli_config` (https://github.com/dart-lang/jnigen/issues/197)
diff --git a/pkgs/jnigen/bin/jnigen.dart b/pkgs/jnigen/bin/jnigen.dart index a5065de..518ba11 100644 --- a/pkgs/jnigen/bin/jnigen.dart +++ b/pkgs/jnigen/bin/jnigen.dart
@@ -12,6 +12,9 @@ } on ConfigException catch (e) { log.fatal(e); return; + } on FormatException catch (e) { + log.fatal(e); + return; } await generateJniBindings(config); }
diff --git a/pkgs/jnigen/lib/src/config/yaml_reader.dart b/pkgs/jnigen/lib/src/config/yaml_reader.dart index 4347ecb..ecae2cb 100644 --- a/pkgs/jnigen/lib/src/config/yaml_reader.dart +++ b/pkgs/jnigen/lib/src/config/yaml_reader.dart
@@ -6,15 +6,17 @@ import 'package:args/args.dart'; import 'package:yaml/yaml.dart'; +import 'package:cli_config/cli_config.dart' as cli_config; import 'config_exception.dart'; /// YAML Reader which enables to override specific values from command line. class YamlReader { - YamlReader.of(this.cli, this.yaml, this.yamlFile); - Map<String, String> cli; - Map<dynamic, dynamic> yaml; - File? yamlFile; + final cli_config.Config _config; + + final Uri? _configRoot; + + YamlReader.of(this._config, this._configRoot); /// Parses the provided command line arguments and returns a [YamlReader]. /// @@ -42,19 +44,15 @@ stderr.writeln(parser.usage); exit(1); } - final configFile = results['config'] as String?; - Map<dynamic, dynamic> yamlMap = {}; - if (configFile != null) { + final configFilePath = results['config'] as String?; + String? configFileContents; + Uri? configFileUri; + if (configFilePath != null) { try { - final yamlInput = loadYaml(File(configFile).readAsStringSync(), - sourceUrl: Uri.file(configFile)); - if (yamlInput is Map) { - yamlMap = yamlInput; - } else { - throw ConfigException('YAML config must be set of key value pairs'); - } + configFileContents = File(configFilePath).readAsStringSync(); + configFileUri = File(configFilePath).uri; } on Exception catch (e) { - stderr.writeln('cannot read $configFile: $e'); + stderr.writeln('Cannot read $configFilePath: $e.'); } } final regex = RegExp('([a-z-_.]+)=(.+)'); @@ -69,97 +67,53 @@ throw ConfigException('override does not match expected pattern'); } } + final config = cli_config.Config.fromConfigFileContents( + commandLineDefines: results['override'], + workingDirectory: Directory.current.uri, + environment: Platform.environment, + fileContents: configFileContents, + fileSourceUri: configFileUri, + ); return YamlReader.of( - properties, yamlMap, configFile != null ? File(configFile) : null); + config, + configFileUri?.resolve('.'), + ); } - bool? getBool(String property) { - if (cli.containsKey(property)) { - final v = cli[property]!; - if (v == 'true') { - return true; - } - if (v == 'false') { - return false; - } - throw ConfigException('expected boolean value for $property, got $v'); - } - return getYamlValue<bool>(property); - } + bool? getBool(String property) => _config.optionalBool(property); - String? getString(String property) { - final configValue = cli[property] ?? getYamlValue<String>(property); - return configValue; - } + String? getString(String property) => _config.optionalString(property); /// Same as [getString] but path is resolved relative to YAML config if it's /// from YAML config. - String? getPath(String property) { - final cliOverride = cli[property]; - if (cliOverride != null) return cliOverride; - final path = getYamlValue<String>(property); - if (path == null) return null; - // In (very unlikely) case YAML config didn't come from a file, - // do not try to resolve anything. - if (yamlFile == null) return path; - final yamlDir = yamlFile!.parent; - return yamlDir.uri.resolve(path).toFilePath(); - } + String? getPath(String property) => + _config.optionalPath(property)?.toFilePath(); - List<String>? getStringList(String property) { - final configValue = cli[property]?.split(';') ?? - getYamlValue<YamlList>(property)?.cast<String>(); - return configValue; - } + List<String>? getStringList(String property) => _config.optionalStringList( + property, + splitCliPattern: ';', + combineAllConfigs: false, + ); List<String>? getPathList(String property) { - final cliOverride = cli[property]?.split(';'); - if (cliOverride != null) return cliOverride; - final paths = getYamlValue<YamlList>(property)?.cast<String>(); - if (paths == null) return null; - // In (very unlikely) case YAML config didn't come from a file. - if (yamlFile == null) return paths; - final yamlDir = yamlFile!.parent; - return paths.map((path) => yamlDir.uri.resolve(path).toFilePath()).toList(); + final configResult = _config.optionalPathList( + property, + combineAllConfigs: false, + splitCliPattern: ';', + ); + return configResult?.map((e) => e.path).toList(); } - String? getOneOf(String property, Set<String> values) { - final value = cli[property] ?? getYamlValue<String>(property); - if (value == null || values.contains(value)) { - return value; - } - throw ConfigException('expected one of $values for $property'); - } + String? getOneOf(String property, Set<String> values) => + _config.optionalString(property, validValues: values); Map<String, String>? getStringMap(String property) { - final value = getYamlValue<YamlMap>(property); + final value = _config.valueOf<YamlMap?>(property); return value?.cast<String, String>(); } - bool hasValue(String property) => getYamlValue<dynamic>(property) != null; - - T? getYamlValue<T>(String property) { - final path = property.split('.'); - dynamic cursor = yaml; - String current = ''; - for (var i in path) { - if (cursor is YamlMap || cursor is Map) { - cursor = cursor[i]; - } else { - throw ConfigException('expected $current to be a YAML map'); - } - current = [if (current != '') current, i].join('.'); - if (cursor == null) { - return null; - } - } - if (cursor is! T) { - throw ConfigException( - 'expected $T for $property, got ${cursor.runtimeType}'); - } - return cursor; - } + bool hasValue(String property) => _config.valueOf<dynamic>(property) != null; /// Returns URI of the directory containing YAML config. - Uri? getConfigRoot() => yamlFile?.parent.uri; + Uri? getConfigRoot() => _configRoot; }
diff --git a/pkgs/jnigen/pubspec.yaml b/pkgs/jnigen/pubspec.yaml index b944f6b..2a3c731 100644 --- a/pkgs/jnigen/pubspec.yaml +++ b/pkgs/jnigen/pubspec.yaml
@@ -17,6 +17,7 @@ args: ^2.3.0 yaml: ^3.1.0 logging: ^1.0.2 + cli_config: ^0.1.0 dev_dependencies: lints: ^2.0.0 @@ -25,4 +26,3 @@ test: ^1.17.5 build_runner: ^2.2.0 json_serializable: ^6.6.0 -
diff --git a/pkgs/jnigen/test/config_test.dart b/pkgs/jnigen/test/config_test.dart index 883bae8..fd935c3 100644 --- a/pkgs/jnigen/test/config_test.dart +++ b/pkgs/jnigen/test/config_test.dart
@@ -2,6 +2,8 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'dart:io'; + import 'package:jnigen/src/config/config.dart'; import 'package:test/test.dart'; import 'package:path/path.dart' hide equals; @@ -10,12 +12,12 @@ import 'jackson_core_test/generate.dart'; const packageTests = 'test'; -final jacksonCoreTests = join(packageTests, 'jackson_core_test'); -final thirdParty = join(jacksonCoreTests, 'third_party'); -final lib = join(thirdParty, 'lib'); -final src = join(thirdParty, 'src'); -final testLib = join(thirdParty, 'test_', 'lib'); -final testSrc = join(thirdParty, 'test_', 'src'); +final jacksonCoreTests = absolute(packageTests, 'jackson_core_test'); +final thirdParty = absolute(jacksonCoreTests, 'third_party'); +final lib = absolute(thirdParty, 'lib'); +final src = absolute(thirdParty, 'src'); +final testLib = absolute(thirdParty, 'test_', 'lib'); +final testSrc = absolute(thirdParty, 'test_', 'src'); /// Compares 2 [Config] objects using [expect] to give useful errors when /// two fields are not equal. @@ -74,7 +76,7 @@ Config parseYamlConfig({List<String> overrides = const []}) => Config.parseArgs(['--config', jnigenYaml, ...overrides]); -void testForErrorChecking( +void testForErrorChecking<T extends Exception>( {required String name, required List<String> overrides, dynamic Function(Config)? function}) { @@ -86,7 +88,7 @@ function(config); } }, - throwsA(isA<ConfigException>()), + throwsA(isA<T>()), ); }); } @@ -95,8 +97,8 @@ final config = Config.parseArgs([ '--config', jnigenYaml, - '-Doutput.c.path=$testSrc/', - '-Doutput.dart.path=$testLib/', + '-Doutput.c.path=$testSrc${Platform.pathSeparator}', + '-Doutput.dart.path=$testLib${Platform.pathSeparator}', ]); test('compare configuration values', () { @@ -104,19 +106,19 @@ }); group('Test for config error checking', () { - testForErrorChecking( + testForErrorChecking<ConfigException>( name: 'Invalid bindings type', overrides: ['-Doutput.bindings_type=c_base'], ); - testForErrorChecking( + testForErrorChecking<ConfigException>( name: 'Invalid output structure', overrides: ['-Doutput.dart.structure=singl_file'], ); - testForErrorChecking( + testForErrorChecking<ConfigException>( name: 'Dart path not ending with /', overrides: ['-Doutput.dart.path=lib'], ); - testForErrorChecking( + testForErrorChecking<FormatException>( name: 'Invalid log level', overrides: ['-Dlog_level=inf'], );