Comments (9)
Code
import 'package:macro_test/macro_test.dart';
@ControllerMacro()
class MyControllerText {
@CustomAnnotation()
void main() {}
}
class CustomAnnotation {
const CustomAnnotation();
}
The reason it crashes is that the macro attempts to access the identifier @CustomAnnotation
during the declarations phase. At this time this identifier is not resolved yet - we resolve metadata after the declarations phase, but before the definitions phase.
The reason we cannot resolve annotations until after the declarations phase is that resolution potentially depends on constructors that might be added at any point during the declarations phase.
From the macro API implementation inside the analyzer we don't have any better solution than to throw - macro.ResolvedIdentifier resolveIdentifier()
must return something, and if the identifier cannot be resolved, there is nothing to return.
@jakemac53 For any API suggestions.
from sdk.
With https://dart-review.googlesource.com/c/sdk/+/366966 we will tell the name of the unresolved identifier.
Theoretically we know much more - the exact AST node (so the offset), and the content of the file. So, if this happens regularly, we can provide more details to simplify identification of the problematic identifier.
from sdk.
The reason we cannot resolve annotations until after the declarations phase is that resolution potentially depends on constructors that might be added at any point during the declarations phase.
The type is definitely already known, and it seems like we should be able to then know the assumed "identifier" for any constructor (it must be a const constructor with that name on that known type). So, while you can't tie the constructor identifier to a specific AST node or element, we should know everything we need to know to output a reference to that identifier as Code, which is the important part (the import URI for it plus the scope (class name) and the name of the constructor)?
from sdk.
True, we should be able to resolve the type element.
from sdk.
BTW, here is the script that I use to see if the example runs well, and generated code.
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
void main() async {
var collection = AnalysisContextCollectionImpl(
includedPaths: [
'/Users/scheglov/tmp/2024-05-17/AnalyzerCrashResolveIdentifier/lib/controller.dart',
],
);
var timer = Stopwatch()..start();
for (var analysisContext in collection.contexts) {
print(analysisContext.contextRoot.root.path);
var analysisSession = analysisContext.currentSession;
for (var path in analysisContext.contextRoot.analyzedFiles()) {
if (path.endsWith('.dart')) {
var libResult = await analysisSession.getResolvedLibrary(path);
if (libResult is ResolvedLibraryResult) {
for (var unitResult in libResult.units) {
print(' ${unitResult.path}');
var ep = '\n ';
print(' errors:$ep${unitResult.errors.join(ep)}');
print('---');
print(unitResult.content);
print('---');
}
}
}
}
}
print('[time: ${timer.elapsedMilliseconds} ms]');
await collection.dispose();
}
from sdk.
https://dart-review.googlesource.com/c/sdk/+/366895 fixes the crash.
from sdk.
The solution now indeed works for the const constructor annotations, though using a reference to a global const field still results in a crash.
import 'package:macro_test/macro_test.dart';
@ControllerMacro()
class MyControllerText {
@CustomAnnotation()
@refAnnotation
void main() {
}
}
class CustomAnnotation {
const CustomAnnotation();
}
const refAnnotation = CustomAnnotation();
This code now fails with
Invalid argument(s): Unresolved identifier: ref
#0 DeclarationBuilder.resolveIdentifier (package:analyzer/src/summary2/macro_declarations.dart:308:9)
#1 _Builder._buildIdentifier (package:_macros/src/executor/augmentation_library.dart:73:53)
#2 _Builder._buildCode (package:_macros/src/executor/augmentation_library.dart:133:9)
#3 _Builder._buildCode (package:_macros/src/executor/augmentation_library.dart:131:9)
#4 _Builder.build (package:_macros/src/executor/augmentation…
As expected since 2fa0501 now outputs the reference to the offending identifier.
Could there be a possibility to also assume the identifier code of the const field similarly to how constructor identifiers are assumed or is this not possible with the information known in the declaration phase? Reading @jakemac53's explanation on how this is possible for constructors also let's me assume this is possible for const fields, since we should know both the import uri of the const field's library as well as the name of the global field.
from sdk.
During the declarations phase we cannot resolve identifiers that are not guaranteed to be names of types.
Because resolution @refAnnotation
could change if the next macro will declare refAnnotation
in this library.
Of course we technically can do this in the analyzer, but the result might be sometimes surprising.
My reading of @jakemac53 comment "you can't tie the constructor identifier to a specific AST node or element" - we don't know the element, but this does not matter because we can output the constructor name, and regardless what it is, it will be the same as the referenced by the annotation.
from sdk.
Ah okay I see the problem. So if I want to have declarative macros which are copying metadata, this will only work for const constructor invocations. Thanks for clarifying!
from sdk.
Related Issues (20)
- Coverage reports differ when --optimization-counter-threshold=-1 is used HOT 6
- vm/dart/isolates/shared_test flakily fails on vm-reload-linux-release-x64 HOT 5
- Pre-built Stack Class in the Dart Standard Library HOT 2
- Data driven fix: Replacing a method with a getter when method has been removed does not work correctly
- Never-bounded types cause CFE crash
- [dartdev] `Could not find dart. Have you built the full Dart SDK?` on `dart build` HOT 10
- [infra] More frequent dev releases HOT 1
- Consider dropping instructions after return, throw, unreachable, br in wasm_builder
- Consider optimizing `x < 0 || x > positiveInt` to single unsigned comparison
- Support `Add null check` fix for entire file HOT 4
- Failures on [dart2wasm] Use unsafeCast in a few places...Reland "[vm] Move `ResolveUri` to bin" HOT 3
- Analyzer data-based fix request HOT 2
- `dart compile js` fails with the newest SDK HOT 17
- Cannot resolve top-level methods with docimports HOT 4
- [Wildcard Variables] Update `DUPLICATE_DEFINTION` reporting
- CFE fails to report error when `super` is used in a redirecting constructor. HOT 2
- DevTools not serving properly on app refresh HOT 1
- [Wildcard Variables] Update `DUPLICATE_FIELD_FORMAL_PARAMETER` reporting
- `@internal` annotation does not supress `public_member_api_docs` lint on functions HOT 1
- Dart analyzer does not infer the correct type for generic record HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from sdk.