ArKanjo 0.5.1
A tool for find code duplicated functions in codebases
embedding_method.cpp
Go to the documentation of this file.
7
8#include <algorithm>
9#include <array>
10#include <cstdio>
11#include <fstream>
12#include <iomanip>
13#include <iostream>
14
16
17EmbeddingMethod::EmbeddingMethod(const fs::path& base_path_, double similarity_,
18 std::vector<std::string> pass_through_args_) {
19 base_path = base_path_;
20 similarity = similarity_;
21 pass_through_args = std::move(pass_through_args_);
22
23 if (similarity < 0) {
24 std::cerr << "SIMILARITY SHOULD BE GREATER OR EQUAL 0 TO USE DUPLICATION FINDER BY LLM EMBEDDINGS";
25 }
26}
27
28std::string EmbeddingMethod::build_command(const fs::path& source_dir) const {
29 std::string command = "python3 -W ignore ";
30 command += Config::config().third_party_dir.string();
31 command += "/embedding/llm_detection.py";
32 command += " --source-dir ";
33 command += source_dir.string();
34 command += " --min-similarity ";
35 command += std::to_string(similarity);
36
37 for (const auto& arg : pass_through_args) {
38 command += " '";
39 for (char c : arg) {
40 if (c == '\'')
41 command += "'\\''";
42 else
43 command += c;
44 }
45 command += "'";
46 }
47 return command;
48}
49
50bool EmbeddingMethod::parse_line(const std::string& line, DuplicationEntry& entry) const {
51 std::vector<std::string> tokens = Utils::split_string(line, '\t');
52 if (tokens.size() != 3) {
53 return false;
54 }
55
56 try {
57 double sim = std::stod(tokens[2]);
58 entry = {sim, tokens[0], tokens[1]};
59 } catch (const std::exception&) {
60 return false;
61 }
62 return true;
63}
64
65std::vector<DuplicationEntry> EmbeddingMethod::read_results(FILE* pipe) const {
66 std::vector<DuplicationEntry> pairs;
67 std::array<char, 4096> buffer{};
68 std::string leftover;
69
70 while (fgets(buffer.data(), buffer.size(), pipe) != nullptr) {
71 leftover += buffer.data();
72
73 size_t newline_pos;
74 while ((newline_pos = leftover.find('\n')) != std::string::npos) {
75 std::string line = leftover.substr(0, newline_pos);
76 leftover.erase(0, newline_pos + 1);
77
78 DuplicationEntry entry;
79 if (parse_line(line, entry) && std::get<0>(entry) >= similarity) {
80 pairs.push_back(entry);
81 }
82 }
83 }
84
85 sort(pairs.rbegin(), pairs.rend());
86 return pairs;
87}
88
89void EmbeddingMethod::save_duplications(std::vector<DuplicationEntry>& file_duplication_pairs) {
90 fs::path output_file_path = FunctionStorage{}.build_similarity_path();
91
92 auto fout = std::ofstream(output_file_path.string());
93
94 fout << file_duplication_pairs.size() << '\n';
95 for (const auto& [similarity, path1, path2] : file_duplication_pairs) {
96 fout << path1 << ' ' << path2 << ' ';
97 fout << std::fixed << std::setprecision(2) << similarity << '\n';
98 }
99
100 fout.close();
101}
102
104 fs::path base = base_path / source_feature_path;
105
106 auto source = fd.get_feature<SourceFeature>();
107 if (!source)
108 return;
109
110 fs::path relative(fd.path);
111 std::string filename = fd.function_name + relative.extension().string();
112 fs::path path = base / relative / filename;
113 Utils::write_file(path, source->code + "\n");
114}
115
117 fs::path source_dir = base_path / source_feature_path;
118
119 std::string command = build_command(source_dir);
120
121 FILE* pipe = popen(command.c_str(), "r");
122 if (!pipe) {
123 std::cerr << "Error executing the LLM detection script.\n";
124 return;
125 }
126
127 std::vector<DuplicationEntry> file_duplication_pairs = read_results(pipe);
128
129 pclose(pipe);
130
131 fm::write(SAVING_MESSAGE);
132
133 save_duplications(file_duplication_pairs);
134}
static Config & config()
Gets the singleton configuration instance.
Definition: config.cpp:68
void execute() override
void on_function(const FunctionData &fd) override
EmbeddingMethod(const fs::path &base_path_, double similarity_, std::vector< std::string > pass_through_args_={})
Constructs the LLM detector.
static void write(const std::string &template_str, const std::vector< T > &data, enum Format effective=Format::AUTO, RowColorFn color_fn=nullptr, std::ostream &out=std::cout)
std::string function_name
Name of the function.
std::string path
std::shared_ptr< T > get_feature() const
fs::path build_similarity_path() const
Builds similarity file path.
Configuration management interface.
LLM-embedding-based code duplication detection.
Provides access to function storage locations.
std::tuple< double, std::string, std::string > DuplicationEntry
tuple format of the detected duplicates (similarity_percentage, path1, path2)
Definition: method.hpp:11
std::vector< std::string > split_string(const std::string &s, char delimiter)
Splits a string by a delimiter into tokens.
Definition: utils.cpp:84
void write_file(const fs::path &path, const std::string &content)
Writes content to a file at specified path.
Definition: utils.cpp:19
fs::path source_feature_path
std::filesystem::path third_party_dir
Directory containing third-party dependencies.
Definition: schema.hpp:17
Defines utility functions used across all files.