forked from qt-creator/qt-creator
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 <nikolai.kosjar@qt.io>
This commit is contained in:
@@ -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,17 +159,21 @@ void ClangCompletionContextAnalyzer::handleFunctionCall(int afterOperatorPositio
|
||||
// No function completion if cursor is not after '(' or ','
|
||||
m_positionForProposal = afterOperatorPosition;
|
||||
setActionAndClangPosition(PassThroughToLibClang, afterOperatorPosition);
|
||||
} else if (looksLikeAFunctionCall(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);
|
||||
m_positionForProposal,
|
||||
functionNameStart);
|
||||
} else { // e.g. "(" without any function name in front
|
||||
m_positionForProposal = afterOperatorPosition;
|
||||
setActionAndClangPosition(PassThroughToLibClang, afterOperatorPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ClangCompletionContextAnalyzer::handleNonFunctionCall(int position)
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user