17int SimilarityExplorer::find_number_pairs_show(
int number_pair_found)
const {
19 return number_pair_found;
21 return std::min(limit_on_results, number_pair_found);
24bool SimilarityExplorer::match_pattern(
const Function& function1,
const Function& function2)
const {
28 if (both_path_need_to_match_pattern) {
29 return match1 && match2;
31 return match1 || match2;
42 if (!match_pattern(function1, function2))
44 if (limit_on_results !=
UNLIMITED_RESULTS && processed_results >= limit_on_results) {
56 .func_a = function1.
name(),
57 .func_b = function2.
name(),
58 .start_a = location1.declaration,
59 .start_b = location2.declaration,
60 .end_a = location1.end,
61 .end_b = location2.end,
62 .duplicated_lines = location1.size(),
67int SimilarityExplorer::find_number_pair_found(
const std::vector<SimilarPair>& similar_path_pairs)
const {
70 for (
const auto& similar_pair : similar_path_pairs) {
71 const Path& path1 = similarity_table->
get_path(similar_pair.id1);
72 const Path& path2 = similarity_table->
get_path(similar_pair.id2);
77 if (match_pattern(function1, function2))
83std::vector<SimilarPair> SimilarityExplorer::build_similar_path_pairs() {
85 if (sorted_by_number_of_duplicated_code) {
90 return similar_path_pairs;
93void SimilarityExplorer::explorer_clusters() {
94 auto clusters_info = similarity_table->
get_clusters_info(sorted_by_number_of_duplicated_code);
96 int clusters_to_show = limit_on_results > 0
97 ? std::min(limit_on_results, (
int)clusters_info.size())
98 : (int)clusters_info.size();
100 for (
int idx = 0; idx < clusters_to_show; idx++) {
101 const auto& info = clusters_info[idx];
102 fm::write(
"Cluster #" + std::to_string(idx + 1)
103 +
" (Files: " + std::to_string(info.paths.size())
104 +
", Pairs: " + std::to_string(info.total_pairs)
105 +
", Lines: " + std::to_string(info.total_lines)
106 +
", Score: " + std::to_string(info.score()) +
")");
109 std::vector<SimilarityExplorerEntry> entries{};
111 for (
const auto& path : info.paths) {
117 path.relative_path().parent_path().string(),
119 path.relative_path().filename().string(),
123 location.declaration,
141void SimilarityExplorer::explorer() {
142 auto start = std::chrono::high_resolution_clock::now();
145 fm::write(
"Building pairs of similar paths...");
147 auto similar_path_pairs = build_similar_path_pairs();
150 fm::write(
"Finding pair of numbers found and show...");
152 int number_pair_found = find_number_pair_found(similar_path_pairs);
153 int number_pairs_show = find_number_pairs_show(number_pair_found);
156 fm::time(
"Execution time build similar path pairs:", start);
159 number_pair_found, number_pairs_show
163 std::vector<SimilarityExplorerEntry> vector_entry = {};
164 for (
const auto& similar_pair : similar_path_pairs) {
165 const Path& path1 = similarity_table->
get_path(similar_pair.id1);
166 const Path& path2 = similarity_table->
get_path(similar_pair.id2);
168 auto entry = process_similar_path_pair(path1, path2);
169 if (entry.duplicated_lines <= 0)
171 vector_entry.push_back(entry);
181 : similarity_table(table),
183 pattern_to_match(
""),
184 both_path_need_to_match_pattern(false),
185 sorted_by_number_of_duplicated_code(false),
186 use_clusters(false) {}
190 if (
auto limiter =
options.get_as<
int>(
"limiter"))
191 this->limit_on_results = *limiter;
192 }
catch (
const std::invalid_argument&) {
194 "--limiter must be a valid number (passing " +
195 std::string(*
options.get(
"limiter")) +
")"
197 }
catch (
const std::out_of_range&) {
198 throw CLIError(
"--limiter outside the permitted range");
204void SimilarityExplorer::print_template_variables() {
210 for (
const auto& [k, _] : j.items()) {
216 fm::write(
" arkanjo explorer --template \"{func_a:function} ~ {func_b:function} ({duplicated_lines:number} lines)\"\n");
220 if (
options.has(
"template-help")) {
221 print_template_variables();
225 if (
auto pattern =
options.get(
"pattern"))
226 this->pattern_to_match = *pattern;
228 both_path_need_to_match_pattern =
options.has(
"both-match");
229 sorted_by_number_of_duplicated_code =
options.has(
"sort");
230 use_clusters =
options.has(
"cluster");
232 if (
auto template_value =
options.get(
"template"))
233 this->template_processed_results_output = *template_value;
Base class for CLI-related errors.
const CliOption * options() const final
Function load_metadata(const Path &path)
Loads function metadata from a path.
static std::string format_path_message_in_pair(const Function &function)
Formats path for display.
Represents a function extracted from a codebase.
bool contains_given_pattern(const std::string &pattern) const
Checks whether the function contains a pattern.
const std::string & name() const
Gets the function name.
const FunctionLocation & scope_location() const
Gets the function location inside the source file.
Represents a logical path to a function in the codebase.
fs::path relative_path() const
Gets the directory portion of the path.
static constexpr int UNLIMITED_RESULTS
Constant for unlimited results display.
bool validate(const ParsedOptions &options) override
Validate the arguments already analyzed.
bool run(const ParsedOptions &options) override
Handles code exploration command.
Represents a similarity graph between functions (paths).
std::vector< SimilarPair > get_all_similar_pairs()
Gets all similar path pairs with scores, sorted.
std::vector< ClusterInfo > get_clusters_info(bool sorted)
Returns detailed information about all clusters found in the similarity table.
const Path & get_path(PathId id) const
void sort_pairs_by_line_number(std::vector< SimilarPair > &similar_pairs) const
Sorts path pairs by line count.
void sort_pairs_by_similarity(std::vector< SimilarPair > &similar_pairs) const
Sorts path pairs by similarity.
double get_similarity(const Path &path1, const Path &path2)
Gets similarity between two paths.
Provides functionality to load Function objects from external sources.
Provides utilities for printing function information and source code.
const std::string LIMITER_PRINT
Constant string used as a visual delimiter/separator in prints.
Duplicate function exploration interface.
void to_json(json &j, const SimilarityExplorerEntry &d)