Skip to content
Open
Show file tree
Hide file tree
Changes from 5 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
2 changes: 2 additions & 0 deletions pkgs/hooks/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
- Add `ProtocolExtension.setupLogger`, which the hooks runner calls to provide
the logger used for validation diagnostics before any other method is invoked
on the extension.
- Add `HookInputUserDefines.baseUri`, which can be used to resolve paths
from nested user-defined options.

## 2.1.0

Expand Down
66 changes: 52 additions & 14 deletions pkgs/hooks/lib/src/config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -225,17 +225,21 @@ final class HookInputUserDefines {
/// Then:
/// - `input.userDefines['enable_experimental_features']` returns `true`.
/// - `input.userDefines['optimization_level']` returns `"O3"`.
Object? operator [](String key) {
final syntaxNode = _input._syntax.userDefines;
if (syntaxNode == null) {
return null;
}
final packageUserDefines = PackageUserDefinesSyntaxExtension.fromSyntax(
syntaxNode,
);
final pubspecSource = packageUserDefines.workspacePubspec;
return pubspecSource?.defines[key];
}
Object? operator [](String key) => _findDefine([key])?.$1;

/// An absolute [Uri] that can be used to interpret user-defines as paths.
///
/// This uses the [keyPathDefine] to traverse available options, starting at
/// the root. If the key path contains a string, this enters a YAML map. For
/// an integer element, this enters a YAML sequence. Any other key path
/// element is invalid and throws.
/// If no element exists for any position in the key path, null is returned.
///
/// This is a generalized variant of [path] returning the base URI for all
/// options under [keyPathDefine]. To resolve a top-level string option as a
/// path, use [path] directly.
Uri? baseUri(List<Object /* String|int */> keyPathDefine) =>
_findDefine(keyPathDefine)?.$2.basePath;

/// Resolves the relative path provided in the user-define for [key] to an
/// absolute [Uri] pointing to the file or directory on the host filesystem.
Expand Down Expand Up @@ -269,10 +273,21 @@ final class HookInputUserDefines {
/// }
/// ```
Uri? path(String key) {
Comment thread
simolus3 marked this conversation as resolved.
if (_findDefine([key]) case (final String value, final source)?) {
return source.basePath.resolve(value);
}

return null;
}

(Object, PackageUserDefinesSource)? _findDefine(
Iterable<Object?> keyPathDefine,
) {
final syntaxNode = _input._syntax.userDefines;
if (syntaxNode == null) {
return null;
}

final packageUserDefines = PackageUserDefinesSyntaxExtension.fromSyntax(
syntaxNode,
);
Expand All @@ -284,9 +299,32 @@ final class HookInputUserDefines {
// TODO(https://github.com/dart-lang/native/issues/2215): Add commandline
// arguments.
for (final source in sources) {
final relativepath = source.defines[key];
if (relativepath is String) {
return source.basePath.resolve(relativepath);
Object? options = source.defines;

for (final (i, key) in keyPathDefine.indexed) {
if (key is String) {
if (options is Map) {
options = options[key];
} else {
return null;
}
} else if (key is int) {
if (options is List) {
options = options[key];
} else {
return null;
}
} else {
throw ArgumentError.value(
keyPathDefine,
'keyPathDefine',
'Must contain only strings or ints (found `$key` at index $i).',
);
}
}

if (options != null) {
return (options, source);
}
}
return null;
Expand Down
8 changes: 8 additions & 0 deletions pkgs/hooks_runner/test/test_data/user_defines_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ void main() async {
// The native assets build runner must be reinvoked if the pubspec
// changes, as the pubspec could contain user-defines.
expect(result.dependencies, contains(pubspecUri));
expect(
result.dependencies,
contains(packageUri.resolve('assets/data.json')),
);
expect(
result.dependencies,
contains(packageUri.resolve('assets/second.json')),
);
}),
);
}
1 change: 1 addition & 0 deletions pkgs/hooks_runner/test_data/manifest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@
- use_all_api/hook/link.dart
- use_all_api/pubspec.yaml
- user_defines/assets/data.json
- user_defines/assets/second.json
- user_defines/bin/user_defines.dart
- user_defines/hook/build.dart
- user_defines/pubspec.yaml
Expand Down
3 changes: 3 additions & 0 deletions pkgs/hooks_runner/test_data/user_defines/assets/second.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"foo": "bar"
}
19 changes: 19 additions & 0 deletions pkgs/hooks_runner/test_data/user_defines/hook/build.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,24 @@ void main(List<String> arguments) async {
}
final file = File.fromUri(someFile);
output.dependencies.add(file.uri);

final base = input.userDefines.baseUri([
'nested',
'options',
'paths',
0,
]);
if (base == null) {
throw Exception(
'User-define nested.options.paths.0 does not have the right value: '
'${input.userDefines['nested']}.',
);
}

final pathOption =

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Lol, now accessing baseUri is easier than the user-defines themselves 😄

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I can add a helper that traverses through options and returns the original define, but I suspect most hooks with complex options would use helper packages like json_serializable for this anyway.

(((input.userDefines['nested'] as Map)['options'] as Map)['paths']
as List)[0]
as String;
output.dependencies.add(base.resolve(pathOption));
});
}
4 changes: 4 additions & 0 deletions pkgs/hooks_runner/test_data/user_defines/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,9 @@ hooks:
user_define_key2:
foo: bar
some_file: assets/data.json
nested:
options:
paths:
- assets/second.json
some_other_package: # package name
user_define_key3: user_define_value3
Loading