-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use package:_macro_host in _analyzer_macros.
- Loading branch information
1 parent
5b70e02
commit 175c819
Showing
6 changed files
with
215 additions
and
115 deletions.
There are no files selected for viewing
163 changes: 163 additions & 0 deletions
163
pkgs/_analyzer_macros/lib/analyzer_macro_implementation.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
// 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 'package:_macro_host/macro_host.dart'; | ||
// ignore: implementation_imports | ||
import 'package:analyzer/src/summary2/macro_injected_impl.dart' as injected; | ||
import 'package:dart_model/dart_model.dart'; | ||
import 'package:macro_service/macro_service.dart'; | ||
import 'package:macros/macros.dart'; | ||
// ignore: implementation_imports | ||
import 'package:macros/src/executor.dart' as injected; | ||
|
||
/// Injected macro implementation for the analyzer. | ||
class MacroImplementation implements injected.MacroImplementation, HostService { | ||
final Uri packageConfig; | ||
final Map<String, String> macroImplByName; | ||
late final MacroHost _host; | ||
|
||
MacroImplementation._(this.packageConfig, this.macroImplByName); | ||
|
||
/// Starts the macro host. | ||
/// | ||
/// [packageConfig] is the package config of the workspace of the code being | ||
/// edited. | ||
/// | ||
/// [macroImplByName] identifies macros, it's a placeholder until we identify | ||
/// macros using package config. Keys are macro annotation qualified names | ||
/// (`uri#name`) and values are macro implementation qualified names. | ||
static Future<MacroImplementation> start({ | ||
required Uri packageConfig, | ||
required Map<String, String> macroImplByName, | ||
}) async { | ||
final result = MacroImplementation._(packageConfig, macroImplByName); | ||
result._host = await MacroHost.serve( | ||
macroImplByName: macroImplByName, service: result); | ||
return result; | ||
} | ||
|
||
@override | ||
injected.MacroPackageConfigs get packageConfigs => MacroPackageConfigs(this); | ||
|
||
@override | ||
injected.MacroRunner get runner => MacroRunner(this); | ||
|
||
@override | ||
Future<Response?> handle(MacroRequest request) async { | ||
if (request.type != MacroRequestType.queryRequest) return null; | ||
return Response.queryResponse(QueryResponse()); | ||
} | ||
} | ||
|
||
class MacroPackageConfigs implements injected.MacroPackageConfigs { | ||
final MacroImplementation impl; | ||
|
||
MacroPackageConfigs(this.impl); | ||
|
||
@override | ||
bool isMacro(Uri uri, String name) => | ||
impl._host.isMacro(impl.packageConfig, QualifiedName('$uri#$name')); | ||
} | ||
|
||
class MacroRunner implements injected.MacroRunner { | ||
final MacroImplementation impl; | ||
|
||
MacroRunner(this.impl); | ||
|
||
@override | ||
injected.RunningMacro run(Uri uri, String name) => RunningMacro.run( | ||
impl, | ||
QualifiedName('$uri#$name'), | ||
// Look up from the macro name to its implementation. | ||
QualifiedName(impl.macroImplByName['$uri#$name']!)); | ||
} | ||
|
||
class RunningMacro implements injected.RunningMacro { | ||
final MacroImplementation impl; | ||
final QualifiedName name; | ||
final QualifiedName implementation; | ||
late final Future _started; | ||
|
||
RunningMacro._(this.impl, this.name, this.implementation); | ||
|
||
static RunningMacro run(MacroImplementation impl, QualifiedName name, | ||
QualifiedName implementation) { | ||
final result = RunningMacro._(impl, name, implementation); | ||
// TODO(davidmorgan): this is currently what starts the macro running, | ||
// make it explicit. | ||
result._started = | ||
impl._host.queryMacroPhases(impl.packageConfig, implementation); | ||
return result; | ||
} | ||
|
||
@override | ||
Future<MacroExecutionResult> executeDeclarationsPhase(MacroTarget target, | ||
DeclarationPhaseIntrospector declarationsPhaseIntrospector) async { | ||
await _started; | ||
return MacroExecutionResult( | ||
target, await impl._host.augment(name, AugmentRequest(phase: 2))); | ||
} | ||
|
||
@override | ||
Future<MacroExecutionResult> executeDefinitionsPhase(MacroTarget target, | ||
DefinitionPhaseIntrospector definitionPhaseIntrospector) async { | ||
await _started; | ||
return MacroExecutionResult( | ||
target, await impl._host.augment(name, AugmentRequest(phase: 3))); | ||
} | ||
|
||
@override | ||
Future<MacroExecutionResult> executeTypesPhase( | ||
MacroTarget target, TypePhaseIntrospector typePhaseIntrospector) async { | ||
await _started; | ||
return MacroExecutionResult( | ||
target, await impl._host.augment(name, AugmentRequest(phase: 1))); | ||
} | ||
} | ||
|
||
/// Converts [AugmentResponse] to [injected.MacroExecutionResult]. | ||
class MacroExecutionResult implements injected.MacroExecutionResult { | ||
final MacroTarget target; | ||
final AugmentResponse augmentResponse; | ||
|
||
MacroExecutionResult(this.target, this.augmentResponse); | ||
|
||
@override | ||
List<Diagnostic> get diagnostics => []; | ||
|
||
@override | ||
Map<Identifier, Iterable<DeclarationCode>> get enumValueAugmentations => {}; | ||
|
||
@override | ||
MacroException? get exception => null; | ||
|
||
@override | ||
Map<Identifier, NamedTypeAnnotationCode> get extendsTypeAugmentations => {}; | ||
|
||
@override | ||
Map<Identifier, Iterable<TypeAnnotationCode>> get interfaceAugmentations => | ||
{}; | ||
|
||
@override | ||
Iterable<DeclarationCode> get libraryAugmentations => {}; | ||
|
||
@override | ||
Map<Identifier, Iterable<TypeAnnotationCode>> get mixinAugmentations => {}; | ||
|
||
@override | ||
Iterable<String> get newTypeNames => []; | ||
|
||
@override | ||
void serialize(Object serializer) => throw UnimplementedError(); | ||
|
||
@override | ||
Map<Identifier, Iterable<DeclarationCode>> get typeAugmentations => { | ||
// TODO(davidmorgan): this assumes augmentations are for the macro | ||
// application target. Instead, it should be explicit in | ||
// `AugmentResponse`. | ||
(target as Declaration).identifier: augmentResponse.augmentations | ||
.map((a) => DeclarationCode.fromParts([a.code])) | ||
.toList(), | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.