Clang: Fix SOFT ASSERT: "!m_functionName.isEmpty()"

...that ocurred for e.g. "foo (<COMPLETE HERE>".

We did not handle the following cases:
 1) white space after the function name
 2) nothing before parenthesis

Change-Id: If6aedd2cc938df30516e13a860d07d7a509633ae
Reviewed-by: Erik Verbruggen <erik.verbruggen@theqtcompany.com>
This commit is contained in:
Nikolai Kosjar
2016-04-20 12:54:28 +02:00
parent 474b8ec5c0
commit 11836a14cf
3 changed files with 29 additions and 4 deletions

View File

@@ -101,6 +101,7 @@ ClangCompletionContextAnalyzer::analyzeFunctionCall(int endOfOperator) const
ExpressionUnderCursor euc(m_languageFeatures); ExpressionUnderCursor euc(m_languageFeatures);
index = euc.startOfFunctionCall(textCursor); index = euc.startOfFunctionCall(textCursor);
index = ActivationSequenceContextProcessor::skipPrecedingWhitespace(m_interface, index);
const int functionNameStart = ActivationSequenceContextProcessor::findStartOfName(m_interface, const int functionNameStart = ActivationSequenceContextProcessor::findStartOfName(m_interface,
index); index);
@@ -159,9 +160,14 @@ void ClangCompletionContextAnalyzer::handleFunctionCall(int afterOperatorPositio
setActionAndClangPosition(PassThroughToLibClang, afterOperatorPosition); setActionAndClangPosition(PassThroughToLibClang, afterOperatorPosition);
} else { } else {
const FunctionInfo functionInfo = analyzeFunctionCall(afterOperatorPosition); const FunctionInfo functionInfo = analyzeFunctionCall(afterOperatorPosition);
m_functionName = functionInfo.functionName; if (functionInfo.isValid()) {
setActionAndClangPosition(PassThroughToLibClangAfterLeftParen, m_functionName = functionInfo.functionName;
functionInfo.functionNamePosition); setActionAndClangPosition(PassThroughToLibClangAfterLeftParen,
functionInfo.functionNamePosition);
} else {
m_positionForProposal = afterOperatorPosition;
setActionAndClangPosition(PassThroughToLibClang, afterOperatorPosition);
}
} }
} }
} }

View File

@@ -64,7 +64,12 @@ public:
private: private:
ClangCompletionContextAnalyzer(); ClangCompletionContextAnalyzer();
struct FunctionInfo { int functionNamePosition; QString functionName; }; struct FunctionInfo {
bool isValid() const { return functionNamePosition != -1 && !functionName.isEmpty(); }
int functionNamePosition = -1;
QString functionName;
};
FunctionInfo analyzeFunctionCall(int endOfExpression) const; FunctionInfo analyzeFunctionCall(int endOfExpression) const;
void setActionAndClangPosition(CompletionAction action, int position); void setActionAndClangPosition(CompletionAction action, int position);

View File

@@ -258,6 +258,20 @@ TEST_F(ClangCompletionContextAnalyzer, ParameteTwoWithSpaceAtCall)
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, -5, -3, positionInText)); ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, -5, -3, positionInText));
} }
TEST_F(ClangCompletionContextAnalyzer, WhitespaceAfterFunctionName)
{
auto analyzer = runAnalyzer("foo (@");
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, -5, 0, positionInText));
}
TEST_F(ClangCompletionContextAnalyzer, AfterOpeningParenthesis)
{
auto analyzer = runAnalyzer("(@");
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClang, 0, 0, positionInText));
}
TEST_F(ClangCompletionContextAnalyzer, ParameteOneAtSignal) TEST_F(ClangCompletionContextAnalyzer, ParameteOneAtSignal)
{ {
auto analyzer = runAnalyzer("SIGNAL(@"); auto analyzer = runAnalyzer("SIGNAL(@");