Thank you for your interest in contributing! This document provides guidelines and instructions for contributing to this project.
- Code of Conduct
- Getting Started
- Development Setup
- Coding Standards
- Testing Requirements
- Pull Request Process
- Commit Convention
- Architecture Guidelines
- Documentation
- Reporting Issues
This project follows the Contributor Covenant code of conduct. By participating, you are expected to uphold this code. Please report unacceptable behaviour to the maintainers.
- Fork the repository on GitHub.
- Clone your fork locally.
- Run
dart pub getto install dependencies. - Run
dart testto verify all tests pass. - Create a feature branch for your change.
Requirements:
- Dart SDK
>=3.3.0 - No Flutter needed — pure Dart package
# Get dependencies
dart pub get
# Run tests
dart test
# Run analysis
dart analyze
# Format code
dart format .
# Score the package locally
dart pub global activate pana
pana .- Follow the Effective Dart style guide.
- Use
dart format— all PRs are format-checked. dart analyzemust report zero issues — theanalysis_options.yamluses thelintspackage with additional rules.- All public API members must have dartdoc comments.
- Prefer
finaloverlatewhere possible. - Use explicit types on public APIs.
- All tests must pass (
dart test). - New features must include tests covering:
- Happy path (feature works as expected)
- Error path (appropriate exceptions thrown)
- Edge cases (empty inputs, boundary conditions)
- Maintain or improve code coverage — aim for ≥ 95%.
- Ensure
dart format .anddart analyze .both pass with zero issues. - Run the full test suite:
dart test. - Update
CHANGELOG.mdunder the[Unreleased]section. - Reference the related issue in your PR description.
- Await code review — at least one approval is required before merging.
Use Conventional Commits:
| Prefix | Use for |
|---|---|
feat: |
New feature |
fix: |
Bug fix |
docs: |
Documentation changes only |
test: |
Adding/updating tests |
refactor: |
Refactoring without feature/fix |
perf: |
Performance improvement |
chore: |
Build, tooling, dependency updates |
BREAKING CHANGE: |
Breaking API change (add to body) |
Examples:
feat: add tryGetAsync<T> to ServiceProviderBase
fix: propagate ResolutionChain through transitive dependencies
docs: add getAll multi-registration example to README
The package uses a two-phase architecture:
Build phase (ServiceCollection.buildServiceProvider()):
CallSiteResolverconvertsServiceDescriptorobjects into an immutableMap<Type, CallSite>tree.DependencyGraphdetects circular dependencies.CallSiteValidatordetects scope violations (captive dependencies).RootServiceProviderstores the compiled maps,SingletonCache, andDisposalTracker.
Resolve phase (calls to getRequired<T>() etc.):
CallSiteExecutorwalks theCallSitetree.ResolutionChain(O(1)Set-backed) detects runtime cycles.- Results are cached per their lifetime (
SingletonCache/ScopedCache).
Key contracts:
ServiceDescriptoris immutable once created.ServiceCollectionis single-use — build once, then frozen.- All constructor injection is AOT-safe via
ReflectionHelper.
- Every public API element needs a dartdoc comment.
- Code examples in dartdoc should use triple-backtick Dart blocks.
- Update
README.mdfor new end-user features. - Update
CHANGELOG.mdfor every user-visible change.
Please open a GitHub issue and include:
- Dart SDK version (
dart --version). - Minimal reproducible example.
- Expected vs actual behaviour.
- Full stack trace if an exception was thrown.