This repository has been archived by the owner on Jul 16, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 258
/
unused_files_analyzer.dart
125 lines (105 loc) · 3.8 KB
/
unused_files_analyzer.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import 'dart:io';
import 'package:analyzer/dart/analysis/analysis_context.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/utilities.dart';
import 'package:path/path.dart';
import '../../config_builder/config_builder.dart';
import '../../config_builder/models/analysis_options.dart';
import '../../reporters/models/reporter.dart';
import '../../utils/analyzer_utils.dart';
import 'models/unused_files_file_report.dart';
import 'reporters/reporter_factory.dart';
import 'reporters/unused_files_report_params.dart';
import 'unused_files_analysis_config.dart';
import 'unused_files_config.dart';
import 'unused_files_visitor.dart';
/// The analyzer responsible for collecting unused files reports.
class UnusedFilesAnalyzer {
const UnusedFilesAnalyzer();
/// Returns a reporter for the given [name]. Use the reporter
/// to convert analysis reports to console, JSON or other supported format.
Reporter<UnusedFilesFileReport, void, UnusedFilesReportParams>? getReporter({
required String name,
required IOSink output,
}) =>
reporter(
name: name,
output: output,
);
/// Returns a list of unused files reports
/// for analyzing all files in the given [folders].
/// The analysis is configured with the [config].
Future<Iterable<UnusedFilesFileReport>> runCliAnalysis(
Iterable<String> folders,
String rootFolder,
UnusedFilesConfig config, {
String? sdkPath,
}) async {
final collection =
createAnalysisContextCollection(folders, rootFolder, sdkPath);
final unusedFiles = <String>{};
for (final context in collection.contexts) {
final unusedFilesAnalysisConfig =
_getAnalysisConfig(context, rootFolder, config);
final filePaths = getFilePaths(
folders,
context,
rootFolder,
unusedFilesAnalysisConfig.globalExcludes,
);
unusedFiles.addAll(filePaths);
final analyzedFiles =
filePaths.intersection(context.contextRoot.analyzedFiles().toSet());
for (final filePath in analyzedFiles) {
final unit = await context.currentSession.getResolvedUnit(filePath);
unusedFiles.removeAll(_analyzeFile(filePath, unit, config.isMonorepo));
}
final notAnalyzedFiles = filePaths.difference(analyzedFiles);
for (final filePath in notAnalyzedFiles) {
if (unusedFilesAnalysisConfig.analyzerExcludedPatterns
.any((pattern) => pattern.matches(filePath))) {
final unit = await resolveFile2(path: filePath);
unusedFiles
.removeAll(_analyzeFile(filePath, unit, config.isMonorepo));
}
}
}
return unusedFiles.map((path) {
final relativePath = relative(path, from: rootFolder);
return UnusedFilesFileReport(
path: path,
relativePath: relativePath,
);
}).toSet();
}
void deleteAllUnusedFiles(Iterable<UnusedFilesFileReport> reports) {
for (final report in reports) {
File(report.path).deleteSync();
}
}
UnusedFilesAnalysisConfig _getAnalysisConfig(
AnalysisContext context,
String rootFolder,
UnusedFilesConfig config,
) {
final analysisOptions = analysisOptionsFromContext(context) ??
analysisOptionsFromFilePath(rootFolder, context);
final contextConfig =
ConfigBuilder.getUnusedFilesConfigFromOption(analysisOptions)
.merge(config);
return ConfigBuilder.getUnusedFilesConfig(contextConfig, rootFolder);
}
Iterable<String> _analyzeFile(
String filePath,
SomeResolvedUnitResult unit,
bool ignoreExports,
) {
if (unit is ResolvedUnitResult) {
final visitor =
UnusedFilesVisitor(filePath, ignoreExports: ignoreExports);
unit.unit.visitChildren(visitor);
return visitor.paths;
}
return [];
}
}