|
3 | 3 | use std::path::{Path, PathBuf}; |
4 | 4 | use std::process::ExitCode; |
5 | 5 |
|
6 | | -use clap::Parser; |
| 6 | +use clap::{Parser, ValueEnum}; |
7 | 7 | use mimalloc::MiMalloc; |
8 | 8 |
|
9 | | -use dc::{load_configuration, render_report, run_analysis, AnalysisReport, DcError, ReportFormat}; |
| 9 | +use dc::{ |
| 10 | + load_configuration, render_report, run_analysis, AnalysisReport, DcError, EntityKind, |
| 11 | + ReportFormat, |
| 12 | +}; |
10 | 13 |
|
11 | 14 | #[global_allocator] |
12 | 15 | static GLOBAL: MiMalloc = MiMalloc; |
@@ -38,11 +41,40 @@ struct CommandLineArguments { |
38 | 41 | #[arg(short, long, value_enum, default_value_t = ReportFormat::Text)] |
39 | 42 | format: ReportFormat, |
40 | 43 |
|
| 44 | + /// Виды сущностей в отчете. По умолчанию выводятся все виды. |
| 45 | + /// Допускает повторение и перечисление через запятую. |
| 46 | + #[arg(short, long = "kind", value_enum, value_delimiter = ',')] |
| 47 | + kinds: Vec<FindingKindArgument>, |
| 48 | + |
41 | 49 | /// Вывод дополнительной статистики анализа. |
42 | 50 | #[arg(short, long, default_value_t = false)] |
43 | 51 | verbose: bool, |
44 | 52 | } |
45 | 53 |
|
| 54 | +/// Вид сущности для фильтрации находок из командной строки. |
| 55 | +#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)] |
| 56 | +enum FindingKindArgument { |
| 57 | + /// Функции уровня модуля. |
| 58 | + Function, |
| 59 | + /// Классы. |
| 60 | + Class, |
| 61 | + /// Методы классов. |
| 62 | + Method, |
| 63 | + /// Переменные уровня модуля. |
| 64 | + Variable, |
| 65 | +} |
| 66 | + |
| 67 | +impl From<FindingKindArgument> for EntityKind { |
| 68 | + fn from(kind_argument: FindingKindArgument) -> Self { |
| 69 | + match kind_argument { |
| 70 | + FindingKindArgument::Function => EntityKind::Function, |
| 71 | + FindingKindArgument::Class => EntityKind::Class, |
| 72 | + FindingKindArgument::Method => EntityKind::Method, |
| 73 | + FindingKindArgument::Variable => EntityKind::Variable, |
| 74 | + } |
| 75 | + } |
| 76 | +} |
| 77 | + |
46 | 78 | /// Инициализирует процесс анализа и выводит результаты. |
47 | 79 | /// |
48 | 80 | /// :return: Статус завершения программы. |
@@ -85,7 +117,32 @@ fn execute(command_line_arguments: &CommandLineArguments) -> Result<AnalysisRepo |
85 | 117 | } |
86 | 118 | let analyzer_configuration = |
87 | 119 | load_configuration(command_line_arguments.config_path.as_deref(), target_path)?; |
88 | | - Ok(run_analysis(target_path, &analyzer_configuration)) |
| 120 | + let mut analysis_report = run_analysis(target_path, &analyzer_configuration); |
| 121 | + filter_findings_by_kind(&mut analysis_report, &command_line_arguments.kinds); |
| 122 | + Ok(analysis_report) |
| 123 | +} |
| 124 | + |
| 125 | +/// Оставляет в отчете только находки запрошенных видов. |
| 126 | +/// |
| 127 | +/// Пустой список видов означает отсутствие фильтрации. Код завершения |
| 128 | +/// программы определяется уже отфильтрованными находками. |
| 129 | +/// |
| 130 | +/// :param analysis_report: Итоговый отчет анализа. |
| 131 | +/// :param requested_kinds: Виды сущностей из аргументов командной строки. |
| 132 | +fn filter_findings_by_kind( |
| 133 | + analysis_report: &mut AnalysisReport, |
| 134 | + requested_kinds: &[FindingKindArgument], |
| 135 | +) { |
| 136 | + if requested_kinds.is_empty() { |
| 137 | + return; |
| 138 | + } |
| 139 | + let allowed_kinds: Vec<EntityKind> = requested_kinds |
| 140 | + .iter() |
| 141 | + .map(|kind_argument| EntityKind::from(*kind_argument)) |
| 142 | + .collect(); |
| 143 | + analysis_report |
| 144 | + .findings |
| 145 | + .retain(|finding| allowed_kinds.contains(&finding.entity_kind)); |
89 | 146 | } |
90 | 147 |
|
91 | 148 | /// Выводит предупреждения о пропущенных файлах в поток ошибок. |
|
0 commit comments