refactor: refactored platform reflection to platform mirrors

This commit is contained in:
Patrick Stewart 2024-12-25 14:31:41 -07:00
parent 3e9de4cbb2
commit a79809f46b
87 changed files with 1443 additions and 954 deletions

View file

@ -1,5 +1,5 @@
import 'package:platform_contracts/contracts.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
/// A utility class for calling methods with dependency injection.
class BoundMethod {

View file

@ -1,5 +1,5 @@
import 'package:platform_contracts/contracts.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
import 'contextual_binding_builder.dart';
import 'bound_method.dart';

View file

@ -1,5 +1,5 @@
import 'package:platform_contracts/contracts.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
/// A builder for defining contextual bindings for the container.
class ContextualBindingBuilder implements ContextualBindingBuilderContract {

View file

@ -1,5 +1,5 @@
import 'package:platform_contracts/contracts.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
/// Utility class for container-related operations.
class Util {

View file

@ -12,7 +12,7 @@ environment:
dependencies:
dsr_container: ^0.0.1
platform_contracts: ^0.1.0
platform_reflection: ^0.1.0
platform_mirrors: ^0.1.0
# path: ^1.8.0
dev_dependencies:

View file

@ -1,4 +1,4 @@
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
import 'collection.dart';
/// A proxy class for higher-order collection operations.
@ -31,7 +31,7 @@ class HigherOrderCollectionProxy<T> {
}
// Handle object property access
if (Reflector.isReflectable(item.runtimeType)) {
if (ReflectionRegistry.isReflectable(item.runtimeType)) {
try {
// Use direct property access
switch (name) {
@ -57,7 +57,7 @@ class HigherOrderCollectionProxy<T> {
if (item == null) return null;
// Handle method calls
if (Reflector.isReflectable(item.runtimeType)) {
if (ReflectionRegistry.isReflectable(item.runtimeType)) {
try {
// Use direct method invocation
switch (_method) {
@ -107,7 +107,7 @@ class HigherOrderCollectionProxy<T> {
}
// Handle object property access
if (Reflector.isReflectable(item.runtimeType)) {
if (ReflectionRegistry.isReflectable(item.runtimeType)) {
try {
// Use direct property access
switch (property) {
@ -149,7 +149,7 @@ class HigherOrderCollectionProxy<T> {
}
// Handle object property access
if (Reflector.isReflectable(item.runtimeType)) {
if (ReflectionRegistry.isReflectable(item.runtimeType)) {
try {
// Use direct property access
switch (property) {
@ -188,8 +188,9 @@ class HigherOrderCollectionProxy<T> {
}
// Handle object property access
if (Reflector.isReflectable(item.runtimeType)) {
final metadata = Reflector.getPropertyMetadata(item.runtimeType);
if (ReflectionRegistry.isReflectable(item.runtimeType)) {
final metadata =
ReflectionRegistry.getPropertyMetadata(item.runtimeType);
return metadata?.containsKey(property) ?? false;
}

View file

@ -8,7 +8,7 @@ environment:
dependencies:
meta: ^1.9.0
platform_contracts: ^0.1.0
platform_reflection: ^0.1.0
platform_mirrors: ^0.1.0
dev_dependencies:
lints: ^2.1.0

View file

@ -1,4 +1,4 @@
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
import 'package:test/test.dart';
import 'package:platform_collections/src/collection.dart';
import 'package:platform_collections/src/higher_order_collection_proxy.dart';
@ -24,16 +24,16 @@ void main() {
setUp(() {
// Register TestModel for reflection
Reflector.registerType(TestModel);
ReflectionRegistry.registerType(TestModel);
// Register properties
Reflector.registerProperty(TestModel, 'name', String,
ReflectionRegistry.registerProperty(TestModel, 'name', String,
isReadable: true, isWritable: true);
Reflector.registerProperty(TestModel, 'age', int,
ReflectionRegistry.registerProperty(TestModel, 'age', int,
isReadable: true, isWritable: true);
// Register methods with proper return types
Reflector.registerMethod(
ReflectionRegistry.registerMethod(
TestModel,
'greet',
[], // no parameters
@ -41,7 +41,7 @@ void main() {
isStatic: false,
);
Reflector.registerMethod(
ReflectionRegistry.registerMethod(
TestModel,
'setAge',
[int], // takes an int parameter
@ -60,17 +60,17 @@ void main() {
});
test('reflection registration is correct', () {
expect(Reflector.isReflectable(TestModel), isTrue,
expect(ReflectionRegistry.isReflectable(TestModel), isTrue,
reason: 'TestModel should be reflectable');
final props = Reflector.getPropertyMetadata(TestModel);
final props = ReflectionRegistry.getPropertyMetadata(TestModel);
expect(props, isNotNull, reason: 'Property metadata should exist');
expect(props!['name'], isNotNull,
reason: 'name property should be registered');
expect(props['age'], isNotNull,
reason: 'age property should be registered');
final methods = Reflector.getMethodMetadata(TestModel);
final methods = ReflectionRegistry.getMethodMetadata(TestModel);
expect(methods, isNotNull, reason: 'Method metadata should exist');
expect(methods!['greet'], isNotNull,
reason: 'greet method should be registered');
@ -155,7 +155,7 @@ void main() {
tearDown(() {
// Clean up reflection metadata after each test
Reflector.reset();
ReflectionRegistry.reset();
});
});
}

View file

@ -1,4 +1,4 @@
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
/// Interface for objects that can provide methods to be mixed in
abstract class MacroProvider {

View file

@ -7,7 +7,7 @@ environment:
dependencies:
platform_contracts: ^0.1.0
platform_reflection: ^0.1.0
platform_mirrors: ^0.1.0
meta: ^1.9.0
dev_dependencies:

View file

@ -1,6 +1,6 @@
import 'package:test/test.dart';
import 'package:platform_macroable/platform_macroable.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
@reflectable
class TestClass with Macroable {}

View file

@ -48,7 +48,7 @@ final value = mirror.getField(#prop).reflectee;
mirror.invoke(#method, [42]);
// Platform Reflection
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
final reflector = RuntimeReflector.instance;
final instance = reflector.createInstance(MyClass, positionalArgs: []) as MyClass;
@ -94,7 +94,7 @@ To migrate from dart:mirrors to Platform Reflection:
import 'dart:mirrors';
// After
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
```
2. Add registration for each reflectable class:

View file

@ -22,7 +22,7 @@ dependencies:
### 1. Define and Register a Class
```dart
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
@reflectable
class User {

View file

@ -1,4 +1,4 @@
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
// Custom annotation to demonstrate metadata
class Validate {
@ -73,17 +73,17 @@ class User extends Entity {
void main() async {
// Register classes for reflection
Reflector.register(Identifiable);
Reflector.register(Entity);
Reflector.register(User);
Reflector.register(Container);
ReflectionRegistry.register(Identifiable);
ReflectionRegistry.register(Entity);
ReflectionRegistry.register(User);
ReflectionRegistry.register(Container);
// Register Container<int> specifically for reflection
final container = Container<int>(42);
Reflector.register(container.runtimeType);
ReflectionRegistry.register(container.runtimeType);
// Register property metadata directly
Reflector.registerPropertyMetadata(
ReflectionRegistry.registerPropertyMetadata(
User,
'name',
PropertyMetadata(
@ -95,7 +95,7 @@ void main() async {
),
);
Reflector.registerPropertyMetadata(
ReflectionRegistry.registerPropertyMetadata(
User,
'age',
PropertyMetadata(
@ -106,7 +106,7 @@ void main() async {
),
);
Reflector.registerPropertyMetadata(
ReflectionRegistry.registerPropertyMetadata(
User,
'tags',
PropertyMetadata(
@ -117,7 +117,7 @@ void main() async {
),
);
Reflector.registerPropertyMetadata(
ReflectionRegistry.registerPropertyMetadata(
User,
'id',
PropertyMetadata(
@ -129,7 +129,7 @@ void main() async {
);
// Register User methods
Reflector.registerMethod(
ReflectionRegistry.registerMethod(
User,
'greet',
[String],
@ -138,7 +138,7 @@ void main() async {
isRequired: [false],
);
Reflector.registerMethod(
ReflectionRegistry.registerMethod(
User,
'addTag',
[String],
@ -147,7 +147,7 @@ void main() async {
isRequired: [true],
);
Reflector.registerMethod(
ReflectionRegistry.registerMethod(
User,
'getName',
[],
@ -155,7 +155,7 @@ void main() async {
);
// Register constructors with creators
Reflector.registerConstructor(
ReflectionRegistry.registerConstructor(
User,
'',
parameterTypes: [String, String, int, List],
@ -169,7 +169,7 @@ void main() async {
),
);
Reflector.registerConstructor(
ReflectionRegistry.registerConstructor(
User,
'guest',
creator: () => User.guest(),

View file

@ -2,17 +2,37 @@ library mirrors;
import 'package:platform_contracts/contracts.dart';
import 'src/mirrors/mirror_system.dart';
import 'src/core/mirror_system.dart';
import 'src/mirrors/instance_mirror.dart';
/// Core
export 'src/core/library_scanner.dart';
export 'src/core/reflector.dart';
export 'src/core/runtime_reflector.dart';
export 'src/core/scanner.dart';
/// Annotations
export 'src/annotations/reflectable.dart';
/// MirrorSystem
export 'src/mirrors/mirror_system.dart';
/// Core
export 'src/core/mirror_system.dart';
/// Discovery
export 'src/discovery/type_analyzer.dart';
export 'src/discovery/library_scanner.dart';
export 'src/discovery/scanner.dart';
/// Discovery Models
export 'src/discovery/models/models.dart';
/// Exceptions
export 'src/exceptions/invalid_arguments_exception.dart';
export 'src/exceptions/member_not_found_exception.dart';
export 'src/exceptions/not_reflectable_exception.dart';
export 'src/exceptions/reflection_exception.dart';
/// Metadata
export 'src/metadata/constructor_metadata.dart';
export 'src/metadata/function_metadata.dart';
export 'src/metadata/method_metadata.dart';
export 'src/metadata/parameter_metadata.dart';
export 'src/metadata/property_metadata.dart';
export 'src/metadata/type_metadata.dart';
export 'src/metadata/type_parameter_metadata.dart';
/// Mirrors
export 'src/mirrors/base_mirror.dart';
@ -28,15 +48,14 @@ export 'src/mirrors/type_mirror.dart';
export 'src/mirrors/type_variable_mirror.dart';
export 'src/mirrors/variable_mirror.dart';
/// Reflector
export 'src/reflector/runtime_reflector.dart';
/// Registry
export 'src/registry/reflection_registry.dart';
/// Types
export 'src/mirrors/special_types.dart';
/// Metadata and Annotations
export 'src/annotations.dart';
export 'src/metadata.dart';
/// Exceptions
export 'src/exceptions.dart';
export 'src/types/special_types.dart';
/// Reflects an instance.
InstanceMirrorContract reflect(dynamic reflectee) {

View file

@ -0,0 +1,7 @@
/// Marks a class as reflectable, allowing runtime reflection capabilities.
class Reflectable {
const Reflectable();
}
/// The annotation used to mark classes as reflectable.
const reflectable = Reflectable();

View file

@ -1,6 +1,6 @@
import 'dart:core';
import 'package:platform_contracts/contracts.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
/// Implementation of [MirrorSystemContract] that provides reflection on a set of libraries.
class MirrorSystem implements MirrorSystemContract {
@ -162,7 +162,7 @@ class MirrorSystem implements MirrorSystemContract {
ClassMirrorContract _createClassMirror(Type type) {
// Check if type is reflectable
if (!Reflector.isReflectable(type)) {
if (!ReflectionRegistry.isReflectable(type)) {
throw ArgumentError('Type is not reflectable: $type');
}
@ -178,8 +178,8 @@ class MirrorSystem implements MirrorSystemContract {
);
// Get metadata from registry
final properties = Reflector.getPropertyMetadata(type) ?? {};
final methods = Reflector.getMethodMetadata(type) ?? {};
final properties = ReflectionRegistry.getPropertyMetadata(type) ?? {};
final methods = ReflectionRegistry.getMethodMetadata(type) ?? {};
// Create declarations map
final declarations = <Symbol, DeclarationMirrorContract>{};
@ -261,7 +261,7 @@ class MirrorSystem implements MirrorSystemContract {
@override
TypeMirrorContract reflectType(Type type) {
if (!Reflector.isReflectable(type)) {
if (!ReflectionRegistry.isReflectable(type)) {
throw ArgumentError('Type is not reflectable: $type');
}
return _getOrCreateTypeMirror(type);

View file

@ -1,6 +1,6 @@
import 'dart:core';
import 'package:platform_contracts/contracts.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
/// Runtime scanner that analyzes libraries and extracts their metadata.
class LibraryScanner {
@ -203,73 +203,3 @@ class LibraryAnalyzer {
]);
}
}
/// Information about a library.
class LibraryInfo {
final Uri uri;
final List<FunctionInfo> topLevelFunctions;
final List<VariableInfo> topLevelVariables;
final List<DependencyInfo> dependencies;
final List<DependencyInfo> exports;
LibraryInfo({
required this.uri,
required this.topLevelFunctions,
required this.topLevelVariables,
required this.dependencies,
required this.exports,
});
}
/// Information about a top-level function.
class FunctionInfo {
final String name;
final List<Type> parameterTypes;
final List<ParameterMetadata> parameters;
final bool returnsVoid;
final Type returnType;
final bool isPrivate;
FunctionInfo({
required this.name,
required this.parameterTypes,
required this.parameters,
required this.returnsVoid,
required this.returnType,
required this.isPrivate,
});
}
/// Information about a top-level variable.
class VariableInfo {
final String name;
final Type type;
final bool isFinal;
final bool isConst;
final bool isPrivate;
VariableInfo({
required this.name,
required this.type,
required this.isFinal,
required this.isConst,
required this.isPrivate,
});
}
/// Information about a library dependency.
class DependencyInfo {
final Uri uri;
final String? prefix;
final bool isDeferred;
final List<String> showCombinators;
final List<String> hideCombinators;
DependencyInfo({
required this.uri,
required this.prefix,
required this.isDeferred,
required this.showCombinators,
required this.hideCombinators,
});
}

View file

@ -0,0 +1,69 @@
import '../../metadata/parameter_metadata.dart';
/// Information about a constructor.
///
/// Contains metadata about a constructor including:
/// - The constructor's name
/// - Parameter types and metadata
class ConstructorInfo {
/// The name of the constructor
final String name;
/// List of parameter types for this constructor
final List<Type> parameterTypes;
/// List of parameter metadata for this constructor
final List<ParameterMetadata> parameters;
/// Creates a new [ConstructorInfo] instance.
///
/// All parameters are required:
/// - [name]: The constructor's name
/// - [parameterTypes]: List of parameter types
/// - [parameters]: List of parameter metadata
const ConstructorInfo({
required this.name,
required this.parameterTypes,
required this.parameters,
});
@override
String toString() {
final buffer = StringBuffer();
if (name.isNotEmpty) {
buffer.write('$name(');
} else {
buffer.write('(');
}
buffer.write(parameters.join(', '));
buffer.write(')');
return buffer.toString();
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is ConstructorInfo &&
other.name == name &&
_listEquals(other.parameterTypes, parameterTypes) &&
_listEquals(other.parameters, parameters);
}
@override
int get hashCode {
return Object.hash(
name,
Object.hashAll(parameterTypes),
Object.hashAll(parameters),
);
}
bool _listEquals<T>(List<T> a, List<T> b) {
if (identical(a, b)) return true;
if (a.length != b.length) return false;
for (var i = 0; i < a.length; i++) {
if (a[i] != b[i]) return false;
}
return true;
}
}

View file

@ -0,0 +1,83 @@
/// Information about a library dependency.
///
/// Contains metadata about a dependency including:
/// - The dependency's URI
/// - Import prefix (if any)
/// - Whether it's deferred
/// - Show/hide combinators
class DependencyInfo {
/// The URI of the dependency
final Uri uri;
/// The prefix used for this dependency (e.g., 'as prefix')
final String? prefix;
/// Whether this dependency is deferred
final bool isDeferred;
/// List of identifiers shown from this dependency
final List<String> showCombinators;
/// List of identifiers hidden from this dependency
final List<String> hideCombinators;
/// Creates a new [DependencyInfo] instance.
///
/// Required parameters:
/// - [uri]: The dependency's URI
/// - [prefix]: The prefix used for this dependency (can be null)
/// - [isDeferred]: Whether the dependency is deferred
/// - [showCombinators]: List of shown identifiers
/// - [hideCombinators]: List of hidden identifiers
const DependencyInfo({
required this.uri,
required this.prefix,
required this.isDeferred,
required this.showCombinators,
required this.hideCombinators,
});
@override
String toString() {
final buffer = StringBuffer();
if (isDeferred) buffer.write('deferred ');
buffer.write('$uri');
if (prefix != null) buffer.write(' as $prefix');
if (showCombinators.isNotEmpty)
buffer.write(' show ${showCombinators.join(", ")}');
if (hideCombinators.isNotEmpty)
buffer.write(' hide ${hideCombinators.join(", ")}');
return buffer.toString();
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is DependencyInfo &&
other.uri == uri &&
other.prefix == prefix &&
other.isDeferred == isDeferred &&
_listEquals(other.showCombinators, showCombinators) &&
_listEquals(other.hideCombinators, hideCombinators);
}
@override
int get hashCode {
return Object.hash(
uri,
prefix,
isDeferred,
Object.hashAll(showCombinators),
Object.hashAll(hideCombinators),
);
}
bool _listEquals<T>(List<T> a, List<T> b) {
if (identical(a, b)) return true;
if (a.length != b.length) return false;
for (var i = 0; i < a.length; i++) {
if (a[i] != b[i]) return false;
}
return true;
}
}

View file

@ -0,0 +1,82 @@
import '../../metadata/parameter_metadata.dart';
/// Information about a top-level function.
///
/// Contains metadata about a function including:
/// - The function's name
/// - Parameter types and metadata
/// - Return type information
/// - Privacy status
class FunctionInfo {
/// The name of the function
final String name;
/// List of parameter types for this function
final List<Type> parameterTypes;
/// List of parameter metadata for this function
final List<ParameterMetadata> parameters;
/// Whether this function returns void
final bool returnsVoid;
/// The return type of this function
final Type returnType;
/// Whether this function is private
final bool isPrivate;
/// Creates a new [FunctionInfo] instance.
///
/// All parameters are required:
/// - [name]: The function's name
/// - [parameterTypes]: List of parameter types
/// - [parameters]: List of parameter metadata
/// - [returnsVoid]: Whether the function returns void
/// - [returnType]: The function's return type
/// - [isPrivate]: Whether the function is private
const FunctionInfo({
required this.name,
required this.parameterTypes,
required this.parameters,
required this.returnsVoid,
required this.returnType,
required this.isPrivate,
});
@override
String toString() => 'FunctionInfo(name: $name, returnType: $returnType)';
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is FunctionInfo &&
other.name == name &&
_listEquals(other.parameterTypes, parameterTypes) &&
_listEquals(other.parameters, parameters) &&
other.returnsVoid == returnsVoid &&
other.returnType == returnType &&
other.isPrivate == isPrivate;
}
@override
int get hashCode {
return Object.hash(
name,
Object.hashAll(parameterTypes),
Object.hashAll(parameters),
returnsVoid,
returnType,
isPrivate,
);
}
bool _listEquals<T>(List<T> a, List<T> b) {
if (identical(a, b)) return true;
if (a.length != b.length) return false;
for (var i = 0; i < a.length; i++) {
if (a[i] != b[i]) return false;
}
return true;
}
}

View file

@ -0,0 +1,78 @@
import 'function_info.dart';
import 'variable_info.dart';
import 'dependency_info.dart';
/// Information about a library.
///
/// Contains metadata about a Dart library including:
/// - The library's URI
/// - Top-level functions defined in the library
/// - Top-level variables defined in the library
/// - Dependencies (imports) used by the library
/// - Exports exposed by the library
class LibraryInfo {
/// The URI identifying this library
final Uri uri;
/// List of top-level functions defined in this library
final List<FunctionInfo> topLevelFunctions;
/// List of top-level variables defined in this library
final List<VariableInfo> topLevelVariables;
/// List of dependencies (imports) used by this library
final List<DependencyInfo> dependencies;
/// List of exports exposed by this library
final List<DependencyInfo> exports;
/// Creates a new [LibraryInfo] instance.
///
/// All parameters are required:
/// - [uri]: The URI identifying this library
/// - [topLevelFunctions]: List of top-level functions
/// - [topLevelVariables]: List of top-level variables
/// - [dependencies]: List of dependencies (imports)
/// - [exports]: List of exports
const LibraryInfo({
required this.uri,
required this.topLevelFunctions,
required this.topLevelVariables,
required this.dependencies,
required this.exports,
});
@override
String toString() => 'LibraryInfo(uri: $uri)';
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is LibraryInfo &&
other.uri == uri &&
_listEquals(other.topLevelFunctions, topLevelFunctions) &&
_listEquals(other.topLevelVariables, topLevelVariables) &&
_listEquals(other.dependencies, dependencies) &&
_listEquals(other.exports, exports);
}
@override
int get hashCode {
return Object.hash(
uri,
Object.hashAll(topLevelFunctions),
Object.hashAll(topLevelVariables),
Object.hashAll(dependencies),
Object.hashAll(exports),
);
}
bool _listEquals<T>(List<T> a, List<T> b) {
if (identical(a, b)) return true;
if (a.length != b.length) return false;
for (var i = 0; i < a.length; i++) {
if (a[i] != b[i]) return false;
}
return true;
}
}

View file

@ -0,0 +1,89 @@
import '../../metadata/parameter_metadata.dart';
/// Information about a method.
///
/// Contains metadata about a method including:
/// - The method's name
/// - Parameter types and metadata
/// - Return type information
/// - Whether it's static
class MethodInfo {
/// The name of the method
final String name;
/// List of parameter types for this method
final List<Type> parameterTypes;
/// List of parameter metadata for this method
final List<ParameterMetadata> parameters;
/// Whether this method returns void
final bool returnsVoid;
/// The return type of this method
final Type returnType;
/// Whether this method is static
final bool isStatic;
/// Creates a new [MethodInfo] instance.
///
/// All parameters are required:
/// - [name]: The method's name
/// - [parameterTypes]: List of parameter types
/// - [parameters]: List of parameter metadata
/// - [returnsVoid]: Whether the method returns void
/// - [returnType]: The method's return type
/// - [isStatic]: Whether the method is static
const MethodInfo({
required this.name,
required this.parameterTypes,
required this.parameters,
required this.returnsVoid,
required this.returnType,
required this.isStatic,
});
@override
String toString() {
final buffer = StringBuffer();
if (isStatic) buffer.write('static ');
buffer.write('$returnType $name(');
buffer.write(parameters.join(', '));
buffer.write(')');
return buffer.toString();
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is MethodInfo &&
other.name == name &&
_listEquals(other.parameterTypes, parameterTypes) &&
_listEquals(other.parameters, parameters) &&
other.returnsVoid == returnsVoid &&
other.returnType == returnType &&
other.isStatic == isStatic;
}
@override
int get hashCode {
return Object.hash(
name,
Object.hashAll(parameterTypes),
Object.hashAll(parameters),
returnsVoid,
returnType,
isStatic,
);
}
bool _listEquals<T>(List<T> a, List<T> b) {
if (identical(a, b)) return true;
if (a.length != b.length) return false;
for (var i = 0; i < a.length; i++) {
if (a[i] != b[i]) return false;
}
return true;
}
}

View file

@ -0,0 +1,9 @@
export 'constructor_info.dart';
export 'dependency_info.dart';
export 'function_info.dart';
export 'library_info.dart';
export 'method_info.dart';
export 'parameter_info.dart';
export 'property_info.dart';
export 'type_info.dart';
export 'variable_info.dart';

View file

@ -0,0 +1,100 @@
import 'type_info.dart';
/// Information about a function parameter.
///
/// Contains metadata about a parameter including:
/// - The parameter's name
/// - Type
/// - Whether it's required, named, or optional
/// - Default value
/// - Any annotations applied to the parameter
class ParameterInfo {
/// The name of the parameter
final String name;
/// The type of the parameter
final TypeInfo type;
/// Whether this parameter is required
final bool isRequired;
/// Whether this parameter is named
final bool isNamed;
/// Whether this parameter is optional
final bool isOptional;
/// The default value for this parameter, if any
final Object? defaultValue;
/// List of annotations applied to this parameter
final List<Object> annotations;
/// Creates a new [ParameterInfo] instance.
///
/// Required parameters:
/// - [name]: The parameter's name
/// - [type]: The parameter's type
/// - [isRequired]: Whether the parameter is required
/// - [isNamed]: Whether the parameter is named
/// - [isOptional]: Whether the parameter is optional
/// - [annotations]: List of annotations on the parameter
///
/// Optional parameters:
/// - [defaultValue]: The default value for this parameter
const ParameterInfo({
required this.name,
required this.type,
required this.isRequired,
required this.isNamed,
required this.isOptional,
required this.annotations,
this.defaultValue,
});
@override
String toString() {
final buffer = StringBuffer();
if (isNamed) buffer.write(isRequired ? 'required ' : '');
buffer.write('$type $name');
if (defaultValue != null) {
buffer.write(' = $defaultValue');
}
return buffer.toString();
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is ParameterInfo &&
other.name == name &&
other.type == type &&
other.isRequired == isRequired &&
other.isNamed == isNamed &&
other.isOptional == isOptional &&
other.defaultValue == defaultValue &&
_listEquals(other.annotations, annotations);
}
@override
int get hashCode {
return Object.hash(
name,
type,
isRequired,
isNamed,
isOptional,
defaultValue,
Object.hashAll(annotations),
);
}
bool _listEquals<T>(List<T> a, List<T> b) {
if (identical(a, b)) return true;
if (a.length != b.length) return false;
for (var i = 0; i < a.length; i++) {
if (a[i] != b[i]) return false;
}
return true;
}
}

View file

@ -0,0 +1,48 @@
/// Information about a property.
///
/// Contains metadata about a property including:
/// - The property's name
/// - Type
/// - Whether it's final
class PropertyInfo {
/// The name of the property
final String name;
/// The type of the property
final Type type;
/// Whether this property is final
final bool isFinal;
/// Creates a new [PropertyInfo] instance.
///
/// All parameters are required:
/// - [name]: The property's name
/// - [type]: The property's type
/// - [isFinal]: Whether the property is final
const PropertyInfo({
required this.name,
required this.type,
required this.isFinal,
});
@override
String toString() {
final buffer = StringBuffer();
if (isFinal) buffer.write('final ');
buffer.write('$type $name');
return buffer.toString();
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is PropertyInfo &&
other.name == name &&
other.type == type &&
other.isFinal == isFinal;
}
@override
int get hashCode => Object.hash(name, type, isFinal);
}

View file

@ -0,0 +1,70 @@
import 'property_info.dart';
import 'method_info.dart';
import 'constructor_info.dart';
/// Information about a type.
///
/// Contains metadata about a type including:
/// - The type itself
/// - Properties defined on the type
/// - Methods defined on the type
/// - Constructors defined on the type
class TypeInfo {
/// The type being described
final Type type;
/// List of properties defined on this type
final List<PropertyInfo> properties;
/// List of methods defined on this type
final List<MethodInfo> methods;
/// List of constructors defined on this type
final List<ConstructorInfo> constructors;
/// Creates a new [TypeInfo] instance.
///
/// All parameters are required:
/// - [type]: The type being described
/// - [properties]: List of properties defined on the type
/// - [methods]: List of methods defined on the type
/// - [constructors]: List of constructors defined on the type
const TypeInfo({
required this.type,
required this.properties,
required this.methods,
required this.constructors,
});
@override
String toString() => 'TypeInfo(type: $type)';
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is TypeInfo &&
other.type == type &&
_listEquals(other.properties, properties) &&
_listEquals(other.methods, methods) &&
_listEquals(other.constructors, constructors);
}
@override
int get hashCode {
return Object.hash(
type,
Object.hashAll(properties),
Object.hashAll(methods),
Object.hashAll(constructors),
);
}
bool _listEquals<T>(List<T> a, List<T> b) {
if (identical(a, b)) return true;
if (a.length != b.length) return false;
for (var i = 0; i < a.length; i++) {
if (a[i] != b[i]) return false;
}
return true;
}
}

View file

@ -0,0 +1,69 @@
/// Information about a top-level variable.
///
/// Contains metadata about a variable including:
/// - The variable's name
/// - Type
/// - Whether it's final, const, or private
class VariableInfo {
/// The name of the variable
final String name;
/// The type of the variable
final Type type;
/// Whether this variable is final
final bool isFinal;
/// Whether this variable is const
final bool isConst;
/// Whether this variable is private
final bool isPrivate;
/// Creates a new [VariableInfo] instance.
///
/// All parameters are required:
/// - [name]: The variable's name
/// - [type]: The variable's type
/// - [isFinal]: Whether the variable is final
/// - [isConst]: Whether the variable is const
/// - [isPrivate]: Whether the variable is private
const VariableInfo({
required this.name,
required this.type,
required this.isFinal,
required this.isConst,
required this.isPrivate,
});
@override
String toString() {
final buffer = StringBuffer();
if (isConst) buffer.write('const ');
if (isFinal) buffer.write('final ');
buffer.write('$type $name');
return buffer.toString();
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is VariableInfo &&
other.name == name &&
other.type == type &&
other.isFinal == isFinal &&
other.isConst == isConst &&
other.isPrivate == isPrivate;
}
@override
int get hashCode {
return Object.hash(
name,
type,
isFinal,
isConst,
isPrivate,
);
}
}

View file

@ -0,0 +1,86 @@
import 'dart:core';
import 'package:platform_mirrors/mirrors.dart';
/// Runtime scanner that analyzes types and extracts their metadata.
class Scanner {
// Private constructor to prevent instantiation
Scanner._();
// Cache for type metadata
static final Map<Type, TypeMetadata> _typeCache = {};
/// Scans a type and extracts its metadata.
static void scanType(Type type) {
if (_typeCache.containsKey(type)) return;
// First register the type with Reflector
ReflectionRegistry.register(type);
// Get mirror system and analyze type
//final mirrorSystem = MirrorSystem.current();
final typeInfo = TypeAnalyzer.analyze(type);
// Convert properties, methods, and constructors to metadata
final propertyMetadata = <String, PropertyMetadata>{};
final methodMetadata = <String, MethodMetadata>{};
final constructorMetadata = <ConstructorMetadata>[];
// Register properties
for (var property in typeInfo.properties) {
final propertyMeta = PropertyMetadata(
name: property.name,
type: property.type,
isReadable: true,
isWritable: !property.isFinal,
);
propertyMetadata[property.name] = propertyMeta;
ReflectionRegistry.registerPropertyMetadata(
type, property.name, propertyMeta);
}
// Register methods
for (var method in typeInfo.methods) {
final methodMeta = MethodMetadata(
name: method.name,
parameterTypes: method.parameterTypes,
parameters: method.parameters,
returnsVoid: method.returnsVoid,
returnType: method.returnType,
isStatic: method.isStatic,
);
methodMetadata[method.name] = methodMeta;
ReflectionRegistry.registerMethodMetadata(type, method.name, methodMeta);
}
// Register constructors
for (var constructor in typeInfo.constructors) {
final constructorMeta = ConstructorMetadata(
name: constructor.name,
parameterTypes: constructor.parameterTypes,
parameters: constructor.parameters,
);
constructorMetadata.add(constructorMeta);
ReflectionRegistry.registerConstructorMetadata(type, constructorMeta);
}
// Create and cache the metadata
final metadata = TypeMetadata(
type: type,
name: type.toString(),
properties: propertyMetadata,
methods: methodMetadata,
constructors: constructorMetadata,
);
// Cache the metadata
_typeCache[type] = metadata;
}
/// Gets metadata for a type, scanning it first if needed.
static TypeMetadata getTypeMetadata(Type type) {
if (!_typeCache.containsKey(type)) {
scanType(type);
}
return _typeCache[type]!;
}
}

View file

@ -1,88 +1,4 @@
import 'dart:core';
import 'package:platform_reflection/mirrors.dart';
/// Runtime scanner that analyzes types and extracts their metadata.
class Scanner {
// Private constructor to prevent instantiation
Scanner._();
// Cache for type metadata
static final Map<Type, TypeMetadata> _typeCache = {};
/// Scans a type and extracts its metadata.
static void scanType(Type type) {
if (_typeCache.containsKey(type)) return;
// First register the type with Reflector
Reflector.register(type);
// Get mirror system and analyze type
//final mirrorSystem = MirrorSystem.current();
final typeInfo = TypeAnalyzer.analyze(type);
// Convert properties, methods, and constructors to metadata
final propertyMetadata = <String, PropertyMetadata>{};
final methodMetadata = <String, MethodMetadata>{};
final constructorMetadata = <ConstructorMetadata>[];
// Register properties
for (var property in typeInfo.properties) {
final propertyMeta = PropertyMetadata(
name: property.name,
type: property.type,
isReadable: true,
isWritable: !property.isFinal,
);
propertyMetadata[property.name] = propertyMeta;
Reflector.registerPropertyMetadata(type, property.name, propertyMeta);
}
// Register methods
for (var method in typeInfo.methods) {
final methodMeta = MethodMetadata(
name: method.name,
parameterTypes: method.parameterTypes,
parameters: method.parameters,
returnsVoid: method.returnsVoid,
returnType: method.returnType,
isStatic: method.isStatic,
);
methodMetadata[method.name] = methodMeta;
Reflector.registerMethodMetadata(type, method.name, methodMeta);
}
// Register constructors
for (var constructor in typeInfo.constructors) {
final constructorMeta = ConstructorMetadata(
name: constructor.name,
parameterTypes: constructor.parameterTypes,
parameters: constructor.parameters,
);
constructorMetadata.add(constructorMeta);
Reflector.registerConstructorMetadata(type, constructorMeta);
}
// Create and cache the metadata
final metadata = TypeMetadata(
type: type,
name: type.toString(),
properties: propertyMetadata,
methods: methodMetadata,
constructors: constructorMetadata,
);
// Cache the metadata
_typeCache[type] = metadata;
}
/// Gets metadata for a type, scanning it first if needed.
static TypeMetadata getTypeMetadata(Type type) {
if (!_typeCache.containsKey(type)) {
scanType(type);
}
return _typeCache[type]!;
}
}
import 'package:platform_mirrors/mirrors.dart';
/// Analyzes types at runtime to extract their metadata.
class TypeAnalyzer {
@ -325,63 +241,3 @@ class TypeAnalyzer {
);
}
}
/// Information about a type.
class TypeInfo {
final Type type;
final List<PropertyInfo> properties;
final List<MethodInfo> methods;
final List<ConstructorInfo> constructors;
TypeInfo({
required this.type,
required this.properties,
required this.methods,
required this.constructors,
});
}
/// Information about a property.
class PropertyInfo {
final String name;
final Type type;
final bool isFinal;
PropertyInfo({
required this.name,
required this.type,
required this.isFinal,
});
}
/// Information about a method.
class MethodInfo {
final String name;
final List<Type> parameterTypes;
final List<ParameterMetadata> parameters;
final bool returnsVoid;
final Type returnType;
final bool isStatic;
MethodInfo({
required this.name,
required this.parameterTypes,
required this.parameters,
required this.returnsVoid,
required this.returnType,
required this.isStatic,
});
}
/// Information about a constructor.
class ConstructorInfo {
final String name;
final List<Type> parameterTypes;
final List<ParameterMetadata> parameters;
ConstructorInfo({
required this.name,
required this.parameterTypes,
required this.parameters,
});
}

View file

@ -0,0 +1,14 @@
import 'package:platform_mirrors/mirrors.dart';
/// Exception thrown when invalid arguments are provided to a reflective operation.
class InvalidArgumentsException extends ReflectionException {
/// The name of the member being invoked.
final String memberName;
/// The type the member belongs to.
final Type type;
/// Creates a new invalid arguments exception.
const InvalidArgumentsException(this.memberName, this.type)
: super('Invalid arguments for $memberName on type $type');
}

View file

@ -0,0 +1,14 @@
import 'package:platform_mirrors/mirrors.dart';
/// Exception thrown when a member is not found during reflection.
class MemberNotFoundException extends ReflectionException {
/// The name of the member that was not found.
final String memberName;
/// The type the member was looked up on.
final Type type;
/// Creates a new member not found exception.
const MemberNotFoundException(this.memberName, this.type)
: super('Member $memberName not found on type $type');
}

View file

@ -0,0 +1,12 @@
import 'package:platform_mirrors/mirrors.dart';
/// Exception thrown when attempting to reflect on a non-reflectable type.
class NotReflectableException extends ReflectionException {
/// The type that was not reflectable.
final Type type;
/// Creates a new not reflectable exception.
const NotReflectableException(this.type)
: super('Type $type is not reflectable. '
'Make sure it is annotated with @reflectable or registered manually.');
}

View file

@ -0,0 +1,11 @@
/// Base class for all reflection-related exceptions.
class ReflectionException implements Exception {
/// The error message.
final String message;
/// Creates a new reflection exception.
const ReflectionException(this.message);
@override
String toString() => 'ReflectionException: $message';
}

View file

@ -0,0 +1,45 @@
import 'package:platform_mirrors/mirrors.dart';
/// Represents metadata about a type's constructor.
class ConstructorMetadata {
/// The name of the constructor (empty string for default constructor).
final String name;
/// The parameter types of the constructor in order.
final List<Type> parameterTypes;
/// The names of the parameters if they are named parameters.
final List<String>? parameterNames;
/// Detailed metadata about each parameter.
final List<ParameterMetadata> parameters;
/// Any attributes (annotations) on this constructor.
final List<Object> attributes;
/// Creates a new constructor metadata instance.
const ConstructorMetadata({
this.name = '',
required this.parameterTypes,
required this.parameters,
this.parameterNames,
this.attributes = const [],
});
/// Whether this constructor uses named parameters.
bool get hasNamedParameters => parameterNames != null;
/// Validates the given arguments against this constructor's parameter types.
bool validateArguments(List<Object?> arguments) {
if (arguments.length != parameterTypes.length) return false;
for (var i = 0; i < arguments.length; i++) {
final arg = arguments[i];
if (arg != null && arg.runtimeType != parameterTypes[i]) {
return false;
}
}
return true;
}
}

View file

@ -0,0 +1,38 @@
import 'package:platform_mirrors/mirrors.dart';
/// Represents metadata about a function.
class FunctionMetadata {
/// The parameters of the function.
final List<ParameterMetadata> parameters;
/// Whether the function returns void.
final bool returnsVoid;
/// The return type of the function.
final Type returnType;
/// Type parameters for generic functions.
final List<TypeParameterMetadata> typeParameters;
/// Creates a new function metadata instance.
const FunctionMetadata({
required this.parameters,
required this.returnsVoid,
required this.returnType,
this.typeParameters = const [],
});
/// Validates the given arguments against this function's parameters.
bool validateArguments(List<Object?> arguments) {
if (arguments.length != parameters.length) return false;
for (var i = 0; i < arguments.length; i++) {
final arg = arguments[i];
if (arg != null && arg.runtimeType != parameters[i].type) {
return false;
}
}
return true;
}
}

View file

@ -0,0 +1,54 @@
import 'package:platform_mirrors/mirrors.dart';
/// Represents metadata about a type's method.
class MethodMetadata {
/// The name of the method.
final String name;
/// The parameter types of the method in order.
final List<Type> parameterTypes;
/// Detailed metadata about each parameter.
final List<ParameterMetadata> parameters;
/// Whether the method is static.
final bool isStatic;
/// Whether the method returns void.
final bool returnsVoid;
/// The return type of the method.
final Type returnType;
/// Any attributes (annotations) on this method.
final List<Object> attributes;
/// Type parameters for generic methods.
final List<TypeParameterMetadata> typeParameters;
/// Creates a new method metadata instance.
const MethodMetadata({
required this.name,
required this.parameterTypes,
required this.parameters,
required this.returnsVoid,
required this.returnType,
this.isStatic = false,
this.attributes = const [],
this.typeParameters = const [],
});
/// Validates the given arguments against this method's parameter types.
bool validateArguments(List<Object?> arguments) {
if (arguments.length != parameterTypes.length) return false;
for (var i = 0; i < arguments.length; i++) {
final arg = arguments[i];
if (arg != null && arg.runtimeType != parameterTypes[i]) {
return false;
}
}
return true;
}
}

View file

@ -0,0 +1,30 @@
/// Represents metadata about a parameter.
class ParameterMetadata {
/// The name of the parameter.
final String name;
/// The type of the parameter.
final Type type;
/// Whether this parameter is required.
final bool isRequired;
/// Whether this parameter is named.
final bool isNamed;
/// The default value for this parameter, if any.
final Object? defaultValue;
/// Any attributes (annotations) on this parameter.
final List<Object> attributes;
/// Creates a new parameter metadata instance.
const ParameterMetadata({
required this.name,
required this.type,
required this.isRequired,
this.isNamed = false,
this.defaultValue,
this.attributes = const [],
});
}

View file

@ -0,0 +1,26 @@
/// Represents metadata about a type's property.
class PropertyMetadata {
/// The name of the property.
final String name;
/// The type of the property.
final Type type;
/// Whether the property can be read.
final bool isReadable;
/// Whether the property can be written to.
final bool isWritable;
/// Any attributes (annotations) on this property.
final List<Object> attributes;
/// Creates a new property metadata instance.
const PropertyMetadata({
required this.name,
required this.type,
this.isReadable = true,
this.isWritable = true,
this.attributes = const [],
});
}

View file

@ -0,0 +1,96 @@
import 'package:platform_mirrors/mirrors.dart';
/// Represents metadata about a type.
class TypeMetadata {
/// The actual type this metadata represents.
final Type type;
/// The name of the type.
final String name;
/// The properties defined on this type.
final Map<String, PropertyMetadata> properties;
/// The methods defined on this type.
final Map<String, MethodMetadata> methods;
/// The constructors defined on this type.
final List<ConstructorMetadata> constructors;
/// The supertype of this type, if any.
final TypeMetadata? supertype;
/// The interfaces this type implements.
final List<TypeMetadata> interfaces;
/// The mixins this type uses.
final List<TypeMetadata> mixins;
/// Any attributes (annotations) on this type.
final List<Object> attributes;
/// Type parameters for generic types.
final List<TypeParameterMetadata> typeParameters;
/// Type arguments if this is a generic type instantiation.
final List<TypeMetadata> typeArguments;
/// Creates a new type metadata instance.
const TypeMetadata({
required this.type,
required this.name,
required this.properties,
required this.methods,
required this.constructors,
this.supertype,
this.interfaces = const [],
this.mixins = const [],
this.attributes = const [],
this.typeParameters = const [],
this.typeArguments = const [],
});
/// Whether this type is generic (has type parameters).
bool get isGeneric => typeParameters.isNotEmpty;
/// Whether this is a generic type instantiation.
bool get isGenericInstantiation => typeArguments.isNotEmpty;
/// Gets a property by name, throwing if not found.
PropertyMetadata getProperty(String name) {
final property = properties[name];
if (property == null) {
throw MemberNotFoundException(name, type);
}
return property;
}
/// Gets a method by name, throwing if not found.
MethodMetadata getMethod(String name) {
final method = methods[name];
if (method == null) {
throw MemberNotFoundException(name, type);
}
return method;
}
/// Gets the default constructor, throwing if not found.
ConstructorMetadata get defaultConstructor {
return constructors.firstWhere(
(c) => c.name.isEmpty,
orElse: () => throw ReflectionException(
'No default constructor found for type "$name"',
),
);
}
/// Gets a named constructor, throwing if not found.
ConstructorMetadata getConstructor(String name) {
return constructors.firstWhere(
(c) => c.name == name,
orElse: () => throw ReflectionException(
'Constructor "$name" not found for type "$type"',
),
);
}
}

View file

@ -0,0 +1,22 @@
/// Represents metadata about a type parameter.
class TypeParameterMetadata {
/// The name of the type parameter (e.g., 'T', 'E').
final String name;
/// The type of the parameter.
final Type type;
/// The upper bound of the type parameter, if any.
final Type? bound;
/// Any attributes (annotations) on this type parameter.
final List<Object> attributes;
/// Creates a new type parameter metadata instance.
const TypeParameterMetadata({
required this.name,
required this.type,
this.bound,
this.attributes = const [],
});
}

View file

@ -1,5 +1,5 @@
import 'package:platform_contracts/contracts.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
/// Implementation of [ClassMirrorContract].
class ClassMirror extends TypeMirror implements ClassMirrorContract {
@ -69,7 +69,7 @@ class ClassMirror extends TypeMirror implements ClassMirrorContract {
]) {
try {
// Get constructor metadata
final constructors = Reflector.getConstructorMetadata(type);
final constructors = ReflectionRegistry.getConstructorMetadata(type);
if (constructors == null || constructors.isEmpty) {
throw ReflectionException('No constructors found for type $type');
}
@ -101,7 +101,8 @@ class ClassMirror extends TypeMirror implements ClassMirrorContract {
}
// Get instance creator
final creator = Reflector.getInstanceCreator(type, constructorStr);
final creator =
ReflectionRegistry.getInstanceCreator(type, constructorStr);
if (creator == null) {
throw ReflectionException(
'No instance creator found for constructor $constructorStr');
@ -134,7 +135,7 @@ class ClassMirror extends TypeMirror implements ClassMirrorContract {
[Map<Symbol, dynamic>? namedArguments]) {
try {
// Get method metadata
final methods = Reflector.getMethodMetadata(type);
final methods = ReflectionRegistry.getMethodMetadata(type);
if (methods == null ||
!methods.containsKey(_symbolToString(memberName))) {
throw ReflectionException('Method $memberName not found');

View file

@ -1,6 +1,6 @@
import 'dart:core';
import 'package:platform_contracts/contracts.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
/// Implementation of [InstanceMirrorContract] that provides reflection on instances.
class InstanceMirror implements InstanceMirrorContract {
@ -26,7 +26,8 @@ class InstanceMirror implements InstanceMirrorContract {
InstanceMirrorContract invoke(Symbol memberName, List positionalArguments,
[Map<Symbol, dynamic> namedArguments = const {}]) {
// Get method metadata
final methods = Reflector.getMethodMetadata(_reflectee.runtimeType);
final methods =
ReflectionRegistry.getMethodMetadata(_reflectee.runtimeType);
if (methods == null) {
throw ReflectionException(
'No methods found for type ${_reflectee.runtimeType}');
@ -90,7 +91,8 @@ class InstanceMirror implements InstanceMirrorContract {
@override
InstanceMirrorContract getField(Symbol fieldName) {
// Get property metadata
final properties = Reflector.getPropertyMetadata(_reflectee.runtimeType);
final properties =
ReflectionRegistry.getPropertyMetadata(_reflectee.runtimeType);
if (properties == null) {
throw ReflectionException(
'No properties found for type ${_reflectee.runtimeType}');
@ -146,7 +148,8 @@ class InstanceMirror implements InstanceMirrorContract {
@override
InstanceMirrorContract setField(Symbol fieldName, dynamic value) {
// Get property metadata
final properties = Reflector.getPropertyMetadata(_reflectee.runtimeType);
final properties =
ReflectionRegistry.getPropertyMetadata(_reflectee.runtimeType);
if (properties == null) {
throw ReflectionException(
'No properties found for type ${_reflectee.runtimeType}');

View file

@ -1,6 +1,6 @@
import 'dart:core';
import 'package:platform_contracts/contracts.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
/// Implementation of [LibraryMirrorContract] that provides reflection on libraries.
class LibraryMirror extends TypedMirror implements LibraryMirrorContract {

View file

@ -1,5 +1,5 @@
import 'package:platform_contracts/contracts.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
/// Implementation of [MethodMirrorContract] that provides reflection on methods.
class MethodMirror extends TypedMirror implements MethodMirrorContract {

View file

@ -1,6 +1,6 @@
import 'dart:core';
import 'package:platform_contracts/contracts.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
/// Implementation of [ParameterMirrorContract] that provides reflection on parameters.
class ParameterMirror extends MutableOwnerMirror

View file

@ -1,7 +1,7 @@
import 'dart:core';
import 'package:platform_contracts/contracts.dart'
hide PropertyMetadata, MethodMetadata, ConstructorMetadata;
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
/// Implementation of [TypeMirrorContract] that provides reflection on types.
class TypeMirror extends TypedMirror implements TypeMirrorContract {
@ -32,8 +32,8 @@ class TypeMirror extends TypedMirror implements TypeMirrorContract {
metadata: metadata,
) {
// Register type with reflector if not already registered
if (!Reflector.isReflectable(type)) {
Reflector.registerType(type);
if (!ReflectionRegistry.isReflectable(type)) {
ReflectionRegistry.registerType(type);
}
// Validate generic type arguments
@ -164,15 +164,15 @@ class TypeMirror extends TypedMirror implements TypeMirrorContract {
/// Gets the properties defined on this type.
Map<String, PropertyMetadata> get properties =>
Reflector.getPropertyMetadata(type) ?? {};
ReflectionRegistry.getPropertyMetadata(type) ?? {};
/// Gets the methods defined on this type.
Map<String, MethodMetadata> get methods =>
Reflector.getMethodMetadata(type) ?? {};
ReflectionRegistry.getMethodMetadata(type) ?? {};
/// Gets the constructors defined on this type.
List<ConstructorMetadata> get constructors =>
Reflector.getConstructorMetadata(type) ?? [];
ReflectionRegistry.getConstructorMetadata(type) ?? [];
@override
bool isSubtypeOf(TypeMirrorContract other) {
@ -189,7 +189,7 @@ class TypeMirror extends TypedMirror implements TypeMirrorContract {
if (type == voidType) return other.type == voidType;
// Get type metadata
final metadata = Reflector.getTypeMetadata(type);
final metadata = ReflectionRegistry.getTypeMetadata(type);
if (metadata == null) return false;
// Check supertype

View file

@ -1,6 +1,6 @@
import 'package:platform_contracts/contracts.dart'
hide PropertyMetadata, MethodMetadata, ConstructorMetadata;
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
/// Implementation of [TypeVariableMirrorContract] that provides reflection on type variables.
class TypeVariableMirror extends TypedMirror

View file

@ -1,6 +1,6 @@
import 'dart:core';
import 'package:platform_contracts/contracts.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
/// Implementation of [VariableMirrorContract] that provides reflection on variables.
class VariableMirror extends MutableOwnerMirror

View file

@ -1,6 +1,6 @@
import 'dart:isolate' as isolate;
import 'package:platform_contracts/contracts.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
/// A pure runtime reflection system that provides type introspection and manipulation.
class RuntimeReflector {
@ -141,12 +141,12 @@ class RuntimeReflector {
}) {
try {
// Check if type is reflectable
if (!Reflector.isReflectable(type)) {
if (!ReflectionRegistry.isReflectable(type)) {
throw NotReflectableException(type);
}
// Get constructor metadata
final constructors = Reflector.getConstructorMetadata(type);
final constructors = ReflectionRegistry.getConstructorMetadata(type);
if (constructors == null || constructors.isEmpty) {
throw ReflectionException('No constructors found for type $type');
}
@ -159,7 +159,8 @@ class RuntimeReflector {
);
// Get constructor factory
final factory = Reflector.getInstanceCreator(type, constructor.name);
final factory =
ReflectionRegistry.getInstanceCreator(type, constructor.name);
if (factory == null) {
throw ReflectionException(
'No factory found for constructor ${constructor.name} on type $type');
@ -250,7 +251,7 @@ class RuntimeReflector {
}
// Check if type is reflectable
if (!Reflector.isReflectable(type)) {
if (!ReflectionRegistry.isReflectable(type)) {
throw NotReflectableException(type);
}
@ -267,10 +268,10 @@ class RuntimeReflector {
_classMirrorCache[type] = emptyMirror;
// Get metadata from registry
final properties = Reflector.getPropertyMetadata(type) ?? {};
final methods = Reflector.getMethodMetadata(type) ?? {};
final constructors = Reflector.getConstructorMetadata(type) ?? [];
final typeMetadata = Reflector.getTypeMetadata(type);
final properties = ReflectionRegistry.getPropertyMetadata(type) ?? {};
final methods = ReflectionRegistry.getMethodMetadata(type) ?? {};
final constructors = ReflectionRegistry.getConstructorMetadata(type) ?? [];
final typeMetadata = ReflectionRegistry.getTypeMetadata(type);
// Create declarations map
final declarations = <Symbol, DeclarationMirrorContract>{};
@ -390,7 +391,7 @@ class RuntimeReflector {
/// Reflects on a type, returning its type mirror.
TypeMirrorContract reflectType(Type type) {
// Check if type is reflectable
if (!Reflector.isReflectable(type)) {
if (!ReflectionRegistry.isReflectable(type)) {
throw NotReflectableException(type);
}
@ -400,7 +401,7 @@ class RuntimeReflector {
/// Creates a new instance reflector for the given object.
InstanceMirrorContract reflect(Object instance) {
// Check if type is reflectable
if (!Reflector.isReflectable(instance.runtimeType)) {
if (!ReflectionRegistry.isReflectable(instance.runtimeType)) {
throw NotReflectableException(instance.runtimeType);
}

View file

@ -1,10 +1,10 @@
import 'dart:collection';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
/// Static registry for reflection metadata.
class Reflector {
class ReflectionRegistry {
// Private constructor to prevent instantiation
Reflector._();
ReflectionRegistry._();
// Type metadata storage
static final Map<Type, Map<String, PropertyMetadata>> _propertyMetadata =

View file

@ -1,4 +1,4 @@
name: platform_reflection
name: platform_mirrors
description: A lightweight, cross-platform reflection system for Dart
version: 0.1.0
publish_to: none

View file

@ -1,5 +1,5 @@
import 'dart:isolate';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
import 'package:test/test.dart';
// Function to run in isolate

View file

@ -1,5 +1,5 @@
import 'package:platform_contracts/contracts.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
import 'package:test/test.dart';
// Top-level function for testing

View file

@ -1,5 +1,5 @@
import 'package:platform_contracts/contracts.dart' hide PropertyMetadata;
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
import 'package:test/test.dart';
@reflectable
@ -18,8 +18,8 @@ void main() {
mirrorSystem = MirrorSystem.instance;
// Register test class
Reflector.registerType(TestClass);
Reflector.registerPropertyMetadata(
ReflectionRegistry.registerType(TestClass);
ReflectionRegistry.registerPropertyMetadata(
TestClass,
'name',
PropertyMetadata(

View file

@ -1,5 +1,5 @@
import 'package:platform_contracts/contracts.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
import 'package:test/test.dart';
@reflectable
@ -27,18 +27,18 @@ void main() {
setUp(() {
reflector = RuntimeReflector.instance;
Reflector.reset();
ReflectionRegistry.reset();
});
group('Type Reflection', () {
test('reflectType returns correct type metadata', () {
Reflector.register(Person);
ReflectionRegistry.register(Person);
final mirror = reflector.reflectType(Person);
expect(mirror.simpleName.toString(), contains('Person'));
});
test('reflect creates instance mirror', () {
Reflector.register(Person);
ReflectionRegistry.register(Person);
final person = Person('John', 30);
final mirror = reflector.reflect(person);
expect(mirror.reflectee, equals(person));
@ -57,9 +57,10 @@ void main() {
late InstanceMirrorContract mirror;
setUp(() {
Reflector.register(Person);
Reflector.registerProperty(Person, 'name', String);
Reflector.registerProperty(Person, 'age', int, isWritable: false);
ReflectionRegistry.register(Person);
ReflectionRegistry.registerProperty(Person, 'name', String);
ReflectionRegistry.registerProperty(Person, 'age', int,
isWritable: false);
person = Person('John', 30);
mirror = reflector.reflect(person);
@ -94,8 +95,8 @@ void main() {
late InstanceMirrorContract mirror;
setUp(() {
Reflector.register(Person);
Reflector.registerMethod(
ReflectionRegistry.register(Person);
ReflectionRegistry.registerMethod(
Person,
'greet',
[String],
@ -123,15 +124,15 @@ void main() {
group('Constructor Invocation', () {
setUp(() {
Reflector.register(Person);
Reflector.registerConstructor(
ReflectionRegistry.register(Person);
ReflectionRegistry.registerConstructor(
Person,
'',
parameterTypes: [String, int],
parameterNames: ['name', 'age'],
creator: (String name, int age) => Person(name, age),
);
Reflector.registerConstructor(
ReflectionRegistry.registerConstructor(
Person,
'guest',
creator: () => Person.guest(),

View file

@ -1,4 +1,4 @@
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
import 'package:test/test.dart';
@reflectable
@ -64,21 +64,22 @@ class ChildTestClass extends ParentTestClass {
void main() {
group('Scanner', () {
setUp(() {
Reflector.reset();
ReflectionRegistry.reset();
});
test('scans properties correctly', () {
// Register base metadata
Reflector.register(TestClass);
Reflector.registerProperty(TestClass, 'name', String);
Reflector.registerProperty(TestClass, 'id', int, isWritable: false);
Reflector.registerProperty(TestClass, 'tags', List<String>);
Reflector.registerProperty(TestClass, 'version', String,
ReflectionRegistry.register(TestClass);
ReflectionRegistry.registerProperty(TestClass, 'name', String);
ReflectionRegistry.registerProperty(TestClass, 'id', int,
isWritable: false);
ReflectionRegistry.registerProperty(TestClass, 'tags', List<String>);
ReflectionRegistry.registerProperty(TestClass, 'version', String,
isWritable: false);
// Scan type
Scanner.scanType(TestClass);
final metadata = Reflector.getPropertyMetadata(TestClass);
final metadata = ReflectionRegistry.getPropertyMetadata(TestClass);
expect(metadata, isNotNull);
expect(metadata!['name'], isNotNull);
@ -100,8 +101,8 @@ void main() {
test('scans methods correctly', () {
// Register base metadata
Reflector.register(TestClass);
Reflector.registerMethod(
ReflectionRegistry.register(TestClass);
ReflectionRegistry.registerMethod(
TestClass,
'addTag',
[String],
@ -109,7 +110,7 @@ void main() {
parameterNames: ['tag'],
isRequired: [true],
);
Reflector.registerMethod(
ReflectionRegistry.registerMethod(
TestClass,
'greet',
[String],
@ -117,7 +118,7 @@ void main() {
parameterNames: ['greeting'],
isRequired: [false],
);
Reflector.registerMethod(
ReflectionRegistry.registerMethod(
TestClass,
'create',
[String, int],
@ -130,7 +131,7 @@ void main() {
// Scan type
Scanner.scanType(TestClass);
final metadata = Reflector.getMethodMetadata(TestClass);
final metadata = ReflectionRegistry.getMethodMetadata(TestClass);
expect(metadata, isNotNull);
@ -171,8 +172,8 @@ void main() {
test('scans constructors correctly', () {
// Register base metadata
Reflector.register(TestClass);
Reflector.registerConstructor(
ReflectionRegistry.register(TestClass);
ReflectionRegistry.registerConstructor(
TestClass,
'',
parameterTypes: [String, int, List<String>],
@ -180,14 +181,14 @@ void main() {
isRequired: [true, true, false],
isNamed: [false, true, true],
);
Reflector.registerConstructor(
ReflectionRegistry.registerConstructor(
TestClass,
'guest',
);
// Scan type
Scanner.scanType(TestClass);
final metadata = Reflector.getConstructorMetadata(TestClass);
final metadata = ReflectionRegistry.getConstructorMetadata(TestClass);
expect(metadata, isNotNull);
expect(metadata!.length, equals(2));
@ -216,11 +217,12 @@ void main() {
test('scanned type works with reflection', () {
// Register base metadata
Reflector.register(TestClass);
Reflector.registerProperty(TestClass, 'name', String);
Reflector.registerProperty(TestClass, 'id', int, isWritable: false);
Reflector.registerProperty(TestClass, 'tags', List<String>);
Reflector.registerMethod(
ReflectionRegistry.register(TestClass);
ReflectionRegistry.registerProperty(TestClass, 'name', String);
ReflectionRegistry.registerProperty(TestClass, 'id', int,
isWritable: false);
ReflectionRegistry.registerProperty(TestClass, 'tags', List<String>);
ReflectionRegistry.registerMethod(
TestClass,
'addTag',
[String],
@ -228,7 +230,7 @@ void main() {
parameterNames: ['tag'],
isRequired: [true],
);
Reflector.registerMethod(
ReflectionRegistry.registerMethod(
TestClass,
'greet',
[String],
@ -236,7 +238,7 @@ void main() {
parameterNames: ['greeting'],
isRequired: [false],
);
Reflector.registerConstructor(
ReflectionRegistry.registerConstructor(
TestClass,
'',
parameterTypes: [String, int, List<String>],
@ -246,7 +248,7 @@ void main() {
creator: (String name, {required int id, List<String>? tags}) =>
TestClass(name, id: id, tags: tags),
);
Reflector.registerConstructor(
ReflectionRegistry.registerConstructor(
TestClass,
'guest',
creator: () => TestClass.guest(),
@ -299,10 +301,10 @@ void main() {
test('handles generic types correctly', () {
// Register base metadata
Reflector.register(GenericTestClass);
Reflector.registerProperty(GenericTestClass, 'value', dynamic);
Reflector.registerProperty(GenericTestClass, 'items', List);
Reflector.registerMethod(
ReflectionRegistry.register(GenericTestClass);
ReflectionRegistry.registerProperty(GenericTestClass, 'value', dynamic);
ReflectionRegistry.registerProperty(GenericTestClass, 'items', List);
ReflectionRegistry.registerMethod(
GenericTestClass,
'addItem',
[dynamic],
@ -310,7 +312,7 @@ void main() {
parameterNames: ['item'],
isRequired: [true],
);
Reflector.registerMethod(
ReflectionRegistry.registerMethod(
GenericTestClass,
'getValue',
[],
@ -319,14 +321,14 @@ void main() {
// Scan type
Scanner.scanType(GenericTestClass);
final metadata = Reflector.getPropertyMetadata(GenericTestClass);
final metadata = ReflectionRegistry.getPropertyMetadata(GenericTestClass);
expect(metadata, isNotNull);
expect(metadata!['value'], isNotNull);
expect(metadata['items'], isNotNull);
expect(metadata['items']!.type, equals(List));
final methodMeta = Reflector.getMethodMetadata(GenericTestClass);
final methodMeta = ReflectionRegistry.getMethodMetadata(GenericTestClass);
expect(methodMeta, isNotNull);
expect(methodMeta!['addItem'], isNotNull);
expect(methodMeta['getValue'], isNotNull);
@ -334,24 +336,24 @@ void main() {
test('handles inheritance correctly', () {
// Register base metadata
Reflector.register(ParentTestClass);
Reflector.register(ChildTestClass);
Reflector.registerProperty(ParentTestClass, 'name', String);
Reflector.registerProperty(ChildTestClass, 'name', String);
Reflector.registerProperty(ChildTestClass, 'age', int);
Reflector.registerMethod(
ReflectionRegistry.register(ParentTestClass);
ReflectionRegistry.register(ChildTestClass);
ReflectionRegistry.registerProperty(ParentTestClass, 'name', String);
ReflectionRegistry.registerProperty(ChildTestClass, 'name', String);
ReflectionRegistry.registerProperty(ChildTestClass, 'age', int);
ReflectionRegistry.registerMethod(
ParentTestClass,
'getName',
[],
false,
);
Reflector.registerMethod(
ReflectionRegistry.registerMethod(
ChildTestClass,
'getName',
[],
false,
);
Reflector.registerConstructor(
ReflectionRegistry.registerConstructor(
ChildTestClass,
'',
parameterTypes: [String, int],
@ -365,8 +367,9 @@ void main() {
Scanner.scanType(ParentTestClass);
Scanner.scanType(ChildTestClass);
final parentMeta = Reflector.getPropertyMetadata(ParentTestClass);
final childMeta = Reflector.getPropertyMetadata(ChildTestClass);
final parentMeta =
ReflectionRegistry.getPropertyMetadata(ParentTestClass);
final childMeta = ReflectionRegistry.getPropertyMetadata(ChildTestClass);
expect(parentMeta, isNotNull);
expect(parentMeta!['name'], isNotNull);

View file

@ -1,127 +0,0 @@
import 'package:platform_reflection/mirrors.dart';
/// Registry of reflectable types and their metadata.
class ReflectionRegistry {
/// Map of type to its property metadata
static final _properties = <Type, Map<String, PropertyMetadata>>{};
/// Map of type to its method metadata
static final _methods = <Type, Map<String, MethodMetadata>>{};
/// Map of type to its constructor metadata
static final _constructors = <Type, List<ConstructorMetadata>>{};
/// Map of type to its constructor factories
static final _constructorFactories = <Type, Map<String, Function>>{};
/// Registers a type as reflectable
static void registerType(Type type) {
_properties[type] = {};
_methods[type] = {};
_constructors[type] = [];
_constructorFactories[type] = {};
}
/// Registers a property for a type
static void registerProperty(
Type type,
String name,
Type propertyType, {
bool isReadable = true,
bool isWritable = true,
}) {
_properties[type]![name] = PropertyMetadata(
name: name,
type: propertyType,
isReadable: isReadable,
isWritable: isWritable,
);
}
/// Registers a method for a type
static void registerMethod(
Type type,
String name,
List<Type> parameterTypes,
bool returnsVoid,
Type returnType, {
List<String>? parameterNames,
List<bool>? isRequired,
List<bool>? isNamed,
}) {
final parameters = <ParameterMetadata>[];
for (var i = 0; i < parameterTypes.length; i++) {
parameters.add(ParameterMetadata(
name: parameterNames?[i] ?? 'param$i',
type: parameterTypes[i],
isRequired: isRequired?[i] ?? true,
isNamed: isNamed?[i] ?? false,
));
}
_methods[type]![name] = MethodMetadata(
name: name,
parameterTypes: parameterTypes,
parameters: parameters,
returnsVoid: returnsVoid,
returnType: returnType,
isStatic: false,
);
}
/// Registers a constructor for a type
static void registerConstructor(
Type type,
String name,
Function factory, {
List<Type>? parameterTypes,
List<String>? parameterNames,
List<bool>? isRequired,
List<bool>? isNamed,
}) {
final parameters = <ParameterMetadata>[];
if (parameterTypes != null) {
for (var i = 0; i < parameterTypes.length; i++) {
parameters.add(ParameterMetadata(
name: parameterNames?[i] ?? 'param$i',
type: parameterTypes[i],
isRequired: isRequired?[i] ?? true,
isNamed: isNamed?[i] ?? false,
));
}
}
_constructors[type]!.add(ConstructorMetadata(
name: name,
parameterTypes: parameterTypes ?? [],
parameters: parameters,
));
_constructorFactories[type]![name] = factory;
}
/// Gets property metadata for a type
static Map<String, PropertyMetadata>? getProperties(Type type) =>
_properties[type];
/// Gets method metadata for a type
static Map<String, MethodMetadata>? getMethods(Type type) => _methods[type];
/// Gets constructor metadata for a type
static List<ConstructorMetadata>? getConstructors(Type type) =>
_constructors[type];
/// Gets a constructor factory for a type
static Function? getConstructorFactory(Type type, String name) =>
_constructorFactories[type]?[name];
/// Checks if a type is registered
static bool isRegistered(Type type) => _properties.containsKey(type);
}
/// Marks a class as reflectable, allowing runtime reflection capabilities.
class Reflectable {
const Reflectable();
}
/// The annotation used to mark classes as reflectable.
const reflectable = Reflectable();

View file

@ -1,48 +0,0 @@
/// Base class for all reflection-related exceptions.
class ReflectionException implements Exception {
/// The error message.
final String message;
/// Creates a new reflection exception.
const ReflectionException(this.message);
@override
String toString() => 'ReflectionException: $message';
}
/// Exception thrown when attempting to reflect on a non-reflectable type.
class NotReflectableException extends ReflectionException {
/// The type that was not reflectable.
final Type type;
/// Creates a new not reflectable exception.
const NotReflectableException(this.type)
: super('Type $type is not reflectable. '
'Make sure it is annotated with @reflectable or registered manually.');
}
/// Exception thrown when invalid arguments are provided to a reflective operation.
class InvalidArgumentsException extends ReflectionException {
/// The name of the member being invoked.
final String memberName;
/// The type the member belongs to.
final Type type;
/// Creates a new invalid arguments exception.
const InvalidArgumentsException(this.memberName, this.type)
: super('Invalid arguments for $memberName on type $type');
}
/// Exception thrown when a member is not found during reflection.
class MemberNotFoundException extends ReflectionException {
/// The name of the member that was not found.
final String memberName;
/// The type the member was looked up on.
final Type type;
/// Creates a new member not found exception.
const MemberNotFoundException(this.memberName, this.type)
: super('Member $memberName not found on type $type');
}

View file

@ -1,311 +0,0 @@
import 'package:platform_reflection/mirrors.dart';
/// Represents metadata about a type parameter.
class TypeParameterMetadata {
/// The name of the type parameter (e.g., 'T', 'E').
final String name;
/// The type of the parameter.
final Type type;
/// The upper bound of the type parameter, if any.
final Type? bound;
/// Any attributes (annotations) on this type parameter.
final List<Object> attributes;
/// Creates a new type parameter metadata instance.
const TypeParameterMetadata({
required this.name,
required this.type,
this.bound,
this.attributes = const [],
});
}
/// Represents metadata about a parameter.
class ParameterMetadata {
/// The name of the parameter.
final String name;
/// The type of the parameter.
final Type type;
/// Whether this parameter is required.
final bool isRequired;
/// Whether this parameter is named.
final bool isNamed;
/// The default value for this parameter, if any.
final Object? defaultValue;
/// Any attributes (annotations) on this parameter.
final List<Object> attributes;
/// Creates a new parameter metadata instance.
const ParameterMetadata({
required this.name,
required this.type,
required this.isRequired,
this.isNamed = false,
this.defaultValue,
this.attributes = const [],
});
}
/// Represents metadata about a type's property.
class PropertyMetadata {
/// The name of the property.
final String name;
/// The type of the property.
final Type type;
/// Whether the property can be read.
final bool isReadable;
/// Whether the property can be written to.
final bool isWritable;
/// Any attributes (annotations) on this property.
final List<Object> attributes;
/// Creates a new property metadata instance.
const PropertyMetadata({
required this.name,
required this.type,
this.isReadable = true,
this.isWritable = true,
this.attributes = const [],
});
}
/// Represents metadata about a type's method.
class MethodMetadata {
/// The name of the method.
final String name;
/// The parameter types of the method in order.
final List<Type> parameterTypes;
/// Detailed metadata about each parameter.
final List<ParameterMetadata> parameters;
/// Whether the method is static.
final bool isStatic;
/// Whether the method returns void.
final bool returnsVoid;
/// The return type of the method.
final Type returnType;
/// Any attributes (annotations) on this method.
final List<Object> attributes;
/// Type parameters for generic methods.
final List<TypeParameterMetadata> typeParameters;
/// Creates a new method metadata instance.
const MethodMetadata({
required this.name,
required this.parameterTypes,
required this.parameters,
required this.returnsVoid,
required this.returnType,
this.isStatic = false,
this.attributes = const [],
this.typeParameters = const [],
});
/// Validates the given arguments against this method's parameter types.
bool validateArguments(List<Object?> arguments) {
if (arguments.length != parameterTypes.length) return false;
for (var i = 0; i < arguments.length; i++) {
final arg = arguments[i];
if (arg != null && arg.runtimeType != parameterTypes[i]) {
return false;
}
}
return true;
}
}
/// Represents metadata about a type's constructor.
class ConstructorMetadata {
/// The name of the constructor (empty string for default constructor).
final String name;
/// The parameter types of the constructor in order.
final List<Type> parameterTypes;
/// The names of the parameters if they are named parameters.
final List<String>? parameterNames;
/// Detailed metadata about each parameter.
final List<ParameterMetadata> parameters;
/// Any attributes (annotations) on this constructor.
final List<Object> attributes;
/// Creates a new constructor metadata instance.
const ConstructorMetadata({
this.name = '',
required this.parameterTypes,
required this.parameters,
this.parameterNames,
this.attributes = const [],
});
/// Whether this constructor uses named parameters.
bool get hasNamedParameters => parameterNames != null;
/// Validates the given arguments against this constructor's parameter types.
bool validateArguments(List<Object?> arguments) {
if (arguments.length != parameterTypes.length) return false;
for (var i = 0; i < arguments.length; i++) {
final arg = arguments[i];
if (arg != null && arg.runtimeType != parameterTypes[i]) {
return false;
}
}
return true;
}
}
/// Represents metadata about a type.
class TypeMetadata {
/// The actual type this metadata represents.
final Type type;
/// The name of the type.
final String name;
/// The properties defined on this type.
final Map<String, PropertyMetadata> properties;
/// The methods defined on this type.
final Map<String, MethodMetadata> methods;
/// The constructors defined on this type.
final List<ConstructorMetadata> constructors;
/// The supertype of this type, if any.
final TypeMetadata? supertype;
/// The interfaces this type implements.
final List<TypeMetadata> interfaces;
/// The mixins this type uses.
final List<TypeMetadata> mixins;
/// Any attributes (annotations) on this type.
final List<Object> attributes;
/// Type parameters for generic types.
final List<TypeParameterMetadata> typeParameters;
/// Type arguments if this is a generic type instantiation.
final List<TypeMetadata> typeArguments;
/// Creates a new type metadata instance.
const TypeMetadata({
required this.type,
required this.name,
required this.properties,
required this.methods,
required this.constructors,
this.supertype,
this.interfaces = const [],
this.mixins = const [],
this.attributes = const [],
this.typeParameters = const [],
this.typeArguments = const [],
});
/// Whether this type is generic (has type parameters).
bool get isGeneric => typeParameters.isNotEmpty;
/// Whether this is a generic type instantiation.
bool get isGenericInstantiation => typeArguments.isNotEmpty;
/// Gets a property by name, throwing if not found.
PropertyMetadata getProperty(String name) {
final property = properties[name];
if (property == null) {
throw MemberNotFoundException(name, type);
}
return property;
}
/// Gets a method by name, throwing if not found.
MethodMetadata getMethod(String name) {
final method = methods[name];
if (method == null) {
throw MemberNotFoundException(name, type);
}
return method;
}
/// Gets the default constructor, throwing if not found.
ConstructorMetadata get defaultConstructor {
return constructors.firstWhere(
(c) => c.name.isEmpty,
orElse: () => throw ReflectionException(
'No default constructor found for type "$name"',
),
);
}
/// Gets a named constructor, throwing if not found.
ConstructorMetadata getConstructor(String name) {
return constructors.firstWhere(
(c) => c.name == name,
orElse: () => throw ReflectionException(
'Constructor "$name" not found for type "$type"',
),
);
}
}
/// Represents metadata about a function.
class FunctionMetadata {
/// The parameters of the function.
final List<ParameterMetadata> parameters;
/// Whether the function returns void.
final bool returnsVoid;
/// The return type of the function.
final Type returnType;
/// Type parameters for generic functions.
final List<TypeParameterMetadata> typeParameters;
/// Creates a new function metadata instance.
const FunctionMetadata({
required this.parameters,
required this.returnsVoid,
required this.returnType,
this.typeParameters = const [],
});
/// Validates the given arguments against this function's parameters.
bool validateArguments(List<Object?> arguments) {
if (arguments.length != parameters.length) return false;
for (var i = 0; i < arguments.length; i++) {
final arg = arguments[i];
if (arg != null && arg.runtimeType != parameters[i].type) {
return false;
}
}
return true;
}
}

View file

@ -1,5 +1,5 @@
import 'package:platform_macroable/platform_macroable.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
/// Provides higher-order tap functionality with macro support.
///
@ -33,7 +33,7 @@ class HigherOrderTapProxy<T extends Object> with Macroable {
return super.noSuchMethod(invocation);
} catch (_) {
// If not a macro, forward to target
final methods = Reflector.getMethodMetadata(_target.runtimeType);
final methods = ReflectionRegistry.getMethodMetadata(_target.runtimeType);
if (methods == null) {
throw NoSuchMethodError.withInvocation(_target, invocation);
}

View file

@ -1,5 +1,5 @@
import 'once.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
/// A class that provides functionality to ensure methods are only executed once.
///
@ -25,9 +25,9 @@ class Onceable {
// If not executed yet, register the callback type
if (!_once[key]!.executed &&
!Reflector.isReflectable(callback.runtimeType)) {
Reflector.register(callback.runtimeType);
Reflector.registerMethod(
!ReflectionRegistry.isReflectable(callback.runtimeType)) {
ReflectionRegistry.register(callback.runtimeType);
ReflectionRegistry.registerMethod(
callback.runtimeType,
'call',
const <Type>[],

View file

@ -1,5 +1,5 @@
import 'package:platform_macroable/platform_macroable.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
/// Provides Laravel-like Optional type functionality with macro support.
///
@ -46,7 +46,8 @@ class Optional<T> with Macroable {
final instance = reflector.reflect(_value!);
if (instance != null) {
final type = instance.type;
final metadata = Reflector.getPropertyMetadata(type.reflectedType);
final metadata =
ReflectionRegistry.getPropertyMetadata(type.reflectedType);
if (metadata != null && metadata.containsKey(key)) {
// Access property through dynamic dispatch
@ -89,7 +90,8 @@ class Optional<T> with Macroable {
final instance = reflector.reflect(_value!);
if (instance != null) {
final type = instance.type;
final metadata = Reflector.getPropertyMetadata(type.reflectedType);
final metadata =
ReflectionRegistry.getPropertyMetadata(type.reflectedType);
return metadata != null && metadata.containsKey(key);
}
} catch (_) {

View file

@ -1,5 +1,5 @@
import 'package:platform_contracts/contracts.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
/// Provides reflection utilities for examining types and methods at runtime.
class SupportReflector {
@ -28,12 +28,12 @@ class SupportReflector {
final targetType = target is Type ? target : target.runtimeType;
// Check if type is registered for reflection
if (!Reflector.isReflectable(targetType)) {
if (!ReflectionRegistry.isReflectable(targetType)) {
return false;
}
// Check for regular method
final methods = Reflector.getMethodMetadata(targetType);
final methods = ReflectionRegistry.getMethodMetadata(targetType);
if (methods != null) {
// If the method is private, return false
if (methodName.startsWith('_')) {
@ -157,12 +157,12 @@ class SupportReflector {
final reflectedType = type.reflectedType;
// Check if it's registered for reflection
if (!Reflector.isReflectable(reflectedType)) {
if (!ReflectionRegistry.isReflectable(reflectedType)) {
return false;
}
// Get the property metadata
final properties = Reflector.getPropertyMetadata(reflectedType);
final properties = ReflectionRegistry.getPropertyMetadata(reflectedType);
if (properties == null) {
return false;
}

View file

@ -1,5 +1,5 @@
import 'package:meta/meta.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
/// A mixin that provides method forwarding functionality.
///
@ -38,7 +38,7 @@ mixin ForwardsCalls {
}
// Get method metadata
final methods = Reflector.getMethodMetadata(object.runtimeType);
final methods = ReflectionRegistry.getMethodMetadata(object.runtimeType);
if (methods == null || !methods.containsKey(method)) {
throwBadMethodCallException(method);
}

View file

@ -1,11 +1,12 @@
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
/// A trait that provides functionality to reflect on closures.
mixin ReflectsClosures {
/// Get the number of parameters that a closure accepts.
int getClosureParameterCount(Function closure) {
try {
final metadata = Reflector.getMethodMetadata(closure.runtimeType);
final metadata =
ReflectionRegistry.getMethodMetadata(closure.runtimeType);
if (metadata == null || !metadata.containsKey('call')) {
return 0;
}
@ -19,7 +20,8 @@ mixin ReflectsClosures {
/// Get the parameter names of a closure.
List<String> getClosureParameterNames(Function closure) {
try {
final metadata = Reflector.getMethodMetadata(closure.runtimeType);
final metadata =
ReflectionRegistry.getMethodMetadata(closure.runtimeType);
if (metadata == null || !metadata.containsKey('call')) {
return [];
}
@ -33,7 +35,8 @@ mixin ReflectsClosures {
/// Get the parameter types of a closure.
List<Type> getClosureParameterTypes(Function closure) {
try {
final metadata = Reflector.getMethodMetadata(closure.runtimeType);
final metadata =
ReflectionRegistry.getMethodMetadata(closure.runtimeType);
if (metadata == null || !metadata.containsKey('call')) {
return [];
}
@ -52,7 +55,8 @@ mixin ReflectsClosures {
/// Determine if a closure returns void.
bool isClosureVoid(Function closure) {
try {
final metadata = Reflector.getMethodMetadata(closure.runtimeType);
final metadata =
ReflectionRegistry.getMethodMetadata(closure.runtimeType);
if (metadata == null || !metadata.containsKey('call')) {
return false;
}
@ -66,7 +70,8 @@ mixin ReflectsClosures {
/// Determine if a closure is nullable.
bool isClosureNullable(Function closure) {
try {
final metadata = Reflector.getMethodMetadata(closure.runtimeType);
final metadata =
ReflectionRegistry.getMethodMetadata(closure.runtimeType);
if (metadata == null || !metadata.containsKey('call')) {
return true;
}
@ -89,7 +94,8 @@ mixin ReflectsClosures {
}
// Also check if it's marked as async in the metadata
final metadata = Reflector.getMethodMetadata(closure.runtimeType);
final metadata =
ReflectionRegistry.getMethodMetadata(closure.runtimeType);
if (metadata == null || !metadata.containsKey('call')) {
return false;
}

View file

@ -20,7 +20,7 @@ dependencies:
platform_conditionable: ^1.0.0
platform_contracts: ^1.0.0
platform_macroable: ^1.0.0
platform_reflection: ^1.0.0
platform_mirrors: ^1.0.0

View file

@ -1,5 +1,5 @@
import 'package:test/test.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
import 'package:platform_support/platform_support.dart';
void main() {
@ -10,7 +10,7 @@ void main() {
});
tearDown(() {
Reflector.reset();
ReflectionRegistry.reset();
});
group('Onceable', () {

View file

@ -1,6 +1,6 @@
import 'package:test/test.dart';
import 'package:platform_support/platform_support.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
@reflectable
class TargetClass {
@ -32,18 +32,18 @@ void main() {
setUp(() {
// Register classes for reflection
Reflector.reset();
Reflector.register(TargetClass);
ReflectionRegistry.reset();
ReflectionRegistry.register(TargetClass);
// Register methods
Reflector.registerMethod(
ReflectionRegistry.registerMethod(
TargetClass,
'getValue',
[/* no parameters */],
false, // not void
);
Reflector.registerMethod(
ReflectionRegistry.registerMethod(
TargetClass,
'setValue',
[String],
@ -52,14 +52,14 @@ void main() {
isRequired: [true],
);
Reflector.registerMethod(
ReflectionRegistry.registerMethod(
TargetClass,
'chainedMethod',
[/* no parameters */],
false, // not void
);
Reflector.registerMethod(
ReflectionRegistry.registerMethod(
TargetClass,
'throwingMethod',
[/* no parameters */],

View file

@ -1,6 +1,6 @@
import 'package:test/test.dart';
import 'package:platform_support/platform_support.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
@reflectable
class TestObject {
@ -13,16 +13,16 @@ void main() {
setUp(() {
reflector = RuntimeReflector.instance;
Reflector.reset();
ReflectionRegistry.reset();
// Register TestObject for reflection
Reflector.register(TestObject);
ReflectionRegistry.register(TestObject);
// Register property
Reflector.registerProperty(TestObject, 'item', String);
ReflectionRegistry.registerProperty(TestObject, 'item', String);
// Register constructors
Reflector.registerConstructor(
ReflectionRegistry.registerConstructor(
TestObject,
'',
parameterTypes: [String],

View file

@ -1,6 +1,6 @@
import 'package:test/test.dart';
import 'package:platform_contracts/contracts.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
import 'package:platform_support/platform_support.dart';
class TestClass {
@ -106,8 +106,8 @@ void main() {
testClassMirror.declarations[Symbol('noSuchMethod')] = noSuchMethodMirror;
// Register test classes
Reflector.register(TestClass);
Reflector.registerMethod(
ReflectionRegistry.register(TestClass);
ReflectionRegistry.registerMethod(
TestClass,
'publicMethod',
[TestClass],
@ -117,7 +117,7 @@ void main() {
isNamed: [false],
isStatic: false,
);
Reflector.registerMethod(
ReflectionRegistry.registerMethod(
TestClass,
'_privateMethod',
[TestClass],
@ -127,7 +127,7 @@ void main() {
isNamed: [false],
isStatic: false,
);
Reflector.registerMethod(
ReflectionRegistry.registerMethod(
TestClass,
'noSuchMethod',
[Invocation],
@ -139,20 +139,20 @@ void main() {
);
// Register enums
Reflector.register(SimpleEnum);
Reflector.registerProperty(
ReflectionRegistry.register(SimpleEnum);
ReflectionRegistry.registerProperty(
SimpleEnum,
'values',
List<SimpleEnum>,
);
Reflector.register(BackedEnum);
Reflector.registerProperty(
ReflectionRegistry.register(BackedEnum);
ReflectionRegistry.registerProperty(
BackedEnum,
'values',
List<BackedEnum>,
);
Reflector.registerProperty(
ReflectionRegistry.registerProperty(
BackedEnum,
'name',
String,
@ -162,7 +162,7 @@ void main() {
});
tearDown(() {
Reflector.reset();
ReflectionRegistry.reset();
});
group('SupportReflector', () {

View file

@ -1,6 +1,6 @@
import 'package:test/test.dart';
import 'package:platform_support/platform_support.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
@reflectable
class TappableTest with Tappable {
@ -34,11 +34,11 @@ void main() {
instance = TappableTest();
// Register class and methods for reflection
Reflector.reset();
Reflector.register(TappableTest);
ReflectionRegistry.reset();
ReflectionRegistry.register(TappableTest);
// Register setValue method
Reflector.registerMethod(
ReflectionRegistry.registerMethod(
TappableTest,
'setValue',
[String],
@ -48,7 +48,7 @@ void main() {
);
// Register getValue method
Reflector.registerMethod(
ReflectionRegistry.registerMethod(
TappableTest,
'getValue',
[],
@ -56,7 +56,7 @@ void main() {
);
// Register tap method
Reflector.registerMethod(
ReflectionRegistry.registerMethod(
TappableTest,
'tap',
[Function],

View file

@ -1,5 +1,5 @@
import 'package:test/test.dart';
import 'package:platform_reflection/mirrors.dart';
import 'package:platform_mirrors/mirrors.dart';
import 'package:platform_support/src/traits/reflects_closures.dart';
class TestClass with ReflectsClosures {}
@ -16,13 +16,13 @@ void main() {
testClass = TestClass();
// Register function types
Reflector.register(StringIntFunction);
Reflector.register(VoidFunction);
Reflector.register(AsyncVoidFunction);
Reflector.register(IntFunction);
ReflectionRegistry.register(StringIntFunction);
ReflectionRegistry.register(VoidFunction);
ReflectionRegistry.register(AsyncVoidFunction);
ReflectionRegistry.register(IntFunction);
// Register method metadata for each function type
Reflector.registerMethod(
ReflectionRegistry.registerMethod(
StringIntFunction,
'call',
[String, int],
@ -32,21 +32,21 @@ void main() {
isNamed: [false, false],
);
Reflector.registerMethod(
ReflectionRegistry.registerMethod(
VoidFunction,
'call',
[],
true,
);
Reflector.registerMethod(
ReflectionRegistry.registerMethod(
AsyncVoidFunction,
'call',
[],
true,
);
Reflector.registerMethod(
ReflectionRegistry.registerMethod(
IntFunction,
'call',
[],
@ -55,14 +55,14 @@ void main() {
});
tearDown(() {
Reflector.reset();
ReflectionRegistry.reset();
});
group('ReflectsClosures', () {
test('getClosureParameterCount returns correct count', () {
final closure = (String name, int age) {};
Reflector.register(closure.runtimeType);
Reflector.registerMethod(
ReflectionRegistry.register(closure.runtimeType);
ReflectionRegistry.registerMethod(
closure.runtimeType,
'call',
[String, int],
@ -76,8 +76,8 @@ void main() {
test('getClosureParameterCount returns 0 for no parameters', () {
final closure = () {};
Reflector.register(closure.runtimeType);
Reflector.registerMethod(
ReflectionRegistry.register(closure.runtimeType);
ReflectionRegistry.registerMethod(
closure.runtimeType,
'call',
[],
@ -88,8 +88,8 @@ void main() {
test('getClosureParameterNames returns correct names', () {
final closure = (String name, int age) {};
Reflector.register(closure.runtimeType);
Reflector.registerMethod(
ReflectionRegistry.register(closure.runtimeType);
ReflectionRegistry.registerMethod(
closure.runtimeType,
'call',
[String, int],
@ -104,8 +104,8 @@ void main() {
test('getClosureParameterNames returns empty list for no parameters', () {
final closure = () {};
Reflector.register(closure.runtimeType);
Reflector.registerMethod(
ReflectionRegistry.register(closure.runtimeType);
ReflectionRegistry.registerMethod(
closure.runtimeType,
'call',
[],
@ -116,8 +116,8 @@ void main() {
test('getClosureParameterTypes returns correct types', () {
final closure = (String name, int age) {};
Reflector.register(closure.runtimeType);
Reflector.registerMethod(
ReflectionRegistry.register(closure.runtimeType);
ReflectionRegistry.registerMethod(
closure.runtimeType,
'call',
[String, int],
@ -132,8 +132,8 @@ void main() {
test('getClosureParameterTypes returns empty list for no parameters', () {
final closure = () {};
Reflector.register(closure.runtimeType);
Reflector.registerMethod(
ReflectionRegistry.register(closure.runtimeType);
ReflectionRegistry.registerMethod(
closure.runtimeType,
'call',
[],
@ -144,8 +144,8 @@ void main() {
test('closureHasParameter returns true for existing parameter', () {
final closure = (String name, int age) {};
Reflector.register(closure.runtimeType);
Reflector.registerMethod(
ReflectionRegistry.register(closure.runtimeType);
ReflectionRegistry.registerMethod(
closure.runtimeType,
'call',
[String, int],
@ -160,8 +160,8 @@ void main() {
test('closureHasParameter returns false for non-existent parameter', () {
final closure = (String name, int age) {};
Reflector.register(closure.runtimeType);
Reflector.registerMethod(
ReflectionRegistry.register(closure.runtimeType);
ReflectionRegistry.registerMethod(
closure.runtimeType,
'call',
[String, int],
@ -175,8 +175,8 @@ void main() {
test('isClosureVoid returns true for void closure', () {
final closure = () {};
Reflector.register(closure.runtimeType);
Reflector.registerMethod(
ReflectionRegistry.register(closure.runtimeType);
ReflectionRegistry.registerMethod(
closure.runtimeType,
'call',
[],
@ -187,8 +187,8 @@ void main() {
test('isClosureVoid returns false for non-void closure', () {
final closure = () => 42;
Reflector.register(closure.runtimeType);
Reflector.registerMethod(
ReflectionRegistry.register(closure.runtimeType);
ReflectionRegistry.registerMethod(
closure.runtimeType,
'call',
[],
@ -199,8 +199,8 @@ void main() {
test('isClosureNullable returns true for nullable closure', () {
final closure = () => null;
Reflector.register(closure.runtimeType);
Reflector.registerMethod(
ReflectionRegistry.register(closure.runtimeType);
ReflectionRegistry.registerMethod(
closure.runtimeType,
'call',
[],
@ -211,8 +211,8 @@ void main() {
test('isClosureNullable returns false for non-nullable closure', () {
final closure = () {};
Reflector.register(closure.runtimeType);
Reflector.registerMethod(
ReflectionRegistry.register(closure.runtimeType);
ReflectionRegistry.registerMethod(
closure.runtimeType,
'call',
[],
@ -223,8 +223,8 @@ void main() {
test('isClosureAsync returns true for async closure', () {
final closure = () async {};
Reflector.register(closure.runtimeType);
Reflector.registerMethod(
ReflectionRegistry.register(closure.runtimeType);
ReflectionRegistry.registerMethod(
closure.runtimeType,
'call',
[],
@ -235,8 +235,8 @@ void main() {
test('isClosureAsync returns false for sync closure', () {
final closure = () {};
Reflector.register(closure.runtimeType);
Reflector.registerMethod(
ReflectionRegistry.register(closure.runtimeType);
ReflectionRegistry.registerMethod(
closure.runtimeType,
'call',
[],