1// Copyright 2014 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import 'dart:io' show Directory;
6
7import 'package:analyzer/dart/analysis/analysis_context.dart';
8import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
9import 'package:analyzer/dart/analysis/results.dart';
10import 'package:analyzer/dart/analysis/session.dart';
11import 'package:path/path.dart' as path;
12
13import '../utils.dart';
14
15/// Analyzes the dart source files in the given `flutterRootDirectory` with the
16/// given [AnalyzeRule]s.
17///
18/// The `includePath` parameter takes a collection of paths relative to the given
19/// `flutterRootDirectory`. It specifies the files or directory this function
20/// should analyze. Defaults to null in which case this function analyzes the
21/// all dart source files in `flutterRootDirectory`.
22///
23/// The `excludePath` parameter takes a collection of paths relative to the given
24/// `flutterRootDirectory` that this function should skip analyzing.
25///
26/// If a compilation unit can not be resolved, this function ignores the
27/// corresponding dart source file and logs an error using [foundError].
28Future<void> analyzeWithRules(
29 String flutterRootDirectory,
30 List<AnalyzeRule> rules, {
31 Iterable<String>? includePaths,
32 Iterable<String>? excludePaths,
33}) async {
34 if (!Directory(flutterRootDirectory).existsSync()) {
35 foundError(<String>['Analyzer error: the specified $flutterRootDirectory does not exist.']);
36 }
37 final Iterable<String> includes =
38 includePaths?.map(
39 (String relativePath) => path.canonicalize('$flutterRootDirectory/$relativePath'),
40 ) ??
41 <String>[path.canonicalize(flutterRootDirectory)];
42 final AnalysisContextCollection collection = AnalysisContextCollection(
43 includedPaths: includes.toList(),
44 excludedPaths:
45 excludePaths
46 ?.map((String relativePath) => path.canonicalize('$flutterRootDirectory/$relativePath'))
47 .toList(),
48 );
49
50 final List<String> analyzerErrors = <String>[];
51 for (final AnalysisContext context in collection.contexts) {
52 final Iterable<String> analyzedFilePaths = context.contextRoot.analyzedFiles();
53 final AnalysisSession session = context.currentSession;
54
55 for (final String filePath in analyzedFilePaths) {
56 final SomeResolvedUnitResult unit = await session.getResolvedUnit(filePath);
57 if (unit is ResolvedUnitResult) {
58 for (final AnalyzeRule rule in rules) {
59 rule.applyTo(unit);
60 }
61 } else {
62 analyzerErrors.add(
63 'Analyzer error: file $unit could not be resolved. Expected "ResolvedUnitResult", got ${unit.runtimeType}.',
64 );
65 }
66 }
67 }
68
69 if (analyzerErrors.isNotEmpty) {
70 foundError(analyzerErrors);
71 }
72 for (final AnalyzeRule verifier in rules) {
73 verifier.reportViolations(flutterRootDirectory);
74 }
75}
76
77/// An interface that defines a set of best practices, and collects information
78/// about code that violates the best practices in a [ResolvedUnitResult].
79///
80/// The [analyzeWithRules] function scans and analyzes the specified
81/// source directory using the dart analyzer package, and applies custom rules
82/// defined in the form of this interface on each resulting [ResolvedUnitResult].
83/// The [reportViolations] method will be called at the end, once all
84/// [ResolvedUnitResult]s are parsed.
85///
86/// Implementers can assume each [ResolvedUnitResult] is valid compilable dart
87/// code, as the caller only applies the custom rules once the code passes
88/// `flutter analyze`.
89abstract class AnalyzeRule {
90 /// Applies this rule to the given [ResolvedUnitResult] (typically a file), and
91 /// collects information about violations occurred in the compilation unit.
92 void applyTo(ResolvedUnitResult unit);
93
94 /// Reports all violations in the resolved compilation units [applyTo] was
95 /// called on, if any.
96 ///
97 /// This method is called once all [ResolvedUnitResult] are parsed.
98 ///
99 /// The implementation typically calls [foundErrors] to report violations.
100 void reportViolations(String workingDirectory);
101}
102

Provided by KDAB

Privacy Policy
Learn more about Flutter for embedded and desktop on industrialflutter.com