forked from qt-creator/qt-creator
Mark the symbols lazily in a background thread.
This commit is contained in:
@@ -270,15 +270,13 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
struct FindCanonicalSymbol
|
||||
struct CanonicalSymbol
|
||||
{
|
||||
CPPEditor *editor;
|
||||
QString code;
|
||||
TypeOfExpression typeOfExpression;
|
||||
ExpressionUnderCursor expressionUnderCursor;
|
||||
SemanticInfo info;
|
||||
|
||||
FindCanonicalSymbol(CPPEditor *editor, const SemanticInfo &info)
|
||||
CanonicalSymbol(CPPEditor *editor, const SemanticInfo &info)
|
||||
: editor(editor), info(info)
|
||||
{
|
||||
typeOfExpression.init(info.doc, info.snapshot);
|
||||
@@ -289,12 +287,19 @@ struct FindCanonicalSymbol
|
||||
return typeOfExpression.context();
|
||||
}
|
||||
|
||||
inline bool isIdentifierChar(const QChar &ch) const
|
||||
static inline bool isIdentifierChar(const QChar &ch)
|
||||
{
|
||||
return ch.isLetterOrNumber() || ch == QLatin1Char('_');
|
||||
}
|
||||
|
||||
Symbol *operator()(const QTextCursor &cursor)
|
||||
Scope *getScopeAndExpression(const QTextCursor &cursor, QString *code)
|
||||
{
|
||||
return getScopeAndExpression(editor, info, cursor, code);
|
||||
}
|
||||
|
||||
static Scope *getScopeAndExpression(CPPEditor *editor, const SemanticInfo &info,
|
||||
const QTextCursor &cursor,
|
||||
QString *code)
|
||||
{
|
||||
if (! info.doc)
|
||||
return 0;
|
||||
@@ -316,10 +321,30 @@ struct FindCanonicalSymbol
|
||||
++pos;
|
||||
tc.setPosition(pos);
|
||||
|
||||
code = expressionUnderCursor(tc);
|
||||
Scope *scope = info.doc->scopeAt(line, col);
|
||||
ExpressionUnderCursor expressionUnderCursor;
|
||||
*code = expressionUnderCursor(tc);
|
||||
return info.doc->scopeAt(line, col);
|
||||
}
|
||||
|
||||
Symbol *operator()(const QTextCursor &cursor)
|
||||
{
|
||||
QString code;
|
||||
|
||||
if (Scope *scope = getScopeAndExpression(cursor, &code))
|
||||
return operator()(scope, code);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Symbol *operator()(Scope *scope, const QString &code)
|
||||
{
|
||||
return canonicalSymbol(scope, code, typeOfExpression);
|
||||
}
|
||||
|
||||
static Symbol *canonicalSymbol(Scope *scope, const QString &code, TypeOfExpression &typeOfExpression)
|
||||
{
|
||||
const QList<LookupItem> results = typeOfExpression(code, scope, TypeOfExpression::Preprocess);
|
||||
|
||||
for (int i = 0; i < results.size(); ++i) { // ### TODO virtual methods and classes.
|
||||
const LookupItem &r = results.at(i);
|
||||
|
||||
@@ -329,6 +354,7 @@ struct FindCanonicalSymbol
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // end of anonymous namespace
|
||||
@@ -372,6 +398,10 @@ CPPEditor::CPPEditor(QWidget *parent)
|
||||
m_nextHighlightBlockNumber = 0;
|
||||
connect(&m_highlightWatcher, SIGNAL(resultsReadyAt(int,int)), SLOT(highlightTypeUsages(int,int)));
|
||||
connect(&m_highlightWatcher, SIGNAL(finished()), SLOT(finishTypeUsages()));
|
||||
|
||||
m_referencesRevision = 0;
|
||||
m_referencesCursorPosition = 0;
|
||||
connect(&m_referencesWatcher, SIGNAL(finished()), SLOT(markSymbolsNow()));
|
||||
}
|
||||
|
||||
CPPEditor::~CPPEditor()
|
||||
@@ -587,7 +617,7 @@ void CPPEditor::findUsages()
|
||||
{
|
||||
const SemanticInfo info = m_lastSemanticInfo;
|
||||
|
||||
FindCanonicalSymbol cs(this, info);
|
||||
CanonicalSymbol cs(this, info);
|
||||
Symbol *canonicalSymbol = cs(textCursor());
|
||||
if (canonicalSymbol) {
|
||||
m_modelManager->findUsages(canonicalSymbol, cs.context());
|
||||
@@ -634,7 +664,7 @@ void CPPEditor::renameUsagesNow()
|
||||
{
|
||||
const SemanticInfo info = m_lastSemanticInfo;
|
||||
|
||||
FindCanonicalSymbol cs(this, info);
|
||||
CanonicalSymbol cs(this, info);
|
||||
if (Symbol *canonicalSymbol = cs(textCursor())) {
|
||||
if (canonicalSymbol->identifier() != 0) {
|
||||
if (showWarningMessage()) {
|
||||
@@ -649,42 +679,73 @@ void CPPEditor::renameUsagesNow()
|
||||
}
|
||||
}
|
||||
|
||||
void CPPEditor::markSymbols(Symbol *canonicalSymbol, const SemanticInfo &info)
|
||||
void CPPEditor::markSymbolsNow()
|
||||
{
|
||||
//updateSemanticInfo(m_semanticHighlighter->semanticInfo(currentSource()));
|
||||
if (m_references.isCanceled())
|
||||
return;
|
||||
else if (m_referencesCursorPosition != position())
|
||||
return;
|
||||
else if (m_referencesRevision != editorRevision())
|
||||
return;
|
||||
|
||||
abortRename();
|
||||
const SemanticInfo info = m_lastSemanticInfo;
|
||||
TranslationUnit *unit = info.doc->translationUnit();
|
||||
const QList<int> result = m_references.result();
|
||||
|
||||
QList<QTextEdit::ExtraSelection> selections;
|
||||
|
||||
if (info.doc && canonicalSymbol) {
|
||||
TranslationUnit *unit = info.doc->translationUnit();
|
||||
foreach (int index, result) {
|
||||
unsigned line, column;
|
||||
unit->getTokenPosition(index, &line, &column);
|
||||
|
||||
LookupContext context(info.doc, info.snapshot);
|
||||
const QList<int> references = m_modelManager->references(canonicalSymbol, context);
|
||||
foreach (int index, references) {
|
||||
unsigned line, column;
|
||||
unit->getTokenPosition(index, &line, &column);
|
||||
if (column)
|
||||
--column; // adjust the column position.
|
||||
|
||||
if (column)
|
||||
--column; // adjust the column position.
|
||||
const int len = unit->tokenAt(index).f.length;
|
||||
|
||||
const int len = unit->tokenAt(index).f.length;
|
||||
QTextCursor cursor(document()->findBlockByNumber(line - 1));
|
||||
cursor.setPosition(cursor.position() + column);
|
||||
cursor.setPosition(cursor.position() + len, QTextCursor::KeepAnchor);
|
||||
|
||||
QTextCursor cursor(document()->findBlockByNumber(line - 1));
|
||||
cursor.setPosition(cursor.position() + column);
|
||||
cursor.setPosition(cursor.position() + len, QTextCursor::KeepAnchor);
|
||||
QTextEdit::ExtraSelection sel;
|
||||
sel.format = m_occurrencesFormat;
|
||||
sel.cursor = cursor;
|
||||
selections.append(sel);
|
||||
|
||||
QTextEdit::ExtraSelection sel;
|
||||
sel.format = m_occurrencesFormat;
|
||||
sel.cursor = cursor;
|
||||
selections.append(sel);
|
||||
}
|
||||
}
|
||||
|
||||
setExtraSelections(CodeSemanticsSelection, selections);
|
||||
}
|
||||
|
||||
static QList<int> lazyFindReferences(Scope *scope, QString code, const LookupContext &context)
|
||||
{
|
||||
TypeOfExpression typeOfExpression;
|
||||
typeOfExpression.init(context.thisDocument(), context.snapshot(), context.bindings());
|
||||
if (Symbol *canonicalSymbol = CanonicalSymbol::canonicalSymbol(scope, code, typeOfExpression))
|
||||
return CppTools::CppModelManagerInterface::instance()->references(canonicalSymbol, context);
|
||||
return QList<int>();
|
||||
}
|
||||
|
||||
void CPPEditor::markSymbols(const QTextCursor &tc, const SemanticInfo &info)
|
||||
{
|
||||
abortRename();
|
||||
|
||||
if (! info.doc)
|
||||
return;
|
||||
|
||||
CanonicalSymbol cs(this, info);
|
||||
QString expression;
|
||||
if (Scope *scope = cs.getScopeAndExpression(this, info, tc, &expression)) {
|
||||
LookupContext context(info.doc, info.snapshot);
|
||||
|
||||
m_references.cancel();
|
||||
m_referencesRevision = info.revision;
|
||||
m_referencesCursorPosition = position();
|
||||
m_references = QtConcurrent::run(&lazyFindReferences, scope, expression, context);
|
||||
m_referencesWatcher.setFuture(m_references);
|
||||
}
|
||||
}
|
||||
|
||||
void CPPEditor::renameSymbolUnderCursor()
|
||||
{
|
||||
updateSemanticInfo(m_semanticHighlighter->semanticInfo(currentSource()));
|
||||
@@ -1792,8 +1853,7 @@ void CPPEditor::updateSemanticInfo(const SemanticInfo &semanticInfo)
|
||||
if (! m_renameSelections.isEmpty())
|
||||
setExtraSelections(CodeSemanticsSelection, m_renameSelections); // ###
|
||||
else {
|
||||
FindCanonicalSymbol cs(this, semanticInfo);
|
||||
markSymbols(cs(textCursor()), semanticInfo);
|
||||
markSymbols(textCursor(), semanticInfo);
|
||||
}
|
||||
|
||||
m_lastSemanticInfo.forced = false; // clear the forced flag
|
||||
|
@@ -236,13 +236,15 @@ private Q_SLOTS:
|
||||
void highlightTypeUsages(int from, int to);
|
||||
void finishTypeUsages();
|
||||
|
||||
void markSymbolsNow();
|
||||
|
||||
void performQuickFix(int index);
|
||||
|
||||
private:
|
||||
bool showWarningMessage() const;
|
||||
void setShowWarningMessage(bool showWarningMessage);
|
||||
|
||||
void markSymbols(CPlusPlus::Symbol *canonicalSymbol, const SemanticInfo &info);
|
||||
void markSymbols(const QTextCursor &tc, const SemanticInfo &info);
|
||||
bool sortedOutline() const;
|
||||
CPlusPlus::Symbol *findDefinition(CPlusPlus::Symbol *symbol, const CPlusPlus::Snapshot &snapshot);
|
||||
virtual void indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar);
|
||||
@@ -305,6 +307,11 @@ private:
|
||||
QFutureWatcher<SemanticInfo::Use> m_highlightWatcher;
|
||||
unsigned m_highlightRevision; // the editor revision that requested the highlight
|
||||
int m_nextHighlightBlockNumber;
|
||||
|
||||
QFuture<QList<int> > m_references;
|
||||
QFutureWatcher<QList<int> > m_referencesWatcher;
|
||||
unsigned m_referencesRevision;
|
||||
int m_referencesCursorPosition;
|
||||
};
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user