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 get full display type name from DartType? #553

Open
ductranit opened this issue Aug 11, 2021 · 5 comments
Open

How to get full display type name from DartType? #553

ductranit opened this issue Aug 11, 2021 · 5 comments

Comments

@ductranit
Copy link

I have a property like:

Map<MyEnum, Map<String, String>> animations = {};

Before I can read its type when running analyzer with this code:

class MyGenerator extends Generator {
 @override
 String generate(LibraryReader library, BuildStep buildStep) {
     ClassElement clazzElement;   // get class Element from LibraryReader
     for (var field in clazzElement.fields) {
          var type = field.type.getDisplayString(withNullability: false); // it returns "Map<MyEnum, Map<String, String>>"
     }
 }
}

But now the field type result is Map<dynamic, Map<dynamic, dynamic>**>
The doc says that I shouldn't depend on getDisplayString(), but I can't find any way to do this.
How can I get the full type Map<MyEnum, Map<String, String>> from my property?

Flutter doctor:

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel master, 2.5.0-6.0.pre.30, on Mac OS X 10.15.7 19H1323 darwin-x64, locale en-US)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[✓] Xcode - develop for iOS and macOS
[✓] Chrome - develop for the web
[✓] Android Studio (version 4.2)
[✓] VS Code (version 1.58.2)
[✓] VS Code (version 1.60.0-insider)
[✓] Connected device (2 available)

• No issues found!

@jakemac53
Copy link
Contributor

jakemac53 commented Aug 11, 2021

Can you provide more info, and ideally a reproduction case? It sounds like you said this used to work and no longer does. When did it stop working? Was there an SDK or analyzer update that changed the behavior?

@ductranit
Copy link
Author

ductranit commented Aug 12, 2021

@jakemac53 This issue just happen recently on latest SDK (I upgraded flutter few times). I can't tell you which version that worked before because it was few months ago. The source_gen version was 1.0.2 (but the same issue on 1.0.5).
To reproduce, you can use the source_gen example and add this class:

class Test {
    Map<MyEnum, Map<String, String>> animations = {};
}

Then use this generator to read it:

class MyGenerator extends Generator {
 @override
 String generate(LibraryReader library, BuildStep buildStep) {
    library.allElements.forEach((element) {
      final classElement = cast<ClassElement>(element);
      final annotations = library.annotatedWith(typeChecker);
      if (classElement != null && !classElement.isEnum) {
        for (var field in classElement.fields) {
          var type = field.type.getDisplayString(withNullability: false);
           // I expect the type is "Map<MyEnum, Map<String, String>>" but it returns "Map<dynamic, Map<dynamic, dynamic>**>"
          print(type);
        }
      }
    });
 }
}

The problem is that the sdk changed behavior of getDisplayString

@natebosch
Copy link
Member

I'm not sure if this is something we want to try to support directly.

Mockito has a utility to help get a TypeReference since it uses code_builder. I'm not sure if we could generalize this in some way that it's not tied to code_builder.
https://github.com/dart-lang/mockito/blob/15ca5ad2132abfddad54677e29025b2b7a9a0ab1/lib/src/builder.dart#L1420-L1473

@srawlins - do you think there is an opportunity to share any of this logic in source_gen or is this better left to individual builders?

@srawlins
Copy link
Member

I've lightly pondered this for a while, but my use case always comes down to a necessary dependency on code_builder since I definitely want _i1.Map<_i2.MyEnum, ... if the types are provided via import prefixes (as they are in mockito, using code_builder.

So the utility necessarily depends on code_builder and source_gen. One possible solution is a new package, "source_gen code_builder utilities". Right off the bat, it could be used by mockito and angular, perhaps more.

What are the downsides to a new package? Maintenance..., not much else. (Not to minimize "maintenance," this is huge during language version bump cycles, like Null Safety, or a major version bump to dependencies...)

@natebosch
Copy link
Member

What do you think about creating a class in source_gen that holds the same symbol, url, and types information as TypeReference. It would take a small amount of shim code in each usage to translate from the new class to TypeReference.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants