diff --git a/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri b/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri index 36dfedb41c3..67fb24df110 100644 --- a/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri +++ b/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri @@ -18,7 +18,7 @@ HEADERS += \ $$PWD/usedmacro.h \ $$PWD/sourcedependency.h \ $$PWD/filestatus.h \ - $$PWD/projectpartartefacts.h + $$PWD/projectpartartefact.h !isEmpty(LIBTOOLING_LIBS) { SOURCES += \ @@ -65,4 +65,6 @@ SOURCES += \ $$PWD/sourcerangefilter.cpp \ $$PWD/symbolindexer.cpp \ $$PWD/symbolentry.cpp \ - $$PWD/symbolstorageinterface.cpp + $$PWD/symbolstorageinterface.cpp \ + $$PWD/projectpartartefact.cpp + diff --git a/src/tools/clangrefactoringbackend/source/projectpartartefact.cpp b/src/tools/clangrefactoringbackend/source/projectpartartefact.cpp new file mode 100644 index 00000000000..b1431c34073 --- /dev/null +++ b/src/tools/clangrefactoringbackend/source/projectpartartefact.cpp @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "projectpartartefact.h" + +#include + +#include +#include +#include + +namespace ClangBackEnd { + +ProjectPartArtefact::ProjectPartArtefact(Utils::SmallStringView compilerArgumentsText, Utils::SmallStringView compilerMacrosText, int projectPartId) + : compilerArguments(toStringVector(compilerArgumentsText)), + compilerMacros(toCompilerMacros(compilerMacrosText)), + projectPartId(projectPartId) +{ +} + +Utils::SmallStringVector ProjectPartArtefact::toStringVector(Utils::SmallStringView jsonText) +{ + if (jsonText.isEmpty()) + return {}; + + QJsonDocument document = createJsonDocument(jsonText, "Compiler arguments parsing error"); + + return Utils::transform(document.array(), [] (const QJsonValue &value) { + return Utils::SmallString{value.toString()}; + }); +} + +CompilerMacros ProjectPartArtefact::createCompilerMacrosFromDocument(const QJsonDocument &document) +{ + QJsonObject object = document.object(); + CompilerMacros macros; + macros.reserve(object.size()); + + for (auto current = object.constBegin(); current != object.constEnd(); ++current) + macros.emplace_back(current.key(), current.value().toString()); + + std::sort(macros.begin(), macros.end()); + + return macros; +} + +CompilerMacros ProjectPartArtefact::toCompilerMacros(Utils::SmallStringView jsonText) +{ + if (jsonText.isEmpty()) + return {}; + + QJsonDocument document = createJsonDocument(jsonText, "Compiler macros parsing error"); + + return createCompilerMacrosFromDocument(document); +} + +QJsonDocument ProjectPartArtefact::createJsonDocument(Utils::SmallStringView jsonText, + const char *whatError) +{ + QJsonParseError error; + QJsonDocument document = QJsonDocument::fromJson(QByteArray::fromRawData(jsonText.data(), + jsonText.size()), + &error); + checkError(whatError, error); + + return document; +} + +void ProjectPartArtefact::checkError(const char *whatError, const QJsonParseError &error) +{ + if (error.error != QJsonParseError::NoError) { + throw ProjectPartArtefactParseError(whatError, + error.errorString()); + } +} + +bool operator==(const ProjectPartArtefact &first, const ProjectPartArtefact &second) +{ + return first.compilerArguments == second.compilerArguments + && first.compilerMacros == second.compilerMacros; +} + +} // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/projectpartartefacts.h b/src/tools/clangrefactoringbackend/source/projectpartartefact.h similarity index 57% rename from src/tools/clangrefactoringbackend/source/projectpartartefacts.h rename to src/tools/clangrefactoringbackend/source/projectpartartefact.h index 646a87e7906..364ffbd42bf 100644 --- a/src/tools/clangrefactoringbackend/source/projectpartartefacts.h +++ b/src/tools/clangrefactoringbackend/source/projectpartartefact.h @@ -25,14 +25,14 @@ #pragma once -#include +#include "projectpartartefactexception.h" + #include #include -#include -#include -#include +QT_FORWARD_DECLARE_CLASS(QJsonDocument) +QT_FORWARD_DECLARE_STRUCT(QJsonParseError) namespace ClangBackEnd { @@ -41,45 +41,21 @@ class ProjectPartArtefact public: ProjectPartArtefact(Utils::SmallStringView compilerArgumentsText, Utils::SmallStringView compilerMacrosText, - int projectPartId) - : compilerArguments(toStringVector(compilerArgumentsText)), - compilerMacros(toCompilerMacros(compilerMacrosText)), - projectPartId(projectPartId) - { - } + int projectPartId); static - Utils::SmallStringVector toStringVector(Utils::SmallStringView jsonText) - { - QJsonDocument document = QJsonDocument::fromJson(QByteArray::fromRawData(jsonText.data(), - jsonText.size())); - - return Utils::transform(document.array(), [] (const QJsonValue &value) { - return Utils::SmallString{value.toString()}; - }); - } - + Utils::SmallStringVector toStringVector(Utils::SmallStringView jsonText); static - CompilerMacros toCompilerMacros(Utils::SmallStringView jsonText) - { - QJsonDocument document = QJsonDocument::fromJson(QByteArray::fromRawData(jsonText.data(), - jsonText.size())); - QJsonObject object = document.object(); - CompilerMacros macros; - macros.reserve(object.size()); - - for (auto current = object.constBegin(); current != object.constEnd(); ++current) - macros.emplace_back(current.key(), current.value().toString()); - - return macros; - } - + CompilerMacros createCompilerMacrosFromDocument(const QJsonDocument &document); + static + CompilerMacros toCompilerMacros(Utils::SmallStringView jsonText); + static + QJsonDocument createJsonDocument(Utils::SmallStringView jsonText, + const char *whatError); + static + void checkError(const char *whatError, const QJsonParseError &error); friend - bool operator==(const ProjectPartArtefact &first, const ProjectPartArtefact &second) - { - return first.compilerArguments == second.compilerArguments - && first.compilerMacros == second.compilerMacros; - } + bool operator==(const ProjectPartArtefact &first, const ProjectPartArtefact &second); public: Utils::SmallStringVector compilerArguments; @@ -88,4 +64,4 @@ public: }; using ProjectPartArtefacts = std::vector; -} +} // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/projectpartartefactexception.h b/src/tools/clangrefactoringbackend/source/projectpartartefactexception.h new file mode 100644 index 00000000000..22f1b3ed945 --- /dev/null +++ b/src/tools/clangrefactoringbackend/source/projectpartartefactexception.h @@ -0,0 +1,40 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include + +namespace ClangBackEnd { + +class ProjectPartArtefactParseError : public Sqlite::Exception +{ +public: + ProjectPartArtefactParseError(const char *whatErrorHasHappen, + Utils::SmallString &&errorMessage) + : Exception(whatErrorHasHappen, std::move(errorMessage)) + { + } +}; + +} diff --git a/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h b/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h index cd77704328e..a68c91e56df 100644 --- a/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h +++ b/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h @@ -27,7 +27,7 @@ #include "filestatus.h" #include "projectpartentry.h" -#include "projectpartartefacts.h" +#include "projectpartartefact.h" #include "sourcelocationentry.h" #include "sourcedependency.h" #include "symbolentry.h" diff --git a/tests/unit/unittest/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp index 2403175bfd1..bacc0be5587 100644 --- a/tests/unit/unittest/gtest-creator-printing.cpp +++ b/tests/unit/unittest/gtest-creator-printing.cpp @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/tests/unit/unittest/mocksqlitereadstatement.h b/tests/unit/unittest/mocksqlitereadstatement.h index c0773a512fc..d0566b9c917 100644 --- a/tests/unit/unittest/mocksqlitereadstatement.h +++ b/tests/unit/unittest/mocksqlitereadstatement.h @@ -31,7 +31,7 @@ #include #include -#include +#include #include diff --git a/tests/unit/unittest/projectpartartefact-test.cpp b/tests/unit/unittest/projectpartartefact-test.cpp index a7328125438..03dcf9c0d76 100644 --- a/tests/unit/unittest/projectpartartefact-test.cpp +++ b/tests/unit/unittest/projectpartartefact-test.cpp @@ -25,7 +25,7 @@ #include "googletest.h" -#include +#include namespace { @@ -38,6 +38,19 @@ TEST(ProjectPartArtefact, CompilerArguments) ASSERT_THAT(artefact.compilerArguments, ElementsAre(Eq("-DFoo"), Eq("-DBar"))); } +TEST(ProjectPartArtefact, EmptyCompilerArguments) +{ + ClangBackEnd::ProjectPartArtefact artefact{"", "", 1}; + + ASSERT_THAT(artefact.compilerArguments, IsEmpty()); +} + +TEST(ProjectPartArtefact, CompilerArgumentsParseError) +{ + ASSERT_THROW(ClangBackEnd::ProjectPartArtefact("\"-DFoo\",\"-DBar\"]", "", 1), + ClangBackEnd::ProjectPartArtefactParseError); +} + TEST(ProjectPartArtefact, CompilerMacros) { ClangBackEnd::ProjectPartArtefact artefact{"", "{\"Foo\":\"1\",\"Bar\":\"42\"}", 1}; @@ -45,4 +58,18 @@ TEST(ProjectPartArtefact, CompilerMacros) ASSERT_THAT(artefact.compilerMacros, UnorderedElementsAre(Eq(CompilerMacro{"Foo", "1"}), Eq(CompilerMacro{"Bar", "42"}))); } + +TEST(ProjectPartArtefact, EmptyCompilerMacros) +{ + ClangBackEnd::ProjectPartArtefact artefact{"", "", 1}; + + ASSERT_THAT(artefact.compilerMacros, IsEmpty()); +} + +TEST(ProjectPartArtefact, CompilerMacrosParseError) +{ + ASSERT_THROW(ClangBackEnd::ProjectPartArtefact("", "\"Foo\":\"1\",\"Bar\":\"42\"}", 1), + ClangBackEnd::ProjectPartArtefactParseError); +} + } diff --git a/tests/unit/unittest/symbolindexer-test.cpp b/tests/unit/unittest/symbolindexer-test.cpp index fe509beda1f..8336345e6df 100644 --- a/tests/unit/unittest/symbolindexer-test.cpp +++ b/tests/unit/unittest/symbolindexer-test.cpp @@ -82,12 +82,12 @@ protected: ClangBackEnd::FilePathId generatedFilePathId{1, 21}; ProjectPartContainer projectPart1{"project1", {"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"}, - {{"DEFINE", "1"}}, + {{"BAR", "1"}, {"FOO", "1"}}, {header1PathId}, {main1PathId}}; ProjectPartContainer projectPart2{"project2", {"-I", TESTDATA_DIR, "-x", "c++-header", "-Wno-pragma-once-outside-header"}, - {{"DEFINE", "1"}}, + {{"BAR", "1"}, {"FOO", "0"}}, {header2PathId}, {main2PathId}}; FileContainers unsaved{{{TESTDATA_DIR, "query_simplefunction.h"}, @@ -99,7 +99,7 @@ protected: UsedMacros usedMacros{{"Foo", {1, 1}}}; FileStatuses fileStatus{{{1, 2}, 3, 4}}; SourceDependencies sourceDependencies{{{1, 1}, {1, 2}}, {{1, 1}, {1, 3}}}; - ClangBackEnd::ProjectPartArtefact artefact{"[-DFOO]", "{\"FOO\":\"1\"}", 74}; + ClangBackEnd::ProjectPartArtefact artefact{"[\"-DFOO\"]", "{\"FOO\":\"1\",\"BAR\":\"1\"}", 74}; NiceMock mockSqliteTransactionBackend; NiceMock mockCollector; NiceMock mockStorage; @@ -178,10 +178,10 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsUpdateProjectPartsInStorage) { EXPECT_CALL(mockStorage, insertOrUpdateProjectPart(Eq("project1"), ElementsAre("-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"), - ElementsAre(CompilerMacro{"DEFINE", "1"}))); + ElementsAre(CompilerMacro{"BAR", "1"}, CompilerMacro{"FOO", "1"}))); EXPECT_CALL(mockStorage, insertOrUpdateProjectPart(Eq("project2"), ElementsAre("-I", TESTDATA_DIR, "-x", "c++-header", "-Wno-pragma-once-outside-header"), - ElementsAre(CompilerMacro{"DEFINE", "1"}))); + ElementsAre(CompilerMacro{"BAR", "1"}, CompilerMacro{"FOO", "0"}))); indexer.updateProjectParts({projectPart1, projectPart2}, Utils::clone(unsaved)); } diff --git a/tests/unit/unittest/symbolstorage-test.cpp b/tests/unit/unittest/symbolstorage-test.cpp index f0e1e3f2473..536cbbe4ffa 100644 --- a/tests/unit/unittest/symbolstorage-test.cpp +++ b/tests/unit/unittest/symbolstorage-test.cpp @@ -90,7 +90,7 @@ protected: {2, {"function2USR", "function2"}}}; SourceLocationEntries sourceLocations{{1, {1, 3}, {42, 23}, SymbolType::Declaration}, {2, {1, 4}, {7, 11}, SymbolType::Declaration}}; - ClangBackEnd::ProjectPartArtefact artefact{"-DFOO", "{\"FOO\":\"1\"}", 74}; + ClangBackEnd::ProjectPartArtefact artefact{"[\"-DFOO\"]", "{\"FOO\":\"1\"}", 74}; Storage storage{statementFactory, filePathCache}; }; diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro index c40571bd0a2..81efab24636 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -92,6 +92,7 @@ SOURCES += \ nativefilepathview-test.cpp \ mocktimer.cpp \ tokenprocessor-test.cpp \ + projectpartartefact-test.cpp \ highlightingresultreporter-test.cpp !isEmpty(LIBCLANG_LIBS) {