diff --git a/CMakePresets.json b/CMakePresets.json index 2e75ce28c..1fe236756 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -108,6 +108,16 @@ "description": "Build with Clang with Debug Symbols", "inherits": ["base-windows-debug", "base-clang"] }, + { + "name": "Debug-windows-clang-static", + "displayName": "Windows Static Debug (clang)", + "description": "Build with Clang as Debug but statically linked", + "inherits": ["base-windows-debug", "base-clang"], + "cacheVariables": { + "STATICALLY_LINK": "true", + "ZYDIS_BUILD_SHARED_LIB": "OFF" + } + }, { "name": "RelWithDebInfo-windows-clang", "displayName": "Windows RelWithDebInfo (clang)", diff --git a/common/util/FileUtil.cpp b/common/util/FileUtil.cpp index dc08cfed3..732515f1a 100644 --- a/common/util/FileUtil.cpp +++ b/common/util/FileUtil.cpp @@ -706,4 +706,24 @@ std::string make_screenshot_filepath(const GameVersion game_version, const std:: return file_path; } +std::string get_majority_file_line_endings(const std::string& file_contents) { + size_t lf_count = 0; + size_t crlf_count = 0; + + for (size_t i = 0; i < file_contents.size(); ++i) { + if (file_contents[i] == '\n') { + if (i > 0 && file_contents[i - 1] == '\r') { + crlf_count++; + } else { + lf_count++; + } + } + } + + if (crlf_count > lf_count) { + return "\r\n"; + } + return "\n"; +} + } // namespace file_util diff --git a/common/util/FileUtil.h b/common/util/FileUtil.h index b8ea71fcc..942a3d0e7 100644 --- a/common/util/FileUtil.h +++ b/common/util/FileUtil.h @@ -69,4 +69,5 @@ std::vector sort_filepaths(const std::vector& paths, const b /// Will overwrite the destination if it exists void copy_file(const fs::path& src, const fs::path& dst); std::string make_screenshot_filepath(const GameVersion game_version, const std::string& name = ""); +std::string get_majority_file_line_endings(const std::string& file_contents); } // namespace file_util diff --git a/common/util/string_util.cpp b/common/util/string_util.cpp index 6ae4bf29a..21e0c6340 100644 --- a/common/util/string_util.cpp +++ b/common/util/string_util.cpp @@ -102,6 +102,22 @@ std::vector split(const ::std::string& str, char delimiter) { return google_diff::split_string(str, delimiter); } +std::vector split_string(const std::string& str, const std::string& delimiter) { + std::vector parsed; + std::string::size_type pos = 0; + while (true) { + const std::string::size_type found = str.find(delimiter, pos); + if (found == std::string::npos) { + parsed.push_back(str.substr(pos)); + break; + } else { + parsed.push_back(str.substr(pos, found - pos)); + pos = found + delimiter.length(); + } + } + return parsed; +} + std::vector regex_get_capture_groups(const std::string& str, const std::string& regex) { std::vector groups; diff --git a/common/util/string_util.h b/common/util/string_util.h index 69706573a..b0aed57f5 100644 --- a/common/util/string_util.h +++ b/common/util/string_util.h @@ -18,7 +18,9 @@ int line_count(const std::string& str); bool valid_regex(const std::string& regex); std::string diff(const std::string& lhs, const std::string& rhs); /// Default splits on \n characters +/// DEPRECATED - stop using it, limited as it only takes a char std::vector split(const ::std::string& str, char delimiter = '\n'); +std::vector split_string(const std::string& str, const std::string& delimiter = "\n"); std::string join(const std::vector& strs, const std::string& join_with); std::vector regex_get_capture_groups(const std::string& str, const std::string& regex); bool replace(std::string& str, const std::string& from, const std::string& to); diff --git a/lsp/state/workspace.cpp b/lsp/state/workspace.cpp index 83f09153e..6447df0e4 100644 --- a/lsp/state/workspace.cpp +++ b/lsp/state/workspace.cpp @@ -295,7 +295,8 @@ void Workspace::stop_tracking_file(const LSPSpec::DocumentUri& file_uri) { WorkspaceOGFile::WorkspaceOGFile(const std::string& content, const GameVersion& game_version) : m_content(content), m_game_version(game_version) { - m_lines = str_util::split(content); + const auto line_ending = file_util::get_majority_file_line_endings(content); + m_lines = str_util::split_string(content, line_ending); lg::info("Added new OG file. {} lines with {} symbols and {} diagnostics", m_lines.size(), m_symbols.size(), m_diagnostics.size()); } @@ -322,24 +323,17 @@ std::optional WorkspaceOGFile::get_symbol_at_position( } WorkspaceIRFile::WorkspaceIRFile(const std::string& content) { - // Get all lines of file - std::string::size_type pos = 0; - std::string::size_type prev = 0; + const auto line_ending = file_util::get_majority_file_line_endings(content); + m_lines = str_util::split_string(content, line_ending); - // TODO - i hate this assignment inside a conditional, get rid of it - while ((pos = content.find("\r\n", prev)) != std::string::npos) { - std::string line = content.substr(prev, pos - prev); - m_lines.push_back(line); - // Run any checks on that line - find_all_types_path(line); - find_function_symbol(m_lines.size() - 1, line); - identify_diagnostics(m_lines.size() - 1, line); - prev = pos + 1; + for (int i = 0; i < m_lines.size(); i++) { + const auto& line = m_lines.at(i); + if (m_all_types_uri == "") { + find_all_types_path(line); + } + find_function_symbol(i, line); + identify_diagnostics(i, line); } - std::string line = content.substr(prev); - m_lines.push_back(line); - find_function_symbol(m_lines.size() - 1, line); - identify_diagnostics(m_lines.size() - 1, line); lg::info("Added new IR file. {} lines with {} symbols and {} diagnostics", m_lines.size(), m_symbols.size(), m_diagnostics.size());