#include "lua.hpp" #include "LuaCodeFormat.h" #ifdef _MSC_VER #define EXPORT __declspec(dllexport) #else #define EXPORT #endif std::string luaToString(lua_State* L, int idx) { if (lua_isstring(L, idx)) { return lua_tostring(L, idx); } else if (lua_isinteger(L, idx)) { return std::to_string(lua_tointeger(L, idx)); } else if (lua_isnumber(L, idx)) { return std::to_string(lua_tonumber(L, idx)); } else if (lua_isboolean(L, idx)) { return lua_toboolean(L, idx) ? "true" : "false"; } else { return "nil"; } } std::string GetDiagnosisString(DiagnosisType type) { switch (type) { case DiagnosisType::MaxLineWidth: return "MaxLineWidth"; case DiagnosisType::Indent: return "Indent"; case DiagnosisType::Align: return "Align"; case DiagnosisType::Blank: return "Blank"; case DiagnosisType::EndWithNewLine: return "EndWithNewLine"; case DiagnosisType::NameStyle: return "NameStyle"; case DiagnosisType::StatementLineSpace: return "StatementLineSpace"; case DiagnosisType::Spell: return "Spell"; } return ""; } int format(lua_State* L) { int top = lua_gettop(L); if (top < 2) { return 0; } if (lua_isstring(L, 1) && lua_isstring(L, 2)) { try { std::string filename = lua_tostring(L, 1); std::string text = lua_tostring(L, 2); LuaCodeFormat::ConfigMap configMap; if (top == 3 && lua_istable(L, 3)) { lua_pushnil(L); while (lua_next(L, -2) != 0) { auto key = luaToString(L, -2); auto value = luaToString(L, -1); if (key != "nil") { configMap.insert({key, value}); } lua_pop(L, 1); } } auto formattedText = LuaCodeFormat::GetInstance().Reformat(filename, std::move(text), configMap); if (formattedText.empty()) { lua_pushboolean(L, false); return 1; } lua_pushboolean(L, true); lua_pushlstring(L, formattedText.c_str(), formattedText.size()); return 2; } catch (std::exception& e) { std::string err = e.what(); lua_settop(L, top); lua_pushboolean(L, false); lua_pushlstring(L, err.c_str(), err.size()); return 2; } } return 0; } enum class UpdateType { Created = 1, Changed = 2, Deleted = 3 }; int range_format(lua_State* L) { int top = lua_gettop(L); if (top < 4) { return 0; } if (lua_isstring(L, 1) && lua_isstring(L, 2) && lua_isinteger(L, 3) && lua_isinteger(L, 4)) { try { std::string filename = lua_tostring(L, 1); std::string text = lua_tostring(L, 2); int startLine = lua_tointeger(L, 3); int endLine = lua_tointeger(L, 4); LuaCodeFormat::ConfigMap configMap; if (top == 5 && lua_istable(L, 5)) { lua_pushnil(L); while (lua_next(L, -2) != 0) { auto key = luaToString(L, -2); auto value = luaToString(L, -1); if (key != "nil") { configMap.insert({key, value}); } lua_pop(L, 1); } } LuaFormatRange range(startLine, endLine); auto formattedText = LuaCodeFormat::GetInstance().RangeFormat(filename, range, std::move(text), configMap); if (formattedText.empty()) { lua_pushboolean(L, false); return 1; } lua_pushboolean(L, true); lua_pushlstring(L, formattedText.c_str(), formattedText.size()); lua_pushinteger(L, range.StartLine); lua_pushinteger(L, range.EndLine); return 4; } catch (std::exception& e) { std::string err = e.what(); lua_settop(L, top); lua_pushboolean(L, false); lua_pushlstring(L, err.c_str(), err.size()); return 2; } } return 0; } int update_config(lua_State* L) { int top = lua_gettop(L); if (top < 3) { return 0; } if (lua_isinteger(L, 1) && lua_isstring(L, 2) && lua_isstring(L, 3)) { try { auto type = static_cast(lua_tointeger(L, 1)); std::string workspaceUri = lua_tostring(L, 2); std::string configPath = lua_tostring(L, 3); switch (type) { case UpdateType::Created: case UpdateType::Changed: { LuaCodeFormat::GetInstance().UpdateCodeStyle(workspaceUri, configPath); break; } case UpdateType::Deleted: { LuaCodeFormat::GetInstance().RemoveCodeStyle(workspaceUri); break; } } lua_pushboolean(L, true); return 1; } catch (std::exception& e) { std::string err = e.what(); lua_settop(L, top); lua_pushboolean(L, false); lua_pushlstring(L, err.c_str(), err.size()); return 2; } } return 0; } int diagnose_file(lua_State* L) { int top = lua_gettop(L); if (top < 2) { return 0; } if (lua_isstring(L, 1) && lua_isstring(L, 2)) { try { std::string filename = lua_tostring(L, 1); std::string text = lua_tostring(L, 2); auto result = LuaCodeFormat::GetInstance().Diagnose(filename, std::move(text)); if (!result.first) { lua_pushboolean(L, false); return 1; } auto& diagnosticInfos = result.second; lua_pushboolean(L, true); int count = 1; lua_newtable(L); for (auto& diagnosticInfo : diagnosticInfos) { // 诊断信息表 lua_newtable(L); //message { lua_pushstring(L, "message"); lua_pushlstring(L, diagnosticInfo.Message.c_str(), diagnosticInfo.Message.size()); lua_rawset(L, -3); lua_pushstring(L, "type"); lua_pushstring(L, GetDiagnosisString(diagnosticInfo.type).c_str()); lua_rawset(L, -3); } // range { lua_pushstring(L, "range"); //range table lua_newtable(L); lua_pushstring(L, "start"); // start table lua_newtable(L); lua_pushstring(L, "line"); lua_pushinteger(L, diagnosticInfo.Range.Start.Line); lua_rawset(L, -3); lua_pushstring(L, "character"); lua_pushinteger(L, diagnosticInfo.Range.Start.Character); lua_rawset(L, -3); lua_rawset(L, -3); // set start = {} lua_pushstring(L, "end"); // end table lua_newtable(L); lua_pushstring(L, "line"); lua_pushinteger(L, diagnosticInfo.Range.End.Line); lua_rawset(L, -3); lua_pushstring(L, "character"); lua_pushinteger(L, diagnosticInfo.Range.End.Character); lua_rawset(L, -3); lua_rawset(L, -3); // set end = {} lua_rawset(L, -3); // set range = {} } // 不确认lua会不会把他改成宏,所以不要在这里用++count lua_rawseti(L, -2, count); count++; } return 2; } catch (std::exception& e) { std::string err = e.what(); lua_settop(L, top); lua_pushboolean(L, false); lua_pushlstring(L, err.c_str(), err.size()); return 2; } } return 0; } int set_default_config(lua_State* L) { int top = lua_gettop(L); if (top != 1) { return 0; } if (lua_istable(L, 1)) { try { LuaCodeFormat::ConfigMap configMap; lua_pushnil(L); while (lua_next(L, - 2) != 0) { auto key = luaToString(L, -2); auto value = luaToString(L, -1); if (key != "nil") { configMap.insert({key, value}); } lua_pop(L, 1); } LuaCodeFormat::GetInstance().SetDefaultCodeStyle(configMap); lua_pushboolean(L, true); return 1; } catch (std::exception& e) { std::string err = e.what(); lua_settop(L, top); lua_pushboolean(L, false); lua_pushlstring(L, err.c_str(), err.size()); return 2; } } return 0; } int set_nonstandard_symbol(lua_State* L) { int top = lua_gettop(L); if (top != 2) { return 0; } if (lua_isstring(L, 1) && lua_istable(L, 2)) { try { std::string type = lua_tostring(L, 1); std::vector tokens; lua_pushnil(L); while (lua_next(L, -2) != 0) { auto value = luaToString(L, -1); tokens.push_back(value); lua_pop(L, 1); } lua_settop(L, top); LuaCodeFormat::GetInstance().SetSupportNonStandardSymbol(type, tokens); lua_pushboolean(L, true); return 1; } catch (std::exception& e) { std::string err = e.what(); lua_settop(L, top); lua_pushboolean(L, false); lua_pushlstring(L, err.c_str(), err.size()); return 2; } } return 0; } int spell_load_dictionary_from_path(lua_State* L) { int top = lua_gettop(L); if (top != 1) { return 0; } if (lua_isstring(L, 1)) { try { auto path = lua_tostring(L, 1); LuaCodeFormat::GetInstance().LoadSpellDictionary(path); lua_pushboolean(L, true); return 1; } catch (std::exception& e) { std::string err = e.what(); lua_settop(L, top); lua_pushboolean(L, false); lua_pushlstring(L, err.c_str(), err.size()); return 2; } } return 0; } int spell_load_dictionary_from_buffer(lua_State* L) { int top = lua_gettop(L); if (top != 1) { return 0; } if (lua_isstring(L, 1)) { try { auto dictionary = lua_tostring(L, 1); LuaCodeFormat::GetInstance().LoadSpellDictionaryFromBuffer(dictionary); lua_pushboolean(L, true); return 1; } catch (std::exception& e) { std::string err = e.what(); lua_settop(L, top); lua_pushboolean(L, false); lua_pushlstring(L, err.c_str(), err.size()); return 2; } } return 0; } int spell_analysis(lua_State* L) { int top = lua_gettop(L); if (top < 2) { return 0; } if (lua_isstring(L, 1) && lua_isstring(L, 2)) { try { std::string filename = lua_tostring(L, 1); std::string text = lua_tostring(L, 2); CodeSpellChecker::CustomDictionary tempDict; if (top == 3 && lua_istable(L, 3)) { lua_pushnil(L); while (lua_next(L, -2) != 0) { auto value = luaToString(L, -1); tempDict.insert(value); lua_pop(L, 1); } } auto diagnosticInfos = LuaCodeFormat::GetInstance().SpellCheck(filename, std::move(text), tempDict); lua_pushboolean(L, true); int count = 1; lua_newtable(L); for (auto& diagnosticInfo : diagnosticInfos) { // 诊断信息表 lua_newtable(L); //message { lua_pushstring(L, "message"); lua_pushlstring(L, diagnosticInfo.Message.c_str(), diagnosticInfo.Message.size()); lua_rawset(L, -3); lua_pushstring(L, "type"); lua_pushstring(L, GetDiagnosisString(diagnosticInfo.type).c_str()); lua_rawset(L, -3); lua_pushstring(L, "data"); lua_pushstring(L, diagnosticInfo.Data.c_str()); lua_rawset(L, -3); } // range { lua_pushstring(L, "range"); //range table lua_newtable(L); lua_pushstring(L, "start"); // start table lua_newtable(L); lua_pushstring(L, "line"); lua_pushinteger(L, diagnosticInfo.Range.Start.Line); lua_rawset(L, -3); lua_pushstring(L, "character"); lua_pushinteger(L, diagnosticInfo.Range.Start.Character); lua_rawset(L, -3); lua_rawset(L, -3); // set start = {} lua_pushstring(L, "end"); // end table lua_newtable(L); lua_pushstring(L, "line"); lua_pushinteger(L, diagnosticInfo.Range.End.Line); lua_rawset(L, -3); lua_pushstring(L, "character"); lua_pushinteger(L, diagnosticInfo.Range.End.Character); lua_rawset(L, -3); lua_rawset(L, -3); // set end = {} lua_rawset(L, -3); // set range = {} } // 不确认lua会不会把他改成宏,所以不要在这里用++count lua_rawseti(L, -2, count); count++; } return 2; } catch (std::exception& e) { std::string err = e.what(); lua_settop(L, top); lua_pushboolean(L, false); lua_pushlstring(L, err.c_str(), err.size()); return 2; } } return 0; } int spell_suggest(lua_State* L) { int top = lua_gettop(L); if (top != 1) { return 0; } if (lua_isstring(L, 1)) { try { std::string word = lua_tostring(L, 1); auto suggests = LuaCodeFormat::GetInstance().SpellCorrect(word); int count = 1; lua_newtable(L); for (auto& suggest : suggests) { if (!suggest.Term.empty()) { lua_pushstring(L, suggest.Term.c_str()); lua_rawseti(L, -2, count); count++; } // 15个已经可以了 if (count == 15) { break; } } return 2; } catch (std::exception& e) { std::string err = e.what(); lua_settop(L, top); lua_pushboolean(L, false); lua_pushlstring(L, err.c_str(), err.size()); return 2; } } return 0; } static const luaL_Reg lib[] = { {"format", format}, {"range_format", range_format}, {"update_config", update_config}, {"diagnose_file", diagnose_file}, {"set_default_config", set_default_config}, {"spell_load_dictionary_from_path", spell_load_dictionary_from_path}, {"spell_load_dictionary_from_buffer", spell_load_dictionary_from_buffer}, {"spell_analysis", spell_analysis}, {"spell_suggest", spell_suggest}, {"set_nonstandard_symbol", set_nonstandard_symbol}, {nullptr, nullptr} }; extern "C" EXPORT int luaopen_code_format(lua_State* L) { luaL_newlibtable(L, lib); luaL_setfuncs(L, lib, 0); return 1; }