aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorEike Ziller <eike.ziller@qt.io>2018-01-17 09:30:57 +0100
committerEike Ziller <eike.ziller@qt.io>2018-01-17 09:30:57 +0100
commit115afed94b8e85db29b0c057e7c143a3d053d6cc (patch)
tree7663d95ed448c963ab8b913b675a78f0dea65fdc /tests
parent76bc20ffceadfff894dfd98a0285ae52577be3bf (diff)
parent2765409d2bdc79753f96bf6bb894b2884ac5b0cd (diff)
Merge remote-tracking branch 'origin/4.6'
Conflicts: tests/unit/unittest/gtest-creator-printing.cpp tests/unit/unittest/gtest-creator-printing.h Change-Id: I43d2571617bfbf41c0fcf23502ab77975540eba4
Diffstat (limited to 'tests')
-rw-r--r--tests/unit/echoserver/echoclangcodemodelserver.cpp5
-rw-r--r--tests/unit/echoserver/echoclangcodemodelserver.h1
-rw-r--r--tests/unit/unittest/clangtooltipinfo-test.cpp628
-rw-r--r--tests/unit/unittest/conditionally-disabled-tests.h6
-rw-r--r--tests/unit/unittest/data/tooltipinfo.cpp180
-rw-r--r--tests/unit/unittest/data/tooltipinfo.h3
-rw-r--r--tests/unit/unittest/dummyclangipcclient.h1
-rw-r--r--tests/unit/unittest/gtest-creator-printing.cpp46
-rw-r--r--tests/unit/unittest/gtest-creator-printing.h6
-rw-r--r--tests/unit/unittest/mockclangcodemodelclient.h2
-rw-r--r--tests/unit/unittest/mockclangcodemodelserver.h2
-rw-r--r--tests/unit/unittest/unittest.pro1
-rw-r--r--tests/unit/unittest/unsavedfile-test.cpp28
13 files changed, 908 insertions, 1 deletions
diff --git a/tests/unit/echoserver/echoclangcodemodelserver.cpp b/tests/unit/echoserver/echoclangcodemodelserver.cpp
index 2c0fea98c9..38d2d39544 100644
--- a/tests/unit/echoserver/echoclangcodemodelserver.cpp
+++ b/tests/unit/echoserver/echoclangcodemodelserver.cpp
@@ -98,6 +98,11 @@ void EchoClangCodeModelServer::requestFollowSymbol(const RequestFollowSymbolMess
echoMessage(message);
}
+void EchoClangCodeModelServer::requestToolTip(const RequestToolTipMessage &message)
+{
+ echoMessage(message);
+}
+
void EchoClangCodeModelServer::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message)
{
echoMessage(message);
diff --git a/tests/unit/echoserver/echoclangcodemodelserver.h b/tests/unit/echoserver/echoclangcodemodelserver.h
index 2dc8c30913..d3452d2d32 100644
--- a/tests/unit/echoserver/echoclangcodemodelserver.h
+++ b/tests/unit/echoserver/echoclangcodemodelserver.h
@@ -47,6 +47,7 @@ public:
void requestDocumentAnnotations(const RequestDocumentAnnotationsMessage &message) override;
void requestReferences(const RequestReferencesMessage &message) override;
void requestFollowSymbol(const RequestFollowSymbolMessage &message) override;
+ void requestToolTip(const RequestToolTipMessage &message) override;
void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override;
private:
diff --git a/tests/unit/unittest/clangtooltipinfo-test.cpp b/tests/unit/unittest/clangtooltipinfo-test.cpp
new file mode 100644
index 0000000000..4f6c980649
--- /dev/null
+++ b/tests/unit/unittest/clangtooltipinfo-test.cpp
@@ -0,0 +1,628 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 "googletest.h"
+#include "rundocumentparse-utility.h"
+
+#include <clangdocument.h>
+#include <clangdocuments.h>
+#include <clangsupport_global.h>
+#include <clangtooltipinfocollector.h>
+#include <clangtranslationunit.h>
+#include <fixitcontainer.h>
+#include <projectpart.h>
+#include <projects.h>
+#include <sourcelocationcontainer.h>
+#include <sourcerangecontainer.h>
+#include <unsavedfiles.h>
+
+#include <utils/qtcassert.h>
+
+#include <clang-c/Index.h>
+
+using ::ClangBackEnd::ProjectPart;
+using ::ClangBackEnd::SourceLocationContainer;
+using ::ClangBackEnd::Document;
+using ::ClangBackEnd::UnsavedFiles;
+using ::ClangBackEnd::ToolTipInfo;
+using ::ClangBackEnd::SourceRangeContainer;
+
+namespace {
+
+#define CHECK_MEMBER(actual, expected, memberName) \
+ if (actual.memberName() != expected.memberName()) { \
+ *result_listener << #memberName " is " + PrintToString(actual.memberName()) \
+ << " and not " + PrintToString(expected.memberName()); \
+ return false; \
+ }
+
+MATCHER_P(IsToolTip, expected, std::string(negation ? "isn't" : "is") + PrintToString(expected))
+{
+ CHECK_MEMBER(arg, expected, text);
+ CHECK_MEMBER(arg, expected, briefComment);
+
+ CHECK_MEMBER(arg, expected, qdocIdCandidates);
+ CHECK_MEMBER(arg, expected, qdocMark);
+ CHECK_MEMBER(arg, expected, qdocCategory);
+
+ CHECK_MEMBER(arg, expected, sizeInBytes);
+
+ return true;
+}
+
+MATCHER_P(IsQdocToolTip, expected, std::string(negation ? "isn't" : "is") + PrintToString(expected))
+{
+ CHECK_MEMBER(arg, expected, qdocIdCandidates);
+ CHECK_MEMBER(arg, expected, qdocMark);
+ CHECK_MEMBER(arg, expected, qdocCategory);
+
+ return true;
+}
+
+#undef CHECK_MEMBER
+
+struct Data {
+ ProjectPart projectPart{Utf8StringLiteral("projectPartId"), {Utf8StringLiteral("-std=c++14")}};
+ ClangBackEnd::ProjectParts projects;
+ ClangBackEnd::UnsavedFiles unsavedFiles;
+ ClangBackEnd::Documents documents{projects, unsavedFiles};
+ Document document{Utf8StringLiteral(TESTDATA_DIR "/tooltipinfo.cpp"),
+ projectPart,
+ {},
+ documents};
+ UnitTest::RunDocumentParse _1{document};
+};
+
+class ToolTipInfo : public ::testing::Test
+{
+protected:
+ ::ToolTipInfo tooltip(uint line, uint column)
+ {
+ return d->document.translationUnit().tooltip(d->unsavedFiles,
+ Utf8StringLiteral("UTF-8"),
+ line,
+ column);
+ }
+
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+
+private:
+ static std::unique_ptr<Data> d;
+};
+
+TEST_F(ToolTipInfo, LocalVariableInt)
+{
+ const ::ToolTipInfo actual = tooltip(3, 5);
+
+ ASSERT_THAT(actual, IsToolTip(::ToolTipInfo(Utf8StringLiteral("int"))));
+}
+
+TEST_F(ToolTipInfo, LocalVariablePointerToConstInt)
+{
+ const ::ToolTipInfo actual = tooltip(4, 5);
+
+ ASSERT_THAT(actual, IsToolTip(::ToolTipInfo(Utf8StringLiteral("const int *"))));
+}
+
+TEST_F(ToolTipInfo, LocalParameterVariableConstRefCustomType)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("const Foo &"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("Foo")});
+ expected.setQdocMark(Utf8StringLiteral("Foo"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(12, 12);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, LocalNonParameterVariableConstRefCustomType)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("const Foo"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("Foo")});
+ expected.setQdocMark(Utf8StringLiteral("Foo"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(14, 5);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, MemberVariable)
+{
+ const ::ToolTipInfo actual = tooltip(12, 16);
+
+ ASSERT_THAT(actual, IsToolTip(::ToolTipInfo(Utf8StringLiteral("int"))));
+}
+
+TEST_F(ToolTipInfo, DISABLED_WITHOUT_PRETTYDECL_PATCH(MemberFunctionCall_QualifiedName))
+{
+ const ::ToolTipInfo actual = tooltip(21, 9);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("int Bar::mem()"));
+}
+
+// ChangeLog: Show extra specifiers. For functions e.g.: virtual, inline, explicit, const, volatile
+TEST_F(ToolTipInfo, DISABLED_WITHOUT_PRETTYDECL_PATCH(MemberFunctionCall_ExtraSpecifiers))
+{
+ const ::ToolTipInfo actual = tooltip(22, 9);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("virtual int Bar::virtualConstMem() const"));
+}
+
+TEST_F(ToolTipInfo, MemberFunctionCall_qdocIdCandidates)
+{
+ const ::ToolTipInfo actual = tooltip(21, 9);
+
+ ASSERT_THAT(actual.qdocIdCandidates(), ElementsAre(Utf8StringLiteral("Bar::mem"),
+ Utf8StringLiteral("mem")));
+}
+
+TEST_F(ToolTipInfo, MemberFunctionCall_qdocMark_FIXLIBCLANG_CHECKED)
+{
+ const ::ToolTipInfo actual = tooltip(21, 9);
+
+ ASSERT_THAT(actual.qdocMark(), Utf8StringLiteral("mem()"));
+}
+
+// TODO: Check what is really needed for qdoc before implementing this one.
+TEST_F(ToolTipInfo, DISABLED_MemberFunctionCall_qdocMark_extraSpecifiers)
+{
+ const ::ToolTipInfo actual = tooltip(22, 9);
+
+ ASSERT_THAT(actual.qdocMark(), Utf8StringLiteral("virtualConstMem() const"));
+}
+
+TEST_F(ToolTipInfo, MemberFunctionCall_qdocCategory)
+{
+ const ::ToolTipInfo actual = tooltip(21, 9);
+
+ ASSERT_THAT(actual.qdocCategory(), ::ToolTipInfo::Function);
+}
+
+// TODO: Show the template parameter type, too: "template<typename T>...)"
+TEST_F(ToolTipInfo, DISABLED_WITHOUT_PRETTYDECL_PATCH(TemplateFunctionCall))
+{
+ const ::ToolTipInfo actual = tooltip(30, 5);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("template<> void t<Foo>(int foo)"));
+}
+
+TEST_F(ToolTipInfo, TemplateFunctionCall_qdocIdCandidates)
+{
+ const ::ToolTipInfo actual = tooltip(30, 5);
+
+ ASSERT_THAT(actual.qdocIdCandidates(), ElementsAre(Utf8StringLiteral("t")));
+}
+
+TEST_F(ToolTipInfo, TemplateFunctionCall_qdocMark_FIXLIBCLANG_CHECKED)
+{
+ const ::ToolTipInfo actual = tooltip(30, 5);
+
+ ASSERT_THAT(actual.qdocMark(), Utf8StringLiteral("t(int)"));
+}
+
+TEST_F(ToolTipInfo, TemplateFunctionCall_qdocCategory)
+{
+ const ::ToolTipInfo actual = tooltip(30, 5);
+
+ ASSERT_THAT(actual.qdocCategory(), ::ToolTipInfo::Function);
+}
+
+TEST_F(ToolTipInfo, BriefComment)
+{
+ const ::ToolTipInfo actual = tooltip(41, 5);
+
+ ASSERT_THAT(actual.briefComment(), Utf8StringLiteral("This is a crazy function."));
+}
+
+TEST_F(ToolTipInfo, Enum)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("EnumType"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("EnumType")});
+ expected.setQdocMark(Utf8StringLiteral("EnumType"));
+ expected.setQdocCategory(::ToolTipInfo::Enum);
+
+ const ::ToolTipInfo actual = tooltip(49, 12);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, Enumerator)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("6"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("Custom")});
+ expected.setQdocMark(Utf8StringLiteral("EnumType"));
+ expected.setQdocCategory(::ToolTipInfo::Enum);
+
+ const ::ToolTipInfo actual = tooltip(49, 22);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, TemplateTypeFromParameter)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("const Baz<int> &"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("Baz")});
+ expected.setQdocMark(Utf8StringLiteral("Baz"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(55, 25);
+
+ ASSERT_THAT(actual, IsQdocToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, TemplateTypeFromNonParameter)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("Baz<int>"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("Baz")});
+ expected.setQdocMark(Utf8StringLiteral("Baz"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(56, 19);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, IncludeDirective)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral(TESTDATA_DIR"/tooltipinfo.h"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("tooltipinfo.h")});
+ expected.setQdocMark(Utf8StringLiteral("tooltipinfo.h"));
+ expected.setQdocCategory(::ToolTipInfo::Brief);
+
+ const ::ToolTipInfo actual = tooltip(59, 11);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, MacroUse_WithMacroFromSameFile)
+{
+ const ::ToolTipInfo actual = tooltip(66, 5);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("#define MACRO_FROM_MAINFILE(x) x + 3"));
+}
+
+TEST_F(ToolTipInfo, MacroUse_WithMacroFromHeader)
+{
+ const ::ToolTipInfo actual = tooltip(67, 5);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("#define MACRO_FROM_HEADER(x) x + \\\n x + \\\n x"));
+}
+
+TEST_F(ToolTipInfo, MacroUse_qdoc)
+{
+ ::ToolTipInfo expected;
+ expected.setQdocIdCandidates({Utf8StringLiteral("MACRO_FROM_MAINFILE")});
+ expected.setQdocMark(Utf8StringLiteral("MACRO_FROM_MAINFILE"));
+ expected.setQdocCategory(::ToolTipInfo::Macro);
+
+ const ::ToolTipInfo actual = tooltip(66, 5);
+
+ ASSERT_THAT(actual, IsQdocToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, TypeNameIntroducedByUsingDirectiveIsQualified)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("N::Muu"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("N::Muu"), Utf8StringLiteral("Muu")});
+ expected.setQdocMark(Utf8StringLiteral("Muu"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(77, 5);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, TypeNameIntroducedByUsingDirectiveOfAliasIsResolvedAndQualified)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("N::Muu"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("N::Muu"), Utf8StringLiteral("Muu")});
+ expected.setQdocMark(Utf8StringLiteral("Muu"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(82, 5);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, TypeNameIntroducedByUsingDeclarationIsQualified)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("N::Muu"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("N::Muu"), Utf8StringLiteral("Muu")});
+ expected.setQdocMark(Utf8StringLiteral("Muu"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(87, 5);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, SizeForClassDefinition)
+{
+ const ::ToolTipInfo actual = tooltip(92, 8);
+
+ ASSERT_THAT(actual.sizeInBytes(), Utf8StringLiteral("2"));
+}
+
+TEST_F(ToolTipInfo, SizeForMemberField)
+{
+ const ::ToolTipInfo actual = tooltip(95, 10);
+
+ ASSERT_THAT(actual.sizeInBytes(), Utf8StringLiteral("1"));
+}
+
+TEST_F(ToolTipInfo, SizeForEnum)
+{
+ const ::ToolTipInfo actual = tooltip(97, 12);
+
+ ASSERT_THAT(actual.sizeInBytes(), Utf8StringLiteral("4"));
+}
+
+TEST_F(ToolTipInfo, SizeForUnion)
+{
+ const ::ToolTipInfo actual = tooltip(98, 7);
+
+ ASSERT_THAT(actual.sizeInBytes(), Utf8StringLiteral("1"));
+}
+
+TEST_F(ToolTipInfo, Namespace)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("X"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("X")});
+ expected.setQdocMark(Utf8StringLiteral("X"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(106, 11);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, NamespaceQualified)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("X::Y"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("X::Y"), Utf8StringLiteral("Y")});
+ expected.setQdocMark(Utf8StringLiteral("Y"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(107, 11);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+// TODO: Show unresolved and resolved name, for F1 try both.
+TEST_F(ToolTipInfo, TypeName_ResolveTypeDef)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("Ptr<Nuu>"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("PtrFromTypeDef")});
+ expected.setQdocMark(Utf8StringLiteral("PtrFromTypeDef"));
+ expected.setQdocCategory(::ToolTipInfo::Typedef);
+
+ const ::ToolTipInfo actual = tooltip(122, 5);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+// TODO: Show unresolved and resolved name, for F1 try both.
+TEST_F(ToolTipInfo, TypeName_ResolveAlias)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("Ptr<Nuu>"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("PtrFromTypeAlias")});
+ expected.setQdocMark(Utf8StringLiteral("PtrFromTypeAlias"));
+ expected.setQdocCategory(::ToolTipInfo::Typedef);
+
+ const ::ToolTipInfo actual = tooltip(123, 5);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+// The referenced cursor is a CXCursor_TypeAliasTemplateDecl, its type is invalid
+// and so probably clang_getTypedefDeclUnderlyingType() does not return anything useful.
+// TODO: Fix the cursor's type or add new API in libclang for querying the template type alias.
+TEST_F(ToolTipInfo, DISABLED_TypeName_ResolveTemplateTypeAlias)
+{
+ const ::ToolTipInfo actual = tooltip(124, 5);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("Ptr<Nuu>"));
+}
+
+TEST_F(ToolTipInfo, TypeName_ResolveTemplateTypeAlias_qdoc)
+{
+ ::ToolTipInfo expected;
+ expected.setQdocIdCandidates({Utf8StringLiteral("PtrFromTemplateTypeAlias")});
+ expected.setQdocMark(Utf8StringLiteral("PtrFromTemplateTypeAlias"));
+ expected.setQdocCategory(::ToolTipInfo::Typedef);
+
+ const ::ToolTipInfo actual = tooltip(124, 5);
+
+ ASSERT_THAT(actual, IsQdocToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, TemplateClassReference)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("Zii<T>"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("Zii")});
+ expected.setQdocMark(Utf8StringLiteral("Zii"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(134, 5);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, TemplateClassQualified)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("U::Yii<T>"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("U::Yii"), Utf8StringLiteral("Yii")});
+ expected.setQdocMark(Utf8StringLiteral("Yii"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(135, 5);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, ResolveNamespaceAliasForType)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("A::X"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("A::X"), Utf8StringLiteral("X")});
+ expected.setQdocMark(Utf8StringLiteral("X"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(144, 8);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+// TODO: Show unresolved and resolved name, for F1 try both.
+TEST_F(ToolTipInfo, ResolveNamespaceAlias)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("A"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("B")});
+ expected.setQdocMark(Utf8StringLiteral("B"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+
+ const ::ToolTipInfo actual = tooltip(144, 5);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, QualificationForTemplateClassInClassInNamespace)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("N::Outer::Inner<int>"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("N::Outer::Inner"),
+ Utf8StringLiteral("Outer::Inner"),
+ Utf8StringLiteral("Inner")});
+ expected.setQdocMark(Utf8StringLiteral("Inner"));
+ expected.setQdocCategory(::ToolTipInfo::ClassOrNamespace);
+ expected.setSizeInBytes(Utf8StringLiteral("1"));
+
+ const ::ToolTipInfo actual = tooltip(153, 16);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, Function)
+{
+ ::ToolTipInfo expected(Utf8StringLiteral("void f()"));
+ expected.setQdocIdCandidates({Utf8StringLiteral("f")});
+ expected.setQdocMark(Utf8StringLiteral("f()"));
+ expected.setQdocCategory(::ToolTipInfo::Function);
+
+ const ::ToolTipInfo actual = tooltip(165, 5);
+
+ ASSERT_THAT(actual, IsToolTip(expected));
+}
+
+TEST_F(ToolTipInfo, Function_QualifiedName)
+{
+ const ::ToolTipInfo actual = tooltip(166, 8);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("void R::f()"));
+}
+
+TEST_F(ToolTipInfo, Function_qdocIdCandidatesAreQualified)
+{
+ const ::ToolTipInfo actual = tooltip(166, 8);
+
+ ASSERT_THAT(actual.qdocIdCandidates(), ElementsAre(Utf8StringLiteral("R::f"),
+ Utf8StringLiteral("f")));
+}
+
+TEST_F(ToolTipInfo, DISABLED_WITHOUT_PRETTYDECL_PATCH(Function_HasParameterName))
+{
+ const ::ToolTipInfo actual = tooltip(167, 5);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("void f(int param)"));
+}
+
+// TODO: Implement with CXPrintingPolicy
+TEST_F(ToolTipInfo, DISABLED_Function_HasDefaultArgument)
+{
+ const ::ToolTipInfo actual = tooltip(168, 5);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("void z(int = 1)"));
+}
+
+TEST_F(ToolTipInfo, Function_qdocMarkHasNoParameterName)
+{
+ const ::ToolTipInfo actual = tooltip(167, 5);
+
+ ASSERT_THAT(actual.qdocMark(), Utf8StringLiteral("f(int)"));
+}
+
+TEST_F(ToolTipInfo, Function_qdocMarkHasNoDefaultArgument)
+{
+ const ::ToolTipInfo actual = tooltip(168, 5);
+
+ ASSERT_THAT(actual.qdocMark(), Utf8StringLiteral("z(int)"));
+}
+
+TEST_F(ToolTipInfo, AutoTypeBuiltin)
+{
+ const ::ToolTipInfo actual = tooltip(176, 5);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("int"));
+}
+
+// TODO: Test for qdoc entries, too.
+TEST_F(ToolTipInfo, AutoTypeEnum)
+{
+ const ::ToolTipInfo actual = tooltip(177, 5);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("EnumType"));
+}
+
+// TODO: Test for qdoc entries, too.
+TEST_F(ToolTipInfo, AutoTypeClassType)
+{
+ const ::ToolTipInfo actual = tooltip(178, 5);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("Bar"));
+}
+
+// TODO: Test for qdoc entries, too.
+// TODO: Deduced template arguments work, too?!
+TEST_F(ToolTipInfo, AutoTypeClassTemplateType)
+{
+ const ::ToolTipInfo actual = tooltip(179, 5);
+
+ ASSERT_THAT(actual.text(), Utf8StringLiteral("Zii<int>"));
+}
+
+std::unique_ptr<Data> ToolTipInfo::d;
+
+void ToolTipInfo::SetUpTestCase()
+{
+ d.reset(new Data);
+}
+
+void ToolTipInfo::TearDownTestCase()
+{
+ d.reset();
+}
+
+} // anonymous namespace
diff --git a/tests/unit/unittest/conditionally-disabled-tests.h b/tests/unit/unittest/conditionally-disabled-tests.h
index 27e6fe173b..8f55db10d7 100644
--- a/tests/unit/unittest/conditionally-disabled-tests.h
+++ b/tests/unit/unittest/conditionally-disabled-tests.h
@@ -33,3 +33,9 @@
#else
# define DISABLED_ON_WINDOWS(x) x
#endif
+
+#ifdef IS_PRETTY_DECL_SUPPORTED
+# define DISABLED_WITHOUT_PRETTYDECL_PATCH(x) x
+#else
+# define DISABLED_WITHOUT_PRETTYDECL_PATCH(x) DISABLED_##x
+#endif
diff --git a/tests/unit/unittest/data/tooltipinfo.cpp b/tests/unit/unittest/data/tooltipinfo.cpp
new file mode 100644
index 0000000000..1945577b63
--- /dev/null
+++ b/tests/unit/unittest/data/tooltipinfo.cpp
@@ -0,0 +1,180 @@
+void f(int foo, const int *cfoo)
+{
+ foo++;
+ cfoo++;
+}
+
+
+
+struct Foo { int member = 0; };
+int g(const Foo &foo)
+{
+ return foo.member;
+ const Foo bar;
+ bar;
+}
+
+struct Bar { virtual ~Bar(); int mem(){} virtual int virtualConstMem() const; };
+void h(const Foo &foo, Bar &bar)
+{
+ g(foo);
+ bar.mem();
+ bar.virtualConstMem();
+}
+
+
+template <typename T>
+void t(int foo) { (void)foo; }
+void c()
+{
+ t<Foo>(3);
+}
+
+
+
+/**
+ * \brief This is a crazy function.
+ */
+void documentedFunction();
+void d()
+{
+ documentedFunction();
+}
+
+
+
+enum EnumType { V1, V2, Custom = V2 + 5 };
+EnumType e()
+{
+ return EnumType::Custom;
+}
+
+
+
+template <typename T> struct Baz { T member; };
+void t2(const Baz<int> &b) {
+ Baz<int> baz; baz = b;
+}
+
+#include "tooltipinfo.h"
+
+
+
+#define MACRO_FROM_MAINFILE(x) x + 3
+void foo()
+{
+ MACRO_FROM_MAINFILE(7);
+ MACRO_FROM_HEADER(7);
+}
+
+
+
+namespace N { struct Muu{}; }
+namespace G = N;
+void o()
+{
+ using namespace N;
+ Muu muu; (void)muu;
+}
+void n()
+{
+ using namespace G;
+ Muu muu; (void)muu;
+}
+void q()
+{
+ using N::Muu;
+ Muu muu; (void)muu;
+}
+
+
+
+struct Sizes
+{
+ char memberChar1;
+ char memberChar2;
+};
+enum class FancyEnumType { V1, V2 };
+union Union
+{
+ char memberChar1;
+ char memberChar2;
+};
+
+
+
+namespace X {
+namespace Y {
+}
+}
+
+
+
+template<typename T> struct Ptr {};
+struct Nuu {};
+
+typedef Ptr<Nuu> PtrFromTypeDef;
+using PtrFromTypeAlias = Ptr<Nuu>;
+template<typename T> using PtrFromTemplateTypeAlias = Ptr<T>;
+
+void y()
+{
+ PtrFromTypeDef b; (void)b;
+ PtrFromTypeAlias a; (void)a;
+ PtrFromTemplateTypeAlias<Nuu> c; (void)c;
+}
+
+
+
+template <typename T> struct Zii {};
+namespace U { template <typename T> struct Yii {}; }
+void mc()
+{
+ using namespace U;
+ Zii<int> zii; (void) zii;
+ Yii<int> yii; (void) yii;
+}
+
+
+
+namespace A { struct X {}; }
+namespace B = A;
+void ab()
+{
+ B::X x; (void)x;
+}
+
+
+
+namespace N {
+struct Outer
+{
+ template <typename T> struct Inner {};
+ Inner<int> inner;
+};
+}
+
+
+
+void f();
+namespace R { void f(); }
+void f(int param);
+void z(int = 1);
+void user()
+{
+ f();
+ R::f();
+ f(1);
+ z();
+}
+
+
+
+
+void autoTypes()
+{
+ auto a = 3; (void)a;
+ auto b = EnumType::V1; (void)b;
+ auto c = Bar(); (void)c;
+ auto d = Zii<int>(); (void)d;
+}
diff --git a/tests/unit/unittest/data/tooltipinfo.h b/tests/unit/unittest/data/tooltipinfo.h
new file mode 100644
index 0000000000..47d3bb92e7
--- /dev/null
+++ b/tests/unit/unittest/data/tooltipinfo.h
@@ -0,0 +1,3 @@
+#define MACRO_FROM_HEADER(x) x + \
+ x + \
+ x
diff --git a/tests/unit/unittest/dummyclangipcclient.h b/tests/unit/unittest/dummyclangipcclient.h
index 3908f9e89f..e840b0a6c7 100644
--- a/tests/unit/unittest/dummyclangipcclient.h
+++ b/tests/unit/unittest/dummyclangipcclient.h
@@ -38,4 +38,5 @@ public:
void documentAnnotationsChanged(const ClangBackEnd::DocumentAnnotationsChangedMessage &) override {}
void references(const ClangBackEnd::ReferencesMessage &) override {}
void followSymbol(const ClangBackEnd::FollowSymbolMessage &) override {}
+ void tooltip(const ClangBackEnd::ToolTipMessage &) override {}
};
diff --git a/tests/unit/unittest/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp
index 16e5133c56..dc8edee24b 100644
--- a/tests/unit/unittest/gtest-creator-printing.cpp
+++ b/tests/unit/unittest/gtest-creator-printing.cpp
@@ -42,6 +42,7 @@
#include <sourcelocationscontainer.h>
#include <tokeninfos.h>
#include <filepathview.h>
+#include <tooltipinfo.h>
#include <cpptools/usages.h>
@@ -290,6 +291,17 @@ std::ostream &operator<<(std::ostream &os, const ReferencesMessage &message)
return os;
}
+std::ostream &operator<<(std::ostream &os, const ToolTipMessage &message)
+{
+ os << "("
+ << message.fileContainer() << ", "
+ << message.ticketNumber() << ", "
+ << message.toolTipInfo() << ", "
+ << ")";
+
+ return os;
+}
+
std::ostream &operator<<(std::ostream &os, const EchoMessage &/*message*/)
{
return os << "()";
@@ -406,7 +418,8 @@ std::ostream &operator<<(std::ostream &os, const FileContainer &container)
<< container.filePath() << ", "
<< container.projectPartId() << ", "
<< container.fileArguments() << ", "
- << container.documentRevision();
+ << container.documentRevision() << ", "
+ << container.textCodecName();
if (container.hasUnsavedFileContent())
os << ", "
@@ -573,6 +586,37 @@ std::ostream &operator<<(std::ostream &os, const RequestReferencesMessage &messa
return os;
}
+std::ostream &operator<<(std::ostream &out, const RequestToolTipMessage &message)
+{
+ out << "("
+ << message.fileContainer() << ", "
+ << message.ticketNumber() << ", "
+ << message.line() << ", "
+ << message.column() << ", "
+ << ")";
+
+ return out;
+}
+
+std::ostream &operator<<(std::ostream &os, const ToolTipInfo::QdocCategory category)
+{
+ return os << qdocCategoryToString(category);
+}
+
+std::ostream &operator<<(std::ostream &out, const ToolTipInfo &info)
+{
+ out << "("
+ << info.m_text << ", "
+ << info.m_briefComment << ", "
+ << info.m_qdocIdCandidates << ", "
+ << info.m_qdocMark << ", "
+ << info.m_qdocCategory
+ << info.m_sizeInBytes << ", "
+ << ")";
+
+ return out;
+}
+
std::ostream &operator<<(std::ostream &os, const RequestSourceLocationsForRenamingMessage &message)
{
diff --git a/tests/unit/unittest/gtest-creator-printing.h b/tests/unit/unittest/gtest-creator-printing.h
index 072719ff6d..73848ba854 100644
--- a/tests/unit/unittest/gtest-creator-printing.h
+++ b/tests/unit/unittest/gtest-creator-printing.h
@@ -79,6 +79,7 @@ class CodeCompletedMessage;
class EchoMessage;
class DocumentAnnotationsChangedMessage;
class ReferencesMessage;
+class ToolTipMessage;
class FollowSymbolMessage;
class CompleteCodeMessage;
class EndMessage;
@@ -103,6 +104,7 @@ class RemovePchProjectPartsMessage;
class RequestDocumentAnnotationsMessage;
class RequestFollowSymbolMessage;
class RequestReferencesMessage;
+class RequestToolTipMessage;
class RequestSourceLocationsForRenamingMessage;
class RequestSourceRangesAndDiagnosticsForQueryMessage;
class RequestSourceRangesForQueryMessage;
@@ -124,6 +126,7 @@ template <char WindowsSlash>
class AbstractFilePathView;
using FilePathView = AbstractFilePathView<'/'>;
using NativeFilePathView = AbstractFilePathView<'\\'>;
+class ToolTipInfo;
std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry);
std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths);
@@ -136,6 +139,7 @@ std::ostream &operator<<(std::ostream &out, const CodeCompletedMessage &message)
std::ostream &operator<<(std::ostream &out, const EchoMessage &message);
std::ostream &operator<<(std::ostream &out, const DocumentAnnotationsChangedMessage &message);
std::ostream &operator<<(std::ostream &out, const ReferencesMessage &message);
+std::ostream &operator<<(std::ostream &out, const ToolTipMessage &message);
std::ostream &operator<<(std::ostream &out, const FollowSymbolMessage &message);
std::ostream &operator<<(std::ostream &out, const CompleteCodeMessage &message);
std::ostream &operator<<(std::ostream &out, const EndMessage &message);
@@ -162,6 +166,8 @@ std::ostream &operator<<(std::ostream &out, const RemovePchProjectPartsMessage &
std::ostream &operator<<(std::ostream &out, const RequestDocumentAnnotationsMessage &message);
std::ostream &operator<<(std::ostream &out, const RequestFollowSymbolMessage &message);
std::ostream &operator<<(std::ostream &out, const RequestReferencesMessage &message);
+std::ostream &operator<<(std::ostream &out, const RequestToolTipMessage &message);
+std::ostream &operator<<(std::ostream &out, const ToolTipInfo &info);
std::ostream &operator<<(std::ostream &out, const RequestSourceLocationsForRenamingMessage &message);
std::ostream &operator<<(std::ostream &out, const RequestSourceRangesAndDiagnosticsForQueryMessage &message);
std::ostream &operator<<(std::ostream &out, const RequestSourceRangesForQueryMessage &message);
diff --git a/tests/unit/unittest/mockclangcodemodelclient.h b/tests/unit/unittest/mockclangcodemodelclient.h
index 2e287909dd..3b5a3cfbf5 100644
--- a/tests/unit/unittest/mockclangcodemodelclient.h
+++ b/tests/unit/unittest/mockclangcodemodelclient.h
@@ -45,4 +45,6 @@ public:
void(const ClangBackEnd::ReferencesMessage &message));
MOCK_METHOD1(followSymbol,
void(const ClangBackEnd::FollowSymbolMessage &message));
+ MOCK_METHOD1(tooltip,
+ void(const ClangBackEnd::ToolTipMessage &message));
};
diff --git a/tests/unit/unittest/mockclangcodemodelserver.h b/tests/unit/unittest/mockclangcodemodelserver.h
index 8b6c66b2a3..468f683bf5 100644
--- a/tests/unit/unittest/mockclangcodemodelserver.h
+++ b/tests/unit/unittest/mockclangcodemodelserver.h
@@ -55,6 +55,8 @@ public:
void(const ClangBackEnd::RequestReferencesMessage &message));
MOCK_METHOD1(requestFollowSymbol,
void(const ClangBackEnd::RequestFollowSymbolMessage &message));
+ MOCK_METHOD1(requestToolTip,
+ void(const ClangBackEnd::RequestToolTipMessage &message));
MOCK_METHOD1(updateVisibleTranslationUnits,
void(const ClangBackEnd::UpdateVisibleTranslationUnitsMessage &message));
};
diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro
index 3c9642a46a..257a83370c 100644
--- a/tests/unit/unittest/unittest.pro
+++ b/tests/unit/unittest/unittest.pro
@@ -118,6 +118,7 @@ SOURCES += \
clangstring-test.cpp \
clangsupportivetranslationunitinitializer-test.cpp \
clangsuspenddocumentjob-test.cpp \
+ clangtooltipinfo-test.cpp \
clangtranslationunits-test.cpp \
clangtranslationunit-test.cpp \
clangupdatedocumentannotationsjob-test.cpp \
diff --git a/tests/unit/unittest/unsavedfile-test.cpp b/tests/unit/unittest/unsavedfile-test.cpp
index 05783a33c3..7e4d3dae68 100644
--- a/tests/unit/unittest/unsavedfile-test.cpp
+++ b/tests/unit/unittest/unsavedfile-test.cpp
@@ -203,4 +203,32 @@ TEST_F(UnsavedFile, HasCharacterForLastLineColumn)
ASSERT_TRUE(unsavedFile.hasCharacterAt(1, 7, 't'));
}
+TEST_F(UnsavedFile, LineRangeForInvalidLines)
+{
+ ::UnsavedFile unsavedFile(filePath, fileContent);
+
+ ASSERT_THAT(unsavedFile.lineRange(2, 1), Utf8String());
+}
+
+TEST_F(UnsavedFile, LineRangeForSingleLine)
+{
+ ::UnsavedFile unsavedFile(filePath, Utf8StringLiteral("foo"));
+
+ ASSERT_THAT(unsavedFile.lineRange(1, 1), Utf8StringLiteral("foo"));
+}
+
+TEST_F(UnsavedFile, LineRangeForSingleLineInMultipleLines)
+{
+ ::UnsavedFile unsavedFile(filePath, Utf8StringLiteral("foo\nbar\n\baz"));
+
+ ASSERT_THAT(unsavedFile.lineRange(2, 2), Utf8StringLiteral("bar"));
+}
+
+TEST_F(UnsavedFile, LineRangeForTwoLines)
+{
+ ::UnsavedFile unsavedFile(filePath, Utf8StringLiteral("foo\nbar\n\baz"));
+
+ ASSERT_THAT(unsavedFile.lineRange(2, 3), Utf8StringLiteral("bar\n\baz"));
+}
+
} // anonymous namespace