17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-17 05:09:20 +02:00

Fix/sonar maintainability rebased (#209)

* refactor(sonar): use override instead of redundant virtual (cpp:S3471)

* refactor(sonar): remove empty statements, one declaration per statement (cpp:S1116, cpp:S1659)

* refactor(sonar): drop redundant lambda return types (cpp:S3574)

* refactor(sonar): prefer using over typedef (cpp:S5416)

* refactor(sonar): use =default for trivial special members (cpp:S3490)

* refactor(sonar): use nullptr literal (cpp:S4962)

* refactor(sonar): remove redundant access specifiers (cpp:S3539)

* refactor(sonar): remove redundant casts (cpp:S1905)

* refactor(sonar): use std::scoped_lock instead of std::lock_guard (cpp:S5997)

* refactor(sonar): construct elements in place with emplace_back (cpp:S6003)

* refactor(sonar): make narrowing conversions explicit (cpp:S5276)

* refactor(sonar): mark unused parameters (cpp:S1172)

Unused names are commented out; parameters used only on some platforms
are marked [[maybe_unused]].

* refactor(sonar): declare non-mutating member functions const (cpp:S5817)

Virtual functions are left untouched so overrides keep matching.

* refactor(sonar): merge collapsible nested if statements (cpp:S1066)

Comments that preceded the inner if are kept above the merged statement.

* refactor(sonar): scope single-use variables in if init-statements (cpp:S6004)

* fix(sonar): give polymorphic base classes virtual destructors (cpp:S1235)

* refactor(sonar): use try_emplace for map insertion (cpp:S6030)

* refactor(sonar): use auto where the type is spelled out on the right (cpp:S5827)

* refactor(sonar): remove redundant parentheses (cpp:S1110)

* refactor(sonar): document intentionally empty functions (cpp:S1186)

* refactor(sonar): remove dead stores (cpp:S1854)

Side effects (e.g. LISTLINE++) are kept.

* refactor(sonar): remove unused variables, captures and private fields (cpp:S1481, cpp:S1068)

* refactor(sonar): use structured bindings for pair access (cpp:S6005)

* refactor(sonar): use range-based loops and ranges algorithms (cpp:S5566)

* refactor(sonar): split chained assignments (cpp:S1121)

* refactor(sonar): add default cases to switch statements (cpp:S3562)

* refactor(sonar): use std::size for array lengths (cpp:S7127)

* refactor(sonar): use std::ranges algorithms and std::erase(_if) (cpp:S6197)

* refactor(sonar): access static members through the class (cpp:S2209)

* refactor(sonar): add braces around nested if-else (cpp:S5261)

* refactor(sonar): avoid side effects inside typeid operands (cpp:S5279)

* refactor(sonar): drop top-level const from by-value return types (cpp:S5951)

* refactor(sonar): declare variables separately from their type definitions (cpp:S3646)

* refactor(sonar): declare loop counters in the for statement (cpp:S5955)

* refactor(sonar): rely on class template argument deduction (cpp:S6012)

* refactor(sonar): inherit base constructors instead of forwarding them (cpp:S5952)

* refactor(sonar): rename locals that shadow outer declarations (cpp:S1117)

Only local variables and definition parameters are renamed; shadowing
struct fields and enumerators in headers are left for a separate change.

* refactor(sonar): reduce enum qualification with using enum (cpp:S6177)

Applied only where no unqualified name in the block could be captured by
the introduced enumerators.

* refactor(sonar): mark converting constructors explicit (cpp:S1709)

sound_source and the gl::object conversion operators stay implicit; they
are relied upon by copy-list-initialisation and GL calls.

* refactor(sonar): initialise members in initialiser lists or declarations (cpp:S3230)

* refactor(sonar): make read-only local references and pointers const (cpp:S5350)

* refactor(sonar): take read-only pointer and reference parameters as const (cpp:S995)

TTrain command handlers keep their signature, it is fixed by the handler table.

* refactor(sonar): pass expensive-to-copy parameters by const reference (cpp:S1238)

Signatures declared in files touched by PR 206 (Driver.h, EU07.cpp) and
virtual overrides are left unchanged.

* refactor(sonar): use transparent comparators for string-keyed maps (cpp:S6045)

std::unordered_map instances and map types exposed in headers used by
other modules are left as they are.

* fix(sonar): do not use UI text as a printf format string (cpp:S5281)

Text lines containing '%' would otherwise be interpreted as format
specifiers by ImGui::TextColored.

* refactor(sonar): use std::bind_front for callbacks (cpp:S5995)

* refactor(sonar): drop const_cast on string literals passed to the Python C API (cpp:S859)

* refactor(sonar): take read-only string parameters as std::string_view (cpp:S6009)

The Windows messaging helpers keep std::string, they need c_str().

* refactor(sonar): make read-only global tables const (cpp:S5421)

Mutable global state (flags, timers, singletons) is left as is.

* refactor(sonar): replace single-case switch statements with if (cpp:S1301)

* refactor(sonar): format UUIDs and log timestamps with std::format (cpp:S6494, cpp:S5945)

* refactor(sonar): use std::array for local fixed-size arrays (cpp:S5945)

Arrays that are class members or part of headers are left unchanged.

* fix(sonar): test the bearing damage bit, not bit 0 (cpp:S872)

'DamageFlag & dtrain_bearing > 0' parsed as 'DamageFlag & (dtrain_bearing > 0)',
i.e. DamageFlag & 1, so bearing friction reacted to the wrong damage flag.

* refactor(sonar): assorted small fixes

- empty() instead of size() comparisons (cpp:S1155)
- member initialisers in declaration order (cpp:S3229)
- no redundant c_str() when a std::string is accepted (cpp:S7121)
- contains() on associative containers (cpp:S6171)
- const reference instead of a copying range-for (cpp:S6032)
- starts_with() for prefix checks (cpp:S6178)
- no std::move on temporaries (cpp:S5274)
- has_value() on std::optional (cpp:S7172)
- bool literals for bool members (cpp:S5820)
- inline only on the definition (cpp:S3548)
- explicit base access specifier (cpp:S5965)
- explicit element access instead of dereferencing an array (cpp:S7116)
- rely on the C++20 rewritten operator!= (cpp:S6186)

* refactor(sonar): more small fixes

- std::format instead of iostream manipulators in to_string/to_hex_str (cpp:S6495);
  output verified identical, negative hex values keep the unsigned form
- remove an empty compound statement (cpp:S108)
- drop an always-false unsigned < 0 branch (cpp:S1768)
- explicit lambda capture (cpp:S3608)
- std::make_unique (cpp:S5950)

* chore: strip stray carriage returns left in TTrain constructor comments

* fix: keep quantize() in its own value type

The S5276 change cast the result of the generic quantize<Type_>() to
unsigned int, which truncated float/double callers (shadow angle slider,
editor rotation snapping, AI speed control steps) and broke negative values.

* fix(sonar): use integer loop counters in segment sampling (cpp:S2193)

* refactor(sonar): clean up issues reported on PR 209

- remove locals left unused after the dead-store cleanup (cpp:S1481, cpp:S1854)
- unnamed unused parameter (cpp:S1172)
- single-use declarations moved into if init-statements (cpp:S6004)
- auto for casted initialisers (cpp:S5827)
- const references and pointers where nothing is modified (cpp:S5350)
- rename structured bindings shadowed by inner declarations (cpp:S1117)
This commit is contained in:
jerrrrycho
2026-10-11 13:22:33 +02:00
committed by GitHub
parent c26041f2e7
commit 6263fe539b
162 changed files with 4220 additions and 4598 deletions

View File

@@ -30,36 +30,36 @@ void render_task::run()
cancel();
return;
}
for (auto const &datapair : m_input->floats)
for (auto const &[dataname, datavalue] : m_input->floats)
{
auto *value{PyGetFloat(datapair.second)};
auto *value{PyGetFloat(datavalue)};
if (value == nullptr)
{
PyErr_Clear();
continue;
}
PyDict_SetItemString(input, datapair.first.c_str(), value);
PyDict_SetItemString(input, dataname.c_str(), value);
Py_DECREF(value);
}
for (auto const &datapair : m_input->integers)
for (auto const &[dataname, datavalue] : m_input->integers)
{
auto *value{PyLong_FromLong(datapair.second)};
auto *value{PyLong_FromLong(datavalue)};
if (value == nullptr)
{
PyErr_Clear();
continue;
}
PyDict_SetItemString(input, datapair.first.c_str(), value);
PyDict_SetItemString(input, dataname.c_str(), value);
Py_DECREF(value);
}
for (auto const &datapair : m_input->bools)
for (auto const &[dataname, datavalue] : m_input->bools)
{
// Py_True / Py_False sa niesmiertelne, ale PyDict_SetItemString i tak
// pobiera wlasna referencje - nie zwalniamy
auto *value{PyGetBool(datapair.second)};
PyDict_SetItemString(input, datapair.first.c_str(), value);
auto *value{PyGetBool(datavalue)};
PyDict_SetItemString(input, dataname.c_str(), value);
}
for (auto const &datapair : m_input->strings)
for (auto const &[dataname, datavalue] : m_input->strings)
{
// Nazwy scenerii/wagonow (asName, SceneryFile, asCarName, cCode...) moga
// byc albo w UTF-8, albo w starym kodowaniu Windows-1250. PyUnicode_FromString
@@ -68,8 +68,8 @@ void render_task::run()
//
// Strategia: najpierw probujemy UTF-8 (strict). Jesli sie nie uda - probujemy
// cp1250. Jesli oba zawioda - pomijamy klucz, ale nie wywracamy symulatora.
char const *const str{datapair.second.c_str()};
Py_ssize_t const len{static_cast<Py_ssize_t>(datapair.second.size())};
char const *const str{datavalue.c_str()};
Py_ssize_t const len{static_cast<Py_ssize_t>(datavalue.size())};
auto *value{PyUnicode_DecodeUTF8(str, len, "strict")};
if (value == nullptr)
@@ -82,16 +82,16 @@ void render_task::run()
PyErr_Clear();
continue;
}
PyDict_SetItemString(input, datapair.first.c_str(), value);
PyDict_SetItemString(input, dataname.c_str(), value);
Py_DECREF(value);
}
for (auto const &datapair : m_input->vec2_lists)
for (auto const &[dataname, datavalue] : m_input->vec2_lists)
{
PyObject *list = PyList_New(datapair.second.size());
PyObject *list = PyList_New(datavalue.size());
for (size_t i = 0; i < datapair.second.size(); i++)
for (size_t i = 0; i < datavalue.size(); i++)
{
auto const &vec = datapair.second[i];
auto const &vec = datavalue[i];
WriteLog("passing " + glm::to_string(vec));
PyObject *tuple = PyTuple_New(2);
@@ -101,24 +101,24 @@ void render_task::run()
PyList_SetItem(list, i, tuple); // steals ref
}
PyDict_SetItemString(input, datapair.first.c_str(), list);
PyDict_SetItemString(input, dataname.c_str(), list);
Py_DECREF(list);
}
m_input = nullptr;
// call the renderer
auto *output{PyObject_CallMethod(m_renderer, const_cast<char *>("render"), const_cast<char *>("O"), input)};
auto *output{PyObject_CallMethod(m_renderer, "render", "O", input)};
Py_DECREF(input);
if (output != nullptr)
{
auto *outputWidth = PyObject_CallMethod(m_renderer, const_cast<char *>("get_width"), nullptr);
auto *outputHeight = PyObject_CallMethod(m_renderer, const_cast<char *>("get_height"), nullptr);
auto *outputWidth = PyObject_CallMethod(m_renderer, "get_width", nullptr);
auto *outputHeight = PyObject_CallMethod(m_renderer, "get_height", nullptr);
if (outputWidth != nullptr && outputHeight != nullptr && m_target != nullptr)
{
const int screenWidth = static_cast<int>(PyLong_AsLong(outputWidth));
const int screenHeight = static_cast<int>(PyLong_AsLong(outputHeight));
const auto screenWidth = static_cast<int>(PyLong_AsLong(outputWidth));
const auto screenHeight = static_cast<int>(PyLong_AsLong(outputHeight));
const bool useRgb = false && !Global.gfx_usegles;
@@ -166,7 +166,7 @@ void render_task::run()
}
// get commands from renderer
auto *commandsPO = PyObject_CallMethod(m_renderer, const_cast<char *>("getCommands"), nullptr);
auto *commandsPO = PyObject_CallMethod(m_renderer, "getCommands", nullptr);
if (commandsPO != nullptr)
{
std::vector<std::string> commands = python_external_utils::PyObjectToStringArray(commandsPO);
@@ -178,10 +178,10 @@ void render_task::run()
for (const auto &cmd : commands)
{
std::string baseCmd;
int p1 = 0, p2 = 0;
int p1 = 0;
int p2 = 0;
size_t pos1 = cmd.find(';');
if (pos1 == std::string::npos)
if (size_t pos1 = cmd.find(';'); pos1 == std::string::npos)
{
baseCmd = cmd;
}
@@ -224,7 +224,7 @@ void render_task::run()
}
}
void render_task::upload()
void render_task::upload() const
{
if (Global.python_uploadmain && m_target && m_target->shared_tex)
{
@@ -232,7 +232,7 @@ void render_task::upload()
}
}
void render_task::cancel() {}
void render_task::cancel() const { /* nothing to do */ }
// initializes the module. returns true on success
auto python_taskqueue::init() -> bool
@@ -310,7 +310,7 @@ auto python_taskqueue::init() -> bool
stringiomodule = PyImport_ImportModule("io");
stringioclassname = stringiomodule != nullptr ? PyObject_GetAttrString(stringiomodule, "StringIO") : nullptr;
stringioobject = stringioclassname != nullptr ? PyObject_CallObject(stringioclassname, nullptr) : nullptr;
m_stderr = {(stringioobject == nullptr ? nullptr : PySys_SetObject(const_cast<char *>("stderr"), stringioobject) != 0 ? nullptr : stringioobject)};
m_stderr = {(stringioobject == nullptr ? nullptr : PySys_SetObject("stderr", stringioobject) != 0 ? nullptr : stringioobject)};
if (false == run_file("abstractscreenrenderer"))
{
@@ -362,23 +362,23 @@ void python_taskqueue::exit()
// document intent. clearing the deque also actually releases the tasks,
// which the previous code did not do (cancel() is a no-op stub).
{
std::lock_guard<std::mutex> lock(m_tasks.mutex);
for (auto &task : m_tasks.data)
std::scoped_lock lock(m_tasks.mutex);
for (auto const &task : m_tasks.data)
{
task->cancel();
}
m_tasks.data.clear();
}
{
std::lock_guard<std::mutex> lock(m_uploadtasks.mutex);
std::scoped_lock lock(m_uploadtasks.mutex);
m_uploadtasks.data.clear();
}
// reclaim cached python objects while the interpreter is still alive,
// so no Py_DECREF lands on a finalized interpreter during later teardown
acquire_lock();
for (auto &entry : m_renderers)
for (auto const &[renderername, rendererobject] : m_renderers)
{
Py_XDECREF(entry.second);
Py_XDECREF(rendererobject);
}
m_renderers.clear();
Py_XDECREF(m_stderr);
@@ -394,7 +394,7 @@ void python_taskqueue::exit()
auto python_taskqueue::insert(task_request const &Task) -> bool
{
if (!m_initialized || false == Global.python_enabled || Task.renderer.empty() || Task.input == nullptr || Task.target == 0)
if (!m_initialized || false == Global.python_enabled || Task.renderer.empty() || Task.input == nullptr || Task.target == nullptr)
{
return false;
}
@@ -409,7 +409,7 @@ auto python_taskqueue::insert(task_request const &Task) -> bool
bool newtaskinserted{false};
// acquire a lock on the task queue and add the new task
{
std::lock_guard<std::mutex> lock(m_tasks.mutex);
std::scoped_lock lock(m_tasks.mutex);
// check the task list for a pending request with the same target
for (auto &task : m_tasks.data)
{
@@ -437,13 +437,13 @@ auto python_taskqueue::insert(task_request const &Task) -> bool
auto python_taskqueue::run_file(std::string const &File, std::string const &Path) -> bool
{
auto const lookup{FileExists({Path + File, "python/local/" + File}, {".py"})};
if (lookup.first.empty())
auto const [filepath, fileextension]{FileExists({Path + File, "python/local/" + File}, {".py"})};
if (filepath.empty())
{
return false;
}
std::ifstream inputfile{lookup.first + lookup.second};
std::ifstream inputfile{filepath + fileextension};
std::string input;
input.assign(std::istreambuf_iterator<char>(inputfile), std::istreambuf_iterator<char>());
@@ -464,17 +464,16 @@ void python_taskqueue::acquire_lock()
}
// releases the python gil and swaps the main thread out
void python_taskqueue::release_lock()
void python_taskqueue::release_lock() const
{
PyEval_SaveThread();
}
auto python_taskqueue::fetch_renderer(std::string const Renderer) -> PyObject *
auto python_taskqueue::fetch_renderer(std::string const &Renderer) -> PyObject *
{
auto const lookup{m_renderers.find(Renderer)};
if (lookup != std::end(m_renderers))
if (auto const lookup{m_renderers.find(Renderer)}; lookup != std::end(m_renderers))
{
return lookup->second;
}
@@ -510,7 +509,7 @@ auto python_taskqueue::fetch_renderer(std::string const Renderer) -> PyObject *
}
renderer = PyObject_CallObject(renderername, rendererarguments);
PyObject_CallMethod(renderer, const_cast<char *>("manul_set_format"), const_cast<char *>("(s)"), "RGBA");
PyObject_CallMethod(renderer, "manul_set_format", "(s)", "RGBA");
if (PyErr_Occurred() != nullptr)
{
@@ -527,11 +526,11 @@ auto python_taskqueue::fetch_renderer(std::string const Renderer) -> PyObject *
}
release_lock();
// cache the failures as well so we don't try again on subsequent requests
m_renderers.emplace(Renderer, renderer);
m_renderers.try_emplace(Renderer, renderer);
return renderer;
}
void python_taskqueue::run(GLFWwindow *Context, rendertask_sequence &Tasks, uploadtask_sequence &Upload_Tasks, threading::condition_variable &Condition, std::atomic<bool> &Exit)
void python_taskqueue::run(GLFWwindow *Context, rendertask_sequence &Tasks, uploadtask_sequence &Upload_Tasks, threading::condition_variable &Condition, std::atomic<bool> const &Exit)
{
if (Context)
@@ -554,7 +553,7 @@ void python_taskqueue::run(GLFWwindow *Context, rendertask_sequence &Tasks, uplo
task = nullptr;
// acquire a lock on the task queue and potentially grab a task from it
{
std::lock_guard<std::mutex> lock(Tasks.mutex);
std::scoped_lock lock(Tasks.mutex);
if (false == Tasks.data.empty())
{
// fifo
@@ -573,7 +572,7 @@ void python_taskqueue::run(GLFWwindow *Context, rendertask_sequence &Tasks, uplo
task->upload();
else
{
std::lock_guard<std::mutex> lock(Upload_Tasks.mutex);
std::scoped_lock lock(Upload_Tasks.mutex);
Upload_Tasks.data.push_back(task);
}
if (PyErr_Occurred() != nullptr)
@@ -608,9 +607,9 @@ void python_taskqueue::run(GLFWwindow *Context, rendertask_sequence &Tasks, uplo
void python_taskqueue::update()
{
std::lock_guard<std::mutex> lock(m_uploadtasks.mutex);
std::scoped_lock lock(m_uploadtasks.mutex);
for (auto &task : m_uploadtasks.data)
for (auto const &task : m_uploadtasks.data)
task->upload();
m_uploadtasks.data.clear();
@@ -622,21 +621,21 @@ void python_taskqueue::error()
{
// std err pythona jest buforowane
PyErr_Print();
auto *errortext{PyObject_CallMethod(m_stderr, const_cast<char *>("getvalue"), nullptr)};
if (errortext != nullptr)
if (auto *errortext{PyObject_CallMethod(m_stderr, "getvalue", nullptr)}; errortext != nullptr)
{
const char *errstr = PyUnicode_AsUTF8(errortext);
if (errstr != nullptr)
if (const char *errstr = PyUnicode_AsUTF8(errortext); errstr != nullptr)
ErrorLog(errstr);
Py_DECREF(errortext);
}
PyObject_CallMethod(m_stderr, const_cast<char *>("truncate"), const_cast<char *>("L"), (long long)0);
PyObject_CallMethod(m_stderr, const_cast<char *>("seek"), const_cast<char *>("L"), (long long)0);
PyObject_CallMethod(m_stderr, "truncate", "L", (long long)0);
PyObject_CallMethod(m_stderr, "seek", "L", (long long)0);
}
else
{
// nie dziala buffor pythona
PyObject *type, *value, *traceback;
PyObject *type;
PyObject *value;
PyObject *traceback;
PyErr_Fetch(&type, &value, &traceback);
if (type == nullptr)
{
@@ -647,11 +646,9 @@ void python_taskqueue::error()
{
ErrorLog("Python Interpreter: don't know how to handle null exception");
}
auto *typetext{PyObject_Str(type)};
if (typetext != nullptr)
if (auto *typetext{PyObject_Str(type)}; typetext != nullptr)
{
const char *s = PyUnicode_AsUTF8(typetext);
if (s)
if (const char *s = PyUnicode_AsUTF8(typetext); s)
ErrorLog(s);
Py_DECREF(typetext);
}
@@ -660,8 +657,7 @@ void python_taskqueue::error()
auto *valuetext{PyObject_Str(value)};
if (valuetext != nullptr)
{
const char *s = PyUnicode_AsUTF8(valuetext);
if (s)
if (const char *s = PyUnicode_AsUTF8(valuetext); s)
ErrorLog(s);
Py_DECREF(valuetext);
}
@@ -669,8 +665,7 @@ void python_taskqueue::error()
auto *tracebacktext{PyObject_Str(traceback)};
if (tracebacktext != nullptr)
{
const char *s = PyUnicode_AsUTF8(tracebacktext);
if (s)
if (const char *s = PyUnicode_AsUTF8(tracebacktext); s)
ErrorLog(s);
Py_DECREF(tracebacktext);
}
@@ -709,7 +704,7 @@ std::vector<std::string> python_external_utils::PyObjectToStringArray(PyObject *
return emptyIfError;
}
result.push_back(std::string(str));
result.emplace_back(str);
Py_DECREF(item); // Decrease reference count for the item
}