♻️ 使用module重构所有代码
This commit is contained in:
@@ -1,166 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <spdlog/sinks/stdout_sinks.h>
|
||||
#include <spdlog/sinks/basic_file_sink.h>
|
||||
#include "./args_parser.hpp"
|
||||
|
||||
namespace lsp::utils
|
||||
{
|
||||
ArgsParser& ArgsParser::Instance()
|
||||
{
|
||||
static ArgsParser instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
const ServerConfig& ArgsParser::Parse(int argc, char* argv[])
|
||||
{
|
||||
config_ = ServerConfig {};
|
||||
bool use_stdio = false;
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
std::string arg = argv[i];
|
||||
|
||||
if (arg == "--help")
|
||||
{
|
||||
config_.show_help = true;
|
||||
return config_;
|
||||
}
|
||||
|
||||
if (arg == "--log=trace")
|
||||
config_.log_level = spdlog::level::trace;
|
||||
else if (arg == "--log=debug")
|
||||
config_.log_level = spdlog::level::debug;
|
||||
else if (arg == "--log=info")
|
||||
config_.log_level = spdlog::level::info;
|
||||
else if (arg == "--log=warn")
|
||||
config_.log_level = spdlog::level::warn;
|
||||
else if (arg == "--log=error")
|
||||
config_.log_level = spdlog::level::err;
|
||||
else if (arg == "--log=off")
|
||||
config_.log_level = spdlog::level::off;
|
||||
else if (arg.find("--log-file=") == 0)
|
||||
config_.log_file = arg.substr(11);
|
||||
else if (arg == "--log-stderr")
|
||||
config_.use_stderr = true;
|
||||
else if (arg.find("--interpreter=") == 0)
|
||||
config_.interpreter_path = arg.substr(14);
|
||||
else if (arg.find("--threads=") == 0)
|
||||
{
|
||||
std::string count_str = arg.substr(10);
|
||||
try
|
||||
{
|
||||
size_t count = std::stoul(count_str);
|
||||
if (count == 0 || count > 32)
|
||||
{
|
||||
std::cerr << "[TSL-LSP] Error: Thread count must be between 1 and 32" << std::endl;
|
||||
std::exit(1);
|
||||
}
|
||||
config_.thread_count = count;
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
std::cerr << "[TSL-LSP] Error: Invalid thread count: " << count_str << std::endl;
|
||||
std::exit(1);
|
||||
}
|
||||
}
|
||||
else if (arg == "--stdio")
|
||||
{
|
||||
use_stdio = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "[TSL-LSP] Error: Unknown argument: " << arg << std::endl;
|
||||
std::cerr << "Use --help for usage information" << std::endl;
|
||||
}
|
||||
}
|
||||
std::cerr << "TSL Language Server " << __DATE__ << std::endl;
|
||||
if (use_stdio)
|
||||
std::cerr << "[TSL-LSP] JosnRPc using stdio" << std::endl;
|
||||
|
||||
// config_.interpreter_path = "/mnt/c/Programs/Tinysoft/TSLGen2/";
|
||||
return config_;
|
||||
}
|
||||
|
||||
const ServerConfig& ArgsParser::GetConfig() const
|
||||
{
|
||||
return config_;
|
||||
}
|
||||
|
||||
void ArgsParser::SetupLogger(const ServerConfig& config)
|
||||
{
|
||||
std::vector<spdlog::sink_ptr> sinks;
|
||||
|
||||
if (config.use_stderr)
|
||||
sinks.push_back(std::make_shared<spdlog::sinks::stderr_sink_mt>());
|
||||
|
||||
if (!config.log_file.empty())
|
||||
{
|
||||
try
|
||||
{
|
||||
sinks.push_back(std::make_shared<spdlog::sinks::basic_file_sink_mt>(config.log_file, true));
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << "[TSL-LSP] Failed to create log file: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
auto logger = std::make_shared<spdlog::logger>("tsl_lsp", sinks.begin(), sinks.end());
|
||||
logger->set_level(config.log_level);
|
||||
logger->set_pattern("[%Y-%m-%d %H:%M:%S] [%^%l%$] %v");
|
||||
|
||||
spdlog::set_default_logger(logger);
|
||||
spdlog::flush_on(spdlog::level::warn);
|
||||
}
|
||||
|
||||
void ArgsParser::PrintHelp(const std::string& program_name)
|
||||
{
|
||||
// 获取硬件线程数
|
||||
size_t hardware_threads = std::thread::hardware_concurrency();
|
||||
if (hardware_threads == 0)
|
||||
hardware_threads = 0; // 表示无法检测
|
||||
|
||||
std::cout << "TSL Language Server Protocol (LSP) Server\n"
|
||||
<< "Version: " << __DATE__ << " build\n"
|
||||
<< "\n"
|
||||
<< "Usage: " << program_name << " [options]\n"
|
||||
<< "\n"
|
||||
<< "Options:\n"
|
||||
<< " --help Show this help message and exit\n"
|
||||
<< "\n"
|
||||
<< "Interpreter options:\n"
|
||||
<< " --interpreter=PATH Set path to TSL interpreter executable\n"
|
||||
<< " Required for some language features\n"
|
||||
<< "\n"
|
||||
<< "Logging options:\n"
|
||||
<< " --log=LEVEL Set log level (trace, debug, info, warn, error, off)\n"
|
||||
<< " Default: info\n"
|
||||
<< " --log-file=PATH Write logs to file at PATH\n"
|
||||
<< " --log-stderr Output logs to stderr\n"
|
||||
<< "\n"
|
||||
<< "Performance options:\n"
|
||||
<< " --threads=N Set number of worker threads (1-32)\n"
|
||||
<< " Default: 4\n";
|
||||
|
||||
// 显示硬件信息
|
||||
if (hardware_threads > 0)
|
||||
std::cout << " Hardware threads available: " << hardware_threads << "\n";
|
||||
else
|
||||
std::cout << " Hardware threads: unable to detect\n";
|
||||
|
||||
std::cout << "\n"
|
||||
<< "Examples:\n"
|
||||
<< " # Run with debug logging to stderr\n"
|
||||
<< " " << program_name << " --log=debug --log-stderr\n"
|
||||
<< "\n"
|
||||
<< " # Run with 8 worker threads and log to file\n"
|
||||
<< " " << program_name << " --threads=8 --log-file=server.log\n"
|
||||
<< "\n"
|
||||
<< " # Run with maximum hardware threads\n";
|
||||
|
||||
if (hardware_threads > 0)
|
||||
std::cout << " " << program_name << " --threads=" << hardware_threads << "\n";
|
||||
else
|
||||
std::cout << " " << program_name << " --threads=16 # adjust based on your CPU\n";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
module;
|
||||
|
||||
#include <spdlog/sinks/basic_file_sink.h>
|
||||
#include <spdlog/sinks/stdout_sinks.h>
|
||||
|
||||
export module lsp.utils.args_parser;
|
||||
import spdlog;
|
||||
|
||||
import std;
|
||||
|
||||
export namespace lsp::utils
|
||||
{
|
||||
struct ServerConfig
|
||||
{
|
||||
bool use_stderr = false;
|
||||
bool show_help = false;
|
||||
std::size_t thread_count = 4;
|
||||
spdlog::level::level_enum log_level = spdlog::level::info;
|
||||
std::string log_file;
|
||||
std::string interpreter_path;
|
||||
};
|
||||
|
||||
class ArgsParser
|
||||
{
|
||||
public:
|
||||
ArgsParser(const ArgsParser&) = delete;
|
||||
ArgsParser& operator=(const ArgsParser&) = delete;
|
||||
static ArgsParser& Instance();
|
||||
|
||||
const ServerConfig& Parse(int argc, char* argv[]);
|
||||
const ServerConfig& GetConfig() const;
|
||||
|
||||
static void SetupLogger(const ServerConfig& config);
|
||||
static void PrintHelp(const std::string& program_name);
|
||||
|
||||
private:
|
||||
ArgsParser() = default;
|
||||
~ArgsParser() = default;
|
||||
|
||||
ServerConfig config_;
|
||||
};
|
||||
}
|
||||
|
||||
namespace lsp::utils
|
||||
{
|
||||
ArgsParser& ArgsParser::Instance()
|
||||
{
|
||||
static ArgsParser instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
const ServerConfig& ArgsParser::Parse(int argc, char* argv[])
|
||||
{
|
||||
config_ = ServerConfig{};
|
||||
bool use_stdio = false;
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
std::string arg = argv[i];
|
||||
|
||||
if (arg == "--help")
|
||||
{
|
||||
config_.show_help = true;
|
||||
return config_;
|
||||
}
|
||||
|
||||
if (arg == "--log=trace")
|
||||
config_.log_level = spdlog::level::trace;
|
||||
else if (arg == "--log=debug")
|
||||
config_.log_level = spdlog::level::debug;
|
||||
else if (arg == "--log=info")
|
||||
config_.log_level = spdlog::level::info;
|
||||
else if (arg == "--log=warn")
|
||||
config_.log_level = spdlog::level::warn;
|
||||
else if (arg == "--log=error")
|
||||
config_.log_level = spdlog::level::err;
|
||||
else if (arg == "--log=off")
|
||||
config_.log_level = spdlog::level::off;
|
||||
else if (arg.find("--log-file=") == 0)
|
||||
config_.log_file = arg.substr(std::strlen("--log-file="));
|
||||
else if (arg == "--use-stdio")
|
||||
use_stdio = true;
|
||||
else if (arg.find("--threads=") == 0)
|
||||
{
|
||||
auto value = arg.substr(std::strlen("--threads="));
|
||||
config_.thread_count = std::max<std::size_t>(1, static_cast<std::size_t>(std::stoi(value)));
|
||||
}
|
||||
else if (arg.find("--interpreter=") == 0)
|
||||
{
|
||||
config_.interpreter_path = arg.substr(std::strlen("--interpreter="));
|
||||
}
|
||||
}
|
||||
|
||||
if (!use_stdio)
|
||||
config_.use_stderr = true;
|
||||
|
||||
return config_;
|
||||
}
|
||||
|
||||
const ServerConfig& ArgsParser::GetConfig() const
|
||||
{
|
||||
return config_;
|
||||
}
|
||||
|
||||
void ArgsParser::SetupLogger(const ServerConfig& config)
|
||||
{
|
||||
spdlog::set_pattern("%Y-%m-%d %H:%M:%S.%e [%t] [%^%l%$] %v");
|
||||
|
||||
if (!config.log_file.empty())
|
||||
{
|
||||
auto file_logger = spdlog::basic_logger_mt("file_logger", config.log_file);
|
||||
file_logger->set_level(config.log_level);
|
||||
spdlog::set_default_logger(file_logger);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto console_logger = spdlog::stdout_logger_mt("console_logger");
|
||||
console_logger->set_level(config.log_level);
|
||||
spdlog::set_default_logger(console_logger);
|
||||
}
|
||||
|
||||
spdlog::set_level(config.log_level);
|
||||
}
|
||||
|
||||
void ArgsParser::PrintHelp(const std::string& program_name)
|
||||
{
|
||||
std::cout << "Usage: " << program_name << " [options]\\n\\n"
|
||||
<< "Options:\\n"
|
||||
<< " --help Show this help message\\n"
|
||||
<< " --log=<level> Set log level (trace, debug, info, warn, error, off)\\n"
|
||||
<< " --log-file=<path> Output logs to specified file\\n"
|
||||
<< " --use-stdio Use stdin/stdout for I/O (default: stderr)\\n"
|
||||
<< " --threads=<count> Number of worker threads\\n"
|
||||
<< " --interpreter=<path> Custom interpreter path\\n";
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
namespace lsp::utils
|
||||
{
|
||||
struct ServerConfig
|
||||
{
|
||||
bool use_stderr = false;
|
||||
bool show_help = false;
|
||||
size_t thread_count = 4;
|
||||
spdlog::level::level_enum log_level = spdlog::level::info;
|
||||
std::string log_file;
|
||||
std::string interpreter_path;
|
||||
};
|
||||
|
||||
class ArgsParser
|
||||
{
|
||||
public:
|
||||
ArgsParser(const ArgsParser&) = delete;
|
||||
ArgsParser& operator=(const ArgsParser&) = delete;
|
||||
static ArgsParser& Instance();
|
||||
|
||||
const ServerConfig& Parse(int argc, char* argv[]);
|
||||
const ServerConfig& GetConfig() const;
|
||||
|
||||
static void SetupLogger(const ServerConfig& config);
|
||||
static void PrintHelp(const std::string& program_name);
|
||||
|
||||
private:
|
||||
ArgsParser() = default;
|
||||
~ArgsParser() = default;
|
||||
|
||||
ServerConfig config_;
|
||||
};
|
||||
}
|
||||
@@ -1,14 +1,17 @@
|
||||
#include <algorithm>
|
||||
#include "./string.hpp"
|
||||
module;
|
||||
|
||||
import std;
|
||||
|
||||
module lsp.utils.string;
|
||||
|
||||
namespace lsp::utils
|
||||
{
|
||||
std::string Trim(const std::string& str)
|
||||
{
|
||||
size_t first = str.find_first_not_of(" \t\n\r");
|
||||
std::size_t first = str.find_first_not_of(" \t\n\r");
|
||||
if (first == std::string::npos)
|
||||
return "";
|
||||
size_t last = str.find_last_not_of(" \t\n\r");
|
||||
std::size_t last = str.find_last_not_of(" \t\n\r");
|
||||
return str.substr(first, last - first + 1);
|
||||
}
|
||||
|
||||
@@ -56,7 +59,7 @@ namespace lsp::utils
|
||||
if (prefix.size() > str.size())
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < prefix.size(); ++i)
|
||||
for (std::size_t i = 0; i < prefix.size(); ++i)
|
||||
{
|
||||
if (std::tolower(static_cast<unsigned char>(str[i])) !=
|
||||
std::tolower(static_cast<unsigned char>(prefix[i])))
|
||||
@@ -70,8 +73,8 @@ namespace lsp::utils
|
||||
if (suffix.size() > str.size())
|
||||
return false;
|
||||
|
||||
size_t offset = str.size() - suffix.size();
|
||||
for (size_t i = 0; i < suffix.size(); ++i)
|
||||
std::size_t offset = str.size() - suffix.size();
|
||||
for (std::size_t i = 0; i < suffix.size(); ++i)
|
||||
{
|
||||
if (std::tolower(static_cast<unsigned char>(str[offset + i])) !=
|
||||
std::tolower(static_cast<unsigned char>(suffix[i])))
|
||||
@@ -82,9 +85,9 @@ namespace lsp::utils
|
||||
|
||||
int ICompare(const std::string& a, const std::string& b)
|
||||
{
|
||||
size_t min_len = std::min(a.size(), b.size());
|
||||
std::size_t min_len = std::min(a.size(), b.size());
|
||||
|
||||
for (size_t i = 0; i < min_len; ++i)
|
||||
for (std::size_t i = 0; i < min_len; ++i)
|
||||
{
|
||||
int ca = std::tolower(static_cast<unsigned char>(a[i]));
|
||||
int cb = std::tolower(static_cast<unsigned char>(b[i]));
|
||||
@@ -102,11 +105,26 @@ namespace lsp::utils
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t IHash(const std::string& str)
|
||||
std::size_t IHash(const std::string& str)
|
||||
{
|
||||
size_t hash = 0;
|
||||
std::size_t hash = 0;
|
||||
for (unsigned char c : str)
|
||||
hash = hash * 31 + std::tolower(c);
|
||||
return hash;
|
||||
}
|
||||
|
||||
std::size_t IHasher::operator()(const std::string& key) const
|
||||
{
|
||||
return IHash(key);
|
||||
}
|
||||
|
||||
bool IEqualTo::operator()(const std::string& a, const std::string& b) const
|
||||
{
|
||||
return IEquals(a, b);
|
||||
}
|
||||
|
||||
bool ILess::operator()(const std::string& a, const std::string& b) const
|
||||
{
|
||||
return ICompare(a, b) < 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#pragma once
|
||||
module;
|
||||
|
||||
#include <string>
|
||||
export module lsp.utils.string;
|
||||
|
||||
namespace lsp::utils
|
||||
import std;
|
||||
|
||||
export namespace lsp::utils
|
||||
{
|
||||
// ==================== 字符串工具 ====================
|
||||
std::string Trim(const std::string& str);
|
||||
@@ -18,30 +20,21 @@ namespace lsp::utils
|
||||
bool IStartsWith(const std::string& str, const std::string& prefix);
|
||||
bool IEndsWith(const std::string& str, const std::string& suffix);
|
||||
int ICompare(const std::string& a, const std::string& b);
|
||||
size_t IHash(const std::string& str);
|
||||
std::size_t IHash(const std::string& str);
|
||||
|
||||
// ==================== STL 容器比较器 ====================
|
||||
struct IHasher
|
||||
{
|
||||
size_t operator()(const std::string& key) const
|
||||
{
|
||||
return IHash(key);
|
||||
}
|
||||
std::size_t operator()(const std::string& key) const;
|
||||
};
|
||||
|
||||
struct IEqualTo
|
||||
{
|
||||
bool operator()(const std::string& a, const std::string& b) const
|
||||
{
|
||||
return IEquals(a, b);
|
||||
}
|
||||
bool operator()(const std::string& a, const std::string& b) const;
|
||||
};
|
||||
|
||||
struct ILess
|
||||
{
|
||||
bool operator()(const std::string& a, const std::string& b) const
|
||||
{
|
||||
return ICompare(a, b) < 0;
|
||||
}
|
||||
bool operator()(const std::string& a, const std::string& b) const;
|
||||
};
|
||||
}
|
||||
+18
-2
@@ -1,5 +1,21 @@
|
||||
#include <algorithm>
|
||||
#include "./text_coordinates.hpp"
|
||||
module;
|
||||
|
||||
extern "C" {
|
||||
}
|
||||
|
||||
export module lsp.utils.text_coordinates;
|
||||
import tree_sitter;
|
||||
|
||||
import std;
|
||||
|
||||
import lsp.protocol;
|
||||
|
||||
export namespace lsp::utils::text_coordinates
|
||||
{
|
||||
protocol::uinteger ToOffset(const protocol::Position& position, const protocol::string& content);
|
||||
TSPoint ToPoint(const protocol::Position& position);
|
||||
TSPoint CalculateEndPoint(const protocol::string& text, TSPoint start);
|
||||
}
|
||||
|
||||
namespace lsp::utils::text_coordinates
|
||||
{
|
||||
@@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "../protocol/protocol.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include <tree_sitter/api.h>
|
||||
}
|
||||
|
||||
namespace lsp::utils::text_coordinates
|
||||
{
|
||||
protocol::uinteger ToOffset(const protocol::Position& position, const protocol::string& content);
|
||||
TSPoint ToPoint(const protocol::Position& position);
|
||||
TSPoint CalculateEndPoint(const protocol::string& text, TSPoint start);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user