Skip to content

[ffigen] Ignore deprecated APIs #1403

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions pkgs/ffigen/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
- Create a public facing API for ffigen that can be invoked as a library:
`void generate(Config config)`. Make `Config` an implementatble interface,
rather than needing to be parsed from yaml.
- Add a `external-versions` config option. Setting the minimum target
version will omit APIs from the generated bindings if they were deprecated
before this version.

## 13.0.0

Expand Down
36 changes: 35 additions & 1 deletion pkgs/ffigen/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,41 @@ import:
- 'package:some_pkg/symbols.yaml'
- 'path/to/some/symbol_file.yaml'
```
</td>
</td>
</tr>

<tr>
<td>
external-versions
</td>
<td>
Interfaces, methods, and other API elements may be marked with
deprecation annotations that indicate which platform version they were
deprecated in. If external-versions is set, APIs that were
deprecated as of the minimum version will be omitted from the
generated bindings.
<br><br>
The minimum version is specified per platform, and an API will be
generated if it is available on *any* of the targeted platform versions.
If a version is not specified for a particular platform, the API's
inclusion will be based purely on the platforms that have a specified
minimum version.
<br><br>
Current support OS keys are ios and macos. If you have a use case for
version checking on other OSs, please file an issue.
</td>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe explicitly mention which keys are supported: ios and macos.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

<td>

```yaml
external-versions:
# See https://docs.flutter.dev/reference/supported-platforms.
ios:
min: 12.0.0
macos:
min: 10.14.0
```

</td>
</tr>
</tbody>
</table>
Expand Down
24 changes: 24 additions & 0 deletions pkgs/ffigen/ffigen.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,30 @@
},
"silence-enum-warning": {
"type": "boolean"
},
"external-versions": {
"type": "object",
"additionalProperties": false,
"properties": {
"ios": {
"type": "object",
"additionalProperties": false,
"properties": {
"min": {
"type": "string"
}
}
},
"macos": {
"type": "object",
"additionalProperties": false,
"properties": {
"min": {
"type": "string"
}
}
}
}
}
},
"required": [
Expand Down
14 changes: 12 additions & 2 deletions pkgs/ffigen/lib/src/config_provider/config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ abstract interface class Config {
/// Whether to format the output file.
bool get formatOutput;

/// Minimum target versions for ObjC APIs, per OS. APIs that were deprecated
/// before this version will not be generated.
ExternalVersions get externalVersions;

factory Config({
Uri? filename,
PackageConfig? packageConfig,
Expand All @@ -177,7 +181,7 @@ abstract interface class Config {
Language language = Language.c,
required List<Uri> entryPoints,
bool Function(Uri header)? shouldIncludeHeaderFunc,
List<String> compilerOpts = const <String>[],
List<String>? compilerOpts,
Map<String, List<VarArgFunction>> varArgFunctions =
const <String, List<VarArgFunction>>{},
DeclarationFilters? functionDecl,
Expand Down Expand Up @@ -218,6 +222,7 @@ abstract interface class Config {
FfiNativeConfig ffiNativeConfig = const FfiNativeConfig(enabled: false),
bool ignoreSourceErrors = false,
bool formatOutput = true,
ExternalVersions externalVersions = const ExternalVersions(),
}) =>
ConfigImpl(
filename: filename == null ? null : Uri.file(filename.toFilePath()),
Expand All @@ -231,7 +236,7 @@ abstract interface class Config {
language: language,
entryPoints: entryPoints,
shouldIncludeHeaderFunc: shouldIncludeHeaderFunc ?? (_) => true,
compilerOpts: compilerOpts,
compilerOpts: compilerOpts ?? defaultCompilerOpts(),
varArgFunctions: varArgFunctions,
functionDecl: functionDecl ?? DeclarationFilters.excludeAll,
structDecl: structDecl ?? DeclarationFilters.excludeAll,
Expand Down Expand Up @@ -286,6 +291,7 @@ abstract interface class Config {
ffiNativeConfig: ffiNativeConfig,
ignoreSourceErrors: ignoreSourceErrors,
formatOutput: formatOutput,
externalVersions: externalVersions,
);
}

Expand Down Expand Up @@ -318,4 +324,8 @@ abstract interface class DeclarationFilters {

static final excludeAll = DeclarationFilters();
static final includeAll = DeclarationFilters(shouldInclude: (_) => true);

static DeclarationFilters include(Set<String> names) => DeclarationFilters(
shouldInclude: (Declaration decl) => names.contains(decl.originalName),
);
}
4 changes: 4 additions & 0 deletions pkgs/ffigen/lib/src/config_provider/config_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ class ConfigImpl implements Config {
@override
final bool formatOutput;

@override
final ExternalVersions externalVersions;

ConfigImpl({
required this.filename,
required this.packageConfig,
Expand Down Expand Up @@ -222,6 +225,7 @@ class ConfigImpl implements Config {
required this.ffiNativeConfig,
required this.ignoreSourceErrors,
required this.formatOutput,
required this.externalVersions,
});
}

Expand Down
17 changes: 17 additions & 0 deletions pkgs/ffigen/lib/src/config_provider/config_types.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ library;

import 'dart:io';

import 'package:pub_semver/pub_semver.dart';
import 'package:quiver/pattern.dart' as quiver;

import '../code_generator.dart';
Expand Down Expand Up @@ -432,3 +433,19 @@ class Declaration {
required this.originalName,
});
}

class ExternalVersions {
final Versions? ios;
final Versions? macos;
const ExternalVersions({this.ios, this.macos});
}

class Versions {
final Version? min;

// TODO(https://github.com/dart-lang/native/issues/300): max isn't supported
// yet.
final Version? max;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leave TODO that max isn't supported yet.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


const Versions({this.min, this.max});
}
21 changes: 21 additions & 0 deletions pkgs/ffigen/lib/src/config_provider/spec_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:glob/glob.dart';
import 'package:logging/logging.dart';
import 'package:package_config/package_config.dart';
import 'package:path/path.dart' as p;
import 'package:pub_semver/pub_semver.dart';
import 'package:quiver/pattern.dart' as quiver;
import 'package:yaml/yaml.dart';

Expand Down Expand Up @@ -631,3 +632,23 @@ FfiNativeConfig ffiNativeExtractor(dynamic yamlConfig) {
assetId: yamlMap?[strings.ffiNativeAsset] as String?,
);
}

ExternalVersions externalVersionsExtractor(Map<dynamic, dynamic>? yamlConfig) =>
ExternalVersions(
ios: versionsExtractor(yamlConfig?[strings.ios]),
macos: versionsExtractor(yamlConfig?[strings.macos]),
);

Versions? versionsExtractor(dynamic yamlConfig) {
final yamlMap = yamlConfig as Map?;
if (yamlMap == null) return null;
return Versions(
min: versionExtractor(yamlMap[strings.externalVersionsMin]),
);
}

Version? versionExtractor(dynamic yamlVersion) {
final versionString = yamlVersion as String?;
if (versionString == null) return null;
return Version.parse(versionString);
}
28 changes: 28 additions & 0 deletions pkgs/ffigen/lib/src/config_provider/yaml_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,12 @@ class YamlConfig implements Config {
@override
bool formatOutput = true;

/// Minimum target versions for ObjC APIs, per OS. APIs that were deprecated
/// before this version will not be generated.
@override
ExternalVersions get externalVersions => _externalVersions;
late ExternalVersions _externalVersions;

YamlConfig._({required this.filename, required this.packageConfig});

/// Create config from Yaml map.
Expand Down Expand Up @@ -828,6 +834,28 @@ class YamlConfig implements Config {
defaultValue: (node) => false,
resultOrDefault: (node) => _silenceEnumWarning = node.value as bool,
),
HeterogeneousMapEntry(
key: strings.externalVersions,
valueConfigSpec: HeterogeneousMapConfigSpec(
entries: strings.externalVersionsPlatforms
.map((plat) => HeterogeneousMapEntry(
key: plat,
valueConfigSpec: HeterogeneousMapConfigSpec(
entries: [
HeterogeneousMapEntry(
key: strings.externalVersionsMin,
valueConfigSpec: StringConfigSpec(),
),
],
),
))
.toList(),
transform: (node) => externalVersionsExtractor(node.value),
),
defaultValue: (node) => const ExternalVersions(),
resultOrDefault: (node) =>
_externalVersions = (node.value) as ExternalVersions,
),
],
);
}
Expand Down
Loading