Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1 +1 @@
* @netsells/flutter
* @hedgehoglab-engineering/flutter-team
69 changes: 44 additions & 25 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,38 +1,57 @@
name: ci

on: pull_request
on:
pull_request:
push:
branches: [main]

permissions:
contents: read

defaults:
run:
shell: bash

jobs:
build:
analyse:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.3.4
- uses: dart-lang/setup-dart@v1
- uses: actions/checkout@v7
- uses: subosito/flutter-action@v2
with:
channel: stable
cache: true

- name: Install Dependencies
run: dart pub get
- name: Show SDK versions
run: flutter --version

- name: Format
run: dart format --set-exit-if-changed .

- name: Analyze
run: dart analyze .
- name: Install dependencies
run: |
dart pub get
dart pub get --directory example

pana:
runs-on: ubuntu-latest
- name: Format
run: dart format --output=none --set-exit-if-changed .

steps:
- uses: actions/checkout@v2.3.4
- uses: subosito/flutter-action@v1.5.0
- name: Analyse package
run: dart analyze --fatal-infos . 2>&1 | tee analyze-root.log

- name: Install Dependencies
run: |
flutter packages get
flutter pub global activate pana
- name: Analyse example
run: dart analyze --fatal-infos example 2>&1 | tee analyze-example.log

- name: Verify Pub Score
# The analyser already fails on unknown lints (undefined_lint), but
# removed and deprecated rules are not always reported, so the check
# below also reads the logs for the three diagnostics and guards the
# latest versioned file against rules known to be removed in Dart 3.
- name: Fail on undefined, removed or deprecated lints
run: |
PANA=$(pana . --no-warning); PANA_SCORE=$(echo $PANA | sed -n "s/.*Points: \([0-9]*\)\/\([0-9]*\)./\1\/\2/p")
echo "score: $PANA_SCORE"
IFS='/'; read -a SCORE_ARR <<< "$PANA_SCORE"; SCORE=SCORE_ARR[0]; TOTAL=SCORE_ARR[1]
if (( $SCORE < $TOTAL )); then echo "minimum score not met!"; exit 1; fi
if grep -E 'undefined_lint|removed_lint|deprecated_lint|included_file_warning' analyze-root.log analyze-example.log; then
echo "Lint configuration references unknown, removed or deprecated rules." >&2
exit 1
fi
latest=$(ls lib/analysis_options.*.*.*.yaml | sort -V | tail -n 1)
removed='always_require_non_null_named_parameters|avoid_null_checks_in_equality_operators|avoid_private_typedef_functions|avoid_returning_null|avoid_returning_null_for_future|iterable_contains_unrelated_type|list_remove_unrelated_type|package_api_docs|prefer_equal_for_default_values|unnecessary_await_in_return'
if grep -nE "^ - ($removed)\$" "$latest"; then
echo "$latest lists rules removed or deprecated in Dart 3." >&2
exit 1
fi
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.dart_tool
.packages
pubspec.lock
.DS_Store
.DS_Store
*.log
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
# 6.0.0

- Rename the package from `netsells_flutter_analysis` to `hedgehoglab_flutter_analysis` and move maintenance to hedgehog lab. The library file is now `hedgehoglab_flutter_analysis.dart`.
- Add `lib/analysis_options.6.0.0.yaml` and point `lib/analysis_options.yaml` at it. Earlier versioned files are unchanged.
- Remove rules that no longer exist, or are deprecated, in Dart 3:
- Removed: `always_require_non_null_named_parameters`, `avoid_returning_null`, `avoid_returning_null_for_future`, `iterable_contains_unrelated_type`, `list_remove_unrelated_type`, `package_api_docs`, `prefer_equal_for_default_values`
- Deprecated: `avoid_null_checks_in_equality_operators`, `avoid_private_typedef_functions`, `unnecessary_await_in_return`
- Add `flutter_style_todos`.
- Enable `strict-casts`, `strict-inference` and `strict-raw-types`. BREAKING for projects that adopt 6.0.0: expect new analyser errors until implicit casts, inferred `dynamic` and raw generic types are fixed.
- Exclude generated code (`*.g.dart`, `*.freezed.dart`, `*.gr.dart`, `*.mocks.dart`) and the `android`, `ios`, `web`, `windows`, `macos` and `linux` directories.
- Replace the broad `lib/**.*.dart` and `test/**.*.dart` excludes from 5.0.0, which also hid hand-written files with a dotted name.
- Keep `lines_longer_than_80_chars`, matching the default `dart format` page width.
- Require Dart 3.13 or later (verified against Flutter 3.47).
- Modernise CI and drop the pana job.

# 5.0.0

- Upgrade to Flutter 3.10 and Dart 3
Expand Down
1 change: 1 addition & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
MIT License

Copyright (c) 2021 Netsells
Copyright (c) 2026 hedgehog lab

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
87 changes: 65 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,53 +1,96 @@
# Netsells Flutter Analysis
# hedgehog lab Flutter Analysis

This package provides lint rules for Dart and Flutter which are used at [Netsells](https://netsells.co.uk).
The standard Dart and Flutter analyser configuration used at hedgehog lab. A project adopts it with one `include:` line, and gets the same lint rules, strict language modes and generated-code excludes as every other hedgehog lab project.

**Note**: This package was heavily inspired by [very_good_analysis](https://pub.dev/packages/very_good_analysis).
This package is a maintained fork of [netsells/flutter-analysis](https://github.com/netsells/flutter-analysis), which was itself inspired by [very_good_analysis](https://pub.dev/packages/very_good_analysis). See [Attribution](#attribution).

## Usage
## Adopting it

To use the lints, add a dependency in your `pubspec.yaml`:
Add the package as a git dependency, pinned to a tag, in `pubspec.yaml`:

```yaml
dev_dependencies:
netsells_flutter_analysis: ^5.0.0
hedgehoglab_flutter_analysis:
git:
url: https://github.com/hedgehoglab-engineering/flutter-analysis.git
ref: 6.0.0
```

Then, add an include in `analysis_options.yaml`:
Then include the versioned file in `analysis_options.yaml`:

```yaml
include: package:netsells_flutter_analysis/analysis_options.yaml
include: package:hedgehoglab_flutter_analysis/analysis_options.6.0.0.yaml
```

This will ensure you always use the latest version of the lints. If you wish to restrict the lint version, specify a version of `analysis_options.yaml` instead:
Run `flutter pub get`, then `flutter analyze`. Expect new findings on the first run: 6.0.0 turns on `strict-casts`, `strict-inference` and `strict-raw-types`.

```yaml
include: package:netsells_flutter_analysis/analysis_options.4.0.0.yaml
```
Requires Dart 3.13 or later. The package is not published to pub.dev.

## What 6.0.0 contains

- The rule set from 5.0.0, minus rules that no longer exist or are deprecated in Dart 3, plus `flutter_style_todos`. See the [CHANGELOG](CHANGELOG.md) for the exact list.
- `strict-casts`, `strict-inference` and `strict-raw-types`.
- Excludes for generated code (`*.g.dart`, `*.freezed.dart`, `*.gr.dart`, `*.mocks.dart`) and the platform directories.
- Severity overrides inherited from Netsells (`missing_return` and `missing_required_param` as errors, `close_sinks` and `invalid_annotation_target` ignored).
- `lines_longer_than_80_chars` stays on. It matches the default `dart format` page width, and it catches what the formatter cannot wrap (long strings and comments). A project that sets a different `page_width` should override the rule in its own `analysis_options.yaml`.

## Versioning policy

Each release that changes rules adds a new versioned file, `lib/analysis_options.X.Y.Z.yaml`. Earlier files are never edited, so a project that includes `analysis_options.6.0.0.yaml` gets the same rules for as long as it pins that file.

- Projects pin both the git `ref` and the versioned file in the `include:` line. Upgrading is a deliberate change to both, reviewed like any other dependency bump.
- `lib/analysis_options.yaml` always points at the latest version. Including it means rules can change under you on the next `pub upgrade`, so avoid it in projects with a clean-analyser CI gate.
- New or tightened rules (and anything that makes a clean project fail) get a new major or minor version. Removing a rule the SDK no longer supports is also a new version, because the old file stops being accurate on newer SDKs.

## Migrating

### From netsells_flutter_analysis

1. Replace the dependency with the git dependency above.
2. Change the include to `package:hedgehoglab_flutter_analysis/analysis_options.6.0.0.yaml`.
3. Fix new findings from the strict language modes. If a project cannot absorb them at once, include `analysis_options.5.0.0.yaml` first (the Netsells rules, unchanged) and move to 6.0.0 in a separate change.

## Suppressing Lints
### From an inline copy of the rules

There may be cases where specific lint rules are undesirable. Lint rules can be surpressed at the line, file, or project level.
1. Add the dependency and replace the copied `linter:` block with the include line.
2. Keep only project-specific `analyzer:` entries (extra excludes or severity changes) and `linter.rules` overrides. Anything that duplicates 6.0.0 can go.
3. Run `flutter analyze` and compare with the previous result. The usual differences are the strict modes and the generated-code excludes.

An example use case for suppressing lint rules at the file level is suppressing the `prefer_const_constructors` in order to achieve 100% code coverage. This is due to the fact that const constructors are executed before the tests are run, resulting in no coverage collection.
## Suppressing lints

### Line Level
Some rules are undesirable in particular places. Suppress at the line, file or project level.

To surpress a specific lint rule for a specific line of code, use an `ignore` comment directly above the line:
A line:

```dart
// ignore: public_member_api_docs
class A {}
```

### File Level

To surpress a specific lint rule of a specific file, use an `ignore_for_file` comment at the top of the file:
A file:

```dart
// ignore_for_file: public_member_api_docs
```

class A {}
A project: override the rule in the project's `analysis_options.yaml` after the `include:` line.

```yaml
linter:
rules:
lines_longer_than_80_chars: false
```

## Developing this package

CI formats and analyses the package and the `example` project with `--fatal-infos`, and fails on any undefined, removed or deprecated lint. Before adding a rule, check its status on [dart.dev](https://dart.dev/tools/linter-rules/all). Run the same checks locally:

class B {}
```sh
dart format --output=none --set-exit-if-changed .
dart analyze --fatal-infos .
dart analyze --fatal-infos example
```

## Attribution

Created by [Netsells](https://netsells.co.uk) and released under the MIT licence. The original copyright notice is retained in [LICENSE](LICENSE), with hedgehog lab's alongside it.
2 changes: 1 addition & 1 deletion example/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
include: package:netsells_flutter_analysis/analysis_options.yaml
include: package:hedgehoglab_flutter_analysis/analysis_options.6.0.0.yaml
2 changes: 1 addition & 1 deletion example/lib/example.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import 'package:netsells_flutter_analysis/netsells_flutter_analysis.dart';
import 'package:hedgehoglab_flutter_analysis/hedgehoglab_flutter_analysis.dart';

Future<void> main() async {
/// Await async functions.
Expand Down
7 changes: 3 additions & 4 deletions example/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
name: netsells_flutter_analysis_example
name: hedgehoglab_flutter_analysis_example
version: 0.0.1
publish_to: none

environment:
sdk: ">=3.0.0 <4.0.0"
flutter: ">=3.10.0"
sdk: ">=3.13.0 <4.0.0"

dependencies:
netsells_flutter_analysis:
hedgehoglab_flutter_analysis:
path: ../
Loading
Loading