Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to access metadata of Named Fields in a RecordType using Dart Analyzer? #59817

Open
jodinathan opened this issue Dec 28, 2024 · 5 comments
Open
Labels
analyzer-api Issues that impact the public API of the analyzer package area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. P2 A bug or feature request we're likely to work on triage-automation See https://github.com/dart-lang/ecosystem/tree/main/pkgs/sdk_triage_bot. type-question A question about expected behavior or functionality

Comments

@jodinathan
Copy link

I asked at SO before coming here.

I am working on a Dart builder and need to inspect the metadata (annotations) applied to the named fields of a RecordType. However, while I can successfully access RecordType.namedFields, the resulting RecordTypeNamedField objects do not appear to expose any metadata-related members.

Here is an example of the code I am trying to analyze:

Future<({@SomeAnnotation() String foo, int bar})?> someFunction() async {
  return null;
}

In this case, I need to determine programmatically that the foo field is annotated with @SomeAnnotation.

My Setup:
Dart SDK: 3.6.0
Analyzer version: 6.11.0

Question:
How can I access the metadata (annotations) of a named field in a RecordType using Dart's analyzer package in the context of a builder? Is there a specific API or workaround to achieve this?

@dart-github-bot
Copy link
Collaborator

Summary: User needs to access metadata (annotations) on named fields within a Dart RecordType using the analyzer package for a Dart builder. Currently, RecordTypeNamedField lacks necessary metadata access.

@dart-github-bot dart-github-bot added area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. triage-automation See https://github.com/dart-lang/ecosystem/tree/main/pkgs/sdk_triage_bot. type-question A question about expected behavior or functionality labels Dec 28, 2024
@keertip keertip added analyzer-api Issues that impact the public API of the analyzer package P2 A bug or feature request we're likely to work on labels Dec 30, 2024
@keertip
Copy link
Contributor

keertip commented Dec 30, 2024

/cc @bwilkerson, @scheglov

@scheglov
Copy link
Contributor

You cannot access metadata on types. And RecordTypeNamedField is a part of types.
Usually you access metadata of an element, e.g. ClassElement.
But record type fields are not elements, they are not always explicitly defined, e.g. final v = (0, 1);

You can access metadata on RecordTypeAnnotationField, which is AST.
If the AST is resolved, you can access its element, etc.

@jodinathan
Copy link
Author

@scheglov Could you provide an example of how to access a RecordTypeAnnotationField from a MethodElement?
Something simple, similar to the example in my post, would be great.

@scheglov
Copy link
Contributor

Unfortunately it is not possible to go directly from a MethodElement to resolved AST.

Something like this works, but is not necessary ideal too.

import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/file_system/overlay_file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';

Future<void> main() async {
  var resourceProvider = OverlayResourceProvider(
    PhysicalResourceProvider.INSTANCE,
  );

  var workspacePath = '/workspace';
  var testPackageRootPath = '$workspacePath/test';
  var testFilePath = '$testPackageRootPath/lib/test.dart';

  resourceProvider.setOverlay(
    testFilePath,
    content: r'''
class A {
  (@deprecated int, String) foo() => (0, '');
}
''',
    modificationStamp: -1,
  );

  var byteStore = MemoryByteStore();

  var collection = AnalysisContextCollectionImpl(
    resourceProvider: resourceProvider,
    includedPaths: [
      workspacePath,
    ],
    byteStore: byteStore,
  );

  var analysisContext = collection.contextFor(testFilePath);
  var analysisSession = analysisContext.currentSession;

  var unitResult = await analysisSession.getUnitElement(testFilePath);
  unitResult as UnitElementResult;
  var foo = unitResult.element.classes[0].methods[0];

  var libraryResult = await analysisSession.getResolvedLibrary(testFilePath);
  libraryResult as ResolvedLibraryResult;
  var fooNodeResult = libraryResult.getElementDeclaration(foo)!;
  var node = fooNodeResult.node as MethodDeclaration;
  print(node);

  var returnType = node.returnType as RecordTypeAnnotation;
  var metadata = returnType.fields[0].metadata;
  print(metadata[0].element);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
analyzer-api Issues that impact the public API of the analyzer package area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. P2 A bug or feature request we're likely to work on triage-automation See https://github.com/dart-lang/ecosystem/tree/main/pkgs/sdk_triage_bot. type-question A question about expected behavior or functionality
Projects
None yet
Development

No branches or pull requests

4 participants