Commit d809e3fb authored by Ivan Donchevskii's avatar Ivan Donchevskii

Clang: send function name position for completion

... to reuse this position in backend (instead of
searching the function start again)

Change-Id: I02818dce4fc37ed6e7ecfb533191dbfe60610204
Reviewed-by: Nikolai Kosjar's avatarNikolai Kosjar <nikolai.kosjar@qt.io>
parent cffcba67
......@@ -933,9 +933,12 @@ void IpcCommunicator::completeCode(ClangCompletionAssistProcessor *assistProcess
const QString &filePath,
quint32 line,
quint32 column,
const QString &projectFilePath)
const QString &projectFilePath,
qint32 funcNameStartLine,
qint32 funcNameStartColumn)
{
const CompleteCodeMessage message(filePath, line, column, projectFilePath);
const CompleteCodeMessage message(filePath, line, column, projectFilePath, funcNameStartLine,
funcNameStartColumn);
m_ipcSender->completeCode(message);
m_ipcReceiver.addExpectedCodeCompletedMessage(message.ticketNumber(), assistProcessor);
}
......@@ -174,7 +174,9 @@ public:
void completeCode(ClangCompletionAssistProcessor *assistProcessor, const QString &filePath,
quint32 line,
quint32 column,
const QString &projectFilePath);
const QString &projectFilePath,
qint32 funcNameStartLine = -1,
qint32 funcNameStartColumn = -1);
void registerProjectsParts(const QVector<CppTools::ProjectPart::Ptr> projectParts);
......
......@@ -253,7 +253,8 @@ IAssistProposal *ClangCompletionAssistProcessor::startCompletionHelper()
}
case ClangCompletionContextAnalyzer::PassThroughToLibClangAfterLeftParen: {
m_sentRequestType = FunctionHintCompletion;
const bool requestSent = sendCompletionRequest(analyzer.positionForClang(), QByteArray());
const bool requestSent = sendCompletionRequest(analyzer.positionForClang(), QByteArray(),
analyzer.functionNameStart());
setPerformWasApplicable(requestSent);
break;
}
......@@ -548,14 +549,26 @@ void setLastCompletionPosition(const QString &filePath,
}
bool ClangCompletionAssistProcessor::sendCompletionRequest(int position,
const QByteArray &customFileContent)
ClangCompletionAssistProcessor::Position
ClangCompletionAssistProcessor::extractLineColumn(int position)
{
int line, column;
TextEditor::Convenience::convertPosition(m_interface->textDocument(), position, &line, &column);
if (position < 0)
return {-1, -1};
int line = -1, column = -1;
TextEditor::Convenience::convertPosition(m_interface->textDocument(),
position,
&line,
&column);
const QTextBlock block = m_interface->textDocument()->findBlock(position);
column += ClangCodeModel::Utils::extraUtf8CharsShift(block.text(), column) + 1;
return {line, column};
}
bool ClangCompletionAssistProcessor::sendCompletionRequest(int position,
const QByteArray &customFileContent,
int functionNameStartPosition)
{
const QString filePath = m_interface->fileName();
auto &ipcCommunicator = m_interface->ipcCommunicator();
......@@ -567,8 +580,12 @@ bool ClangCompletionAssistProcessor::sendCompletionRequest(int position,
setLastDocumentRevision(filePath);
}
const Position cursorPosition = extractLineColumn(position);
const Position functionNameStart = extractLineColumn(functionNameStartPosition);
const QString projectPartId = CppTools::CppToolsBridge::projectPartIdForFile(filePath);
ipcCommunicator.completeCode(this, filePath, uint(line), uint(column), projectPartId);
ipcCommunicator.completeCode(this, filePath, uint(cursorPosition.line),
uint(cursorPosition.column), projectPartId,
functionNameStart.line, functionNameStart.column);
setLastCompletionPosition(filePath, position);
return true;
}
......
......@@ -82,9 +82,14 @@ private:
UnsavedFileContentInfo unsavedFileContent(const QByteArray &customFileContent) const;
void sendFileContent(const QByteArray &customFileContent);
bool sendCompletionRequest(int position, const QByteArray &customFileContent);
bool sendCompletionRequest(int position,
const QByteArray &customFileContent,
int functionNameStartPosition = -1);
private:
struct Position { int line; int column; };
Position extractLineColumn(int position);
QScopedPointer<const ClangCompletionAssistInterface> m_interface;
unsigned m_completionOperator;
enum CompletionRequestType { NormalCompletion, FunctionHintCompletion } m_sentRequestType;
......
......@@ -91,7 +91,7 @@ void ClangCompletionContextAnalyzer::analyze()
}
}
bool ClangCompletionContextAnalyzer::looksLikeAFunctionCall(int endOfOperator) const
int ClangCompletionContextAnalyzer::startOfFunctionCall(int endOfOperator) const
{
int index = ActivationSequenceContextProcessor::skipPrecedingWhitespace(m_interface,
endOfOperator);
......@@ -104,22 +104,24 @@ bool ClangCompletionContextAnalyzer::looksLikeAFunctionCall(int endOfOperator) c
const int functionNameStart = ActivationSequenceContextProcessor::findStartOfName(m_interface,
index);
if (functionNameStart == -1)
return false;
return -1;
QTextCursor functionNameSelector(m_interface->textDocument());
functionNameSelector.setPosition(functionNameStart);
functionNameSelector.setPosition(index, QTextCursor::KeepAnchor);
const QString functionName = functionNameSelector.selectedText().trimmed();
return !functionName.isEmpty();
return functionName.isEmpty() ? -1 : functionNameStart;
}
void ClangCompletionContextAnalyzer::setActionAndClangPosition(CompletionAction action,
int position)
int position,
int functionNameStart)
{
QTC_CHECK(position >= -1);
m_completionAction = action;
m_positionForClang = position;
m_functionNameStart = functionNameStart;
}
void
......@@ -157,15 +159,19 @@ void ClangCompletionContextAnalyzer::handleFunctionCall(int afterOperatorPositio
// No function completion if cursor is not after '(' or ','
m_positionForProposal = afterOperatorPosition;
setActionAndClangPosition(PassThroughToLibClang, afterOperatorPosition);
} else if (looksLikeAFunctionCall(afterOperatorPosition)) {
// Always pass the position right after '(' to libclang because
// positions after the comma might be problematic if a preceding
// argument is invalid code.
setActionAndClangPosition(PassThroughToLibClangAfterLeftParen,
m_positionForProposal);
} else { // e.g. "(" without any function name in front
m_positionForProposal = afterOperatorPosition;
setActionAndClangPosition(PassThroughToLibClang, afterOperatorPosition);
} else {
const int functionNameStart = startOfFunctionCall(afterOperatorPosition);
if (functionNameStart >= 0) {
// Always pass the position right after '(' to libclang because
// positions after the comma might be problematic if a preceding
// argument is invalid code.
setActionAndClangPosition(PassThroughToLibClangAfterLeftParen,
m_positionForProposal,
functionNameStart);
} else { // e.g. "(" without any function name in front
m_positionForProposal = afterOperatorPosition;
setActionAndClangPosition(PassThroughToLibClang, afterOperatorPosition);
}
}
}
}
......
......@@ -56,14 +56,17 @@ public:
unsigned completionOperator() const { return m_completionOperator; }
int positionForProposal() const { return m_positionForProposal; }
int positionForClang() const { return m_positionForClang; }
int functionNameStart() const { return m_functionNameStart; }
int positionEndOfExpression() const { return m_positionEndOfExpression; }
private:
ClangCompletionContextAnalyzer();
bool looksLikeAFunctionCall(int endOfExpression) const;
int startOfFunctionCall(int endOfExpression) const;
void setActionAndClangPosition(CompletionAction action, int position);
void setActionAndClangPosition(CompletionAction action,
int position,
int functionNameStart = -1);
void setAction(CompletionAction action);
bool handleNonFunctionCall(int position);
......@@ -79,6 +82,7 @@ private:
CPlusPlus::Kind m_completionOperator = CPlusPlus::T_EOF_SYMBOL;
int m_positionForProposal = -1;
int m_positionForClang = -1;
int m_functionNameStart = -1;
int m_positionEndOfExpression = -1;
};
......
......@@ -497,4 +497,20 @@ TEST_F(ClangCompletionContextAnalyzer, TemplatedFunctionSecondArgument)
ASSERT_THAT(analyzer, HasResult(CCA::PassThroughToLibClangAfterLeftParen, -3, -3, positionInText));
}
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);
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment