summaryrefslogtreecommitdiffstats
path: root/debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/sorting.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/sorting.cpp')
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/sorting.cpp698
1 files changed, 0 insertions, 698 deletions
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/sorting.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/sorting.cpp
deleted file mode 100644
index bec55749..00000000
--- a/debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/sorting.cpp
+++ /dev/null
@@ -1,698 +0,0 @@
-/**
- * @file sorting.cpp
- * Sorts chunks and imports
- *
- * @author Ben Gardner
- * @license GPL v2+
- */
-
-#include "sorting.h"
-
-#include "newlines.h"
-#include "prototypes.h"
-
-#include <regex>
-
-constexpr static auto LCURRENT = LSORT;
-
-using namespace uncrustify;
-
-Option<std::string> *include_category_options[] =
-{
- &options::include_category_0,
- &options::include_category_1,
- &options::include_category_2,
-};
-constexpr static int kIncludeCategoriesCount = 3;
-
-
-struct include_category
-{
- include_category(const std::string &pattern)
- : regex(pattern)
- {
- }
- std::regex regex;
-};
-
-
-include_category *include_categories[kIncludeCategoriesCount];
-
-
-/**
- * Compare two series of chunks, starting with the given ones.
- * @param pc1 first instance to compare
- * @param pc2 second instance to compare
- * @param tcare take care of case (lower case/ upper case) Issue #2091
- *
- * @retval == 0 both text elements are equal
- * @retval > 0
- * @retval < 0
- */
-static int compare_chunks(chunk_t *pc1, chunk_t *pc2, bool tcare = false);
-
-
-/**
- * Sorting should be pretty rare and should usually only include a few chunks.
- * We need to minimize the number of swaps, as those are expensive.
- * So, we do a min sort.
- */
-static void do_the_sort(chunk_t **chunks, size_t num_chunks);
-
-
-#define MARK_CHANGE() mark_change(__func__, __LINE__)
-
-
-static void mark_change(const char *func, size_t line)
-{
- LOG_FUNC_ENTRY();
- cpd.changes++;
-
- if (cpd.pass_count == 0)
- {
- LOG_FMT(LCHANGE, "%s(%d): change %d on %s:%zu\n",
- __func__, __LINE__, cpd.changes, func, line);
- }
-}
-
-
-static void prepare_categories()
-{
- for (int i = 0; i < kIncludeCategoriesCount; ++i)
- {
- const auto &cat_pattern = (*include_category_options[i])();
-
- if (!cat_pattern.empty())
- {
- include_categories[i] = new include_category(cat_pattern);
- }
- else
- {
- include_categories[i] = nullptr;
- }
- }
-}
-
-
-static void cleanup_categories()
-{
- for (auto &include_category : include_categories)
- {
- if (include_category == nullptr)
- {
- continue;
- }
- delete include_category;
- include_category = NULL;
- }
-}
-
-
-static int get_chunk_priority(chunk_t *pc)
-{
- for (int i = 0; i < kIncludeCategoriesCount; i++)
- {
- if (include_categories[i] != nullptr)
- {
- if (std::regex_match(pc->text(), include_categories[i]->regex))
- {
- return(i);
- }
- }
- }
-
- return(kIncludeCategoriesCount);
-}
-
-
-/**
- * Returns true if the text contains filename without extension.
- */
-static bool text_contains_filename_without_ext(const char *text)
-{
- std::string filepath = cpd.filename;
- size_t slash_idx = filepath.find_last_of("/\\");
- std::string filename_without_ext = filepath;
-
- if ( slash_idx != std::string::npos
- && slash_idx < (filepath.size() - 1))
- {
- std::string filename = filepath.substr(slash_idx + 1);
- size_t dot_idx = filename.find_last_of('.');
- filename_without_ext = filename.substr(0, dot_idx);
- }
- const std::regex special_chars = std::regex(R"([-[\]{}()*+?.,\^$|#\s])");
- const std::string sanitized_filename = std::regex_replace(filename_without_ext, special_chars, R"(\$&)");
- const std::regex filename_pattern = std::regex("\\S?" + sanitized_filename + "\\b.*");
-
- return(std::regex_match(text, filename_pattern));
-}
-
-
-/**
- * Get chunk text without the extension.
- */
-static unc_text get_text_without_ext(const unc_text &chunk_text)
-{
- unc_text result = chunk_text;
- int idx = result.rfind(".", result.size() - 1);
-
- if (idx == -1)
- {
- return(result);
- }
- result.erase(idx, result.size() - idx);
- return(result);
-}
-
-
-/**
- * Returns true if unc_text has "." which implies extension.
- */
-static bool has_dot(const unc_text &chunk_text)
-{
- int idx = chunk_text.rfind(".", chunk_text.size() - 1);
-
- return(idx != -1);
-}
-
-
-/**
- * Returns chunk string required for sorting.
- */
-static unc_text chunk_sort_str(chunk_t *pc)
-{
- if (get_chunk_parent_type(pc) == CT_PP_INCLUDE)
- {
- return(unc_text{ pc->str, 0, pc->len() - 1 });
- }
- return(pc->str);
-}
-
-
-//! Compare two chunks
-static int compare_chunks(chunk_t *pc1, chunk_t *pc2, bool tcare)
-{
- LOG_FUNC_ENTRY();
- LOG_FMT(LSORT, "%s(%d): @begin pc1->len is %zu, line is %zu, column is %zu\n",
- __func__, __LINE__, pc1->len(), pc1->orig_line, pc1->orig_col);
- LOG_FMT(LSORT, "%s(%d): @begin pc2->len is %zu, line is %zu, column is %zu\n",
- __func__, __LINE__, pc2->len(), pc2->orig_line, pc2->orig_col);
-
- if (pc1 == pc2) // same chunk is always identical thus return 0 differences
- {
- return(0);
- }
-
- while ( pc1 != nullptr
- && pc2 != nullptr)
- {
- auto const &s1_ext = chunk_sort_str(pc1);
- auto const &s2_ext = chunk_sort_str(pc2);
-
- log_rule_B("mod_sort_incl_import_ignore_extension");
- auto const &s1 = (options::mod_sort_incl_import_ignore_extension()) ? get_text_without_ext(s1_ext) : s1_ext;
- auto const &s2 = (options::mod_sort_incl_import_ignore_extension()) ? get_text_without_ext(s2_ext) : s2_ext;
- log_rule_B("mod_sort_incl_import_prioritize_filename");
-
- if (options::mod_sort_incl_import_prioritize_filename())
- {
- bool s1_contains_filename = text_contains_filename_without_ext(s1.c_str());
- bool s2_contains_filename = text_contains_filename_without_ext(s2.c_str());
-
- if ( s1_contains_filename
- && !s2_contains_filename)
- {
- return(-1);
- }
- else if ( !s1_contains_filename
- && s2_contains_filename)
- {
- return(1);
- }
- }
-
- if (options::mod_sort_incl_import_prioritize_extensionless())
- {
- log_rule_B("mod_sort_incl_import_prioritize_extensionless");
- const bool s1_has_dot = has_dot(s1_ext);
- const bool s2_has_dot = has_dot(s2_ext);
-
- if ( s1_has_dot
- && !s2_has_dot)
- {
- return(1);
- }
- else if ( !s1_has_dot
- && s2_has_dot)
- {
- return(-1);
- }
- }
-
- if (options::mod_sort_incl_import_prioritize_angle_over_quotes())
- {
- log_rule_B("mod_sort_incl_import_prioritize_angle_over_quotes");
-
- if ( s1.startswith("<")
- && s2.startswith("\""))
- {
- return(-1);
- }
- else if ( s1.startswith("\"")
- && s2.startswith("<"))
- {
- return(1);
- }
- }
- int ppc1 = get_chunk_priority(pc1);
- int ppc2 = get_chunk_priority(pc2);
-
- if (ppc1 != ppc2)
- {
- return(ppc1 - ppc2);
- }
- LOG_FMT(LSORT, "%s(%d): text is %s, pc1->len is %zu, line is %zu, column is %zu\n",
- __func__, __LINE__, pc1->text(), pc1->len(), pc1->orig_line, pc1->orig_col);
- LOG_FMT(LSORT, "%s(%d): text is %s, pc2->len is %zu, line is %zu, column is %zu\n",
- __func__, __LINE__, pc2->text(), pc2->len(), pc2->orig_line, pc2->orig_col);
-
- int ret_val = unc_text::compare(s1, s2, std::min(s1.size(), s2.size()), tcare);
- LOG_FMT(LSORT, "%s(%d): ret_val is %d\n",
- __func__, __LINE__, ret_val);
-
- if (ret_val != 0)
- {
- return(ret_val);
- }
-
- if (pc1->len() != pc2->len())
- {
- return(pc1->len() - pc2->len());
- }
- // Same word, same length. Step to the next chunk.
- pc1 = chunk_get_next(pc1);
- LOG_FMT(LSORT, "%s(%d): text is %s, pc1->len is %zu, line is %zu, column is %zu\n",
- __func__, __LINE__, pc1->text(), pc1->len(), pc1->orig_line, pc1->orig_col);
-
- if (chunk_is_token(pc1, CT_MEMBER))
- {
- pc1 = chunk_get_next(pc1);
- LOG_FMT(LSORT, "%s(%d): text is %s, pc1->len is %zu, line is %zu, column is %zu\n",
- __func__, __LINE__, pc1->text(), pc1->len(), pc1->orig_line, pc1->orig_col);
- }
- pc2 = chunk_get_next(pc2);
- LOG_FMT(LSORT, "%s(%d): text is %s, pc2->len is %zu, line is %zu, column is %zu\n",
- __func__, __LINE__, pc2->text(), pc2->len(), pc2->orig_line, pc2->orig_col);
-
- if (chunk_is_token(pc2, CT_MEMBER))
- {
- pc2 = chunk_get_next(pc2);
- LOG_FMT(LSORT, "%s(%d): text is %s, pc2->len is %zu, line is %zu, column is %zu\n",
- __func__, __LINE__, pc2->text(), pc2->len(), pc2->orig_line, pc2->orig_col);
- }
- LOG_FMT(LSORT, "%s(%d): >>>text is %s, pc1->len is %zu, line is %zu, column is %zu\n",
- __func__, __LINE__, pc1->text(), pc1->len(), pc1->orig_line, pc1->orig_col);
- LOG_FMT(LSORT, "%s(%d): >>>text is %s, pc2->len is %zu, line is %zu, column is %zu\n",
- __func__, __LINE__, pc2->text(), pc2->len(), pc2->orig_line, pc2->orig_col);
-
- // If we hit a newline or nullptr, we are done
- if ( pc1 == nullptr
- || chunk_is_newline(pc1)
- || pc2 == nullptr
- || chunk_is_newline(pc2))
- {
- break;
- }
- }
-
- if ( pc1 == nullptr
- || !chunk_is_newline(pc2))
- {
- return(-1);
- }
-
- if (!chunk_is_newline(pc1))
- {
- return(1);
- }
- return(0);
-} // compare_chunks
-
-
-/**
- * Sorting should be pretty rare and should usually only include a few chunks.
- * We need to minimize the number of swaps, as those are expensive.
- * So, we do a min sort.
- */
-static void do_the_sort(chunk_t **chunks, size_t num_chunks)
-{
- LOG_FUNC_ENTRY();
-
- LOG_FMT(LSORT, "%s(%d): %zu chunks:",
- __func__, __LINE__, num_chunks);
-
- for (size_t idx = 0; idx < num_chunks; idx++)
- {
- LOG_FMT(LSORT, " [%s]", chunks[idx]->text());
- }
-
- LOG_FMT(LSORT, "\n");
-
- size_t start_idx;
-
- log_rule_B("mod_sort_case_sensitive");
- bool take_care = options::mod_sort_case_sensitive(); // Issue #2091
-
- for (start_idx = 0; start_idx < (num_chunks - 1); start_idx++)
- {
- // Find the index of the minimum value
- size_t min_idx = start_idx;
-
- for (size_t idx = start_idx + 1; idx < num_chunks; idx++)
- {
- if (compare_chunks(chunks[idx], chunks[min_idx], take_care) < 0) // Issue #2091
- {
- min_idx = idx;
- }
- }
-
- // Swap the lines if the minimum isn't the first entry
- if (min_idx != start_idx)
- {
- chunk_swap_lines(chunks[start_idx], chunks[min_idx]);
- log_rule_B("mod_sort_incl_import_grouping_enabled");
-
- if (options::mod_sort_incl_import_grouping_enabled())
- {
- chunk_t *pc = chunks[min_idx];
- chunks[min_idx] = chunks[start_idx];
- chunks[start_idx] = pc;
- }
- else
- {
- // Don't need to swap, since we only want the side-effects
- chunks[min_idx] = chunks[start_idx];
- }
- }
- }
-} // do_the_sort
-
-
-/**
- * Remove blank lines between chunks.
- */
-static void remove_blank_lines_between_imports(chunk_t **chunks, size_t num_chunks)
-{
- LOG_FUNC_ENTRY();
-
- if (num_chunks < 2)
- {
- return;
- }
-
- for (size_t idx = 0; idx < (num_chunks - 1); idx++)
- {
- chunk_t *chunk1 = chunk_get_next_nl(chunks[idx]);
- chunk1->nl_count = 1;
- MARK_CHANGE();
- }
-}
-
-
-/**
- * Delete chunks on line having chunk.
- */
-static void delete_chunks_on_line_having_chunk(chunk_t *chunk)
-{
- LOG_FUNC_ENTRY();
-
- chunk_t *pc = chunk_first_on_line(chunk);
-
- while ( pc != nullptr
- && !chunk_is_comment(pc))
- {
- chunk_t *next_pc = chunk_get_next(pc);
- LOG_FMT(LCHUNK, "%s(%d): Removed '%s' on orig_line %zu\n",
- __func__, __LINE__, pc->text(), pc->orig_line);
-
- if (chunk_is_newline(pc))
- {
- chunk_del(pc);
- break;
- }
- else
- {
- chunk_del(pc);
- }
- pc = next_pc;
- }
-}
-
-
-/**
- * Dedupe import/include directives.
- */
-static void dedupe_imports(chunk_t **chunks, size_t num_chunks)
-{
- LOG_FUNC_ENTRY();
- log_rule_B("mod_sort_case_sensitive");
-
- for (size_t idx = 1; idx < num_chunks; idx++)
- {
- auto const &s1 = chunk_sort_str(chunks[idx - 1]);
- auto const &s2 = chunk_sort_str(chunks[idx]);
-
- if (s1.size() != s2.size())
- {
- continue;
- }
- int ret_val = unc_text::compare(s1, s2, std::min(s1.size(), s2.size()), options::mod_sort_case_sensitive());
-
- if (ret_val == 0)
- {
- delete_chunks_on_line_having_chunk(chunks[idx - 1]);
- }
- }
-}
-
-
-/**
- * Add blank line before the chunk.
- */
-static void blankline_add_before(chunk_t *pc)
-{
- chunk_t *newline = newline_add_before(chunk_first_on_line(pc));
-
- if (newline->nl_count < 2)
- {
- double_newline(newline);
- }
-}
-
-
-/**
- * Group imports.
- */
-static void group_imports_by_adding_newlines(chunk_t **chunks, size_t num_chunks)
-{
- LOG_FUNC_ENTRY();
-
- // Group imports based on first character, typically quote or angle.
- int c_idx = -1;
- int c_idx_last = -1;
-
- for (size_t idx = 0; idx < num_chunks; idx++)
- {
- if (chunks[idx]->str.size() > 0)
- {
- c_idx = chunks[idx]->str.at(0);
- }
- else
- {
- c_idx = -1;
- }
-
- if ( c_idx_last != c_idx
- && idx > 0)
- {
- blankline_add_before(chunks[idx]);
- }
- c_idx_last = c_idx;
- }
-
- // Group imports based on having extension.
- bool chunk_has_dot = false;
- bool chunk_last_has_dot = false;
-
- for (size_t idx = 0; idx < num_chunks; idx++)
- {
- chunk_has_dot = has_dot(chunks[idx]->str);
-
- if ( chunk_last_has_dot != chunk_has_dot
- && idx > 0)
- {
- blankline_add_before(chunks[idx]);
- }
- chunk_last_has_dot = chunk_has_dot;
- }
-
- // Group imports based on priority defined by config.
- int chunk_pri = -1;
- int chunk_pri_last = -1;
-
- for (size_t idx = 0; idx < num_chunks; idx++)
- {
- chunk_pri = get_chunk_priority(chunks[idx]);
-
- if ( chunk_pri_last != chunk_pri
- && idx > 0)
- {
- blankline_add_before(chunks[idx]);
- }
- chunk_pri_last = chunk_pri;
- }
-
- // Group imports that contain filename pattern.
- bool chunk_has_filename = false;
- bool last_chunk_has_filename = false;
-
- for (size_t idx = 0; idx < num_chunks; idx++)
- {
- auto const &chunk_text = chunk_sort_str(chunks[idx]);
- chunk_has_filename = text_contains_filename_without_ext(chunk_text.c_str());
-
- if ( !chunk_has_filename
- && last_chunk_has_filename)
- {
- blankline_add_before(chunks[idx]);
- }
- last_chunk_has_filename = chunk_has_filename;
- }
-} // group_imports_by_adding_newlines
-
-
-void sort_imports(void)
-{
- LOG_FUNC_ENTRY();
- const int max_number_to_sort = 1024;
- const int max_lines_to_check_for_sort_after_include = 128;
- const int max_gap_threshold_between_include_to_sort = 32;
-
- chunk_t *chunks[max_number_to_sort];
- size_t num_chunks = 0;
- chunk_t *p_last = nullptr;
- chunk_t *p_imp = nullptr;
- chunk_t *p_imp_last = nullptr;
-
- prepare_categories();
-
- chunk_t *pc = chunk_get_head();
-
- log_rule_B("mod_sort_incl_import_grouping_enabled");
-
- while (pc != nullptr)
- {
- // Simple optimization to limit the sorting. Any MAX_LINES_TO_CHECK_AFTER_INCLUDE lines after last
- // import is seen are ignore from sorting.
- if ( options::mod_sort_incl_import_grouping_enabled()
- && p_imp_last != nullptr
- && (pc->orig_line - p_imp_last->orig_line) > max_lines_to_check_for_sort_after_include)
- {
- break;
- }
- chunk_t *next = chunk_get_next(pc);
-
- if (chunk_is_newline(pc))
- {
- bool did_import = false;
-
- if ( p_imp != nullptr
- && p_last != nullptr
- && ( chunk_is_token(p_last, CT_SEMICOLON)
- || p_imp->flags.test(PCF_IN_PREPROC)))
- {
- if (num_chunks < max_number_to_sort)
- {
- LOG_FMT(LSORT, "%s(%d): p_imp is %s\n",
- __func__, __LINE__, p_imp->text());
- chunks[num_chunks++] = p_imp;
- }
- else
- {
- fprintf(stderr, "Number of 'import' to be sorted is too big for the current value %d.\n", max_number_to_sort);
- fprintf(stderr, "Please make a report.\n");
- log_flush(true);
- cpd.error_count++;
- exit(2);
- }
- did_import = true;
- }
- log_rule_B("mod_sort_incl_import_grouping_enabled");
-
- if ( !did_import
- || ( !options::mod_sort_incl_import_grouping_enabled()
- && pc->nl_count > 1)
- || ( options::mod_sort_incl_import_grouping_enabled()
- && p_imp_last != nullptr
- && (pc->orig_line - p_imp_last->orig_line) > max_gap_threshold_between_include_to_sort)
- || next == nullptr)
- {
- if (num_chunks > 1)
- {
- log_rule_B("mod_sort_incl_import_grouping_enabled");
-
- if (options::mod_sort_incl_import_grouping_enabled())
- {
- remove_blank_lines_between_imports(chunks, num_chunks);
- do_the_sort(chunks, num_chunks);
- group_imports_by_adding_newlines(chunks, num_chunks);
- dedupe_imports(chunks, num_chunks);
- }
- else
- {
- do_the_sort(chunks, num_chunks);
- }
- }
- num_chunks = 0;
- }
- p_imp_last = p_imp;
- p_imp = nullptr;
- p_last = nullptr;
- }
- else if (chunk_is_token(pc, CT_IMPORT))
- {
- log_rule_B("mod_sort_import");
-
- if (options::mod_sort_import())
- {
- p_imp = chunk_get_next(pc);
- }
- }
- else if (chunk_is_token(pc, CT_USING))
- {
- log_rule_B("mod_sort_using");
-
- if (options::mod_sort_using())
- {
- p_imp = chunk_get_next(pc);
- }
- }
- else if (chunk_is_token(pc, CT_PP_INCLUDE))
- {
- log_rule_B("mod_sort_include");
-
- if (options::mod_sort_include())
- {
- p_imp = chunk_get_next(pc);
- p_last = pc;
- }
- }
- else if (!chunk_is_comment(pc))
- {
- p_last = pc;
- }
- pc = next;
- }
- cleanup_categories();
-} // sort_imports