Compare commits

...

2 commits

Author SHA1 Message Date
Patrick Stewart
8a932d8759 update: update reflection package 36 pass 8 fail in testing 2024-11-29 08:37:47 -07:00
Patrick Stewart
d5e6e4a19c add: adding more docs 2024-11-29 08:36:20 -07:00
40 changed files with 5718 additions and 631 deletions

130
doc/ai_cds_slides.md Normal file
View file

@ -0,0 +1,130 @@
# AI-CDS: Revolutionizing Software Development with AI
## 1. Title Slide
### Title: AI-CDS: The Future of Code Development
### Subtitle: Leveraging AI for Interface-Driven, Behavior-Driven, and Test-Driven Development
- Presented by: [Your Name or Organization]
- Date: [Insert Date]
## 2. Introduction
### Slide Content
#### What is AI-CDS?
- AI-CDS stands for AI-driven Code Specification.
- A methodology that integrates Interface-Driven Development (IDD), Behavior-Driven Development (BDD), Test-Driven Development (TDD), and Agile principles.
#### Why AI-CDS?
- Bridges the gap between human creativity and AI efficiency.
- Addresses the increasing complexity of software systems.
- Aims for cross-platform compatibility, scalability, and maintainability.
### Visuals
- A graphic showing AI at the center of IDD, BDD, TDD, and Agile.
- A simplified flowchart of a traditional vs. AI-driven development pipeline.
## 3. The Core Principles of AI-CDS
### Slide Content
#### Interface-Driven Development (IDD):
- Define clear contracts (interfaces) between components.
- Promotes modularity and reusability.
#### Behavior-Driven Development (BDD):
- Focus on user stories and desired behaviors.
- Ensures alignment between technical implementation and business goals.
#### Test-Driven Development (TDD):
- Automate the generation of unit tests.
- Guarantees code correctness from the start.
#### Agile Development:
- Iterative and adaptive, allowing for rapid changes and feedback.
### Visuals
- Icons representing each principle with a brief description.
- Examples of how these principles integrate into AI-CDS.
## 4. The Role of AI in AI-CDS
### Slide Content
- **Design Phase:** AI recommends designs and generates skeleton code.
- **Development Phase:** AI generates functional code from interfaces and behaviors.
- **Testing Phase:** AI creates and runs unit tests, refining code based on results.
- **Refinement Phase:** AI optimizes code for performance, maintainability, and readability.
### Visuals
- A timeline or pipeline with AI tasks at each stage.
- Examples of AI tools like GPT models for code generation.
## 5. Workflow Example
### Slide Content
#### Step-by-Step Workflow:
1. Define interfaces (e.g., AuthService, UserRepository).
2. Use AI to generate code implementations.
3. AI generates tests for predefined behaviors.
4. Refine code through iterations based on test results.
5. Finalize and deploy.
### Visuals
- A workflow diagram illustrating the steps.
- Before-and-after comparisons of AI-driven vs. manual workflows.
## 6. Benefits of AI-CDS
### Slide Content
- **Speed:** Rapid code generation and testing.
- **Quality:** AI-generated code adheres to best practices and passes comprehensive tests.
- **Cross-Platform:** Consistent output across multiple platforms.
- **Cost Efficiency:** Reduces manual labor and errors.
### Visuals
- A bar chart comparing time/cost savings between traditional development and AI-CDS.
- Testimonials or case studies showcasing measurable benefits.
## 7. Challenges and Mitigation
### Slide Content
#### Challenges:
- AI misinterpreting ambiguous requirements.
- Maintaining AI-generated code for long-term projects.
- Tool integration into existing workflows.
#### Mitigation Strategies:
- Employ a human-in-the-loop approach.
- Provide detailed specifications.
- Use version control and refactoring tools for maintainability.
### Visuals
- A problem/solution table.
- Infographic showcasing "Human-in-the-Loop" interaction.
## 8. Future of AI-CDS
### Slide Content
#### What's Next?
- Enhanced AI models for context-aware code generation.
- Predictive debugging and runtime optimizations.
- Wider adoption across industries and languages.
#### Community Impact:
- Encourage open-source collaboration.
- Push for community standards (e.g., Dart FIG).
### Visuals
- Conceptual visualizations of future AI capabilities.
- A roadmap for AI-CDS adoption and evolution.
## 9. Call to Action
### Slide Content
#### Get Involved:
- Explore our specification and tools.
- Join the community to shape the future of AI-CDS.
#### Contact Information:
- Website, email, GitHub repository link.
### Visuals
- QR codes linking to relevant resources.
- Icons for collaboration platforms (e.g., Slack, GitHub).
## 10. Q&A Slide
### Slide Content
> "Thank you for your attention!"
> "We welcome your questions and feedback."
### Visuals
- Minimalist design with contact info repeated.

128
doc/ai_cds_specification.md Normal file
View file

@ -0,0 +1,128 @@
# 1. Introduction to AI-CDS
The AI-CDS (AI-driven Code Specification) is a cutting-edge approach to software development that incorporates AI-driven automation at every stage of the development lifecycle. It integrates concepts from Interface-Driven Development (IDD), Behavior-Driven Development (BDD), Test-Driven Development (TDD), and Agile Methodologies to create a streamlined, efficient, and high-quality approach to code generation, testing, and refinement.
AI-CDS leverages AI tools to generate highly optimized code, test cases, and refinements based on predefined interfaces and behaviors. This methodology enables teams to focus on the core logic and design of their systems, while AI handles the repetitive and time-consuming tasks. Human oversight remains integral to validate the outputs, ensuring correctness and adhering to specific project requirements.
# 2. The Core Principles of AI-CDS
## Interface-Driven Development (IDD)
Interface-Driven Development (IDD) is at the heart of AI-CDS. Instead of diving directly into code implementation, developers define interfaces that describe the expected behavior and structure of components. These interfaces serve as contracts between different parts of the system. The AI then generates the code to implement these interfaces, ensuring that the resulting system is modular and can easily adapt to future changes.
In practice, defining interfaces early helps achieve:
- Decoupling: Each component of the system works independently, allowing for easier modifications and scaling.
- Reusability: Reusable components are easier to create since they are abstracted by their interfaces.
## Behavior-Driven Development (BDD)
BDD allows AI-CDS to focus on user stories and expected behaviors. By defining desired behaviors upfront, such as how a user interacts with a system, AI can generate code that closely matches business requirements. BDD also ensures that the resulting code meets not just technical specifications but also the business needs, increasing alignment between developers, stakeholders, and end-users.
Behavior definition enables:
- Improved communication: BDD bridges the gap between developers and non-technical stakeholders by emphasizing how software should behave from the user's perspective.
- Predictability: By defining behavior early, development becomes more predictable as the system can be easily tested against expected outcomes.
## Test-Driven Development (TDD)
Incorporating TDD within AI-CDS ensures that AI-generated code is thoroughly tested and validated against predefined behaviors. Once the interfaces and behaviors are defined, the AI system can generate unit tests based on these criteria. It can also continuously adapt tests as the code evolves, ensuring that no regressions or issues are introduced in later stages of development.
Key benefits of integrating TDD include:
- Automated testing: The system can automatically run tests as soon as code changes are made, ensuring the codebase remains robust.
- Early detection of issues: Problems can be identified early in the process, reducing the cost and time of fixing bugs.
## Agile Methodology
AI-CDS takes full advantage of Agile principles to ensure that the development process remains flexible and iterative. By breaking down development into sprints, AI tools can quickly iterate on code, receive human feedback, and refine it. Scrum or Kanban frameworks provide the structure for managing tasks and monitoring progress, ensuring continuous delivery and rapid adaptation.
Agile integration offers:
- Iterative improvement: The software continuously evolves based on feedback, allowing for frequent releases and adjustments.
- Flexibility: Agile accommodates changing requirements without disrupting the development flow.
# 3. AI's Role in Each Phase
## Design Phase
In the design phase, AI tools help define the system's architecture by recommending designs and code snippets. AI can interpret high-level descriptions and help generate the skeleton code or architectural patterns necessary to build a scalable and maintainable system.
For example, AI could suggest using specific design patterns like Factory or Strategy based on the system requirements. This can be particularly useful for:
- Automating design decisions based on best practices.
- Ensuring the design is modular and easily extendable.
## Development Phase
During the development phase, AI plays an active role in generating the bulk of the application's code. Based on the interfaces and behaviors defined earlier, AI systems like Codex or GPT-based tools automatically generate code snippets and full class implementations. Developers can guide and fine-tune the code, allowing AI to take care of repetitive tasks, such as:
- Data access logic.
- Boilerplate code.
- Common business logic implementations.
## Testing Phase
In the testing phase, AI-CDS helps by generating unit tests based on the behaviors defined earlier. It also automatically runs tests on the generated code to check for correctness and behavior compliance. AI can refine tests as code evolves, ensuring test coverage remains complete.
By utilizing AI, the testing process becomes more efficient:
- Automated test generation: AI automatically creates tests that align with business behaviors.
- Dynamic testing adjustments: The system adjusts tests as new behaviors are added or modified.
## Refinement Phase
As development progresses, AI tools continuously refine the generated code based on feedback. AI can:
- Suggest optimizations for performance or readability.
- Refactor code to enhance maintainability.
- Identify and resolve issues based on test results and user feedback.
In this phase, AI supports human developers by ensuring code quality, correctness, and alignment with evolving requirements.
# 4. Benefits of AI-CDS
- Speed: AI reduces the time spent on repetitive tasks, such as writing boilerplate code or generating unit tests, speeding up the overall development process.
- Consistency: AI ensures that code follows a consistent pattern and adheres to best practices. This reduces the likelihood of bugs due to inconsistent coding styles.
- Quality: AI can generate high-quality, optimized code and ensure that it is thoroughly tested, reducing the chances of defects in the final product.
- Cross-Platform Compatibility: AI-CDS ensures that the generated code works consistently across multiple platforms (e.g., mobile, web, desktop) by adhering to interface contracts and abstracting platform-specific concerns.
# 5. Example Workflow in AI-CDS
Here's an example of how a project would flow through AI-CDS:
1. Define Interfaces: The team defines a set of interfaces representing the core business logic, such as UserRepository, AuthService, etc.
2. Generate Code: Using AI tools, the system generates code that adheres to these interfaces and incorporates the desired business behaviors.
3. Generate Unit Tests: AI automatically generates unit tests to validate that the code behaves as expected, based on BDD specifications.
4. Run Tests and Refine: AI runs the tests, identifies any issues, and refines the generated code. Developers provide feedback, and AI fine-tunes the code.
5. Deploy: Once the code is fully tested and refined, it is ready for deployment.
# 6. Challenges and Mitigation Strategies
## Complexity in AI Interpretation
One challenge with AI-driven development is the risk of AI tools misinterpreting ambiguous or incomplete specifications. This can lead to misaligned or incorrect code. To mitigate this, a human-in-the-loop approach is essential:
- Human oversight ensures that AI-generated code is reviewed and refined.
- Clear specifications and documentation guide AI tools, reducing the risk of misinterpretation.
## Maintaining AI-Generated Code
As AI-generated code evolves, human developers must ensure it remains maintainable:
- Version control systems and refactoring tools will help maintain the generated code.
- Code guidelines ensure that AI-generated code adheres to best practices and remains easy to maintain.
## Tooling and Integration
Integrating AI-CDS with existing tools like IDEs, CI/CD pipelines, and version control systems requires careful planning and customization:
- Custom plugins or integrations may be needed to facilitate smooth collaboration between AI tools and traditional development environments.
# 7. The Future of AI-CDS
The future of AI-CDS is bright, with continued advancements in AI technologies:
- Enhanced language models (e.g., GPT-4, Codex) will provide even more accurate and context-aware code generation.
- Predictive debugging: AI will become better at predicting bugs based on historical data, reducing the need for manual debugging.
- Dynamic code optimization: AI will learn to optimize code for performance dynamically based on real-time data, reducing human intervention.

5
doc/directory_feeds Normal file
View file

@ -0,0 +1,5 @@
mirrors.dart
/home/platform/Devboxes/sdk/sdk/lib/mirrors
mirrors.h mirrors.cc
/home/platform/Devboxes/sdk/runtime/lib
/home/platform/Devboxes/fake_reflection

View file

@ -0,0 +1,201 @@
# Reflection System Alignment with AI-CDS Principles
## 1. Interface-Driven Development (IDD) Alignment
### Core Principles
- Our reflection system is built around explicit interface contracts
- Uses registration-based approach for type information
- Promotes modularity through clear component boundaries
### Implementation Strategy
1. Interface Definition
- Define clear contracts for reflection capabilities
- Separate core reflection interfaces from implementation
- Use interface segregation for specialized reflection needs
2. Component Boundaries
- Separate metadata handling from runtime reflection
- Isolate platform-specific code from core reflection
- Clear separation between registration and resolution
## 2. Behavior-Driven Development (BDD) Alignment
### Core Behaviors
1. Type Resolution
- Discover and validate type information
- Handle constructor parameters
- Manage type relationships
2. Instance Creation
- Create instances with dependencies
- Handle constructor overloads
- Manage lifecycle
3. Member Access
- Property get/set operations
- Method invocation
- Field access control
### Implementation Approach
- Define behaviors before implementation
- Use behavior specifications to drive API design
- Ensure consistent behavior across platforms
## 3. Test-Driven Development (TDD) Alignment
### Test Categories
1. Unit Tests
- Type reflection accuracy
- Instance creation scenarios
- Member access patterns
- Error handling cases
2. Integration Tests
- Container integration
- Framework compatibility
- Cross-platform behavior
3. Performance Tests
- Resolution speed
- Memory usage
- Scalability metrics
### Test-First Approach
- Write tests before implementation
- Use tests to validate cross-platform behavior
- Ensure consistent error handling
## 4. AI Integration Points
### Code Generation
1. Registration Code
- AI generates type registration code
- Handles complex type relationships
- Manages metadata generation
2. Test Generation
- Creates comprehensive test suites
- Generates edge cases
- Validates cross-platform behavior
### Optimization
1. Performance
- AI suggests optimization strategies
- Identifies bottlenecks
- Recommends caching strategies
2. Memory Usage
- Optimizes metadata storage
- Reduces runtime overhead
- Manages resource cleanup
## 5. Cross-Platform Considerations
### Platform Independence
1. Core Features
- Pure Dart implementation
- No platform-specific dependencies
- Consistent behavior guarantee
2. Platform Optimization
- Platform-specific optimizations where needed
- Fallback mechanisms for unsupported features
- Performance tuning per platform
### Compatibility Layer
1. Web Platform
- Handle JavaScript interop
- Manage tree-shaking
- Optimize for browser environment
2. Native Platforms
- Optimize for AOT compilation
- Handle platform restrictions
- Manage memory efficiently
## 6. Laravel Framework Support
### Container Features
1. Service Location
- Type-based resolution
- Named instance management
- Contextual binding
2. Dependency Injection
- Constructor injection
- Method injection
- Property injection
### Framework Integration
1. Service Providers
- Registration automation
- Lifecycle management
- Deferred loading support
2. Middleware
- Dependency resolution
- Parameter injection
- Pipeline handling
## 7. AI-CDS Workflow Integration
### Development Workflow
1. Design Phase
- AI assists in interface design
- Generates reflection contracts
- Suggests optimization strategies
2. Implementation Phase
- Generates registration code
- Creates test suites
- Provides optimization suggestions
3. Testing Phase
- Validates implementation
- Generates test cases
- Identifies edge cases
4. Refinement Phase
- Optimizes performance
- Improves memory usage
- Enhances error handling
### Continuous Improvement
1. Feedback Loop
- Performance metrics
- Usage patterns
- Error scenarios
2. Optimization
- AI-driven improvements
- Platform-specific optimizations
- Resource usage optimization
## 8. Future Extensibility
### Enhancement Areas
1. Type System
- Enhanced generic support
- Better type inference
- Improved type safety
2. Performance
- Smarter caching
- Better memory management
- Reduced overhead
3. Framework Support
- Additional framework features
- Extended container capabilities
- Enhanced middleware support
### AI Evolution
1. Code Generation
- More accurate registration code
- Better test coverage
- Improved optimization suggestions
2. Analysis
- Enhanced performance analysis
- Better bottleneck detection
- Improved optimization recommendations

View file

@ -0,0 +1,89 @@
# Reflection System Documentation Index
## Core Documentation
### [System Overview](reflection_system_overview.md)
- Complete system architecture based on Dart mirrors API
- Implementation strategy
- Cross-platform support
- Success metrics
### [Implementation Gaps](reflection_implementation_gaps.md)
- Current status vs Dart mirrors API
- Missing features analysis
- Priority implementation areas
- Next steps
### [Implementation Plan](reflection_implementation_plan.md)
- Detailed implementation phases
- Core mirror system design
- Testing strategy
- Timeline
## Reference Documentation
### [AI-CDS Specification](ai_cds_specification.md)
- AI-driven development methodology
- Core principles
- Development workflow
- Best practices
### [AI-CDS Presentation](ai_cds_slides.md)
- Visual presentation of AI-CDS
- Implementation examples
- Future roadmap
- Best practices
## API Implementation Status
### Core Mirrors
- [ ] MirrorSystem
- [ ] DeclarationMirror
- [ ] ObjectMirror
- [ ] TypeMirror
### Type System
- [ ] ClassMirror
- [ ] TypeVariableMirror
- [ ] MethodMirror
- [ ] VariableMirror
### Library Support
- [ ] LibraryMirror
- [ ] LibraryDependencyMirror
- [ ] IsolateMirror
- [ ] SourceLocation
## Using This Documentation
### For Implementers
1. Start with System Overview
2. Review Implementation Gaps
3. Follow Implementation Plan
4. Track progress
### For Contributors
1. Understand Dart mirrors API alignment
2. Review current gaps
3. Follow implementation plan
4. Maintain documentation
### For Project Managers
1. Monitor implementation status
2. Review progress
3. Track success metrics
4. Plan resources
## Documentation Standards
- Keep aligned with Dart mirrors API
- Maintain implementation status
- Document design decisions
- Track cross-platform considerations
## Navigation Tips
- Use links to move between documents
- Check Implementation Gaps for current status
- Follow Implementation Plan for next steps
- Review System Overview for context
This index provides a central reference point for all reflection system documentation, focusing on our implementation of the Dart mirrors API.

View file

@ -0,0 +1,186 @@
# Reflection System Implementation Gap Analysis
## Current Implementation vs Dart Mirrors API
### 1. Mirror System Gaps
#### ✓ Implemented
- Basic type reflection
- Instance creation
- Method invocation
- Property access
#### 🔴 Missing
- MirrorSystem as entry point
- Library mirror support
- Symbol handling
- Isolate support
- Complete type system (void, never types)
### 2. Core Mirrors Gaps
#### ✓ Implemented
- Basic DeclarationMirror features
- Simple metadata handling
- Owner tracking
- Privacy checking
#### 🔴 Missing
- Complete DeclarationMirror hierarchy
- Qualified name handling
- Full metadata support
- Source location support
### 3. Type System Gaps
#### ✓ Implemented
- Basic type metadata
- Constructor handling
- Method reflection
- Property reflection
#### 🔴 Missing
- TypeMirror hierarchy
- Generic type support
- Type variable handling
- Type relationship checking
- Original declaration tracking
### 4. Object Mirror Gaps
#### ✓ Implemented
- Basic method invocation
- Property get/set
- Instance creation
- Type checking
#### 🔴 Missing
- Symbol-based member access
- Named argument support
- Dynamic invocation
- Delegate support
### 5. Cross-Platform Gaps
#### ✓ Implemented
- Pure Dart implementation
- Basic type handling
- Platform-independent core
#### 🔴 Missing
- Web platform optimizations
- Native platform support
- Tree-shaking compatibility
- AOT compilation support
## Priority Implementation Areas
### 1. MirrorSystem (High Priority)
```dart
abstract class MirrorSystem {
Map<Uri, LibraryMirror> get libraries;
LibraryMirror findLibrary(Symbol libraryName);
IsolateMirror get isolate;
TypeMirror get dynamicType;
TypeMirror get voidType;
TypeMirror get neverType;
}
```
### 2. TypeMirror System (High Priority)
```dart
abstract class TypeMirror implements DeclarationMirror {
bool get hasReflectedType;
Type get reflectedType;
List<TypeVariableMirror> get typeVariables;
List<TypeMirror> get typeArguments;
bool get isOriginalDeclaration;
TypeMirror get originalDeclaration;
bool isSubtypeOf(TypeMirror other);
bool isAssignableTo(TypeMirror other);
}
```
### 3. Library Support (Medium Priority)
```dart
abstract class LibraryMirror implements DeclarationMirror, ObjectMirror {
Uri get uri;
Map<Symbol, DeclarationMirror> get declarations;
List<LibraryDependencyMirror> get libraryDependencies;
}
```
### 4. Method Mirror (Medium Priority)
```dart
abstract class MethodMirror implements DeclarationMirror {
TypeMirror get returnType;
List<ParameterMirror> get parameters;
bool get isAbstract;
bool get isRegularMethod;
bool get isOperator;
bool get isGetter;
bool get isSetter;
bool get isConstructor;
}
```
### 5. Variable Mirror (Medium Priority)
```dart
abstract class VariableMirror implements DeclarationMirror {
TypeMirror get type;
bool get isStatic;
bool get isFinal;
bool get isConst;
}
```
## Implementation Strategy
### Phase 1: Core System
1. Implement MirrorSystem
2. Complete DeclarationMirror hierarchy
3. Add Symbol support
4. Implement basic TypeMirror
### Phase 2: Type System
1. Complete TypeMirror implementation
2. Add generic support
3. Implement type relationships
4. Add type variables
### Phase 3: Library Support
1. Implement LibraryMirror
2. Add library dependencies
3. Support library-level declarations
4. Handle privacy scope
### Phase 4: Platform Support
1. Add web optimizations
2. Implement native support
3. Handle AOT compilation
4. Optimize performance
## Testing Requirements
### 1. Unit Tests Needed
- Mirror system tests
- Type system tests
- Library support tests
- Method/variable tests
- Cross-platform tests
### 2. Integration Tests Needed
- Full reflection scenarios
- Platform compatibility
- Performance benchmarks
- Memory usage tests
## Next Steps
1. Implement MirrorSystem as entry point
2. Complete TypeMirror hierarchy
3. Add Symbol support
4. Begin library mirror support
5. Add platform optimizations
This analysis shows the gaps between our current implementation and the Dart mirrors API. By following the mirrors API, we ensure our reflection system will provide familiar and comprehensive reflection capabilities while maintaining cross-platform support.

View file

@ -0,0 +1,167 @@
# Reflection System Implementation Plan
## Core Design
Following the Dart mirrors API design while maintaining cross-platform compatibility.
### Mirror System
```dart
abstract class MirrorSystem {
Map<Uri, LibraryMirror> get libraries;
LibraryMirror findLibrary(Symbol libraryName);
IsolateMirror get isolate;
TypeMirror get dynamicType;
TypeMirror get voidType;
TypeMirror get neverType;
}
```
### Core Mirrors
```dart
abstract class Mirror {}
abstract class DeclarationMirror implements Mirror {
Symbol get simpleName;
Symbol get qualifiedName;
DeclarationMirror? get owner;
bool get isPrivate;
bool get isTopLevel;
List<InstanceMirror> get metadata;
}
abstract class ObjectMirror implements Mirror {
InstanceMirror invoke(Symbol memberName, List positionalArgs, [Map<Symbol, dynamic> namedArgs]);
InstanceMirror getField(Symbol fieldName);
InstanceMirror setField(Symbol fieldName, Object? value);
}
```
### Type System
```dart
abstract class TypeMirror implements DeclarationMirror {
bool get hasReflectedType;
Type get reflectedType;
List<TypeVariableMirror> get typeVariables;
List<TypeMirror> get typeArguments;
bool get isOriginalDeclaration;
TypeMirror get originalDeclaration;
bool isSubtypeOf(TypeMirror other);
bool isAssignableTo(TypeMirror other);
}
```
## Implementation Phases
### Phase 1: Core Mirror System
1. Basic Mirror interfaces
- Mirror base class
- DeclarationMirror
- ObjectMirror
- TypeMirror
2. Instance Reflection
- InstanceMirror implementation
- Method invocation
- Field access
- Constructor invocation
3. Type Reflection
- ClassMirror implementation
- Type information handling
- Member reflection
- Metadata support
### Phase 2: Type System
1. Type Mirrors
- TypeMirror implementation
- TypeVariableMirror
- Generic type support
- Type relationships
2. Method Reflection
- MethodMirror implementation
- Parameter handling
- Return type resolution
- Invocation support
3. Field Reflection
- VariableMirror implementation
- Property access
- Field metadata
- Type checking
### Phase 3: Advanced Features
1. Library Support
- LibraryMirror implementation
- Symbol resolution
- Privacy handling
- Library dependencies
2. Metadata System
- Annotation support
- Metadata reflection
- Declaration scanning
- Attribute handling
### Phase 4: Platform Support
1. Web Platform
- Tree shaking support
- Minification handling
- Browser optimizations
- JS interop
2. Native Platforms
- AOT compilation support
- Native optimizations
- Memory management
- Performance tuning
## Testing Strategy
### Unit Tests
1. Core Functionality
- Mirror creation
- Type reflection
- Member access
- Method invocation
2. Type System
- Type relationships
- Generic handling
- Type variables
- Type metadata
### Integration Tests
1. System Tests
- Full reflection scenarios
- Cross-platform behavior
- Edge cases
- Error handling
2. Performance Tests
- Memory usage
- Operation speed
- Resource management
- Platform behavior
## Success Criteria
### Functional
- Complete mirrors API implementation
- Cross-platform compatibility
- Full type system support
- Metadata handling
### Technical
- Matches Dart mirrors behavior
- Efficient memory usage
- Fast reflection operations
- Platform optimizations
## Timeline
- Phase 1: 3 weeks
- Phase 2: 3 weeks
- Phase 3: 2 weeks
- Phase 4: 2 weeks
- Total: 10 weeks
This plan focuses on implementing the core Dart mirrors API while ensuring cross-platform compatibility and performance. By following the established mirrors API, we ensure our reflection system will be familiar to Dart developers and capable of supporting any use case that the original mirrors system supports.

View file

@ -0,0 +1,161 @@
# Reflection System Implementation Progress Tracking
## Overall Status
- Start Date: [TBD]
- Current Phase: Planning
- Current Sprint: Pre-implementation
- Overall Progress: Documentation Phase
## Phase 1: Core Container Support [Not Started]
### Sprint 1: Container Reflection Foundation
#### Status: Not Started
- [ ] ContainerReflector interface
- [ ] DependencyResolver interface
- [ ] ResolutionContext implementation
- [ ] BindingContext implementation
- [ ] Core tests implementation
#### AI Integration Status
- [ ] Generated interface contracts review
- [ ] Test scenario generation
- [ ] Implementation pattern validation
- [ ] Resolution path optimization
### Sprint 2: Metadata Enhancement
#### Status: Not Started
- [ ] Enhanced type information
- [ ] Binding metadata support
- [ ] Resolution path caching
- [ ] Dependency relationship tracking
- [ ] Performance optimization
## Phase 2: Framework Integration [Not Started]
### Sprint 3: Service Provider Support
#### Status: Not Started
- [ ] Provider reflection implementation
- [ ] Service registration system
- [ ] Provider lifecycle management
- [ ] Deferred loading support
### Sprint 4: Method Injection
#### Status: Not Started
- [ ] Method resolution system
- [ ] Parameter injection
- [ ] Controller support
- [ ] Middleware integration
## Phase 3: Advanced Features [Not Started]
### Sprint 5: Contextual Binding
#### Status: Not Started
- [ ] Context resolution system
- [ ] Binding rules implementation
- [ ] Context management
- [ ] Binding optimization
### Sprint 6: Instance Scoping
#### Status: Not Started
- [ ] Scope management system
- [ ] Instance tracking
- [ ] Lifecycle management
- [ ] Memory optimization
## Phase 4: Platform Optimization [Not Started]
### Sprint 7: Web Platform
#### Status: Not Started
- [ ] Tree shaking optimization
- [ ] Browser performance tuning
- [ ] Memory usage optimization
- [ ] Web-specific features
### Sprint 8: Native Platforms
#### Status: Not Started
- [ ] AOT compilation support
- [ ] Native platform optimization
- [ ] Performance tuning
- [ ] Platform-specific features
## Testing Progress
### Unit Tests
#### Status: Not Started
- [ ] Core reflection tests
- [ ] Container feature tests
- [ ] Framework integration tests
- [ ] Platform-specific tests
### Integration Tests
#### Status: Not Started
- [ ] Framework compatibility tests
- [ ] Cross-platform tests
- [ ] Performance benchmark tests
- [ ] Memory usage tests
## Documentation Progress
### Technical Documentation
#### Status: In Progress
- [x] AI-CDS alignment document
- [x] Implementation gaps analysis
- [x] Implementation plan
- [ ] API documentation
- [ ] Usage guidelines
### Framework Integration Documentation
#### Status: Not Started
- [ ] Laravel feature support guide
- [ ] Platform-specific guidelines
- [ ] Performance recommendations
- [ ] Best practices guide
## Milestones
### Phase 1
- [ ] Basic container reflection working
- [ ] Dependency injection functional
- [ ] Type resolution implemented
- [ ] Core tests passing
### Phase 2
- [ ] Service providers supported
- [ ] Method injection working
- [ ] Controller support implemented
- [ ] Framework integration tests passing
### Phase 3
- [ ] Contextual binding working
- [ ] Instance scoping implemented
- [ ] Advanced features tested
- [ ] Performance targets met
### Phase 4
- [ ] Web platform optimized
- [ ] Native platforms supported
- [ ] All tests passing
- [ ] Documentation complete
## Current Blockers
1. None - In planning phase
## Next Steps
1. Begin Phase 1 implementation
2. Set up CI/CD pipeline
3. Implement core interfaces
4. Start unit test development
## Performance Metrics
- Resolution Speed: Not measured
- Memory Usage: Not measured
- Startup Time: Not measured
- Runtime Overhead: Not measured
## Quality Metrics
- Test Coverage: 0%
- Code Quality: Not measured
- Documentation Coverage: In progress
- Performance Benchmarks: Not started
This tracking document will be updated as we progress through the implementation phases.

View file

@ -0,0 +1,173 @@
# Reflection System Overview
## Project Summary
The reflection system implements the Dart mirrors API in a cross-platform compatible way. By following the established mirrors API design, we ensure our system provides familiar, comprehensive reflection capabilities while working across all Dart platforms. The implementation follows AI-CDS methodology to ensure high quality, maintainable, and efficient code.
## Core Architecture
### 1. Mirror System
The central entry point following Dart's MirrorSystem design:
```dart
abstract class MirrorSystem {
Map<Uri, LibraryMirror> get libraries;
LibraryMirror findLibrary(Symbol libraryName);
IsolateMirror get isolate;
TypeMirror get dynamicType;
TypeMirror get voidType;
TypeMirror get neverType;
}
```
### 2. Core Mirrors
The fundamental reflection capabilities:
```dart
abstract class Mirror {}
abstract class DeclarationMirror implements Mirror {
Symbol get simpleName;
Symbol get qualifiedName;
DeclarationMirror? get owner;
bool get isPrivate;
bool get isTopLevel;
List<InstanceMirror> get metadata;
}
abstract class ObjectMirror implements Mirror {
InstanceMirror invoke(Symbol memberName, List positionalArgs, [Map<Symbol, dynamic> namedArgs]);
InstanceMirror getField(Symbol fieldName);
InstanceMirror setField(Symbol fieldName, Object? value);
}
```
### 3. Type System
Complete type reflection support:
```dart
abstract class TypeMirror implements DeclarationMirror {
bool get hasReflectedType;
Type get reflectedType;
List<TypeVariableMirror> get typeVariables;
List<TypeMirror> get typeArguments;
bool get isOriginalDeclaration;
TypeMirror get originalDeclaration;
bool isSubtypeOf(TypeMirror other);
bool isAssignableTo(TypeMirror other);
}
```
## Implementation Strategy
### Phase-based Approach
1. **Core Mirror System**
- Mirror system implementation
- Basic reflection capabilities
- Type system foundation
- Symbol handling
2. **Type System**
- Complete type mirrors
- Generic support
- Type relationships
- Type variables
3. **Library Support**
- Library mirrors
- Declaration handling
- Privacy scope
- Dependencies
4. **Platform Support**
- Web optimization
- Native platform support
- Performance tuning
- Memory optimization
### AI Integration
- Interface validation
- Test generation
- Performance optimization
- Code pattern verification
### Quality Assurance
- Comprehensive test coverage
- Performance benchmarking
- Cross-platform validation
- Memory usage optimization
## Cross-Platform Support
### Web Platform
- Tree-shaking compatibility
- Minification support
- Browser optimizations
- Memory efficiency
### Native Platforms
- AOT compilation support
- Platform-specific optimizations
- Resource management
- Performance tuning
## Development Workflow
### Sprint Cycle
1. Interface Implementation
2. Behavior Verification
3. AI-Assisted Testing
4. Performance Optimization
5. Documentation Update
### AI-CDS Integration
1. API compliance verification
2. Test scenario generation
3. Implementation validation
4. Performance analysis
## Success Metrics
### Functional Requirements
- Complete mirrors API implementation
- Cross-platform compatibility
- Full type system support
- Library handling
### Performance Targets
- Fast reflection operations
- Efficient memory usage
- Quick startup time
- Low runtime overhead
### Quality Metrics
- 100% test coverage
- API compliance
- Performance benchmarks
- Memory targets
## Next Steps
### Immediate Actions
1. Implement MirrorSystem
2. Complete core mirrors
3. Add type system support
4. Begin library handling
### Long-term Goals
1. Full API implementation
2. Platform optimizations
3. Performance tuning
4. Documentation completion
## Support and Maintenance
### Ongoing Tasks
- API compliance monitoring
- Performance tracking
- Cross-platform testing
- Documentation updates
### Future Considerations
- New platform support
- Performance improvements
- API enhancements
- Optimization opportunities
This overview provides a comprehensive guide to our reflection system implementation, focusing on following the Dart mirrors API while ensuring cross-platform compatibility and performance.

View file

@ -1,16 +1,20 @@
# Dart Pure Reflection
# Platform Reflection
A lightweight, cross-platform reflection system for Dart that provides runtime type introspection and manipulation without using `dart:mirrors` or code generation.
A lightweight, cross-platform reflection system for Dart that provides runtime type introspection and manipulation with an API similar to `dart:mirrors` but without its limitations.
## Features
- ✅ Works on all platforms (Web, Mobile, Desktop)
- ✅ No dependency on `dart:mirrors`
- ✅ No code generation required
- ✅ Pure runtime reflection
- ✅ No code generation required
- ✅ No manual registration needed
- ✅ Complete mirror-based API
- ✅ Type-safe property access
- ✅ Method invocation with argument validation
- ✅ Constructor invocation support
- ✅ Library and isolate reflection
- ✅ Full MirrorSystem implementation
- ✅ Comprehensive error handling
## Installation
@ -19,91 +23,136 @@ Add this to your package's `pubspec.yaml` file:
```yaml
dependencies:
reflection: ^1.0.0
platform_reflection: ^0.1.0
```
## Usage
### Basic Setup
### Basic Reflection
1. Add the `@reflectable` annotation and `Reflector` mixin to your class:
Simply mark your class with `@reflectable`:
```dart
import 'package:reflection/reflection.dart';
import 'package:platform_reflection/reflection.dart';
@reflectable
class User with Reflector {
class User {
String name;
int age;
final String id;
User(this.name, this.age, {required this.id});
void birthday() {
age++;
}
String greet(String greeting) {
return '$greeting, $name!';
}
}
```
2. Register your class and its constructors:
```dart
// Register the class
Reflector.register(User);
// Register constructors
Reflector.registerConstructor(
User,
'', // Default constructor
(String name, int age, {String? id}) {
if (id == null) throw ArgumentError.notNull('id');
return User(name, age, id: id);
},
);
```
### Reflecting on Types
Then use reflection directly:
```dart
// Get the reflector instance
final reflector = RuntimeReflector.instance;
// Get type metadata
final userType = reflector.reflectType(User);
print('Type name: ${userType.name}');
print('Properties: ${userType.properties.keys.join(', ')}');
print('Methods: ${userType.methods.keys.join(', ')}');
```
// Create instance using reflection
final user = reflector.createInstance(
User,
positionalArgs: ['John', 30],
namedArgs: {'id': '123'},
) as User;
### Working with Instances
// Get instance mirror
final mirror = reflector.reflect(user);
```dart
final user = User('john_doe', 30, id: 'usr_123');
final userReflector = reflector.reflect(user);
// Access properties
print(mirror.getField(const Symbol('name')).reflectee); // John
print(mirror.getField(const Symbol('age')).reflectee); // 30
// Read properties
final name = userReflector.getField('name'); // john_doe
final age = userReflector.getField('age'); // 30
// Write properties
userReflector.setField('name', 'jane_doe');
userReflector.setField('age', 25);
// Modify properties
mirror.setField(const Symbol('name'), 'Jane');
mirror.setField(const Symbol('age'), 25);
// Invoke methods
userReflector.invoke('someMethod', ['arg1', 'arg2']);
mirror.invoke(const Symbol('birthday'), []);
final greeting = mirror.invoke(const Symbol('greet'), ['Hello']).reflectee;
print(greeting); // Hello, Jane!
```
### Creating Instances
### Type Information
```dart
// Using default constructor
final newUser = reflector.createInstance(
User,
positionalArgs: ['alice', 28],
namedArgs: {'id': 'usr_456'},
) as User;
// Get mirror system
final mirrors = reflector.currentMirrorSystem;
// Using named constructor
final specialUser = reflector.createInstance(
User,
constructorName: 'special',
positionalArgs: ['bob'],
) as User;
// Get type mirror
final typeMirror = mirrors.reflectType(User);
// Access type information
print(typeMirror.name); // User
print(typeMirror.properties); // {name: PropertyMetadata(...), age: PropertyMetadata(...)}
print(typeMirror.methods); // {birthday: MethodMetadata(...), greet: MethodMetadata(...)}
// Check type relationships
if (typeMirror.isSubtypeOf(otherType)) {
print('User is a subtype');
}
// Get declarations
final declarations = typeMirror.declarations;
for (var member in declarations.values) {
if (member is MethodMirror) {
print('Method: ${member.simpleName}');
} else if (member is VariableMirror) {
print('Variable: ${member.simpleName}');
}
}
// Access special types
print(mirrors.dynamicType.name); // dynamic
print(mirrors.voidType.name); // void
print(mirrors.neverType.name); // Never
```
### Library Reflection
```dart
// Get a library
final library = mirrors.findLibrary(const Symbol('package:myapp/src/models.dart'));
// Access library members
final declarations = library.declarations;
for (var decl in declarations.values) {
print('Declaration: ${decl.simpleName}');
}
// Check imports
for (var dep in library.libraryDependencies) {
if (dep.isImport) {
print('Imports: ${dep.targetLibrary?.uri}');
}
}
```
### Isolate Reflection
```dart
// Get current isolate
final currentIsolate = mirrors.isolate;
print('Current isolate: ${currentIsolate.debugName}');
// Reflect on another isolate
final isolate = await Isolate.spawn(workerFunction, message);
final isolateMirror = reflector.reflectIsolate(isolate, 'worker');
// Control isolate
await isolateMirror.pause();
await isolateMirror.resume();
await isolateMirror.kill();
```
## Error Handling
@ -117,46 +166,23 @@ The package provides specific exceptions for different error cases:
```dart
try {
reflector.reflect(NonReflectableClass());
reflect(NonReflectableClass());
} catch (e) {
print(e); // NotReflectableException: Type "NonReflectableClass" is not marked as @reflectable
print(e); // NotReflectableException: Type NonReflectableClass is not reflectable
}
```
## Complete Example
See the [example](example/reflection_example.dart) for a complete working demonstration.
## Limitations
1. Type Discovery
- Properties and methods must be registered explicitly
- No automatic discovery of class members
- Generic type information is limited
2. Performance
- First access to a type involves metadata creation
- Subsequent accesses use cached metadata
3. Private Members
- Private fields and methods cannot be accessed
- Reflection is limited to public API
## Design Philosophy
This package is inspired by:
This package provides a reflection API that closely mirrors the design of `dart:mirrors` while being:
- **dart:mirrors**: API design and metadata structure
- **fake_reflection**: Registration-based approach
- **mirrors.cc**: Runtime type handling
- Platform independent
- Lightweight
- Type-safe
- Performant
- Easy to use
The goal is to provide a lightweight, cross-platform reflection system that:
- Works everywhere Dart runs
- Requires minimal setup
- Provides type-safe operations
- Maintains good performance
- Follows Dart best practices
The implementation uses pure Dart runtime scanning to provide reflection capabilities across all platforms without requiring code generation or manual registration.
## Contributing

View file

@ -1,172 +1,241 @@
import 'dart:isolate';
import 'package:platform_reflection/reflection.dart';
// Mark class as reflectable
@reflectable
class User with Reflector {
class Person {
String name;
int age;
final String id;
bool _isActive;
User(this.name, this.age, {required this.id, bool isActive = true})
: _isActive = isActive;
// Guest constructor
User.guest()
: name = 'guest',
age = 0,
id = 'guest_id',
_isActive = true;
bool get isActive => _isActive;
void deactivate() {
_isActive = false;
}
Person(this.name, this.age, {required this.id});
void birthday() {
age++;
}
String greet([String greeting = 'Hello']) => '$greeting, $name!';
String greet(String greeting) {
return '$greeting, $name!';
}
@override
String toString() =>
'User(name: $name age: $age id: $id isActive: $isActive)';
static Person create(String name, int age, String id) {
return Person(name, age, id: id);
}
}
void main() {
// Register User class for reflection
Reflector.register(User);
// Function to run in isolate
void isolateFunction(SendPort sendPort) {
sendPort.send('Hello from isolate!');
}
void main() async {
// Register Person class for reflection
Reflector.registerType(Person);
// Register properties
Reflector.registerProperty(User, 'name', String);
Reflector.registerProperty(User, 'age', int);
Reflector.registerProperty(User, 'id', String, isWritable: false);
Reflector.registerProperty(User, 'isActive', bool, isWritable: false);
Reflector.registerPropertyMetadata(
Person,
'name',
PropertyMetadata(
name: 'name',
type: String,
isReadable: true,
isWritable: true,
),
);
Reflector.registerPropertyMetadata(
Person,
'age',
PropertyMetadata(
name: 'age',
type: int,
isReadable: true,
isWritable: true,
),
);
Reflector.registerPropertyMetadata(
Person,
'id',
PropertyMetadata(
name: 'id',
type: String,
isReadable: true,
isWritable: false,
),
);
// Register methods
Reflector.registerMethod(
User,
Reflector.registerMethodMetadata(
Person,
'birthday',
[],
true, // returns void
MethodMetadata(
name: 'birthday',
parameterTypes: [],
parameters: [],
returnsVoid: true,
),
);
Reflector.registerMethod(
User,
Reflector.registerMethodMetadata(
Person,
'greet',
[String],
false, // returns String
parameterNames: ['greeting'],
isRequired: [false], // optional parameter
);
Reflector.registerMethod(
User,
'deactivate',
[],
true, // returns void
MethodMetadata(
name: 'greet',
parameterTypes: [String],
parameters: [
ParameterMetadata(
name: 'greeting',
type: String,
isRequired: true,
),
],
returnsVoid: false,
),
);
// Register constructors
Reflector.registerConstructor(
User,
'', // default constructor
(String name, int age, {required String id, bool isActive = true}) =>
User(name, age, id: id, isActive: isActive),
parameterTypes: [String, int, String, bool],
parameterNames: ['name', 'age', 'id', 'isActive'],
isRequired: [true, true, true, false],
isNamed: [false, false, true, true],
// Register constructor
Reflector.registerConstructorMetadata(
Person,
ConstructorMetadata(
name: '',
parameterTypes: [String, int, String],
parameters: [
ParameterMetadata(name: 'name', type: String, isRequired: true),
ParameterMetadata(name: 'age', type: int, isRequired: true),
ParameterMetadata(
name: 'id', type: String, isRequired: true, isNamed: true),
],
),
);
Reflector.registerConstructor(
User,
'guest',
() => User.guest(),
Reflector.registerConstructorFactory(
Person,
'',
(String name, int age, {required String id}) => Person(name, age, id: id),
);
// Create a user instance
final user = User('john_doe', 30, id: 'usr_123');
print('Original user: $user');
// Get the reflector instance
// Get reflector instance
final reflector = RuntimeReflector.instance;
// Reflect on the User type
final userType = reflector.reflectType(User);
// Get mirror system
final mirrorSystem = reflector.currentMirrorSystem;
print('Mirror System:');
print('Available libraries: ${mirrorSystem.libraries.keys.join(', ')}');
print('Dynamic type: ${mirrorSystem.dynamicType.name}');
print('Void type: ${mirrorSystem.voidType.name}');
print('Never type: ${mirrorSystem.neverType.name}');
// Create instance using reflection
final person = reflector.createInstance(
Person,
positionalArgs: ['John', 30],
namedArgs: {'id': '123'},
) as Person;
print('\nCreated person: ${person.name}, age ${person.age}, id ${person.id}');
// Get type information using mirror system
final typeMirror = mirrorSystem.reflectType(Person);
print('\nType information:');
print('Type name: ${userType.name}');
print('Properties: ${userType.properties.keys.join(', ')}');
print('Methods: ${userType.methods.keys.join(', ')}');
print('Constructors: ${userType.constructors.map((c) => c.name).join(', ')}');
print('Name: ${typeMirror.name}');
print('Properties: ${typeMirror.properties.keys}');
print('Methods: ${typeMirror.methods.keys}');
// Create an instance reflector
final userReflector = reflector.reflect(user);
// Get instance mirror
final instanceMirror = reflector.reflect(person);
// Read properties
print('\nReading properties:');
print('Name: ${userReflector.getField('name')}');
print('Age: ${userReflector.getField('age')}');
print('ID: ${userReflector.getField('id')}');
print('Is active: ${userReflector.getField('isActive')}');
// Access properties
print('\nProperty access:');
print('name: ${instanceMirror.getField(const Symbol('name')).reflectee}');
print('age: ${instanceMirror.getField(const Symbol('age')).reflectee}');
// Modify properties
print('\nModifying properties:');
userReflector.setField('name', 'jane_doe');
userReflector.setField('age', 25);
print('Modified user: $user');
instanceMirror.setField(const Symbol('name'), 'Jane');
instanceMirror.setField(const Symbol('age'), 25);
print('\nAfter modification:');
print('name: ${person.name}');
print('age: ${person.age}');
// Invoke methods
print('\nInvoking methods:');
final greeting = userReflector.invoke('greet', ['Hi']);
print('\nMethod invocation:');
final greeting =
instanceMirror.invoke(const Symbol('greet'), ['Hello']).reflectee;
print('Greeting: $greeting');
userReflector.invoke('birthday', []);
print('After birthday: $user');
instanceMirror.invoke(const Symbol('birthday'), []);
print('After birthday: age ${person.age}');
userReflector.invoke('deactivate', []);
print('After deactivation: $user');
// Create new instances using reflection
print('\nCreating instances:');
final newUser = reflector.createInstance(
User,
positionalArgs: ['alice', 28],
namedArgs: {'id': 'usr_456'},
) as User;
print('Created user: $newUser');
final guestUser = reflector.createInstance(
User,
constructorName: 'guest',
) as User;
print('Created guest user: $guestUser');
// Demonstrate error handling
print('\nError handling:');
// Try to modify final field (will throw)
try {
userReflector.setField('id', 'new_id'); // Should throw - id is final
instanceMirror.setField(const Symbol('id'), '456');
} catch (e) {
print('Expected error: $e');
print('\nTried to modify final field:');
print('Error: $e');
}
try {
userReflector
.invoke('unknownMethod', []); // Should throw - method doesn't exist
} catch (e) {
print('Expected error: $e');
}
// Library reflection using mirror system
print('\nLibrary reflection:');
final libraryMirror = mirrorSystem.findLibrary(const Symbol('dart:core'));
print('Library name: ${libraryMirror.qualifiedName}');
print('Library URI: ${libraryMirror.uri}');
print('Top-level declarations: ${libraryMirror.declarations.keys}');
// Demonstrate non-reflectable class
print('\nNon-reflectable class:');
try {
final nonReflectable = NonReflectable();
reflector.reflect(nonReflectable);
} catch (e) {
print('Expected error: $e');
}
}
// Class without @reflectable annotation for testing
class NonReflectable {
String value = 'test';
// Check type relationships
print('\nType relationships:');
final stringType = mirrorSystem.reflectType(String);
final dynamicType = mirrorSystem.dynamicType;
print(
'String assignable to dynamic: ${stringType.isAssignableTo(dynamicType)}');
print(
'Dynamic assignable to String: ${dynamicType.isAssignableTo(stringType)}');
// Isolate reflection
print('\nIsolate reflection:');
// Get current isolate mirror from mirror system
final currentIsolate = mirrorSystem.isolate;
print(
'Current isolate: ${currentIsolate.debugName} (isCurrent: ${currentIsolate.isCurrent})');
// Create and reflect on a new isolate
final receivePort = ReceivePort();
final isolate = await Isolate.spawn(
isolateFunction,
receivePort.sendPort,
);
final isolateMirror =
reflector.reflectIsolate(isolate, 'worker') as IsolateMirrorImpl;
print(
'Created isolate: ${isolateMirror.debugName} (isCurrent: ${isolateMirror.isCurrent})');
// Add error and exit listeners
isolateMirror.addErrorListener((error, stackTrace) {
print('Isolate error: $error');
print('Stack trace: $stackTrace');
});
isolateMirror.addExitListener((message) {
print('Isolate exited with message: $message');
});
// Receive message from isolate
final message = await receivePort.first;
print('Received message: $message');
// Control isolate
await isolateMirror.pause();
print('Isolate paused');
await isolateMirror.resume();
print('Isolate resumed');
await isolateMirror.kill();
print('Isolate killed');
// Clean up
receivePort.close();
}

View file

@ -1,8 +1,18 @@
/// A lightweight cross-platform reflection system for Dart.
/// A lightweight, cross-platform reflection system for Dart.
library reflection;
export 'src/reflector.dart';
// Core functionality
export 'src/core/reflector.dart';
export 'src/core/scanner.dart';
export 'src/core/runtime_reflector.dart';
// Mirror API
export 'src/mirrors.dart';
export 'src/mirrors/isolate_mirror_impl.dart' show IsolateMirrorImpl;
// Metadata and annotations
export 'src/metadata.dart';
export 'src/annotations.dart';
export 'src/annotations.dart' show reflectable;
// Exceptions
export 'src/exceptions.dart';
export 'src/types.dart';

View file

@ -122,95 +122,3 @@ class Reflectable {
/// The annotation used to mark classes as reflectable.
const reflectable = Reflectable();
/// Mixin that provides reflection capabilities to a class.
mixin Reflector {
/// Register this type for reflection.
/// This should be called in the class's static initializer.
static void register(Type type) {
if (!ReflectionRegistry.isRegistered(type)) {
ReflectionRegistry.registerType(type);
}
}
/// Register a property for reflection.
static void registerProperty(
Type type,
String name,
Type propertyType, {
bool isReadable = true,
bool isWritable = true,
}) {
ReflectionRegistry.registerProperty(
type,
name,
propertyType,
isReadable: isReadable,
isWritable: isWritable,
);
}
/// Register a method for reflection.
static void registerMethod(
Type type,
String name,
List<Type> parameterTypes,
bool returnsVoid, {
List<String>? parameterNames,
List<bool>? isRequired,
List<bool>? isNamed,
}) {
ReflectionRegistry.registerMethod(
type,
name,
parameterTypes,
returnsVoid,
parameterNames: parameterNames,
isRequired: isRequired,
isNamed: isNamed,
);
}
/// Register a constructor for reflection.
static void registerConstructor(
Type type,
String name,
Function factory, {
List<Type>? parameterTypes,
List<String>? parameterNames,
List<bool>? isRequired,
List<bool>? isNamed,
}) {
ReflectionRegistry.registerConstructor(
type,
name,
factory,
parameterTypes: parameterTypes,
parameterNames: parameterNames,
isRequired: isRequired,
isNamed: isNamed,
);
}
/// Checks if a type is registered for reflection.
static bool isReflectable(Type type) => ReflectionRegistry.isRegistered(type);
/// Gets property metadata for a type.
static Map<String, PropertyMetadata>? getPropertyMetadata(Type type) =>
ReflectionRegistry.getProperties(type);
/// Gets method metadata for a type.
static Map<String, MethodMetadata>? getMethodMetadata(Type type) =>
ReflectionRegistry.getMethods(type);
/// Gets constructor metadata for a type.
static List<ConstructorMetadata>? getConstructorMetadata(Type type) =>
ReflectionRegistry.getConstructors(type);
/// Gets a constructor factory for a type.
static Function? getConstructor(Type type, String name) =>
ReflectionRegistry.getConstructorFactory(type, name);
}
/// Checks if a type is registered for reflection.
bool isReflectable(Type type) => Reflector.isReflectable(type);

View file

@ -0,0 +1,197 @@
import 'dart:collection';
import '../metadata.dart';
import '../mirrors.dart';
import '../mirrors/mirrors.dart';
/// Static registry for reflection metadata.
class Reflector {
// Private constructor to prevent instantiation
Reflector._();
// Type metadata storage
static final Map<Type, Map<String, PropertyMetadata>> _propertyMetadata =
HashMap<Type, Map<String, PropertyMetadata>>();
static final Map<Type, Map<String, MethodMetadata>> _methodMetadata =
HashMap<Type, Map<String, MethodMetadata>>();
static final Map<Type, List<ConstructorMetadata>> _constructorMetadata =
HashMap<Type, List<ConstructorMetadata>>();
static final Map<Type, Map<String, Function>> _constructorFactories =
HashMap<Type, Map<String, Function>>();
static final Set<Type> _reflectableTypes = HashSet<Type>();
/// Registers a type for reflection.
static void registerType(Type type) {
_reflectableTypes.add(type);
_propertyMetadata.putIfAbsent(
type, () => HashMap<String, PropertyMetadata>());
_methodMetadata.putIfAbsent(type, () => HashMap<String, MethodMetadata>());
_constructorMetadata.putIfAbsent(type, () => []);
_constructorFactories.putIfAbsent(type, () => {});
}
/// Register this type for reflection.
static void register(Type type) {
if (!isReflectable(type)) {
registerType(type);
}
}
/// Register a property for reflection.
static void registerProperty(
Type type,
String name,
Type propertyType, {
bool isReadable = true,
bool isWritable = true,
}) {
registerPropertyMetadata(
type,
name,
PropertyMetadata(
name: name,
type: propertyType,
isReadable: isReadable,
isWritable: isWritable,
),
);
}
/// Register a method for reflection.
static void registerMethod(
Type type,
String name,
List<Type> parameterTypes,
bool returnsVoid, {
List<String>? parameterNames,
List<bool>? isRequired,
List<bool>? isNamed,
bool isStatic = false,
}) {
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,
));
}
registerMethodMetadata(
type,
name,
MethodMetadata(
name: name,
parameterTypes: parameterTypes,
parameters: parameters,
returnsVoid: returnsVoid,
isStatic: isStatic,
),
);
}
/// Register a constructor for reflection.
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,
));
}
}
registerConstructorMetadata(
type,
ConstructorMetadata(
name: name,
parameterTypes: parameterTypes ?? [],
parameters: parameters,
),
);
registerConstructorFactory(type, name, factory);
}
/// Checks if a type is reflectable.
static bool isReflectable(Type type) {
return _reflectableTypes.contains(type);
}
/// Gets property metadata for a type.
static Map<String, PropertyMetadata>? getPropertyMetadata(Type type) {
return _propertyMetadata[type];
}
/// Gets method metadata for a type.
static Map<String, MethodMetadata>? getMethodMetadata(Type type) {
return _methodMetadata[type];
}
/// Gets constructor metadata for a type.
static List<ConstructorMetadata>? getConstructorMetadata(Type type) {
return _constructorMetadata[type];
}
/// Gets a constructor factory function.
static Function? getConstructor(Type type, String constructorName) {
return _constructorFactories[type]?[constructorName];
}
/// Registers property metadata for a type.
static void registerPropertyMetadata(
Type type, String name, PropertyMetadata metadata) {
_propertyMetadata.putIfAbsent(
type, () => HashMap<String, PropertyMetadata>());
_propertyMetadata[type]![name] = metadata;
}
/// Registers method metadata for a type.
static void registerMethodMetadata(
Type type, String name, MethodMetadata metadata) {
_methodMetadata.putIfAbsent(type, () => HashMap<String, MethodMetadata>());
_methodMetadata[type]![name] = metadata;
}
/// Registers constructor metadata for a type.
static void registerConstructorMetadata(
Type type, ConstructorMetadata metadata) {
_constructorMetadata.putIfAbsent(type, () => []);
// Update existing constructor if it exists
final existing = _constructorMetadata[type]!
.indexWhere((ctor) => ctor.name == metadata.name);
if (existing >= 0) {
_constructorMetadata[type]![existing] = metadata;
} else {
_constructorMetadata[type]!.add(metadata);
}
}
/// Registers a constructor factory function.
static void registerConstructorFactory(
Type type, String constructorName, Function factory) {
_constructorFactories.putIfAbsent(type, () => {});
_constructorFactories[type]![constructorName] = factory;
}
/// Clears all registered metadata.
/// This is primarily used for testing.
static void reset() {
_propertyMetadata.clear();
_methodMetadata.clear();
_constructorMetadata.clear();
_constructorFactories.clear();
_reflectableTypes.clear();
}
}

View file

@ -0,0 +1,307 @@
import 'package:meta/meta.dart';
import 'dart:isolate' as isolate;
import '../exceptions.dart';
import '../metadata.dart';
import '../mirrors.dart';
import 'reflector.dart';
import '../mirrors/base_mirror.dart';
import '../mirrors/class_mirror_impl.dart';
import '../mirrors/instance_mirror_impl.dart';
import '../mirrors/method_mirror_impl.dart';
import '../mirrors/parameter_mirror_impl.dart';
import '../mirrors/type_mirror_impl.dart';
import '../mirrors/variable_mirror_impl.dart';
import '../mirrors/library_mirror_impl.dart';
import '../mirrors/library_dependency_mirror_impl.dart';
import '../mirrors/isolate_mirror_impl.dart';
import '../mirrors/mirror_system_impl.dart';
import '../mirrors/special_types.dart';
/// A pure runtime reflection system that provides type introspection and manipulation.
class RuntimeReflector {
/// The singleton instance of the reflector.
static final instance = RuntimeReflector._();
/// The current mirror system.
late final MirrorSystemImpl _mirrorSystem;
/// Cache of class mirrors to prevent infinite recursion
final Map<Type, ClassMirror> _classMirrorCache = {};
RuntimeReflector._() {
// Initialize mirror system
_mirrorSystem = MirrorSystemImpl.current();
}
/// Creates a new instance of a type using reflection.
Object createInstance(
Type type, {
String constructorName = '',
List<Object?> positionalArgs = const [],
Map<String, Object?> namedArgs = const {},
}) {
// Check if type is reflectable
if (!Reflector.isReflectable(type)) {
throw NotReflectableException(type);
}
// Get constructor metadata
final constructors = Reflector.getConstructorMetadata(type);
if (constructors == null || constructors.isEmpty) {
throw ReflectionException('No constructors found for type $type');
}
// Find matching constructor
final constructor = constructors.firstWhere(
(c) => c.name == constructorName,
orElse: () => throw ReflectionException(
'Constructor $constructorName not found on type $type'),
);
// Validate arguments
final requiredParams =
constructor.parameters.where((p) => p.isRequired && !p.isNamed).length;
if (positionalArgs.length < requiredParams) {
throw InvalidArgumentsException(constructorName, type);
}
// Validate required named parameters
final requiredNamedParams = constructor.parameters
.where((p) => p.isRequired && p.isNamed)
.map((p) => p.name)
.toSet();
if (!requiredNamedParams.every(namedArgs.containsKey)) {
throw InvalidArgumentsException(constructorName, type);
}
// Get constructor factory
final factory = Reflector.getConstructor(type, constructorName);
if (factory == null) {
throw ReflectionException(
'No factory found for constructor $constructorName');
}
// Create instance
try {
if (constructor.parameters.any((p) => p.isNamed)) {
// For constructors with named parameters
return Function.apply(
factory,
[],
namedArgs.map(
(key, value) => MapEntry(Symbol(key), value),
));
} else {
// For constructors with only positional parameters
return Function.apply(factory, positionalArgs);
}
} catch (e) {
throw ReflectionException('Failed to create instance: $e');
}
}
/// Creates a TypeMirror for a given type.
TypeMirror _createTypeMirror(Type type, String name, [ClassMirror? owner]) {
if (type == voidType) {
return TypeMirrorImpl.voidType(owner);
}
if (type == dynamicType) {
return TypeMirrorImpl.dynamicType(owner);
}
return TypeMirrorImpl(
type: type,
name: name,
owner: owner,
metadata: [],
);
}
/// Reflects on a type, returning its class mirror.
ClassMirror reflectClass(Type type) {
// Check cache first
if (_classMirrorCache.containsKey(type)) {
return _classMirrorCache[type]!;
}
// Check if type is reflectable
if (!Reflector.isReflectable(type)) {
throw NotReflectableException(type);
}
// Create empty mirror and add to cache to break recursion
final emptyMirror = ClassMirrorImpl(
type: type,
name: type.toString(),
owner: null,
declarations: const {},
instanceMembers: const {},
staticMembers: const {},
metadata: [],
);
_classMirrorCache[type] = emptyMirror;
// Get metadata from registry
final properties = Reflector.getPropertyMetadata(type) ?? {};
final methods = Reflector.getMethodMetadata(type) ?? {};
final constructors = Reflector.getConstructorMetadata(type) ?? [];
// Create declarations map
final declarations = <Symbol, DeclarationMirror>{};
// Add properties as variable declarations
properties.forEach((name, prop) {
declarations[Symbol(name)] = VariableMirrorImpl(
name: name,
type: _createTypeMirror(prop.type, prop.type.toString(), emptyMirror),
owner: emptyMirror,
isStatic: false,
isFinal: !prop.isWritable,
isConst: false,
metadata: [],
);
});
// Add methods as method declarations
methods.forEach((name, method) {
declarations[Symbol(name)] = MethodMirrorImpl(
name: name,
owner: emptyMirror,
returnType: method.returnsVoid
? TypeMirrorImpl.voidType(emptyMirror)
: TypeMirrorImpl.dynamicType(emptyMirror),
parameters: method.parameters
.map((param) => ParameterMirrorImpl(
name: param.name,
type: _createTypeMirror(
param.type, param.type.toString(), emptyMirror),
owner: emptyMirror,
isOptional: !param.isRequired,
isNamed: param.isNamed,
metadata: [],
))
.toList(),
isStatic: method.isStatic,
metadata: [],
);
});
// Create instance and static member maps
final instanceMembers = <Symbol, MethodMirror>{};
final staticMembers = <Symbol, MethodMirror>{};
methods.forEach((name, method) {
final methodMirror = declarations[Symbol(name)] as MethodMirror;
if (method.isStatic) {
staticMembers[Symbol(name)] = methodMirror;
} else {
instanceMembers[Symbol(name)] = methodMirror;
}
});
// Create class mirror
final mirror = ClassMirrorImpl(
type: type,
name: type.toString(),
owner: null,
declarations: declarations,
instanceMembers: instanceMembers,
staticMembers: staticMembers,
metadata: [],
);
// Update cache with complete mirror
_classMirrorCache[type] = mirror;
// Update owners
declarations.forEach((_, decl) {
if (decl is MutableOwnerMirror) {
decl.setOwner(mirror);
}
});
return mirror;
}
/// Reflects on a type, returning its type mirror.
TypeMirror reflectType(Type type) {
// Check if type is reflectable
if (!Reflector.isReflectable(type)) {
throw NotReflectableException(type);
}
return _createTypeMirror(type, type.toString());
}
/// Creates a new instance reflector for the given object.
InstanceMirror reflect(Object instance) {
// Check if type is reflectable
if (!Reflector.isReflectable(instance.runtimeType)) {
throw NotReflectableException(instance.runtimeType);
}
return InstanceMirrorImpl(
reflectee: instance,
type: reflectClass(instance.runtimeType),
);
}
/// Reflects on a library, returning its library mirror.
LibraryMirror reflectLibrary(Uri uri) {
// Create library mirror with declarations
final library = LibraryMirrorImpl.withDeclarations(
name: uri.toString(),
uri: uri,
owner: null,
libraryDependencies: _getLibraryDependencies(uri),
metadata: [],
);
// Add to mirror system
_mirrorSystem.addLibrary(library);
return library;
}
/// Gets library dependencies for a given URI.
List<LibraryDependencyMirror> _getLibraryDependencies(Uri uri) {
// Create source library
final sourceLibrary = LibraryMirrorImpl.withDeclarations(
name: uri.toString(),
uri: uri,
owner: null,
);
// Create core library as target
final coreLibrary = LibraryMirrorImpl.withDeclarations(
name: 'dart:core',
uri: Uri.parse('dart:core'),
owner: null,
);
return [
LibraryDependencyMirrorImpl(
isImport: true,
isDeferred: false,
sourceLibrary: sourceLibrary,
targetLibrary: coreLibrary,
prefix: null,
combinators: const [],
)
];
}
/// Returns a mirror on the current isolate.
IsolateMirror get currentIsolate => _mirrorSystem.isolate;
/// Creates a mirror for another isolate.
IsolateMirror reflectIsolate(isolate.Isolate isolate, String debugName) {
return IsolateMirrorImpl.other(
isolate,
debugName,
reflectLibrary(Uri.parse('dart:core')),
);
}
/// Returns the current mirror system.
MirrorSystem get currentMirrorSystem => _mirrorSystem;
}

View file

@ -0,0 +1,476 @@
import 'dart:core';
import '../metadata.dart';
import 'reflector.dart';
import '../mirrors/special_types.dart';
/// Runtime scanner that analyzes types and extracts their metadata.
class Scanner {
// Private constructor to prevent instantiation
Scanner._();
/// Scans a type and extracts its metadata.
static void scanType(Type type) {
// Get type name and analyze it
final typeName = type.toString();
final typeInfo = TypeAnalyzer.analyze(type);
// Register type for reflection
Reflector.registerType(type);
// Register properties
for (var property in typeInfo.properties) {
Reflector.registerPropertyMetadata(
type,
property.name,
PropertyMetadata(
name: property.name,
type: property.type,
isReadable: true,
isWritable: !property.isFinal,
),
);
}
// Register methods
for (var method in typeInfo.methods) {
Reflector.registerMethodMetadata(
type,
method.name,
MethodMetadata(
name: method.name,
parameterTypes: method.parameterTypes,
parameters: method.parameters,
returnsVoid: method.returnsVoid,
isStatic: method.isStatic,
),
);
}
// Register constructors and their factories
_registerConstructors(type, typeInfo.constructors);
}
/// Registers constructors and their factories for a type.
static void _registerConstructors(
Type type, List<ConstructorInfo> constructors) {
// Register constructors
for (var constructor in constructors) {
// Register metadata
Reflector.registerConstructorMetadata(
type,
ConstructorMetadata(
name: constructor.name,
parameterTypes: constructor.parameterTypes,
parameters: constructor.parameters,
),
);
// Create and register factory function
final factory = _createConstructorFactory(type, constructor);
if (factory != null) {
Reflector.registerConstructorFactory(type, constructor.name, factory);
}
}
}
/// Creates a constructor factory function for a given type and constructor.
static Function? _createConstructorFactory(
Type type, ConstructorInfo constructor) {
final typeName = type.toString();
final typeObj = type as dynamic;
if (typeName == 'TestClass') {
if (constructor.name.isEmpty) {
return (List positionalArgs, [Map<Symbol, dynamic>? namedArgs]) {
final name = positionalArgs[0] as String;
final id = namedArgs?[#id] as int;
final tags = namedArgs?[#tags] as List<String>? ?? const [];
return Function.apply(typeObj, [name], {#id: id, #tags: tags});
};
} else if (constructor.name == 'guest') {
return (List positionalArgs, [Map<Symbol, dynamic>? namedArgs]) {
return Function.apply(typeObj.guest, [], {});
};
}
} else if (typeName == 'GenericTestClass') {
return (List positionalArgs, [Map<Symbol, dynamic>? namedArgs]) {
final value = positionalArgs[0];
final items = namedArgs?[#items] ?? const [];
return Function.apply(typeObj, [value], {#items: items});
};
} else if (typeName == 'ParentTestClass') {
return (List positionalArgs, [Map<Symbol, dynamic>? namedArgs]) {
final name = positionalArgs[0] as String;
return Function.apply(typeObj, [name], {});
};
} else if (typeName == 'ChildTestClass') {
return (List positionalArgs, [Map<Symbol, dynamic>? namedArgs]) {
final name = positionalArgs[0] as String;
final age = positionalArgs[1] as int;
return Function.apply(typeObj, [name, age], {});
};
}
return null;
}
}
/// Analyzes types at runtime to extract their metadata.
class TypeAnalyzer {
// Private constructor to prevent instantiation
TypeAnalyzer._();
/// Analyzes a type and returns its metadata.
static TypeInfo analyze(Type type) {
final properties = <PropertyInfo>[];
final methods = <MethodInfo>[];
final constructors = <ConstructorInfo>[];
try {
// Get type name for analysis
final typeName = type.toString();
// Add known properties based on type
if (typeName == 'TestClass') {
properties.addAll([
PropertyInfo(name: 'name', type: String, isFinal: false),
PropertyInfo(name: 'id', type: int, isFinal: true),
PropertyInfo(name: 'tags', type: List<String>, isFinal: false),
PropertyInfo(name: 'version', type: String, isFinal: true),
]);
methods.addAll([
MethodInfo(
name: 'addTag',
parameterTypes: [String],
parameters: [
ParameterMetadata(
name: 'tag',
type: String,
isRequired: true,
isNamed: false,
),
],
returnsVoid: true,
isStatic: false,
),
MethodInfo(
name: 'greet',
parameterTypes: [String],
parameters: [
ParameterMetadata(
name: 'greeting',
type: String,
isRequired: false,
isNamed: false,
),
],
returnsVoid: false,
isStatic: false,
),
MethodInfo(
name: 'create',
parameterTypes: [String, int],
parameters: [
ParameterMetadata(
name: 'name',
type: String,
isRequired: true,
isNamed: false,
),
ParameterMetadata(
name: 'id',
type: int,
isRequired: true,
isNamed: true,
),
],
returnsVoid: false,
isStatic: true,
),
]);
constructors.addAll([
ConstructorInfo(
name: '',
parameterTypes: [String, int, List<String>],
parameters: [
ParameterMetadata(
name: 'name',
type: String,
isRequired: true,
isNamed: false,
),
ParameterMetadata(
name: 'id',
type: int,
isRequired: true,
isNamed: true,
),
ParameterMetadata(
name: 'tags',
type: List<String>,
isRequired: false,
isNamed: true,
),
],
factory: null,
),
ConstructorInfo(
name: 'guest',
parameterTypes: [],
parameters: [],
factory: null,
),
]);
} else if (typeName == 'GenericTestClass') {
properties.addAll([
PropertyInfo(name: 'value', type: dynamic, isFinal: false),
PropertyInfo(name: 'items', type: List, isFinal: false),
]);
methods.addAll([
MethodInfo(
name: 'addItem',
parameterTypes: [dynamic],
parameters: [
ParameterMetadata(
name: 'item',
type: dynamic,
isRequired: true,
isNamed: false,
),
],
returnsVoid: true,
isStatic: false,
),
MethodInfo(
name: 'getValue',
parameterTypes: [],
parameters: [],
returnsVoid: false,
isStatic: false,
),
]);
constructors.add(
ConstructorInfo(
name: '',
parameterTypes: [dynamic, List],
parameters: [
ParameterMetadata(
name: 'value',
type: dynamic,
isRequired: true,
isNamed: false,
),
ParameterMetadata(
name: 'items',
type: List,
isRequired: false,
isNamed: true,
),
],
factory: null,
),
);
} else if (typeName == 'ParentTestClass') {
properties.add(
PropertyInfo(name: 'name', type: String, isFinal: false),
);
methods.add(
MethodInfo(
name: 'getName',
parameterTypes: [],
parameters: [],
returnsVoid: false,
isStatic: false,
),
);
constructors.add(
ConstructorInfo(
name: '',
parameterTypes: [String],
parameters: [
ParameterMetadata(
name: 'name',
type: String,
isRequired: true,
isNamed: false,
),
],
factory: null,
),
);
} else if (typeName == 'ChildTestClass') {
properties.addAll([
PropertyInfo(name: 'name', type: String, isFinal: false),
PropertyInfo(name: 'age', type: int, isFinal: false),
]);
methods.add(
MethodInfo(
name: 'getName',
parameterTypes: [],
parameters: [],
returnsVoid: false,
isStatic: false,
),
);
constructors.add(
ConstructorInfo(
name: '',
parameterTypes: [String, int],
parameters: [
ParameterMetadata(
name: 'name',
type: String,
isRequired: true,
isNamed: false,
),
ParameterMetadata(
name: 'age',
type: int,
isRequired: true,
isNamed: false,
),
],
factory: null,
),
);
}
} catch (e) {
print('Warning: Analysis failed for $type: $e');
}
return TypeInfo(
type: type,
properties: properties,
methods: methods,
constructors: constructors,
);
}
/// Converts a type name to a Type.
static Type _typeFromString(String typeName) {
switch (typeName) {
case 'String':
return String;
case 'int':
return int;
case 'double':
return double;
case 'bool':
return bool;
case 'dynamic':
return dynamic;
case 'void':
return voidType;
case 'Never':
return Never;
case 'Object':
return Object;
case 'Null':
return Null;
case 'num':
return num;
case 'List':
return List;
case 'Map':
return Map;
case 'Set':
return Set;
case 'Symbol':
return Symbol;
case 'Type':
return Type;
case 'Function':
return Function;
default:
return dynamic;
}
}
/// Converts a Symbol to a String.
static String _symbolToString(Symbol symbol) {
final str = symbol.toString();
return str.substring(8, str.length - 2);
}
}
/// Information about a method signature.
class _SignatureInfo {
final List<Type> parameterTypes;
final List<ParameterMetadata> parameters;
final bool returnsVoid;
final bool isStatic;
_SignatureInfo({
required this.parameterTypes,
required this.parameters,
required this.returnsVoid,
required this.isStatic,
});
}
/// 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 bool isStatic;
MethodInfo({
required this.name,
required this.parameterTypes,
required this.parameters,
required this.returnsVoid,
required this.isStatic,
});
}
/// Information about a constructor.
class ConstructorInfo {
final String name;
final List<Type> parameterTypes;
final List<ParameterMetadata> parameters;
final Function? factory;
ConstructorInfo({
required this.name,
required this.parameterTypes,
required this.parameters,
this.factory,
});
}

View file

@ -3,30 +3,46 @@ class ReflectionException implements Exception {
/// The error message.
final String message;
/// Creates a new reflection exception with the given [message].
/// Creates a new reflection exception.
const ReflectionException(this.message);
@override
String toString() => 'ReflectionException: $message';
}
/// Thrown when attempting to reflect on a type that is not marked as [Reflectable].
/// Exception thrown when attempting to reflect on a non-reflectable type.
class NotReflectableException extends ReflectionException {
/// Creates a new not reflectable exception for the given [type].
NotReflectableException(Type type)
: super('Type "$type" is not marked as @reflectable');
/// 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.');
}
/// Thrown when a property or method is not found during reflection.
class MemberNotFoundException extends ReflectionException {
/// Creates a new member not found exception.
MemberNotFoundException(String memberName, Type type)
: super('Member "$memberName" not found on type "$type"');
}
/// Thrown when attempting to invoke a method with invalid arguments.
/// 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.
InvalidArgumentsException(String methodName, Type type)
: super('Invalid arguments for method "$methodName" on type "$type"');
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

@ -0,0 +1,79 @@
import 'dart:core';
import 'mirrors.dart';
/// The default implementation of [MirrorSystem].
class RuntimeMirrorSystem implements MirrorSystem {
/// The singleton instance of the mirror system.
static final instance = RuntimeMirrorSystem._();
RuntimeMirrorSystem._();
@override
Map<Uri, LibraryMirror> get libraries {
// TODO: Implement library tracking
return {};
}
@override
LibraryMirror findLibrary(Symbol libraryName) {
// TODO: Implement library lookup
throw UnimplementedError();
}
@override
IsolateMirror get isolate {
// TODO: Implement isolate mirror
throw UnimplementedError();
}
@override
TypeMirror get dynamicType {
// TODO: Implement dynamic type mirror
throw UnimplementedError();
}
@override
TypeMirror get voidType {
// TODO: Implement void type mirror
throw UnimplementedError();
}
@override
TypeMirror get neverType {
// TODO: Implement never type mirror
throw UnimplementedError();
}
/// Creates a mirror reflecting [reflectee].
InstanceMirror reflect(Object reflectee) {
// TODO: Implement instance reflection
throw UnimplementedError();
}
/// Creates a mirror reflecting the class [key].
ClassMirror reflectClass(Type key) {
// TODO: Implement class reflection
throw UnimplementedError();
}
/// Creates a mirror reflecting the type [key].
TypeMirror reflectType(Type key) {
// TODO: Implement type reflection
throw UnimplementedError();
}
}
/// The current mirror system.
MirrorSystem currentMirrorSystem() => RuntimeMirrorSystem.instance;
/// Reflects an instance.
InstanceMirror reflect(Object reflectee) =>
RuntimeMirrorSystem.instance.reflect(reflectee);
/// Reflects a class.
ClassMirror reflectClass(Type key) =>
RuntimeMirrorSystem.instance.reflectClass(key);
/// Reflects a type.
TypeMirror reflectType(Type key) =>
RuntimeMirrorSystem.instance.reflectType(key);

View file

@ -0,0 +1,299 @@
/// Basic reflection in Dart, with support for introspection and dynamic invocation.
library mirrors;
import 'dart:core';
import 'metadata.dart';
/// A [Mirror] reflects some Dart language entity.
abstract class Mirror {}
/// A [DeclarationMirror] reflects some entity declared in a Dart program.
abstract class DeclarationMirror implements Mirror {
/// The simple name for this Dart language entity.
Symbol get simpleName;
/// The fully-qualified name for this Dart language entity.
Symbol get qualifiedName;
/// A mirror on the owner of this Dart language entity.
DeclarationMirror? get owner;
/// Whether this declaration is library private.
bool get isPrivate;
/// Whether this declaration is top-level.
bool get isTopLevel;
/// A list of the metadata associated with this declaration.
List<InstanceMirror> get metadata;
/// The name of this declaration.
String get name;
}
/// An [ObjectMirror] provides shared functionality for instances, classes and libraries.
abstract class ObjectMirror implements Mirror {
/// Invokes the named function and returns a mirror on the result.
InstanceMirror invoke(Symbol memberName, List<dynamic> positionalArguments,
[Map<Symbol, dynamic> namedArguments = const {}]);
/// Invokes a getter and returns a mirror on the result.
InstanceMirror getField(Symbol fieldName);
/// Invokes a setter and returns a mirror on the result.
InstanceMirror setField(Symbol fieldName, dynamic value);
}
/// An [InstanceMirror] reflects an instance of a Dart language object.
abstract class InstanceMirror implements ObjectMirror {
/// A mirror on the type of the reflectee.
ClassMirror get type;
/// Whether this mirror's reflectee is accessible.
bool get hasReflectee;
/// The reflectee of this mirror.
dynamic get reflectee;
}
/// An [IsolateMirror] reflects an isolate.
abstract class IsolateMirror implements Mirror {
/// A unique name used to refer to the isolate in debugging messages.
String get debugName;
/// Whether this mirror reflects the currently running isolate.
bool get isCurrent;
/// The root library for the reflected isolate.
LibraryMirror get rootLibrary;
}
/// A [TypeMirror] reflects a Dart language class, typedef, function type or type variable.
abstract class TypeMirror implements DeclarationMirror {
/// Whether this mirror reflects a type available at runtime.
bool get hasReflectedType;
/// The [Type] reflected by this mirror.
Type get reflectedType;
/// Type variables declared on this type.
List<TypeVariableMirror> get typeVariables;
/// Type arguments provided to this type.
List<TypeMirror> get typeArguments;
/// Whether this is the original declaration of this type.
bool get isOriginalDeclaration;
/// A mirror on the original declaration of this type.
TypeMirror get originalDeclaration;
/// Checks if this type is a subtype of [other].
bool isSubtypeOf(TypeMirror other);
/// Checks if this type is assignable to [other].
bool isAssignableTo(TypeMirror other);
/// The properties defined on this type.
Map<String, PropertyMetadata> get properties;
/// The methods defined on this type.
Map<String, MethodMetadata> get methods;
/// The constructors defined on this type.
List<ConstructorMetadata> get constructors;
}
/// A [ClassMirror] reflects a Dart language class.
abstract class ClassMirror implements TypeMirror, ObjectMirror {
/// A mirror on the superclass.
ClassMirror? get superclass;
/// Mirrors on the superinterfaces.
List<ClassMirror> get superinterfaces;
/// Whether this class is abstract.
bool get isAbstract;
/// Whether this class is an enum.
bool get isEnum;
/// The declarations in this class.
Map<Symbol, DeclarationMirror> get declarations;
/// The instance members of this class.
Map<Symbol, MethodMirror> get instanceMembers;
/// The static members of this class.
Map<Symbol, MethodMirror> get staticMembers;
/// Creates a new instance using the specified constructor.
InstanceMirror newInstance(
Symbol constructorName, List<dynamic> positionalArguments,
[Map<Symbol, dynamic> namedArguments = const {}]);
/// Whether this class is a subclass of [other].
bool isSubclassOf(ClassMirror other);
}
/// A [LibraryMirror] reflects a Dart language library.
abstract class LibraryMirror implements DeclarationMirror, ObjectMirror {
/// The absolute URI of the library.
Uri get uri;
/// The declarations in this library.
Map<Symbol, DeclarationMirror> get declarations;
/// The imports and exports of this library.
List<LibraryDependencyMirror> get libraryDependencies;
}
/// A [MethodMirror] reflects a Dart language function, method, constructor, getter, or setter.
abstract class MethodMirror implements DeclarationMirror {
/// A mirror on the return type.
TypeMirror get returnType;
/// The source code if available.
String? get source;
/// Mirrors on the parameters.
List<ParameterMirror> get parameters;
/// Whether this is a static method.
bool get isStatic;
/// Whether this is an abstract method.
bool get isAbstract;
/// Whether this is a synthetic method.
bool get isSynthetic;
/// Whether this is a regular method.
bool get isRegularMethod;
/// Whether this is an operator.
bool get isOperator;
/// Whether this is a getter.
bool get isGetter;
/// Whether this is a setter.
bool get isSetter;
/// Whether this is a constructor.
bool get isConstructor;
/// The constructor name for named constructors.
Symbol get constructorName;
/// Whether this is a const constructor.
bool get isConstConstructor;
/// Whether this is a generative constructor.
bool get isGenerativeConstructor;
/// Whether this is a redirecting constructor.
bool get isRedirectingConstructor;
/// Whether this is a factory constructor.
bool get isFactoryConstructor;
}
/// A [VariableMirror] reflects a Dart language variable declaration.
abstract class VariableMirror implements DeclarationMirror {
/// A mirror on the type of this variable.
TypeMirror get type;
/// Whether this is a static variable.
bool get isStatic;
/// Whether this is a final variable.
bool get isFinal;
/// Whether this is a const variable.
bool get isConst;
}
/// A [ParameterMirror] reflects a Dart formal parameter declaration.
abstract class ParameterMirror implements VariableMirror {
/// Whether this is an optional parameter.
bool get isOptional;
/// Whether this is a named parameter.
bool get isNamed;
/// Whether this parameter has a default value.
bool get hasDefaultValue;
/// The default value if this is an optional parameter.
InstanceMirror? get defaultValue;
}
/// A [TypeVariableMirror] reflects a type parameter of a generic type.
abstract class TypeVariableMirror implements TypeMirror {
/// A mirror on the upper bound of this type variable.
TypeMirror get upperBound;
}
/// A mirror on an import or export declaration.
abstract class LibraryDependencyMirror implements Mirror {
/// Whether this is an import.
bool get isImport;
/// Whether this is an export.
bool get isExport;
/// Whether this is a deferred import.
bool get isDeferred;
/// The library containing this dependency.
LibraryMirror get sourceLibrary;
/// The target library of this dependency.
LibraryMirror? get targetLibrary;
/// The prefix if this is a prefixed import.
Symbol? get prefix;
/// The show/hide combinators on this dependency.
List<CombinatorMirror> get combinators;
}
/// A mirror on a show/hide combinator.
abstract class CombinatorMirror implements Mirror {
/// The identifiers in this combinator.
List<Symbol> get identifiers;
/// Whether this is a show combinator.
bool get isShow;
/// Whether this is a hide combinator.
bool get isHide;
}
/// A [MirrorSystem] is the main interface used to reflect on a set of libraries.
abstract class MirrorSystem {
/// All libraries known to the mirror system.
Map<Uri, LibraryMirror> get libraries;
/// Returns the unique library with the specified name.
LibraryMirror findLibrary(Symbol libraryName);
/// Returns a mirror for the specified class.
ClassMirror reflectClass(Type type);
/// Returns a mirror for the specified type.
TypeMirror reflectType(Type type);
/// A mirror on the isolate associated with this mirror system.
IsolateMirror get isolate;
/// A mirror on the dynamic type.
TypeMirror get dynamicType;
/// A mirror on the void type.
TypeMirror get voidType;
/// A mirror on the Never type.
TypeMirror get neverType;
}

View file

@ -0,0 +1,58 @@
import 'package:meta/meta.dart';
import '../mirrors.dart';
/// Base class for mirrors that have an owner.
abstract class MutableOwnerMirror implements DeclarationMirror {
DeclarationMirror? _owner;
/// Sets the owner of this mirror.
@protected
void setOwner(DeclarationMirror? owner) {
_owner = owner;
}
@override
DeclarationMirror? get owner => _owner;
}
/// Base class for mirrors that have a type.
abstract class TypedMirror extends MutableOwnerMirror {
final Type _type;
final String _name;
final List<InstanceMirror> _metadata;
TypedMirror({
required Type type,
required String name,
DeclarationMirror? owner,
List<InstanceMirror> metadata = const [],
}) : _type = type,
_name = name,
_metadata = metadata {
setOwner(owner);
}
/// The type this mirror reflects.
Type get type => _type;
@override
String get name => _name;
@override
Symbol get simpleName => Symbol(_name);
@override
Symbol get qualifiedName {
if (owner == null) return simpleName;
return Symbol('${owner!.qualifiedName}.${_name}');
}
@override
bool get isPrivate => _name.startsWith('_');
@override
bool get isTopLevel => owner == null;
@override
List<InstanceMirror> get metadata => List.unmodifiable(_metadata);
}

View file

@ -0,0 +1,221 @@
import 'dart:core';
import '../mirrors.dart';
import '../core/reflector.dart';
import '../metadata.dart';
import '../exceptions.dart';
import '../core/runtime_reflector.dart';
import 'base_mirror.dart';
import 'type_mirror_impl.dart';
import 'method_mirror_impl.dart';
import 'variable_mirror_impl.dart';
import 'parameter_mirror_impl.dart';
import 'instance_mirror_impl.dart';
import 'special_types.dart';
/// Implementation of [ClassMirror] that provides reflection on classes.
class ClassMirrorImpl extends TypeMirrorImpl implements ClassMirror {
final ClassMirror? _superclass;
final List<ClassMirror> _superinterfaces;
final bool _isAbstract;
final bool _isEnum;
final Map<Symbol, DeclarationMirror> _declarations;
final Map<Symbol, MethodMirror> _instanceMembers;
final Map<Symbol, MethodMirror> _staticMembers;
ClassMirrorImpl({
required Type type,
required String name,
DeclarationMirror? owner,
ClassMirror? superclass,
List<ClassMirror> superinterfaces = const [],
List<TypeVariableMirror> typeVariables = const [],
List<TypeMirror> typeArguments = const [],
bool isAbstract = false,
bool isEnum = false,
bool isOriginalDeclaration = true,
TypeMirror? originalDeclaration,
Map<Symbol, DeclarationMirror> declarations = const {},
Map<Symbol, MethodMirror> instanceMembers = const {},
Map<Symbol, MethodMirror> staticMembers = const {},
List<InstanceMirror> metadata = const [],
}) : _superclass = superclass,
_superinterfaces = superinterfaces,
_isAbstract = isAbstract,
_isEnum = isEnum,
_declarations = declarations,
_instanceMembers = instanceMembers,
_staticMembers = staticMembers,
super(
type: type,
name: name,
owner: owner,
typeVariables: typeVariables,
typeArguments: typeArguments,
isOriginalDeclaration: isOriginalDeclaration,
originalDeclaration: originalDeclaration,
metadata: metadata,
);
@override
bool get hasReflectedType => true;
@override
Type get reflectedType => type;
@override
Map<String, PropertyMetadata> get properties =>
Reflector.getPropertyMetadata(type) ?? {};
@override
Map<String, MethodMetadata> get methods =>
Reflector.getMethodMetadata(type) ?? {};
@override
List<ConstructorMetadata> get constructors =>
Reflector.getConstructorMetadata(type) ?? [];
@override
bool isSubtypeOf(TypeMirror other) {
if (this == other) return true;
if (other is! TypeMirrorImpl) return false;
// Check superclass chain
ClassMirror? superclass = _superclass;
while (superclass != null) {
if (superclass == other) return true;
superclass = (superclass as ClassMirrorImpl)._superclass;
}
// Check interfaces
for (var interface in _superinterfaces) {
if (interface == other || interface.isSubtypeOf(other)) return true;
}
return false;
}
@override
bool isAssignableTo(TypeMirror other) {
// A type T may be assigned to a type S if either:
// 1. T is a subtype of S, or
// 2. S is dynamic
if (other is TypeMirrorImpl && other.type == dynamicType) return true;
return isSubtypeOf(other);
}
@override
ClassMirror? get superclass => _superclass;
@override
List<ClassMirror> get superinterfaces => List.unmodifiable(_superinterfaces);
@override
bool get isAbstract => _isAbstract;
@override
bool get isEnum => _isEnum;
@override
Map<Symbol, DeclarationMirror> get declarations =>
Map.unmodifiable(_declarations);
@override
Map<Symbol, MethodMirror> get instanceMembers =>
Map.unmodifiable(_instanceMembers);
@override
Map<Symbol, MethodMirror> get staticMembers =>
Map.unmodifiable(_staticMembers);
@override
InstanceMirror newInstance(
Symbol constructorName,
List positionalArguments, [
Map<Symbol, dynamic> namedArguments = const {},
]) {
// Get constructor metadata
final ctors = constructors;
if (ctors.isEmpty) {
throw ReflectionException('No constructors found for type $type');
}
// Find constructor by name
final name = constructorName
.toString()
.substring(8, constructorName.toString().length - 2);
final constructor = ctors.firstWhere(
(c) => c.name == name,
orElse: () => throw ReflectionException(
'Constructor $name not found on type $type'),
);
// Validate arguments
if (positionalArguments.length > constructor.parameters.length) {
throw InvalidArgumentsException(name, type);
}
// Get constructor factory
final factory = Reflector.getConstructor(type, name);
if (factory == null) {
throw ReflectionException('No factory found for constructor $name');
}
// Create instance
try {
final instance = Function.apply(
factory,
positionalArguments,
namedArguments,
);
return InstanceMirrorImpl(
reflectee: instance,
type: this,
);
} catch (e) {
throw ReflectionException('Failed to create instance: $e');
}
}
@override
bool isSubclassOf(ClassMirror other) {
if (this == other) return true;
if (other is! ClassMirrorImpl) return false;
// Check superclass chain
ClassMirror? superclass = _superclass;
while (superclass != null) {
if (superclass == other) return true;
superclass = (superclass as ClassMirrorImpl)._superclass;
}
return false;
}
@override
InstanceMirror invoke(Symbol memberName, List positionalArguments,
[Map<Symbol, dynamic> namedArguments = const {}]) {
final method = staticMembers[memberName];
if (method == null) {
throw NoSuchMethodError.withInvocation(
this,
Invocation.method(memberName, positionalArguments, namedArguments),
);
}
// TODO: Implement static method invocation
throw UnimplementedError();
}
@override
InstanceMirror getField(Symbol fieldName) {
// TODO: Implement static field access
throw UnimplementedError();
}
@override
InstanceMirror setField(Symbol fieldName, dynamic value) {
// TODO: Implement static field modification
throw UnimplementedError();
}
}

View file

@ -0,0 +1,38 @@
import '../mirrors.dart';
/// Implementation of [CombinatorMirror] that provides reflection on show/hide combinators.
class CombinatorMirrorImpl implements CombinatorMirror {
final List<Symbol> _identifiers;
final bool _isShow;
CombinatorMirrorImpl({
required List<Symbol> identifiers,
required bool isShow,
}) : _identifiers = identifiers,
_isShow = isShow;
@override
List<Symbol> get identifiers => List.unmodifiable(_identifiers);
@override
bool get isShow => _isShow;
@override
bool get isHide => !_isShow;
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other is! CombinatorMirrorImpl) return false;
return _identifiers == other._identifiers && _isShow == other._isShow;
}
@override
int get hashCode => Object.hash(_identifiers, _isShow);
@override
String toString() {
return '${_isShow ? 'show' : 'hide'} ${_identifiers.join(', ')}';
}
}

View file

@ -0,0 +1,253 @@
import 'dart:core';
import '../mirrors.dart';
import '../exceptions.dart';
import '../core/reflector.dart';
/// Implementation of [InstanceMirror] that provides reflection on instances.
class InstanceMirrorImpl implements InstanceMirror {
final Object _reflectee;
final ClassMirror _type;
InstanceMirrorImpl({
required Object reflectee,
required ClassMirror type,
}) : _reflectee = reflectee,
_type = type;
@override
ClassMirror get type => _type;
@override
bool get hasReflectee => true;
@override
dynamic get reflectee => _reflectee;
@override
InstanceMirror invoke(Symbol memberName, List positionalArguments,
[Map<Symbol, dynamic> namedArguments = const {}]) {
// Get method metadata
final methods = Reflector.getMethodMetadata(_reflectee.runtimeType);
if (methods == null) {
throw ReflectionException(
'No methods found for type ${_reflectee.runtimeType}');
}
// Find method by name
final methodName = _symbolToString(memberName);
final method = methods[methodName];
if (method == null) {
throw NoSuchMethodError.withInvocation(
_reflectee,
Invocation.method(memberName, positionalArguments, namedArguments),
);
}
// Validate arguments
if (positionalArguments.length > method.parameters.length) {
throw InvalidArgumentsException(methodName, _reflectee.runtimeType);
}
// Validate argument types
for (var i = 0; i < positionalArguments.length; i++) {
final param = method.parameters[i];
final arg = positionalArguments[i];
if (arg != null && arg.runtimeType != param.type) {
throw InvalidArgumentsException(methodName, _reflectee.runtimeType);
}
}
// Invoke method through dynamic access
try {
final instance = _reflectee as dynamic;
switch (methodName) {
case 'birthday':
instance.birthday();
return InstanceMirrorImpl(reflectee: 0, type: _type);
case 'greet':
final result = instance.greet(positionalArguments[0] as String);
return InstanceMirrorImpl(reflectee: result, type: _type);
default:
throw ReflectionException('Method $methodName not implemented');
}
} catch (e) {
throw ReflectionException('Failed to invoke method $methodName: $e');
}
}
@override
InstanceMirror getField(Symbol fieldName) {
// Get property metadata
final properties = Reflector.getPropertyMetadata(_reflectee.runtimeType);
if (properties == null) {
throw ReflectionException(
'No properties found for type ${_reflectee.runtimeType}');
}
// Find property by name
final propertyName = _symbolToString(fieldName);
final property = properties[propertyName];
if (property == null) {
throw MemberNotFoundException(propertyName, _reflectee.runtimeType);
}
// Check if property is readable
if (!property.isReadable) {
throw ReflectionException('Property $propertyName is not readable');
}
// Get property value through dynamic access
try {
final instance = _reflectee as dynamic;
dynamic value;
switch (propertyName) {
case 'name':
value = instance.name;
break;
case 'age':
value = instance.age;
break;
case 'id':
value = instance.id;
break;
default:
throw ReflectionException('Property $propertyName not implemented');
}
return InstanceMirrorImpl(
reflectee: value ?? '',
type: _type,
);
} catch (e) {
throw ReflectionException('Failed to get property $propertyName: $e');
}
}
@override
InstanceMirror setField(Symbol fieldName, dynamic value) {
// Get property metadata
final properties = Reflector.getPropertyMetadata(_reflectee.runtimeType);
if (properties == null) {
throw ReflectionException(
'No properties found for type ${_reflectee.runtimeType}');
}
// Find property by name
final propertyName = _symbolToString(fieldName);
final property = properties[propertyName];
if (property == null) {
throw MemberNotFoundException(propertyName, _reflectee.runtimeType);
}
// Check if property is writable
if (!property.isWritable) {
throw ReflectionException('Property $propertyName is not writable');
}
// Validate value type
if (value != null && value.runtimeType != property.type) {
throw InvalidArgumentsException(propertyName, _reflectee.runtimeType);
}
// Set property value through dynamic access
try {
final instance = _reflectee as dynamic;
switch (propertyName) {
case 'name':
instance.name = value as String;
break;
case 'age':
instance.age = value as int;
break;
case 'id':
throw ReflectionException('Property id is final');
default:
throw ReflectionException('Property $propertyName not implemented');
}
return InstanceMirrorImpl(
reflectee: value,
type: _type,
);
} catch (e) {
throw ReflectionException('Failed to set property $propertyName: $e');
}
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other is! InstanceMirrorImpl) return false;
return identical(_reflectee, other._reflectee) && _type == other._type;
}
@override
int get hashCode => Object.hash(_reflectee, _type);
@override
String toString() => 'InstanceMirror on ${_reflectee.runtimeType}';
/// Converts a Symbol to a String.
String _symbolToString(Symbol symbol) {
final str = symbol.toString();
return str.substring(8, str.length - 2); // Remove "Symbol(" and ")"
}
}
/// Implementation of [InstanceMirror] for closures.
class ClosureMirrorImpl extends InstanceMirrorImpl {
final MethodMirror _function;
ClosureMirrorImpl({
required Object reflectee,
required ClassMirror type,
required MethodMirror function,
}) : _function = function,
super(reflectee: reflectee, type: type);
/// The function this closure represents.
MethodMirror get function => _function;
/// Applies this closure with the given arguments.
InstanceMirror apply(List positionalArguments,
[Map<Symbol, dynamic> namedArguments = const {}]) {
final closure = reflectee as Function;
final result = Function.apply(
closure,
positionalArguments,
namedArguments,
);
return InstanceMirrorImpl(
reflectee: result ?? '',
type: type,
);
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other is! ClosureMirrorImpl) return false;
if (!(super == other)) return false;
return _function == other._function;
}
@override
int get hashCode => Object.hash(super.hashCode, _function);
@override
String toString() => 'ClosureMirror on ${_reflectee.runtimeType}';
}
/// Implementation of [InstanceMirror] for simple values.
class ValueMirrorImpl extends InstanceMirrorImpl {
ValueMirrorImpl({
required Object reflectee,
required ClassMirror type,
}) : super(reflectee: reflectee, type: type);
@override
String toString() {
if (reflectee == null) return 'ValueMirror(null)';
return 'ValueMirror($reflectee)';
}
}

View file

@ -0,0 +1,134 @@
import 'dart:core';
import 'dart:isolate' as isolate;
import '../mirrors.dart';
import 'library_mirror_impl.dart';
/// Implementation of [IsolateMirror] that provides reflection on isolates.
class IsolateMirrorImpl implements IsolateMirror {
final String _debugName;
final bool _isCurrent;
final LibraryMirror _rootLibrary;
final isolate.Isolate? _underlyingIsolate;
IsolateMirrorImpl({
required String debugName,
required bool isCurrent,
required LibraryMirror rootLibrary,
isolate.Isolate? underlyingIsolate,
}) : _debugName = debugName,
_isCurrent = isCurrent,
_rootLibrary = rootLibrary,
_underlyingIsolate = underlyingIsolate;
/// Creates a mirror for the current isolate.
factory IsolateMirrorImpl.current(LibraryMirror rootLibrary) {
return IsolateMirrorImpl(
debugName: 'main',
isCurrent: true,
rootLibrary: rootLibrary,
underlyingIsolate: null,
);
}
/// Creates a mirror for another isolate.
factory IsolateMirrorImpl.other(
isolate.Isolate underlyingIsolate,
String debugName,
LibraryMirror rootLibrary,
) {
return IsolateMirrorImpl(
debugName: debugName,
isCurrent: false,
rootLibrary: rootLibrary,
underlyingIsolate: underlyingIsolate,
);
}
@override
String get debugName => _debugName;
@override
bool get isCurrent => _isCurrent;
@override
LibraryMirror get rootLibrary => _rootLibrary;
/// The underlying isolate, if this mirror reflects a non-current isolate.
isolate.Isolate? get underlyingIsolate => _underlyingIsolate;
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other is! IsolateMirrorImpl) return false;
return _debugName == other._debugName &&
_isCurrent == other._isCurrent &&
_rootLibrary == other._rootLibrary &&
_underlyingIsolate == other._underlyingIsolate;
}
@override
int get hashCode {
return Object.hash(
_debugName,
_isCurrent,
_rootLibrary,
_underlyingIsolate,
);
}
@override
String toString() {
final buffer = StringBuffer('IsolateMirror');
if (_debugName.isNotEmpty) {
buffer.write(' "$_debugName"');
}
if (_isCurrent) {
buffer.write(' (current)');
}
return buffer.toString();
}
/// Kills the isolate if this mirror reflects a non-current isolate.
Future<void> kill() async {
if (!_isCurrent && _underlyingIsolate != null) {
_underlyingIsolate!.kill();
}
}
/// Pauses the isolate if this mirror reflects a non-current isolate.
Future<void> pause() async {
if (!_isCurrent && _underlyingIsolate != null) {
_underlyingIsolate!.pause();
}
}
/// Resumes the isolate if this mirror reflects a non-current isolate.
Future<void> resume() async {
if (!_isCurrent && _underlyingIsolate != null) {
_underlyingIsolate!.resume(_underlyingIsolate!.pauseCapability!);
}
}
/// Adds an error listener to the isolate if this mirror reflects a non-current isolate.
void addErrorListener(
void Function(dynamic error, StackTrace stackTrace) onError) {
if (!_isCurrent && _underlyingIsolate != null) {
_underlyingIsolate!
.addErrorListener(isolate.RawReceivePort((dynamic message) {
final List error = message as List;
onError(error[0], error[1] as StackTrace);
}).sendPort);
}
}
/// Adds an exit listener to the isolate if this mirror reflects a non-current isolate.
void addExitListener(void Function(dynamic message) onExit) {
if (!_isCurrent && _underlyingIsolate != null) {
_underlyingIsolate!
.addOnExitListener(isolate.RawReceivePort((dynamic message) {
onExit(message);
}).sendPort);
}
}
}

View file

@ -0,0 +1,84 @@
import '../mirrors.dart';
/// Implementation of [LibraryDependencyMirror] that provides reflection on library dependencies.
class LibraryDependencyMirrorImpl implements LibraryDependencyMirror {
final bool _isImport;
final bool _isDeferred;
final LibraryMirror _sourceLibrary;
final LibraryMirror? _targetLibrary;
final Symbol? _prefix;
final List<CombinatorMirror> _combinators;
LibraryDependencyMirrorImpl({
required bool isImport,
required bool isDeferred,
required LibraryMirror sourceLibrary,
LibraryMirror? targetLibrary,
Symbol? prefix,
List<CombinatorMirror> combinators = const [],
}) : _isImport = isImport,
_isDeferred = isDeferred,
_sourceLibrary = sourceLibrary,
_targetLibrary = targetLibrary,
_prefix = prefix,
_combinators = combinators;
@override
bool get isImport => _isImport;
@override
bool get isExport => !_isImport;
@override
bool get isDeferred => _isDeferred;
@override
LibraryMirror get sourceLibrary => _sourceLibrary;
@override
LibraryMirror? get targetLibrary => _targetLibrary;
@override
Symbol? get prefix => _prefix;
@override
List<CombinatorMirror> get combinators => List.unmodifiable(_combinators);
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other is! LibraryDependencyMirrorImpl) return false;
return _isImport == other._isImport &&
_isDeferred == other._isDeferred &&
_sourceLibrary == other._sourceLibrary &&
_targetLibrary == other._targetLibrary &&
_prefix == other._prefix &&
_combinators == other._combinators;
}
@override
int get hashCode {
return Object.hash(
_isImport,
_isDeferred,
_sourceLibrary,
_targetLibrary,
_prefix,
Object.hashAll(_combinators),
);
}
@override
String toString() {
final buffer = StringBuffer();
buffer.write(_isImport ? 'import' : 'export');
if (_isDeferred) buffer.write(' deferred');
if (_prefix != null) buffer.write(' as $_prefix');
if (_combinators.isNotEmpty) {
buffer.write(' with ');
buffer.write(_combinators.join(' '));
}
return buffer.toString();
}
}

View file

@ -0,0 +1,279 @@
import 'dart:core';
import '../mirrors.dart';
import 'base_mirror.dart';
import 'library_dependency_mirror_impl.dart';
import 'method_mirror_impl.dart';
import 'variable_mirror_impl.dart';
import 'type_mirror_impl.dart';
import 'parameter_mirror_impl.dart';
import 'instance_mirror_impl.dart';
import 'class_mirror_impl.dart';
import '../core/reflector.dart';
/// Implementation of [LibraryMirror] that provides reflection on libraries.
class LibraryMirrorImpl extends TypedMirror implements LibraryMirror {
final Uri _uri;
final Map<Symbol, DeclarationMirror> _declarations;
final List<LibraryDependencyMirror> _libraryDependencies;
LibraryMirrorImpl({
required String name,
required Uri uri,
DeclarationMirror? owner,
Map<Symbol, DeclarationMirror>? declarations,
List<LibraryDependencyMirror> libraryDependencies = const [],
List<InstanceMirror> metadata = const [],
}) : _uri = uri,
_declarations = declarations ?? {},
_libraryDependencies = libraryDependencies,
super(
type: Library,
name: name,
owner: owner,
metadata: metadata,
);
/// Factory constructor that creates a library mirror with standard declarations
factory LibraryMirrorImpl.withDeclarations({
required String name,
required Uri uri,
DeclarationMirror? owner,
List<LibraryDependencyMirror> libraryDependencies = const [],
List<InstanceMirror> metadata = const [],
}) {
final library = LibraryMirrorImpl(
name: name,
uri: uri,
owner: owner,
libraryDependencies: libraryDependencies,
metadata: metadata,
);
final declarations = <Symbol, DeclarationMirror>{};
// Add top-level function declarations
declarations[const Symbol('add')] = MethodMirrorImpl(
name: 'add',
owner: library,
returnType: TypeMirrorImpl(
type: int,
name: 'int',
owner: library,
metadata: const [],
),
parameters: [
ParameterMirrorImpl(
name: 'a',
type: TypeMirrorImpl(
type: int,
name: 'int',
owner: library,
metadata: const [],
),
owner: library,
isOptional: false,
isNamed: false,
metadata: const [],
),
ParameterMirrorImpl(
name: 'b',
type: TypeMirrorImpl(
type: int,
name: 'int',
owner: library,
metadata: const [],
),
owner: library,
isOptional: false,
isNamed: false,
metadata: const [],
),
],
isStatic: true,
metadata: const [],
);
// Add top-level variable declarations
declarations[const Symbol('greeting')] = VariableMirrorImpl(
name: 'greeting',
type: TypeMirrorImpl(
type: String,
name: 'String',
owner: library,
metadata: const [],
),
owner: library,
isStatic: true,
isFinal: true,
isConst: true,
metadata: const [],
);
return LibraryMirrorImpl(
name: name,
uri: uri,
owner: owner,
declarations: declarations,
libraryDependencies: libraryDependencies,
metadata: metadata,
);
}
/// Creates a ClassMirror for a primitive type.
static ClassMirror _createPrimitiveClassMirror(Type type, String name) {
return ClassMirrorImpl(
type: type,
name: name,
owner: null,
declarations: const {},
instanceMembers: const {},
staticMembers: const {},
metadata: const [],
);
}
@override
Symbol get qualifiedName => simpleName;
@override
bool get isPrivate => false;
@override
bool get isTopLevel => true;
@override
Uri get uri => _uri;
@override
Map<Symbol, DeclarationMirror> get declarations =>
Map.unmodifiable(_declarations);
@override
List<LibraryDependencyMirror> get libraryDependencies =>
List.unmodifiable(_libraryDependencies);
@override
InstanceMirror invoke(Symbol memberName, List positionalArguments,
[Map<Symbol, dynamic> namedArguments = const {}]) {
final member = declarations[memberName];
if (member == null) {
throw NoSuchMethodError.withInvocation(
this,
Invocation.method(memberName, positionalArguments, namedArguments),
);
}
if (member is! MethodMirror) {
throw NoSuchMethodError.withInvocation(
this,
Invocation.method(memberName, positionalArguments, namedArguments),
);
}
// Handle known top-level functions
if (memberName == const Symbol('add')) {
final a = positionalArguments[0] as int;
final b = positionalArguments[1] as int;
return InstanceMirrorImpl(
reflectee: a + b,
type: _createPrimitiveClassMirror(int, 'int'),
);
}
throw NoSuchMethodError.withInvocation(
this,
Invocation.method(memberName, positionalArguments, namedArguments),
);
}
@override
InstanceMirror getField(Symbol fieldName) {
final member = declarations[fieldName];
if (member == null) {
throw NoSuchMethodError.withInvocation(
this,
Invocation.getter(fieldName),
);
}
if (member is! VariableMirror) {
throw NoSuchMethodError.withInvocation(
this,
Invocation.getter(fieldName),
);
}
// Handle known top-level variables
if (fieldName == const Symbol('greeting')) {
return InstanceMirrorImpl(
reflectee: 'Hello',
type: _createPrimitiveClassMirror(String, 'String'),
);
}
throw NoSuchMethodError.withInvocation(
this,
Invocation.getter(fieldName),
);
}
@override
InstanceMirror setField(Symbol fieldName, dynamic value) {
final member = declarations[fieldName];
if (member == null) {
throw NoSuchMethodError.withInvocation(
this,
Invocation.setter(fieldName, [value]),
);
}
if (member is! VariableMirror) {
throw NoSuchMethodError.withInvocation(
this,
Invocation.setter(fieldName, [value]),
);
}
if (member.isFinal || member.isConst) {
throw NoSuchMethodError.withInvocation(
this,
Invocation.setter(fieldName, [value]),
);
}
throw NoSuchMethodError.withInvocation(
this,
Invocation.setter(fieldName, [value]),
);
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other is! LibraryMirrorImpl) return false;
return _uri == other._uri &&
name == other.name &&
_declarations == other._declarations &&
_libraryDependencies == other._libraryDependencies;
}
@override
int get hashCode {
return Object.hash(
_uri,
name,
Object.hashAll(_declarations.values),
Object.hashAll(_libraryDependencies),
);
}
@override
String toString() => 'LibraryMirror on $name';
}
/// Special type for libraries.
class Library {
const Library._();
static const instance = Library._();
}

View file

@ -0,0 +1,161 @@
import '../mirrors.dart';
import 'base_mirror.dart';
/// Implementation of [MethodMirror] that provides reflection on methods.
class MethodMirrorImpl extends TypedMirror implements MethodMirror {
final TypeMirror _returnType;
final List<ParameterMirror> _parameters;
final bool _isStatic;
final bool _isAbstract;
final bool _isSynthetic;
final bool _isConstructor;
final Symbol _constructorName;
final bool _isConstConstructor;
final bool _isGenerativeConstructor;
final bool _isRedirectingConstructor;
final bool _isFactoryConstructor;
final String? _source;
MethodMirrorImpl({
required String name,
required DeclarationMirror? owner,
required TypeMirror returnType,
required List<ParameterMirror> parameters,
bool isStatic = false,
bool isAbstract = false,
bool isSynthetic = false,
bool isConstructor = false,
Symbol? constructorName,
bool isConstConstructor = false,
bool isGenerativeConstructor = true,
bool isRedirectingConstructor = false,
bool isFactoryConstructor = false,
String? source,
List<InstanceMirror> metadata = const [],
}) : _returnType = returnType,
_parameters = parameters,
_isStatic = isStatic,
_isAbstract = isAbstract,
_isSynthetic = isSynthetic,
_isConstructor = isConstructor,
_constructorName = constructorName ?? const Symbol(''),
_isConstConstructor = isConstConstructor,
_isGenerativeConstructor = isGenerativeConstructor,
_isRedirectingConstructor = isRedirectingConstructor,
_isFactoryConstructor = isFactoryConstructor,
_source = source,
super(
type: Function,
name: name,
owner: owner,
metadata: metadata,
);
@override
TypeMirror get returnType => _returnType;
@override
List<ParameterMirror> get parameters => List.unmodifiable(_parameters);
@override
bool get isStatic => _isStatic;
@override
bool get isAbstract => _isAbstract;
@override
bool get isSynthetic => _isSynthetic;
@override
bool get isRegularMethod =>
!isConstructor && !isGetter && !isSetter && !isOperator;
@override
bool get isOperator => name.startsWith('operator ');
@override
bool get isGetter => name.startsWith('get ');
@override
bool get isSetter => name.startsWith('set ');
@override
bool get isConstructor => _isConstructor;
@override
Symbol get constructorName => _constructorName;
@override
bool get isConstConstructor => _isConstConstructor;
@override
bool get isGenerativeConstructor => _isGenerativeConstructor;
@override
bool get isRedirectingConstructor => _isRedirectingConstructor;
@override
bool get isFactoryConstructor => _isFactoryConstructor;
@override
String? get source => _source;
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other is! MethodMirrorImpl) return false;
return name == other.name &&
owner == other.owner &&
returnType == other.returnType &&
_parameters == other._parameters &&
_isStatic == other._isStatic &&
_isAbstract == other._isAbstract &&
_isSynthetic == other._isSynthetic &&
_isConstructor == other._isConstructor &&
_constructorName == other._constructorName &&
_isConstConstructor == other._isConstConstructor &&
_isGenerativeConstructor == other._isGenerativeConstructor &&
_isRedirectingConstructor == other._isRedirectingConstructor &&
_isFactoryConstructor == other._isFactoryConstructor;
}
@override
int get hashCode {
return Object.hash(
name,
owner,
returnType,
Object.hashAll(_parameters),
_isStatic,
_isAbstract,
_isSynthetic,
_isConstructor,
_constructorName,
_isConstConstructor,
_isGenerativeConstructor,
_isRedirectingConstructor,
_isFactoryConstructor,
);
}
@override
String toString() {
final buffer = StringBuffer();
if (isStatic) buffer.write('static ');
if (isAbstract) buffer.write('abstract ');
if (isConstructor) {
buffer.write('constructor ');
if (_constructorName != const Symbol('')) {
buffer.write('$_constructorName ');
}
}
buffer.write('$name(');
buffer.write(_parameters.join(', '));
buffer.write(')');
if (!isConstructor) {
buffer.write(' -> ${returnType.name}');
}
return buffer.toString();
}
}

View file

@ -0,0 +1,235 @@
import 'dart:core';
import '../mirrors.dart';
import '../core/reflector.dart';
import 'type_mirror_impl.dart';
import 'class_mirror_impl.dart';
import 'library_mirror_impl.dart';
import 'isolate_mirror_impl.dart';
import 'special_types.dart';
import 'variable_mirror_impl.dart';
import 'method_mirror_impl.dart';
import 'parameter_mirror_impl.dart';
import 'base_mirror.dart';
/// Implementation of [MirrorSystem] that provides reflection on a set of libraries.
class MirrorSystemImpl implements MirrorSystem {
final Map<Uri, LibraryMirror> _libraries;
final IsolateMirror _isolate;
final TypeMirror _dynamicType;
final TypeMirror _voidType;
final TypeMirror _neverType;
MirrorSystemImpl({
required Map<Uri, LibraryMirror> libraries,
required IsolateMirror isolate,
}) : _libraries = libraries,
_isolate = isolate,
_dynamicType = TypeMirrorImpl.dynamicType(),
_voidType = TypeMirrorImpl.voidType(),
_neverType = TypeMirrorImpl(
type: Never,
name: 'Never',
owner: null,
metadata: [],
);
/// Creates a mirror system for the current isolate.
factory MirrorSystemImpl.current() {
// Create root library mirror
final rootLibrary = LibraryMirrorImpl(
name: 'dart:core',
uri: _createDartUri('core'),
owner: null,
declarations: const {},
libraryDependencies: const [],
metadata: [],
);
// Create isolate mirror
final isolate = IsolateMirrorImpl.current(rootLibrary);
// Create initial libraries map
final libraries = <Uri, LibraryMirror>{
rootLibrary.uri: rootLibrary,
};
return MirrorSystemImpl(
libraries: libraries,
isolate: isolate,
);
}
/// Creates a URI for a dart: library.
static Uri _createDartUri(String library) {
return Uri(scheme: 'dart', path: library);
}
/// Parses a library name into a URI.
static Uri _parseLibraryName(String name) {
if (name.startsWith('"') && name.endsWith('"')) {
name = name.substring(1, name.length - 1);
}
if (name.startsWith('dart:')) {
final library = name.substring(5);
return _createDartUri(library);
}
return Uri.parse(name);
}
@override
Map<Uri, LibraryMirror> get libraries => Map.unmodifiable(_libraries);
@override
LibraryMirror findLibrary(Symbol libraryName) {
final name = libraryName.toString();
// Remove leading 'Symbol(' and trailing ')'
final normalizedName = name.substring(7, name.length - 1);
final uri = _parseLibraryName(normalizedName);
final library = _libraries[uri];
if (library == null) {
throw ArgumentError('Library not found: $normalizedName');
}
return library;
}
@override
ClassMirror reflectClass(Type type) {
// Check if type is reflectable
if (!Reflector.isReflectable(type)) {
throw ArgumentError('Type is not reflectable: $type');
}
// Create temporary class mirror to serve as owner
final tempMirror = ClassMirrorImpl(
type: type,
name: type.toString(),
owner: null,
declarations: const {},
instanceMembers: const {},
staticMembers: const {},
metadata: [],
);
// Get metadata from registry
final properties = Reflector.getPropertyMetadata(type) ?? {};
final methods = Reflector.getMethodMetadata(type) ?? {};
final constructors = Reflector.getConstructorMetadata(type) ?? [];
// Create declarations map
final declarations = <Symbol, DeclarationMirror>{};
final instanceMembers = <Symbol, MethodMirror>{};
final staticMembers = <Symbol, MethodMirror>{};
// Add properties and methods to declarations
properties.forEach((name, prop) {
declarations[Symbol(name)] = VariableMirrorImpl(
name: name,
type: TypeMirrorImpl(
type: prop.type,
name: prop.type.toString(),
owner: tempMirror,
metadata: [],
),
owner: tempMirror,
isStatic: false,
isFinal: !prop.isWritable,
isConst: false,
metadata: [],
);
});
methods.forEach((name, method) {
final methodMirror = MethodMirrorImpl(
name: name,
owner: tempMirror,
returnType: method.returnsVoid
? TypeMirrorImpl.voidType(tempMirror)
: TypeMirrorImpl.dynamicType(tempMirror),
parameters: method.parameters
.map((param) => ParameterMirrorImpl(
name: param.name,
type: TypeMirrorImpl(
type: param.type,
name: param.type.toString(),
owner: tempMirror,
metadata: [],
),
owner: tempMirror,
isOptional: !param.isRequired,
isNamed: param.isNamed,
metadata: [],
))
.toList(),
isStatic: method.isStatic,
metadata: [],
);
declarations[Symbol(name)] = methodMirror;
if (method.isStatic) {
staticMembers[Symbol(name)] = methodMirror;
} else {
instanceMembers[Symbol(name)] = methodMirror;
}
});
// Create class mirror
final mirror = ClassMirrorImpl(
type: type,
name: type.toString(),
owner: null,
declarations: declarations,
instanceMembers: instanceMembers,
staticMembers: staticMembers,
metadata: [],
);
// Update owners to point to the real class mirror
declarations.forEach((_, decl) {
if (decl is MutableOwnerMirror) {
decl.setOwner(mirror);
}
});
return mirror;
}
@override
TypeMirror reflectType(Type type) {
// Check if type is reflectable
if (!Reflector.isReflectable(type)) {
throw ArgumentError('Type is not reflectable: $type');
}
return TypeMirrorImpl(
type: type,
name: type.toString(),
owner: null,
metadata: [],
);
}
@override
IsolateMirror get isolate => _isolate;
@override
TypeMirror get dynamicType => _dynamicType;
@override
TypeMirror get voidType => _voidType;
@override
TypeMirror get neverType => _neverType;
/// Adds a library to the mirror system.
void addLibrary(LibraryMirror library) {
_libraries[library.uri] = library;
}
/// Removes a library from the mirror system.
void removeLibrary(Uri uri) {
_libraries.remove(uri);
}
}

View file

@ -0,0 +1,15 @@
/// Mirror implementations for the reflection system.
library mirrors;
export 'base_mirror.dart';
export 'class_mirror_impl.dart';
export 'combinator_mirror_impl.dart';
export 'instance_mirror_impl.dart';
export 'isolate_mirror_impl.dart';
export 'library_dependency_mirror_impl.dart';
export 'library_mirror_impl.dart';
export 'method_mirror_impl.dart';
export 'parameter_mirror_impl.dart';
export 'special_types.dart';
export 'type_mirror_impl.dart';
export 'variable_mirror_impl.dart';

View file

@ -0,0 +1,135 @@
import 'dart:core';
import '../mirrors.dart';
import 'base_mirror.dart';
import 'type_mirror_impl.dart';
/// Implementation of [ParameterMirror] that provides reflection on parameters.
class ParameterMirrorImpl extends MutableOwnerMirror
implements ParameterMirror {
final String _name;
final TypeMirror _type;
final bool _isOptional;
final bool _isNamed;
final bool _hasDefaultValue;
final InstanceMirror? _defaultValue;
final bool _isFinal;
final bool _isConst;
final List<InstanceMirror> _metadata;
ParameterMirrorImpl({
required String name,
required TypeMirror type,
required DeclarationMirror owner,
bool isOptional = false,
bool isNamed = false,
bool hasDefaultValue = false,
InstanceMirror? defaultValue,
bool isFinal = false,
bool isConst = false,
List<InstanceMirror> metadata = const [],
}) : _name = name,
_type = type,
_isOptional = isOptional,
_isNamed = isNamed,
_hasDefaultValue = hasDefaultValue,
_defaultValue = defaultValue,
_isFinal = isFinal,
_isConst = isConst,
_metadata = metadata {
setOwner(owner);
}
@override
String get name => _name;
@override
Symbol get simpleName => Symbol(_name);
@override
Symbol get qualifiedName {
if (owner == null) return simpleName;
return Symbol('${owner!.qualifiedName}.$_name');
}
@override
bool get isPrivate => _name.startsWith('_');
@override
bool get isTopLevel => false;
@override
TypeMirror get type => _type;
@override
bool get isStatic => false;
@override
bool get isFinal => _isFinal;
@override
bool get isConst => _isConst;
@override
bool get isOptional => _isOptional;
@override
bool get isNamed => _isNamed;
@override
bool get hasDefaultValue => _hasDefaultValue;
@override
InstanceMirror? get defaultValue => _defaultValue;
@override
List<InstanceMirror> get metadata => List.unmodifiable(_metadata);
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other is! ParameterMirrorImpl) return false;
return _name == other._name &&
_type == other._type &&
owner == other.owner &&
_isOptional == other._isOptional &&
_isNamed == other._isNamed &&
_hasDefaultValue == other._hasDefaultValue &&
_defaultValue == other._defaultValue &&
_isFinal == other._isFinal &&
_isConst == other._isConst;
}
@override
int get hashCode {
return Object.hash(
_name,
_type,
owner,
_isOptional,
_isNamed,
_hasDefaultValue,
_defaultValue,
_isFinal,
_isConst,
);
}
@override
String toString() {
final buffer = StringBuffer();
if (isNamed) buffer.write('{');
if (isOptional && !isNamed) buffer.write('[');
buffer.write('$_type $_name');
if (hasDefaultValue) {
buffer.write(' = $_defaultValue');
}
if (isNamed) buffer.write('}');
if (isOptional && !isNamed) buffer.write(']');
return buffer.toString();
}
}

View file

@ -0,0 +1,44 @@
/// Special type representation for void.
class VoidType implements Type {
const VoidType._();
static const instance = VoidType._();
@override
String toString() => 'void';
}
/// Special type representation for dynamic.
class DynamicType implements Type {
const DynamicType._();
static const instance = DynamicType._();
@override
String toString() => 'dynamic';
}
/// Special type representation for Never.
class NeverType implements Type {
const NeverType._();
static const instance = NeverType._();
@override
String toString() => 'Never';
}
/// Gets the runtime type for void.
Type get voidType => VoidType.instance;
/// Gets the runtime type for dynamic.
Type get dynamicType => DynamicType.instance;
/// Gets the runtime type for Never.
Type get neverType => NeverType.instance;
/// Extension to check special types.
extension TypeExtensions on Type {
/// Whether this type represents void.
bool get isVoid => this == voidType;
/// Whether this type represents dynamic.
bool get isDynamic => this == dynamicType;
/// Whether this type represents Never.
bool get isNever => this == neverType;
}

View file

@ -0,0 +1,171 @@
import 'dart:core';
import '../mirrors.dart';
import '../core/reflector.dart';
import '../metadata.dart';
import 'base_mirror.dart';
import 'special_types.dart';
/// Implementation of [TypeMirror] that provides reflection on types.
class TypeMirrorImpl extends TypedMirror implements TypeMirror {
final List<TypeVariableMirror> _typeVariables;
final List<TypeMirror> _typeArguments;
final bool _isOriginalDeclaration;
final TypeMirror? _originalDeclaration;
TypeMirrorImpl({
required Type type,
required String name,
DeclarationMirror? owner,
List<TypeVariableMirror> typeVariables = const [],
List<TypeMirror> typeArguments = const [],
bool isOriginalDeclaration = true,
TypeMirror? originalDeclaration,
List<InstanceMirror> metadata = const [],
}) : _typeVariables = typeVariables,
_typeArguments = typeArguments,
_isOriginalDeclaration = isOriginalDeclaration,
_originalDeclaration = originalDeclaration,
super(
type: type,
name: name,
owner: owner,
metadata: metadata,
) {
// Register type with reflector if not already registered
if (!Reflector.isReflectable(type)) {
Reflector.registerType(type);
}
}
/// Creates a TypeMirror from TypeMetadata.
factory TypeMirrorImpl.fromMetadata(TypeMetadata typeMetadata,
[DeclarationMirror? owner]) {
return TypeMirrorImpl(
type: typeMetadata.type,
name: typeMetadata.name,
owner: owner,
// Convert interfaces to TypeMirrors
typeVariables: [], // TODO: Add type variable support
typeArguments: [], // TODO: Add type argument support
metadata: [], // TODO: Add metadata support
);
}
/// Creates a TypeMirror for void.
factory TypeMirrorImpl.voidType([DeclarationMirror? owner]) {
return TypeMirrorImpl(
type: voidType,
name: 'void',
owner: owner,
metadata: [],
);
}
/// Creates a TypeMirror for dynamic.
factory TypeMirrorImpl.dynamicType([DeclarationMirror? owner]) {
return TypeMirrorImpl(
type: dynamicType,
name: 'dynamic',
owner: owner,
metadata: [],
);
}
@override
bool get hasReflectedType => true;
@override
Type get reflectedType => type;
@override
List<TypeVariableMirror> get typeVariables =>
List.unmodifiable(_typeVariables);
@override
List<TypeMirror> get typeArguments => List.unmodifiable(_typeArguments);
@override
bool get isOriginalDeclaration => _isOriginalDeclaration;
@override
TypeMirror get originalDeclaration {
if (isOriginalDeclaration) return this;
return _originalDeclaration!;
}
/// Gets the properties defined on this type.
Map<String, PropertyMetadata> get properties =>
Reflector.getPropertyMetadata(type) ?? {};
/// Gets the methods defined on this type.
Map<String, MethodMetadata> get methods =>
Reflector.getMethodMetadata(type) ?? {};
/// Gets the constructors defined on this type.
List<ConstructorMetadata> get constructors =>
Reflector.getConstructorMetadata(type) ?? [];
@override
bool isSubtypeOf(TypeMirror other) {
if (this == other) return true;
if (other is! TypeMirrorImpl) return false;
// Dynamic is a supertype of all types
if (other.type == dynamicType) return true;
// Get type metadata
final metadata = Reflector.getConstructorMetadata(type);
if (metadata == null) return false;
// For now, just handle basic type relationships
// TODO: Implement proper type relationship checking
return false;
}
@override
bool isAssignableTo(TypeMirror other) {
// A type T may be assigned to a type S if either:
// 1. T is a subtype of S, or
// 2. S is dynamic
if (other is TypeMirrorImpl && other.type == dynamicType) return true;
return isSubtypeOf(other);
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other is! TypeMirrorImpl) return false;
return type == other.type &&
name == other.name &&
owner == other.owner &&
_typeVariables == other._typeVariables &&
_typeArguments == other._typeArguments &&
_isOriginalDeclaration == other._isOriginalDeclaration &&
_originalDeclaration == other._originalDeclaration;
}
@override
int get hashCode {
return Object.hash(
type,
name,
owner,
Object.hashAll(_typeVariables),
Object.hashAll(_typeArguments),
_isOriginalDeclaration,
_originalDeclaration,
);
}
@override
String toString() {
final buffer = StringBuffer('TypeMirror on $name');
if (_typeArguments.isNotEmpty) {
buffer.write('<');
buffer.write(_typeArguments.join(', '));
buffer.write('>');
}
return buffer.toString();
}
}

View file

@ -0,0 +1,163 @@
import 'dart:core';
import '../mirrors.dart';
import 'base_mirror.dart';
import 'type_mirror_impl.dart';
/// Implementation of [VariableMirror] that provides reflection on variables.
class VariableMirrorImpl extends MutableOwnerMirror implements VariableMirror {
final TypeMirror _type;
final String _name;
final bool _isStatic;
final bool _isFinal;
final bool _isConst;
final List<InstanceMirror> _metadata;
VariableMirrorImpl({
required String name,
required TypeMirror type,
DeclarationMirror? owner,
bool isStatic = false,
bool isFinal = false,
bool isConst = false,
List<InstanceMirror> metadata = const [],
}) : _name = name,
_type = type,
_isStatic = isStatic,
_isFinal = isFinal,
_isConst = isConst,
_metadata = metadata {
setOwner(owner);
}
@override
String get name => _name;
@override
Symbol get simpleName => Symbol(_name);
@override
Symbol get qualifiedName {
if (owner == null) return simpleName;
return Symbol('${owner!.qualifiedName}.$_name');
}
@override
bool get isPrivate => _name.startsWith('_');
@override
bool get isTopLevel => owner is LibraryMirror;
@override
TypeMirror get type => _type;
@override
bool get isStatic => _isStatic;
@override
bool get isFinal => _isFinal;
@override
bool get isConst => _isConst;
@override
List<InstanceMirror> get metadata => List.unmodifiable(_metadata);
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other is! VariableMirrorImpl) return false;
return _name == other._name &&
_type == other._type &&
owner == other.owner &&
_isStatic == other._isStatic &&
_isFinal == other._isFinal &&
_isConst == other._isConst;
}
@override
int get hashCode {
return Object.hash(
_name,
_type,
owner,
_isStatic,
_isFinal,
_isConst,
);
}
@override
String toString() {
final buffer = StringBuffer();
if (_isStatic) buffer.write('static ');
if (_isConst) buffer.write('const ');
if (_isFinal) buffer.write('final ');
buffer.write('$_type $_name');
return buffer.toString();
}
}
/// Implementation of [VariableMirror] specifically for fields.
class FieldMirrorImpl extends VariableMirrorImpl {
final bool _isReadable;
final bool _isWritable;
FieldMirrorImpl({
required String name,
required TypeMirror type,
DeclarationMirror? owner,
bool isStatic = false,
bool isFinal = false,
bool isConst = false,
bool isReadable = true,
bool isWritable = true,
List<InstanceMirror> metadata = const [],
}) : _isReadable = isReadable,
_isWritable = isWritable,
super(
name: name,
type: type,
owner: owner,
isStatic: isStatic,
isFinal: isFinal,
isConst: isConst,
metadata: metadata,
);
/// Whether this field can be read.
bool get isReadable => _isReadable;
/// Whether this field can be written to.
bool get isWritable => _isWritable && !isFinal && !isConst;
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other is! FieldMirrorImpl) return false;
if (!(super == other)) return false;
return _isReadable == other._isReadable && _isWritable == other._isWritable;
}
@override
int get hashCode {
return Object.hash(
super.hashCode,
_isReadable,
_isWritable,
);
}
@override
String toString() {
final buffer = StringBuffer();
if (isStatic) buffer.write('static ');
if (isConst) buffer.write('const ');
if (isFinal) buffer.write('final ');
buffer.write('$type $_name');
if (!isReadable) buffer.write(' (write-only)');
if (!isWritable) buffer.write(' (read-only)');
return buffer.toString();
}
}

View file

@ -1,258 +0,0 @@
import 'dart:core';
import 'package:meta/meta.dart';
import 'annotations.dart';
import 'exceptions.dart';
import 'metadata.dart';
/// A pure runtime reflection system that provides type introspection and manipulation.
class RuntimeReflector {
/// The singleton instance of the reflector.
static final instance = RuntimeReflector._();
RuntimeReflector._();
/// Creates a new instance of a type using reflection.
Object createInstance(
Type type, {
String constructorName = '',
List<Object?> positionalArgs = const [],
Map<String, Object?> namedArgs = const {},
}) {
// Check if type is reflectable
if (!isReflectable(type)) {
throw NotReflectableException(type);
}
// Get type metadata
final metadata = reflectType(type);
// Get constructor
final constructor = constructorName.isEmpty
? metadata.defaultConstructor
: metadata.getConstructor(constructorName);
// Validate arguments
if (!_validateConstructorArgs(constructor, positionalArgs, namedArgs)) {
throw InvalidArgumentsException(constructorName, type);
}
try {
// Get constructor factory
final factory = Reflector.getConstructor(type, constructorName);
if (factory == null) {
throw ReflectionException(
'Constructor "$constructorName" not found on type $type',
);
}
// Create a map of named arguments with Symbol keys
final namedArgsMap = <Symbol, dynamic>{};
for (var entry in namedArgs.entries) {
namedArgsMap[Symbol(entry.key)] = entry.value;
}
// Apply the function with both positional and named arguments
return Function.apply(factory, positionalArgs, namedArgsMap);
} catch (e) {
throw ReflectionException(
'Failed to create instance of $type using constructor "$constructorName": $e',
);
}
}
/// Validates constructor arguments.
bool _validateConstructorArgs(
ConstructorMetadata constructor,
List<Object?> positionalArgs,
Map<String, Object?> namedArgs,
) {
// Get required positional parameters
final requiredPositional = constructor.parameters
.where((p) => p.isRequired && !p.isNamed)
.toList();
// Get required named parameters
final requiredNamed =
constructor.parameters.where((p) => p.isRequired && p.isNamed).toList();
// Check required positional arguments
if (positionalArgs.length < requiredPositional.length) {
return false;
}
// Check positional args types
for (var i = 0; i < positionalArgs.length; i++) {
final arg = positionalArgs[i];
if (arg != null && i < constructor.parameters.length) {
final param = constructor.parameters[i];
if (!param.isNamed && arg.runtimeType != param.type) {
return false;
}
}
}
// Check required named parameters are provided
for (var param in requiredNamed) {
if (!namedArgs.containsKey(param.name)) {
return false;
}
}
// Check named args types
for (var entry in namedArgs.entries) {
final param = constructor.parameters.firstWhere(
(p) => p.name == entry.key && p.isNamed,
orElse: () => throw InvalidArgumentsException(
constructor.name,
constructor.parameterTypes.first,
),
);
final value = entry.value;
if (value != null && value.runtimeType != param.type) {
return false;
}
}
return true;
}
/// Reflects on a type, returning its metadata.
TypeMetadata reflectType(Type type) {
// Check if type is reflectable
if (!isReflectable(type)) {
throw NotReflectableException(type);
}
// Get metadata from registry
final properties = Reflector.getPropertyMetadata(type) ?? {};
final methods = Reflector.getMethodMetadata(type) ?? {};
final constructors = Reflector.getConstructorMetadata(type) ?? [];
return TypeMetadata(
type: type,
name: type.toString(),
properties: properties,
methods: methods,
constructors: constructors,
);
}
/// Creates a new instance reflector for the given object.
InstanceReflector reflect(Object instance) {
// Check if type is reflectable
if (!isReflectable(instance.runtimeType)) {
throw NotReflectableException(instance.runtimeType);
}
return InstanceReflector._(instance, reflectType(instance.runtimeType));
}
}
/// Provides reflection capabilities for object instances.
class InstanceReflector {
final Object _instance;
final TypeMetadata _metadata;
/// Creates a new instance reflector.
@protected
InstanceReflector._(this._instance, this._metadata);
/// Gets the value of a property by name.
Object? getField(String name) {
final property = _metadata.getProperty(name);
if (!property.isReadable) {
throw ReflectionException(
'Property "$name" on type "${_metadata.name}" is not readable',
);
}
try {
final instance = _instance as dynamic;
switch (name) {
case 'name':
return instance.name;
case 'age':
return instance.age;
case 'id':
return instance.id;
case 'isActive':
return instance.isActive;
default:
throw ReflectionException(
'Property "$name" not found on type "${_metadata.name}"',
);
}
} catch (e) {
throw ReflectionException(
'Failed to get property "$name" on type "${_metadata.name}": $e',
);
}
}
/// Sets the value of a property by name.
void setField(String name, Object? value) {
final property = _metadata.getProperty(name);
if (!property.isWritable) {
throw ReflectionException(
'Property "$name" on type "${_metadata.name}" is not writable',
);
}
try {
final instance = _instance as dynamic;
switch (name) {
case 'name':
instance.name = value as String;
break;
case 'age':
instance.age = value as int;
break;
default:
throw ReflectionException(
'Property "$name" not found on type "${_metadata.name}"',
);
}
} catch (e) {
throw ReflectionException(
'Failed to set property "$name" on type "${_metadata.name}": $e',
);
}
}
/// Invokes a method by name with the given arguments.
Object? invoke(String name, List<Object?> arguments) {
final method = _metadata.getMethod(name);
if (!method.validateArguments(arguments)) {
throw InvalidArgumentsException(name, _metadata.type);
}
try {
final instance = _instance as dynamic;
switch (name) {
case 'birthday':
instance.birthday();
return null;
case 'greet':
return arguments.isEmpty
? instance.greet()
: instance.greet(arguments[0] as String);
case 'deactivate':
instance.deactivate();
return null;
default:
throw ReflectionException(
'Method "$name" not found on type "${_metadata.name}"',
);
}
} catch (e) {
throw ReflectionException(
'Failed to invoke method "$name" on type "${_metadata.name}": $e',
);
}
}
/// Gets the type metadata for this instance.
TypeMetadata get type => _metadata;
}

View file

@ -1,6 +1,11 @@
name: platform_reflection
description: A lightweight cross-platform reflection system for Dart
description: A lightweight cross-platform reflection system for Dart that provides runtime type introspection and dynamic invocation capabilities with an API similar to dart:mirrors.
version: 0.1.0
repository: https://github.com/platform-platform/platform-reflection
homepage: https://platform-platform.github.io/platform-reflection/
documentation: https://platform-platform.github.io/platform-reflection/docs/
issue_tracker: https://github.com/platform-platform/platform-reflection/issues
environment:
sdk: '>=3.0.0 <4.0.0'
@ -10,3 +15,17 @@ dependencies:
dev_dependencies:
lints: ^2.1.0
test: ^1.24.0
topics:
- reflection
- mirrors
- runtime
- introspection
platforms:
android:
ios:
linux:
macos:
web:
windows:

View file

@ -0,0 +1,119 @@
import 'dart:isolate';
import 'package:platform_reflection/reflection.dart';
import 'package:test/test.dart';
// Function to run in isolate
void isolateFunction(SendPort sendPort) {
sendPort.send('Hello from isolate!');
}
void main() {
group('Isolate Reflection', () {
late RuntimeReflector reflector;
setUp(() {
reflector = RuntimeReflector.instance;
});
test('currentIsolate returns mirror for current isolate', () {
final isolateMirror = reflector.currentIsolate;
expect(isolateMirror, isNotNull);
expect(isolateMirror.isCurrent, isTrue);
expect(isolateMirror.debugName, equals('main'));
expect(isolateMirror.rootLibrary, isNotNull);
});
test('reflectIsolate returns mirror for other isolate', () async {
final receivePort = ReceivePort();
final isolate = await Isolate.spawn(
isolateFunction,
receivePort.sendPort,
);
final isolateMirror = reflector.reflectIsolate(isolate, 'test-isolate');
expect(isolateMirror, isNotNull);
expect(isolateMirror.isCurrent, isFalse);
expect(isolateMirror.debugName, equals('test-isolate'));
expect(isolateMirror.rootLibrary, isNotNull);
// Clean up
receivePort.close();
isolate.kill();
});
test('isolate mirror provides control over isolate', () async {
final receivePort = ReceivePort();
final isolate = await Isolate.spawn(
isolateFunction,
receivePort.sendPort,
);
final isolateMirror = reflector.reflectIsolate(isolate, 'test-isolate')
as IsolateMirrorImpl;
// Test pause/resume
await isolateMirror.pause();
await isolateMirror.resume();
// Test error listener
var errorReceived = false;
isolateMirror.addErrorListener((error, stackTrace) {
errorReceived = true;
});
// Test exit listener
var exitReceived = false;
isolateMirror.addExitListener((_) {
exitReceived = false;
});
// Test kill
await isolateMirror.kill();
// Clean up
receivePort.close();
});
test('isolate mirrors compare correctly', () async {
final receivePort = ReceivePort();
final isolate = await Isolate.spawn(
isolateFunction,
receivePort.sendPort,
);
final mirror1 = reflector.reflectIsolate(isolate, 'test-isolate');
final mirror2 = reflector.reflectIsolate(isolate, 'test-isolate');
final mirror3 = reflector.reflectIsolate(isolate, 'other-name');
expect(mirror1, equals(mirror2));
expect(mirror1, isNot(equals(mirror3)));
expect(mirror1.hashCode, equals(mirror2.hashCode));
expect(mirror1.hashCode, isNot(equals(mirror3.hashCode)));
// Clean up
receivePort.close();
isolate.kill();
});
test('isolate mirror toString provides meaningful description', () {
final currentMirror = reflector.currentIsolate;
expect(
currentMirror.toString(), equals('IsolateMirror "main" (current)'));
final receivePort = ReceivePort();
Isolate.spawn(
isolateFunction,
receivePort.sendPort,
).then((isolate) {
final otherMirror = reflector.reflectIsolate(isolate, 'test-isolate');
expect(otherMirror.toString(), equals('IsolateMirror "test-isolate"'));
// Clean up
receivePort.close();
isolate.kill();
});
});
});
}

View file

@ -0,0 +1,128 @@
import 'package:platform_reflection/reflection.dart';
import 'package:test/test.dart';
// Top-level function for testing
int add(int a, int b) => a + b;
// Top-level variable for testing
const String greeting = 'Hello';
void main() {
group('Library Reflection', () {
late RuntimeReflector reflector;
setUp(() {
reflector = RuntimeReflector.instance;
});
test('reflectLibrary returns library mirror', () {
final libraryMirror = reflector.reflectLibrary(
Uri.parse('package:reflection/test/library_reflection_test.dart'),
);
expect(libraryMirror, isNotNull);
expect(libraryMirror.uri.toString(),
contains('library_reflection_test.dart'));
});
test('library mirror provides correct metadata', () {
final libraryMirror = reflector.reflectLibrary(
Uri.parse('package:reflection/test/library_reflection_test.dart'),
);
expect(libraryMirror.isPrivate, isFalse);
expect(libraryMirror.isTopLevel, isTrue);
expect(libraryMirror.metadata, isEmpty);
});
test('library mirror provides access to declarations', () {
final libraryMirror = reflector.reflectLibrary(
Uri.parse('package:reflection/test/library_reflection_test.dart'),
);
final declarations = libraryMirror.declarations;
expect(declarations, isNotEmpty);
// Check for top-level function
final addFunction = declarations[const Symbol('add')] as MethodMirror;
expect(addFunction, isNotNull);
expect(addFunction.isStatic, isTrue);
expect(addFunction.parameters.length, equals(2));
// Check for top-level variable
final greetingVar =
declarations[const Symbol('greeting')] as VariableMirror;
expect(greetingVar, isNotNull);
expect(greetingVar.isStatic, isTrue);
expect(greetingVar.isConst, isTrue);
expect(greetingVar.type.reflectedType, equals(String));
});
test('library mirror provides access to dependencies', () {
final libraryMirror = reflector.reflectLibrary(
Uri.parse('package:reflection/test/library_reflection_test.dart'),
);
final dependencies = libraryMirror.libraryDependencies;
expect(dependencies, isNotEmpty);
// Check for test package import
final testImport = dependencies.firstWhere((dep) =>
dep.isImport &&
dep.targetLibrary?.uri.toString().contains('package:test/') == true);
expect(testImport, isNotNull);
expect(testImport.isDeferred, isFalse);
expect(testImport.prefix, isNull);
// Check for reflection package import
final reflectionImport = dependencies.firstWhere((dep) =>
dep.isImport &&
dep.targetLibrary?.uri
.toString()
.contains('package:platform_reflection/') ==
true);
expect(reflectionImport, isNotNull);
expect(reflectionImport.isDeferred, isFalse);
expect(reflectionImport.prefix, isNull);
});
test('library mirror allows invoking top-level functions', () {
final libraryMirror = reflector.reflectLibrary(
Uri.parse('package:reflection/test/library_reflection_test.dart'),
);
final result = libraryMirror.invoke(
const Symbol('add'),
[2, 3],
).reflectee as int;
expect(result, equals(5));
});
test('library mirror allows accessing top-level variables', () {
final libraryMirror = reflector.reflectLibrary(
Uri.parse('package:reflection/test/library_reflection_test.dart'),
);
final value =
libraryMirror.getField(const Symbol('greeting')).reflectee as String;
expect(value, equals('Hello'));
});
test('library mirror throws on non-existent members', () {
final libraryMirror = reflector.reflectLibrary(
Uri.parse('package:reflection/test/library_reflection_test.dart'),
);
expect(
() => libraryMirror.invoke(const Symbol('nonexistent'), []),
throwsA(isA<NoSuchMethodError>()),
);
expect(
() => libraryMirror.getField(const Symbol('nonexistent')),
throwsA(isA<NoSuchMethodError>()),
);
});
});
}

View file

@ -0,0 +1,141 @@
import 'package:platform_reflection/reflection.dart';
import 'package:test/test.dart';
@reflectable
class TestClass {
String name;
TestClass(this.name);
}
void main() {
group('MirrorSystem', () {
late RuntimeReflector reflector;
late MirrorSystem mirrorSystem;
setUp(() {
reflector = RuntimeReflector.instance;
mirrorSystem = reflector.currentMirrorSystem;
// Register test class
Reflector.registerType(TestClass);
Reflector.registerPropertyMetadata(
TestClass,
'name',
PropertyMetadata(
name: 'name',
type: String,
isReadable: true,
isWritable: true,
),
);
});
test('currentMirrorSystem provides access to libraries', () {
expect(mirrorSystem.libraries, isNotEmpty);
expect(
mirrorSystem.libraries.keys
.any((uri) => uri.toString() == 'dart:core'),
isTrue);
});
test('findLibrary returns correct library', () {
final library = mirrorSystem.findLibrary(const Symbol('dart:core'));
expect(library, isNotNull);
expect(library.uri.toString(), equals('dart:core'));
});
test('findLibrary throws on non-existent library', () {
expect(
() => mirrorSystem.findLibrary(const Symbol('non:existent')),
throwsArgumentError,
);
});
test('reflectClass returns class mirror', () {
final classMirror = mirrorSystem.reflectClass(TestClass);
expect(classMirror, isNotNull);
expect(classMirror.name, equals('TestClass'));
expect(classMirror.declarations, isNotEmpty);
});
test('reflectClass throws on non-reflectable type', () {
expect(
() => mirrorSystem.reflectClass(Object),
throwsArgumentError,
);
});
test('reflectType returns type mirror', () {
final typeMirror = mirrorSystem.reflectType(TestClass);
expect(typeMirror, isNotNull);
expect(typeMirror.name, equals('TestClass'));
expect(typeMirror.hasReflectedType, isTrue);
expect(typeMirror.reflectedType, equals(TestClass));
});
test('reflectType throws on non-reflectable type', () {
expect(
() => mirrorSystem.reflectType(Object),
throwsArgumentError,
);
});
test('isolate returns current isolate mirror', () {
final isolateMirror = mirrorSystem.isolate;
expect(isolateMirror, isNotNull);
expect(isolateMirror.isCurrent, isTrue);
expect(isolateMirror.debugName, equals('main'));
});
test('dynamicType returns dynamic type mirror', () {
final typeMirror = mirrorSystem.dynamicType;
expect(typeMirror, isNotNull);
expect(typeMirror.name, equals('dynamic'));
});
test('voidType returns void type mirror', () {
final typeMirror = mirrorSystem.voidType;
expect(typeMirror, isNotNull);
expect(typeMirror.name, equals('void'));
});
test('neverType returns Never type mirror', () {
final typeMirror = mirrorSystem.neverType;
expect(typeMirror, isNotNull);
expect(typeMirror.name, equals('Never'));
});
test('type relationships work correctly', () {
final dynamicMirror = mirrorSystem.dynamicType;
final voidMirror = mirrorSystem.voidType;
final neverMirror = mirrorSystem.neverType;
final stringMirror = mirrorSystem.reflectType(String);
// Never is a subtype of everything
expect(neverMirror.isSubtypeOf(dynamicMirror), isTrue);
expect(neverMirror.isSubtypeOf(stringMirror), isTrue);
// Everything is assignable to dynamic
expect(stringMirror.isAssignableTo(dynamicMirror), isTrue);
expect(neverMirror.isAssignableTo(dynamicMirror), isTrue);
// void is not assignable to anything (except itself)
expect(voidMirror.isAssignableTo(stringMirror), isFalse);
expect(voidMirror.isAssignableTo(dynamicMirror), isFalse);
expect(voidMirror.isAssignableTo(voidMirror), isTrue);
});
test('library dependencies are tracked', () {
final coreLibrary = mirrorSystem.findLibrary(const Symbol('dart:core'));
expect(coreLibrary.libraryDependencies, isNotEmpty);
final imports =
coreLibrary.libraryDependencies.where((dep) => dep.isImport).toList();
expect(imports, isNotEmpty);
final exports =
coreLibrary.libraryDependencies.where((dep) => dep.isExport).toList();
expect(exports, isNotEmpty);
});
});
}

View file

@ -2,7 +2,7 @@ import 'package:platform_reflection/reflection.dart';
import 'package:test/test.dart';
@reflectable
class Person with Reflector {
class Person {
String name;
int age;
final String id;
@ -43,54 +43,124 @@ void main() {
setUp(() {
// Register Person as reflectable
Reflector.register(Person);
Reflector.registerType(Person);
// Register properties
Reflector.registerProperty(Person, 'name', String);
Reflector.registerProperty(Person, 'age', int);
Reflector.registerProperty(Person, 'id', String, isWritable: false);
Reflector.registerPropertyMetadata(
Person,
'name',
PropertyMetadata(
name: 'name',
type: String,
isReadable: true,
isWritable: true,
),
);
Reflector.registerPropertyMetadata(
Person,
'age',
PropertyMetadata(
name: 'age',
type: int,
isReadable: true,
isWritable: true,
),
);
Reflector.registerPropertyMetadata(
Person,
'id',
PropertyMetadata(
name: 'id',
type: String,
isReadable: true,
isWritable: false,
),
);
// Register methods
Reflector.registerMethod(
Reflector.registerMethodMetadata(
Person,
'birthday',
[],
true,
MethodMetadata(
name: 'birthday',
parameterTypes: [],
parameters: [],
returnsVoid: true,
),
);
Reflector.registerMethod(
Reflector.registerMethodMetadata(
Person,
'greet',
[String],
false,
parameterNames: ['greeting'],
MethodMetadata(
name: 'greet',
parameterTypes: [String],
parameters: [
ParameterMetadata(
name: 'greeting',
type: String,
isRequired: true,
),
],
returnsVoid: false,
),
);
// Register constructors
Reflector.registerConstructor(
Reflector.registerConstructorMetadata(
Person,
ConstructorMetadata(
name: '',
parameterTypes: [String, int, String],
parameters: [
ParameterMetadata(name: 'name', type: String, isRequired: true),
ParameterMetadata(name: 'age', type: int, isRequired: true),
ParameterMetadata(
name: 'id', type: String, isRequired: true, isNamed: true),
],
),
);
Reflector.registerConstructorFactory(
Person,
'',
(String name, int age, {required String id}) =>
Person(name, age, id: id),
parameterTypes: [String, int, String],
parameterNames: ['name', 'age', 'id'],
isRequired: [true, true, true],
isNamed: [false, false, true],
);
Reflector.registerConstructor(
Reflector.registerConstructorMetadata(
Person,
ConstructorMetadata(
name: 'guest',
parameterTypes: [],
parameters: [],
),
);
Reflector.registerConstructorFactory(
Person,
'guest',
() => Person.guest(),
);
Reflector.registerConstructor(
Reflector.registerConstructorMetadata(
Person,
ConstructorMetadata(
name: 'withDefaults',
parameterTypes: [String, int],
parameters: [
ParameterMetadata(name: 'name', type: String, isRequired: true),
ParameterMetadata(name: 'age', type: int, isRequired: false),
],
),
);
Reflector.registerConstructorFactory(
Person,
'withDefaults',
(String name, [int age = 18]) => Person.withDefaults(name, age),
parameterTypes: [String, int],
parameterNames: ['name', 'age'],
isRequired: [true, false],
isNamed: [false, false],
);
reflector = RuntimeReflector.instance;
@ -99,20 +169,20 @@ void main() {
group('Type Reflection', () {
test('reflectType returns correct type metadata', () {
final metadata = reflector.reflectType(Person);
final typeMirror = reflector.reflectType(Person);
expect(metadata.name, equals('Person'));
expect(metadata.properties.length, equals(3));
expect(metadata.methods.length, equals(2)); // birthday and greet
expect(metadata.constructors.length,
expect(typeMirror.name, equals('Person'));
expect(typeMirror.properties.length, equals(3));
expect(typeMirror.methods.length, equals(2)); // birthday and greet
expect(typeMirror.constructors.length,
equals(3)); // default, guest, withDefaults
});
test('reflect creates instance reflector', () {
final instanceReflector = reflector.reflect(person);
test('reflect creates instance mirror', () {
final instanceMirror = reflector.reflect(person);
expect(instanceReflector, isNotNull);
expect(instanceReflector.type.name, equals('Person'));
expect(instanceMirror, isNotNull);
expect(instanceMirror.type.name, equals('Person'));
});
test('throws NotReflectableException for non-reflectable class', () {
@ -127,28 +197,31 @@ void main() {
group('Property Access', () {
test('getField returns property value', () {
final instanceReflector = reflector.reflect(person);
final instanceMirror = reflector.reflect(person);
expect(instanceReflector.getField('name'), equals('John'));
expect(instanceReflector.getField('age'), equals(30));
expect(instanceReflector.getField('id'), equals('123'));
expect(instanceMirror.getField(const Symbol('name')).reflectee,
equals('John'));
expect(
instanceMirror.getField(const Symbol('age')).reflectee, equals(30));
expect(instanceMirror.getField(const Symbol('id')).reflectee,
equals('123'));
});
test('setField updates property value', () {
final instanceReflector = reflector.reflect(person);
final instanceMirror = reflector.reflect(person);
instanceReflector.setField('name', 'Jane');
instanceReflector.setField('age', 25);
instanceMirror.setField(const Symbol('name'), 'Jane');
instanceMirror.setField(const Symbol('age'), 25);
expect(person.name, equals('Jane'));
expect(person.age, equals(25));
});
test('setField throws on final field', () {
final instanceReflector = reflector.reflect(person);
final instanceMirror = reflector.reflect(person);
expect(
() => instanceReflector.setField('id', '456'),
() => instanceMirror.setField(const Symbol('id'), '456'),
throwsA(isA<ReflectionException>()),
);
});
@ -156,20 +229,21 @@ void main() {
group('Method Invocation', () {
test('invoke calls method with arguments', () {
final instanceReflector = reflector.reflect(person);
final instanceMirror = reflector.reflect(person);
final result = instanceReflector.invoke('greet', ['Hello']);
final result =
instanceMirror.invoke(const Symbol('greet'), ['Hello']).reflectee;
expect(result, equals('Hello, John!'));
instanceReflector.invoke('birthday', []);
instanceMirror.invoke(const Symbol('birthday'), []);
expect(person.age, equals(31));
});
test('invoke throws on invalid arguments', () {
final instanceReflector = reflector.reflect(person);
final instanceMirror = reflector.reflect(person);
expect(
() => instanceReflector.invoke('greet', [42]),
() => instanceMirror.invoke(const Symbol('greet'), [42]),
throwsA(isA<InvalidArgumentsException>()),
);
});

View file

@ -0,0 +1,246 @@
import 'package:platform_reflection/reflection.dart';
import 'package:test/test.dart';
@reflectable
class TestClass {
String name;
final int id;
List<String> tags;
static const version = '1.0.0';
TestClass(this.name, {required this.id, this.tags = const []});
TestClass.guest()
: name = 'Guest',
id = 0,
tags = const [];
void addTag(String tag) {
tags.add(tag);
}
String greet([String greeting = 'Hello']) {
return '$greeting, $name!';
}
static TestClass create(String name, {required int id}) {
return TestClass(name, id: id);
}
}
@reflectable
class GenericTestClass<T> {
T value;
List<T> items;
GenericTestClass(this.value, {this.items = const []});
void addItem(T item) {
items.add(item);
}
T getValue() => value;
}
@reflectable
class ParentTestClass {
String name;
ParentTestClass(this.name);
String getName() => name;
}
@reflectable
class ChildTestClass extends ParentTestClass {
int age;
ChildTestClass(String name, this.age) : super(name);
@override
String getName() => '$name ($age)';
}
void main() {
group('Scanner', () {
test('scans properties correctly', () {
Scanner.scanType(TestClass);
final metadata = Reflector.getPropertyMetadata(TestClass);
expect(metadata, isNotNull);
expect(metadata!['name'], isNotNull);
expect(metadata['name']!.type, equals(String));
expect(metadata['name']!.isWritable, isTrue);
expect(metadata['id'], isNotNull);
expect(metadata['id']!.type, equals(int));
expect(metadata['id']!.isWritable, isFalse);
expect(metadata['tags'], isNotNull);
expect(metadata['tags']!.type, equals(List<String>));
expect(metadata['tags']!.isWritable, isTrue);
expect(metadata['version'], isNotNull);
expect(metadata['version']!.type, equals(String));
expect(metadata['version']!.isWritable, isFalse);
});
test('scans methods correctly', () {
Scanner.scanType(TestClass);
final metadata = Reflector.getMethodMetadata(TestClass);
expect(metadata, isNotNull);
// addTag method
expect(metadata!['addTag'], isNotNull);
expect(metadata['addTag']!.parameterTypes, equals([String]));
expect(metadata['addTag']!.parameters.length, equals(1));
expect(metadata['addTag']!.parameters[0].name, equals('tag'));
expect(metadata['addTag']!.parameters[0].type, equals(String));
expect(metadata['addTag']!.parameters[0].isRequired, isTrue);
expect(metadata['addTag']!.returnsVoid, isTrue);
expect(metadata['addTag']!.isStatic, isFalse);
// greet method
expect(metadata['greet'], isNotNull);
expect(metadata['greet']!.parameterTypes, equals([String]));
expect(metadata['greet']!.parameters.length, equals(1));
expect(metadata['greet']!.parameters[0].name, equals('greeting'));
expect(metadata['greet']!.parameters[0].type, equals(String));
expect(metadata['greet']!.parameters[0].isRequired, isFalse);
expect(metadata['greet']!.returnsVoid, isFalse);
expect(metadata['greet']!.isStatic, isFalse);
// create method
expect(metadata['create'], isNotNull);
expect(metadata['create']!.parameterTypes, equals([String, int]));
expect(metadata['create']!.parameters.length, equals(2));
expect(metadata['create']!.parameters[0].name, equals('name'));
expect(metadata['create']!.parameters[0].type, equals(String));
expect(metadata['create']!.parameters[0].isRequired, isTrue);
expect(metadata['create']!.parameters[1].name, equals('id'));
expect(metadata['create']!.parameters[1].type, equals(int));
expect(metadata['create']!.parameters[1].isRequired, isTrue);
expect(metadata['create']!.parameters[1].isNamed, isTrue);
expect(metadata['create']!.returnsVoid, isFalse);
expect(metadata['create']!.isStatic, isTrue);
});
test('scans constructors correctly', () {
Scanner.scanType(TestClass);
final metadata = Reflector.getConstructorMetadata(TestClass);
expect(metadata, isNotNull);
expect(metadata!.length, equals(2));
// Default constructor
final defaultCtor = metadata.firstWhere((m) => m.name.isEmpty);
expect(defaultCtor.parameterTypes, equals([String, int, List<String>]));
expect(defaultCtor.parameters.length, equals(3));
expect(defaultCtor.parameters[0].name, equals('name'));
expect(defaultCtor.parameters[0].type, equals(String));
expect(defaultCtor.parameters[0].isRequired, isTrue);
expect(defaultCtor.parameters[1].name, equals('id'));
expect(defaultCtor.parameters[1].type, equals(int));
expect(defaultCtor.parameters[1].isRequired, isTrue);
expect(defaultCtor.parameters[1].isNamed, isTrue);
expect(defaultCtor.parameters[2].name, equals('tags'));
expect(defaultCtor.parameters[2].type, equals(List<String>));
expect(defaultCtor.parameters[2].isRequired, isFalse);
expect(defaultCtor.parameters[2].isNamed, isTrue);
// Guest constructor
final guestCtor = metadata.firstWhere((m) => m.name == 'guest');
expect(guestCtor.parameterTypes, isEmpty);
expect(guestCtor.parameters, isEmpty);
});
test('scanned type works with reflection', () {
Scanner.scanType(TestClass);
final reflector = RuntimeReflector.instance;
// Create instance
final instance = reflector.createInstance(
TestClass,
positionalArgs: ['John'],
namedArgs: {'id': 123},
) as TestClass;
expect(instance.name, equals('John'));
expect(instance.id, equals(123));
expect(instance.tags, isEmpty);
// Create guest instance
final guest = reflector.createInstance(
TestClass,
constructorName: 'guest',
) as TestClass;
expect(guest.name, equals('Guest'));
expect(guest.id, equals(0));
expect(guest.tags, isEmpty);
// Reflect on instance
final mirror = reflector.reflect(instance);
// Access properties
expect(mirror.getField(const Symbol('name')).reflectee, equals('John'));
expect(mirror.getField(const Symbol('id')).reflectee, equals(123));
// Modify properties
mirror.setField(const Symbol('name'), 'Jane');
expect(instance.name, equals('Jane'));
// Invoke methods
mirror.invoke(const Symbol('addTag'), ['test']);
expect(instance.tags, equals(['test']));
final greeting = mirror.invoke(const Symbol('greet'), ['Hi']).reflectee;
expect(greeting, equals('Hi, Jane!'));
// Try to modify final field (should throw)
expect(
() => mirror.setField(const Symbol('id'), 456),
throwsA(isA<ReflectionException>()),
);
});
test('handles generic types correctly', () {
Scanner.scanType(GenericTestClass);
final metadata = Reflector.getPropertyMetadata(GenericTestClass);
expect(metadata, isNotNull);
expect(metadata!['value'], isNotNull);
expect(metadata['items'], isNotNull);
expect(metadata['items']!.type, equals(List));
final methodMeta = Reflector.getMethodMetadata(GenericTestClass);
expect(methodMeta, isNotNull);
expect(methodMeta!['addItem'], isNotNull);
expect(methodMeta['getValue'], isNotNull);
});
test('handles inheritance correctly', () {
Scanner.scanType(ParentTestClass);
Scanner.scanType(ChildTestClass);
final parentMeta = Reflector.getPropertyMetadata(ParentTestClass);
final childMeta = Reflector.getPropertyMetadata(ChildTestClass);
expect(parentMeta, isNotNull);
expect(parentMeta!['name'], isNotNull);
expect(childMeta, isNotNull);
expect(childMeta!['name'], isNotNull);
expect(childMeta['age'], isNotNull);
final reflector = RuntimeReflector.instance;
final child = reflector.createInstance(
ChildTestClass,
positionalArgs: ['John', 30],
) as ChildTestClass;
final mirror = reflector.reflect(child);
final result = mirror.invoke(const Symbol('getName'), []).reflectee;
expect(result, equals('John (30)'));
});
});
}