Update public API (#70)
- Updated `Config`'s class members to use public getter, private variable pattern.
- Replaced ConfigError with FormatException.
- Refactored all shared global variables to data.dart.
- Send test coverage to coveralls in travis.
diff --git a/.travis.yml b/.travis.yml
index fe0efef..cd06229 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,14 +12,20 @@
directories:
- $HOME/.pub-cache
before_install:
- # install libclang-dev
+ # Install libclang-dev.
- sudo add-apt-repository "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-10 main"
- wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -
- sudo apt-get update
- sudo apt-get install clang-10 libclang-10-dev
- # use clang from installed llvm
+ # Use clang from installed llvm.
- export PATH="/usr/lib/llvm-10/bin:$PATH"
before_script:
- 'pub run ffigen:setup'
- cd test/native_test && dart build_test_dylib.dart && cd ../..
+
+matrix:
+ include:
+ - dart: dev
+ script: ./tool/travis.sh
+ name: Collect and report coverage.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 21853fb..b773ee0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,4 @@
-# 0.2.0-dev
+# 0.2.0
- Updated header config. Header `entry-points` and `include-directives` are now specified under `headers` key. Glob syntax is allowed.
- Updated declaration `include`/`exclude` config. These are now specified as a list.
- Added Regexp based declaration renaming using `rename` subkey.
diff --git a/README.md b/README.md
index 477a0e9..f97ab70 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,6 @@
+[![pub package](https://img.shields.io/pub/v/ffigen.svg)](https://pub.dev/packages/ffigen)
[![Build Status](https://travis-ci.org/dart-lang/ffigen.svg?branch=master)](https://travis-ci.org/dart-lang/ffigen)
+[![Coverage Status](https://coveralls.io/repos/github/dart-lang/ffigen/badge.svg?branch=master)](https://coveralls.io/github/dart-lang/ffigen?branch=master)
Experimental binding generator for [FFI](https://dart.dev/guides/libraries/c-interop)
bindings.
diff --git a/bin/ffigen.dart b/bin/ffigen.dart
index 9328b28..d0b2ee1 100644
--- a/bin/ffigen.dart
+++ b/bin/ffigen.dart
@@ -34,7 +34,7 @@
Config config;
try {
config = getConfig(argResult);
- } on ConfigError {
+ } on FormatException {
print('Please fix configuration errors and re-run the tool.');
exit(1);
}
@@ -42,10 +42,6 @@
// Parse the bindings according to config object provided.
final library = parse(config);
- if (config.sort) {
- library.sort();
- }
-
// Generate file for the parsed bindings.
final gen = File(config.output);
library.generateFile(gen);
diff --git a/lib/ffigen.dart b/lib/ffigen.dart
index 2b0a304..3425eec 100644
--- a/lib/ffigen.dart
+++ b/lib/ffigen.dart
@@ -8,5 +8,5 @@
library ffigen;
export 'src/code_generator.dart' show Library;
-export 'src/config_provider.dart' show Config, ConfigError;
+export 'src/config_provider.dart' show Config;
export 'src/header_parser.dart' show parse;
diff --git a/lib/src/config_provider/config.dart b/lib/src/config_provider/config.dart
index 583287d..0a913ad 100644
--- a/lib/src/config_provider/config.dart
+++ b/lib/src/config_provider/config.dart
@@ -21,53 +21,66 @@
/// Handles validation, extraction of confiurations from yaml file.
class Config {
/// output file name.
- String output;
-
+ String get output => _output;
+ String _output;
// Holds headers and filters for header.
- Headers headers;
+ Headers get headers => _headers;
+ Headers _headers;
/// CommandLine Arguments to pass to clang_compiler.
- List<String> compilerOpts;
+ List<String> get compilerOpts => _compilerOpts;
+ List<String> _compilerOpts;
/// Declaration config for Functions.
- Declaration functionDecl;
+ Declaration get functionDecl => _functionDecl;
+ Declaration _functionDecl;
/// Declaration config for Structs.
- Declaration structDecl;
+ Declaration get structDecl => _structDecl;
+ Declaration _structDecl;
/// Declaration config for Enums.
- Declaration enumClassDecl;
+ Declaration get enumClassDecl => _enumClassDecl;
+ Declaration _enumClassDecl;
/// Declaration config for Enums.
- Declaration macroDecl;
+ Declaration get macroDecl => _macroDecl;
+ Declaration _macroDecl;
/// If generated bindings should be sorted alphabetically.
- bool sort;
+ bool get sort => _sort;
+ bool _sort;
/// If typedef of supported types(int8_t) should be directly used.
- bool useSupportedTypedefs;
+ bool get useSupportedTypedefs => _useSupportedTypedefs;
+ bool _useSupportedTypedefs;
/// Extracted Doc comment type.
- CommentType commentType;
+ CommentType get commentType => _commentType;
+ CommentType _commentType;
/// If tool should generate array workarounds.
///
/// If false(default), structs with inline array members will have all its
/// members removed.
- bool arrayWorkaround;
+ bool get arrayWorkaround => _arrayWorkaround;
+ bool _arrayWorkaround;
/// If constants should be generated for unnamed enums.
- bool unnamedEnums;
+ bool get unnamedEnums => _unnamedEnums;
+ bool _unnamedEnums;
/// Name of the wrapper class.
- String wrapperName;
+ String get wrapperName => _wrapperName;
+ String _wrapperName;
/// Doc comment for the wrapper class.
- String wrapperDocComment;
+ String get wrapperDocComment => _wrapperDocComment;
+ String _wrapperDocComment;
/// Header of the generated bindings.
- String preamble;
-
+ String get preamble => _preamble;
+ String _preamble;
Config._();
/// Create config from Yaml map.
@@ -79,7 +92,7 @@
final result = configspecs._checkConfigs(map, specs);
if (!result) {
- throw ConfigError();
+ throw FormatException('Invalid configurations provided.');
}
configspecs._extract(map, specs);
@@ -133,20 +146,21 @@
requirement: Requirement.yes,
validator: outputValidator,
extractor: outputExtractor,
- extractedResult: (dynamic result) => output = result as String,
+ 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,
+ 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>,
+ _compilerOpts = result as List<String>,
),
strings.functions: Specification<Declaration>(
requirement: Requirement.no,
@@ -154,7 +168,7 @@
extractor: declarationConfigExtractor,
defaultValue: () => Declaration(),
extractedResult: (dynamic result) {
- functionDecl = result as Declaration;
+ _functionDecl = result as Declaration;
},
),
strings.structs: Specification<Declaration>(
@@ -163,7 +177,7 @@
extractor: declarationConfigExtractor,
defaultValue: () => Declaration(),
extractedResult: (dynamic result) {
- structDecl = result as Declaration;
+ _structDecl = result as Declaration;
},
),
strings.enums: Specification<Declaration>(
@@ -172,7 +186,7 @@
extractor: declarationConfigExtractor,
defaultValue: () => Declaration(),
extractedResult: (dynamic result) {
- enumClassDecl = result as Declaration;
+ _enumClassDecl = result as Declaration;
},
),
strings.macros: Specification<Declaration>(
@@ -181,7 +195,7 @@
extractor: declarationConfigExtractor,
defaultValue: () => Declaration(),
extractedResult: (dynamic result) {
- macroDecl = result as Declaration;
+ _macroDecl = result as Declaration;
},
),
strings.sizemap: Specification<Map<int, SupportedNativeType>>(
@@ -202,7 +216,7 @@
validator: booleanValidator,
extractor: booleanExtractor,
defaultValue: () => false,
- extractedResult: (dynamic result) => sort = result as bool,
+ extractedResult: (dynamic result) => _sort = result as bool,
),
strings.useSupportedTypedefs: Specification<bool>(
requirement: Requirement.no,
@@ -210,7 +224,7 @@
extractor: booleanExtractor,
defaultValue: () => true,
extractedResult: (dynamic result) =>
- useSupportedTypedefs = result as bool,
+ _useSupportedTypedefs = result as bool,
),
strings.comments: Specification<CommentType>(
requirement: Requirement.no,
@@ -218,28 +232,28 @@
extractor: commentExtractor,
defaultValue: () => CommentType.def(),
extractedResult: (dynamic result) =>
- commentType = result as CommentType,
+ _commentType = result as CommentType,
),
strings.arrayWorkaround: Specification<bool>(
requirement: Requirement.no,
validator: booleanValidator,
extractor: booleanExtractor,
defaultValue: () => false,
- extractedResult: (dynamic result) => arrayWorkaround = result as bool,
+ extractedResult: (dynamic result) => _arrayWorkaround = result as bool,
),
strings.unnamedEnums: Specification<bool>(
requirement: Requirement.no,
validator: booleanValidator,
extractor: booleanExtractor,
defaultValue: () => true,
- extractedResult: (dynamic result) => unnamedEnums = result as bool,
+ extractedResult: (dynamic result) => _unnamedEnums = result as bool,
),
strings.name: Specification<String>(
requirement: Requirement.prefer,
validator: dartClassNameValidator,
extractor: stringExtractor,
defaultValue: () => 'NativeLibrary',
- extractedResult: (dynamic result) => wrapperName = result as String,
+ extractedResult: (dynamic result) => _wrapperName = result as String,
),
strings.description: Specification<String>(
requirement: Requirement.prefer,
@@ -247,28 +261,14 @@
extractor: stringExtractor,
defaultValue: () => null,
extractedResult: (dynamic result) =>
- wrapperDocComment = result as String,
+ _wrapperDocComment = result as String,
),
strings.preamble: Specification<String>(
requirement: Requirement.no,
validator: nonEmptyStringValidator,
extractor: stringExtractor,
- extractedResult: (dynamic result) => preamble = result as String,
+ extractedResult: (dynamic result) => _preamble = result as String,
),
};
}
}
-
-class ConfigError implements Exception {
- final String message;
- ConfigError([this.message]);
-
- @override
- String toString() {
- if (message == null) {
- return 'ConfigError: Invalid configurations provided.';
- } else {
- return 'ConfigError: $message';
- }
- }
-}
diff --git a/lib/src/config_provider/config_types.dart b/lib/src/config_provider/config_types.dart
index b699239..fa59745 100644
--- a/lib/src/config_provider/config_types.dart
+++ b/lib/src/config_provider/config_types.dart
@@ -54,12 +54,14 @@
/// Path to headers.
///
/// This contains all the headers, after extraction from Globs.
- List<String> entryPoints = [];
+ final List<String> entryPoints;
/// Include filter for headers.
- HeaderIncludeFilter includeFilter = GlobHeaderFilter();
+ final HeaderIncludeFilter includeFilter;
- Headers({this.entryPoints, this.includeFilter});
+ Headers({List<String> entryPoints, HeaderIncludeFilter includeFilter})
+ : entryPoints = entryPoints ?? [],
+ includeFilter = includeFilter ?? GlobHeaderFilter();
}
abstract class HeaderIncludeFilter {
diff --git a/lib/src/header_parser/data.dart b/lib/src/header_parser/data.dart
index 87551cb..6c21338 100644
--- a/lib/src/header_parser/data.dart
+++ b/lib/src/header_parser/data.dart
@@ -5,7 +5,9 @@
import 'dart:ffi';
import 'dart:isolate';
-import 'package:ffigen/src/config_provider.dart';
+import 'package:ffigen/src/code_generator.dart' show Constant;
+import 'package:ffigen/src/config_provider.dart' show Config;
+import 'package:meta/meta.dart';
import 'clang_bindings/clang_bindings.dart' show Clang;
import 'utils.dart';
@@ -13,16 +15,40 @@
/// Holds all Global shared variables.
/// Holds configurations.
-Config config;
+Config get config => _config;
+Config _config;
/// Holds clang functions.
-Clang clang;
+Clang get clang => _clang;
+Clang _clang;
+
+// Tracks seen status for bindings
+BindingsIndex get bindingsIndex => _bindingsIndex;
+BindingsIndex _bindingsIndex;
/// Used for naming typedefs.
-IncrementalNamer incrementalNamer;
+IncrementalNamer get incrementalNamer => _incrementalNamer;
+IncrementalNamer _incrementalNamer;
/// Holds the unique id refering to this isolate.
///
/// Used by visitChildren_wrap to call the correct dart function from C.
// int get uid => Isolate.current.controlPort.;
final uid = Isolate.current.controlPort.nativePort;
+
+/// Saved macros, Key: prefixedName, Value originalName.
+Map<String, String> get savedMacros => _savedMacros;
+Map<String, String> _savedMacros;
+
+/// Saved unnamed EnumConstants.
+List<Constant> get unnamedEnumConstants => _unnamedEnumConstants;
+List<Constant> _unnamedEnumConstants;
+
+void initializeGlobals({@required Config config, @required Clang clang}) {
+ _config = config;
+ _clang = clang;
+ _incrementalNamer = IncrementalNamer();
+ _savedMacros = {};
+ _unnamedEnumConstants = [];
+ _bindingsIndex = BindingsIndex();
+}
diff --git a/lib/src/header_parser/includer.dart b/lib/src/header_parser/includer.dart
index c17b13e..a4766e1 100644
--- a/lib/src/header_parser/includer.dart
+++ b/lib/src/header_parser/includer.dart
@@ -2,20 +2,13 @@
// 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 'package:ffigen/src/code_generator.dart';
import 'data.dart';
/// Utility functions to check whether a binding should be parsed or not
/// based on filters.
-// Stores binding names already scene. Mp key is same as their original name.
-Map<String, Struc> _structs = {};
-Map<String, Func> _functions = {};
-Map<String, EnumClass> _enumClass = {};
-Map<String, String> _macros = {};
-
bool shouldIncludeStruct(String name) {
- if (_structs.containsKey(name) || name == '') {
+ if (bindingsIndex.isSeenStruct(name) || name == '') {
return false;
} else if (config.structDecl == null ||
config.structDecl.shouldInclude(name)) {
@@ -26,7 +19,7 @@
}
bool shouldIncludeFunc(String name) {
- if (_functions.containsKey(name) || name == '') {
+ if (bindingsIndex.isSeenFunc(name) || name == '') {
return false;
} else if (config.functionDecl == null ||
config.functionDecl.shouldInclude(name)) {
@@ -37,7 +30,7 @@
}
bool shouldIncludeEnumClass(String name) {
- if (_enumClass.containsKey(name) || name == '') {
+ if (bindingsIndex.isSeenEnumClass(name) || name == '') {
return false;
} else if (config.enumClassDecl == null ||
config.enumClassDecl.shouldInclude(name)) {
@@ -48,7 +41,7 @@
}
bool shouldIncludeMacro(String name) {
- if (_macros.containsKey(name) || name == '') {
+ if (bindingsIndex.isSeenMacro(name) || name == '') {
return false;
} else if (config.macroDecl == null || config.macroDecl.shouldInclude(name)) {
return true;
@@ -76,51 +69,3 @@
return _headerCache[sourceFile];
}
-
-bool isSeenStruc(String originalName) {
- return _structs.containsKey(originalName);
-}
-
-void addStrucToSeen(String originalName, Struc struc) {
- _structs[originalName] = struc;
-}
-
-Struc getSeenStruc(String originalName) {
- return _structs[originalName];
-}
-
-bool isSeenFunc(String originalName) {
- return _functions.containsKey(originalName);
-}
-
-void addFuncToSeen(String originalName, Func func) {
- _functions[originalName] = func;
-}
-
-Func getSeenFunc(String originalName) {
- return _functions[originalName];
-}
-
-bool isSeenEnumClass(String originalName) {
- return _enumClass.containsKey(originalName);
-}
-
-void addEnumClassToSeen(String originalName, EnumClass enumClass) {
- _enumClass[originalName] = enumClass;
-}
-
-EnumClass getSeenEnumClass(String originalName) {
- return _enumClass[originalName];
-}
-
-bool isSeenMacro(String originalName) {
- return _macros.containsKey(originalName);
-}
-
-void addMacroToSeen(String originalName, String macro) {
- _macros[originalName] = macro;
-}
-
-String getSeenMacro(String originalName) {
- return _macros[originalName];
-}
diff --git a/lib/src/header_parser/parser.dart b/lib/src/header_parser/parser.dart
index 87e14ef..1771574 100644
--- a/lib/src/header_parser/parser.dart
+++ b/lib/src/header_parser/parser.dart
@@ -10,7 +10,6 @@
import 'package:ffigen/src/header_parser/sub_parsers/macro_parser.dart';
import 'package:ffigen/src/config_provider/config_types.dart';
import 'package:ffigen/src/find_resource.dart';
-import 'package:ffigen/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart';
import 'package:ffigen/src/header_parser/translation_unit_parser.dart';
import 'package:ffigen/src/strings.dart' as strings;
import 'package:logging/logging.dart';
@@ -21,8 +20,8 @@
import 'utils.dart';
/// Main entrypoint for header_parser.
-Library parse(Config conf, {bool sort = false}) {
- initParser(conf);
+Library parse(Config c) {
+ initParser(c);
final bindings = parseToBindings();
@@ -33,7 +32,7 @@
header: config.preamble,
);
- if (sort) {
+ if (config.sort) {
library.sort();
}
return library;
@@ -45,13 +44,9 @@
var _logger = Logger('ffigen.header_parser.parser');
-/// Initialises parser, clears any previous values.
+/// Initializes parser, clears any previous values.
void initParser(Config c) {
- // Set global configurations.
- config = c;
- incrementalNamer = IncrementalNamer();
-
- // Find full path of dynamic library and initialise bindings.
+ // Find full path of dynamic library and initialize bindings.
if (findDotDartTool() == null) {
throw Exception('Unable to find .dart_tool.');
} else {
@@ -60,7 +55,12 @@
strings.ffigenFolderName,
strings.dylibFileName,
);
- clang = clang_types.Clang(DynamicLibrary.open(fullDylibPath));
+
+ // Initialize global variables.
+ initializeGlobals(
+ config: c,
+ clang: clang_types.Clang(DynamicLibrary.open(fullDylibPath)),
+ );
}
}
@@ -74,7 +74,6 @@
/// Add compiler opt for comment parsing for clang based on config.
if (config.commentType.length != CommentLength.none &&
config.commentType.style == CommentStyle.any) {
- config.compilerOpts ??= [];
config.compilerOpts.add(strings.fparseAllComments);
}
@@ -122,7 +121,7 @@
}
// Add all saved unnamed enums.
- bindings.addAll(getSavedUnNamedEnums());
+ bindings.addAll(unnamedEnumConstants);
// Parse all saved macros.
bindings.addAll(parseSavedMacros());
diff --git a/lib/src/header_parser/sub_parsers/enumdecl_parser.dart b/lib/src/header_parser/sub_parsers/enumdecl_parser.dart
index 0fbb9e8..3460e28 100644
--- a/lib/src/header_parser/sub_parsers/enumdecl_parser.dart
+++ b/lib/src/header_parser/sub_parsers/enumdecl_parser.dart
@@ -42,14 +42,15 @@
} else {
_logger.fine('Unnamed enum inside a typedef.');
}
- } else if (shouldIncludeEnumClass(enumName) && !isSeenEnumClass(enumName)) {
+ } else if (shouldIncludeEnumClass(enumName) &&
+ !bindingsIndex.isSeenEnumClass(enumName)) {
_logger.fine('++++ Adding Enum: ${cursor.completeStringRepr()}');
_stack.top.enumClass = EnumClass(
dartDoc: getCursorDocComment(cursor),
originalName: enumName,
name: config.enumClassDecl.renameUsingConfig(enumName),
);
- addEnumClassToSeen(enumName, _stack.top.enumClass);
+ bindingsIndex.addEnumClassToSeen(enumName, _stack.top.enumClass);
_addEnumConstant(cursor);
}
diff --git a/lib/src/header_parser/sub_parsers/functiondecl_parser.dart b/lib/src/header_parser/sub_parsers/functiondecl_parser.dart
index d958c57..9137c73 100644
--- a/lib/src/header_parser/sub_parsers/functiondecl_parser.dart
+++ b/lib/src/header_parser/sub_parsers/functiondecl_parser.dart
@@ -32,7 +32,7 @@
_stack.top.unimplementedParameterType = false;
final funcName = cursor.spelling();
- if (shouldIncludeFunc(funcName) && !isSeenFunc(funcName)) {
+ if (shouldIncludeFunc(funcName) && !bindingsIndex.isSeenFunc(funcName)) {
_logger.fine('++++ Adding Function: ${cursor.completeStringRepr()}');
final rt = _getFunctionReturnType(cursor);
@@ -70,7 +70,7 @@
returnType: rt,
parameters: parameters,
);
- addFuncToSeen(funcName, _stack.top.func);
+ bindingsIndex.addFuncToSeen(funcName, _stack.top.func);
}
return _stack.pop().func;
diff --git a/lib/src/header_parser/sub_parsers/macro_parser.dart b/lib/src/header_parser/sub_parsers/macro_parser.dart
index 27a7b30..dd35b78 100644
--- a/lib/src/header_parser/sub_parsers/macro_parser.dart
+++ b/lib/src/header_parser/sub_parsers/macro_parser.dart
@@ -18,21 +18,18 @@
var _logger = Logger('ffigen.header_parser.macro_parser');
-/// Saved macros, Key: prefixedName, Value originalName.
-final _savedMacros = <String, String>{};
-
/// Adds a macro definition to be parsed later.
void saveMacroDefinition(Pointer<clang_types.CXCursor> cursor) {
final originalMacroName = cursor.spelling();
if (shouldIncludeMacro(originalMacroName) &&
- !isSeenMacro(originalMacroName) &&
+ !bindingsIndex.isSeenMacro(originalMacroName) &&
clang.clang_Cursor_isMacroBuiltin_wrap(cursor) == 0 &&
clang.clang_Cursor_isMacroFunctionLike_wrap(cursor) == 0) {
// Parse macro only if it's not builtin or function-like.
_logger.fine(
"++++ Saved Macro '$originalMacroName' for later : ${cursor.completeStringRepr()}");
final prefixedName = config.macroDecl.renameUsingConfig(originalMacroName);
- addMacroToSeen(originalMacroName, prefixedName);
+ bindingsIndex.addMacroToSeen(originalMacroName, prefixedName);
_saveMacro(prefixedName, originalMacroName);
}
}
@@ -41,7 +38,7 @@
///
/// Macros are parsed later in [parseSavedMacros()].
void _saveMacro(String name, String originalName) {
- _savedMacros[name] = originalName;
+ savedMacros[name] = originalName;
}
List<Constant> _bindings;
@@ -52,7 +49,7 @@
List<Constant> parseSavedMacros() {
_bindings = [];
- if (_savedMacros.keys.isEmpty) {
+ if (savedMacros.keys.isEmpty) {
return _bindings;
}
@@ -117,7 +114,7 @@
switch (k) {
case clang_types.CXEvalResultKind.CXEval_Int:
constant = Constant(
- originalName: _savedMacros[macroName],
+ originalName: savedMacros[macroName],
name: macroName,
rawType: 'int',
rawValue: clang.clang_EvalResult_getAsLongLong(e).toString(),
@@ -125,7 +122,7 @@
break;
case clang_types.CXEvalResultKind.CXEval_Float:
constant = Constant(
- originalName: _savedMacros[macroName],
+ originalName: savedMacros[macroName],
name: macroName,
rawType: 'double',
rawValue: clang.clang_EvalResult_getAsDouble(e).toString(),
@@ -138,7 +135,7 @@
// Escape ' character, because our strings are enclosed with '.
value = value.replaceAll("'", r"\'");
constant = Constant(
- originalName: _savedMacros[macroName],
+ originalName: savedMacros[macroName],
name: macroName,
rawType: 'String',
rawValue: "'${value}'",
@@ -177,7 +174,7 @@
/// Generated macro variable names.
///
/// Used to determine if macro should be included in bindings or not.
-Set<String> _macroVarNames = {};
+Set<String> _macroVarNames;
/// Creates a temporary file for parsing macros in current directory.
File createFileForMacros() {
@@ -204,10 +201,10 @@
}
_macroVarNames = {};
- for (final prefixedMacroName in _savedMacros.keys) {
+ for (final prefixedMacroName in savedMacros.keys) {
// Write macro.
final macroVarName = MacroVariableString.encode(prefixedMacroName);
- sb.writeln('auto ${macroVarName} = ${_savedMacros[prefixedMacroName]};');
+ sb.writeln('auto ${macroVarName} = ${savedMacros[prefixedMacroName]};');
// Add to _macroVarNames.
_macroVarNames.add(macroVarName);
}
diff --git a/lib/src/header_parser/sub_parsers/structdecl_parser.dart b/lib/src/header_parser/sub_parsers/structdecl_parser.dart
index 39c56de..3b62123 100644
--- a/lib/src/header_parser/sub_parsers/structdecl_parser.dart
+++ b/lib/src/header_parser/sub_parsers/structdecl_parser.dart
@@ -43,7 +43,7 @@
if (structName.isEmpty) {
_logger.finest('unnamed structure or typedef structure declaration');
} else if ((ignoreFilter || shouldIncludeStruct(structName)) &&
- (!isSeenStruc(structName))) {
+ (!bindingsIndex.isSeenStruct(structName))) {
_logger.fine(
'++++ Adding Structure: structName: ${structName}, ${cursor.completeStringRepr()}');
_stack.top.struc = Struc(
@@ -53,7 +53,7 @@
);
// Adding to seen here to stop recursion if a struct has itself as a
// member, members are updated later.
- addStrucToSeen(structName, _stack.top.struc);
+ bindingsIndex.addStructToSeen(structName, _stack.top.struc);
_setStructMembers(cursor);
}
diff --git a/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart b/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart
index fedeb7e..b5039c4 100644
--- a/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart
+++ b/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart
@@ -14,10 +14,6 @@
var _logger = Logger('ffigen.header_parser.unnamed_enumdecl_parser');
-List<Constant> _constants = [];
-
-List<Constant> getSavedUnNamedEnums() => _constants;
-
/// Saves unnamed enums.
void saveUnNamedEnum(Pointer<clang_types.CXCursor> cursor) {
final resultCode = clang.clang_visitChildren_wrap(
@@ -58,7 +54,7 @@
/// Adds the parameter to func in [functiondecl_parser.dart].
void _addUnNamedEnumConstant(Pointer<clang_types.CXCursor> cursor) {
- _constants.add(
+ unnamedEnumConstants.add(
Constant(
originalName: cursor.spelling(),
name: config.enumClassDecl.renameMemberUsingConfig(
diff --git a/lib/src/header_parser/type_extractor/extractor.dart b/lib/src/header_parser/type_extractor/extractor.dart
index 1336d7e..c76c8ea 100644
--- a/lib/src/header_parser/type_extractor/extractor.dart
+++ b/lib/src/header_parser/type_extractor/extractor.dart
@@ -10,7 +10,6 @@
import '../clang_bindings/clang_bindings.dart' as clang_types;
import '../data.dart';
-import '../includer.dart';
import '../sub_parsers/structdecl_parser.dart';
import '../translation_unit_parser.dart';
import '../type_extractor/cxtypekindmap.dart';
@@ -104,8 +103,8 @@
// Also add a struct binding, if its unseen.
// TODO(23): Check if we should auto add struct.
- if (isSeenStruc(structName)) {
- type = Type.struct(getSeenStruc(structName));
+ if (bindingsIndex.isSeenStruct(structName)) {
+ type = Type.struct(bindingsIndex.getSeenStruct(structName));
} else {
final struc = parseStructDeclaration(cursor,
name: fixedStructName, ignoreFilter: true);
@@ -113,7 +112,7 @@
// Add to bindings.
addToBindings(struc);
// Add to seen.
- addStrucToSeen(structName, struc);
+ bindingsIndex.addStructToSeen(structName, struc);
}
cxtype.dispose();
diff --git a/lib/src/header_parser/utils.dart b/lib/src/header_parser/utils.dart
index e8190bf..6d8e159 100644
--- a/lib/src/header_parser/utils.dart
+++ b/lib/src/header_parser/utils.dart
@@ -322,3 +322,60 @@
return '${base}_$i';
}
}
+
+/// Tracks if a binding is 'seen' or not.
+class BindingsIndex {
+ // Stores binding names already seen. Map key is same as their original name.
+ final Map<String, Struc> _structs = {};
+ final Map<String, Func> _functions = {};
+ final Map<String, EnumClass> _enumClass = {};
+ final Map<String, String> _macros = {};
+
+ bool isSeenStruct(String originalName) {
+ return _structs.containsKey(originalName);
+ }
+
+ void addStructToSeen(String originalName, Struc struc) {
+ _structs[originalName] = struc;
+ }
+
+ Struc getSeenStruct(String originalName) {
+ return _structs[originalName];
+ }
+
+ bool isSeenFunc(String originalName) {
+ return _functions.containsKey(originalName);
+ }
+
+ void addFuncToSeen(String originalName, Func func) {
+ _functions[originalName] = func;
+ }
+
+ Func getSeenFunc(String originalName) {
+ return _functions[originalName];
+ }
+
+ bool isSeenEnumClass(String originalName) {
+ return _enumClass.containsKey(originalName);
+ }
+
+ void addEnumClassToSeen(String originalName, EnumClass enumClass) {
+ _enumClass[originalName] = enumClass;
+ }
+
+ EnumClass getSeenEnumClass(String originalName) {
+ return _enumClass[originalName];
+ }
+
+ bool isSeenMacro(String originalName) {
+ return _macros.containsKey(originalName);
+ }
+
+ void addMacroToSeen(String originalName, String macro) {
+ _macros[originalName] = macro;
+ }
+
+ String getSeenMacro(String originalName) {
+ return _macros[originalName];
+ }
+}
diff --git a/pubspec.yaml b/pubspec.yaml
index 3151c7d..5659a9d 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -3,7 +3,7 @@
# BSD-style license that can be found in the LICENSE file.
name: ffigen
-version: 0.2.0-dev
+version: 0.2.0
homepage: https://github.com/dart-lang/ffigen
description: Experimental generator for FFI bindings, using LibClang to parse C/C++ header files.
diff --git a/test/test_coverage.dart b/test/test_coverage.dart
new file mode 100644
index 0000000..812105f
--- /dev/null
+++ b/test/test_coverage.dart
@@ -0,0 +1,46 @@
+// 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.
+
+import 'code_generator_test.dart' as code_generator_test;
+import 'collision_tests/decl_decl_collision_test.dart'
+ as collision_tests_decl_decl_collision_test;
+import 'collision_tests/reserved_keyword_collision_test.dart'
+ as collision_tests_reserved_keyword_collision_test;
+import 'example_tests/cjson_example_test.dart'
+ as example_tests_cjson_example_test;
+import 'example_tests/libclang_example_test.dart'
+ as example_tests_libclang_example_test;
+import 'example_tests/simple_example_test.dart'
+ as example_tests_simple_example_test;
+import 'header_parser_tests/function_n_struct_test.dart'
+ as header_parser_tests_function_n_struct_test;
+import 'header_parser_tests/functions_test.dart'
+ as header_parser_tests_functions_test;
+import 'header_parser_tests/macros_test.dart'
+ as header_parser_tests_macros_test;
+import 'header_parser_tests/nested_parsing_test.dart'
+ as header_parser_tests_nested_parsing_test;
+import 'header_parser_tests/unnamed_enums_test.dart'
+ as header_parser_tests_unnamed_enums_test;
+import 'large_integration_tests/large_test.dart'
+ as large_integration_tests_large_test;
+import 'native_test/native_test.dart' as native_test_native_test;
+import 'rename_tests/rename_test.dart' as rename_tests_rename_test;
+
+void main() {
+ large_integration_tests_large_test.main();
+ example_tests_cjson_example_test.main();
+ example_tests_simple_example_test.main();
+ example_tests_libclang_example_test.main();
+ collision_tests_decl_decl_collision_test.main();
+ collision_tests_reserved_keyword_collision_test.main();
+ header_parser_tests_functions_test.main();
+ header_parser_tests_macros_test.main();
+ header_parser_tests_function_n_struct_test.main();
+ header_parser_tests_nested_parsing_test.main();
+ header_parser_tests_unnamed_enums_test.main();
+ native_test_native_test.main();
+ rename_tests_rename_test.main();
+ code_generator_test.main();
+}
diff --git a/tool/travis.sh b/tool/travis.sh
new file mode 100755
index 0000000..987955b
--- /dev/null
+++ b/tool/travis.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+# 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.
+
+# Fast fail the script on failures.
+set -e
+
+# Gather coverage and upload to Coveralls.
+pub global activate remove_from_coverage
+pub global activate dart_coveralls
+# Generate coverage report.
+pub global run dart_coveralls calc test/test_coverage.dart > lcov.info
+# Remove extra files from coverage report.
+pub global run remove_from_coverage -f lcov.info -r ".pub-cache"
+# Upload to coveralls.
+gem install coveralls-lcov
+coveralls-lcov lcov.info