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.

Home Page:https://pub.dev/packages/reflectable

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Why declarations requires invokingCapability?

zim32 opened this issue · comments

commented

If I remove invokingCapability, declarations are empty.

Here is simple code

import 'package:reflectable/reflectable.dart';
import 'reflectable_test.reflectable.dart';

class TestReflectable extends Reflectable {
  const TestReflectable() : super(typingCapability, reflectedTypeCapability);
}

const myReflector = TestReflectable();

@myReflector
class FooClass {
  String fooProperty = '1233';
}

void main(List<String> arguments) {
  initializeReflectable();
  final classMirror = myReflector.reflectType(FooClass) as ClassMirror;
  print(classMirror.declarations.length);
  // prints 0. Why?
}

It was a design decision made very early in the development of reflectable that invocation capabilities would yield a basic "universe of discourse", in the sense that only declarations with such capabilities would be considered for reflection support. The rationale was that reflection which is static-only would be done in different ways (presumably by importing the analyzer and working on the static analysis representation of the program offered by the analyzer). Reflectable is intended to provide reflection support at run-time, so, presumably, there would always be a run-time element of the services offered.

I believe that this is a property of reflectable which is not easy to change.

Note that invokingCapability is quite broad (same as instanceInvokeCapability plus staticInvokeCapability plus newInstanceCapability), you may only need a subset of those.

commented

Ok. Got it. Thanks

Why only classes declared with the Reflectable framework can be reflected?

In a real world scenario people also want to reflect 3rd part classes, and usually this is the main use case for reflection, since if you control a code you reduces the cases where you need reflection.

Note: I'm just highlighting a very important design decision, since mirrors are about to be replaced and this package is one of the current Google's references for reflection.

commented

Docs are bad, but I think there is possibility to specify Regex for classes to generate reflections for.

@gmpassos wrote:

Why only classes declared with the Reflectable framework can be reflected?

I don't know what it means to be declared with the Reflectable framework..

Reflectable is based on code generation. It generates code that supports a set of reflective operations on a set of source code entities and/or run-time entities. For instance, you can get support for reflective invocation of instance members on instances of a class C. This is achieved by creating a reflector (a direct subclass of Reflectable), say MyReflector, whose constructor includes instanceInvokeCapability, and then adding @MyReflector() as metadata on the class C.

This is the typical approach that you'd use when you have written the class C. Soo, for example, https://github.com/google/reflectable.dart/blob/master/test_reflectable/test/basic_test.dart.

If you want to obtain reflection support for a class in 'dart:core' or any other library that you cannot edit, you'd use a declaration that associates the reflector MyReflectable with the class "at a distance". This is done by adding an instance of GlobalQuantifyCapability as metadata to an import of reflectable.dart. See, for example, https://github.com/google/reflectable.dart/blob/master/test_reflectable/test/global_quantify_test.dart. Global quantification allows you to match classes with a regular expression, and there's a variant that relies on metadata (so if you want to obtain reflection support for exactly the classes that already have a specific annotation @something, then you specify that a specific reflector should support declarations that carry @something).

So there's no particular limitation that prevents you from using reflection with third party classes: You can request reflection support if you can specify the name of the class, a regular expression that matches the name of the class, a specific kind of metadata that the class carries (and more).

It might be helpful to take a look at the directory test_reflectable/test, and it might give you an overview of the approach to take a look at 'The Design of Reflectable Capabilities'.

HTH ;-)

commented

I have one more question, want to ask here. Can I get somehow info about if property type is nullable or not? Can not figure out.
F.e. can i distinguish between String and String? types?

Reflectable does work with programs whose source code is using null safety, but it is not yet able to deliver the information about null safety related properties.

Please create an issue requesting this, such that it's on the agenda, and people can vote for it. Certain things should be easy (like having a bool get isNullable on a TypeMirror), but I don't have an overview of all the implications, so it would be useful to get it started.

@ eernstg wrote:

I don't know what it means to be declared with the Reflectable framework..

What I mean is that you can't reflect to a class that is not declared depending on reflectable (by annotation or extending something). At least I couldn't find any example on how to reflect a class that wasn't design to be reflected with reflectable.

What I want to point is the usual need to reflect a class that was created by a 3rd part that wast never imagining that his class could be used by reflection. This is a real use case for general code reflection.

It seems that this example that you pointed shows a better scenario:
https://github.com/google/reflectable.dart/blob/master/test_reflectable/test/global_quantify_test.dart

Based in the commonly available documentation it seems that it's only possible to reflect classes that we're designed with reflectable.

FYI:
https://github.com/gmpassos/reflection_factory

I'm the author of the package reflection_factory that has a similar approach of reflectable.

What I mean is that you can't reflect to a class that is not declared depending on reflectable

That is not true.

I mentioned GlobalQuantifyCapability and explained briefly how it works. In https://github.com/google/reflectable.dart/blob/master/test_reflectable/test/new_instance_native_test.dart, that capability is used to obtain reflection support for the system class List. That class does not depend on reflectable.

GlobalQuantifyCapability is an annotation, but it is associated with an import of reflectable.dart, not with the class (or the classes, or functions, etc) for which it requests reflection support.

If the given reflector includes subtypeQuantifyCapability then it requests reflection support for all subtypes of any class that it is associated with. So you could use GlobalQuantifyCapability to request reflection support for, say, Widget, with that reflector. It would then support reflection for all subtypes of Widget (that is classes that extend Widget or classes that implements Widget, directly or indirectly). So you don't need to know the names of the classes that you're getting reflection support for.

PS: I took a brief look at reflection_factory. Interesting! I wasn't aware of that package, and it is always useful to be aware of a broader selection of packages for any given task.

Thanks for the discussion.

I have understood that the capability to reflect over 3rd part classes already exists.

I recommend to update your README to show a simple example for this use case.
https://github.com/google/reflectable.dart/blob/master/reflectable/README.md

Regards,
GMP

commented

I agree that docs is somewhat.. not compelte
There is just super simple example and veru techincal and hard to read design document.
And tests.

It will be super cool of you can make docs more user-friendly.
Thanks for feedback

Good idea! Cf. #265.