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)
- The SDK configured in dart.flutterSdkPath is not a valid SDK folder. HOT 1
- [breaking change] Change `SecurityContext` to an `abstract final class` HOT 4
- Unhandled Exception: type '_Type' is not a subtype of type 'IBaseModel' in type cast HOT 2
- `Thread 1 is not paused` error at the end of a web test HOT 7
- textDocument/completion payload sizes can be very large because of documentation of in-scope items HOT 7
- Dart cannot open a socket on Android device, not simulator HOT 6
- stdin stream closes unexpectedly when Dart program is spawned from a bat file (which is spawned by a NodeJS process) and an msys2 program has been run earlier in the bat file HOT 1
- vm/cc/DartAPI_BreakpointLockRace flaky -> Timeout on vm-linux-debug-x64c HOT 1
- Crash on new ffi/msan_test on ARM64 MSAN configurations
- Set-Cookie path should not be case-insensitive
- Provide a compatible method to conditionally import between WASM and regular Web with also backward compatibility HOT 5
- [resource_identifiers] closures out of static functions
- pkg/json breaks when a field name contains $ HOT 2
- [vm/ffi] `Pointer.asTypedList` shared across isolates causes use after free
- WASM incorrectly advertises dart.library.js HOT 2
- CFE fails to notice record field name differences when performing subtype matches HOT 1
- extension type on a Function named call HOT 7
- Invalid fixes being suggested
- Add a fix to create an extension method
- How should I load JS libraries from within WASM? 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.