#include "CodeFormat.h"
#include "CodeFormatCore/Config/LuaEditorConfig.h"
#include "CodeFormatCore/RangeFormat/RangeFormatBuilder.h"
#include "LuaParser/Parse/LuaParser.h"
#include "Util/StringUtil.h"
CodeFormat &CodeFormat::GetInstance() {
static CodeFormat instance;
return instance;
}
CodeFormat::CodeFormat()
: _supportNonStandardSymbol(false),
_supportCLikeComments(false) {
}
void CodeFormat::UpdateCodeStyle(const std::string &workspaceUri, const std::string &configPath) {
for (auto &config: _configs) {
if (config.Workspace == workspaceUri) {
config.Editorconfig = LuaEditorConfig::OpenFile(configPath);
return;
}
}
auto &config = _configs.emplace_back(
workspaceUri);
config.Editorconfig = LuaEditorConfig::OpenFile(configPath);
}
void CodeFormat::UpdateDiagnosticStyle(InfoTree &tree) {
_diagnosticStyle = LuaDiagnosticStyle();
_diagnosticStyle.ParseTree(tree);
_diagnosticStyle.code_style_check = true;
_diagnosticStyle.name_style_check = false;
_diagnosticStyle.spell_check = false;
}
void CodeFormat::RemoveCodeStyle(const std::string &workspaceUri) {
for (auto it = _configs.begin(); it != _configs.end(); it++) {
if (it->Workspace == workspaceUri) {
_configs.erase(it);
break;
}
}
}
void CodeFormat::SetDefaultCodeStyle(ConfigMap &configMap) {
if (!configMap.empty()) {
LuaStyle style;
style.Parse(configMap);
_defaultStyle = style;
}
}
void CodeFormat::SupportNonStandardSymbol() {
_supportNonStandardSymbol = true;
}
char *CodeFormat::Reformat(const std::string &uri, std::string &&text, FormattingOptions options) {
auto file = LuaSource::From(std::move(text));
LuaLexer luaLexer(file);
if (_supportNonStandardSymbol || options.non_standard_symbol) {
luaLexer.SupportNonStandardSymbol();
}
if (_supportCLikeComments || options.non_standard_symbol) {
luaLexer.SupportCLikeComments();
}
luaLexer.Parse();
LuaParser p(file, std::move(luaLexer.GetTokens()));
p.Parse();
if (p.HasError()) {
return nullptr;
}
LuaSyntaxTree t;
t.BuildTree(p);
LuaStyle style = GetStyle(uri);
SetupStyle(style, options);
FormatBuilder f(style);
auto result = f.GetFormatResult(t);
auto length = result.size();
char *ptr = new char[length + 1];
std::copy(result.begin(), result.end(), ptr);
ptr[length] = '\0';
return ptr;
}
Result<RangeFormatResult> CodeFormat::RangeFormat(const std::string &uri, FormatRange &range,
std::string &&text, FormattingOptions options) {
auto file = std::make_shared<LuaSource>(std::move(text));
LuaLexer luaLexer(file);
if (_supportNonStandardSymbol || options.non_standard_symbol) {
luaLexer.SupportNonStandardSymbol();
}
if (_supportCLikeComments || options.non_standard_symbol) {
luaLexer.SupportCLikeComments();
}
luaLexer.Parse();
LuaParser p(file, std::move(luaLexer.GetTokens()));
p.Parse();
if (p.HasError()) {
return ResultType::Err;
}
LuaSyntaxTree t;
t.BuildTree(p);
LuaStyle style = GetStyle(uri);
SetupStyle(style, options);
RangeFormatBuilder f(style, range);
auto formattedText = f.GetFormatResult(t);
range = f.GetReplaceRange();
char *ptr = new char[formattedText.size() + 1];
std::copy(formattedText.begin(), formattedText.end(), ptr);
ptr[formattedText.size()] = '\0'; return RangeFormatResult{
static_cast<int32_t>(range.StartLine),
static_cast<int32_t>(range.StartCol),
static_cast<int32_t>(range.EndLine),
static_cast<int32_t>(range.EndCol),
ptr};
}
void CodeFormat::SetupStyle(LuaStyle &style, const FormattingOptions &options) {
if (options.use_tabs) {
style.indent_style = IndentStyle::Tab;
style.tab_width = options.indent_size;
} else {
style.indent_style = IndentStyle::Space;
style.indent_size = options.indent_size;
}
style.insert_final_newline = options.insert_final_newline;
}
Result<std::vector<LuaTypeFormat::Result>>
CodeFormat::TypeFormat(const std::string &uri, std::size_t line, std::size_t character, std::string &&text) {
auto file = std::make_shared<LuaSource>(std::move(text));
LuaLexer luaLexer(file);
if (_supportNonStandardSymbol) {
luaLexer.SupportNonStandardSymbol();
}
if (_supportCLikeComments) {
luaLexer.SupportCLikeComments();
}
luaLexer.Parse();
LuaParser p(file, std::move(luaLexer.GetTokens()));
p.Parse();
if (p.HasError()) {
return ResultType::Err;
}
LuaSyntaxTree t;
t.BuildTree(p);
LuaStyle style = GetStyle(uri);
LuaTypeFormatFeatures typeFormatOptions;
typeFormatOptions.auto_complete_end = false;
LuaTypeFormat tf(typeFormatOptions);
tf.Analyze("\n", line, character, t, style);
return tf.GetResult();
}
Result<std::vector<LuaDiagnosticInfo>> CodeFormat::Diagnostic(const std::string &uri, std::string &&text) {
auto file = std::make_shared<LuaSource>(std::move(text));
LuaLexer luaLexer(file);
if (_supportNonStandardSymbol) {
luaLexer.SupportNonStandardSymbol();
}
if (_supportCLikeComments) {
luaLexer.SupportCLikeComments();
}
luaLexer.Parse();
LuaParser p(file, std::move(luaLexer.GetTokens()));
p.Parse();
if (p.HasError()) {
return ResultType::Err;
}
LuaSyntaxTree t;
t.BuildTree(p);
LuaStyle style = GetStyle(uri);
DiagnosticBuilder diagnosticBuilder(style, _diagnosticStyle);
diagnosticBuilder.CodeStyleCheck(t);
return MakeDiagnosticInfo(diagnosticBuilder.GetDiagnosticResults(t), file);
}
LuaStyle &CodeFormat::GetStyle(const std::string &uri) {
std::shared_ptr<LuaEditorConfig> editorConfig = nullptr;
std::size_t matchProcess = 0;
for (auto &config: _configs) {
if (string_util::StartWith(uri, config.Workspace)) {
if (config.Workspace.size() > matchProcess) {
matchProcess = config.Workspace.size();
editorConfig = config.Editorconfig;
}
}
}
if (editorConfig) {
return editorConfig->Generate(uri);
}
return _defaultStyle;
}
std::vector<LuaDiagnosticInfo> CodeFormat::MakeDiagnosticInfo(const std::vector<LuaDiagnostic> &diagnostics,
std::shared_ptr<LuaSource> file) {
std::vector<LuaDiagnosticInfo> results;
for (auto &diagnostic: diagnostics) {
auto &result = results.emplace_back();
result.Type = diagnostic.Type;
result.Message = diagnostic.Message;
result.Data = diagnostic.Data;
result.Start.Line = file->GetLine(diagnostic.Range.StartOffset);
result.Start.Col = file->GetColumn(diagnostic.Range.StartOffset);
result.End.Line = file->GetLine(diagnostic.Range.GetEndOffset());
result.End.Col = file->GetColumn(diagnostic.Range.GetEndOffset()) + 1;
}
return results;
}