jak-project/lsp/lsp_util.cpp
Tyler Wilding 53277a65ad
LSP: A bunch of new OpenGOAL language features (#3437)
- Integrate the AST into the LSP, this makes parsing and tokenizing the
files much easier
- Consolidate most of the symbol info tracking in `goalc` to a single
map. Fixed some issues where the old map would never evict symbols when
re-compiling files. There is still some more to cleanup, but this now
can be used as an incrementally updated source-of-truth for the LSP
- re-compile files when they are saved. Ideally this would be done
everytime they are changed but that:
  - may be too aggressive
- goalc doesn't compile incrementally yet so it likely would be a worse
UX

Features added, see
https://github.com/open-goal/opengoal-vscode/issues/256
- Hover

![image](https://github.com/open-goal/jak-project/assets/13153231/58dadb5d-582c-4c1f-9ffe-eaa4c85a0255)

![image](https://github.com/open-goal/jak-project/assets/13153231/b383adde-57fc-462c-a256-b2de5c30ca9a)
- LSP Status fixed
- Type Hierarchy

![image](https://github.com/open-goal/jak-project/assets/13153231/8e681377-1d4e-4336-ad70-1695a4607340)
- Document Color

![image](https://github.com/open-goal/jak-project/assets/13153231/4e48ccd8-0ed1-4459-a133-5277561e4201)
- Document Symbols
![Screenshot 2024-03-27
004105](https://github.com/open-goal/jak-project/assets/13153231/8e655034-43c4-4261-b6e0-85de00cbfc7f)
- Completions
![Screenshot 2024-03-30
004504](https://github.com/open-goal/jak-project/assets/13153231/d123a187-af90-466b-9eb7-561b2ee97cd1)

---------

Co-authored-by: Hat Kid <6624576+Hat-Kid@users.noreply.github.com>
2024-03-30 19:49:07 -04:00

84 lines
2.2 KiB
C++

#include "lsp_util.h"
#include <sstream>
#include "common/util/string_util.h"
#include "fmt/core.h"
namespace lsp_util {
std::string url_encode(const std::string& value) {
std::ostringstream escaped;
escaped.fill('0');
escaped << std::hex;
for (std::string::const_iterator i = value.begin(), n = value.end(); i != n; ++i) {
std::string::value_type c = (*i);
// Keep alphanumeric and other accepted characters intact
if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~' || c == '/') {
escaped << c;
continue;
}
// Any other characters are percent-encoded
escaped << std::uppercase;
escaped << '%' << std::setw(2) << int((unsigned char)c);
escaped << std::nouppercase;
}
return escaped.str();
}
std::string url_decode(const std::string& input) {
std::ostringstream decoded;
for (std::size_t i = 0; i < input.length(); ++i) {
if (input[i] == '%') {
// Check if there are enough characters remaining
if (i + 2 < input.length()) {
// Convert the next two characters after '%' into an integer value
std::istringstream hexStream(input.substr(i + 1, 2));
int hexValue = 0;
hexStream >> std::hex >> hexValue;
// Append the decoded character to the result
decoded << static_cast<char>(hexValue);
// Skip the next two characters
i += 2;
}
} else if (input[i] == '+') {
// Replace '+' with space character ' '
decoded << ' ';
} else {
// Append the character as is
decoded << input[i];
}
}
return decoded.str();
}
LSPSpec::DocumentUri uri_from_path(fs::path path) {
auto path_str = file_util::convert_to_unix_path_separators(path.string());
// vscode works with proper URL encoded URIs for file paths
// which means we have to roll our own...
path_str = url_encode(path_str);
return fmt::format("file:///{}", path_str);
}
std::string uri_to_path(const LSPSpec::DocumentUri& uri) {
auto decoded_uri = url_decode(uri);
if (str_util::starts_with(decoded_uri, "file:///")) {
#ifdef _WIN32
decoded_uri = decoded_uri.substr(8);
#else
decoded_uri = decoded_uri.substr(7);
#endif
}
return decoded_uri;
}
} // namespace lsp_util