commit e5f84e6d15da8245756276a41797db2600523300 Author: Aric Camarata Date: Fri May 29 15:02:45 2026 -0400 initial release: shared Dart and Flutter lint rules for acamarata packages diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..52cf9ed --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,65 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + test: + name: Test (Dart ${{ matrix.dart-version }}) + runs-on: ubuntu-latest + strategy: + matrix: + dart-version: [stable] + steps: + - uses: actions/checkout@v4 + + - name: Setup Dart ${{ matrix.dart-version }} + uses: dart-lang/setup-dart@v1 + with: + sdk: ${{ matrix.dart-version }} + + - name: Install dependencies + run: dart pub get + + - name: Analyze + run: dart analyze + + - name: Test + run: dart test + + format: + name: Format + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Dart stable + uses: dart-lang/setup-dart@v1 + with: + sdk: stable + + - name: Install dependencies + run: dart pub get + + - name: Check formatting + run: dart format --set-exit-if-changed . + + publish-check: + name: Publish Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Dart stable + uses: dart-lang/setup-dart@v1 + with: + sdk: stable + + - name: Install dependencies + run: dart pub get + + - name: Dry-run publish + run: dart pub publish --dry-run diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9e9586e --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +# Dart build artifacts +.dart_tool/ +build/ +.packages +pubspec.lock +doc/api/ + +# IDE files +*.iml +.idea/ +.vscode/* + +# OS files +.DS_Store + +# AI agent directories (not source code) +.claude/ +.env +.env.* +.codex/ +.cursor/ +.aider/ +.aider.chat.history.md +.continue/ +.windsurf/ +.gemini/ +.codeium/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..4c0c84b --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,32 @@ +# Changelog + +All notable changes to this project are documented here. +Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). +This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [1.0.0] - 2026-05-28 + +### Added + +- Initial release: `analysis_options.yaml` extending `flutter_lints/flutter.yaml` +- Strict acamarata rule overrides: + - `prefer_single_quotes` — consistent string quoting + - `always_declare_return_types` — explicit return types on all functions + - `avoid_print` — no print() in library code + - `require_trailing_commas` — cleaner diffs and merge conflict reduction + - `prefer_const_constructors` + const variants — reduces Flutter rebuilds + - `avoid_dynamic_calls` — no dynamic type invocations + - `public_member_api_docs` — all public APIs documented + - `use_super_parameters` — Dart 2.17+ initializer syntax + - `avoid_positional_boolean_parameters` — boolean parameters must be named + - `sort_constructors_first` — consistent class member ordering + - `curly_braces_in_flow_control_structures` — always use braces +- Analyzer strict mode: `strict-casts`, `strict-inference`, `strict-raw-types` +- `example/analysis_options.yaml` showing the consumer include pattern +- `lib/acamarata_lints.dart` placeholder (lint packages export nothing) +- MIT license, README with install/usage/rule rationale table + +[Unreleased]: https://github.com/acamarata/acamarata_lints/compare/v1.0.0...HEAD +[1.0.0]: https://github.com/acamarata/acamarata_lints/releases/tag/v1.0.0 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f8c021c --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Aric Camarata + +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..23e5fea --- /dev/null +++ b/README.md @@ -0,0 +1,84 @@ +# acamarata_lints + +Shared Dart and Flutter lint rules for [acamarata](https://github.com/acamarata) packages. + +Extends [`flutter_lints`](https://pub.dev/packages/flutter_lints) with additional strict rules used across all acamarata Dart and Flutter packages. One include, consistent style everywhere. + +## Install + +Add to your `pubspec.yaml`: + +```yaml +dev_dependencies: + acamarata_lints: ^1.0.0 +``` + +Run: + +```sh +dart pub get +``` + +## Usage + +In your `analysis_options.yaml`: + +```yaml +include: package:acamarata_lints/analysis_options.yaml +``` + +That is the entire setup. The package resolves the flutter_lints transitive include automatically. + +To add project-specific overrides beneath the include: + +```yaml +include: package:acamarata_lints/analysis_options.yaml + +analyzer: + exclude: + - "**/*.g.dart" + - "**/*.freezed.dart" + +linter: + rules: + public_member_api_docs: false # disable for app code if preferred +``` + +See `example/analysis_options.yaml` for a full annotated example. + +## Rule Rationale + +| Rule | Rationale | +|---|---| +| `prefer_single_quotes` | Consistent string quoting across all files. Matches JS convention. | +| `always_declare_return_types` | Inference alone does not communicate intent on public APIs. | +| `avoid_print` | `print()` leaks into production logs. Use a real logger. | +| `require_trailing_commas` | Trailing commas produce cleaner diffs and reduce merge conflicts. | +| `prefer_const_constructors` | Const constructors reduce Flutter widget rebuilds. | +| `avoid_dynamic_calls` | Dynamic calls bypass the type system and cause runtime errors. | +| `public_member_api_docs` | All public APIs must be documented — these are library packages. | +| `use_super_parameters` | Dart 2.17+ super-initializer syntax reduces boilerplate. | +| `avoid_positional_boolean_parameters` | Boolean positional parameters are unreadable at call sites. | +| `sort_constructors_first` | Consistent class structure across all files. | +| `curly_braces_in_flow_control_structures` | Braces prevent off-by-one bugs when adding statements to control flow. | + +## Strict analyzer modes + +This package enables three strict analyzer modes: + +- `strict-casts` — no implicit casts between types +- `strict-inference` — type inference failures are reported +- `strict-raw-types` — raw generic types (List without a type argument) are flagged + +## Requirements + +- Dart SDK: `>=3.0.0 <4.0.0` +- Depends on: [`flutter_lints`](https://pub.dev/packages/flutter_lints) `>=3.0.0 <6.0.0` + +## Changelog + +See [CHANGELOG.md](CHANGELOG.md). + +## License + +MIT. See [LICENSE](LICENSE). diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..32c9c78 --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,78 @@ +include: package:flutter_lints/flutter.yaml + +analyzer: + exclude: + # The example directory includes package:acamarata_lints/analysis_options.yaml + # which cannot be resolved from within the package itself. Consumers will + # resolve it from their own pub cache after installing the package. + - "example/**" + language: + strict-casts: true + strict-inference: true + strict-raw-types: true + errors: + # Treat these as errors, not warnings + missing_return: error + dead_code: warning + unused_import: warning + +linter: + rules: + # Prefer single quotes for strings — keeps code consistent and matches JS conventions. + prefer_single_quotes: true + + # Every function must declare its return type explicitly. + # Inference alone is not sufficient for public APIs. + always_declare_return_types: true + + # Avoid print() in library code. Use a proper logging mechanism instead. + avoid_print: true + + # Always use trailing commas in argument lists, parameter lists, etc. + # This makes diffs cleaner and reduces merge conflicts. + require_trailing_commas: true + + # Prefer const constructors wherever possible — reduces rebuilds in Flutter. + prefer_const_constructors: true + prefer_const_constructors_in_immutables: true + prefer_const_declarations: true + prefer_const_literals_to_create_immutables: true + + # Avoid unnecessary type annotations where they can be inferred, + # but keep them where they communicate intent on public APIs. + avoid_redundant_argument_values: true + + # Prefer using is! for type checks rather than negated is. + prefer_is_not_operator: true + + # Avoid empty catch blocks — either handle the error or rethrow. + avoid_empty_else: true + empty_catches: true + + # Prefer final for variables that are never reassigned. + prefer_final_fields: true + prefer_final_locals: true + + # Avoid dynamic types — use proper types or generics. + avoid_dynamic_calls: true + + # Sort constructors before other members. + sort_constructors_first: true + + # Use named parameters for booleans — improves call-site readability. + avoid_positional_boolean_parameters: true + + # Document all public APIs. + public_member_api_docs: true + + # Use super-initializer parameters where possible (Dart 2.17+). + use_super_parameters: true + + # Always use curly braces for control flow, even for single statements. + curly_braces_in_flow_control_structures: true + + # Avoid returning null for void-typed return types. + avoid_returning_null_for_void: true + + # Use raw string literals only when they add clarity. + use_raw_strings: false diff --git a/example/analysis_options.yaml b/example/analysis_options.yaml new file mode 100644 index 0000000..e39b448 --- /dev/null +++ b/example/analysis_options.yaml @@ -0,0 +1,20 @@ +# Example: how consumers use acamarata_lints. +# +# In your pubspec.yaml, add: +# +# dev_dependencies: +# acamarata_lints: ^1.0.0 +# +# Then create or update your analysis_options.yaml with this single include: + +include: package:acamarata_lints/analysis_options.yaml + +# You can add project-specific overrides below: +# analyzer: +# exclude: +# - "**/*.g.dart" # Generated files +# - "**/*.freezed.dart" +# +# linter: +# rules: +# public_member_api_docs: false # Optional: disable for app code diff --git a/lib/acamarata_lints.dart b/lib/acamarata_lints.dart new file mode 100644 index 0000000..1a3f104 --- /dev/null +++ b/lib/acamarata_lints.dart @@ -0,0 +1,12 @@ +/// Shared Dart and Flutter lint rules for acamarata packages. +/// +/// This library exports nothing. Lint rules are applied by including +/// the analysis_options.yaml file in your project: +/// +/// ```yaml +/// # In your analysis_options.yaml: +/// include: package:acamarata_lints/analysis_options.yaml +/// ``` +/// +/// See the package README for the full rule list and rationale. +library; diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..76c484f --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,24 @@ +name: acamarata_lints +description: > + Shared Dart and Flutter lint rules for acamarata packages. + Extends flutter_lints with strict acamarata-specific overrides + for consistent code style across all packages. +version: 1.0.0 +homepage: https://github.com/acamarata/acamarata_lints +repository: https://github.com/acamarata/acamarata_lints + +topics: + - lints + - analysis + - flutter + - dart + - style + +environment: + sdk: ">=3.0.0 <4.0.0" + +dependencies: + flutter_lints: ">=3.0.0 <6.0.0" + +dev_dependencies: + test: ^1.25.0 diff --git a/test/acamarata_lints_test.dart b/test/acamarata_lints_test.dart new file mode 100644 index 0000000..0129d4b --- /dev/null +++ b/test/acamarata_lints_test.dart @@ -0,0 +1,11 @@ +// ignore_for_file: avoid_print +import 'package:test/test.dart'; + +void main() { + test('acamarata_lints package is importable', () { + // This package exports no Dart symbols. + // Lint rules are applied via analysis_options.yaml. + // This test exists to satisfy `dart test` in CI. + expect(true, isTrue); + }); +}