• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

dart-lang / ffigen / 5844146996

01 Aug 2023 11:10PM CUT coverage: 92.332%. Remained the same
5844146996

push

github

web-flow
Bump coverallsapp/github-action from 2.2.0 to 2.2.1 (#596)

Bumps [coverallsapp/github-action](https://github.com/coverallsapp/github-action) from 2.2.0 to 2.2.1.
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/coverallsapp/github-action/commit/<a class=hub.com/dart-lang/ffigen/commit/95b1a2355bd0e526ad2fd62da9fd386ad4c98474">95b1a2355<a href="https://github.com/dart-lang/ffigen/commit/daa06036c457277aa7ddbf734123bf76ec921e44">&quot;&gt;&lt;code&gt;95b1a23&lt;/code&gt;&lt;/a&gt; feat: add files option (&lt;a href=&quot;https://redirect.github.com/coverallsapp/github-action/issues/185">#185</a>)</li>
<li><a href="https://github.com/coverallsapp/github-action/commit/<a class="double-link" href="https://github.com/dart-lang/ffigen/commit/12d23ccd512af6f292f5eaf42c191d64928b135c">12d23ccd5</a><a href="https://github.com/dart-lang/ffigen/commit/daa06036c457277aa7ddbf734123bf76ec921e44">&quot;&gt;&lt;code&gt;12d23cc&lt;/code&gt;&lt;/a&gt; feat: add fail-on-error option (&lt;a href=&quot;https://redirect.github.com/coverallsapp/github-action/issues/184&quot;&gt;#184&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/coverallsapp/github-action/commit/</a><a class="double-link" href="https://github.com/dart-lang/ffigen/commit/8e1cba00ac8bb526c6a1b96b810071687e5e8310">8e1cba00a</a><a href="https://github.com/dart-lang/ffigen/commit/daa06036c457277aa7ddbf734123bf76ec921e44">&quot;&gt;&lt;code&gt;8e1cba0&lt;/code&gt;&lt;/a&gt; feat: add measure option (&lt;a href=&quot;https://redirect.github.com/coverallsapp/github-action/issues/183&quot;&gt;#183&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/coverallsapp/github-action/commit/</a><a class="double-link" href="https://github.com/dart-lang/ffigen/commit/cb1c78cc8dd8522acce1a460c643e67515393ef6">cb1c78cc8</a><a href="https://github.com/dart-lang/ffigen/commit/daa06036c457277aa7ddbf734123bf76ec921e44">&quot;&gt;&lt;code&gt;cb1c78c&lt;/code&gt;&lt;/a&gt; docs: clarify coveralls repo permissions (&lt;a href=&quot;https://redirect.github.com/coverallsapp/github-action/issues/182&quot;&gt;#182&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/coverallsapp/github-action/commit/3b7440a0f"><code>3b7440a</code></a> Update README.md (<a href="https://redirect.github.com/coverallsapp/github-action/issues/181">#181</a>)</li>
<li>See full diff in <a href="https://github.com/coverallsapp/github-action/compare/c7885c00c...95b1a2355bd0e526ad2fd62da9fd386ad4c98474">compare view



[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=coverallsapp/github-action&package-manager=github_actions&previous-version=2.2.0&new-version=2.2.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabo... (continued)

3576 of 3873 relevant lines covered (92.33%)

28.42 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.17
/lib/src/config_provider/spec_utils.dart
1
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
2
// for details. All rights reserved. Use of this source code is governed by a
3
// BSD-style license that can be found in the LICENSE file.
4

5
import 'dart:io';
6

7
import 'package:ffigen/src/code_generator.dart';
8
import 'package:ffigen/src/code_generator/utils.dart';
9
import 'package:ffigen/src/header_parser/type_extractor/cxtypekindmap.dart';
10
import 'package:file/local.dart';
11
import 'package:glob/glob.dart';
12
import 'package:logging/logging.dart';
13
import 'package:package_config/package_config.dart';
14
import 'package:path/path.dart' as p;
15
import 'package:quiver/pattern.dart' as quiver;
16
import 'package:yaml/yaml.dart';
17

18
import '../strings.dart' as strings;
19
import 'config_types.dart';
20

21
final _logger = Logger('ffigen.config_provider.spec_utils');
105✔
22

23
/// Replaces the path separators according to current platform.
24
String _replaceSeparators(String path) {
50✔
25
  if (Platform.isWindows) {
50✔
26
    return path.replaceAll(p.posix.separator, p.windows.separator);
×
27
  } else {
28
    return path.replaceAll(p.windows.separator, p.posix.separator);
250✔
29
  }
30
}
31

32
/// Replaces the path separators according to current platform. If a relative
33
/// path is passed in, it is resolved relative to the config path, and the
34
/// absolute path is returned.
35
String _normalizePath(String path, String? configFilename) {
50✔
36
  final skipNormalization =
37
      (configFilename == null) || p.isAbsolute(path) || path.startsWith("**");
16✔
38
  return _replaceSeparators(
50✔
39
      skipNormalization ? path : p.join(p.dirname(configFilename), path));
16✔
40
}
41

42
Map<String, LibraryImport> libraryImportsExtractor(
1✔
43
    Map<String, String>? typeMap) {
44
  final resultMap = <String, LibraryImport>{};
1✔
45
  if (typeMap != null) {
46
    for (final typeName in typeMap.keys) {
2✔
47
      resultMap[typeName] =
1✔
48
          LibraryImport(typeName, typeMap[typeName] as String);
2✔
49
    }
50
  }
51
  return resultMap;
52
}
53

54
void loadImportedTypes(YamlMap fileConfig,
1✔
55
    Map<String, ImportedType> usrTypeMappings, LibraryImport libraryImport) {
56
  final symbols = fileConfig['symbols'] as YamlMap;
1✔
57
  for (final key in symbols.keys) {
2✔
58
    final usr = key as String;
59
    final value = symbols[usr]! as YamlMap;
1✔
60
    usrTypeMappings[usr] = ImportedType(
2✔
61
        libraryImport, value['name'] as String, value['name'] as String);
2✔
62
  }
63
}
64

65
YamlMap loadSymbolFile(String symbolFilePath, String? configFileName,
1✔
66
    PackageConfig? packageConfig) {
67
  final path = symbolFilePath.startsWith('package:')
1✔
68
      ? packageConfig!.resolve(Uri.parse(symbolFilePath))!.toFilePath()
3✔
69
      : _normalizePath(symbolFilePath, configFileName);
×
70

71
  return loadYaml(File(path).readAsStringSync()) as YamlMap;
3✔
72
}
73

74
Map<String, ImportedType> symbolFileImportExtractor(
1✔
75
    List<String> yamlConfig,
76
    Map<String, LibraryImport> libraryImports,
77
    String? configFileName,
78
    PackageConfig? packageConfig) {
79
  final resultMap = <String, ImportedType>{};
1✔
80
  for (final item in yamlConfig) {
2✔
81
    String symbolFilePath;
82
    symbolFilePath = item;
83
    final symbolFile =
84
        loadSymbolFile(symbolFilePath, configFileName, packageConfig);
1✔
85
    final formatVersion = symbolFile[strings.formatVersion] as String;
1✔
86
    if (formatVersion.split('.')[0] !=
3✔
87
        strings.symbolFileFormatVersion.split('.')[0]) {
2✔
88
      _logger.severe(
×
89
          'Incompatible format versions for file $symbolFilePath: ${strings.symbolFileFormatVersion}(ours), $formatVersion(theirs).');
×
90
      exit(1);
×
91
    }
92
    final uniqueNamer = UniqueNamer(libraryImports.keys
2✔
93
        .followedBy([strings.defaultSymbolFileImportPrefix]).toSet());
3✔
94
    for (final file in (symbolFile[strings.files] as YamlMap).keys) {
3✔
95
      final existingImports =
96
          libraryImports.values.where((element) => element.importPath == file);
2✔
97
      if (existingImports.isEmpty) {
1✔
98
        final name =
99
            uniqueNamer.makeUnique(strings.defaultSymbolFileImportPrefix);
1✔
100
        libraryImports[name] = LibraryImport(name, file as String);
2✔
101
      }
102
      final libraryImport = libraryImports.values.firstWhere(
2✔
103
        (element) => element.importPath == file,
3✔
104
      );
105
      loadImportedTypes(
1✔
106
          symbolFile[strings.files][file] as YamlMap, resultMap, libraryImport);
2✔
107
    }
108
  }
109
  return resultMap;
110
}
111

112
Map<String, List<String>> typeMapExtractor(Map<dynamic, dynamic>? yamlConfig) {
3✔
113
  // Key - type_name, Value - [lib, cType, dartType].
114
  final resultMap = <String, List<String>>{};
3✔
115
  final typeMap = yamlConfig;
116
  if (typeMap != null) {
117
    for (final typeName in typeMap.keys) {
6✔
118
      final typeConfigItem = typeMap[typeName] as Map;
3✔
119
      resultMap[typeName as String] = [
6✔
120
        typeConfigItem[strings.lib] as String,
3✔
121
        typeConfigItem[strings.cType] as String,
3✔
122
        typeConfigItem[strings.dartType] as String,
3✔
123
      ];
124
    }
125
  }
126
  return resultMap;
127
}
128

129
Map<String, ImportedType> makeImportTypeMapping(
50✔
130
    Map<String, List<String>> rawTypeMappings,
131
    Map<String, LibraryImport> libraryImportsMap) {
132
  final typeMappings = <String, ImportedType>{};
50✔
133
  for (final key in rawTypeMappings.keys) {
53✔
134
    final lib = rawTypeMappings[key]![0];
6✔
135
    final cType = rawTypeMappings[key]![1];
6✔
136
    final dartType = rawTypeMappings[key]![2];
6✔
137
    if (strings.predefinedLibraryImports.containsKey(lib)) {
6✔
138
      typeMappings[key] =
3✔
139
          ImportedType(strings.predefinedLibraryImports[lib]!, cType, dartType);
9✔
140
    } else if (libraryImportsMap.containsKey(lib)) {
1✔
141
      typeMappings[key] =
1✔
142
          ImportedType(libraryImportsMap[lib]!, cType, dartType);
2✔
143
    } else {
144
      throw Exception("Please declare $lib under library-imports.");
×
145
    }
146
  }
147
  return typeMappings;
148
}
149

150
Type makePointerToType(Type type, int pointerCount) {
1✔
151
  for (var i = 0; i < pointerCount; i++) {
2✔
152
    type = PointerType(type);
1✔
153
  }
154
  return type;
155
}
156

157
String makePostfixFromRawVarArgType(List<String> rawVarArgType) {
1✔
158
  return rawVarArgType
159
      .map((e) => e
2✔
160
          .replaceAll('*', 'Ptr')
1✔
161
          .replaceAll(RegExp(r'_t$'), '')
2✔
162
          .replaceAll(' ', '')
1✔
163
          .replaceAll(RegExp('[^A-Za-z0-9_]'), ''))
2✔
164
      .map((e) => e.length > 1 ? '${e[0].toUpperCase()}${e.substring(1)}' : e)
8✔
165
      .join('');
1✔
166
}
167

168
Type makeTypeFromRawVarArgType(
1✔
169
    String rawVarArgType, Map<String, LibraryImport> libraryImportsMap) {
170
  Type baseType;
171
  var rawBaseType = rawVarArgType.trim();
1✔
172
  // Split the raw type based on pointer usage. E.g -
173
  // int => [int]
174
  // char* => [char,*]
175
  // ffi.Hello ** => [ffi.Hello,**]
176
  final typeStringRegexp = RegExp(r'([a-zA-Z0-9_\s\.]+)(\**)$');
1✔
177
  if (!typeStringRegexp.hasMatch(rawBaseType)) {
1✔
178
    throw Exception('Cannot parse variadic argument type - $rawVarArgType.');
×
179
  }
180
  final regExpMatch = typeStringRegexp.firstMatch(rawBaseType)!;
1✔
181
  final groups = regExpMatch.groups([1, 2]);
2✔
182
  rawBaseType = groups[0]!;
1✔
183
  // Handle basic supported types.
184
  if (cxTypeKindToImportedTypes.containsKey(rawBaseType)) {
2✔
185
    baseType = cxTypeKindToImportedTypes[rawBaseType]!;
2✔
186
  } else if (supportedTypedefToImportedType.containsKey(rawBaseType)) {
2✔
187
    baseType = supportedTypedefToImportedType[rawBaseType]!;
×
188
  } else if (suportedTypedefToSuportedNativeType.containsKey(rawBaseType)) {
2✔
189
    baseType = NativeType(suportedTypedefToSuportedNativeType[rawBaseType]!);
×
190
  } else {
191
    // Use library import if specified (E.g - ffi.UintPtr or custom.MyStruct)
192
    final rawVarArgTypeSplit = rawBaseType.split('.');
1✔
193
    if (rawVarArgTypeSplit.length == 1) {
2✔
194
      final typeName = rawVarArgTypeSplit[0].replaceAll(' ', '');
2✔
195
      baseType = SelfImportedType(typeName, typeName);
1✔
196
    } else if (rawVarArgTypeSplit.length == 2) {
×
197
      final lib = rawVarArgTypeSplit[0];
×
198
      final libraryImport = strings.predefinedLibraryImports[lib] ??
×
199
          libraryImportsMap[rawVarArgTypeSplit[0]];
×
200
      if (libraryImport == null) {
201
        throw Exception('Please declare $lib in library-imports.');
×
202
      }
203
      final typeName = rawVarArgTypeSplit[1].replaceAll(' ', '');
×
204
      baseType = ImportedType(libraryImport, typeName, typeName);
×
205
    } else {
206
      throw Exception(
×
207
          'Invalid type $rawVarArgType : Expected 0 or 1 .(dot) separators.');
×
208
    }
209
  }
210

211
  // Handle pointers
212
  final pointerCount = groups[1]!.length;
2✔
213
  return makePointerToType(baseType, pointerCount);
1✔
214
}
215

216
Map<String, List<VarArgFunction>> makeVarArgFunctionsMapping(
50✔
217
    Map<String, List<RawVarArgFunction>> rawVarArgMappings,
218
    Map<String, LibraryImport> libraryImportsMap) {
219
  final mappings = <String, List<VarArgFunction>>{};
50✔
220
  for (final key in rawVarArgMappings.keys) {
51✔
221
    final varArgList = <VarArgFunction>[];
1✔
222
    for (final rawVarArg in rawVarArgMappings[key]!) {
3✔
223
      var postfix = rawVarArg.postfix ?? '';
1✔
224
      final types = <Type>[];
1✔
225
      for (final rva in rawVarArg.rawTypeStrings) {
2✔
226
        types.add(makeTypeFromRawVarArgType(rva, libraryImportsMap));
2✔
227
      }
228
      if (postfix.isEmpty) {
1✔
229
        if (rawVarArgMappings[key]!.length == 1) {
3✔
230
          postfix = '';
231
        } else {
232
          postfix = makePostfixFromRawVarArgType(rawVarArg.rawTypeStrings);
2✔
233
        }
234
      }
235
      // Extract postfix from config and/or deduce from var names.
236
      varArgList.add(VarArgFunction(postfix, types));
2✔
237
    }
238
    mappings[key] = varArgList;
1✔
239
  }
240
  return mappings;
241
}
242

243
final _quoteMatcher = RegExp(r'''^["'](.*)["']$''', dotAll: true);
18✔
244
final _cmdlineArgMatcher = RegExp(r'''['"](\\"|[^"])*?['"]|[^ ]+''');
18✔
245
List<String> compilerOptsToList(String compilerOpts) {
6✔
246
  final list = <String>[];
6✔
247
  _cmdlineArgMatcher.allMatches(compilerOpts).forEach((element) {
24✔
248
    var match = element.group(0);
6✔
249
    if (match != null) {
250
      if (quiver.matchesFull(_quoteMatcher, match)) {
12✔
251
        match = _quoteMatcher.allMatches(match).first.group(1)!;
4✔
252
      }
253
      list.add(match);
6✔
254
    }
255
  });
256

257
  return list;
258
}
259

260
List<String> compilerOptsExtractor(List<String> value) {
5✔
261
  final list = <String>[];
5✔
262
  for (final el in (value)) {
10✔
263
    list.addAll(compilerOptsToList(el));
10✔
264
  }
265
  return list;
266
}
267

268
Headers headersExtractor(
50✔
269
    Map<dynamic, List<String>> yamlConfig, String? configFilename) {
270
  final entryPoints = <String>[];
50✔
271
  final includeGlobs = <quiver.Glob>[];
50✔
272
  for (final key in yamlConfig.keys) {
100✔
273
    if (key == strings.entryPoints) {
50✔
274
      for (final h in (yamlConfig[key]!)) {
150✔
275
        final headerGlob = _normalizePath(h, configFilename);
50✔
276
        // Add file directly to header if it's not a Glob but a File.
277
        if (File(headerGlob).existsSync()) {
100✔
278
          final osSpecificPath = headerGlob;
279
          entryPoints.add(osSpecificPath);
35✔
280
          _logger.fine('Adding header/file: $headerGlob');
105✔
281
        } else {
282
          final glob = Glob(headerGlob);
15✔
283
          for (final file in glob.listFileSystemSync(const LocalFileSystem(),
15✔
284
              followLinks: true)) {
×
285
            final fixedPath = file.path;
×
286
            entryPoints.add(fixedPath);
×
287
            _logger.fine('Adding header/file: $fixedPath');
×
288
          }
289
        }
290
      }
291
    }
292
    if (key == strings.includeDirectives) {
50✔
293
      for (final h in yamlConfig[key]!) {
30✔
294
        final headerGlob = h;
295
        final fixedGlob = _normalizePath(headerGlob, configFilename);
10✔
296
        includeGlobs.add(quiver.Glob(fixedGlob));
20✔
297
      }
298
    }
299
  }
300
  return Headers(
50✔
301
    entryPoints: entryPoints,
302
    includeFilter: GlobHeaderFilter(
50✔
303
      includeGlobs: includeGlobs,
304
    ),
305
  );
306
}
307

308
/// Returns location of dynamic library by searching default locations. Logs
309
/// error and throws an Exception if not found.
310
String findDylibAtDefaultLocations() {
50✔
311
  String? k;
312
  if (Platform.isLinux) {
50✔
313
    for (final l in strings.linuxDylibLocations) {
×
314
      k = findLibclangDylib(l);
×
315
      if (k != null) return k;
316
    }
317
    Process.runSync('ldconfig', ['-p']);
×
318
    final ldConfigResult = Process.runSync('ldconfig', ['-p']);
×
319
    if (ldConfigResult.exitCode == 0) {
×
320
      final lines = (ldConfigResult.stdout as String).split('\n');
×
321
      final paths = [
×
322
        for (final line in lines)
×
323
          if (line.contains('libclang')) line.split(' => ')[1],
×
324
      ];
325
      for (final location in paths) {
×
326
        if (File(location).existsSync()) {
×
327
          return location;
328
        }
329
      }
330
    }
331
  } else if (Platform.isWindows) {
50✔
332
    final dylibLocations = strings.windowsDylibLocations.toList();
×
333
    final userHome = Platform.environment['USERPROFILE'];
×
334
    if (userHome != null) {
335
      dylibLocations
336
          .add(p.join(userHome, 'scoop', 'apps', 'llvm', 'current', 'bin'));
×
337
    }
338
    for (final l in dylibLocations) {
×
339
      k = findLibclangDylib(l);
×
340
      if (k != null) return k;
341
    }
342
  } else if (Platform.isMacOS) {
50✔
343
    for (final l in strings.macOsDylibLocations) {
100✔
344
      k = findLibclangDylib(l);
50✔
345
      if (k != null) return k;
346
    }
347
    final findLibraryResult =
348
        Process.runSync('xcodebuild', ['-find-library', 'libclang.dylib']);
×
349
    if (findLibraryResult.exitCode == 0) {
×
350
      final location = (findLibraryResult.stdout as String).split('\n').first;
×
351
      if (File(location).existsSync()) {
×
352
        return location;
353
      }
354
    }
355
    final xcodePathResult = Process.runSync('xcode-select', ['-print-path']);
×
356
    if (xcodePathResult.exitCode == 0) {
×
357
      final xcodePath = (xcodePathResult.stdout as String).split('\n').first;
×
358
      final location =
359
          p.join(xcodePath, strings.xcodeDylibLocation, strings.dylibFileName);
×
360
      if (File(location).existsSync()) {
×
361
        return location;
362
      }
363
    }
364
  } else {
365
    throw Exception('Unsupported Platform.');
×
366
  }
367

368
  _logger.severe("Couldn't find dynamic library in default locations.");
×
369
  _logger.severe(
×
370
      "Please supply one or more path/to/llvm in ffigen's config under the key '${strings.llvmPath}'.");
×
371
  throw Exception("Couldn't find dynamic library in default locations.");
×
372
}
373

374
String? findLibclangDylib(String parentFolder) {
50✔
375
  final location = p.join(parentFolder, strings.dylibFileName);
100✔
376
  if (File(location).existsSync()) {
100✔
377
    return location;
378
  } else {
379
    return null;
380
  }
381
}
382

383
String llvmPathExtractor(List<String> value) {
×
384
  // Extract libclang's dylib from user specified paths.
385
  for (final path in value) {
×
386
    final dylibPath =
387
        findLibclangDylib(p.join(path, strings.dynamicLibParentName));
×
388
    if (dylibPath != null) {
389
      _logger.fine('Found dynamic library at: $dylibPath');
×
390
      return dylibPath;
391
    }
392
    // Check if user has specified complete path to dylib.
393
    final completeDylibPath = path;
394
    if (p.extension(completeDylibPath).isNotEmpty &&
×
395
        File(completeDylibPath).existsSync()) {
×
396
      _logger.info(
×
397
          'Using complete dylib path: $completeDylibPath from llvm-path.');
×
398
      return completeDylibPath;
399
    }
400
  }
401
  _logger.fine(
×
402
      "Couldn't find dynamic library under paths specified by ${strings.llvmPath}.");
×
403
  // Extract path from default locations.
404
  try {
405
    final res = findDylibAtDefaultLocations();
×
406
    return res;
407
  } catch (e) {
408
    _logger.severe(
×
409
        "Couldn't find ${p.join(strings.dynamicLibParentName, strings.dylibFileName)} in specified locations.");
×
410
    exit(1);
×
411
  }
412
}
413

414
OutputConfig outputExtractor(
50✔
415
    dynamic value, String? configFilename, PackageConfig? packageConfig) {
416
  if (value is String) {
50✔
417
    return OutputConfig(_normalizePath(value, configFilename), null);
100✔
418
  }
419
  value = value as Map;
420
  return OutputConfig(
1✔
421
    _normalizePath((value)[strings.bindings] as String, configFilename),
2✔
422
    value.containsKey(strings.symbolFile)
1✔
423
        ? symbolFileOutputExtractor(
1✔
424
            value[strings.symbolFile], configFilename, packageConfig)
1✔
425
        : null,
426
  );
427
}
428

429
SymbolFile symbolFileOutputExtractor(
1✔
430
    dynamic value, String? configFilename, PackageConfig? packageConfig) {
431
  value = value as Map;
432
  var output = value[strings.output] as String;
1✔
433
  if (Uri.parse(output).scheme != "package") {
3✔
434
    _logger.warning(
×
435
        'Consider using a Package Uri for ${strings.symbolFile} -> ${strings.output}: $output so that external packages can use it.');
×
436
    output = _normalizePath(output, configFilename);
×
437
  } else {
438
    output = packageConfig!.resolve(Uri.parse(output))!.toFilePath();
3✔
439
  }
440
  final importPath = value[strings.importPath] as String;
1✔
441
  if (Uri.parse(importPath).scheme != "package") {
3✔
442
    _logger.warning(
×
443
        'Consider using a Package Uri for ${strings.symbolFile} -> ${strings.importPath}: $importPath so that external packages can use it.');
×
444
  }
445
  return SymbolFile(importPath, output);
1✔
446
}
447

448
/// Returns true if [str] is not a full name.
449
///
450
/// E.g `abc` is a full name, `abc.*` is not.
451
bool isFullDeclarationName(String str) =>
27✔
452
    quiver.matchesFull(RegExp('[a-zA-Z_0-9]*'), str);
54✔
453

454
Includer extractIncluderFromYaml(Map<dynamic, dynamic> yamlMap) {
50✔
455
  final includeMatchers = <RegExp>[],
50✔
456
      includeFull = <String>{},
457
      excludeMatchers = <RegExp>[],
50✔
458
      excludeFull = <String>{};
459

460
  final include = yamlMap[strings.include] as List<String>?;
50✔
461
  if (include != null) {
462
    if (include.isEmpty) {
22✔
463
      return Includer.excludeByDefault();
×
464
    }
465
    for (final str in include) {
44✔
466
      if (isFullDeclarationName(str)) {
22✔
467
        includeFull.add(str);
22✔
468
      } else {
469
        includeMatchers.add(RegExp(str, dotAll: true));
2✔
470
      }
471
    }
472
  }
473

474
  final exclude = yamlMap[strings.exclude] as List<String>?;
50✔
475
  if (exclude != null) {
476
    for (final str in exclude) {
56✔
477
      if (isFullDeclarationName(str)) {
6✔
478
        excludeFull.add(str);
6✔
479
      } else {
480
        excludeMatchers.add(RegExp(str, dotAll: true));
×
481
      }
482
    }
483
  }
484

485
  return Includer(
50✔
486
    includeMatchers: includeMatchers,
487
    includeFull: includeFull,
488
    excludeMatchers: excludeMatchers,
489
    excludeFull: excludeFull,
490
  );
491
}
492

493
Map<String, List<RawVarArgFunction>> varArgFunctionConfigExtractor(
1✔
494
    Map<dynamic, dynamic> yamlMap) {
495
  final result = <String, List<RawVarArgFunction>>{};
1✔
496
  final configMap = yamlMap;
497
  for (final key in configMap.keys) {
2✔
498
    final List<RawVarArgFunction> vafuncs = [];
1✔
499
    for (final rawVaFunc in (configMap[key] as List)) {
3✔
500
      if (rawVaFunc is List) {
1✔
501
        vafuncs.add(RawVarArgFunction(null, rawVaFunc.cast()));
3✔
502
      } else if (rawVaFunc is Map) {
1✔
503
        vafuncs.add(RawVarArgFunction(rawVaFunc[strings.postfix] as String?,
3✔
504
            (rawVaFunc[strings.types] as List).cast()));
2✔
505
      } else {
506
        throw Exception("Unexpected type in variadic-argument config.");
×
507
      }
508
    }
509
    result[key as String] = vafuncs;
1✔
510
  }
511

512
  return result;
513
}
514

515
Declaration declarationConfigExtractor(Map<dynamic, dynamic> yamlMap) {
50✔
516
  final renamePatterns = <RegExpRenamer>[];
50✔
517
  final renameFull = <String, String>{};
50✔
518
  final memberRenamePatterns = <RegExpMemberRenamer>[];
50✔
519
  final memberRenamerFull = <String, Renamer>{};
50✔
520

521
  final includer = extractIncluderFromYaml(yamlMap);
50✔
522

523
  final symbolIncluder = yamlMap[strings.symbolAddress] as Includer?;
50✔
524

525
  final rename = yamlMap[strings.rename] as Map<dynamic, String>?;
50✔
526

527
  if (rename != null) {
528
    for (final key in rename.keys) {
4✔
529
      final str = key.toString();
2✔
530
      if (isFullDeclarationName(str)) {
2✔
531
        renameFull[str] = rename[str]!;
2✔
532
      } else {
533
        renamePatterns
534
            .add(RegExpRenamer(RegExp(str, dotAll: true), rename[str]!));
8✔
535
      }
536
    }
537
  }
538

539
  final memberRename =
540
      yamlMap[strings.memberRename] as Map<dynamic, Map<dynamic, String>>?;
50✔
541

542
  if (memberRename != null) {
543
    for (final key in memberRename.keys) {
2✔
544
      final decl = key.toString();
1✔
545
      final renamePatterns = <RegExpRenamer>[];
1✔
546
      final renameFull = <String, String>{};
1✔
547

548
      final memberRenameMap = memberRename[decl]!;
1✔
549
      for (final member in memberRenameMap.keys) {
2✔
550
        final memberStr = member.toString();
1✔
551
        if (isFullDeclarationName(memberStr)) {
1✔
552
          renameFull[memberStr] = memberRenameMap[member]!;
2✔
553
        } else {
554
          renamePatterns.add(RegExpRenamer(
2✔
555
              RegExp(memberStr, dotAll: true), memberRenameMap[member]!));
2✔
556
        }
557
      }
558
      if (isFullDeclarationName(decl)) {
1✔
559
        memberRenamerFull[decl] = Renamer(
2✔
560
          renameFull: renameFull,
561
          renamePatterns: renamePatterns,
562
        );
563
      } else {
564
        memberRenamePatterns.add(
1✔
565
          RegExpMemberRenamer(
1✔
566
            RegExp(decl, dotAll: true),
1✔
567
            Renamer(
1✔
568
              renameFull: renameFull,
569
              renamePatterns: renamePatterns,
570
            ),
571
          ),
572
        );
573
      }
574
    }
575
  }
576

577
  return Declaration(
50✔
578
    includer: includer,
579
    renamer: Renamer(
50✔
580
      renameFull: renameFull,
581
      renamePatterns: renamePatterns,
582
    ),
583
    memberRenamer: MemberRenamer(
50✔
584
      memberRenameFull: memberRenamerFull,
585
      memberRenamePattern: memberRenamePatterns,
586
    ),
587
    symbolAddressIncluder: symbolIncluder,
588
  );
589
}
590

591
StructPackingOverride structPackingOverrideExtractor(
1✔
592
    Map<dynamic, dynamic> value) {
593
  final matcherMap = <RegExp, int?>{};
1✔
594
  for (final key in value.keys) {
2✔
595
    matcherMap[RegExp(key as String, dotAll: true)] =
2✔
596
        strings.packingValuesMap[value[key]];
2✔
597
  }
598
  return StructPackingOverride(matcherMap: matcherMap);
1✔
599
}
600

601
FfiNativeConfig ffiNativeExtractor(dynamic yamlConfig) {
1✔
602
  final yamlMap = yamlConfig as Map?;
603
  return FfiNativeConfig(
1✔
604
    enabled: true,
605
    asset: yamlMap?[strings.ffiNativeAsset] as String?,
×
606
  );
607
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc