Skip to content

Commit

Permalink
Placeholder package config reader.
Browse files Browse the repository at this point in the history
  • Loading branch information
davidmorgan committed Aug 7, 2024
1 parent 5b70e02 commit 781a3e4
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 0 deletions.
79 changes: 79 additions & 0 deletions pkgs/_macro_host/lib/src/package_config.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright (c) 2024, 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 'dart:io';

import 'package:dart_model/dart_model.dart';
import 'package:package_config/package_config.dart' as package_config;

/// Reads a package config to determine information about macros.
class PackageConfig {
final Uri uri;

PackageConfig({required this.uri});

/// Checks whether [name] is a macro annotation.
///
/// If so, returns the qualified name of the macro implementation.
///
/// If not, returns `null`.
///
/// This is a placeholder implementation until `language/3728` is
/// implemented. It expects macros to be marked by a comment in the
/// annotation package `pubspec.yaml` that looks like this:
///
/// ```
/// # macro <annotation name> <implementation name>
/// ```
///
/// For example:
///
/// ```
/// # macro declare_x_macro.dart#DeclareX package:_test_macros/declare_x_macro.dart#DeclareXImplementation
/// ```
QualifiedName? lookupMacroImplementation(QualifiedName name) {
var packageName = name.uri;
if (packageName.startsWith('package:') && packageName.contains('/')) {
packageName = packageName.substring('package:'.length);
packageName = packageName.substring(0, packageName.indexOf('/'));
} else {
throw ArgumentError('Name must start "package:" and have a path: $name');
}
final packageConfig = package_config.PackageConfig.parseBytes(
File.fromUri(uri).readAsBytesSync(), uri);
final libraryQualifiedName =
name.string.substring(name.uri.indexOf('/') + 1);

final matchingPackage = packageConfig.packages
.where((p) => p.name == packageName)
.toList()
.singleOrNull;

if (matchingPackage == null) {
throw StateError(
'Package "$packageName" not found in package config at "$uri".');
}

// TODO(language/3728): read macro annotation identifiers from package
// config. Until then, check the pubsec, to simulate what that feature will
// do.
final packageUri = matchingPackage.root;
final pubspecUri = packageUri.replace(
pathSegments:
packageUri.pathSegments.followedBy(['pubspec.yaml']).toList());
final lines = File.fromUri(pubspecUri).readAsLinesSync();

final implsByLibraryQualifiedName = <String, String>{};
for (final line in lines) {
if (!line.startsWith('# macro ')) continue;
final items = line.split(' ');
// The rest of the line should be the library qualified name of the
// annotation then the fully qualified name of the implementation.
implsByLibraryQualifiedName[items[2]] = items[3];
}

final result = implsByLibraryQualifiedName[libraryQualifiedName];
return result == null ? null : QualifiedName(result);
}
}
1 change: 1 addition & 0 deletions pkgs/_macro_host/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dependencies:
_macro_server: any
dart_model: any
macro_service: any
package_config: ^2.1.0

dev_dependencies:
_test_macros: any
Expand Down
24 changes: 24 additions & 0 deletions pkgs/_macro_host/test/package_config_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) 2024, 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 'dart:isolate';

import 'package:_macro_host/src/package_config.dart';
import 'package:dart_model/dart_model.dart';
import 'package:test/test.dart';

void main() {
group(PackageConfig, () {
test('can look up macro implementations', () async {
final packageConfig = PackageConfig(uri: Isolate.packageConfigSync!);

expect(
packageConfig
.lookupMacroImplementation(QualifiedName(
'package:_test_macros/declare_x_macro.dart#DeclareX'))!
.string,
'package:_test_macros/declare_x_macro.dart#DeclareXImplementation');
});
});
}
4 changes: 4 additions & 0 deletions pkgs/_test_macros/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@ dependencies:
dev_dependencies:
dart_flutter_team_lints: ^3.0.0
test: ^1.25.0

# TODO(language/3728): use the real feature when there is one.
# macro declare_x_macro.dart#DeclareX package:_test_macros/declare_x_macro.dart#DeclareXImplementation
# macro query_class.dart#QueryClass package:_test_macros/query_class.dart#QueryClassImplementation

0 comments on commit 781a3e4

Please sign in to comment.