2014-08-19 15:59:29 +02:00
|
|
|
/****************************************************************************
|
|
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2014-08-19 15:59:29 +02:00
|
|
|
**
|
|
|
|
|
** 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
|
2016-01-15 14:57:40 +01:00
|
|
|
** 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.
|
2014-08-19 15:59:29 +02:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** 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.
|
2014-08-19 15:59:29 +02:00
|
|
|
**
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "cppuseselectionsupdater.h"
|
|
|
|
|
|
|
|
|
|
#include "cppcanonicalsymbol.h"
|
|
|
|
|
#include "cppeditor.h"
|
|
|
|
|
|
|
|
|
|
#include <cpptools/cpplocalsymbols.h>
|
2014-09-15 00:12:27 +02:00
|
|
|
#include <cpptools/cppmodelmanager.h>
|
2014-08-19 15:59:29 +02:00
|
|
|
#include <cpptools/cpptoolsreuse.h>
|
2014-09-26 09:14:03 +02:00
|
|
|
#include <texteditor/texteditor.h>
|
2015-02-26 13:22:35 +01:00
|
|
|
#include <texteditor/textdocument.h>
|
2014-08-26 11:20:39 +02:00
|
|
|
#include <texteditor/convenience.h>
|
2014-08-19 15:59:29 +02:00
|
|
|
#include <texteditor/fontsettings.h>
|
|
|
|
|
|
|
|
|
|
#include <cplusplus/Macro.h>
|
|
|
|
|
#include <cplusplus/TranslationUnit.h>
|
|
|
|
|
|
|
|
|
|
#include <utils/qtcassert.h>
|
2016-02-12 12:58:56 +01:00
|
|
|
#include <utils/runextensions.h>
|
2014-08-19 15:59:29 +02:00
|
|
|
|
|
|
|
|
#include <QTextBlock>
|
|
|
|
|
#include <QTextCursor>
|
|
|
|
|
#include <QTextEdit>
|
|
|
|
|
|
|
|
|
|
using namespace CPlusPlus;
|
|
|
|
|
|
|
|
|
|
enum { updateUseSelectionsInternalInMs = 500 };
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
class FunctionDefinitionUnderCursor: protected ASTVisitor
|
|
|
|
|
{
|
|
|
|
|
unsigned _line;
|
|
|
|
|
unsigned _column;
|
|
|
|
|
DeclarationAST *_functionDefinition;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
FunctionDefinitionUnderCursor(TranslationUnit *translationUnit)
|
|
|
|
|
: ASTVisitor(translationUnit),
|
|
|
|
|
_line(0), _column(0)
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
DeclarationAST *operator()(AST *ast, unsigned line, unsigned column)
|
|
|
|
|
{
|
|
|
|
|
_functionDefinition = 0;
|
|
|
|
|
_line = line;
|
|
|
|
|
_column = column;
|
|
|
|
|
accept(ast);
|
|
|
|
|
return _functionDefinition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
virtual bool preVisit(AST *ast)
|
|
|
|
|
{
|
|
|
|
|
if (_functionDefinition)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (FunctionDefinitionAST *def = ast->asFunctionDefinition())
|
|
|
|
|
return checkDeclaration(def);
|
|
|
|
|
|
|
|
|
|
if (ObjCMethodDeclarationAST *method = ast->asObjCMethodDeclaration()) {
|
|
|
|
|
if (method->function_body)
|
|
|
|
|
return checkDeclaration(method);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
bool checkDeclaration(DeclarationAST *ast)
|
|
|
|
|
{
|
|
|
|
|
unsigned startLine, startColumn;
|
|
|
|
|
unsigned endLine, endColumn;
|
|
|
|
|
getTokenStartPosition(ast->firstToken(), &startLine, &startColumn);
|
|
|
|
|
getTokenEndPosition(ast->lastToken() - 1, &endLine, &endColumn);
|
|
|
|
|
|
|
|
|
|
if (_line > startLine || (_line == startLine && _column >= startColumn)) {
|
|
|
|
|
if (_line < endLine || (_line == endLine && _column < endColumn)) {
|
|
|
|
|
_functionDefinition = ast;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
QTextEdit::ExtraSelection extraSelection(const QTextCharFormat &format, const QTextCursor &cursor)
|
|
|
|
|
{
|
|
|
|
|
QTextEdit::ExtraSelection selection;
|
|
|
|
|
selection.format = format;
|
|
|
|
|
selection.cursor = cursor;
|
|
|
|
|
return selection;
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-26 11:20:39 +02:00
|
|
|
class Params
|
2014-08-19 15:59:29 +02:00
|
|
|
{
|
2014-08-26 11:20:39 +02:00
|
|
|
public:
|
|
|
|
|
Params(const QTextCursor &textCursor, const Document::Ptr document, const Snapshot &snapshot)
|
|
|
|
|
: document(document), snapshot(snapshot)
|
|
|
|
|
{
|
|
|
|
|
TextEditor::Convenience::convertPosition(textCursor.document(), textCursor.position(),
|
|
|
|
|
&line, &column);
|
|
|
|
|
CppEditor::Internal::CanonicalSymbol canonicalSymbol(document, snapshot);
|
|
|
|
|
scope = canonicalSymbol.getScopeAndExpression(textCursor, &expression);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
2014-08-19 15:59:29 +02:00
|
|
|
// Shared
|
|
|
|
|
Document::Ptr document;
|
|
|
|
|
|
|
|
|
|
// For local use calculation
|
|
|
|
|
int line;
|
|
|
|
|
int column;
|
|
|
|
|
|
|
|
|
|
// For references calculation
|
|
|
|
|
Scope *scope;
|
|
|
|
|
QString expression;
|
|
|
|
|
Snapshot snapshot;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
using CppEditor::Internal::SemanticUses;
|
|
|
|
|
|
|
|
|
|
void splitLocalUses(const CppTools::SemanticInfo::LocalUseMap &uses,
|
|
|
|
|
const Params &p,
|
|
|
|
|
SemanticUses *selectionsForLocalVariableUnderCursor,
|
|
|
|
|
SemanticUses *selectionsForLocalUnusedVariables)
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(selectionsForLocalVariableUnderCursor, return);
|
|
|
|
|
QTC_ASSERT(selectionsForLocalUnusedVariables, return);
|
|
|
|
|
|
|
|
|
|
LookupContext context(p.document, p.snapshot);
|
|
|
|
|
|
|
|
|
|
CppTools::SemanticInfo::LocalUseIterator it(uses);
|
|
|
|
|
while (it.hasNext()) {
|
|
|
|
|
it.next();
|
|
|
|
|
const SemanticUses &uses = it.value();
|
|
|
|
|
|
|
|
|
|
bool good = false;
|
|
|
|
|
foreach (const CppTools::SemanticInfo::Use &use, uses) {
|
|
|
|
|
unsigned l = p.line;
|
|
|
|
|
unsigned c = p.column + 1; // convertCursorPosition() returns a 0-based column number.
|
|
|
|
|
if (l == use.line && c >= use.column && c <= (use.column + use.length)) {
|
|
|
|
|
good = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (uses.size() == 1) {
|
|
|
|
|
if (!CppTools::isOwnershipRAIIType(it.key(), context))
|
|
|
|
|
selectionsForLocalUnusedVariables->append(uses); // unused declaration
|
|
|
|
|
} else if (good && selectionsForLocalVariableUnderCursor->isEmpty()) {
|
|
|
|
|
selectionsForLocalVariableUnderCursor->append(uses);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CppTools::SemanticInfo::LocalUseMap findLocalUses(const Params &p)
|
|
|
|
|
{
|
|
|
|
|
AST *ast = p.document->translationUnit()->ast();
|
|
|
|
|
FunctionDefinitionUnderCursor functionDefinitionUnderCursor(p.document->translationUnit());
|
|
|
|
|
DeclarationAST *declaration = functionDefinitionUnderCursor(ast, p.line, p.column);
|
|
|
|
|
return CppTools::LocalSymbols(p.document, declaration).uses;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QList<int> findReferences(const Params &p)
|
|
|
|
|
{
|
|
|
|
|
QList<int> result;
|
|
|
|
|
if (!p.scope || p.expression.isEmpty())
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
|
|
TypeOfExpression typeOfExpression;
|
|
|
|
|
Snapshot snapshot = p.snapshot;
|
|
|
|
|
snapshot.insert(p.document);
|
|
|
|
|
typeOfExpression.init(p.document, snapshot);
|
|
|
|
|
typeOfExpression.setExpandTemplates(true);
|
|
|
|
|
|
|
|
|
|
using CppEditor::Internal::CanonicalSymbol;
|
|
|
|
|
if (Symbol *s = CanonicalSymbol::canonicalSymbol(p.scope, p.expression, typeOfExpression)) {
|
2014-09-15 00:12:27 +02:00
|
|
|
CppTools::CppModelManager *mmi = CppTools::CppModelManager::instance();
|
2014-08-19 15:59:29 +02:00
|
|
|
result = mmi->references(s, typeOfExpression.context());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CppEditor::Internal::UseSelectionsResult findUses(const Params p)
|
|
|
|
|
{
|
|
|
|
|
CppEditor::Internal::UseSelectionsResult result;
|
|
|
|
|
|
|
|
|
|
const CppTools::SemanticInfo::LocalUseMap localUses = findLocalUses(p);
|
|
|
|
|
result.localUses = localUses;
|
|
|
|
|
splitLocalUses(localUses, p, &result.selectionsForLocalVariableUnderCursor,
|
|
|
|
|
&result.selectionsForLocalUnusedVariables);
|
|
|
|
|
|
|
|
|
|
if (!result.selectionsForLocalVariableUnderCursor.isEmpty())
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
|
|
result.references = findReferences(p);
|
|
|
|
|
return result; // OK, result.selectionsForLocalUnusedVariables will be passed on
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // anonymous namespace
|
|
|
|
|
|
|
|
|
|
namespace CppEditor {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
2014-09-26 11:37:54 +02:00
|
|
|
CppUseSelectionsUpdater::CppUseSelectionsUpdater(TextEditor::TextEditorWidget *editorWidget)
|
2014-08-19 15:59:29 +02:00
|
|
|
: m_editorWidget(editorWidget)
|
|
|
|
|
, m_findUsesRevision(-1)
|
|
|
|
|
{
|
|
|
|
|
m_timer.setSingleShot(true);
|
|
|
|
|
m_timer.setInterval(updateUseSelectionsInternalInMs);
|
|
|
|
|
connect(&m_timer, SIGNAL(timeout()), this, SLOT(update()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CppUseSelectionsUpdater::scheduleUpdate()
|
|
|
|
|
{
|
|
|
|
|
m_timer.start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CppUseSelectionsUpdater::abortSchedule()
|
|
|
|
|
{
|
|
|
|
|
m_timer.stop();
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-26 11:20:39 +02:00
|
|
|
void CppUseSelectionsUpdater::update(CallType callType)
|
2014-08-19 15:59:29 +02:00
|
|
|
{
|
|
|
|
|
CppEditorWidget *cppEditorWidget = qobject_cast<CppEditorWidget *>(m_editorWidget);
|
|
|
|
|
QTC_ASSERT(cppEditorWidget, return);
|
2014-09-08 10:15:31 +02:00
|
|
|
if (!cppEditorWidget->isSemanticInfoValidExceptLocalUses())
|
|
|
|
|
return;
|
|
|
|
|
|
2014-08-19 15:59:29 +02:00
|
|
|
const CppTools::SemanticInfo semanticInfo = cppEditorWidget->semanticInfo();
|
|
|
|
|
const Document::Ptr document = semanticInfo.doc;
|
|
|
|
|
const Snapshot snapshot = semanticInfo.snapshot;
|
|
|
|
|
|
2014-08-26 12:06:56 +02:00
|
|
|
if (!document)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (semanticInfo.revision != static_cast<unsigned>(textDocument()->revision()))
|
2014-08-19 15:59:29 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
QTC_ASSERT(document->translationUnit(), return);
|
|
|
|
|
QTC_ASSERT(document->translationUnit()->ast(), return);
|
|
|
|
|
QTC_ASSERT(!snapshot.isEmpty(), return);
|
|
|
|
|
|
2014-08-26 11:20:39 +02:00
|
|
|
if (handleMacroCase(document)) {
|
2014-08-19 15:59:29 +02:00
|
|
|
emit finished(CppTools::SemanticInfo::LocalUseMap());
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-26 11:20:39 +02:00
|
|
|
if (callType == Asynchronous)
|
|
|
|
|
handleSymbolCaseAsynchronously(document, snapshot);
|
|
|
|
|
else
|
|
|
|
|
handleSymbolCaseSynchronously(document, snapshot);
|
2014-08-19 15:59:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CppUseSelectionsUpdater::onFindUsesFinished()
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(m_findUsesWatcher, return);
|
|
|
|
|
if (m_findUsesWatcher->isCanceled())
|
|
|
|
|
return;
|
|
|
|
|
if (m_findUsesRevision != textDocument()->revision())
|
|
|
|
|
return;
|
|
|
|
|
// Optimizable: If the cursor is still on the same identifier the results are valid.
|
|
|
|
|
if (m_findUsesCursorPosition != m_editorWidget->position())
|
|
|
|
|
return;
|
|
|
|
|
|
2014-08-26 11:20:39 +02:00
|
|
|
processSymbolCaseResults(m_findUsesWatcher->result());
|
2014-08-19 15:59:29 +02:00
|
|
|
|
|
|
|
|
m_findUsesWatcher.reset();
|
|
|
|
|
m_document.reset();
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-26 11:20:39 +02:00
|
|
|
bool CppUseSelectionsUpdater::handleMacroCase(const Document::Ptr document)
|
2014-08-19 15:59:29 +02:00
|
|
|
{
|
2014-08-26 11:20:39 +02:00
|
|
|
const Macro *macro = CppTools::findCanonicalMacro(m_editorWidget->textCursor(), document);
|
2014-08-19 15:59:29 +02:00
|
|
|
if (!macro)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
const QTextCharFormat &occurrencesFormat = textCharFormat(TextEditor::C_OCCURRENCES);
|
|
|
|
|
ExtraSelections selections;
|
|
|
|
|
|
|
|
|
|
// Macro definition
|
|
|
|
|
if (macro->fileName() == document->fileName()) {
|
|
|
|
|
QTextCursor cursor(textDocument());
|
|
|
|
|
cursor.setPosition(macro->utf16CharOffset());
|
|
|
|
|
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor,
|
|
|
|
|
macro->nameToQString().size());
|
|
|
|
|
|
|
|
|
|
selections.append(extraSelection(occurrencesFormat, cursor));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Other macro uses
|
|
|
|
|
foreach (const Document::MacroUse &use, document->macroUses()) {
|
|
|
|
|
const Macro &useMacro = use.macro();
|
|
|
|
|
if (useMacro.line() != macro->line()
|
|
|
|
|
|| useMacro.utf16CharOffset() != macro->utf16CharOffset()
|
|
|
|
|
|| useMacro.length() != macro->length()
|
|
|
|
|
|| useMacro.fileName() != macro->fileName())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
QTextCursor cursor(textDocument());
|
|
|
|
|
cursor.setPosition(use.utf16charsBegin());
|
|
|
|
|
cursor.setPosition(use.utf16charsEnd(), QTextCursor::KeepAnchor);
|
|
|
|
|
|
|
|
|
|
selections.append(extraSelection(occurrencesFormat, cursor));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
updateUseSelections(selections);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-26 11:20:39 +02:00
|
|
|
void CppUseSelectionsUpdater::handleSymbolCaseAsynchronously(const Document::Ptr document,
|
|
|
|
|
const Snapshot &snapshot)
|
2014-08-19 15:59:29 +02:00
|
|
|
{
|
|
|
|
|
m_document = document;
|
|
|
|
|
|
|
|
|
|
if (m_findUsesWatcher)
|
|
|
|
|
m_findUsesWatcher->cancel();
|
|
|
|
|
m_findUsesWatcher.reset(new QFutureWatcher<UseSelectionsResult>);
|
|
|
|
|
connect(m_findUsesWatcher.data(), SIGNAL(finished()), this, SLOT(onFindUsesFinished()));
|
|
|
|
|
|
|
|
|
|
m_findUsesRevision = textDocument()->revision();
|
|
|
|
|
m_findUsesCursorPosition = m_editorWidget->position();
|
|
|
|
|
|
2014-08-26 11:20:39 +02:00
|
|
|
const Params params = Params(m_editorWidget->textCursor(), document, snapshot);
|
2016-02-12 12:58:56 +01:00
|
|
|
m_findUsesWatcher->setFuture(Utils::runAsync(findUses, params));
|
2014-08-19 15:59:29 +02:00
|
|
|
}
|
|
|
|
|
|
2014-08-26 11:20:39 +02:00
|
|
|
void CppUseSelectionsUpdater::handleSymbolCaseSynchronously(const Document::Ptr document,
|
|
|
|
|
const Snapshot &snapshot)
|
|
|
|
|
{
|
2015-02-04 17:01:07 +02:00
|
|
|
const Document::Ptr previousDocument = m_document;
|
2014-09-05 13:36:59 +02:00
|
|
|
m_document = document;
|
|
|
|
|
|
2014-08-26 11:20:39 +02:00
|
|
|
const Params params = Params(m_editorWidget->textCursor(), document, snapshot);
|
|
|
|
|
const UseSelectionsResult result = findUses(params);
|
|
|
|
|
processSymbolCaseResults(result);
|
2014-09-08 10:15:31 +02:00
|
|
|
|
|
|
|
|
m_document = previousDocument;
|
2014-08-26 11:20:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CppUseSelectionsUpdater::processSymbolCaseResults(const UseSelectionsResult &result)
|
|
|
|
|
{
|
|
|
|
|
const bool hasUsesForLocalVariable = !result.selectionsForLocalVariableUnderCursor.isEmpty();
|
|
|
|
|
const bool hasReferences = !result.references.isEmpty();
|
|
|
|
|
|
|
|
|
|
ExtraSelections localVariableSelections;
|
|
|
|
|
if (hasUsesForLocalVariable) {
|
|
|
|
|
localVariableSelections = toExtraSelections(result.selectionsForLocalVariableUnderCursor,
|
|
|
|
|
TextEditor::C_OCCURRENCES);
|
|
|
|
|
updateUseSelections(localVariableSelections);
|
|
|
|
|
} else if (hasReferences) {
|
|
|
|
|
const ExtraSelections selections = toExtraSelections(result.references,
|
|
|
|
|
TextEditor::C_OCCURRENCES);
|
|
|
|
|
updateUseSelections(selections);
|
|
|
|
|
} else {
|
|
|
|
|
if (!currentUseSelections().isEmpty())
|
|
|
|
|
updateUseSelections(ExtraSelections());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
updateUnusedSelections(toExtraSelections(result.selectionsForLocalUnusedVariables,
|
|
|
|
|
TextEditor::C_OCCURRENCES_UNUSED));
|
|
|
|
|
|
|
|
|
|
emit selectionsForVariableUnderCursorUpdated(localVariableSelections);
|
|
|
|
|
emit finished(result.localUses);
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-19 15:59:29 +02:00
|
|
|
ExtraSelections CppUseSelectionsUpdater::toExtraSelections(const SemanticUses &uses,
|
|
|
|
|
TextEditor::TextStyle style) const
|
|
|
|
|
{
|
|
|
|
|
ExtraSelections result;
|
|
|
|
|
|
|
|
|
|
foreach (const CppTools::SemanticInfo::Use &use, uses) {
|
|
|
|
|
if (use.isInvalid())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
QTextDocument *document = textDocument();
|
|
|
|
|
const int position = document->findBlockByNumber(use.line - 1).position() + use.column - 1;
|
|
|
|
|
const int anchor = position + use.length;
|
|
|
|
|
|
|
|
|
|
QTextEdit::ExtraSelection sel;
|
|
|
|
|
sel.format = textCharFormat(style);
|
|
|
|
|
sel.cursor = QTextCursor(document);
|
|
|
|
|
sel.cursor.setPosition(anchor);
|
|
|
|
|
sel.cursor.setPosition(position, QTextCursor::KeepAnchor);
|
|
|
|
|
|
|
|
|
|
result.append(sel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ExtraSelections CppUseSelectionsUpdater::toExtraSelections(const QList<int> &references,
|
|
|
|
|
TextEditor::TextStyle style) const
|
|
|
|
|
{
|
|
|
|
|
ExtraSelections selections;
|
2014-09-05 13:36:59 +02:00
|
|
|
|
|
|
|
|
QTC_ASSERT(m_document, return selections);
|
|
|
|
|
|
2014-08-19 15:59:29 +02:00
|
|
|
foreach (int index, references) {
|
|
|
|
|
unsigned line, column;
|
|
|
|
|
TranslationUnit *unit = m_document->translationUnit();
|
|
|
|
|
unit->getTokenPosition(index, &line, &column);
|
|
|
|
|
|
|
|
|
|
if (column)
|
|
|
|
|
--column; // adjust the column position.
|
|
|
|
|
|
|
|
|
|
const int len = unit->tokenAt(index).utf16chars();
|
|
|
|
|
|
|
|
|
|
QTextCursor cursor(textDocument()->findBlockByNumber(line - 1));
|
|
|
|
|
cursor.setPosition(cursor.position() + column);
|
|
|
|
|
cursor.setPosition(cursor.position() + len, QTextCursor::KeepAnchor);
|
|
|
|
|
|
|
|
|
|
selections.append(extraSelection(textCharFormat(style), cursor));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return selections;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QTextCharFormat CppUseSelectionsUpdater::textCharFormat(TextEditor::TextStyle category) const
|
|
|
|
|
{
|
|
|
|
|
return m_editorWidget->textDocument()->fontSettings().toTextCharFormat(category);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QTextDocument *CppUseSelectionsUpdater::textDocument() const
|
|
|
|
|
{
|
|
|
|
|
return m_editorWidget->document();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ExtraSelections CppUseSelectionsUpdater::currentUseSelections() const
|
|
|
|
|
{
|
|
|
|
|
return m_editorWidget->extraSelections(
|
2014-09-26 11:37:54 +02:00
|
|
|
TextEditor::TextEditorWidget::CodeSemanticsSelection);
|
2014-08-19 15:59:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CppUseSelectionsUpdater::updateUseSelections(const ExtraSelections &selections)
|
|
|
|
|
{
|
2014-09-26 11:37:54 +02:00
|
|
|
m_editorWidget->setExtraSelections(TextEditor::TextEditorWidget::CodeSemanticsSelection,
|
2014-08-19 15:59:29 +02:00
|
|
|
selections);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CppUseSelectionsUpdater::updateUnusedSelections(const ExtraSelections &selections)
|
|
|
|
|
{
|
2014-09-26 11:37:54 +02:00
|
|
|
m_editorWidget->setExtraSelections(TextEditor::TextEditorWidget::UnusedSymbolSelection,
|
2014-08-19 15:59:29 +02:00
|
|
|
selections);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace CppEditor
|