| // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file |
| // 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. |
| |
| /// Validates the yaml input by the user, prints useful info for the user |
| |
| import 'package:ffigen/src/code_generator.dart'; |
| import 'package:ffigen/src/header_parser/type_extractor/cxtypekindmap.dart'; |
| |
| import 'package:logging/logging.dart'; |
| import 'package:yaml/yaml.dart'; |
| |
| import '../strings.dart' as strings; |
| import 'config_types.dart'; |
| import 'spec_utils.dart'; |
| |
| final _logger = Logger('ffigen.config_provider.config'); |
| |
| /// Provides configurations to other modules. |
| /// |
| /// Handles validation, extraction of confiurations from yaml file. |
| class Config { |
| /// output file name. |
| String get output => _output; |
| late String _output; |
| // Holds headers and filters for header. |
| Headers get headers => _headers; |
| late Headers _headers; |
| |
| /// CommandLine Arguments to pass to clang_compiler. |
| List<String> get compilerOpts => _compilerOpts; |
| late List<String> _compilerOpts; |
| |
| /// Declaration config for Functions. |
| Declaration get functionDecl => _functionDecl; |
| late Declaration _functionDecl; |
| |
| /// Declaration config for Structs. |
| Declaration get structDecl => _structDecl; |
| late Declaration _structDecl; |
| |
| /// Declaration config for Enums. |
| Declaration get enumClassDecl => _enumClassDecl; |
| late Declaration _enumClassDecl; |
| |
| /// Declaration config for Unnamed enum constants. |
| Declaration get unnamedEnumConstants => _unnamedEnumConstants; |
| late Declaration _unnamedEnumConstants; |
| |
| /// Declaration config for Macro constants. |
| Declaration get macroDecl => _macroDecl; |
| late Declaration _macroDecl; |
| |
| /// If generated bindings should be sorted alphabetically. |
| bool get sort => _sort; |
| late bool _sort; |
| |
| /// If typedef of supported types(int8_t) should be directly used. |
| bool get useSupportedTypedefs => _useSupportedTypedefs; |
| late bool _useSupportedTypedefs; |
| |
| /// Stores typedef name to NativeType mappings specified by user. |
| Map<String, SupportedNativeType> get typedefNativeTypeMappings => |
| _typedefNativeTypeMappings; |
| late Map<String, SupportedNativeType> _typedefNativeTypeMappings; |
| |
| /// Extracted Doc comment type. |
| CommentType get commentType => _commentType; |
| late CommentType _commentType; |
| |
| /// If tool should generate array workarounds. |
| /// |
| /// If false(default), structs with inline array members will have all its |
| /// members removed. |
| bool get arrayWorkaround => _arrayWorkaround; |
| late bool _arrayWorkaround; |
| |
| /// If dart bool should be generated for C booleans. |
| bool get dartBool => _dartBool; |
| late bool _dartBool; |
| |
| /// Name of the wrapper class. |
| String get wrapperName => _wrapperName; |
| late String _wrapperName; |
| |
| /// Doc comment for the wrapper class. |
| String get wrapperDocComment => _wrapperDocComment; |
| late String _wrapperDocComment; |
| |
| /// Header of the generated bindings. |
| String get preamble => _preamble; |
| late String _preamble; |
| |
| /// If `Dart_Handle` should be mapped with Handle/Object. |
| bool get useDartHandle => _useDartHandle; |
| late bool _useDartHandle; |
| |
| Config._(); |
| |
| /// Create config from Yaml map. |
| factory Config.fromYaml(YamlMap map) { |
| final configspecs = Config._(); |
| _logger.finest('Config Map: ' + map.toString()); |
| |
| final specs = configspecs._getSpecs(); |
| |
| final result = configspecs._checkConfigs(map, specs); |
| if (!result) { |
| throw FormatException('Invalid configurations provided.'); |
| } |
| |
| configspecs._extract(map, specs); |
| return configspecs; |
| } |
| |
| /// Validates Yaml according to given specs. |
| bool _checkConfigs(YamlMap map, Map<String, Specification> specs) { |
| var _result = true; |
| for (final key in specs.keys) { |
| final spec = specs[key]; |
| if (map.containsKey(key)) { |
| _result = _result && spec!.validator(key, map[key]); |
| } else if (spec!.requirement == Requirement.yes) { |
| _logger.severe("Key '${key}' is required."); |
| _result = false; |
| } else if (spec.requirement == Requirement.prefer) { |
| _logger.warning("Prefer adding Key '$key' to your config."); |
| } |
| } |
| // Warn about unknown keys. |
| for (final key in map.keys) { |
| if (!specs.containsKey(key)) { |
| _logger.warning("Unknown key '$key' found."); |
| } |
| } |
| |
| return _result; |
| } |
| |
| /// Extracts variables from Yaml according to given specs. |
| /// |
| /// Validation must be done beforehand, using [_checkConfigs]. |
| void _extract(YamlMap map, Map<String, Specification> specs) { |
| for (final key in specs.keys) { |
| final spec = specs[key]; |
| if (map.containsKey(key)) { |
| spec!.extractedResult(spec.extractor(map[key])); |
| } else { |
| spec!.extractedResult(spec.defaultValue?.call()); |
| } |
| } |
| } |
| |
| /// Returns map of various specifications avaialble for our tool. |
| /// |
| /// Key: Name, Value: [Specification] |
| Map<String, Specification> _getSpecs() { |
| return <String, Specification>{ |
| strings.output: Specification<String>( |
| requirement: Requirement.yes, |
| validator: outputValidator, |
| extractor: outputExtractor, |
| extractedResult: (dynamic result) => _output = result as String, |
| ), |
| strings.headers: Specification<Headers>( |
| requirement: Requirement.yes, |
| validator: headersValidator, |
| extractor: headersExtractor, |
| extractedResult: (dynamic result) => _headers = result as Headers, |
| ), |
| strings.compilerOpts: Specification<List<String>>( |
| requirement: Requirement.no, |
| validator: compilerOptsValidator, |
| extractor: compilerOptsExtractor, |
| defaultValue: () => [], |
| extractedResult: (dynamic result) => |
| _compilerOpts = result as List<String>, |
| ), |
| strings.functions: Specification<Declaration>( |
| requirement: Requirement.no, |
| validator: declarationConfigValidator, |
| extractor: declarationConfigExtractor, |
| defaultValue: () => Declaration(), |
| extractedResult: (dynamic result) { |
| _functionDecl = result as Declaration; |
| }, |
| ), |
| strings.structs: Specification<Declaration>( |
| requirement: Requirement.no, |
| validator: declarationConfigValidator, |
| extractor: declarationConfigExtractor, |
| defaultValue: () => Declaration(), |
| extractedResult: (dynamic result) { |
| _structDecl = result as Declaration; |
| }, |
| ), |
| strings.enums: Specification<Declaration>( |
| requirement: Requirement.no, |
| validator: declarationConfigValidator, |
| extractor: declarationConfigExtractor, |
| defaultValue: () => Declaration(), |
| extractedResult: (dynamic result) { |
| _enumClassDecl = result as Declaration; |
| }, |
| ), |
| strings.unnamedEnums: Specification<Declaration>( |
| requirement: Requirement.no, |
| validator: declarationConfigValidator, |
| extractor: declarationConfigExtractor, |
| defaultValue: () => Declaration(), |
| extractedResult: (dynamic result) => |
| _unnamedEnumConstants = result as Declaration, |
| ), |
| strings.macros: Specification<Declaration>( |
| requirement: Requirement.no, |
| validator: declarationConfigValidator, |
| extractor: declarationConfigExtractor, |
| defaultValue: () => Declaration(), |
| extractedResult: (dynamic result) { |
| _macroDecl = result as Declaration; |
| }, |
| ), |
| strings.sizemap: Specification<Map<int, SupportedNativeType>>( |
| validator: sizemapValidator, |
| extractor: sizemapExtractor, |
| defaultValue: () => <int, SupportedNativeType>{}, |
| extractedResult: (dynamic result) { |
| final map = result as Map<int, SupportedNativeType>; |
| for (final key in map.keys) { |
| if (cxTypeKindToSupportedNativeTypes.containsKey(key)) { |
| cxTypeKindToSupportedNativeTypes[key] = map[key]!; |
| } |
| } |
| }, |
| ), |
| strings.typedefmap: Specification<Map<String, SupportedNativeType>>( |
| validator: typedefmapValidator, |
| extractor: typedefmapExtractor, |
| defaultValue: () => <String, SupportedNativeType>{}, |
| extractedResult: (dynamic result) => _typedefNativeTypeMappings = |
| result as Map<String, SupportedNativeType>, |
| ), |
| strings.sort: Specification<bool>( |
| requirement: Requirement.no, |
| validator: booleanValidator, |
| extractor: booleanExtractor, |
| defaultValue: () => false, |
| extractedResult: (dynamic result) => _sort = result as bool, |
| ), |
| strings.useSupportedTypedefs: Specification<bool>( |
| requirement: Requirement.no, |
| validator: booleanValidator, |
| extractor: booleanExtractor, |
| defaultValue: () => true, |
| extractedResult: (dynamic result) => |
| _useSupportedTypedefs = result as bool, |
| ), |
| strings.comments: Specification<CommentType>( |
| requirement: Requirement.no, |
| validator: commentValidator, |
| extractor: commentExtractor, |
| defaultValue: () => CommentType.def(), |
| extractedResult: (dynamic result) => |
| _commentType = result as CommentType, |
| ), |
| strings.arrayWorkaround: Specification<bool>( |
| requirement: Requirement.no, |
| validator: booleanValidator, |
| extractor: booleanExtractor, |
| defaultValue: () => false, |
| extractedResult: (dynamic result) => _arrayWorkaround = result as bool, |
| ), |
| strings.dartBool: Specification<bool>( |
| requirement: Requirement.no, |
| validator: booleanValidator, |
| extractor: booleanExtractor, |
| defaultValue: () => true, |
| extractedResult: (dynamic result) => _dartBool = result as bool, |
| ), |
| strings.name: Specification<String>( |
| requirement: Requirement.prefer, |
| validator: dartClassNameValidator, |
| extractor: stringExtractor, |
| defaultValue: () => 'NativeLibrary', |
| extractedResult: (dynamic result) => _wrapperName = result as String, |
| ), |
| strings.description: Specification<String?>( |
| requirement: Requirement.prefer, |
| validator: nonEmptyStringValidator, |
| extractor: stringExtractor, |
| defaultValue: () => null, |
| extractedResult: (dynamic result) => |
| _wrapperDocComment = result as String, |
| ), |
| strings.preamble: Specification<String>( |
| requirement: Requirement.no, |
| validator: nonEmptyStringValidator, |
| extractor: stringExtractor, |
| extractedResult: (dynamic result) => _preamble = result as String, |
| ), |
| strings.useDartHandle: Specification<bool>( |
| requirement: Requirement.no, |
| validator: booleanValidator, |
| extractor: booleanExtractor, |
| defaultValue: () => true, |
| extractedResult: (dynamic result) => _useDartHandle = result as bool, |
| ), |
| }; |
| } |
| } |