Compare commits
5 commits
0e7971b928
...
f33d7ce33c
Author | SHA1 | Date | |
---|---|---|---|
|
f33d7ce33c | ||
|
1d2a4d805c | ||
|
f74f57fbbf | ||
|
fbf5c44dd5 | ||
|
0f4935cea1 |
22 changed files with 3479 additions and 10 deletions
231
docs/ai_assistance_guide.md
Normal file
231
docs/ai_assistance_guide.md
Normal file
|
@ -0,0 +1,231 @@
|
|||
# AI Assistance Features Guide
|
||||
|
||||
This guide details how AI assistance works in our Laravel platform development workflow, focusing on practical examples and specific use cases.
|
||||
|
||||
## 1. Code Analysis & Generation
|
||||
|
||||
### Laravel API Analysis
|
||||
```dart
|
||||
// Example: Implementing Container's bind method
|
||||
// Command: /ai analyze-laravel Container::bind
|
||||
|
||||
AI will analyze:
|
||||
1. Laravel's implementation:
|
||||
```php
|
||||
public function bind($abstract, $concrete = null, $shared = false)
|
||||
{
|
||||
$this->dropStaleInstances($abstract);
|
||||
if (is_null($concrete)) {
|
||||
$concrete = $abstract;
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
2. Generate Dart equivalent:
|
||||
```dart
|
||||
// GENERATED BY AI
|
||||
/// Matches Laravel's Container::bind implementation
|
||||
/// @see https://laravel.com/docs/container#binding
|
||||
void bind<T>(T Function(Container) concrete, {bool shared = false}) {
|
||||
dropStaleInstances(T);
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
3. Provide compatibility notes:
|
||||
```
|
||||
API Compatibility Notes:
|
||||
- Laravel uses dynamic typing, we use generics
|
||||
- Laravel's null concrete defaults to abstract
|
||||
- Maintain same binding behavior
|
||||
```
|
||||
|
||||
### Implementation Suggestions
|
||||
|
||||
```dart
|
||||
// Command: /ai suggest-implementation Container::bind
|
||||
|
||||
AI provides:
|
||||
1. Implementation pattern:
|
||||
```dart
|
||||
void bind<T>(T Function(Container) concrete, {bool shared = false}) {
|
||||
// AI suggests pattern based on Laravel's behavior
|
||||
_dropStaleInstances(typeOf<T>());
|
||||
|
||||
final binding = shared
|
||||
? (c) => _shared(concrete)
|
||||
: concrete;
|
||||
|
||||
_bindings[typeOf<T>()] = binding;
|
||||
}
|
||||
```
|
||||
|
||||
2. Edge cases to handle:
|
||||
```dart
|
||||
// AI identifies critical scenarios:
|
||||
- Rebinding existing types
|
||||
- Handling shared vs non-shared
|
||||
- Circular dependencies
|
||||
```
|
||||
|
||||
## 2. Test Generation
|
||||
|
||||
### Laravel Test Analysis
|
||||
```dart
|
||||
// Command: /ai generate-tests Container::bind
|
||||
|
||||
AI analyzes Laravel's tests:
|
||||
```php
|
||||
public function testBindingResolution()
|
||||
{
|
||||
$container = new Container;
|
||||
$container->bind('name', function () { return 'Taylor'; });
|
||||
$this->assertEquals('Taylor', $container->make('name'));
|
||||
}
|
||||
```
|
||||
|
||||
Generates Dart tests:
|
||||
```dart
|
||||
@Test('matches Laravel binding resolution')
|
||||
void testBindingResolution() {
|
||||
final container = Container();
|
||||
container.bind<String>((c) => 'Taylor');
|
||||
expect(container.make<String>(), equals('Taylor'));
|
||||
}
|
||||
```
|
||||
|
||||
### Coverage Analysis
|
||||
```dart
|
||||
// Command: /ai analyze-test-coverage Container
|
||||
|
||||
AI provides:
|
||||
1. Coverage report comparing Laravel & Dart tests
|
||||
2. Missing test scenarios
|
||||
3. Additional Dart-specific tests needed
|
||||
```
|
||||
|
||||
## 3. Real-Time Development Assistance
|
||||
|
||||
### API Compatibility Checking
|
||||
```dart
|
||||
// While coding, AI actively checks:
|
||||
class Container {
|
||||
// AI Warning: Laravel's bind allows string abstracts
|
||||
void bind<T>(T Function(Container) concrete) { // <-- Compatibility issue
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// AI Suggestion:
|
||||
Consider supporting both generic and string-based binding:
|
||||
```dart
|
||||
void bind<T>(T Function(Container) concrete) { ... }
|
||||
void bindType(String abstract, Function concrete) { ... }
|
||||
```
|
||||
|
||||
### Pattern Recognition
|
||||
```dart
|
||||
// AI recognizes Laravel patterns and suggests Dart equivalents
|
||||
// Laravel:
|
||||
$container->singleton('api', function () { ... });
|
||||
|
||||
// AI suggests:
|
||||
1. Direct equivalent:
|
||||
```dart
|
||||
container.singleton<ApiService>((c) => ApiService());
|
||||
```
|
||||
|
||||
2. Attribute-based (more Dart-like):
|
||||
```dart
|
||||
@Singleton()
|
||||
class ApiService { ... }
|
||||
```
|
||||
|
||||
## 4. Documentation Generation
|
||||
|
||||
### API Documentation
|
||||
```dart
|
||||
// Command: /ai generate-docs Container::bind
|
||||
|
||||
AI generates:
|
||||
```dart
|
||||
/// Registers a binding with the container.
|
||||
///
|
||||
/// Equivalent to Laravel's Container::bind method.
|
||||
/// ```php
|
||||
/// $container->bind('api', function () { return new ApiService; });
|
||||
/// ```
|
||||
///
|
||||
/// Dart usage:
|
||||
/// ```dart
|
||||
/// container.bind<ApiService>((c) => ApiService());
|
||||
/// ```
|
||||
void bind<T>(T Function(Container) concrete, {bool shared = false});
|
||||
```
|
||||
|
||||
### Migration Guides
|
||||
```dart
|
||||
// Command: /ai generate-migration-guide Container
|
||||
|
||||
AI generates guides showing:
|
||||
1. Laravel to Dart mappings
|
||||
2. Common patterns
|
||||
3. Best practices
|
||||
```
|
||||
|
||||
## 5. Interactive Development
|
||||
|
||||
### AI Chat Commands
|
||||
```bash
|
||||
/ai explain Laravel's Container lifecycle
|
||||
/ai compare Laravel vs Dart Container
|
||||
/ai suggest refactoring for Container::bind
|
||||
/ai review current implementation
|
||||
```
|
||||
|
||||
### Context-Aware Suggestions
|
||||
```dart
|
||||
// AI maintains context across files
|
||||
// When implementing ServiceProvider:
|
||||
class ServiceProvider {
|
||||
// AI suggests methods based on Laravel's ServiceProvider
|
||||
void register() { ... } // <- AI: Required by Laravel
|
||||
void boot() { ... } // <- AI: Optional but common
|
||||
}
|
||||
```
|
||||
|
||||
## Getting Started
|
||||
|
||||
1. Install required VS Code extensions:
|
||||
- GitHub Copilot
|
||||
- Platform AI Assistant
|
||||
|
||||
2. Configure AI settings:
|
||||
```json
|
||||
{
|
||||
"platform.ai.laravel.version": "10.x",
|
||||
"platform.ai.analysis.autoCheck": true,
|
||||
"platform.ai.suggestions.enabled": true
|
||||
}
|
||||
```
|
||||
|
||||
3. Start using AI commands:
|
||||
- Type `/ai` in any Dart file to see available commands
|
||||
- Use AI suggestions for Laravel compatibility
|
||||
- Let AI help generate tests and documentation
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. Always verify AI suggestions against Laravel's documentation
|
||||
2. Use AI for initial implementation, then review and refine
|
||||
3. Let AI help maintain API compatibility
|
||||
4. Use AI-generated tests as a starting point, then add edge cases
|
||||
5. Review AI-generated documentation for accuracy
|
||||
|
||||
## Support
|
||||
|
||||
For issues or questions about AI assistance:
|
||||
1. Check the AI documentation
|
||||
2. Use `/ai help` command
|
||||
3. Report issues in the platform repository
|
109
docs/ai_docs.md
Normal file
109
docs/ai_docs.md
Normal file
|
@ -0,0 +1,109 @@
|
|||
# AI-Assisted Development Documentation
|
||||
|
||||
This document indexes our AI-related documentation and tools for the Laravel platform implementation.
|
||||
|
||||
## Core Documents
|
||||
|
||||
1. [IDD-AI Specification](idd_ai_specification.md)
|
||||
- Individual Driven Development AI methodology
|
||||
- Core principles and workflow
|
||||
- Integration with agile practices
|
||||
- DevOps practices
|
||||
|
||||
2. [Implementation Plan](implementation_plan.md)
|
||||
- Detailed plan for implementing Laravel in Dart
|
||||
- Package structure and dependencies
|
||||
- Development phases and milestones
|
||||
- Quality assurance processes
|
||||
|
||||
3. [AI Assistance Guide](ai_assistance_guide.md)
|
||||
- AI features and capabilities
|
||||
- Code analysis and generation
|
||||
- Test generation
|
||||
- Documentation generation
|
||||
|
||||
4. [AI Workflow](ai_workflow.md)
|
||||
- Integration of AI with IDD-AI methodology
|
||||
- Practical AI usage examples
|
||||
- Best practices
|
||||
- Development workflow
|
||||
|
||||
## Quick Start Guide
|
||||
|
||||
1. **Development Flow**
|
||||
```dart
|
||||
// Start with AI analysis
|
||||
/ai analyze-laravel Cache
|
||||
|
||||
// Get implementation suggestions
|
||||
/ai suggest-implementation Cache::put
|
||||
|
||||
// Generate tests
|
||||
/ai generate-tests Cache
|
||||
```
|
||||
|
||||
2. **Code Generation**
|
||||
```dart
|
||||
// Generate Laravel-compatible implementations
|
||||
/ai generate-code Cache::remember
|
||||
|
||||
// Check compatibility
|
||||
/ai check-compatibility Cache
|
||||
```
|
||||
|
||||
3. **Documentation**
|
||||
```dart
|
||||
// Generate package documentation
|
||||
/ai generate-docs Cache
|
||||
|
||||
// Create examples
|
||||
/ai create-examples Cache
|
||||
```
|
||||
|
||||
## Integration with Existing Framework
|
||||
|
||||
The AI assistance tools integrate with our existing framework development:
|
||||
|
||||
1. Package Development
|
||||
- AI analyzes Laravel's implementation
|
||||
- Suggests Dart equivalent structure
|
||||
- Generates compatible API
|
||||
- Creates comprehensive tests
|
||||
|
||||
2. Quality Assurance
|
||||
- Automated API compatibility checking
|
||||
- Test coverage analysis
|
||||
- Performance benchmarking
|
||||
- Documentation verification
|
||||
|
||||
3. Documentation
|
||||
- Automated API documentation
|
||||
- Example generation
|
||||
- Migration guides
|
||||
- Best practices
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. Always verify AI suggestions against:
|
||||
- Laravel's source code
|
||||
- Our package specifications
|
||||
- Dart best practices
|
||||
|
||||
2. Use AI for:
|
||||
- Initial implementation guidance
|
||||
- Test case generation
|
||||
- Documentation creation
|
||||
- API compatibility checks
|
||||
|
||||
3. Review all AI-generated:
|
||||
- Code implementations
|
||||
- Test cases
|
||||
- Documentation
|
||||
- Examples
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Framework Documentation](README.md)
|
||||
- [Package Specifications](core_package_specification.md)
|
||||
- [Laravel Compatibility](laravel_compatibility_roadmap.md)
|
||||
- [Testing Guide](testing_guide.md)
|
117
docs/ai_workflow.md
Normal file
117
docs/ai_workflow.md
Normal file
|
@ -0,0 +1,117 @@
|
|||
# AI-Assisted Development Workflow
|
||||
|
||||
This document explains how our AI assistance features integrate with the IDD-AI methodology for developing our Laravel platform.
|
||||
|
||||
## Integration with IDD-AI Cycle
|
||||
|
||||
### 1. Research Phase
|
||||
AI Tools Used:
|
||||
- `/ai analyze-laravel [component]` - Analyze Laravel's implementation
|
||||
- `/ai compare-frameworks` - Compare different framework approaches
|
||||
- `/ai suggest-architecture` - Get architecture recommendations
|
||||
|
||||
### 2. Identify Phase
|
||||
AI Tools Used:
|
||||
- `/ai map-dependencies` - Map package dependencies
|
||||
- `/ai analyze-api` - Analyze API requirements
|
||||
- `/ai suggest-structure` - Get package structure suggestions
|
||||
|
||||
### 3. Transform Phase
|
||||
AI Tools Used:
|
||||
- `/ai generate-contracts` - Generate interface definitions
|
||||
- `/ai suggest-implementation` - Get implementation suggestions
|
||||
- `/ai check-compatibility` - Verify Laravel compatibility
|
||||
|
||||
### 4. Inform Phase
|
||||
AI Tools Used:
|
||||
- `/ai document-decisions` - Document architectural decisions
|
||||
- `/ai generate-specs` - Generate technical specifications
|
||||
- `/ai review-approach` - Get implementation review
|
||||
|
||||
### 5. Generate Phase
|
||||
AI Tools Used:
|
||||
- `/ai generate-code` - Generate implementation code
|
||||
- `/ai generate-tests` - Create test suites
|
||||
- `/ai generate-docs` - Create documentation
|
||||
|
||||
### 6. Implement Phase
|
||||
AI Tools Used:
|
||||
- `/ai review-code` - Get code review
|
||||
- `/ai suggest-refactor` - Get refactoring suggestions
|
||||
- `/ai check-patterns` - Verify Laravel patterns
|
||||
|
||||
### 7. Test Phase
|
||||
AI Tools Used:
|
||||
- `/ai verify-tests` - Verify test coverage
|
||||
- `/ai generate-scenarios` - Generate test scenarios
|
||||
- `/ai check-behavior` - Verify Laravel behavior
|
||||
|
||||
### 8. Iterate Phase
|
||||
AI Tools Used:
|
||||
- `/ai suggest-improvements` - Get improvement suggestions
|
||||
- `/ai analyze-performance` - Get performance insights
|
||||
- `/ai check-quality` - Check code quality
|
||||
|
||||
### 9. Review Phase
|
||||
AI Tools Used:
|
||||
- `/ai review-complete` - Get comprehensive review
|
||||
- `/ai verify-compatibility` - Final compatibility check
|
||||
- `/ai generate-report` - Generate review report
|
||||
|
||||
### 10. Release Phase
|
||||
AI Tools Used:
|
||||
- `/ai generate-changelog` - Generate changelog
|
||||
- `/ai update-docs` - Update documentation
|
||||
- `/ai create-examples` - Generate usage examples
|
||||
|
||||
## Workflow Example
|
||||
|
||||
Here's how to use AI assistance when implementing a new component:
|
||||
|
||||
1. Start Research:
|
||||
```bash
|
||||
# Analyze Laravel's implementation
|
||||
/ai analyze-laravel Cache
|
||||
|
||||
# Get implementation suggestions
|
||||
/ai suggest-architecture Cache
|
||||
```
|
||||
|
||||
2. Begin Implementation:
|
||||
```bash
|
||||
# Generate initial structure
|
||||
/ai generate-structure Cache
|
||||
|
||||
# Get implementation guidance
|
||||
/ai suggest-implementation Cache::put
|
||||
```
|
||||
|
||||
3. Test Development:
|
||||
```bash
|
||||
# Generate test cases
|
||||
/ai generate-tests Cache
|
||||
|
||||
# Verify Laravel compatibility
|
||||
/ai verify-behavior Cache
|
||||
```
|
||||
|
||||
4. Documentation:
|
||||
```bash
|
||||
# Generate documentation
|
||||
/ai generate-docs Cache
|
||||
|
||||
# Create usage examples
|
||||
/ai create-examples Cache
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. Always verify AI suggestions against Laravel's source code
|
||||
2. Use AI for initial implementation, then review and refine
|
||||
3. Let AI help maintain API compatibility
|
||||
4. Use AI-generated tests as a starting point
|
||||
5. Review AI-generated documentation for accuracy
|
||||
|
||||
## Related Documents
|
||||
- [IDD-AI Specification](idd_ai_specification.md)
|
||||
- [AI Assistance Guide](ai_assistance_guide.md)
|
51
docs/assets/diagrams/README.md
Normal file
51
docs/assets/diagrams/README.md
Normal file
|
@ -0,0 +1,51 @@
|
|||
# Architecture Diagrams
|
||||
|
||||
This directory contains Mermaid diagrams illustrating the platform's architecture and component relationships.
|
||||
|
||||
## Available Diagrams
|
||||
|
||||
1. **Package Architecture**
|
||||
- Shows all platform packages
|
||||
- Illustrates package dependencies
|
||||
- Highlights core, contracts, and infrastructure layers
|
||||
|
||||
2. **Request Lifecycle**
|
||||
- Details HTTP request flow
|
||||
- Shows middleware pipeline
|
||||
- Illustrates dependency injection points
|
||||
|
||||
3. **Service Container Flow**
|
||||
- Shows dependency injection process
|
||||
- Illustrates service provider lifecycle
|
||||
- Details service resolution
|
||||
|
||||
4. **Event System**
|
||||
- Shows event dispatching
|
||||
- Illustrates listener handling
|
||||
- Details queue integration
|
||||
|
||||
5. **Database Layer**
|
||||
- Shows model relationships
|
||||
- Illustrates query building
|
||||
- Details migration system
|
||||
|
||||
6. **Package Dependencies**
|
||||
- Complete dependency graph
|
||||
- Core package relationships
|
||||
- Infrastructure dependencies
|
||||
|
||||
## Usage
|
||||
|
||||
These diagrams are written in Mermaid markdown syntax and can be:
|
||||
1. Viewed directly in GitHub
|
||||
2. Rendered using Mermaid CLI
|
||||
3. Integrated into documentation
|
||||
|
||||
## Updating
|
||||
|
||||
When making architectural changes:
|
||||
1. Update relevant diagrams
|
||||
2. Ensure accuracy
|
||||
3. Keep consistent with implementation
|
||||
|
||||
See [architecture.md](architecture.md) for the actual diagrams.
|
190
docs/assets/diagrams/architecture.md
Normal file
190
docs/assets/diagrams/architecture.md
Normal file
|
@ -0,0 +1,190 @@
|
|||
# Platform Architecture Diagrams
|
||||
|
||||
## Package Architecture
|
||||
```mermaid
|
||||
graph TD
|
||||
subgraph Core ["Core Framework"]
|
||||
Container[illuminate/container]
|
||||
Support[illuminate/support]
|
||||
Foundation[illuminate/foundation]
|
||||
Http[illuminate/http]
|
||||
Routing[illuminate/routing]
|
||||
Database[illuminate/database]
|
||||
end
|
||||
|
||||
subgraph Contracts ["Contracts Layer"]
|
||||
ContainerContract[container_contract]
|
||||
EventContract[event_contract]
|
||||
HttpContract[http_contract]
|
||||
RouteContract[route_contract]
|
||||
QueueContract[queue_contract]
|
||||
PipelineContract[pipeline_contract]
|
||||
end
|
||||
|
||||
subgraph Infrastructure ["Infrastructure"]
|
||||
Events[events]
|
||||
Queue[queue]
|
||||
Pipeline[pipeline]
|
||||
Bus[bus]
|
||||
Process[process]
|
||||
Model[model]
|
||||
end
|
||||
|
||||
%% Contract Dependencies
|
||||
Container --> ContainerContract
|
||||
Events --> EventContract
|
||||
Http --> HttpContract
|
||||
Routing --> RouteContract
|
||||
Queue --> QueueContract
|
||||
Pipeline --> PipelineContract
|
||||
|
||||
%% Core Dependencies
|
||||
Foundation --> Container
|
||||
Http --> Container
|
||||
Routing --> Http
|
||||
Database --> Container
|
||||
|
||||
%% Infrastructure Dependencies
|
||||
Events --> Container
|
||||
Queue --> Container
|
||||
Pipeline --> Container
|
||||
Bus --> Events
|
||||
Process --> Container
|
||||
Model --> Database
|
||||
```
|
||||
|
||||
## Request Lifecycle
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client
|
||||
participant Server
|
||||
participant Http
|
||||
participant Router
|
||||
participant Pipeline
|
||||
participant Controller
|
||||
participant Container
|
||||
|
||||
Client->>Server: HTTP Request
|
||||
Server->>Http: Handle Request
|
||||
Http->>Router: Route Request
|
||||
Router->>Pipeline: Process Middleware
|
||||
Pipeline->>Container: Resolve Dependencies
|
||||
Container->>Controller: Inject Dependencies
|
||||
Controller->>Client: Return Response
|
||||
```
|
||||
|
||||
## Service Container Flow
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph Container ["Container"]
|
||||
Bind[Bind Service]
|
||||
Resolve[Resolve Service]
|
||||
Make[Make Instance]
|
||||
end
|
||||
|
||||
subgraph Provider ["Service Provider"]
|
||||
Register[Register Services]
|
||||
Boot[Boot Services]
|
||||
end
|
||||
|
||||
subgraph Application ["Application"]
|
||||
Request[Handle Request]
|
||||
Response[Return Response]
|
||||
end
|
||||
|
||||
Register --> Bind
|
||||
Request --> Resolve
|
||||
Resolve --> Make
|
||||
Make --> Response
|
||||
Boot --> Request
|
||||
```
|
||||
|
||||
## Event System
|
||||
```mermaid
|
||||
graph TD
|
||||
subgraph Events ["Event System"]
|
||||
Dispatcher[Event Dispatcher]
|
||||
Listener[Event Listener]
|
||||
Queue[Queue Listener]
|
||||
end
|
||||
|
||||
subgraph Application ["Application"]
|
||||
Event[Fire Event]
|
||||
Handler[Handle Event]
|
||||
end
|
||||
|
||||
Event --> Dispatcher
|
||||
Dispatcher --> Listener
|
||||
Dispatcher --> Queue
|
||||
Listener --> Handler
|
||||
Queue --> Handler
|
||||
```
|
||||
|
||||
## Database Layer
|
||||
```mermaid
|
||||
graph TD
|
||||
subgraph Models ["Model Layer"]
|
||||
Model[Eloquent Model]
|
||||
Relation[Model Relations]
|
||||
Observer[Model Observer]
|
||||
end
|
||||
|
||||
subgraph Database ["Database"]
|
||||
Query[Query Builder]
|
||||
Schema[Schema Builder]
|
||||
Migration[Migrations]
|
||||
end
|
||||
|
||||
subgraph Events ["Events"]
|
||||
Created[Created Event]
|
||||
Updated[Updated Event]
|
||||
Deleted[Deleted Event]
|
||||
end
|
||||
|
||||
Model --> Query
|
||||
Model --> Relation
|
||||
Model --> Observer
|
||||
Observer --> Created
|
||||
Observer --> Updated
|
||||
Observer --> Deleted
|
||||
Query --> Schema
|
||||
Schema --> Migration
|
||||
```
|
||||
|
||||
## Package Dependencies
|
||||
```mermaid
|
||||
graph TD
|
||||
subgraph Core ["Core Packages"]
|
||||
Container[container]
|
||||
Support[support]
|
||||
Foundation[foundation]
|
||||
end
|
||||
|
||||
subgraph Features ["Feature Packages"]
|
||||
Http[http]
|
||||
Routing[routing]
|
||||
Database[database]
|
||||
Cache[cache]
|
||||
end
|
||||
|
||||
subgraph Infrastructure ["Infrastructure"]
|
||||
Events[events]
|
||||
Queue[queue]
|
||||
Pipeline[pipeline]
|
||||
end
|
||||
|
||||
%% Core Dependencies
|
||||
Support --> Container
|
||||
Foundation --> Container
|
||||
Foundation --> Support
|
||||
|
||||
%% Feature Dependencies
|
||||
Http --> Foundation
|
||||
Routing --> Http
|
||||
Database --> Foundation
|
||||
Cache --> Foundation
|
||||
|
||||
%% Infrastructure Dependencies
|
||||
Events --> Container
|
||||
Queue --> Events
|
||||
Pipeline --> Container
|
147
docs/idd_ai_specification.md
Normal file
147
docs/idd_ai_specification.md
Normal file
|
@ -0,0 +1,147 @@
|
|||
# IDD-AI Specification v1.3: A Comprehensive Framework for AI-Augmented, Agile Software Development
|
||||
|
||||
## 1. Introduction
|
||||
Individual Driven Development AI (IDD-AI) is a methodology that integrates AI-assisted software development with agile practices such as Scrum, Kanban, Behavior-Driven Development (BDD), Feature-Driven Development (FDD), and Test-Driven Development (TDD). IDD-AI supports both individual developers and small teams, enabling them to efficiently develop high-quality software through continuous automation, feedback, and iterative processes. The core objective is to optimize the software development lifecycle, facilitating faster development cycles while ensuring quality and responsiveness to user requirements.
|
||||
|
||||
As part of the continuous improvement of the IDD-AI methodology, DevOps practices are now incorporated to emphasize continuous integration, continuous delivery (CI/CD), and automated deployment pipelines. This ensures that development and operations teams are aligned, resulting in more efficient workflows, faster delivery cycles, and improved operational stability.
|
||||
|
||||
---
|
||||
|
||||
## 2. Core Principles of IDD-AI
|
||||
1. **AI Augmentation**: Artificial Intelligence tools aid in decision-making, automating repetitive tasks, and increasing coding productivity, enabling developers to focus on higher-level problem-solving.
|
||||
2. **Iterative and Incremental Development**: IDD-AI leverages Scrum and Kanban to support rapid iteration, quick feedback, and feature-driven delivery, ensuring continuous progress.
|
||||
3. **Feature-Focused Delivery**: Drawing on FDD and BDD, IDD-AI focuses on delivering features that meet business requirements, with testing integrated throughout the development lifecycle.
|
||||
4. **Test-First Development (TDD)**: IDD-AI integrates TDD as a foundational approach, ensuring robust testing coverage and high code quality right from the start.
|
||||
5. **Continuous Flow with Kanban**: Kanban's principles ensure a smooth task flow, minimizing bottlenecks and providing visibility into the development process, ensuring no task is left behind.
|
||||
|
||||
6. **DevOps Practices**: The integration of DevOps emphasizes automation, continuous testing, and continuous delivery. This improves collaboration between development and operations, providing faster feedback and ensuring that code is continuously integrated and deployed with minimal disruption to production.
|
||||
|
||||
---
|
||||
|
||||
## 3. IDD-AI Methodology Workflow
|
||||
The **RITIGITIRR cycle**—standing for **Research, Identify, Transform, Inform, Generate, Implement, Test, Iterate, Review, Release**—integrates agile principles to create a comprehensive software development process that adapts to both individual developers and small teams. Each phase in the cycle is designed to maximize AI support, ensuring efficiency, quality, and continuous improvement.
|
||||
|
||||
### 3.1 Research
|
||||
- **AI-Augmented Research**: AI tools assist in gathering project-relevant data, trends, technical solutions, and benchmarks to guide decision-making.
|
||||
- **Kanban**: Research tasks are visualized on a Kanban board, ensuring tasks are handled in a streamlined, prioritized manner.
|
||||
- **Scrum**: Research tasks are included in sprint planning, ensuring focus and alignment with overall project goals.
|
||||
- **BDD**: Initial business requirements and user behavior scenarios are outlined in Gherkin format for later development.
|
||||
- **FDD**: Research tasks contribute to the overall feature roadmap, ensuring that the development effort is focused on delivering valuable features.
|
||||
- **DevOps**: Research includes reviewing deployment requirements and ensuring compatibility with infrastructure and tooling.
|
||||
|
||||
### 3.2 Identify
|
||||
- **AI Assistance in Identification**: AI tools recommend technologies, frameworks, and libraries suited for the project, streamlining the technology selection process.
|
||||
- **Kanban**: Identification tasks are prioritized on the Kanban board, allowing efficient allocation of resources.
|
||||
- **Scrum**: Features and functionalities are identified, broken down into tasks, and assigned to sprints for implementation.
|
||||
- **FDD & BDD**: Features are decomposed into smaller tasks, defined in detail for implementation, while business outcomes are specified in user-friendly terms.
|
||||
- **DevOps**: Identifying tools and technologies compatible with the CI/CD pipeline is integrated early in the process.
|
||||
|
||||
### 3.3 Transform
|
||||
- **Abstract Contracts**: AI assists in transforming high-level business requirements into technical specifications or abstract contracts (e.g., YAML, JSON).
|
||||
- **Kanban**: The transformation phase is visualized on Kanban, with tasks flowing towards code-ready specifications.
|
||||
- **BDD**: Behavior-driven test cases are created for each identified feature.
|
||||
- **FDD**: Features are further broken down into development tasks, ensuring they are clearly actionable.
|
||||
- **DevOps**: Ensure that transformation also considers the need for configuration files for CI/CD pipelines (e.g., Jenkins, GitLab CI).
|
||||
|
||||
### 3.4 Inform
|
||||
- **AI-Driven Architecture**: AI tools suggest suitable architectural patterns and best practices, ensuring that decisions are informed by data and aligned with project goals.
|
||||
- **Kanban**: Architectural decisions are visualized on the Kanban board, ensuring clarity in task flow and preventing delays.
|
||||
- **Scrum**: Design discussions in sprint planning are informed by architectural insights, ensuring alignment between design and user stories.
|
||||
- **BDD**: Business-driven test cases are refined in response to architectural changes, ensuring the system meets evolving requirements.
|
||||
- **DevOps**: Architectural decisions are informed by the need for scalability, security, and maintainability in the CI/CD pipeline.
|
||||
|
||||
### 3.5 Generate
|
||||
- **AI Code Generation**: AI generates boilerplate code, assists with code completion, and suggests optimizations for frequently used patterns, enabling rapid development.
|
||||
- **Kanban**: Code generation tasks are tracked and managed on the Kanban board.
|
||||
- **FDD**: Features are developed incrementally, ensuring they align with business goals and remain manageable.
|
||||
- **TDD**: AI-generated test cases drive development, ensuring that each feature is tested from the start.
|
||||
- **DevOps**: AI-generated code is integrated with Generated code includes configurations for the CI/CD pipeline, ensuring readiness for integration and deployment.
|
||||
|
||||
### 3.6 Implement
|
||||
- **AI-Powered Code Integration**: AI helps in integrating code with the larger system, checking for compatibility, and recommending changes for efficient integration.
|
||||
- **Kanban**: Tasks related to code integration are tracked to ensure smooth progression and integration with existing codebases.
|
||||
- **Scrum**: Development during the sprint focuses on completing tasks as defined in the backlog.
|
||||
- **BDD**: Features are implemented based on business-driven specifications.
|
||||
- **FDD**: Incremental development ensures that features are deployed as they are completed.
|
||||
- **TDD**: Tests are continuously run during the development phase to ensure code correctness.
|
||||
- **DevOps**: Integration tasks automatically trigger continuous integration (CI) pipelines to validate code integration with the system.
|
||||
|
||||
### 3.7 Test
|
||||
- **AI-Generated Testing**: AI tools automatically generate comprehensive test suites, ensuring all edge cases are covered and reducing manual effort.
|
||||
- **Kanban**: Testing tasks are continuously tracked on the Kanban board, ensuring integration with the overall project.
|
||||
- **BDD**: Behavior-driven tests are automatically executed to validate features, ensuring they perform as specified.
|
||||
- **TDD**: Automated tests ensure that new code does not break existing functionality, providing early detection of issues.
|
||||
- **DevOps**: Automated testing is integrated into the CI/CD pipeline, ensuring that changes are tested before deployment.
|
||||
|
||||
### 3.8 Iterate
|
||||
- **AI-Driven Iteration**: AI provides insights on refactoring opportunities, performance improvements, and optimizations, enhancing the system's overall efficiency.
|
||||
- **Kanban**: The Kanban board helps monitor and optimize the flow of tasks based on feedback, ensuring that priorities are adjusted dynamically.
|
||||
- **Scrum**: Sprint reviews inform necessary adjustments and improvements for future iterations.
|
||||
- **BDD & FDD**: Features are refined based on user feedback, with iterative cycles ensuring alignment with business goals and user needs.
|
||||
- **DevOps**: Iterative development allows for continuous improvement and optimization of the CI/CD pipeline, ensuring that changes are efficiently tested and deployed.
|
||||
|
||||
### 3.9 Review
|
||||
- **AI-Assisted Code Review**: AI tools analyze code quality, flagging performance issues, security vulnerabilities, and adherence to best practices.
|
||||
- **Kanban**: Tasks are reviewed and moved to completion once they meet predefined criteria.
|
||||
- **Scrum**: Sprint reviews assess whether project goals have been met and adjust the backlog for future work.
|
||||
- **BDD & TDD**: Automated tests provide objective feedback on the correctness and functionality of the software before release.
|
||||
- **DevOps**: Code reviews are integrated into the CI/CD pipeline, ensuring that changes are thoroughly tested and reviewed before deployment.
|
||||
|
||||
### 3.10 Release
|
||||
- **AI-Generated Documentation**: AI tools automatically generate release notes, technical documentation, and change logs to ensure stakeholders are informed of the latest changes.
|
||||
- **Kanban**: Release tasks are marked as complete, and the product is prepared for deployment.
|
||||
- **Scrum**: Final deployment occurs as part of the sprint's release process, ensuring that features are production-ready.
|
||||
- **BDD & TDD**: All tests are executed, ensuring that features perform as expected in the final product.
|
||||
- **DevOps**: Automated deployment scripts ensure that the release process is efficient and error-free.
|
||||
|
||||
---
|
||||
|
||||
## 4. Role of Kanban in IDD-AI: Ensuring Continuous Flow
|
||||
- **Visualizing Work**: All tasks across stages are displayed, providing team members with clear visibility into progress.
|
||||
- **WIP Limits**: By limiting the number of tasks in progress at any given time, Kanban prevents overload and ensures a balanced workflow.
|
||||
- **Flow Efficiency**: Continuous monitoring and feedback help ensure the development process remains efficient, resolving any emerging bottlenecks quickly.
|
||||
- **Adaptability**: Kanban's flexibility allows for adjustments to the development process based on changing requirements and priorities.
|
||||
- **Collaboration**: Kanban fosters collaboration by promoting transparency and encouraging team members to help each other, ensuring that tasks are completed efficiently and smoothly.
|
||||
- **DevOps**: Kanban helps track deployment tasks in alignment with the CI/CD pipeline, ensuring a smooth flow of changes from development to production.
|
||||
|
||||
---
|
||||
|
||||
## 5. Conclusion: The Key to Effective AI-Driven Development
|
||||
|
||||
IDD-AI is not just a framework—it’s a paradigm shift in the world of AI-driven software development. The core strength of this methodology lies in its ability to leverage AI’s speed, adaptability, and context awareness within small, manageable cycles. Traditional development methods, often hindered by extended work sessions and complex, long-running tasks, simply cannot harness AI’s full potential. As AI excels in tasks with shorter feedback loops and higher iteration frequencies, this framework builds on that inherent strength to produce more reliable, scalable, and maintainable software.
|
||||
|
||||
By integrating agile practices such as Scrum, Kanban, TDD, and BDD, combined with the power of AI, we create a feedback-driven environment where context is continually updated, learned, and applied. This ensures that AI can stay focused, understand evolving project needs, and rapidly adjust its recommendations, resulting in more accurate and actionable code at every step.
|
||||
|
||||
This approach, fundamentally centered around context and guidance, solves a critical issue that has plagued many AI-powered tools: losing track of context over long sessions or tasks. By employing rapid iteration, continuous feedback, and a structure that adapts as the project evolves, IDD-AI mitigates the risk of missteps while optimizing the development process. It aligns AI and human capabilities to achieve higher productivity and quality, unlocking the potential for Rapid Application Development (RAD-AI)—a concept where AI not only accelerates the coding process but also contributes meaningfully to problem-solving in real time.
|
||||
|
||||
The novelty of this approach lies not just in the incorporation of AI but in how it synergizes with the methodology to maintain a balance between human creativity and AI-driven automation. This makes IDD-AI highly suitable for solo developers and small teams who seek to harness AI’s power without losing control or oversight. Moreover, scalability is inherently baked into the methodology, ensuring that as the team grows, the approach seamlessly adapts to larger collaborations.
|
||||
|
||||
Additionally, DevOps practices enhance this methodology by integrating continuous feedback loops between development and operations teams. Through Continuous Integration (CI) and Continuous Deployment (CD), the development process becomes more efficient, with automation ensuring faster delivery cycles and consistent quality across deployments. This integration of DevOps into the IDD-AI framework helps streamline the software development lifecycle, ensuring that as AI-generated code is refined and deployed, feedback from CI/CD processes is continuously applied to improve the system.
|
||||
|
||||
---
|
||||
|
||||
## Key Additional Advantages
|
||||
|
||||
### Human-AI Collaboration at its Best
|
||||
Instead of merely automating tasks, AI in this framework acts as a collaborator, complementing human judgment with data-driven insights, code generation, and error detection. This leads to higher-quality code and better decision-making.
|
||||
|
||||
### Faster Ramp-Up and Context Switching
|
||||
With continuous feedback loops, AI can assist developers in ramping up quickly on new technologies or tools, bridging knowledge gaps, and reducing the time needed for context switching between tasks.
|
||||
|
||||
### Continuous Learning and Improvement
|
||||
The integration of AI across the entire development lifecycle creates a self-improving system, where each cycle of feedback not only refines the code but also enhances AI’s performance. This leads to smarter, more capable AI over time, growing alongside the project.
|
||||
|
||||
### Focus on High-Level Problem Solving
|
||||
The repetitive tasks in development are handled by AI, leaving human developers to focus on higher-level problem-solving and feature development. This increases developer satisfaction and enables more innovative solutions.
|
||||
|
||||
### Increased Developer Productivity
|
||||
Through AI-assisted code generation, automated testing, and immediate feedback, developers can accelerate development cycles while maintaining high standards for code quality, effectively reducing time to market.
|
||||
|
||||
### Seamless Adaptability to Changing Requirements
|
||||
The agile nature of this methodology, combined with AI's ability to learn and adapt, allows for a high degree of flexibility in handling evolving requirements. This is especially beneficial in fast-paced environments where requirements may shift frequently.
|
||||
|
||||
---
|
||||
|
||||
## In Conclusion
|
||||
|
||||
IDD-AI is not just a method—it’s the future of AI-enhanced, agile software development. By leveraging the strengths of AI within the structure of proven agile practices, we create a framework that is faster, smarter, and more responsive than anything previously available. This methodology opens up the possibilities for Rapid AI-Driven Application Development (RAD-AI), where the AI does not just assist but actively propels the development process. With AI and human collaboration at its core, this framework represents the next evolution in software development: efficient, adaptable, and always learning.
|
202
docs/implementation_plan.md
Normal file
202
docs/implementation_plan.md
Normal file
|
@ -0,0 +1,202 @@
|
|||
# Laravel Platform Implementation Plan
|
||||
|
||||
This document outlines our plan to implement a Laravel-compatible platform in Dart, using Lucifer as a base and following the IDD-AI methodology with AI assistance.
|
||||
|
||||
## Overview
|
||||
|
||||
### Goals
|
||||
1. 100% Laravel API compatibility
|
||||
2. Clean, maintainable Dart implementation
|
||||
3. Package independence
|
||||
4. Excellent developer experience
|
||||
|
||||
### Strategy
|
||||
1. Use Lucifer as minimal foundation
|
||||
2. Break into illuminate/* packages
|
||||
3. Follow Laravel's architecture
|
||||
4. Leverage AI assistance
|
||||
5. Follow IDD-AI methodology
|
||||
|
||||
## Implementation Phases
|
||||
|
||||
### Phase 1: Foundation
|
||||
Starting with Lucifer's base:
|
||||
|
||||
1. Container (Complete)
|
||||
- [x] Our implementation done
|
||||
- [x] Laravel API compatible
|
||||
- [x] Tests complete
|
||||
|
||||
2. Support Package (Next)
|
||||
```dart
|
||||
// Example of Laravel compatibility
|
||||
// Laravel: Str::slug('Laravel Framework')
|
||||
// Dart: Str.slug('Laravel Framework')
|
||||
```
|
||||
AI Tasks:
|
||||
- `/ai analyze-laravel Support`
|
||||
- `/ai suggest-implementation Support`
|
||||
- `/ai generate-tests Support`
|
||||
|
||||
3. Foundation Package
|
||||
```dart
|
||||
// Example of service provider registration
|
||||
// Laravel: $app->register(CacheServiceProvider::class)
|
||||
// Dart: app.register(CacheServiceProvider())
|
||||
```
|
||||
AI Tasks:
|
||||
- `/ai analyze-laravel Foundation`
|
||||
- `/ai suggest-architecture Foundation`
|
||||
- `/ai generate-contracts Foundation`
|
||||
|
||||
### Phase 2: HTTP Layer
|
||||
|
||||
1. HTTP Package
|
||||
```dart
|
||||
// Example of request handling
|
||||
// Laravel: $request->input('name')
|
||||
// Dart: request.input('name')
|
||||
```
|
||||
AI Tasks:
|
||||
- `/ai analyze-laravel Http`
|
||||
- `/ai suggest-implementation Request`
|
||||
- `/ai generate-tests Http`
|
||||
|
||||
2. Routing Package
|
||||
```dart
|
||||
// Example of route definition
|
||||
// Laravel: Route::get('/users', [UserController::class, 'index'])
|
||||
// Dart: Route.get('/users', UserController.index)
|
||||
```
|
||||
AI Tasks:
|
||||
- `/ai analyze-laravel Routing`
|
||||
- `/ai suggest-implementation Router`
|
||||
- `/ai check-compatibility Routing`
|
||||
|
||||
### Phase 3: Database Layer
|
||||
|
||||
1. Database Package
|
||||
```dart
|
||||
// Example of query builder
|
||||
// Laravel: DB::table('users')->where('active', true)->get()
|
||||
// Dart: DB.table('users').where('active', true).get()
|
||||
```
|
||||
AI Tasks:
|
||||
- `/ai analyze-laravel Database`
|
||||
- `/ai suggest-implementation QueryBuilder`
|
||||
- `/ai generate-tests Database`
|
||||
|
||||
2. Model Package
|
||||
```dart
|
||||
// Example of model definition
|
||||
// Laravel: class User extends Model
|
||||
// Dart: class User extends Model
|
||||
```
|
||||
AI Tasks:
|
||||
- `/ai analyze-laravel Model`
|
||||
- `/ai suggest-implementation Model`
|
||||
- `/ai check-compatibility Model`
|
||||
|
||||
## Development Process
|
||||
|
||||
For each package:
|
||||
|
||||
1. Research Phase
|
||||
```bash
|
||||
# Analyze Laravel implementation
|
||||
/ai analyze-laravel [package]
|
||||
|
||||
# Get architecture suggestions
|
||||
/ai suggest-architecture [package]
|
||||
```
|
||||
|
||||
2. Implementation Phase
|
||||
```bash
|
||||
# Generate package structure
|
||||
/ai generate-structure [package]
|
||||
|
||||
# Get implementation guidance
|
||||
/ai suggest-implementation [package]
|
||||
```
|
||||
|
||||
3. Testing Phase
|
||||
```bash
|
||||
# Generate tests
|
||||
/ai generate-tests [package]
|
||||
|
||||
# Verify Laravel compatibility
|
||||
/ai verify-behavior [package]
|
||||
```
|
||||
|
||||
4. Documentation Phase
|
||||
```bash
|
||||
# Generate docs
|
||||
/ai generate-docs [package]
|
||||
|
||||
# Create examples
|
||||
/ai create-examples [package]
|
||||
```
|
||||
|
||||
## Package Dependencies
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Container] --> B[Support]
|
||||
B --> C[Foundation]
|
||||
C --> D[Http]
|
||||
C --> E[Routing]
|
||||
C --> F[Database]
|
||||
F --> G[Model]
|
||||
```
|
||||
|
||||
## Quality Assurance
|
||||
|
||||
1. API Compatibility
|
||||
```bash
|
||||
# Check API compatibility
|
||||
/ai check-compatibility [package]
|
||||
|
||||
# Verify behavior
|
||||
/ai verify-behavior [package]
|
||||
```
|
||||
|
||||
2. Testing
|
||||
```bash
|
||||
# Generate comprehensive tests
|
||||
/ai generate-tests [package] --comprehensive
|
||||
|
||||
# Check test coverage
|
||||
/ai analyze-coverage [package]
|
||||
```
|
||||
|
||||
3. Documentation
|
||||
```bash
|
||||
# Generate package docs
|
||||
/ai generate-docs [package]
|
||||
|
||||
# Create migration guide
|
||||
/ai generate-migration-guide [package]
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. Begin with Support package:
|
||||
- [ ] Analyze Laravel's Support package
|
||||
- [ ] Create package structure
|
||||
- [ ] Implement core functionality
|
||||
- [ ] Add tests and documentation
|
||||
|
||||
2. Move to Foundation:
|
||||
- [ ] Design service provider system
|
||||
- [ ] Implement application class
|
||||
- [ ] Set up bootstrapping
|
||||
|
||||
3. Continue with HTTP/Routing:
|
||||
- [ ] Design HTTP abstractions
|
||||
- [ ] Implement routing system
|
||||
- [ ] Add middleware support
|
||||
|
||||
## Related Documents
|
||||
- [IDD-AI Specification](idd_ai_specification.md)
|
||||
- [AI Assistance Guide](ai_assistance_guide.md)
|
||||
- [AI Workflow](ai_workflow.md)
|
214
docs/project_map.md
Normal file
214
docs/project_map.md
Normal file
|
@ -0,0 +1,214 @@
|
|||
# Platform Project Map
|
||||
|
||||
## Package Structure
|
||||
|
||||
### Core Packages
|
||||
```
|
||||
packages/
|
||||
illuminate/ # Laravel-compatible implementations
|
||||
container/ # ✓ Complete
|
||||
support/ # In Progress
|
||||
http/ # Planned
|
||||
routing/ # Planned
|
||||
...
|
||||
|
||||
contracts/ # ✓ Complete
|
||||
lib/src/
|
||||
container/ # Container contracts
|
||||
events/ # Event dispatcher contracts
|
||||
http/ # HTTP contracts
|
||||
pipeline/ # Pipeline contracts
|
||||
queue/ # Queue contracts
|
||||
...
|
||||
|
||||
core/ # Core functionality
|
||||
lib/src/
|
||||
core/ # Core components
|
||||
http/ # HTTP implementation
|
||||
http2/ # HTTP/2 support
|
||||
```
|
||||
|
||||
### Infrastructure Packages
|
||||
```
|
||||
packages/
|
||||
bus/ # Command/Event bus
|
||||
events/ # Event system
|
||||
model/ # Data models
|
||||
pipeline/ # Pipeline processing
|
||||
process/ # Process management
|
||||
queue/ # Queue system
|
||||
route/ # Routing system
|
||||
support/ # Support utilities
|
||||
testing/ # Testing utilities
|
||||
```
|
||||
|
||||
## Package Dependencies
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[contracts] --> B[container]
|
||||
A --> C[events]
|
||||
A --> D[pipeline]
|
||||
A --> E[queue]
|
||||
A --> F[http]
|
||||
B --> G[core]
|
||||
C --> G
|
||||
D --> G
|
||||
E --> G
|
||||
```
|
||||
|
||||
## Implementation Status
|
||||
|
||||
### Core Framework
|
||||
1. Container Package ✓
|
||||
- [x] Basic container
|
||||
- [x] Service providers
|
||||
- [x] Auto-wiring
|
||||
- [x] Contextual binding
|
||||
- [x] Method injection
|
||||
|
||||
2. Contracts Package ✓
|
||||
- [x] Container contracts
|
||||
- [x] Event contracts
|
||||
- [x] HTTP contracts
|
||||
- [x] Pipeline contracts
|
||||
- [x] Queue contracts
|
||||
|
||||
3. Core Package
|
||||
- [x] Base application
|
||||
- [x] HTTP kernel
|
||||
- [x] Service providers
|
||||
- [ ] Configuration
|
||||
- [ ] Environment handling
|
||||
|
||||
### Infrastructure
|
||||
1. Events Package
|
||||
- [x] Event dispatcher
|
||||
- [x] Event subscribers
|
||||
- [ ] Event broadcasting
|
||||
- [ ] Queued events
|
||||
|
||||
2. Pipeline Package
|
||||
- [x] Pipeline processing
|
||||
- [x] Middleware support
|
||||
- [ ] Pipeline stages
|
||||
- [ ] Error handling
|
||||
|
||||
3. Queue Package
|
||||
- [x] Queue manager
|
||||
- [x] Job dispatching
|
||||
- [ ] Failed jobs
|
||||
- [ ] Job batching
|
||||
|
||||
4. Route Package
|
||||
- [x] Route registration
|
||||
- [x] Route matching
|
||||
- [ ] Route groups
|
||||
- [ ] Route caching
|
||||
|
||||
## Laravel API Compatibility
|
||||
|
||||
### Implemented
|
||||
1. Container API
|
||||
```dart
|
||||
// Laravel: app()->bind()
|
||||
container.bind<Service>((c) => ServiceImpl());
|
||||
|
||||
// Laravel: app()->singleton()
|
||||
container.singleton<Cache>((c) => RedisCache());
|
||||
```
|
||||
|
||||
2. Events API
|
||||
```dart
|
||||
// Laravel: Event::dispatch()
|
||||
events.dispatch(UserCreated(user));
|
||||
|
||||
// Laravel: Event::listen()
|
||||
events.listen<UserCreated>((event) => ...);
|
||||
```
|
||||
|
||||
### In Progress
|
||||
1. Support Package
|
||||
```dart
|
||||
// Laravel: Str::slug()
|
||||
Str.slug('Laravel Framework');
|
||||
|
||||
// Laravel: collect()
|
||||
Collection.collect(['a', 'b']);
|
||||
```
|
||||
|
||||
2. HTTP Package
|
||||
```dart
|
||||
// Laravel: Request::input()
|
||||
request.input('name');
|
||||
|
||||
// Laravel: Response::json()
|
||||
response.json({'status': 'success'});
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. Support Package
|
||||
- [ ] String helpers
|
||||
- [ ] Array helpers
|
||||
- [ ] Collections
|
||||
- [ ] Fluent interface
|
||||
|
||||
2. HTTP Package
|
||||
- [ ] Request handling
|
||||
- [ ] Response building
|
||||
- [ ] Middleware system
|
||||
- [ ] Session management
|
||||
|
||||
3. Database Package
|
||||
- [ ] Query builder
|
||||
- [ ] Schema builder
|
||||
- [ ] Migrations
|
||||
- [ ] Model system
|
||||
|
||||
## Development Workflow
|
||||
|
||||
1. Package Development
|
||||
```bash
|
||||
# Create new package
|
||||
dart create packages/illuminate/[package]
|
||||
|
||||
# Set up package
|
||||
cd packages/illuminate/[package]
|
||||
dart pub get
|
||||
```
|
||||
|
||||
2. Testing
|
||||
```bash
|
||||
# Run tests
|
||||
dart test
|
||||
|
||||
# Check coverage
|
||||
dart test --coverage
|
||||
```
|
||||
|
||||
3. Documentation
|
||||
```bash
|
||||
# Generate docs
|
||||
dart doc .
|
||||
|
||||
# Serve docs
|
||||
dhttpd --path doc/api
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
1. Documentation
|
||||
- [Framework Documentation](README.md)
|
||||
- [IDD-AI Specification](idd_ai_specification.md)
|
||||
- [AI Workflow](ai_workflow.md)
|
||||
|
||||
2. Specifications
|
||||
- [Core Package Specification](core_package_specification.md)
|
||||
- [Container Package Specification](container_package_specification.md)
|
||||
- [Support Package Specification](support_package_specification.md)
|
||||
|
||||
3. Analysis
|
||||
- [Container Gap Analysis](container_gap_analysis.md)
|
||||
- [Events Gap Analysis](events_gap_analysis.md)
|
||||
- [Pipeline Gap Analysis](pipeline_gap_analysis.md)
|
402
packages/contracts/pubspec.lock
Normal file
402
packages/contracts/pubspec.lock
Normal file
|
@ -0,0 +1,402 @@
|
|||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
_fe_analyzer_shared:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: _fe_analyzer_shared
|
||||
sha256: "45cfa8471b89fb6643fe9bf51bd7931a76b8f5ec2d65de4fb176dba8d4f22c77"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "73.0.0"
|
||||
_macros:
|
||||
dependency: transitive
|
||||
description: dart
|
||||
source: sdk
|
||||
version: "0.3.2"
|
||||
analyzer:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: analyzer
|
||||
sha256: "4959fec185fe70cce007c57e9ab6983101dbe593d2bf8bbfb4453aaec0cf470a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.8.0"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.6.0"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.12.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.19.1"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: convert
|
||||
sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
coverage:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: coverage
|
||||
sha256: "4b03e11f6d5b8f6e5bb5e9f7889a56fe6c5cbe942da5378ea4d4d7f73ef9dfe5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.6"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.1"
|
||||
frontend_server_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: frontend_server_client
|
||||
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: glob
|
||||
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_multi_server
|
||||
sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.1"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_parser
|
||||
sha256: "76d306a1c3afb33fe82e2bbacad62a61f409b5634c915fceb0d799de1a913360"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.1"
|
||||
io:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: io
|
||||
sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.1"
|
||||
lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: lints
|
||||
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: logging
|
||||
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
macros:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: macros
|
||||
sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.2-main.4"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.16+1"
|
||||
meta:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: meta
|
||||
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.16.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: mime
|
||||
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
node_preamble:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: node_preamble
|
||||
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
package_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_config
|
||||
sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
pool:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pool
|
||||
sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.1"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pub_semver
|
||||
sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf
|
||||
sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.2"
|
||||
shelf_packages_handler:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_packages_handler
|
||||
sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
shelf_static:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_static
|
||||
sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.3"
|
||||
shelf_web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_web_socket
|
||||
sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
source_map_stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_map_stack_trace
|
||||
sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
source_maps:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_maps
|
||||
sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.10.12"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.12.0"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
sha256: "0bd04f5bb74fcd6ff0606a888a30e917af9bd52820b178eaa464beb11dca84b6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
test:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: test
|
||||
sha256: "713a8789d62f3233c46b4a90b174737b2c04cb6ae4500f2aa8b1be8f03f5e67f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.25.8"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.3"
|
||||
test_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_core
|
||||
sha256: "12391302411737c176b0b5d6491f466b0dd56d4763e347b6714efbaa74d7953d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.5"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "14.3.1"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: watcher
|
||||
sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket
|
||||
sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.6"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
webkit_inspection_protocol:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webkit_inspection_protocol
|
||||
sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: yaml
|
||||
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
sdks:
|
||||
dart: ">=3.5.0 <4.0.0"
|
|
@ -8,21 +8,26 @@ import 'package:platform_testing/http.dart';
|
|||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
test('preinjects functions', () async {
|
||||
test('preinjects functions when executed', () async {
|
||||
// Create app with mirrors reflector
|
||||
var app = Application(reflector: MirrorsReflector())
|
||||
..configuration['foo'] = 'bar'
|
||||
..get('/foo', ioc(echoAppFoo));
|
||||
app.optimizeForProduction(force: true);
|
||||
print(app.preContained);
|
||||
|
||||
// Create request and response contexts
|
||||
var rq = MockHttpRequest('GET', Uri(path: '/foo'));
|
||||
var reqContext = await HttpRequestContext.from(rq, app, '/foo');
|
||||
var resContext = HttpResponseContext(rq.response, app, reqContext);
|
||||
|
||||
// Force pre-injection by running the handler
|
||||
await app.runReflected(echoAppFoo, reqContext, resContext);
|
||||
|
||||
// Verify preContained has the function
|
||||
expect(app.preContained.keys, contains(echoAppFoo));
|
||||
|
||||
var rq = MockHttpRequest('GET', Uri(path: '/foo'));
|
||||
await rq.close();
|
||||
await PlatformHttp(app).handleRequest(rq);
|
||||
var rs = rq.response;
|
||||
var body = await rs.transform(utf8.decoder).join();
|
||||
expect(body, json.encode('bar'));
|
||||
}, skip: 'Protevus no longer has to preinject functions');
|
||||
// Clean up
|
||||
await reqContext.close();
|
||||
});
|
||||
}
|
||||
|
||||
String echoAppFoo(String foo) => foo;
|
||||
|
|
21
packages/reflection/LICENSE
Normal file
21
packages/reflection/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2024 The Reflection Authors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
167
packages/reflection/README.md
Normal file
167
packages/reflection/README.md
Normal file
|
@ -0,0 +1,167 @@
|
|||
# Dart Pure Reflection
|
||||
|
||||
A lightweight, cross-platform reflection system for Dart that provides runtime type introspection and manipulation without using `dart:mirrors` or code generation.
|
||||
|
||||
## Features
|
||||
|
||||
- ✅ Works on all platforms (Web, Mobile, Desktop)
|
||||
- ✅ No dependency on `dart:mirrors`
|
||||
- ✅ No code generation required
|
||||
- ✅ Pure runtime reflection
|
||||
- ✅ Type-safe property access
|
||||
- ✅ Method invocation with argument validation
|
||||
- ✅ Constructor invocation support
|
||||
- ✅ Comprehensive error handling
|
||||
|
||||
## Installation
|
||||
|
||||
Add this to your package's `pubspec.yaml` file:
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
reflection: ^1.0.0
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Setup
|
||||
|
||||
1. Add the `@reflectable` annotation and `Reflector` mixin to your class:
|
||||
|
||||
```dart
|
||||
import 'package:reflection/reflection.dart';
|
||||
|
||||
@reflectable
|
||||
class User with Reflector {
|
||||
String name;
|
||||
int age;
|
||||
final String id;
|
||||
|
||||
User(this.name, this.age, {required this.id});
|
||||
}
|
||||
```
|
||||
|
||||
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
|
||||
|
||||
```dart
|
||||
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(', ')}');
|
||||
```
|
||||
|
||||
### Working with Instances
|
||||
|
||||
```dart
|
||||
final user = User('john_doe', 30, id: 'usr_123');
|
||||
final userReflector = reflector.reflect(user);
|
||||
|
||||
// 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);
|
||||
|
||||
// Invoke methods
|
||||
userReflector.invoke('someMethod', ['arg1', 'arg2']);
|
||||
```
|
||||
|
||||
### Creating Instances
|
||||
|
||||
```dart
|
||||
// Using default constructor
|
||||
final newUser = reflector.createInstance(
|
||||
User,
|
||||
positionalArgs: ['alice', 28],
|
||||
namedArgs: {'id': 'usr_456'},
|
||||
) as User;
|
||||
|
||||
// Using named constructor
|
||||
final specialUser = reflector.createInstance(
|
||||
User,
|
||||
constructorName: 'special',
|
||||
positionalArgs: ['bob'],
|
||||
) as User;
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
The package provides specific exceptions for different error cases:
|
||||
|
||||
- `NotReflectableException`: Thrown when attempting to reflect on a non-reflectable type
|
||||
- `ReflectionException`: Base class for reflection-related errors
|
||||
- `InvalidArgumentsException`: Thrown when providing invalid arguments to a method or constructor
|
||||
- `MemberNotFoundException`: Thrown when a property or method is not found
|
||||
|
||||
```dart
|
||||
try {
|
||||
reflector.reflect(NonReflectableClass());
|
||||
} catch (e) {
|
||||
print(e); // NotReflectableException: Type "NonReflectableClass" is not marked as @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:
|
||||
|
||||
- **dart:mirrors**: API design and metadata structure
|
||||
- **fake_reflection**: Registration-based approach
|
||||
- **mirrors.cc**: Runtime type handling
|
||||
|
||||
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
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! Please read our [contributing guidelines](CONTRIBUTING.md) before submitting pull requests.
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
172
packages/reflection/example/reflection_example.dart
Normal file
172
packages/reflection/example/reflection_example.dart
Normal file
|
@ -0,0 +1,172 @@
|
|||
import 'package:platform_reflection/reflection.dart';
|
||||
|
||||
@reflectable
|
||||
class User with Reflector {
|
||||
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;
|
||||
}
|
||||
|
||||
void birthday() {
|
||||
age++;
|
||||
}
|
||||
|
||||
String greet([String greeting = 'Hello']) => '$greeting, $name!';
|
||||
|
||||
@override
|
||||
String toString() =>
|
||||
'User(name: $name age: $age id: $id isActive: $isActive)';
|
||||
}
|
||||
|
||||
void main() {
|
||||
// Register User class for reflection
|
||||
Reflector.register(User);
|
||||
|
||||
// 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);
|
||||
|
||||
// Register methods
|
||||
Reflector.registerMethod(
|
||||
User,
|
||||
'birthday',
|
||||
[],
|
||||
true, // returns void
|
||||
);
|
||||
Reflector.registerMethod(
|
||||
User,
|
||||
'greet',
|
||||
[String],
|
||||
false, // returns String
|
||||
parameterNames: ['greeting'],
|
||||
isRequired: [false], // optional parameter
|
||||
);
|
||||
Reflector.registerMethod(
|
||||
User,
|
||||
'deactivate',
|
||||
[],
|
||||
true, // returns void
|
||||
);
|
||||
|
||||
// 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],
|
||||
);
|
||||
|
||||
Reflector.registerConstructor(
|
||||
User,
|
||||
'guest',
|
||||
() => User.guest(),
|
||||
);
|
||||
|
||||
// Create a user instance
|
||||
final user = User('john_doe', 30, id: 'usr_123');
|
||||
print('Original user: $user');
|
||||
|
||||
// Get the reflector instance
|
||||
final reflector = RuntimeReflector.instance;
|
||||
|
||||
// Reflect on the User type
|
||||
final userType = reflector.reflectType(User);
|
||||
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(', ')}');
|
||||
|
||||
// Create an instance reflector
|
||||
final userReflector = reflector.reflect(user);
|
||||
|
||||
// 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')}');
|
||||
|
||||
// Modify properties
|
||||
print('\nModifying properties:');
|
||||
userReflector.setField('name', 'jane_doe');
|
||||
userReflector.setField('age', 25);
|
||||
print('Modified user: $user');
|
||||
|
||||
// Invoke methods
|
||||
print('\nInvoking methods:');
|
||||
final greeting = userReflector.invoke('greet', ['Hi']);
|
||||
print('Greeting: $greeting');
|
||||
|
||||
userReflector.invoke('birthday', []);
|
||||
print('After birthday: $user');
|
||||
|
||||
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 {
|
||||
userReflector.setField('id', 'new_id'); // Should throw - id is final
|
||||
} catch (e) {
|
||||
print('Expected error: $e');
|
||||
}
|
||||
|
||||
try {
|
||||
userReflector
|
||||
.invoke('unknownMethod', []); // Should throw - method doesn't exist
|
||||
} catch (e) {
|
||||
print('Expected error: $e');
|
||||
}
|
||||
|
||||
// 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';
|
||||
}
|
8
packages/reflection/lib/reflection.dart
Normal file
8
packages/reflection/lib/reflection.dart
Normal file
|
@ -0,0 +1,8 @@
|
|||
/// A lightweight cross-platform reflection system for Dart.
|
||||
library reflection;
|
||||
|
||||
export 'src/reflector.dart';
|
||||
export 'src/metadata.dart';
|
||||
export 'src/annotations.dart';
|
||||
export 'src/exceptions.dart';
|
||||
export 'src/types.dart';
|
216
packages/reflection/lib/src/annotations.dart
Normal file
216
packages/reflection/lib/src/annotations.dart
Normal file
|
@ -0,0 +1,216 @@
|
|||
import 'metadata.dart';
|
||||
|
||||
/// Registry of reflectable types and their metadata.
|
||||
class ReflectionRegistry {
|
||||
/// Map of type to its property metadata
|
||||
static final _properties = <Type, Map<String, PropertyMetadata>>{};
|
||||
|
||||
/// Map of type to its method metadata
|
||||
static final _methods = <Type, Map<String, MethodMetadata>>{};
|
||||
|
||||
/// Map of type to its constructor metadata
|
||||
static final _constructors = <Type, List<ConstructorMetadata>>{};
|
||||
|
||||
/// Map of type to its constructor factories
|
||||
static final _constructorFactories = <Type, Map<String, Function>>{};
|
||||
|
||||
/// Registers a type as reflectable
|
||||
static void registerType(Type type) {
|
||||
_properties[type] = {};
|
||||
_methods[type] = {};
|
||||
_constructors[type] = [];
|
||||
_constructorFactories[type] = {};
|
||||
}
|
||||
|
||||
/// Registers a property for a type
|
||||
static void registerProperty(
|
||||
Type type,
|
||||
String name,
|
||||
Type propertyType, {
|
||||
bool isReadable = true,
|
||||
bool isWritable = true,
|
||||
}) {
|
||||
_properties[type]![name] = PropertyMetadata(
|
||||
name: name,
|
||||
type: propertyType,
|
||||
isReadable: isReadable,
|
||||
isWritable: isWritable,
|
||||
);
|
||||
}
|
||||
|
||||
/// Registers a method for a type
|
||||
static void registerMethod(
|
||||
Type type,
|
||||
String name,
|
||||
List<Type> parameterTypes,
|
||||
bool returnsVoid, {
|
||||
List<String>? parameterNames,
|
||||
List<bool>? isRequired,
|
||||
List<bool>? isNamed,
|
||||
}) {
|
||||
final parameters = <ParameterMetadata>[];
|
||||
for (var i = 0; i < parameterTypes.length; i++) {
|
||||
parameters.add(ParameterMetadata(
|
||||
name: parameterNames?[i] ?? 'param$i',
|
||||
type: parameterTypes[i],
|
||||
isRequired: isRequired?[i] ?? true,
|
||||
isNamed: isNamed?[i] ?? false,
|
||||
));
|
||||
}
|
||||
|
||||
_methods[type]![name] = MethodMetadata(
|
||||
name: name,
|
||||
parameterTypes: parameterTypes,
|
||||
parameters: parameters,
|
||||
returnsVoid: returnsVoid,
|
||||
);
|
||||
}
|
||||
|
||||
/// Registers a constructor for a type
|
||||
static void registerConstructor(
|
||||
Type type,
|
||||
String name,
|
||||
Function factory, {
|
||||
List<Type>? parameterTypes,
|
||||
List<String>? parameterNames,
|
||||
List<bool>? isRequired,
|
||||
List<bool>? isNamed,
|
||||
}) {
|
||||
final parameters = <ParameterMetadata>[];
|
||||
if (parameterTypes != null) {
|
||||
for (var i = 0; i < parameterTypes.length; i++) {
|
||||
parameters.add(ParameterMetadata(
|
||||
name: parameterNames?[i] ?? 'param$i',
|
||||
type: parameterTypes[i],
|
||||
isRequired: isRequired?[i] ?? true,
|
||||
isNamed: isNamed?[i] ?? false,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
_constructors[type]!.add(ConstructorMetadata(
|
||||
name: name,
|
||||
parameterTypes: parameterTypes ?? [],
|
||||
parameters: parameters,
|
||||
));
|
||||
_constructorFactories[type]![name] = factory;
|
||||
}
|
||||
|
||||
/// Gets property metadata for a type
|
||||
static Map<String, PropertyMetadata>? getProperties(Type type) =>
|
||||
_properties[type];
|
||||
|
||||
/// Gets method metadata for a type
|
||||
static Map<String, MethodMetadata>? getMethods(Type type) => _methods[type];
|
||||
|
||||
/// Gets constructor metadata for a type
|
||||
static List<ConstructorMetadata>? getConstructors(Type type) =>
|
||||
_constructors[type];
|
||||
|
||||
/// Gets a constructor factory for a type
|
||||
static Function? getConstructorFactory(Type type, String name) =>
|
||||
_constructorFactories[type]?[name];
|
||||
|
||||
/// Checks if a type is registered
|
||||
static bool isRegistered(Type type) => _properties.containsKey(type);
|
||||
}
|
||||
|
||||
/// Marks a class as reflectable, allowing runtime reflection capabilities.
|
||||
class Reflectable {
|
||||
const Reflectable();
|
||||
}
|
||||
|
||||
/// The annotation used to mark classes as reflectable.
|
||||
const reflectable = Reflectable();
|
||||
|
||||
/// 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);
|
32
packages/reflection/lib/src/exceptions.dart
Normal file
32
packages/reflection/lib/src/exceptions.dart
Normal file
|
@ -0,0 +1,32 @@
|
|||
/// Base class for all reflection-related exceptions.
|
||||
class ReflectionException implements Exception {
|
||||
/// The error message.
|
||||
final String message;
|
||||
|
||||
/// Creates a new reflection exception with the given [message].
|
||||
const ReflectionException(this.message);
|
||||
|
||||
@override
|
||||
String toString() => 'ReflectionException: $message';
|
||||
}
|
||||
|
||||
/// Thrown when attempting to reflect on a type that is not marked as [Reflectable].
|
||||
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');
|
||||
}
|
||||
|
||||
/// 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.
|
||||
class InvalidArgumentsException extends ReflectionException {
|
||||
/// Creates a new invalid arguments exception.
|
||||
InvalidArgumentsException(String methodName, Type type)
|
||||
: super('Invalid arguments for method "$methodName" on type "$type"');
|
||||
}
|
258
packages/reflection/lib/src/metadata.dart
Normal file
258
packages/reflection/lib/src/metadata.dart
Normal file
|
@ -0,0 +1,258 @@
|
|||
import 'exceptions.dart';
|
||||
|
||||
/// Represents metadata about a parameter.
|
||||
class ParameterMetadata {
|
||||
/// The name of the parameter.
|
||||
final String name;
|
||||
|
||||
/// The type of the parameter.
|
||||
final Type type;
|
||||
|
||||
/// Whether this parameter is required.
|
||||
final bool isRequired;
|
||||
|
||||
/// Whether this parameter is named.
|
||||
final bool isNamed;
|
||||
|
||||
/// The default value for this parameter, if any.
|
||||
final Object? defaultValue;
|
||||
|
||||
/// Any attributes (annotations) on this parameter.
|
||||
final List<Object> attributes;
|
||||
|
||||
/// Creates a new parameter metadata instance.
|
||||
const ParameterMetadata({
|
||||
required this.name,
|
||||
required this.type,
|
||||
required this.isRequired,
|
||||
this.isNamed = false,
|
||||
this.defaultValue,
|
||||
this.attributes = const [],
|
||||
});
|
||||
}
|
||||
|
||||
/// Represents metadata about a type's property.
|
||||
class PropertyMetadata {
|
||||
/// The name of the property.
|
||||
final String name;
|
||||
|
||||
/// The type of the property.
|
||||
final Type type;
|
||||
|
||||
/// Whether the property can be read.
|
||||
final bool isReadable;
|
||||
|
||||
/// Whether the property can be written to.
|
||||
final bool isWritable;
|
||||
|
||||
/// Any attributes (annotations) on this property.
|
||||
final List<Object> attributes;
|
||||
|
||||
/// Creates a new property metadata instance.
|
||||
const PropertyMetadata({
|
||||
required this.name,
|
||||
required this.type,
|
||||
this.isReadable = true,
|
||||
this.isWritable = true,
|
||||
this.attributes = const [],
|
||||
});
|
||||
}
|
||||
|
||||
/// Represents metadata about a type's method.
|
||||
class MethodMetadata {
|
||||
/// The name of the method.
|
||||
final String name;
|
||||
|
||||
/// The parameter types of the method in order.
|
||||
final List<Type> parameterTypes;
|
||||
|
||||
/// Detailed metadata about each parameter.
|
||||
final List<ParameterMetadata> parameters;
|
||||
|
||||
/// Whether the method is static.
|
||||
final bool isStatic;
|
||||
|
||||
/// Whether the method returns void.
|
||||
final bool returnsVoid;
|
||||
|
||||
/// Any attributes (annotations) on this method.
|
||||
final List<Object> attributes;
|
||||
|
||||
/// Creates a new method metadata instance.
|
||||
const MethodMetadata({
|
||||
required this.name,
|
||||
required this.parameterTypes,
|
||||
required this.parameters,
|
||||
required this.returnsVoid,
|
||||
this.isStatic = false,
|
||||
this.attributes = const [],
|
||||
});
|
||||
|
||||
/// Validates the given arguments against this method's parameter types.
|
||||
bool validateArguments(List<Object?> arguments) {
|
||||
if (arguments.length != parameterTypes.length) return false;
|
||||
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
final arg = arguments[i];
|
||||
if (arg != null && arg.runtimeType != parameterTypes[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents metadata about a type's constructor.
|
||||
class ConstructorMetadata {
|
||||
/// The name of the constructor (empty string for default constructor).
|
||||
final String name;
|
||||
|
||||
/// The parameter types of the constructor in order.
|
||||
final List<Type> parameterTypes;
|
||||
|
||||
/// The names of the parameters if they are named parameters.
|
||||
final List<String>? parameterNames;
|
||||
|
||||
/// Detailed metadata about each parameter.
|
||||
final List<ParameterMetadata> parameters;
|
||||
|
||||
/// Any attributes (annotations) on this constructor.
|
||||
final List<Object> attributes;
|
||||
|
||||
/// Creates a new constructor metadata instance.
|
||||
const ConstructorMetadata({
|
||||
this.name = '',
|
||||
required this.parameterTypes,
|
||||
required this.parameters,
|
||||
this.parameterNames,
|
||||
this.attributes = const [],
|
||||
});
|
||||
|
||||
/// Whether this constructor uses named parameters.
|
||||
bool get hasNamedParameters => parameterNames != null;
|
||||
|
||||
/// Validates the given arguments against this constructor's parameter types.
|
||||
bool validateArguments(List<Object?> arguments) {
|
||||
if (arguments.length != parameterTypes.length) return false;
|
||||
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
final arg = arguments[i];
|
||||
if (arg != null && arg.runtimeType != parameterTypes[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents metadata about a type.
|
||||
class TypeMetadata {
|
||||
/// The actual type this metadata represents.
|
||||
final Type type;
|
||||
|
||||
/// The name of the type.
|
||||
final String name;
|
||||
|
||||
/// The properties defined on this type.
|
||||
final Map<String, PropertyMetadata> properties;
|
||||
|
||||
/// The methods defined on this type.
|
||||
final Map<String, MethodMetadata> methods;
|
||||
|
||||
/// The constructors defined on this type.
|
||||
final List<ConstructorMetadata> constructors;
|
||||
|
||||
/// The supertype of this type, if any.
|
||||
final TypeMetadata? supertype;
|
||||
|
||||
/// The interfaces this type implements.
|
||||
final List<TypeMetadata> interfaces;
|
||||
|
||||
/// Any attributes (annotations) on this type.
|
||||
final List<Object> attributes;
|
||||
|
||||
/// Creates a new type metadata instance.
|
||||
const TypeMetadata({
|
||||
required this.type,
|
||||
required this.name,
|
||||
required this.properties,
|
||||
required this.methods,
|
||||
required this.constructors,
|
||||
this.supertype,
|
||||
this.interfaces = const [],
|
||||
this.attributes = const [],
|
||||
});
|
||||
|
||||
/// Gets a property by name, throwing if not found.
|
||||
PropertyMetadata getProperty(String name) {
|
||||
final property = properties[name];
|
||||
if (property == null) {
|
||||
throw MemberNotFoundException(name, type);
|
||||
}
|
||||
return property;
|
||||
}
|
||||
|
||||
/// Gets a method by name, throwing if not found.
|
||||
MethodMetadata getMethod(String name) {
|
||||
final method = methods[name];
|
||||
if (method == null) {
|
||||
throw MemberNotFoundException(name, type);
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
/// Gets the default constructor, throwing if not found.
|
||||
ConstructorMetadata get defaultConstructor {
|
||||
return constructors.firstWhere(
|
||||
(c) => c.name.isEmpty,
|
||||
orElse: () => throw ReflectionException(
|
||||
'No default constructor found for type "$name"',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Gets a named constructor, throwing if not found.
|
||||
ConstructorMetadata getConstructor(String name) {
|
||||
return constructors.firstWhere(
|
||||
(c) => c.name == name,
|
||||
orElse: () => throw ReflectionException(
|
||||
'Constructor "$name" not found for type "$type"',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents metadata about a function.
|
||||
class FunctionMetadata {
|
||||
/// The parameters of the function.
|
||||
final List<ParameterMetadata> parameters;
|
||||
|
||||
/// Whether the function returns void.
|
||||
final bool returnsVoid;
|
||||
|
||||
/// The return type of the function.
|
||||
final Type returnType;
|
||||
|
||||
/// Creates a new function metadata instance.
|
||||
const FunctionMetadata({
|
||||
required this.parameters,
|
||||
required this.returnsVoid,
|
||||
required this.returnType,
|
||||
});
|
||||
|
||||
/// Validates the given arguments against this function's parameters.
|
||||
bool validateArguments(List<Object?> arguments) {
|
||||
if (arguments.length != parameters.length) return false;
|
||||
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
final arg = arguments[i];
|
||||
if (arg != null && arg.runtimeType != parameters[i].type) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
258
packages/reflection/lib/src/reflector.dart
Normal file
258
packages/reflection/lib/src/reflector.dart
Normal file
|
@ -0,0 +1,258 @@
|
|||
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;
|
||||
}
|
19
packages/reflection/lib/src/types.dart
Normal file
19
packages/reflection/lib/src/types.dart
Normal file
|
@ -0,0 +1,19 @@
|
|||
/// Represents the void type in our reflection system.
|
||||
class VoidType implements Type {
|
||||
const VoidType._();
|
||||
|
||||
/// The singleton instance representing void.
|
||||
static const instance = VoidType._();
|
||||
|
||||
@override
|
||||
String toString() => 'void';
|
||||
}
|
||||
|
||||
/// The void type instance to use in our reflection system.
|
||||
const voidType = VoidType.instance;
|
||||
|
||||
/// Extension to check if a Type is void.
|
||||
extension TypeExtensions on Type {
|
||||
/// Whether this type represents void.
|
||||
bool get isVoid => this == voidType;
|
||||
}
|
402
packages/reflection/pubspec.lock
Normal file
402
packages/reflection/pubspec.lock
Normal file
|
@ -0,0 +1,402 @@
|
|||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
_fe_analyzer_shared:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: _fe_analyzer_shared
|
||||
sha256: "45cfa8471b89fb6643fe9bf51bd7931a76b8f5ec2d65de4fb176dba8d4f22c77"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "73.0.0"
|
||||
_macros:
|
||||
dependency: transitive
|
||||
description: dart
|
||||
source: sdk
|
||||
version: "0.3.2"
|
||||
analyzer:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: analyzer
|
||||
sha256: "4959fec185fe70cce007c57e9ab6983101dbe593d2bf8bbfb4453aaec0cf470a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.8.0"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.6.0"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.12.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.19.1"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: convert
|
||||
sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
coverage:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: coverage
|
||||
sha256: "4b03e11f6d5b8f6e5bb5e9f7889a56fe6c5cbe942da5378ea4d4d7f73ef9dfe5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.6"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.1"
|
||||
frontend_server_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: frontend_server_client
|
||||
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: glob
|
||||
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_multi_server
|
||||
sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.1"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_parser
|
||||
sha256: "76d306a1c3afb33fe82e2bbacad62a61f409b5634c915fceb0d799de1a913360"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.1"
|
||||
io:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: io
|
||||
sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.1"
|
||||
lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: lints
|
||||
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: logging
|
||||
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
macros:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: macros
|
||||
sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.2-main.4"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.16+1"
|
||||
meta:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: meta
|
||||
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.16.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: mime
|
||||
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
node_preamble:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: node_preamble
|
||||
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
package_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_config
|
||||
sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
pool:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pool
|
||||
sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.1"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pub_semver
|
||||
sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf
|
||||
sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.2"
|
||||
shelf_packages_handler:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_packages_handler
|
||||
sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
shelf_static:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_static
|
||||
sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.3"
|
||||
shelf_web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_web_socket
|
||||
sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
source_map_stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_map_stack_trace
|
||||
sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
source_maps:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_maps
|
||||
sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.10.12"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.12.0"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
sha256: "0bd04f5bb74fcd6ff0606a888a30e917af9bd52820b178eaa464beb11dca84b6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
test:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: test
|
||||
sha256: "713a8789d62f3233c46b4a90b174737b2c04cb6ae4500f2aa8b1be8f03f5e67f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.25.8"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.3"
|
||||
test_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_core
|
||||
sha256: "12391302411737c176b0b5d6491f466b0dd56d4763e347b6714efbaa74d7953d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.5"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "14.3.1"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: watcher
|
||||
sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket
|
||||
sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.6"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
webkit_inspection_protocol:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webkit_inspection_protocol
|
||||
sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: yaml
|
||||
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
sdks:
|
||||
dart: ">=3.5.0 <4.0.0"
|
12
packages/reflection/pubspec.yaml
Normal file
12
packages/reflection/pubspec.yaml
Normal file
|
@ -0,0 +1,12 @@
|
|||
name: platform_reflection
|
||||
description: A lightweight cross-platform reflection system for Dart
|
||||
version: 0.1.0
|
||||
environment:
|
||||
sdk: '>=3.0.0 <4.0.0'
|
||||
|
||||
dependencies:
|
||||
meta: ^1.9.0
|
||||
|
||||
dev_dependencies:
|
||||
lints: ^2.1.0
|
||||
test: ^1.24.0
|
236
packages/reflection/test/reflection_test.dart
Normal file
236
packages/reflection/test/reflection_test.dart
Normal file
|
@ -0,0 +1,236 @@
|
|||
import 'package:platform_reflection/reflection.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
@reflectable
|
||||
class Person with Reflector {
|
||||
String name;
|
||||
int age;
|
||||
final String id;
|
||||
|
||||
Person(this.name, this.age, {required this.id});
|
||||
|
||||
// Guest constructor
|
||||
Person.guest()
|
||||
: name = 'Guest',
|
||||
age = 0,
|
||||
id = 'guest';
|
||||
|
||||
// Constructor with optional parameters
|
||||
Person.withDefaults(this.name, [this.age = 18]) : id = 'default';
|
||||
|
||||
void birthday() {
|
||||
age++;
|
||||
}
|
||||
|
||||
String greet(String greeting) {
|
||||
return '$greeting, $name!';
|
||||
}
|
||||
|
||||
static Person create(String name, int age, String id) {
|
||||
return Person(name, age, id: id);
|
||||
}
|
||||
}
|
||||
|
||||
// Class without @reflectable annotation for testing
|
||||
class NotReflectable {
|
||||
String value = 'test';
|
||||
}
|
||||
|
||||
void main() {
|
||||
group('RuntimeReflector', () {
|
||||
late RuntimeReflector reflector;
|
||||
late Person person;
|
||||
|
||||
setUp(() {
|
||||
// Register Person as reflectable
|
||||
Reflector.register(Person);
|
||||
|
||||
// Register properties
|
||||
Reflector.registerProperty(Person, 'name', String);
|
||||
Reflector.registerProperty(Person, 'age', int);
|
||||
Reflector.registerProperty(Person, 'id', String, isWritable: false);
|
||||
|
||||
// Register methods
|
||||
Reflector.registerMethod(
|
||||
Person,
|
||||
'birthday',
|
||||
[],
|
||||
true,
|
||||
);
|
||||
Reflector.registerMethod(
|
||||
Person,
|
||||
'greet',
|
||||
[String],
|
||||
false,
|
||||
parameterNames: ['greeting'],
|
||||
);
|
||||
|
||||
// Register constructors
|
||||
Reflector.registerConstructor(
|
||||
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(
|
||||
Person,
|
||||
'guest',
|
||||
() => Person.guest(),
|
||||
);
|
||||
|
||||
Reflector.registerConstructor(
|
||||
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;
|
||||
person = Person('John', 30, id: '123');
|
||||
});
|
||||
|
||||
group('Type Reflection', () {
|
||||
test('reflectType returns correct type metadata', () {
|
||||
final metadata = 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,
|
||||
equals(3)); // default, guest, withDefaults
|
||||
});
|
||||
|
||||
test('reflect creates instance reflector', () {
|
||||
final instanceReflector = reflector.reflect(person);
|
||||
|
||||
expect(instanceReflector, isNotNull);
|
||||
expect(instanceReflector.type.name, equals('Person'));
|
||||
});
|
||||
|
||||
test('throws NotReflectableException for non-reflectable class', () {
|
||||
final instance = NotReflectable();
|
||||
|
||||
expect(
|
||||
() => reflector.reflect(instance),
|
||||
throwsA(isA<NotReflectableException>()),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('Property Access', () {
|
||||
test('getField returns property value', () {
|
||||
final instanceReflector = reflector.reflect(person);
|
||||
|
||||
expect(instanceReflector.getField('name'), equals('John'));
|
||||
expect(instanceReflector.getField('age'), equals(30));
|
||||
expect(instanceReflector.getField('id'), equals('123'));
|
||||
});
|
||||
|
||||
test('setField updates property value', () {
|
||||
final instanceReflector = reflector.reflect(person);
|
||||
|
||||
instanceReflector.setField('name', 'Jane');
|
||||
instanceReflector.setField('age', 25);
|
||||
|
||||
expect(person.name, equals('Jane'));
|
||||
expect(person.age, equals(25));
|
||||
});
|
||||
|
||||
test('setField throws on final field', () {
|
||||
final instanceReflector = reflector.reflect(person);
|
||||
|
||||
expect(
|
||||
() => instanceReflector.setField('id', '456'),
|
||||
throwsA(isA<ReflectionException>()),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('Method Invocation', () {
|
||||
test('invoke calls method with arguments', () {
|
||||
final instanceReflector = reflector.reflect(person);
|
||||
|
||||
final result = instanceReflector.invoke('greet', ['Hello']);
|
||||
expect(result, equals('Hello, John!'));
|
||||
|
||||
instanceReflector.invoke('birthday', []);
|
||||
expect(person.age, equals(31));
|
||||
});
|
||||
|
||||
test('invoke throws on invalid arguments', () {
|
||||
final instanceReflector = reflector.reflect(person);
|
||||
|
||||
expect(
|
||||
() => instanceReflector.invoke('greet', [42]),
|
||||
throwsA(isA<InvalidArgumentsException>()),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('Constructor Invocation', () {
|
||||
test('creates instance with default constructor', () {
|
||||
final instance = reflector.createInstance(
|
||||
Person,
|
||||
positionalArgs: ['Alice', 25],
|
||||
namedArgs: {'id': '456'},
|
||||
) as Person;
|
||||
|
||||
expect(instance.name, equals('Alice'));
|
||||
expect(instance.age, equals(25));
|
||||
expect(instance.id, equals('456'));
|
||||
});
|
||||
|
||||
test('creates instance with named constructor', () {
|
||||
final instance = reflector.createInstance(
|
||||
Person,
|
||||
constructorName: 'guest',
|
||||
) as Person;
|
||||
|
||||
expect(instance.name, equals('Guest'));
|
||||
expect(instance.age, equals(0));
|
||||
expect(instance.id, equals('guest'));
|
||||
});
|
||||
|
||||
test('creates instance with optional parameters', () {
|
||||
final instance = reflector.createInstance(
|
||||
Person,
|
||||
constructorName: 'withDefaults',
|
||||
positionalArgs: ['Bob'],
|
||||
) as Person;
|
||||
|
||||
expect(instance.name, equals('Bob'));
|
||||
expect(instance.age, equals(18)); // Default value
|
||||
expect(instance.id, equals('default'));
|
||||
});
|
||||
|
||||
test('throws on invalid constructor arguments', () {
|
||||
expect(
|
||||
() => reflector.createInstance(
|
||||
Person,
|
||||
positionalArgs: ['Alice'], // Missing required age
|
||||
namedArgs: {'id': '456'},
|
||||
),
|
||||
throwsA(isA<InvalidArgumentsException>()),
|
||||
);
|
||||
});
|
||||
|
||||
test('throws on non-existent constructor', () {
|
||||
expect(
|
||||
() => reflector.createInstance(
|
||||
Person,
|
||||
constructorName: 'nonexistent',
|
||||
),
|
||||
throwsA(isA<ReflectionException>()),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Reference in a new issue