diff options
Diffstat (limited to 'src/plugins/axivion/axivionplugin.cpp')
-rw-r--r-- | src/plugins/axivion/axivionplugin.cpp | 148 |
1 files changed, 54 insertions, 94 deletions
diff --git a/src/plugins/axivion/axivionplugin.cpp b/src/plugins/axivion/axivionplugin.cpp index 26f5196a9a..cd8fca0a0c 100644 --- a/src/plugins/axivion/axivionplugin.cpp +++ b/src/plugins/axivion/axivionplugin.cpp @@ -53,21 +53,6 @@ using namespace Utils; namespace Axivion::Internal { -class Issue -{ -public: - QString id; - QString state; - QString errorNumber; - QString message; - QString entity; - QString filePath; - QString severity; - int lineNumber = 0; -}; - -using Issues = QList<Issue>; - QIcon iconForIssue(const QString &prefix) { static QHash<QString, QIcon> prefixToIcon; @@ -154,7 +139,7 @@ public: void onDocumentOpened(IDocument *doc); void onDocumentClosed(IDocument * doc); void clearAllMarks(); - void handleIssuesForFile(const Issues &issues); + void handleIssuesForFile(const Dto::FileViewDto &fileView); void fetchIssueInfo(const QString &id); NetworkAccessManager m_networkAccessManager; @@ -173,18 +158,18 @@ static AxivionPluginPrivate *dd = nullptr; class AxivionTextMark : public TextMark { public: - AxivionTextMark(const FilePath &filePath, const Issue &issue) - : TextMark(filePath, issue.lineNumber, {Tr::tr("Axivion"), AxivionTextMarkId}) + AxivionTextMark(const FilePath &filePath, const Dto::LineMarkerDto &issue) + : TextMark(filePath, issue.startLine, {Tr::tr("Axivion"), AxivionTextMarkId}) { - const QString markText = issue.entity.isEmpty() ? issue.message - : issue.entity + ": " + issue.message; - setToolTip(issue.errorNumber + " " + markText); - setIcon(iconForIssue("SV")); // FIXME adapt to the issue + const QString markText = issue.description; + const QString id = issue.kind + QString::number(issue.id.value_or(-1)); + setToolTip(id + markText); + setIcon(iconForIssue(issue.kind)); setPriority(TextMark::NormalPriority); setLineAnnotation(markText); - setActionsProvider([id = issue.id] { + setActionsProvider([id] { auto action = new QAction; - action->setIcon(Utils::Icons::INFO.icon()); + action->setIcon(Icons::INFO.icon()); action->setToolTip(Tr::tr("Show rule details")); QObject::connect(action, &QAction::triggered, dd, [id] { dd->fetchIssueInfo(id); }); return QList{action}; @@ -281,8 +266,8 @@ static QUrl urlForProject(const QString &projectName) } static constexpr int httpStatusCodeOk = 200; -static const QLatin1String jsonContentType{ "application/json" }; -static const QLatin1String htmlContentType{ "text/html" }; +constexpr char s_htmlContentType[] = "text/html"; +constexpr char s_jsonContentType[] = "application/json"; static Group fetchHtmlRecipe(const QUrl &url, const std::function<void(const QByteArray &)> &handler) { @@ -299,15 +284,11 @@ static Group fetchHtmlRecipe(const QUrl &url, const std::function<void(const QBy const auto onQuerySetup = [storage, url](NetworkQuery &query) { QNetworkRequest request(url); - request.setRawHeader(QByteArrayLiteral("Accept"), - QByteArray(htmlContentType.data(), htmlContentType.size())); - request.setRawHeader(QByteArrayLiteral("Authorization"), - storage->credentials); - const QByteArray ua = QByteArrayLiteral("Axivion") - + QCoreApplication::applicationName().toUtf8() - + QByteArrayLiteral("Plugin/") - + QCoreApplication::applicationVersion().toUtf8(); - request.setRawHeader(QByteArrayLiteral("X-Axivion-User-Agent"), ua); + request.setRawHeader("Accept", s_htmlContentType); + request.setRawHeader("Authorization", storage->credentials); + const QByteArray ua = "Axivion" + QCoreApplication::applicationName().toUtf8() + + "Plugin/" + QCoreApplication::applicationVersion().toUtf8(); + request.setRawHeader("X-Axivion-User-Agent", ua); query.setRequest(request); query.setNetworkAccessManager(&dd->m_networkAccessManager); }; @@ -322,11 +303,10 @@ static Group fetchHtmlRecipe(const QUrl &url, const std::function<void(const QBy .trimmed() .toLower(); if (doneWith == DoneWith::Success && statusCode == httpStatusCodeOk - && contentType == htmlContentType) { + && contentType == s_htmlContentType) { handler(reply->readAll()); return DoneResult::Success; } - return DoneResult::Error; }; @@ -355,22 +335,19 @@ static Group fetchDataRecipe(const QUrl &url, storage->credentials = QByteArrayLiteral("AxToken ") + settings().server.token.toUtf8(); }; - const auto onQuerySetup = [storage, url](NetworkQuery &query) { + const auto onNetworkQuerySetup = [storage, url](NetworkQuery &query) { QNetworkRequest request(url); - request.setRawHeader(QByteArrayLiteral("Accept"), - QByteArray(jsonContentType.data(), jsonContentType.size())); - request.setRawHeader(QByteArrayLiteral("Authorization"), - storage->credentials); - const QByteArray ua = QByteArrayLiteral("Axivion") - + QCoreApplication::applicationName().toUtf8() - + QByteArrayLiteral("Plugin/") - + QCoreApplication::applicationVersion().toUtf8(); - request.setRawHeader(QByteArrayLiteral("X-Axivion-User-Agent"), ua); + request.setRawHeader("Accept", s_jsonContentType); + request.setRawHeader("Authorization", storage->credentials); + const QByteArray ua = "Axivion" + QCoreApplication::applicationName().toUtf8() + + "Plugin/" + QCoreApplication::applicationVersion().toUtf8(); + request.setRawHeader("X-Axivion-User-Agent", ua); query.setRequest(request); query.setNetworkAccessManager(&dd->m_networkAccessManager); + return SetupResult::Continue; }; - const auto onQueryDone = [storage, url](const NetworkQuery &query, DoneWith doneWith) { + const auto onNetworkQueryDone = [storage, url](const NetworkQuery &query, DoneWith doneWith) { QNetworkReply *reply = query.reply(); const QNetworkReply::NetworkError error = reply->error(); const int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); @@ -381,13 +358,13 @@ static Group fetchDataRecipe(const QUrl &url, .trimmed() .toLower(); if (doneWith == DoneWith::Success && statusCode == httpStatusCodeOk - && contentType == jsonContentType) { + && contentType == s_jsonContentType) { storage->serializableData = reply->readAll(); return DoneResult::Success; } const auto getError = [&]() -> Error { - if (contentType == jsonContentType) { + if (contentType == s_jsonContentType) { try { return DashboardError(reply->url(), statusCode, reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString(), @@ -404,8 +381,7 @@ static Group fetchDataRecipe(const QUrl &url, return NetworkError(reply->url(), error, reply->errorString()); }; - MessageManager::writeFlashing( - QStringLiteral("Axivion: %1").arg(getError().message())); + MessageManager::writeFlashing(QStringLiteral("Axivion: %1").arg(getError().message())); return DoneResult::Error; }; @@ -426,7 +402,7 @@ static Group fetchDataRecipe(const QUrl &url, const Group recipe { storage, Sync(onCredentialSetup), - NetworkQueryTask(onQuerySetup, onQueryDone), + NetworkQueryTask(onNetworkQuerySetup, onNetworkQueryDone), AsyncTask<SerializableType>(onDeserializeSetup, onDeserializeDone) }; @@ -495,6 +471,17 @@ Group issueTableRecipe(const IssueListSearch &search, const IssueTableHandler &h return fetchDataRecipe<Dto::IssueTableDto>(url, handler); } +Group lineMarkerRecipe(const FilePath &filePath, const LineMarkerHandler &handler) +{ + QTC_ASSERT(dd->m_currentProjectInfo, return {}); // TODO: Call handler with unexpected? + QTC_ASSERT(!filePath.isEmpty(), return {}); // TODO: Call handler with unexpected? + + const QString fileName = QString::fromUtf8(QUrl::toPercentEncoding(filePath.path())); + const QUrl url = urlForProject(dd->m_currentProjectInfo.value().name + '/') + .resolved(QString("files?filename=" + fileName)); + return fetchDataRecipe<Dto::FileViewDto>(url, handler); +} + Group issueHtmlRecipe(const QString &issueId, const HtmlHandler &handler) { QTC_ASSERT(dd->m_currentProjectInfo, return {}); // TODO: Call handler with unexpected? @@ -569,7 +556,7 @@ void AxivionPluginPrivate::fetchIssueInfo(const QString &id) dd->m_axivionOutputPane.updateAndShowRule(QString::fromUtf8(fixedHtml)); }; - m_issueInfoRunner.start(issueHtmlRecipe(QString("SV") + id, ruleHandler)); + m_issueInfoRunner.start(issueHtmlRecipe(id, ruleHandler)); } void AxivionPluginPrivate::handleOpenedDocs() @@ -591,41 +578,16 @@ void AxivionPluginPrivate::onDocumentOpened(IDocument *doc) if (!doc || !m_currentProjectInfo || !m_project || !m_project->isKnownFile(doc->filePath())) return; - IssueListSearch search; - search.kind = "SV"; - search.filter_path = doc->filePath().relativeChildPath(m_project->projectDirectory()).path(); - search.limit = 0; - - const auto issuesHandler = [this](const Dto::IssueTableDto &dto) { - Issues issues; - const std::vector<std::map<QString, Dto::Any>> &rows = dto.rows; - for (const auto &row : rows) { - Issue issue; - for (auto it = row.cbegin(); it != row.cend(); ++it) { - if (it->first == "id") - issue.id = anyToSimpleString(it->second); - else if (it->first == "state") - issue.state = anyToSimpleString(it->second); - else if (it->first == "errorNumber") - issue.errorNumber = anyToSimpleString(it->second); - else if (it->first == "message") - issue.message = anyToSimpleString(it->second); - else if (it->first == "entity") - issue.entity = anyToSimpleString(it->second); - else if (it->first == "path") - issue.filePath = anyToSimpleString(it->second); - else if (it->first == "severity") - issue.severity = anyToSimpleString(it->second); - else if (it->first == "line") - issue.lineNumber = anyToSimpleString(it->second).toInt(); - } - issues << issue; - } - handleIssuesForFile(issues); - }; + const FilePath filePath = doc->filePath().relativeChildPath(m_project->projectDirectory()); + QTC_ASSERT(!filePath.isEmpty(), return); + const auto handler = [this](const Dto::FileViewDto &data) { + if (data.lineMarkers.empty()) + return; + handleIssuesForFile(data); + }; TaskTree *taskTree = new TaskTree; - taskTree->setRecipe(issueTableRecipe(search, issuesHandler)); + taskTree->setRecipe(lineMarkerRecipe(filePath, handler)); m_docMarksTrees.insert_or_assign(doc, std::unique_ptr<TaskTree>(taskTree)); connect(taskTree, &TaskTree::done, this, [this, doc] { const auto it = m_docMarksTrees.find(doc); @@ -653,24 +615,22 @@ void AxivionPluginPrivate::onDocumentClosed(IDocument *doc) } } -void AxivionPluginPrivate::handleIssuesForFile(const Issues &issues) +void AxivionPluginPrivate::handleIssuesForFile(const Dto::FileViewDto &fileView) { - if (issues.isEmpty()) + if (fileView.lineMarkers.empty()) return; Project *project = ProjectManager::startupProject(); if (!project) return; - const FilePath filePath = project->projectDirectory() - .pathAppended(issues.first().filePath); + const FilePath filePath = project->projectDirectory().pathAppended(fileView.fileName); - const Id axivionId(AxivionTextMarkId); - for (const Issue &issue : issues) { + for (const Dto::LineMarkerDto &marker : std::as_const(fileView.lineMarkers)) { // FIXME the line location can be wrong (even the whole issue could be wrong) // depending on whether this line has been changed since the last axivion run and the // current state of the file - some magic has to happen here - new AxivionTextMark(filePath, issue); + new AxivionTextMark(filePath, marker); } } |