forked from qt-creator/qt-creator
ClangTools: make parsing diagnostics cancelable
Change-Id: Ia5b4bd6f5fbb9a81888b1eaf11b956617e4b740c Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
This commit is contained in:
@@ -677,16 +677,6 @@ void ClangTool::startTool(ClangTool::FileSelection fileSelection,
|
|||||||
ProjectExplorerPlugin::startRunControl(m_runControl);
|
ProjectExplorerPlugin::startRunControl(m_runControl);
|
||||||
}
|
}
|
||||||
|
|
||||||
Diagnostics ClangTool::read(const FilePath &logFilePath,
|
|
||||||
const QSet<FilePath> &projectFiles,
|
|
||||||
QString *errorMessage) const
|
|
||||||
{
|
|
||||||
const auto acceptFromFilePath = [projectFiles](const FilePath &filePath) {
|
|
||||||
return projectFiles.contains(filePath);
|
|
||||||
};
|
|
||||||
return readExportedDiagnostics(logFilePath, acceptFromFilePath, errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
FileInfos ClangTool::collectFileInfos(Project *project, FileSelection fileSelection)
|
FileInfos ClangTool::collectFileInfos(Project *project, FileSelection fileSelection)
|
||||||
{
|
{
|
||||||
FileSelectionType *selectionType = std::get_if<FileSelectionType>(&fileSelection);
|
FileSelectionType *selectionType = std::get_if<FileSelectionType>(&fileSelection);
|
||||||
@@ -763,21 +753,17 @@ void ClangTool::loadDiagnosticsFromFiles()
|
|||||||
|
|
||||||
// Load files
|
// Load files
|
||||||
Diagnostics diagnostics;
|
Diagnostics diagnostics;
|
||||||
QString errors;
|
QStringList errors;
|
||||||
for (const FilePath &filePath : filePaths) {
|
for (const FilePath &filePath : filePaths) {
|
||||||
QString currentError;
|
if (expected_str<Diagnostics> expectedDiagnostics = readExportedDiagnostics(filePath))
|
||||||
diagnostics << readExportedDiagnostics(filePath, {}, ¤tError);
|
diagnostics << *expectedDiagnostics;
|
||||||
|
else
|
||||||
if (!currentError.isEmpty()) {
|
errors.append(expectedDiagnostics.error());
|
||||||
if (!errors.isEmpty())
|
|
||||||
errors.append("\n");
|
|
||||||
errors.append(currentError);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show errors
|
// Show errors
|
||||||
if (!errors.isEmpty()) {
|
if (!errors.isEmpty()) {
|
||||||
AsynchronousMessageBox::critical(Tr::tr("Error Loading Diagnostics"), errors);
|
AsynchronousMessageBox::critical(Tr::tr("Error Loading Diagnostics"), errors.join('\n'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -65,10 +65,6 @@ public:
|
|||||||
const RunSettings &runSettings,
|
const RunSettings &runSettings,
|
||||||
const CppEditor::ClangDiagnosticConfig &diagnosticConfig);
|
const CppEditor::ClangDiagnosticConfig &diagnosticConfig);
|
||||||
|
|
||||||
Diagnostics read(const Utils::FilePath &logFilePath,
|
|
||||||
const QSet<Utils::FilePath> &projectFiles,
|
|
||||||
QString *errorMessage) const;
|
|
||||||
|
|
||||||
FileInfos collectFileInfos(ProjectExplorer::Project *project,
|
FileInfos collectFileInfos(ProjectExplorer::Project *project,
|
||||||
FileSelection fileSelection);
|
FileSelection fileSelection);
|
||||||
|
|
||||||
|
@@ -114,7 +114,6 @@ GroupItem clangToolTask(const AnalyzeInputData &input,
|
|||||||
QString name;
|
QString name;
|
||||||
FilePath executable;
|
FilePath executable;
|
||||||
FilePath outputFilePath;
|
FilePath outputFilePath;
|
||||||
QString errorMessage;
|
|
||||||
};
|
};
|
||||||
const TreeStorage<ClangToolStorage> storage;
|
const TreeStorage<ClangToolStorage> storage;
|
||||||
|
|
||||||
@@ -186,24 +185,36 @@ GroupItem clangToolTask(const AnalyzeInputData &input,
|
|||||||
{false, input.unit.file, data.outputFilePath, {}, input.tool, message, details});
|
{false, input.unit.file, data.outputFilePath, {}, input.tool, message, details});
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto onReadSetup = [=](Async<Diagnostics> &data) {
|
const auto onReadSetup = [=](Async<expected_str<Diagnostics>> &data) {
|
||||||
data.setConcurrentCallData(&readExportedDiagnostics,
|
data.setConcurrentCallData(&parseDiagnostics,
|
||||||
storage->outputFilePath,
|
storage->outputFilePath,
|
||||||
input.diagnosticsFilter,
|
input.diagnosticsFilter);
|
||||||
&storage->errorMessage);
|
|
||||||
data.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
|
data.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
|
||||||
};
|
};
|
||||||
const auto onReadDone = [=](const Async<Diagnostics> &data) {
|
const auto onReadDone = [=](const Async<expected_str<Diagnostics>> &data) {
|
||||||
if (!outputHandler)
|
if (!outputHandler)
|
||||||
return;
|
return;
|
||||||
outputHandler(
|
const expected_str<Diagnostics> result = data.result();
|
||||||
{true, input.unit.file, storage->outputFilePath, data.result(), input.tool});
|
const bool success = result.has_value();
|
||||||
|
Diagnostics diagnostics;
|
||||||
|
QString error;
|
||||||
|
if (success)
|
||||||
|
diagnostics = *result;
|
||||||
|
else
|
||||||
|
error = result.error();
|
||||||
|
outputHandler({success,
|
||||||
|
input.unit.file,
|
||||||
|
storage->outputFilePath,
|
||||||
|
diagnostics,
|
||||||
|
input.tool,
|
||||||
|
error});
|
||||||
};
|
};
|
||||||
const auto onReadError = [=](const Async<Diagnostics> &) {
|
const auto onReadError = [=](const Async<expected_str<Diagnostics>> &data) {
|
||||||
if (!outputHandler)
|
if (!outputHandler)
|
||||||
return;
|
return;
|
||||||
|
const expected_str<Diagnostics> result = data.result();
|
||||||
outputHandler(
|
outputHandler(
|
||||||
{false, input.unit.file, storage->outputFilePath, {}, input.tool, storage->errorMessage});
|
{false, input.unit.file, storage->outputFilePath, {}, input.tool, result.error()});
|
||||||
};
|
};
|
||||||
|
|
||||||
const Group group {
|
const Group group {
|
||||||
@@ -213,7 +224,7 @@ GroupItem clangToolTask(const AnalyzeInputData &input,
|
|||||||
sequential,
|
sequential,
|
||||||
finishAllAndDone,
|
finishAllAndDone,
|
||||||
ProcessTask(onProcessSetup, onProcessDone, onProcessError),
|
ProcessTask(onProcessSetup, onProcessDone, onProcessError),
|
||||||
AsyncTask<Diagnostics>(onReadSetup, onReadDone, onReadError)
|
AsyncTask<expected_str<Diagnostics>>(onReadSetup, onReadDone, onReadError)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return group;
|
return group;
|
||||||
|
@@ -11,26 +11,13 @@
|
|||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
#include <utils/textutils.h>
|
#include <utils/textutils.h>
|
||||||
|
|
||||||
|
#include <QFuture>
|
||||||
|
|
||||||
#include <yaml-cpp/yaml.h>
|
#include <yaml-cpp/yaml.h>
|
||||||
|
|
||||||
namespace ClangTools {
|
namespace ClangTools {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
static bool checkFilePath(const Utils::FilePath &filePath, QString *errorMessage)
|
|
||||||
{
|
|
||||||
QFileInfo fi(filePath.toFileInfo());
|
|
||||||
if (!fi.exists() || !fi.isReadable()) {
|
|
||||||
if (errorMessage) {
|
|
||||||
*errorMessage
|
|
||||||
= QString(QT_TRANSLATE_NOOP("QtC::ClangTools",
|
|
||||||
"File \"%1\" does not exist or is not readable."))
|
|
||||||
.arg(filePath.toUserOutput());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<LineColumnInfo> byteOffsetInUtf8TextToLineColumn(const char *text,
|
std::optional<LineColumnInfo> byteOffsetInUtf8TextToLineColumn(const char *text,
|
||||||
int offset,
|
int offset,
|
||||||
int startLine)
|
int startLine)
|
||||||
@@ -190,19 +177,25 @@ private:
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Diagnostics readExportedDiagnostics(const Utils::FilePath &logFilePath,
|
void parseDiagnostics(QPromise<Utils::expected_str<Diagnostics>> &promise,
|
||||||
const AcceptDiagsFromFilePath &acceptFromFilePath,
|
const Utils::FilePath &logFilePath,
|
||||||
QString *errorMessage)
|
const AcceptDiagsFromFilePath &acceptFromFilePath)
|
||||||
{
|
{
|
||||||
if (!checkFilePath(logFilePath, errorMessage))
|
const Utils::expected_str<QByteArray> localFileContents = logFilePath.fileContents();
|
||||||
return {};
|
if (!localFileContents.has_value()) {
|
||||||
|
promise.addResult(Utils::make_unexpected(localFileContents.error()));
|
||||||
|
promise.future().cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
FileCache fileCache;
|
FileCache fileCache;
|
||||||
Diagnostics diagnostics;
|
Diagnostics diagnostics;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
YAML::Node document = YAML::LoadFile(logFilePath.toString().toStdString());
|
YAML::Node document = YAML::Load(*localFileContents);
|
||||||
for (const auto &diagNode : document["Diagnostics"]) {
|
for (const auto &diagNode : document["Diagnostics"]) {
|
||||||
|
if (promise.isCanceled())
|
||||||
|
return;
|
||||||
// Since llvm/clang 9.0 the diagnostic items are wrapped in a "DiagnosticMessage" node.
|
// Since llvm/clang 9.0 the diagnostic items are wrapped in a "DiagnosticMessage" node.
|
||||||
const auto msgNode = diagNode["DiagnosticMessage"];
|
const auto msgNode = diagNode["DiagnosticMessage"];
|
||||||
const YAML::Node &node = msgNode ? msgNode : diagNode;
|
const YAML::Node &node = msgNode ? msgNode : diagNode;
|
||||||
@@ -252,16 +245,24 @@ Diagnostics readExportedDiagnostics(const Utils::FilePath &logFilePath,
|
|||||||
|
|
||||||
diagnostics.append(diag);
|
diagnostics.append(diag);
|
||||||
}
|
}
|
||||||
|
promise.addResult(diagnostics);
|
||||||
} catch (std::exception &e) {
|
} catch (std::exception &e) {
|
||||||
if (errorMessage) {
|
const QString errorMessage
|
||||||
*errorMessage = QString(
|
= QString(QT_TRANSLATE_NOOP("QtC::ClangTools",
|
||||||
QT_TRANSLATE_NOOP("QtC::ClangTools",
|
"Error: Failed to parse YAML file \"%1\": %2."))
|
||||||
"Error: Failed to parse YAML file \"%1\": %2."))
|
.arg(logFilePath.toUserOutput(), QString::fromUtf8(e.what()));
|
||||||
.arg(logFilePath.toUserOutput(), QString::fromUtf8(e.what()));
|
promise.addResult(Utils::make_unexpected(errorMessage));
|
||||||
}
|
promise.future().cancel();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return diagnostics;
|
Utils::expected_str<Diagnostics> readExportedDiagnostics(
|
||||||
|
const Utils::FilePath &logFilePath, const AcceptDiagsFromFilePath &acceptFromFilePath)
|
||||||
|
{
|
||||||
|
QPromise<Utils::expected_str<Diagnostics>> promise;
|
||||||
|
promise.start();
|
||||||
|
parseDiagnostics(promise, logFilePath, acceptFromFilePath);
|
||||||
|
return promise.future().result();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "clangtoolsdiagnostic.h"
|
#include "clangtoolsdiagnostic.h"
|
||||||
|
|
||||||
|
#include <QPromise>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
namespace Utils { class FilePath; }
|
namespace Utils { class FilePath; }
|
||||||
@@ -16,9 +17,13 @@ namespace Internal {
|
|||||||
using AcceptDiagsFromFilePath = std::function<bool(const Utils::FilePath &)>;
|
using AcceptDiagsFromFilePath = std::function<bool(const Utils::FilePath &)>;
|
||||||
|
|
||||||
// Reads diagnostics generated by "clang-tidy/clazy-standalone -export-fixes=path/to/file"
|
// Reads diagnostics generated by "clang-tidy/clazy-standalone -export-fixes=path/to/file"
|
||||||
Diagnostics readExportedDiagnostics(const Utils::FilePath &logFilePath,
|
void parseDiagnostics(QPromise<Utils::expected_str<Diagnostics>> &promise,
|
||||||
const AcceptDiagsFromFilePath &acceptFromFilePath,
|
const Utils::FilePath &logFilePath,
|
||||||
QString *errorMessage = nullptr);
|
const AcceptDiagsFromFilePath &acceptFromFilePath = {});
|
||||||
|
|
||||||
|
Utils::expected_str<Diagnostics> readExportedDiagnostics(
|
||||||
|
const Utils::FilePath &logFilePath,
|
||||||
|
const AcceptDiagsFromFilePath &acceptFromFilePath = {});
|
||||||
|
|
||||||
// Exposed for tests
|
// Exposed for tests
|
||||||
struct LineColumnInfo {
|
struct LineColumnInfo {
|
||||||
|
@@ -31,41 +31,40 @@ ReadExportedDiagnosticsTest::ReadExportedDiagnosticsTest()
|
|||||||
ReadExportedDiagnosticsTest::~ReadExportedDiagnosticsTest() { delete m_baseDir; }
|
ReadExportedDiagnosticsTest::~ReadExportedDiagnosticsTest() { delete m_baseDir; }
|
||||||
|
|
||||||
void ReadExportedDiagnosticsTest::initTestCase() { QVERIFY(m_baseDir->isValid()); }
|
void ReadExportedDiagnosticsTest::initTestCase() { QVERIFY(m_baseDir->isValid()); }
|
||||||
void ReadExportedDiagnosticsTest::init() { m_message.clear(); }
|
void ReadExportedDiagnosticsTest::init() { }
|
||||||
|
|
||||||
void ReadExportedDiagnosticsTest::testNonExistingFile()
|
void ReadExportedDiagnosticsTest::testNonExistingFile()
|
||||||
{
|
{
|
||||||
const Diagnostics diags = readExportedDiagnostics("nonExistingFile.yaml", {}, &m_message);
|
const expected_str<Diagnostics> diags = readExportedDiagnostics("nonExistingFile.yaml");
|
||||||
QVERIFY(diags.isEmpty());
|
QVERIFY(!diags.has_value());
|
||||||
QVERIFY(!m_message.isEmpty());
|
QVERIFY(!diags.error().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadExportedDiagnosticsTest::testEmptyFile()
|
void ReadExportedDiagnosticsTest::testEmptyFile()
|
||||||
{
|
{
|
||||||
const Diagnostics diags = readExportedDiagnostics(filePath("empty.yaml"), {}, &m_message);
|
const expected_str<Diagnostics> diags = readExportedDiagnostics(filePath("empty.yaml"));
|
||||||
QVERIFY(diags.isEmpty());
|
QVERIFY(diags.has_value());
|
||||||
QVERIFY2(m_message.isEmpty(), qPrintable(m_message));
|
QVERIFY(diags->isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadExportedDiagnosticsTest::testUnexpectedFileContents()
|
void ReadExportedDiagnosticsTest::testUnexpectedFileContents()
|
||||||
{
|
{
|
||||||
const Diagnostics diags = readExportedDiagnostics(filePath("tidy.modernize-use-nullptr.cpp"),
|
const expected_str<Diagnostics> diags = readExportedDiagnostics(
|
||||||
{}, &m_message);
|
filePath("tidy.modernize-use-nullptr.cpp"));
|
||||||
QVERIFY(!m_message.isEmpty());
|
QVERIFY(!diags.has_value());
|
||||||
QVERIFY(diags.isEmpty());
|
QVERIFY(!diags.error().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString appendYamlSuffix(const char *filePathFragment)
|
static QString appendYamlSuffix(const char *filePathFragment)
|
||||||
{
|
{
|
||||||
const QString yamlSuffix = QLatin1String(Utils::HostOsInfo::isWindowsHost()
|
const QString yamlSuffix = QLatin1String(HostOsInfo::isWindowsHost() ? "_win.yaml" : ".yaml");
|
||||||
? "_win.yaml" : ".yaml");
|
|
||||||
return filePathFragment + yamlSuffix;
|
return filePathFragment + yamlSuffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadExportedDiagnosticsTest::testTidy()
|
void ReadExportedDiagnosticsTest::testTidy()
|
||||||
{
|
{
|
||||||
const FilePath sourceFile = filePath("tidy.modernize-use-nullptr.cpp");
|
const FilePath sourceFile = filePath("tidy.modernize-use-nullptr.cpp");
|
||||||
const QString exportedFile = createFile(
|
const FilePath exportedFile = createFile(
|
||||||
filePath(appendYamlSuffix("tidy.modernize-use-nullptr")).toString(),
|
filePath(appendYamlSuffix("tidy.modernize-use-nullptr")).toString(),
|
||||||
sourceFile.toString());
|
sourceFile.toString());
|
||||||
Diagnostic expectedDiag;
|
Diagnostic expectedDiag;
|
||||||
@@ -79,32 +78,31 @@ void ReadExportedDiagnosticsTest::testTidy()
|
|||||||
expectedDiag.location,
|
expectedDiag.location,
|
||||||
{expectedDiag.location, {sourceFile, 2, 26}},
|
{expectedDiag.location, {sourceFile, 2, 26}},
|
||||||
true}};
|
true}};
|
||||||
const Diagnostics diags = readExportedDiagnostics(Utils::FilePath::fromString(exportedFile),
|
const expected_str<Diagnostics> diags = readExportedDiagnostics(exportedFile);
|
||||||
{}, &m_message);
|
|
||||||
|
|
||||||
QVERIFY2(m_message.isEmpty(), qPrintable(m_message));
|
QVERIFY(diags.has_value());
|
||||||
QCOMPARE(diags, {expectedDiag});
|
QCOMPARE(*diags, {expectedDiag});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadExportedDiagnosticsTest::testAcceptDiagsFromFilePaths_None()
|
void ReadExportedDiagnosticsTest::testAcceptDiagsFromFilePaths_None()
|
||||||
{
|
{
|
||||||
const QString sourceFile = filePath("tidy.modernize-use-nullptr.cpp").toString();
|
const QString sourceFile = filePath("tidy.modernize-use-nullptr.cpp").toString();
|
||||||
const QString exportedFile = createFile(filePath("tidy.modernize-use-nullptr.yaml").toString(),
|
const FilePath exportedFile = createFile(filePath("tidy.modernize-use-nullptr.yaml").toString(),
|
||||||
sourceFile);
|
sourceFile);
|
||||||
const auto acceptNone = [](const Utils::FilePath &) { return false; };
|
const auto acceptNone = [](const FilePath &) { return false; };
|
||||||
const Diagnostics diags = readExportedDiagnostics(FilePath::fromString(exportedFile),
|
const expected_str<Diagnostics> diags
|
||||||
acceptNone, &m_message);
|
= readExportedDiagnostics(exportedFile, acceptNone);
|
||||||
QVERIFY2(m_message.isEmpty(), qPrintable(m_message));
|
QVERIFY(diags.has_value());
|
||||||
QVERIFY(diags.isEmpty());
|
QVERIFY(diags->isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Diagnostics from clang (static) analyzer passed through via clang-tidy
|
// Diagnostics from clang (static) analyzer passed through via clang-tidy
|
||||||
void ReadExportedDiagnosticsTest::testTidy_ClangAnalyzer()
|
void ReadExportedDiagnosticsTest::testTidy_ClangAnalyzer()
|
||||||
{
|
{
|
||||||
const FilePath sourceFile = filePath("clang-analyzer.dividezero.cpp");
|
const FilePath sourceFile = filePath("clang-analyzer.dividezero.cpp");
|
||||||
const QString exportedFile = createFile(
|
const FilePath exportedFile
|
||||||
filePath(appendYamlSuffix("clang-analyzer.dividezero")).toString(),
|
= createFile(filePath(appendYamlSuffix("clang-analyzer.dividezero")).toString(),
|
||||||
sourceFile.toString());
|
sourceFile.toString());
|
||||||
Diagnostic expectedDiag;
|
Diagnostic expectedDiag;
|
||||||
expectedDiag.name = "clang-analyzer-core.DivideZero";
|
expectedDiag.name = "clang-analyzer-core.DivideZero";
|
||||||
expectedDiag.location = {sourceFile, 4, 15};
|
expectedDiag.location = {sourceFile, 4, 15};
|
||||||
@@ -128,16 +126,15 @@ void ReadExportedDiagnosticsTest::testTidy_ClangAnalyzer()
|
|||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const Diagnostics diags = readExportedDiagnostics(Utils::FilePath::fromString(exportedFile),
|
const expected_str<Diagnostics> diags = readExportedDiagnostics(exportedFile);
|
||||||
{}, &m_message);
|
QVERIFY(diags.has_value());
|
||||||
QVERIFY2(m_message.isEmpty(), qPrintable(m_message));
|
QCOMPARE(*diags, {expectedDiag});
|
||||||
QCOMPARE(diags, {expectedDiag});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadExportedDiagnosticsTest::testClazy()
|
void ReadExportedDiagnosticsTest::testClazy()
|
||||||
{
|
{
|
||||||
const FilePath sourceFile = filePath("clazy.qgetenv.cpp");
|
const FilePath sourceFile = filePath("clazy.qgetenv.cpp");
|
||||||
const QString exportedFile = createFile(filePath(appendYamlSuffix("clazy.qgetenv")).toString(),
|
const FilePath exportedFile = createFile(filePath(appendYamlSuffix("clazy.qgetenv")).toString(),
|
||||||
sourceFile.toString());
|
sourceFile.toString());
|
||||||
Diagnostic expectedDiag;
|
Diagnostic expectedDiag;
|
||||||
expectedDiag.name = "clazy-qgetenv";
|
expectedDiag.name = "clazy-qgetenv";
|
||||||
@@ -156,10 +153,9 @@ void ReadExportedDiagnosticsTest::testClazy()
|
|||||||
{{sourceFile, 7, 18}, {sourceFile, 7, 29}},
|
{{sourceFile, 7, 18}, {sourceFile, 7, 29}},
|
||||||
true},
|
true},
|
||||||
};
|
};
|
||||||
const Diagnostics diags = readExportedDiagnostics(Utils::FilePath::fromString(exportedFile),
|
const expected_str<Diagnostics> diags = readExportedDiagnostics(exportedFile);
|
||||||
{}, &m_message);
|
QVERIFY(diags.has_value());
|
||||||
QVERIFY2(m_message.isEmpty(), qPrintable(m_message));
|
QCOMPARE(*diags, {expectedDiag});
|
||||||
QCOMPARE(diags, {expectedDiag});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadExportedDiagnosticsTest::testOffsetInvalidText()
|
void ReadExportedDiagnosticsTest::testOffsetInvalidText()
|
||||||
@@ -263,25 +259,24 @@ void ReadExportedDiagnosticsTest::testOffsetMultiByteCodePoint2()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Replace FILE_PATH with a real absolute file path in the *.yaml files.
|
// Replace FILE_PATH with a real absolute file path in the *.yaml files.
|
||||||
QString ReadExportedDiagnosticsTest::createFile(const QString &yamlFilePath,
|
FilePath ReadExportedDiagnosticsTest::createFile(const QString &yamlFilePath,
|
||||||
const QString &filePathToInject) const
|
const QString &filePathToInject) const
|
||||||
{
|
{
|
||||||
QTC_ASSERT(QDir::isAbsolutePath(filePathToInject), return QString());
|
QTC_ASSERT(QDir::isAbsolutePath(filePathToInject), return {});
|
||||||
const Utils::FilePath newFileName = m_baseDir->absolutePath(
|
const FilePath newFileName = m_baseDir->absolutePath(QFileInfo(yamlFilePath).fileName());
|
||||||
QFileInfo(yamlFilePath).fileName());
|
|
||||||
|
|
||||||
Utils::FileReader reader;
|
FileReader reader;
|
||||||
if (QTC_GUARD(reader.fetch(Utils::FilePath::fromString(yamlFilePath),
|
if (QTC_GUARD(reader.fetch(FilePath::fromString(yamlFilePath),
|
||||||
QIODevice::ReadOnly | QIODevice::Text))) {
|
QIODevice::ReadOnly | QIODevice::Text))) {
|
||||||
QByteArray contents = reader.data();
|
QByteArray contents = reader.data();
|
||||||
contents.replace("FILE_PATH", filePathToInject.toLocal8Bit());
|
contents.replace("FILE_PATH", filePathToInject.toLocal8Bit());
|
||||||
|
|
||||||
Utils::FileSaver fileSaver(newFileName, QIODevice::WriteOnly | QIODevice::Text);
|
FileSaver fileSaver(newFileName, QIODevice::WriteOnly | QIODevice::Text);
|
||||||
QTC_CHECK(fileSaver.write(contents));
|
QTC_CHECK(fileSaver.write(contents));
|
||||||
QTC_CHECK(fileSaver.finalize());
|
QTC_CHECK(fileSaver.finalize());
|
||||||
}
|
}
|
||||||
|
|
||||||
return newFileName.toString();
|
return newFileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
FilePath ReadExportedDiagnosticsTest::filePath(const QString &fileName) const
|
FilePath ReadExportedDiagnosticsTest::filePath(const QString &fileName) const
|
||||||
|
@@ -44,11 +44,10 @@ private slots:
|
|||||||
void testOffsetMultiByteCodePoint2();
|
void testOffsetMultiByteCodePoint2();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString createFile(const QString &yamlFilePath, const QString &filePathToInject) const;
|
Utils::FilePath createFile(const QString &yamlFilePath, const QString &filePathToInject) const;
|
||||||
Utils::FilePath filePath(const QString &fileName) const;
|
Utils::FilePath filePath(const QString &fileName) const;
|
||||||
|
|
||||||
CppEditor::Tests::TemporaryCopiedDir * const m_baseDir;
|
CppEditor::Tests::TemporaryCopiedDir * const m_baseDir;
|
||||||
QString m_message;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ClangTools::Internal
|
} // namespace ClangTools::Internal
|
||||||
|
Reference in New Issue
Block a user