Skip to content
This repository was archived by the owner on Jul 16, 2023. It is now read-only.

Commit 8b714dc

Browse files
authored
feat: add experimental monorepo support for check-unused-code (#659)
* feat: add experimental monorepo support for check-unused-code * fix: analyze all not analyzed files if in monorepo mode * fix: fix how context folders are resolved * chore: update changelog * chore: fix test and update the docs * docs: add info about limitations * docs: add no-congratulate flag
1 parent d9f7d35 commit 8b714dc

File tree

10 files changed

+63
-19
lines changed

10 files changed

+63
-19
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
* fix: make `check-unused-l10n` also cover supertype member calls.
99
* fix: cyclomatic complexity calculation for functions with internal lambdas.
1010
* chore: restrict `analyzer` version to `>=2.4.0 <3.3.0`.
11+
* feat: support monorepos for `check-unused-code` command.
1112

1213
## 4.10.0-dev.2
1314

lib/src/analyzers/unused_code_analyzer/unused_code_analyzer.dart

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,9 @@ class UnusedCodeAnalyzer {
8989
}
9090
}
9191

92-
codeUsages.exports.forEach(publicCode.remove);
92+
if (!config.isMonorepo) {
93+
codeUsages.exports.forEach(publicCode.remove);
94+
}
9395

9496
return _getReports(codeUsages, publicCode, rootFolder);
9597
}
@@ -115,10 +117,12 @@ class UnusedCodeAnalyzer {
115117
String rootFolder,
116118
Iterable<Glob> excludes,
117119
) {
118-
final contextFolders = folders
119-
.where((path) => normalize(join(rootFolder, path))
120-
.startsWith(context.contextRoot.root.path))
121-
.toList();
120+
final contextFolders = folders.where((path) {
121+
final newPath = normalize(join(rootFolder, path));
122+
123+
return newPath == context.contextRoot.root.path ||
124+
context.contextRoot.root.path.startsWith('$newPath/');
125+
}).toList();
122126

123127
return extractDartFilesFromFolders(contextFolders, rootFolder, excludes);
124128
}

lib/src/analyzers/unused_code_analyzer/unused_code_config.dart

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ import '../../config_builder/models/analysis_options.dart';
44
class UnusedCodeConfig {
55
final Iterable<String> excludePatterns;
66
final Iterable<String> analyzerExcludePatterns;
7+
final bool isMonorepo;
78

89
const UnusedCodeConfig({
910
required this.excludePatterns,
1011
required this.analyzerExcludePatterns,
12+
required this.isMonorepo,
1113
});
1214

1315
/// Creates the config from analysis [options].
@@ -16,13 +18,18 @@ class UnusedCodeConfig {
1618
excludePatterns: const [],
1719
analyzerExcludePatterns:
1820
options.readIterableOfString(['analyzer', 'exclude']),
21+
isMonorepo: false,
1922
);
2023

2124
/// Creates the config from cli args.
22-
factory UnusedCodeConfig.fromArgs(Iterable<String> excludePatterns) =>
25+
factory UnusedCodeConfig.fromArgs(
26+
Iterable<String> excludePatterns, {
27+
required bool isMonorepo,
28+
}) =>
2329
UnusedCodeConfig(
2430
excludePatterns: excludePatterns,
2531
analyzerExcludePatterns: const [],
32+
isMonorepo: isMonorepo,
2633
);
2734

2835
/// Merges two configs into a single one.
@@ -35,5 +42,6 @@ class UnusedCodeConfig {
3542
...analyzerExcludePatterns,
3643
...overrides.analyzerExcludePatterns,
3744
},
45+
isMonorepo: isMonorepo || overrides.isMonorepo,
3846
);
3947
}

lib/src/cli/cli_runner.dart

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,16 @@ class CliRunner extends CommandRunner<void> {
3737
/// Main entry point for running a command
3838
@override
3939
Future<void> run(Iterable<String> args) async {
40-
final results = parse(args);
41-
final showVersion = results[FlagNames.version] as bool;
40+
try {
41+
final results = parse(args);
42+
final showVersion = results[FlagNames.version] as bool;
4243

43-
if (showVersion) {
44-
_output.writeln('Dart Code Metrics version: $packageVersion');
44+
if (showVersion) {
45+
_output.writeln('Dart Code Metrics version: $packageVersion');
4546

46-
return;
47-
}
47+
return;
48+
}
4849

49-
try {
5050
await super.run(_addDefaultCommand(args));
5151
} on UsageException catch (e) {
5252
_output

lib/src/cli/commands/check_unused_code_command.dart

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,13 @@ class CheckUnusedCodeCommand extends BaseCommand {
3131
final folders = argResults.rest;
3232
final excludePath = argResults[FlagNames.exclude] as String;
3333
final reporterName = argResults[FlagNames.reporter] as String;
34-
34+
final isMonorepo = argResults[FlagNames.isMonorepo] as bool;
3535
final noCongratulate = argResults[FlagNames.noCongratulate] as bool;
3636

37-
final config = ConfigBuilder.getUnusedCodeConfigFromArgs([excludePath]);
37+
final config = ConfigBuilder.getUnusedCodeConfigFromArgs(
38+
[excludePath],
39+
isMonorepo: isMonorepo,
40+
);
3841

3942
final unusedCodeResult = await _analyzer.runCliAnalysis(
4043
folders,
@@ -63,6 +66,7 @@ class CheckUnusedCodeCommand extends BaseCommand {
6366
void _addFlags() {
6467
_usesReporterOption();
6568
addCommonFlags();
69+
_usesIsMonorepoOption();
6670
_usesExitOption();
6771
}
6872

@@ -82,6 +86,15 @@ class CheckUnusedCodeCommand extends BaseCommand {
8286
);
8387
}
8488

89+
void _usesIsMonorepoOption() {
90+
argParser
91+
..addSeparator('')
92+
..addFlag(
93+
FlagNames.isMonorepo,
94+
help: 'Treats all exported code as unused by default.',
95+
);
96+
}
97+
8598
void _usesExitOption() {
8699
argParser
87100
..addSeparator('')

lib/src/cli/models/flag_names.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class FlagNames {
1111
static const reporter = 'reporter';
1212
static const rootFolder = 'root-folder';
1313
static const sdkPath = 'sdk-path';
14+
static const isMonorepo = 'monorepo';
1415
static const version = 'version';
1516

1617
static const consoleReporter = ConsoleReporter.id;

lib/src/config_builder/config_builder.dart

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,10 @@ class ConfigBuilder {
9292

9393
/// Creates a raw unused code config from given [excludePatterns].
9494
static UnusedCodeConfig getUnusedCodeConfigFromArgs(
95-
Iterable<String> excludePatterns,
96-
) =>
97-
UnusedCodeConfig.fromArgs(excludePatterns);
95+
Iterable<String> excludePatterns, {
96+
required bool isMonorepo,
97+
}) =>
98+
UnusedCodeConfig.fromArgs(excludePatterns, isMonorepo: isMonorepo);
9899

99100
/// Creates a raw unused code config from given [options].
100101
static UnusedCodeConfig getUnusedCodeConfigFromOption(

test/src/analyzers/unused_code_analyzer/unused_code_analyzer_test.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,4 +151,5 @@ UnusedCodeConfig _createConfig({
151151
UnusedCodeConfig(
152152
excludePatterns: const [],
153153
analyzerExcludePatterns: analyzerExcludePatterns,
154+
isMonorepo: false,
154155
);

test/src/cli/commands/check_unused_code_command_test.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ const _usage = 'Check unused code in *.dart files.\n'
2222
" --no-congratulate Don't show output even when there are no issues.\n"
2323
'\n'
2424
'\n'
25+
' --[no-]monorepo Treats all exported code as unused by default.\n'
26+
'\n'
27+
'\n'
2528
' --[no-]fatal-unused Treat find unused file as fatal.\n'
2629
'\n'
2730
'Run "metrics help" to see global options.';

website/docs/cli/check-unused-code.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
Checks unused classes, functions, top level variables, extensions, enums, mixins and type aliases.
44

5+
**Note:** current implementation doesn't check for particular class methods usage. Also, it treats code, that is imported with not named conditional imports as unused. This will be fixed in the future releases.
6+
57
To execute the command, run
68

79
```sh
@@ -31,9 +33,19 @@ Usage: metrics check-unused-code [arguments] <directories>
3133
(defaults to "{/**.g.dart,/**.template.dart}")
3234
3335
34-
--[no-]fatal-unused Treat find unused l10n as fatal.
36+
--no-congratulate Don't show output even when there are no issues.
37+
38+
39+
--[no-]monorepo Treats all exported code as unused by default.
40+
41+
42+
--[no-]fatal-unused Treat find unused file as fatal.
3543
```
3644

45+
## Monorepo support
46+
47+
By default the command treats all code that exported from the package as used. To disable this behavior use `--monorepo` flag. This might be useful when all the packages in your repository only unused inside this repository and not published to pub.
48+
3749
## Output example {#output-example}
3850

3951
### Console {#console}

0 commit comments

Comments
 (0)