mirror of
https://github.com/Palm1r/QodeAssist.git
synced 2025-11-12 21:12:44 -05:00
fix: Add tool exception for logging purpose
This commit is contained in:
@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "EditProjectFileTool.hpp"
|
||||
#include "ToolExceptions.hpp"
|
||||
|
||||
#include <coreplugin/documentmanager.h>
|
||||
#include <logger/Logger.hpp>
|
||||
@ -133,13 +134,13 @@ QFuture<QString> EditProjectFileTool::executeAsync(const QJsonObject &input)
|
||||
QString filename = input["filename"].toString();
|
||||
if (filename.isEmpty()) {
|
||||
QString error = "Error: filename parameter is required";
|
||||
throw std::invalid_argument(error.toStdString());
|
||||
throw ToolInvalidArgument(error);
|
||||
}
|
||||
|
||||
QString modeStr = input["mode"].toString();
|
||||
if (modeStr.isEmpty()) {
|
||||
QString error = "Error: mode parameter is required";
|
||||
throw std::invalid_argument(error.toStdString());
|
||||
throw ToolInvalidArgument(error);
|
||||
}
|
||||
|
||||
EditMode mode;
|
||||
@ -155,32 +156,32 @@ QFuture<QString> EditProjectFileTool::executeAsync(const QJsonObject &input)
|
||||
QString error = QString("Error: Invalid mode '%1'. Must be one of: replace, "
|
||||
"insert_before, insert_after, append")
|
||||
.arg(modeStr);
|
||||
throw std::invalid_argument(error.toStdString());
|
||||
throw ToolInvalidArgument(error);
|
||||
}
|
||||
|
||||
QString newText = input["new_text"].toString();
|
||||
if (newText.isEmpty()) {
|
||||
QString error = "Error: new_text parameter is required";
|
||||
throw std::invalid_argument(error.toStdString());
|
||||
throw ToolInvalidArgument(error);
|
||||
}
|
||||
|
||||
QString searchText = input["search_text"].toString();
|
||||
if (mode == EditMode::Replace && searchText.isEmpty()) {
|
||||
QString error = "Error: search_text parameter is required for replace mode";
|
||||
throw std::invalid_argument(error.toStdString());
|
||||
throw ToolInvalidArgument(error);
|
||||
}
|
||||
|
||||
int lineNumber = input["line_number"].toInt(0);
|
||||
if ((mode == EditMode::InsertBefore || mode == EditMode::InsertAfter) && lineNumber <= 0) {
|
||||
QString error = "Error: line_number parameter is required for insert modes and must "
|
||||
"be greater than 0";
|
||||
throw std::invalid_argument(error.toStdString());
|
||||
throw ToolInvalidArgument(error);
|
||||
}
|
||||
|
||||
QString filePath = findFileInProject(filename);
|
||||
if (filePath.isEmpty()) {
|
||||
QString error = QString("Error: File '%1' not found in project").arg(filename);
|
||||
throw std::runtime_error(error.toStdString());
|
||||
throw ToolRuntimeError(error);
|
||||
}
|
||||
|
||||
auto project = ProjectExplorer::ProjectManager::projectForFile(
|
||||
@ -189,14 +190,11 @@ QFuture<QString> EditProjectFileTool::executeAsync(const QJsonObject &input)
|
||||
QString error
|
||||
= QString("Error: File '%1' is excluded by .qodeassistignore and cannot be edited")
|
||||
.arg(filename);
|
||||
throw std::runtime_error(error.toStdString());
|
||||
throw ToolRuntimeError(error);
|
||||
}
|
||||
|
||||
// readFileContent throws exception if file cannot be opened
|
||||
QString originalContent = readFileContent(filePath);
|
||||
if (originalContent.isNull()) {
|
||||
QString error = QString("Error: Could not read file '%1'").arg(filePath);
|
||||
throw std::runtime_error(error.toStdString());
|
||||
}
|
||||
|
||||
LOG_MESSAGE(QString("Prepared file edit: %1 (mode: %2)").arg(filePath, modeStr));
|
||||
|
||||
@ -282,14 +280,21 @@ QString EditProjectFileTool::readFileContent(const QString &filePath) const
|
||||
{
|
||||
QFile file(filePath);
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
LOG_MESSAGE(QString("Could not open file for reading: %1").arg(filePath));
|
||||
return QString();
|
||||
LOG_MESSAGE(QString("Could not open file for reading: %1, error: %2")
|
||||
.arg(filePath, file.errorString()));
|
||||
throw ToolRuntimeError(QString("Error: Could not open file '%1': %2")
|
||||
.arg(filePath, file.errorString()));
|
||||
}
|
||||
|
||||
QTextStream stream(&file);
|
||||
stream.setAutoDetectUnicode(true);
|
||||
QString content = stream.readAll();
|
||||
file.close();
|
||||
|
||||
LOG_MESSAGE(QString("Successfully read file for edit: %1, size: %2 bytes")
|
||||
.arg(filePath)
|
||||
.arg(content.length()));
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "FindFileTool.hpp"
|
||||
#include "ToolExceptions.hpp"
|
||||
|
||||
#include <logger/Logger.hpp>
|
||||
#include <projectexplorer/project.h>
|
||||
@ -113,7 +114,7 @@ QFuture<QString> FindFileTool::executeAsync(const QJsonObject &input)
|
||||
QString query = input["query"].toString().trimmed();
|
||||
if (query.isEmpty()) {
|
||||
QString error = "Error: query parameter is required and cannot be empty";
|
||||
throw std::invalid_argument(error.toStdString());
|
||||
throw ToolInvalidArgument(error);
|
||||
}
|
||||
|
||||
QString filePattern = input["file_pattern"].toString().trimmed();
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "FindSymbolTool.hpp"
|
||||
#include "ToolExceptions.hpp"
|
||||
|
||||
#include <cplusplus/Overview.h>
|
||||
#include <cplusplus/Scope.h>
|
||||
@ -157,13 +158,13 @@ QFuture<QString> FindSymbolTool::executeAsync(const QJsonObject &input)
|
||||
if (symbolName.isEmpty()) {
|
||||
QString error = "Error: 'symbol_name' parameter is required";
|
||||
LOG_MESSAGE(error);
|
||||
throw std::invalid_argument(error.toStdString());
|
||||
throw ToolInvalidArgument(error);
|
||||
}
|
||||
|
||||
if (useRegex && useWildcard) {
|
||||
QString error = "Error: 'use_regex' and 'use_wildcard' cannot be used together";
|
||||
LOG_MESSAGE(error);
|
||||
throw std::invalid_argument(error.toStdString());
|
||||
throw ToolInvalidArgument(error);
|
||||
}
|
||||
|
||||
SymbolType type = parseSymbolType(symbolTypeStr);
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "ListProjectFilesTool.hpp"
|
||||
#include "ToolExceptions.hpp"
|
||||
|
||||
#include <logger/Logger.hpp>
|
||||
#include <projectexplorer/project.h>
|
||||
@ -86,7 +87,7 @@ QFuture<QString> ListProjectFilesTool::executeAsync(const QJsonObject &input)
|
||||
QList<ProjectExplorer::Project *> projects = ProjectExplorer::ProjectManager::projects();
|
||||
if (projects.isEmpty()) {
|
||||
QString error = "Error: No projects found";
|
||||
throw std::runtime_error(error.toStdString());
|
||||
throw ToolRuntimeError(error);
|
||||
}
|
||||
|
||||
QString result;
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "ReadFileByPathTool.hpp"
|
||||
#include "ToolExceptions.hpp"
|
||||
|
||||
#include <coreplugin/documentmanager.h>
|
||||
#include <logger/Logger.hpp>
|
||||
@ -97,16 +98,22 @@ QFuture<QString> ReadProjectFileByPathTool::executeAsync(const QJsonObject &inpu
|
||||
QString filePath = input["filepath"].toString();
|
||||
if (filePath.isEmpty()) {
|
||||
QString error = "Error: filepath parameter is required";
|
||||
throw std::invalid_argument(error.toStdString());
|
||||
throw ToolInvalidArgument(error);
|
||||
}
|
||||
|
||||
QFileInfo fileInfo(filePath);
|
||||
LOG_MESSAGE(QString("Checking file: %1, exists: %2, isFile: %3")
|
||||
.arg(filePath)
|
||||
.arg(fileInfo.exists())
|
||||
.arg(fileInfo.isFile()));
|
||||
|
||||
if (!fileInfo.exists() || !fileInfo.isFile()) {
|
||||
QString error = QString("Error: File '%1' does not exist").arg(filePath);
|
||||
throw std::runtime_error(error.toStdString());
|
||||
throw ToolRuntimeError(error);
|
||||
}
|
||||
|
||||
QString canonicalPath = fileInfo.canonicalFilePath();
|
||||
LOG_MESSAGE(QString("Canonical path: %1").arg(canonicalPath));
|
||||
|
||||
bool isInProject = isFileInProject(canonicalPath);
|
||||
|
||||
@ -117,7 +124,7 @@ QFuture<QString> ReadProjectFileByPathTool::executeAsync(const QJsonObject &inpu
|
||||
QString error = QString("Error: File '%1' is not part of the project. "
|
||||
"Enable 'Allow reading files outside project' in settings to access this file.")
|
||||
.arg(filePath);
|
||||
throw std::runtime_error(error.toStdString());
|
||||
throw ToolRuntimeError(error);
|
||||
}
|
||||
LOG_MESSAGE(QString("Reading file outside project scope: %1").arg(canonicalPath));
|
||||
}
|
||||
@ -127,17 +134,19 @@ QFuture<QString> ReadProjectFileByPathTool::executeAsync(const QJsonObject &inpu
|
||||
if (isInProject && project && m_ignoreManager->shouldIgnore(canonicalPath, project)) {
|
||||
QString error
|
||||
= QString("Error: File '%1' is excluded by .qodeassistignore").arg(filePath);
|
||||
throw std::runtime_error(error.toStdString());
|
||||
throw ToolRuntimeError(error);
|
||||
}
|
||||
|
||||
// readFileContent throws exception if file cannot be opened
|
||||
// If it returns, the file was read successfully (may be empty)
|
||||
QString content = readFileContent(canonicalPath);
|
||||
if (content.isNull()) {
|
||||
QString error = QString("Error: Could not read file '%1'").arg(canonicalPath);
|
||||
throw std::runtime_error(error.toStdString());
|
||||
}
|
||||
|
||||
QString result = QString("File: %1\n\nContent:\n%2").arg(canonicalPath, content);
|
||||
return result;
|
||||
// Return appropriate message for empty or non-empty files
|
||||
if (content.isEmpty()) {
|
||||
return QString("File: %1\n\nThe file is empty").arg(canonicalPath);
|
||||
}
|
||||
|
||||
return QString("File: %1\n\nContent:\n%2").arg(canonicalPath, content);
|
||||
});
|
||||
}
|
||||
|
||||
@ -170,8 +179,9 @@ QString ReadProjectFileByPathTool::readFileContent(const QString &filePath) cons
|
||||
{
|
||||
QFile file(filePath);
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
LOG_MESSAGE(QString("Could not open file: %1").arg(filePath));
|
||||
return QString();
|
||||
LOG_MESSAGE(QString("Could not open file: %1, error: %2").arg(filePath, file.errorString()));
|
||||
throw ToolRuntimeError(QString("Error: Could not open file '%1': %2")
|
||||
.arg(filePath, file.errorString()));
|
||||
}
|
||||
|
||||
QTextStream stream(&file);
|
||||
@ -179,6 +189,13 @@ QString ReadProjectFileByPathTool::readFileContent(const QString &filePath) cons
|
||||
QString content = stream.readAll();
|
||||
|
||||
file.close();
|
||||
|
||||
LOG_MESSAGE(QString("Successfully read file: %1, size: %2 bytes, isEmpty: %3")
|
||||
.arg(filePath)
|
||||
.arg(content.length())
|
||||
.arg(content.isEmpty()));
|
||||
|
||||
// Always return valid QString (empty string for empty files)
|
||||
return content;
|
||||
}
|
||||
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "ReadVisibleFilesTool.hpp"
|
||||
#include "ToolExceptions.hpp"
|
||||
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
#include <coreplugin/editormanager/ieditor.h>
|
||||
@ -85,7 +86,7 @@ QFuture<QString> ReadVisibleFilesTool::executeAsync(const QJsonObject &input)
|
||||
|
||||
if (editors.isEmpty()) {
|
||||
QString error = "Error: No visible files in the editor";
|
||||
throw std::runtime_error(error.toStdString());
|
||||
throw ToolRuntimeError(error);
|
||||
}
|
||||
|
||||
QStringList results;
|
||||
@ -121,7 +122,7 @@ QFuture<QString> ReadVisibleFilesTool::executeAsync(const QJsonObject &input)
|
||||
|
||||
if (results.isEmpty()) {
|
||||
QString error = "Error: All visible files are excluded by .qodeassistignore";
|
||||
throw std::runtime_error(error.toStdString());
|
||||
throw ToolRuntimeError(error);
|
||||
}
|
||||
|
||||
return results.join("\n\n" + QString(80, '=') + "\n\n");
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "SearchInProjectTool.hpp"
|
||||
#include "ToolExceptions.hpp"
|
||||
|
||||
#include <logger/Logger.hpp>
|
||||
#include <projectexplorer/project.h>
|
||||
@ -122,7 +123,7 @@ QFuture<QString> SearchInProjectTool::executeAsync(const QJsonObject &input)
|
||||
QString query = input["query"].toString();
|
||||
if (query.isEmpty()) {
|
||||
QString error = "Error: query parameter is required";
|
||||
throw std::invalid_argument(error.toStdString());
|
||||
throw ToolInvalidArgument(error);
|
||||
}
|
||||
|
||||
bool caseSensitive = input["case_sensitive"].toBool(false);
|
||||
|
||||
69
tools/ToolExceptions.hpp
Normal file
69
tools/ToolExceptions.hpp
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2025 Petr Mironychev
|
||||
*
|
||||
* This file is part of QodeAssist.
|
||||
*
|
||||
* QodeAssist is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* QodeAssist is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with QodeAssist. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QException>
|
||||
#include <QString>
|
||||
|
||||
namespace QodeAssist::Tools {
|
||||
|
||||
class ToolException : public QException
|
||||
{
|
||||
public:
|
||||
explicit ToolException(const QString &message)
|
||||
: m_message(message)
|
||||
, m_stdMessage(message.toStdString())
|
||||
{}
|
||||
|
||||
void raise() const override { throw *this; }
|
||||
ToolException *clone() const override { return new ToolException(*this); }
|
||||
const char *what() const noexcept override { return m_stdMessage.c_str(); }
|
||||
|
||||
QString message() const { return m_message; }
|
||||
|
||||
private:
|
||||
QString m_message;
|
||||
std::string m_stdMessage;
|
||||
};
|
||||
|
||||
class ToolRuntimeError : public ToolException
|
||||
{
|
||||
public:
|
||||
explicit ToolRuntimeError(const QString &message)
|
||||
: ToolException(message)
|
||||
{}
|
||||
|
||||
void raise() const override { throw *this; }
|
||||
ToolRuntimeError *clone() const override { return new ToolRuntimeError(*this); }
|
||||
};
|
||||
|
||||
class ToolInvalidArgument : public ToolException
|
||||
{
|
||||
public:
|
||||
explicit ToolInvalidArgument(const QString &message)
|
||||
: ToolException(message)
|
||||
{}
|
||||
|
||||
void raise() const override { throw *this; }
|
||||
ToolInvalidArgument *clone() const override { return new ToolInvalidArgument(*this); }
|
||||
};
|
||||
|
||||
} // namespace QodeAssist::Tools
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "ToolHandler.hpp"
|
||||
#include "ToolExceptions.hpp"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QTimer>
|
||||
@ -93,8 +94,43 @@ void ToolHandler::onToolExecutionFinished(const QString &toolId)
|
||||
QString result = execution->watcher->result();
|
||||
LOG_MESSAGE(QString("Tool %1 completed").arg(execution->toolName));
|
||||
emit toolCompleted(execution->requestId, execution->toolId, result);
|
||||
} catch (const ToolException &e) {
|
||||
QString error = e.message();
|
||||
if (error.isEmpty()) {
|
||||
error = "Tool execution failed with empty error message";
|
||||
}
|
||||
LOG_MESSAGE(QString("Tool %1 failed: %2").arg(execution->toolName, error));
|
||||
emit toolFailed(execution->requestId, execution->toolId, error);
|
||||
} catch (const QException &e) {
|
||||
QString error = QString::fromUtf8(e.what());
|
||||
if (error.isEmpty()) {
|
||||
error = "Tool execution failed (QException with empty message)";
|
||||
}
|
||||
LOG_MESSAGE(QString("Tool %1 failed: %2").arg(execution->toolName, error));
|
||||
emit toolFailed(execution->requestId, execution->toolId, error);
|
||||
} catch (const std::runtime_error &e) {
|
||||
QString error = QString::fromStdString(e.what());
|
||||
if (error.isEmpty()) {
|
||||
error = "Unknown runtime error occurred";
|
||||
}
|
||||
LOG_MESSAGE(QString("Tool %1 failed: %2").arg(execution->toolName, error));
|
||||
emit toolFailed(execution->requestId, execution->toolId, error);
|
||||
} catch (const std::invalid_argument &e) {
|
||||
QString error = QString::fromStdString(e.what());
|
||||
if (error.isEmpty()) {
|
||||
error = "Invalid argument provided";
|
||||
}
|
||||
LOG_MESSAGE(QString("Tool %1 failed: %2").arg(execution->toolName, error));
|
||||
emit toolFailed(execution->requestId, execution->toolId, error);
|
||||
} catch (const std::exception &e) {
|
||||
QString error = QString::fromStdString(e.what());
|
||||
if (error.isEmpty()) {
|
||||
error = "Unknown exception occurred";
|
||||
}
|
||||
LOG_MESSAGE(QString("Tool %1 failed: %2").arg(execution->toolName, error));
|
||||
emit toolFailed(execution->requestId, execution->toolId, error);
|
||||
} catch (...) {
|
||||
QString error = "Unknown error occurred during tool execution";
|
||||
LOG_MESSAGE(QString("Tool %1 failed: %2").arg(execution->toolName, error));
|
||||
emit toolFailed(execution->requestId, execution->toolId, error);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user