Skip to content

Commit d788ec1

Browse files
liamappelbeHosseinYousefi
authored andcommitted
[ffigen] Ignore deprecated APIs (#1403)
1 parent 274a66a commit d788ec1

28 files changed

+3287
-3013
lines changed

pkgs/ffigen/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
- Create a public facing API for ffigen that can be invoked as a library:
44
`void generate(Config config)`. Make `Config` an implementatble interface,
55
rather than needing to be parsed from yaml.
6+
- Add a `external-versions` config option. Setting the minimum target
7+
version will omit APIs from the generated bindings if they were deprecated
8+
before this version.
69

710
## 13.0.0
811

pkgs/ffigen/README.md

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,41 @@ import:
662662
- 'package:some_pkg/symbols.yaml'
663663
- 'path/to/some/symbol_file.yaml'
664664
```
665-
</td>
665+
</td>
666+
</tr>
667+
668+
<tr>
669+
<td>
670+
external-versions
671+
</td>
672+
<td>
673+
Interfaces, methods, and other API elements may be marked with
674+
deprecation annotations that indicate which platform version they were
675+
deprecated in. If external-versions is set, APIs that were
676+
deprecated as of the minimum version will be omitted from the
677+
generated bindings.
678+
<br><br>
679+
The minimum version is specified per platform, and an API will be
680+
generated if it is available on *any* of the targeted platform versions.
681+
If a version is not specified for a particular platform, the API's
682+
inclusion will be based purely on the platforms that have a specified
683+
minimum version.
684+
<br><br>
685+
Current support OS keys are ios and macos. If you have a use case for
686+
version checking on other OSs, please file an issue.
687+
</td>
688+
<td>
689+
690+
```yaml
691+
external-versions:
692+
# See https://docs.flutter.dev/reference/supported-platforms.
693+
ios:
694+
min: 12.0.0
695+
macos:
696+
min: 10.14.0
697+
```
698+
699+
</td>
666700
</tr>
667701
</tbody>
668702
</table>

pkgs/ffigen/ffigen.schema.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,30 @@
469469
},
470470
"silence-enum-warning": {
471471
"type": "boolean"
472+
},
473+
"external-versions": {
474+
"type": "object",
475+
"additionalProperties": false,
476+
"properties": {
477+
"ios": {
478+
"type": "object",
479+
"additionalProperties": false,
480+
"properties": {
481+
"min": {
482+
"type": "string"
483+
}
484+
}
485+
},
486+
"macos": {
487+
"type": "object",
488+
"additionalProperties": false,
489+
"properties": {
490+
"min": {
491+
"type": "string"
492+
}
493+
}
494+
}
495+
}
472496
}
473497
},
474498
"required": [

pkgs/ffigen/lib/src/config_provider/config.dart

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@ abstract interface class Config {
167167
/// Whether to format the output file.
168168
bool get formatOutput;
169169

170+
/// Minimum target versions for ObjC APIs, per OS. APIs that were deprecated
171+
/// before this version will not be generated.
172+
ExternalVersions get externalVersions;
173+
170174
factory Config({
171175
Uri? filename,
172176
PackageConfig? packageConfig,
@@ -177,7 +181,7 @@ abstract interface class Config {
177181
Language language = Language.c,
178182
required List<Uri> entryPoints,
179183
bool Function(Uri header)? shouldIncludeHeaderFunc,
180-
List<String> compilerOpts = const <String>[],
184+
List<String>? compilerOpts,
181185
Map<String, List<VarArgFunction>> varArgFunctions =
182186
const <String, List<VarArgFunction>>{},
183187
DeclarationFilters? functionDecl,
@@ -218,6 +222,7 @@ abstract interface class Config {
218222
FfiNativeConfig ffiNativeConfig = const FfiNativeConfig(enabled: false),
219223
bool ignoreSourceErrors = false,
220224
bool formatOutput = true,
225+
ExternalVersions externalVersions = const ExternalVersions(),
221226
}) =>
222227
ConfigImpl(
223228
filename: filename == null ? null : Uri.file(filename.toFilePath()),
@@ -231,7 +236,7 @@ abstract interface class Config {
231236
language: language,
232237
entryPoints: entryPoints,
233238
shouldIncludeHeaderFunc: shouldIncludeHeaderFunc ?? (_) => true,
234-
compilerOpts: compilerOpts,
239+
compilerOpts: compilerOpts ?? defaultCompilerOpts(),
235240
varArgFunctions: varArgFunctions,
236241
functionDecl: functionDecl ?? DeclarationFilters.excludeAll,
237242
structDecl: structDecl ?? DeclarationFilters.excludeAll,
@@ -286,6 +291,7 @@ abstract interface class Config {
286291
ffiNativeConfig: ffiNativeConfig,
287292
ignoreSourceErrors: ignoreSourceErrors,
288293
formatOutput: formatOutput,
294+
externalVersions: externalVersions,
289295
);
290296
}
291297

@@ -318,4 +324,8 @@ abstract interface class DeclarationFilters {
318324

319325
static final excludeAll = DeclarationFilters();
320326
static final includeAll = DeclarationFilters(shouldInclude: (_) => true);
327+
328+
static DeclarationFilters include(Set<String> names) => DeclarationFilters(
329+
shouldInclude: (Declaration decl) => names.contains(decl.originalName),
330+
);
321331
}

pkgs/ffigen/lib/src/config_provider/config_impl.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,9 @@ class ConfigImpl implements Config {
172172
@override
173173
final bool formatOutput;
174174

175+
@override
176+
final ExternalVersions externalVersions;
177+
175178
ConfigImpl({
176179
required this.filename,
177180
required this.packageConfig,
@@ -222,6 +225,7 @@ class ConfigImpl implements Config {
222225
required this.ffiNativeConfig,
223226
required this.ignoreSourceErrors,
224227
required this.formatOutput,
228+
required this.externalVersions,
225229
});
226230
}
227231

pkgs/ffigen/lib/src/config_provider/config_types.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ library;
77

88
import 'dart:io';
99

10+
import 'package:pub_semver/pub_semver.dart';
1011
import 'package:quiver/pattern.dart' as quiver;
1112

1213
import '../code_generator.dart';
@@ -432,3 +433,19 @@ class Declaration {
432433
required this.originalName,
433434
});
434435
}
436+
437+
class ExternalVersions {
438+
final Versions? ios;
439+
final Versions? macos;
440+
const ExternalVersions({this.ios, this.macos});
441+
}
442+
443+
class Versions {
444+
final Version? min;
445+
446+
// TODO(https://github.com/dart-lang/native/issues/300): max isn't supported
447+
// yet.
448+
final Version? max;
449+
450+
const Versions({this.min, this.max});
451+
}

pkgs/ffigen/lib/src/config_provider/spec_utils.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import 'package:glob/glob.dart';
99
import 'package:logging/logging.dart';
1010
import 'package:package_config/package_config.dart';
1111
import 'package:path/path.dart' as p;
12+
import 'package:pub_semver/pub_semver.dart';
1213
import 'package:quiver/pattern.dart' as quiver;
1314
import 'package:yaml/yaml.dart';
1415

@@ -631,3 +632,23 @@ FfiNativeConfig ffiNativeExtractor(dynamic yamlConfig) {
631632
assetId: yamlMap?[strings.ffiNativeAsset] as String?,
632633
);
633634
}
635+
636+
ExternalVersions externalVersionsExtractor(Map<dynamic, dynamic>? yamlConfig) =>
637+
ExternalVersions(
638+
ios: versionsExtractor(yamlConfig?[strings.ios]),
639+
macos: versionsExtractor(yamlConfig?[strings.macos]),
640+
);
641+
642+
Versions? versionsExtractor(dynamic yamlConfig) {
643+
final yamlMap = yamlConfig as Map?;
644+
if (yamlMap == null) return null;
645+
return Versions(
646+
min: versionExtractor(yamlMap[strings.externalVersionsMin]),
647+
);
648+
}
649+
650+
Version? versionExtractor(dynamic yamlVersion) {
651+
final versionString = yamlVersion as String?;
652+
if (versionString == null) return null;
653+
return Version.parse(versionString);
654+
}

pkgs/ffigen/lib/src/config_provider/yaml_config.dart

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,12 @@ class YamlConfig implements Config {
284284
@override
285285
bool formatOutput = true;
286286

287+
/// Minimum target versions for ObjC APIs, per OS. APIs that were deprecated
288+
/// before this version will not be generated.
289+
@override
290+
ExternalVersions get externalVersions => _externalVersions;
291+
late ExternalVersions _externalVersions;
292+
287293
YamlConfig._({required this.filename, required this.packageConfig});
288294

289295
/// Create config from Yaml map.
@@ -828,6 +834,28 @@ class YamlConfig implements Config {
828834
defaultValue: (node) => false,
829835
resultOrDefault: (node) => _silenceEnumWarning = node.value as bool,
830836
),
837+
HeterogeneousMapEntry(
838+
key: strings.externalVersions,
839+
valueConfigSpec: HeterogeneousMapConfigSpec(
840+
entries: strings.externalVersionsPlatforms
841+
.map((plat) => HeterogeneousMapEntry(
842+
key: plat,
843+
valueConfigSpec: HeterogeneousMapConfigSpec(
844+
entries: [
845+
HeterogeneousMapEntry(
846+
key: strings.externalVersionsMin,
847+
valueConfigSpec: StringConfigSpec(),
848+
),
849+
],
850+
),
851+
))
852+
.toList(),
853+
transform: (node) => externalVersionsExtractor(node.value),
854+
),
855+
defaultValue: (node) => const ExternalVersions(),
856+
resultOrDefault: (node) =>
857+
_externalVersions = (node.value) as ExternalVersions,
858+
),
831859
],
832860
);
833861
}

0 commit comments

Comments
 (0)