diff --git a/CHANGELOG.md b/CHANGELOG.md index 413b816c..166f72f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,9 @@ # Changelog +## 1.1.0 +- Added new presets +- Removed Angular framework rules +- Added example + ## 1.0.2 - Fix: report in IDE'S is adjusted ## 1.0.1 diff --git a/TROUBLESHOOTING.md b/TROUBLESHOOTING.md index 03487370..8906ea0b 100644 --- a/TROUBLESHOOTING.md +++ b/TROUBLESHOOTING.md @@ -1,8 +1,8 @@ # Troubleshooting -**Note:** If the plugin is analyzing files it should not analyze (like `.dart_tool/` or an external package source code), please create [an issue](https://github.com/dart-code-checker/dart-code-metrics/issues/new?assignees=dkrutskikh&labels=question&template=question.md&title=%5BQuestion%5D+), it's most likely a bug. +**Note:** If the plugin is analyzing files it should not analyze (like `.dart_tool/` or an external package source code), please create [an issue](https://github.com/bancolombia/dart-code-linter/issues), it's most likely a bug. -If the plugin is not working as you'd expect it to work, please consider going through the following steps before creating [an issue](https://github.com/dart-code-checker/dart-code-metrics/issues/new?assignees=dkrutskikh&labels=question&template=question.md&title=%5BQuestion%5D+): +If the plugin is not working as you'd expect it to work, please consider going through the following steps before creating [an issue](https://github.com/bancolombia/dart-code-linter/issues): 1. Check that the plugin is added to an `analyzer` entry in the `analysis_options.yaml` as described in the [Configuration](./README.md#Configuration) section. diff --git a/example/.gitignore b/example/.gitignore new file mode 100644 index 00000000..dbef116d --- /dev/null +++ b/example/.gitignore @@ -0,0 +1,21 @@ +# See https://www.dartlang.org/guides/libraries/private-files + +# Files and directories created by pub +.dart_tool/ +.packages +build/ +# If you're building an application, you may want to check-in your pubspec.lock +pubspec.lock + +# Directory created by dartdoc +# If you don't generate documentation locally you can remove this line. +doc/api/ + +# Avoid committing generated Javascript files: +*.dart.js +*.info.json # Produced by the --dump-info flag. +*.js # When generated by dart2js. Don't specify *.js if your + # project includes source files written in JavaScript. +*.js_ +*.js.deps +*.js.map diff --git a/example/LICENSE b/example/LICENSE new file mode 100644 index 00000000..06c90e54 --- /dev/null +++ b/example/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Dart Code Checker + +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/example/README.md b/example/README.md new file mode 100644 index 00000000..0e8a12b9 --- /dev/null +++ b/example/README.md @@ -0,0 +1,17 @@ +# Examples + +DCL is a static analysis tool and code from it is not expected to be used directly. Instead, it should be added as a dev dependency and installed [as described here](https://github.com/bancolombia/dart-code-linter/blob/trunk/GETTINGSTARTED.md). + +## Preferred way: plugin and CLI + +To use DCL as a plugin or a CLI, check out [this repository](https://github.com/bancolombia/dart-code-linter/blob/trunk/example/lib/main.dart) with the example Flutter app. It covers DCL setup and shows all commands output. + +## Additional way: as a library + +**Note:** usually you don't need to use DCL directly. + +DCL can be used directly as a library, imported and called from your code. Continue with [this example](https://github.com/bancolombia/dart-code-linter/blob/trunk/example/lib_example/lib/main.dart) in order to get more details. + +## Presets + +Presets can be enabled with `extends` config, more details [can be found here](https://github.com/bancolombia/dart-code-linter/wiki/Presets). diff --git a/example/analysis_options.yaml b/example/analysis_options.yaml new file mode 100644 index 00000000..b16e1cab --- /dev/null +++ b/example/analysis_options.yaml @@ -0,0 +1,67 @@ +analyzer: + language: + strict-inference: true + strict-raw-types: true + # Dart Code Linter uses plugins api from the analyzer + # to provide issues highlight in the IDE. If you don't want the issues + # to be shown and need only the CLI, you need to remove the section below. + plugins: + - dart_code_linter + strong-mode: + implicit-casts: false + implicit-dynamic: false + +dart_code_linter: + # Dart Code Linter supports presets. The config from a preset will be merged + # with the config listed in this file. The config listed here has a higher priority. + # Any rule can be simply disabled by setting `- rule-name: false`. + # Uncomment the section below to see how presets work. + # extends: + # - package:dart_code_linter/presets/all.yaml + + # To enabled anti-patterns and metrics in the analysis report, uncomment the sections below. + # Metric violations are not shown in the IDE. + # anti-patterns: + # - long-method + # - long-parameter-list + # metrics: + # cyclomatic-complexity: 20 + # maintainability-index: 50 + # maximum-nesting: 5 + # number-of-parameters: 5 + # source-lines-of-code: 50 + # technical-debt: + # threshold: 16 + # todo-cost: 4 + # ignore-cost: 8 + # ignore-for-file-cost: 16 + # as-dynamic-cost: 16 + # deprecated-annotations-cost: 2 + # file-nullsafety-migration-cost: 2 + # unit-type: "hours" + + # Dart Code Linter provides custom configurable rules. + # The rules have a `kebab-case` naming instead of + # `snake_case` intentionally in order for you to identify, + # whether the rule is from Dart Code Metrics or the standard analyzer. + # All rules share basic configuration like `exclude` section, + # but some also have a rule-specific one. + # Not all rules are listed here, the full list can be found on our website: https://github.com/bancolombia/dart-code-linter/wiki/Rules + rules: + - avoid-top-level-members-in-tests + - avoid-collection-methods-with-unrelated-types + - avoid-missing-enum-constant-in-map + - avoid-unnecessary-type-assertions + - avoid-unnecessary-type-casts + - avoid-unused-parameters + - newline-before-return + - no-boolean-literal-compare + - no-empty-block + - no-equal-then-else + - prefer-async-await + - prefer-correct-type-name: + max-length: 44 + - prefer-match-file-name: + exclude: + - test/** + - prefer-trailing-comma \ No newline at end of file diff --git a/example/lib/main.dart b/example/lib/main.dart new file mode 100644 index 00000000..12b5b932 --- /dev/null +++ b/example/lib/main.dart @@ -0,0 +1,75 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_example/src/unnecessary_nullable_widget.dart'; +import 'package:flutter_example/src/unused_code_widget.dart'; + +void main() { + runApp(const MyApp()); +} + +/// The issue below is reported by Dart Code Linter. +/// In order to resolve the warning, the class or the file should be renamed. +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + @override + Widget build(BuildContext context) => MaterialApp( + title: 'Flutter Demo', + theme: ThemeData( + primarySwatch: Colors.blue, + ), + home: const MyHomePage(title: 'Flutter Demo Home Page'), + ); +} + +class MyHomePage extends StatefulWidget { + const MyHomePage({super.key, required this.title}); + + final String title; + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + int _counter = 0; + + /// The issue below is reported by Dart Code Linter. + /// In order to resolve the warning, the parameter should be used or removed. + void _incrementCounter(BuildContext context) { + setState(() { + _counter++; + }); + } + + @override + Widget build(BuildContext context) => Scaffold( + appBar: AppBar( + title: Text(widget.title), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + 'You have pushed the button this many times:', + ), + Text( + '$_counter', + style: Theme.of(context).textTheme.headline4, + ), + UnusedCodeWidget(), + UnnecessaryNullableWidget(), + ], + ), + ), + + /// The issue below is reported by Dart Code Linter. The severity of a rule can be configured via `severity` config entry. + /// Adding a trailing comma will remove the highlight. + /// Trailing comma can also be added with auto-fix menu command in the IDE. + /// Rules that support auto-fixes are marked with corresponding emoji in the docs https://dartcodemetrics.dev/docs/rules. + floatingActionButton: FloatingActionButton( + onPressed: () => _incrementCounter(context), + tooltip: 'Increment', + child: const Icon(Icons.add), + )); +} diff --git a/example/lib/src/unnecessary_nullable_widget.dart b/example/lib/src/unnecessary_nullable_widget.dart new file mode 100644 index 00000000..4358c824 --- /dev/null +++ b/example/lib/src/unnecessary_nullable_widget.dart @@ -0,0 +1,20 @@ +import 'package:flutter/material.dart'; + +class UnnecessaryNullableWidget extends StatelessWidget { + const UnnecessaryNullableWidget({super.key}); + + /// This callback declares a nullable parameter `value`, + /// but it's actually always used with non-nullable argument. + /// Run `flutter pub run dart_code_linter:metrics check-unnecessary-nullable lib` to see the report. + void someCallback(String? value) { + print(value); + } + + @override + Widget build(BuildContext context) { + return TextButton( + onPressed: () => someCallback('Hello'), + child: Text('From world'), + ); + } +} diff --git a/example/lib/src/unused_code_widget.dart b/example/lib/src/unused_code_widget.dart new file mode 100644 index 00000000..face2eb3 --- /dev/null +++ b/example/lib/src/unused_code_widget.dart @@ -0,0 +1,26 @@ +import 'package:flutter/src/widgets/container.dart'; +import 'package:flutter/src/widgets/framework.dart'; + +/// This variable is not referenced in any file and is actually unused. +/// In order to spot such declarations, +/// run `flutter pub run dart_code_linter:metrics check-unused-code lib`. +const someVariable = '1'; + +/// This function is not referenced in any file and is actually unused. +/// In order to spot such declarations, +/// run `flutter pub run dart_code_linter:metrics check-unused-code lib`. +String topLevelFunction() { + print('Actually unused'); + + return 'Unused'; +} + +/// This widget is used by `main.dart`. +class UnusedCodeWidget extends StatelessWidget { + const UnusedCodeWidget({super.key}); + + @override + Widget build(BuildContext context) { + return Container(); + } +} diff --git a/example/lib/src/unused_widget.dart b/example/lib/src/unused_widget.dart new file mode 100644 index 00000000..2411ce20 --- /dev/null +++ b/example/lib/src/unused_widget.dart @@ -0,0 +1,13 @@ +import 'package:flutter/widgets.dart'; + +/// This widget is not imported by any other file and is not a project entry point. +/// It will be reported by `check-unused-files` command. +/// Run `flutter pub run dart_code_linter:metrics check-unused-files lib` to see the report. +class UnusedWidget extends StatelessWidget { + const UnusedWidget({super.key}); + + @override + Widget build(BuildContext context) { + return Container(); + } +} diff --git a/example/lib_example/lib/main.dart b/example/lib_example/lib/main.dart new file mode 100644 index 00000000..6bce0f0c --- /dev/null +++ b/example/lib_example/lib/main.dart @@ -0,0 +1,47 @@ +import 'dart:io'; + +import 'package:dart_code_linter/lint_analyzer.dart'; + +Future main() async { + // Get some folder you would like to analyze. + const foldersToAnalyze = ['lib', 'test']; + + // Root folder path is used to resolve relative file paths. + const rootFolder = 'projectRoot'; + + // First of all config has to be created for a checker. + const config = LintConfig( + excludePatterns: ['test/resources/**'], + excludeForMetricsPatterns: ['test/**'], + metrics: { + 'maximum-nesting-level': '5', + 'number-of-methods': '10', + }, + excludeForRulesPatterns: ['test/**'], + rules: { + 'double-literal-format': {}, + 'newline-before-return': {'severity': 'info'}, + }, + antiPatterns: {'long-method': {}}, + shouldPrintConfig: false, + analysisOptionsPath: null, + ); + + const analyzer = LintAnalyzer(); + + final result = + await analyzer.runCliAnalysis(foldersToAnalyze, rootFolder, config); + + // Now runner.results() contains some insights about analyzed code. Let's report it! + // For a simple example we would report results to terminal + + // Now pass collected analysis reports from runner to reporter and that's it + await analyzer + .getReporter(name: 'console', output: stdout, reportFolder: '.') + ?.report(result); + + // There is also JsonReporter for making machine-readable reports + // HtmlReporter produces fancy html-documents with bells and whistles + // And CodeClimateReporter produces reports that are widely understood by various CI tools + // If none of these fits your case you can always access raw analysis info via results() method of runner and process it any way you see fit +} diff --git a/example/pubspec.yaml b/example/pubspec.yaml new file mode 100644 index 00000000..facac8ff --- /dev/null +++ b/example/pubspec.yaml @@ -0,0 +1,22 @@ +name: flutter_example +description: Example app with DCL setup. + +publish_to: "none" # Remove this line if you wish to publish to pub.dev + +version: 1.0.0+1 + +environment: + sdk: ">=2.18.2 <3.0.0" + +dependencies: + flutter: + sdk: flutter + cupertino_icons: ^1.0.2 + +dev_dependencies: + dart_code_linter: ^1.1.0 + flutter_test: + sdk: flutter + +flutter: + uses-material-design: true diff --git a/lib/src/analyzers/lint_analyzer/rules/rule_utils.dart b/lib/src/analyzers/lint_analyzer/rules/rule_utils.dart index a4c6be1b..66eaf8bf 100644 --- a/lib/src/analyzers/lint_analyzer/rules/rule_utils.dart +++ b/lib/src/analyzers/lint_analyzer/rules/rule_utils.dart @@ -27,7 +27,7 @@ Issue createIssue({ /// Returns a url of a page containing documentation associated with [rule] Uri documentation(Rule rule) => Uri( scheme: 'https', - host: 'dcm.dev', + host: 'localhost', pathSegments: [ 'docs', 'individuals', diff --git a/lib/src/version.dart b/lib/src/version.dart index 37d103d6..6388e8c6 100644 --- a/lib/src/version.dart +++ b/lib/src/version.dart @@ -1 +1 @@ -const packageVersion = '1.0.2'; +const packageVersion = '1.1.0'; diff --git a/pubspec.yaml b/pubspec.yaml index eef19dd0..ba0ea697 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: dart_code_linter -version: 1.0.2 +version: 1.1.0 description: Dart Code Linter is a software analytics tool that helps developers analyse and improve software quality. Dart Code Linter is based on a fork of Dart Code Metrics. repository: https://github.com/bancolombia/dart-code-linter diff --git a/tools/analyzer_plugin/pubspec.yaml b/tools/analyzer_plugin/pubspec.yaml index a31ae4bb..382ca3af 100644 --- a/tools/analyzer_plugin/pubspec.yaml +++ b/tools/analyzer_plugin/pubspec.yaml @@ -1,12 +1,12 @@ name: dart_code_linter_plugin_loader description: This pubspec determines the version of the analyzer plugin to load. -version: 1.0.2 +version: 1.1.0 environment: sdk: ">=2.14.0 <3.0.0" dependencies: - dart_code_linter: 1.0.2 + dart_code_linter: 1.1.0 dev_dependencies: lints: ^1.0.1