forked from qt-creator/qt-creator
libclang is smart enough to filter the overloads according to which arguments have already been entered, so let's make use of that. Fixes: QTCREATORBUG-650 Change-Id: Ic2711f460c908c6fd9c8efe28c3c63a0ce2d9205 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
590 lines
18 KiB
C++
590 lines
18 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2016 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 <clangcodemodel/clangcompletioncontextanalyzer.h>
|
|
#include <clangcodemodel/clangcompletionassistinterface.h>
|
|
|
|
#include <utils/qtcassert.h>
|
|
|
|
#include <QTextDocument>
|
|
|
|
namespace ClangCodeModel {
|
|
namespace Internal {
|
|
|
|
void PrintTo(const ClangCompletionContextAnalyzer::CompletionAction &completionAction,
|
|
::std::ostream* os)
|
|
{
|
|
using CCA = ClangCompletionContextAnalyzer;
|
|
|
|
switch (completionAction) {
|
|
case CCA::PassThroughToLibClang: *os << "PassThroughToLibClang"; break;
|
|
case CCA::PassThroughToLibClangAfterLeftParen: *os << "PassThroughToLibClangAfterLeftParen"; break;
|
|
case CCA::CompleteDoxygenKeyword: *os << "CompleteDoxygenKeyword"; break;
|
|
case CCA::CompleteIncludePath: *os << "CompleteIncludePath"; break;
|
|
case CCA::CompletePreprocessorDirective: *os << "CompletePreprocessorDirective"; break;
|
|
case CCA::CompleteSignal: *os << "CompleteSignal"; break;
|
|
case CCA::CompleteSlot: *os << "CompleteSlot"; break;
|
|
case CCA::CompleteNone: *os << "CompleteNone"; break;
|
|
}
|
|
}
|
|
|
|
} // Internal
|
|
} // ClangCodeModel
|
|
|
|
namespace {
|
|
|
|
using ::testing::PrintToString;
|
|
using ClangCodeModel::Internal::ClangCompletionAssistInterface;
|
|
using CCA = ClangCodeModel::Internal::ClangCompletionContextAnalyzer;
|
|
|
|
class TestDocument
|
|
{
|
|
public:
|
|
TestDocument(const QByteArray &theSource)
|
|
: source(theSource),
|
|
position(theSource.lastIndexOf('@')) // Use 'lastIndexOf' due to doxygen: "//! @keyword"
|
|
{
|
|
source.remove(position, 1);
|
|
}
|
|
|
|
QByteArray source;
|
|
int position;
|
|
};
|
|
|
|
bool isPassThrough(CCA::CompletionAction completionAction)
|
|
{
|
|
return completionAction != CCA::PassThroughToLibClang
|
|
&& completionAction != CCA::PassThroughToLibClangAfterLeftParen;
|
|
}
|
|
|
|
MATCHER(IsPassThroughToClang, std::string(negation ? "isn't" : "is") + " passed through to Clang")
|
|
{
|
|
const auto completionAction = arg.completionAction();
|
|
if (isPassThrough(completionAction)) {
|
|
*result_listener << "completion action is " << PrintToString(completionAction);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Offsets are relative to positionInText
|
|
MATCHER_P5(HasResult,
|
|
completionAction,
|
|
positionForClangOffset,
|
|
positionForProposalOffset,
|
|
positionInText,
|
|
addSnippets,
|
|
std::string(negation ? "hasn't" : "has")
|
|
+ " result of completion action " + PrintToString(completionAction)
|
|
+ " and offset for clang " + PrintToString(positionForClangOffset)
|
|
+ " and offset for proprosal " + PrintToString(positionForProposalOffset)
|
|
+ " and addSnippets " + PrintToString(addSnippets))
|
|
{
|
|
const int actualPositionForClangOffset = arg.positionForClang() - positionInText;
|
|
const int actualPositionForProposalOffset = arg.positionForProposal() - positionInText;
|
|
|
|
if (arg.completionAction() != completionAction
|
|
|| actualPositionForClangOffset != positionForClangOffset
|
|
|| actualPositionForProposalOffset != positionForProposalOffset
|
|
|| addSnippets != arg.addSnippets()) {
|
|
*result_listener << "completion action is " << PrintToString(arg.completionAction())
|
|
<< " and offset for clang is " << PrintToString(actualPositionForClangOffset)
|
|
<< " and offset for proprosal is " << PrintToString(actualPositionForProposalOffset)
|
|
<< " and addSnippets is " << PrintToString(arg.addSnippets());
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Offsets are relative to positionInText
|
|
MATCHER_P5(HasResultWithoutClangDifference,
|
|
completionAction,
|
|
positionForClangOffset,
|
|
positionForProposalOffset,
|
|
positionInText,
|
|
addSnippets,
|
|
std::string(negation ? "hasn't" : "has")
|
|
+ " result of completion action " + PrintToString(completionAction)
|
|
+ " and offset for clang " + PrintToString(positionForClangOffset)
|
|
+ " and offset for proprosal " + PrintToString(positionForProposalOffset)
|
|
+ " and addSnippets " + PrintToString(addSnippets))
|
|
{
|
|
const int actualPositionForProposalOffset = arg.positionForProposal() - positionInText;
|
|
|
|
if (arg.completionAction() != completionAction
|
|
|| arg.positionForClang() != positionForClangOffset
|
|
|| actualPositionForProposalOffset != positionForProposalOffset
|
|
|| addSnippets != arg.addSnippets()) {
|
|
*result_listener << "completion action is " << PrintToString(arg.completionAction())
|
|
<< " and offset for clang is " << PrintToString(arg.positionForClang())
|
|
<< " and offset for proprosal is " << PrintToString(actualPositionForProposalOffset)
|
|
<< " and addSnippets is " << PrintToString(arg.addSnippets());
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
class ClangCompletionContextAnalyzer : public ::testing::Test
|
|
{
|
|
protected:
|
|
CCA runAnalyzer(const char *text);
|
|
|
|
protected:
|
|
int positionInText = 0;
|
|
};
|
|
|
|
CCA ClangCompletionContextAnalyzer::runAnalyzer(const char *text)
|
|
{
|
|
const TestDocument testDocument(text);
|
|
ClangCompletionAssistInterface assistInterface(testDocument.source, testDocument.position);
|
|
CCA analyzer(&assistInterface, CPlusPlus::LanguageFeatures::defaultFeatures());
|
|
|
|
positionInText = testDocument.position;
|
|
|
|
analyzer.analyze();
|
|
|
|
return analyzer;
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, WordsBeforeCursor)
|
|
{
|
|
auto analyzer = runAnalyzer("foo bar@");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, -3, -3, positionInText, true));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, AfterSpace)
|
|
{
|
|
auto analyzer = runAnalyzer("foo @");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText, true));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, AfterQualification)
|
|
{
|
|
auto analyzer = runAnalyzer(" Foo::@");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, AtEndOfDotMember)
|
|
{
|
|
auto analyzer = runAnalyzer("o.mem@");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, -3, -3, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, AtEndOfDotMemberWithSpaceInside)
|
|
{
|
|
auto analyzer = runAnalyzer("o. mem@");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, -3, -3, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, AtBeginOfDotMember)
|
|
{
|
|
auto analyzer = runAnalyzer("o.@mem");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, AtBeginOfDotMemberWithSpaceInside)
|
|
{
|
|
auto analyzer = runAnalyzer("o. @mem");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, AtEndOfArrow)
|
|
{
|
|
auto analyzer = runAnalyzer("o->mem@");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, -3, -3, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, AtEndOfArrowWithSpaceInside)
|
|
{
|
|
auto analyzer = runAnalyzer("o-> mem@");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, -3, -3, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, AtBeginOfArrow)
|
|
{
|
|
auto analyzer = runAnalyzer("o->@mem");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, AtBeginOfArrowWithSpaceInside)
|
|
{
|
|
auto analyzer = runAnalyzer("o-> @mem");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, ArgumentOneAtCall)
|
|
{
|
|
auto analyzer = runAnalyzer("f(@");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, 0, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, ArgumentTwoAtCall)
|
|
{
|
|
auto analyzer = runAnalyzer("f(1,@");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, -2, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, ArgumentTwoWithSpaceAtCall)
|
|
{
|
|
auto analyzer = runAnalyzer("f(1, @");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, -3, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, WhitespaceAfterFunctionName)
|
|
{
|
|
auto analyzer = runAnalyzer("foo (@");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, 0, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, ConstructorCallWithBraceInitializer)
|
|
{
|
|
auto analyzer = runAnalyzer("f{@");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, 0, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, ArgumentTwoWithSpaceAtConstructorCallWithBraceInitializer)
|
|
{
|
|
auto analyzer = runAnalyzer("f{1, @");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, -3, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, WhitespaceBeforeConstructorCallWithBraceInitializer)
|
|
{
|
|
auto analyzer = runAnalyzer("foo {@");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, 0, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, OpenFunctionScopeNotAConstructor)
|
|
{
|
|
auto analyzer = runAnalyzer("foo() {@");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText, true));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, AfterOpeningParenthesis)
|
|
{
|
|
auto analyzer = runAnalyzer("(@");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText, true));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, AfterOpeningBraceAndIdentifierOnNewLine)
|
|
{
|
|
auto analyzer = runAnalyzer("if (1) {\n"
|
|
"cla@");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, -3, -3, positionInText, true));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, ArgumentOneAtSignal)
|
|
{
|
|
auto analyzer = runAnalyzer("SIGNAL(@");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::CompleteSignal, 0, 0, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, ArgumentOneWithLettersAtSignal)
|
|
{
|
|
auto analyzer = runAnalyzer("SIGNAL(foo@");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::CompleteSignal, -3, -3, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, ArgumentOneAtSlot)
|
|
{
|
|
auto analyzer = runAnalyzer("SLOT(@");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::CompleteSlot, -0, 0, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, ArgumentOneWithLettersAtSlot)
|
|
{
|
|
auto analyzer = runAnalyzer("SLOT(foo@");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::CompleteSlot, -3, -3, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, DoxygenWithBackslash)
|
|
{
|
|
auto analyzer = runAnalyzer("//! \\@");
|
|
|
|
ASSERT_THAT(analyzer, HasResultWithoutClangDifference(CCA::CompleteDoxygenKeyword, -1, 0, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, DoxygenWithAt)
|
|
{
|
|
auto analyzer = runAnalyzer("//! @@");
|
|
|
|
ASSERT_THAT(analyzer, HasResultWithoutClangDifference(CCA::CompleteDoxygenKeyword, -1, 0, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, DoxygenWithParameter)
|
|
{
|
|
auto analyzer = runAnalyzer("//! \\par@");
|
|
|
|
ASSERT_THAT(analyzer, HasResultWithoutClangDifference(CCA::CompleteDoxygenKeyword, -1, -3, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, Preprocessor)
|
|
{
|
|
auto analyzer = runAnalyzer("#@");
|
|
|
|
ASSERT_THAT(analyzer, HasResultWithoutClangDifference(CCA::CompletePreprocessorDirective, -1, 0, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, PreprocessorIf)
|
|
{
|
|
auto analyzer = runAnalyzer("#if@");
|
|
|
|
ASSERT_THAT(analyzer, HasResultWithoutClangDifference(CCA::CompletePreprocessorDirective, -1, -2, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, LocalInclude)
|
|
{
|
|
auto analyzer = runAnalyzer("#include \"foo@\"");
|
|
|
|
ASSERT_THAT(analyzer, HasResultWithoutClangDifference(CCA::CompleteIncludePath, -1, -3, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, GlobalInclude)
|
|
{
|
|
auto analyzer = runAnalyzer("#include <foo@>");
|
|
|
|
ASSERT_THAT(analyzer, HasResultWithoutClangDifference(CCA::CompleteIncludePath, -1, -3, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, GlocalIncludeWithDirectory)
|
|
{
|
|
auto analyzer = runAnalyzer("#include <foo/@>");
|
|
|
|
ASSERT_THAT(analyzer, HasResultWithoutClangDifference(CCA::CompleteIncludePath, -1, 0, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, AfterQuote)
|
|
{
|
|
auto analyzer = runAnalyzer("\"@");
|
|
|
|
ASSERT_THAT(analyzer, IsPassThroughToClang());
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, AfterSpaceQuote)
|
|
{
|
|
auto analyzer = runAnalyzer(" \"@");
|
|
|
|
ASSERT_THAT(analyzer, IsPassThroughToClang());
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, AfterQuotedText)
|
|
{
|
|
auto analyzer = runAnalyzer("\"text\"@");
|
|
|
|
ASSERT_THAT(analyzer, IsPassThroughToClang());
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, InQuotedText)
|
|
{
|
|
auto analyzer = runAnalyzer("\"hello cruel@ world\"");
|
|
|
|
ASSERT_THAT(analyzer, IsPassThroughToClang());
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, SingleQuote)
|
|
{
|
|
auto analyzer = runAnalyzer("'@'");
|
|
|
|
ASSERT_THAT(analyzer, IsPassThroughToClang());
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, AfterLetterInSingleQuoted)
|
|
{
|
|
auto analyzer = runAnalyzer("'a@'");
|
|
|
|
ASSERT_THAT(analyzer, IsPassThroughToClang());
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, CommaOperator)
|
|
{
|
|
auto analyzer = runAnalyzer("a = b,@\"");
|
|
|
|
ASSERT_THAT(analyzer, IsPassThroughToClang());
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, DoxygenMarkerInNonDoxygenComment)
|
|
{
|
|
auto analyzer = runAnalyzer("@@");
|
|
|
|
ASSERT_THAT(analyzer, IsPassThroughToClang());
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, DoxygenMarkerInNonDoxygenComment2)
|
|
{
|
|
auto analyzer = runAnalyzer("\\@");
|
|
|
|
ASSERT_THAT(analyzer, IsPassThroughToClang());
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, AtEndOfOneLineComment)
|
|
{
|
|
auto analyzer = runAnalyzer("// comment@");
|
|
|
|
ASSERT_THAT(analyzer, IsPassThroughToClang());
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, AfterOneLineCommentLine)
|
|
{
|
|
auto analyzer = runAnalyzer("// comment\n"
|
|
"@");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText, true));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, AfterEmptyOneLineComment)
|
|
{
|
|
auto analyzer = runAnalyzer("//\n"
|
|
"@");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText, true));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, AfterOneLineDoxygenComment1)
|
|
{
|
|
auto analyzer = runAnalyzer("/// comment\n"
|
|
"@");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText, true));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, AfterOneLineDoxygenComment2)
|
|
{
|
|
auto analyzer = runAnalyzer("//! comment \n"
|
|
"@");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText, true));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, BeginEndComment)
|
|
{
|
|
auto analyzer = runAnalyzer("/* text@ */");
|
|
|
|
ASSERT_THAT(analyzer, IsPassThroughToClang());
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, Slash)
|
|
{
|
|
auto analyzer = runAnalyzer("5 /@");
|
|
|
|
ASSERT_THAT(analyzer, IsPassThroughToClang());
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, LeftParen)
|
|
{
|
|
auto analyzer = runAnalyzer("(@");
|
|
|
|
ASSERT_THAT(analyzer, IsPassThroughToClang());
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, TwoLeftParen)
|
|
{
|
|
auto analyzer = runAnalyzer("((@");
|
|
|
|
ASSERT_THAT(analyzer, IsPassThroughToClang());
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, AsteriskLeftParen)
|
|
{
|
|
auto analyzer = runAnalyzer("*(@");
|
|
|
|
ASSERT_THAT(analyzer, IsPassThroughToClang());
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, TemplatedFunctionSecondArgument)
|
|
{
|
|
auto analyzer = runAnalyzer("f < decltype(bar -> member) > (1, @");
|
|
|
|
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, 0, -3, positionInText, false));
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, FunctionNameStartPosition)
|
|
{
|
|
auto analyzer = runAnalyzer(" f<Bar>(1, @");
|
|
int functionNameStartPosition = analyzer.functionNameStart();
|
|
|
|
ASSERT_THAT(functionNameStartPosition, 1);
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, QualifiedFunctionNameStartPosition)
|
|
{
|
|
auto analyzer = runAnalyzer(" Namespace::f<Bar>(1, @");
|
|
int functionNameStartPosition = analyzer.functionNameStart();
|
|
|
|
ASSERT_THAT(functionNameStartPosition, 1);
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, SnippetsAfterOpeningBrace)
|
|
{
|
|
auto analyzer = runAnalyzer("{@");
|
|
|
|
ASSERT_TRUE(analyzer.addSnippets());
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, NoSnippetsAfterFunctionCallLike_OpeningBrace)
|
|
{
|
|
auto analyzer = runAnalyzer("foo{@");
|
|
|
|
ASSERT_FALSE(analyzer.addSnippets());
|
|
}
|
|
|
|
TEST_F(ClangCompletionContextAnalyzer, NoSnippetsAfterFunctionCallLike_OpeningParen)
|
|
{
|
|
auto analyzer = runAnalyzer("foo(@");
|
|
|
|
ASSERT_FALSE(analyzer.addSnippets());
|
|
}
|
|
|
|
} // namespace
|