forked from qt-creator/qt-creator
LSP: add symbol support class
Declutter the client and client manager by moving find usage and follow symbol into this helper. This functionality was "temporary" put into the client manager, but is more an implementation detail that shouldn't be handled in that central place. Rename symbol will also go into this helper class. Task-number: QTCREATORBUG-21578 Change-Id: I56680f6ccbb8d244066561167178af7b341b8822 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -405,13 +405,15 @@ void LanguageClientManager::editorOpened(Core::IEditor *editor)
|
||||
if (auto *textEditor = qobject_cast<BaseTextEditor *>(editor)) {
|
||||
if (TextEditorWidget *widget = textEditor->editorWidget()) {
|
||||
connect(widget, &TextEditorWidget::requestLinkAt, this,
|
||||
[this, document = textEditor->textDocument()]
|
||||
[document = textEditor->textDocument()]
|
||||
(const QTextCursor &cursor, Utils::ProcessLinkCallback &callback, bool resolveTarget) {
|
||||
findLinkAt(document, cursor, callback, resolveTarget);
|
||||
if (auto client = clientForDocument(document))
|
||||
client->symbolSupport().findLinkAt(document, cursor, callback, resolveTarget);
|
||||
});
|
||||
connect(widget, &TextEditorWidget::requestUsages, this,
|
||||
[this, document = textEditor->textDocument()](const QTextCursor &cursor) {
|
||||
findUsages(document, cursor);
|
||||
[document = textEditor->textDocument()](const QTextCursor &cursor) {
|
||||
if (auto client = clientForDocument(document))
|
||||
client->symbolSupport().findUsages(document, cursor);
|
||||
});
|
||||
connect(widget, &TextEditorWidget::cursorPositionChanged, this, [this, widget]() {
|
||||
// TODO This would better be a compressing timer
|
||||
@@ -494,116 +496,6 @@ void LanguageClientManager::documentWillSave(Core::IDocument *document)
|
||||
}
|
||||
}
|
||||
|
||||
void LanguageClientManager::findLinkAt(TextEditor::TextDocument *document,
|
||||
const QTextCursor &cursor,
|
||||
Utils::ProcessLinkCallback callback,
|
||||
bool resolveTarget)
|
||||
{
|
||||
const DocumentUri uri = DocumentUri::fromFilePath(document->filePath());
|
||||
const TextDocumentIdentifier documentId(uri);
|
||||
const Position pos(cursor);
|
||||
TextDocumentPositionParams params(documentId, pos);
|
||||
GotoDefinitionRequest request(params);
|
||||
request.setResponseCallback([callback, filePath = document->filePath(), cursor, resolveTarget]
|
||||
(const GotoDefinitionRequest::Response &response) {
|
||||
if (Utils::optional<GotoResult> _result = response.result()) {
|
||||
const GotoResult result = _result.value();
|
||||
if (Utils::holds_alternative<std::nullptr_t>(result))
|
||||
return;
|
||||
auto wordUnderCursor = [cursor, filePath]() {
|
||||
QTextCursor linkCursor = cursor;
|
||||
linkCursor.select(QTextCursor::WordUnderCursor);
|
||||
Utils::Link link(filePath.toString(),
|
||||
linkCursor.blockNumber() + 1,
|
||||
linkCursor.positionInBlock());
|
||||
link.linkTextStart = linkCursor.selectionStart();
|
||||
link.linkTextEnd = linkCursor.selectionEnd();
|
||||
return link;
|
||||
};
|
||||
if (auto ploc = Utils::get_if<Location>(&result)) {
|
||||
callback(resolveTarget ? ploc->toLink() : wordUnderCursor());
|
||||
} else if (auto plloc = Utils::get_if<QList<Location>>(&result)) {
|
||||
if (!plloc->isEmpty())
|
||||
callback(resolveTarget ? plloc->value(0).toLink() : wordUnderCursor());
|
||||
}
|
||||
}
|
||||
});
|
||||
if (Client *client = clientForUri(uri)) {
|
||||
if (client->reachable())
|
||||
client->findLinkAt(request);
|
||||
}
|
||||
}
|
||||
|
||||
QList<Core::SearchResultItem> generateSearchResultItems(const LanguageClientArray<Location> &locations)
|
||||
{
|
||||
auto convertPosition = [](const Position &pos){
|
||||
return Core::Search::TextPosition(pos.line() + 1, pos.character());
|
||||
};
|
||||
auto convertRange = [convertPosition](const Range &range){
|
||||
return Core::Search::TextRange(convertPosition(range.start()), convertPosition(range.end()));
|
||||
};
|
||||
QList<Core::SearchResultItem> result;
|
||||
if (locations.isNull())
|
||||
return result;
|
||||
QMap<QString, QList<Core::Search::TextRange>> rangesInDocument;
|
||||
for (const Location &location : locations.toList())
|
||||
rangesInDocument[location.uri().toFilePath().toString()] << convertRange(location.range());
|
||||
for (auto it = rangesInDocument.begin(); it != rangesInDocument.end(); ++it) {
|
||||
const QString &fileName = it.key();
|
||||
QFile file(fileName);
|
||||
file.open(QFile::ReadOnly);
|
||||
|
||||
Core::SearchResultItem item;
|
||||
item.path = QStringList() << fileName;
|
||||
item.useTextEditorFont = true;
|
||||
|
||||
QStringList lines = QString::fromLocal8Bit(file.readAll()).split(QChar::LineFeed);
|
||||
for (const Core::Search::TextRange &range : it.value()) {
|
||||
item.mainRange = range;
|
||||
if (file.isOpen() && range.begin.line > 0 && range.begin.line <= lines.size())
|
||||
item.text = lines[range.begin.line - 1];
|
||||
else
|
||||
item.text.clear();
|
||||
result << item;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void LanguageClientManager::findUsages(TextEditor::TextDocument *document, const QTextCursor &cursor)
|
||||
{
|
||||
const DocumentUri uri = DocumentUri::fromFilePath(document->filePath());
|
||||
const TextDocumentIdentifier documentId(uri);
|
||||
const Position pos(cursor);
|
||||
QTextCursor termCursor(cursor);
|
||||
termCursor.select(QTextCursor::WordUnderCursor);
|
||||
ReferenceParams params(TextDocumentPositionParams(documentId, pos));
|
||||
params.setContext(ReferenceParams::ReferenceContext(true));
|
||||
FindReferencesRequest request(params);
|
||||
auto callback = [this, wordUnderCursor = termCursor.selectedText()]
|
||||
(const QString &clientName, const FindReferencesRequest::Response &response){
|
||||
if (auto result = response.result()) {
|
||||
Core::SearchResult *search = Core::SearchResultWindow::instance()->startNewSearch(
|
||||
tr("Find References with %1 for:").arg(clientName), "", wordUnderCursor);
|
||||
search->addResults(generateSearchResultItems(result.value()), Core::SearchResult::AddOrdered);
|
||||
QObject::connect(search, &Core::SearchResult::activated,
|
||||
[](const Core::SearchResultItem& item) {
|
||||
Core::EditorManager::openEditorAtSearchResult(item);
|
||||
});
|
||||
search->finishSearch(false);
|
||||
search->popup();
|
||||
}
|
||||
};
|
||||
for (Client *client : reachableClients()) {
|
||||
request.setResponseCallback([callback, clientName = client->name()]
|
||||
(const FindReferencesRequest::Response &response){
|
||||
callback(clientName, response);
|
||||
});
|
||||
if (client->findUsages(request))
|
||||
m_exclusiveRequests[request.id()] << client;
|
||||
}
|
||||
}
|
||||
|
||||
void LanguageClientManager::updateProject(ProjectExplorer::Project *project)
|
||||
{
|
||||
for (BaseSettings *setting : m_currentSettings) {
|
||||
|
||||
Reference in New Issue
Block a user