google / reflectable.dart

Reflectable is a Dart library that allows programmers to eliminate certain usages of dynamic reflection by specialization of reflective code to an equivalent implementation using only static techniques. The use of dynamic reflection is constrained in order to ensure that the specialized code can be generated and will have a reasonable size.
https://pub.dev/packages/reflectable
BSD 3-Clause "New" or "Revised" License
374 stars 56 forks source link

Include annotated types that are not imported to `main.dart` #318

Closed dustincatap closed 1 year ago

dustincatap commented 1 year ago

After updating to Dart 3.0, reflectable is not recognizing the other types that are annotated unless they are imported in main.dart.

console_app.zip

Here is my build.yaml:

targets:
  $default:
    builders:
      reflectable:
        generate_for:
          - lib/main.dart

reflection.dart

import 'package:reflectable/reflectable.dart';

class Reflector extends Reflectable {
  const Reflector()
      : super(declarationsCapability, metadataCapability, invokingCapability);
}

foo.dart:

import 'package:console_app/reflection.dart';

@Reflector()
class Foo {
  void foo() {}
}

bar.dart

import 'package:console_app/reflection.dart';

@Reflector()
class Bar {
  void bar() {}
}

And my main.dart:

// ignore_for_file: unused_import

import 'package:console_app/main.reflectable.dart';
import 'foo.dart'; // This is added to reflectable if imported
// import 'bar.dart'; // This is not added to reflectable if not imported

void main() {
  initializeReflectable();
}
eernstg commented 1 year ago

reflectable is not recognizing the other types that are annotated unless they are imported in main.dart.

It should not be necessary for 'main.dart' to directly import 'foo.dart' and 'bar.dart', but it is (and must be) required that there is an import path from 'main.dart' to 'foo.dart' and to 'bar.dart', in order to include reflection support for the class Foo and the class Bar.

The program as such consists of 'main.dart', plus everything which is imported directly into 'main.dart', plus, recursively, everything is imported into each of those imported libraries. In other words, the libraries in the program 'main.dart' is the transitive import closure of the library 'main.dart'.

If any particular library L isn't in that transitive closure than the reflectable code generator never gets to see the declarations, and hence it cannot generate the code which is needed in order to support reflection on anything in L.

Also, it makes no sense to have support for reflection on anything which doesn't exist in the given program, so it would be a waste of space if the reflectable code generator were to find some extra libraries (say, "everything in the current package", or whatever we could come up with) and include them.

There should not be a connection to the language version being 3.0 or earlier, the reflectable code generator has had this behavior from day one.

eernstg commented 1 year ago

I'll close this issue because it is working as intended. @dustincatap, please create a new issue if something hasn't been clarified, or isn't working.