Include position information in the link

Allowed customizing the link for includes and macro uses and fix it for
highlighting the name.
This commit is contained in:
Thorbjørn Lindeijer
2009-03-24 11:13:37 +01:00
parent eebe9e2fc8
commit 1682a41869
2 changed files with 81 additions and 43 deletions

View File

@@ -370,7 +370,7 @@ void CPPEditor::jumpToMethod(int)
if (! symbol) if (! symbol)
return; return;
openCppEditorAt(locationForSymbol(symbol)); openCppEditorAt(linkToSymbol(symbol));
} }
void CPPEditor::updateMethodBoxIndex() void CPPEditor::updateMethodBoxIndex()
@@ -579,49 +579,63 @@ void CPPEditor::switchDeclarationDefinition()
declaration = symbols.first(); declaration = symbols.first();
if (declaration) if (declaration)
openCppEditorAt(locationForSymbol(declaration)); openCppEditorAt(linkToSymbol(declaration));
} else if (lastSymbol->type()->isFunctionType()) { } else if (lastSymbol->type()->isFunctionType()) {
if (Symbol *def = findDefinition(lastSymbol)) if (Symbol *def = findDefinition(lastSymbol))
openCppEditorAt(locationForSymbol(def)); openCppEditorAt(linkToSymbol(def));
} }
} }
CPPEditor::Location CPPEditor::findDestinationFor(const QTextCursor &cursor) CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor)
{ {
Location dest; Link link;
if (!m_modelManager) if (!m_modelManager)
return dest; return link;
const Snapshot snapshot = m_modelManager->snapshot(); const Snapshot snapshot = m_modelManager->snapshot();
int line = 0, column = 0; int line = 0, column = 0;
convertPosition(cursor.position(), &line, &column); convertPosition(cursor.position(), &line, &column);
Document::Ptr doc = snapshot.value(file()->fileName()); Document::Ptr doc = snapshot.value(file()->fileName());
if (!doc) if (!doc)
return dest; return link;
// Handle include directives // Handle include directives
const unsigned lineno = cursor.blockNumber() + 1; const unsigned lineno = cursor.blockNumber() + 1;
foreach (const Document::Include &incl, doc->includes()) { foreach (const Document::Include &incl, doc->includes()) {
if (incl.line() == lineno) { if (incl.line() == lineno) {
dest.fileName = incl.fileName(); link.fileName = incl.fileName();
return dest; link.pos = cursor.block().position();
link.length = cursor.block().length();
return link;
} }
} }
// Find the last symbol up to the cursor position // Find the last symbol up to the cursor position
Symbol *lastSymbol = doc->findSymbolAt(line, column); Symbol *lastSymbol = doc->findSymbolAt(line, column);
if (!lastSymbol) if (!lastSymbol)
return dest; return link;
// Get the expression under the cursor // Check whether we're at a name
const int endOfName = endOfNameAtPosition(cursor.position()); const int endOfName = endOfNameAtPosition(cursor.position());
if (!characterAt(endOfName - 1).isLetterOrNumber())
return link;
// Remember the position and length of the name
QTextCursor tc = cursor; QTextCursor tc = cursor;
tc.setPosition(endOfName); tc.setPosition(endOfName);
tc.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor);
const int nameStart = tc.position();
const int nameLength = tc.anchor() - tc.position();
// Drop out if we're at a number
if (characterAt(nameStart).isNumber())
return link;
// Evaluate the type of the expression under the cursor
tc.setPosition(endOfName);
ExpressionUnderCursor expressionUnderCursor; ExpressionUnderCursor expressionUnderCursor;
const QString expression = expressionUnderCursor(tc); const QString expression = expressionUnderCursor(tc);
// Evaluate the type of the expression
TypeOfExpression typeOfExpression; TypeOfExpression typeOfExpression;
typeOfExpression.setSnapshot(snapshot); typeOfExpression.setSnapshot(snapshot);
QList<TypeOfExpression::Result> resolvedSymbols = QList<TypeOfExpression::Result> resolvedSymbols =
@@ -634,7 +648,10 @@ CPPEditor::Location CPPEditor::findDestinationFor(const QTextCursor &cursor)
if (!lastSymbol->isFunction()) if (!lastSymbol->isFunction())
def = findDefinition(symbol); def = findDefinition(symbol);
return locationForSymbol(def ? def : symbol); link = linkToSymbol(def ? def : symbol);
link.pos = nameStart;
link.length = nameLength;
return link;
// This would jump to the type of a name // This would jump to the type of a name
#if 0 #if 0
@@ -651,19 +668,21 @@ CPPEditor::Location CPPEditor::findDestinationFor(const QTextCursor &cursor)
foreach (const Document::MacroUse use, doc->macroUses()) { foreach (const Document::MacroUse use, doc->macroUses()) {
if (use.contains(endOfName - 1)) { if (use.contains(endOfName - 1)) {
const Macro &macro = use.macro(); const Macro &macro = use.macro();
dest.fileName = QString::fromUtf8(macro.fileName()); link.fileName = QString::fromUtf8(macro.fileName());
dest.line = macro.line(); link.line = macro.line();
return dest; link.pos = use.begin();
link.length = use.end() - use.begin();
return link;
} }
} }
} }
return dest; return link;
} }
void CPPEditor::jumpToDefinition() void CPPEditor::jumpToDefinition()
{ {
openCppEditorAt(findDestinationFor(textCursor())); openCppEditorAt(findLinkAt(textCursor()));
} }
Symbol *CPPEditor::findDefinition(Symbol *symbol) Symbol *CPPEditor::findDefinition(Symbol *symbol)
@@ -791,12 +810,26 @@ void CPPEditor::mouseMoveEvent(QMouseEvent *e)
if (e->modifiers() & Qt::ControlModifier) { if (e->modifiers() & Qt::ControlModifier) {
// Link emulation behaviour for 'go to definition' // Link emulation behaviour for 'go to definition'
const QTextCursor cursor = cursorForPosition(e->pos()); const QTextCursor cursor = cursorForPosition(e->pos());
const Location loc = findDestinationFor(cursor);
if (!loc.fileName.isEmpty()) { // Check that the mouse was actually on the text somewhere
bool onText = cursorRect(cursor).right() >= e->x();
if (!onText) {
QTextCursor nextPos = cursor;
nextPos.movePosition(QTextCursor::Right);
onText = cursorRect(nextPos).right() >= e->x();
}
const Link link = findLinkAt(cursor);
if (onText && !link.fileName.isEmpty()) {
QTextEdit::ExtraSelection sel; QTextEdit::ExtraSelection sel;
sel.cursor = cursor; sel.cursor = cursor;
if (link.pos >= 0) {
sel.cursor.setPosition(link.pos);
sel.cursor.setPosition(link.pos + link.length, QTextCursor::KeepAnchor);
} else {
sel.cursor.select(QTextCursor::WordUnderCursor); sel.cursor.select(QTextCursor::WordUnderCursor);
}
sel.format.setFontUnderline(true); sel.format.setFontUnderline(true);
sel.format.setForeground(Qt::blue); sel.format.setForeground(Qt::blue);
setExtraSelections(OtherSelection, QList<QTextEdit::ExtraSelection>() << sel); setExtraSelections(OtherSelection, QList<QTextEdit::ExtraSelection>() << sel);
@@ -821,7 +854,7 @@ void CPPEditor::mouseReleaseEvent(QMouseEvent *e)
&& e->button() == Qt::LeftButton) { && e->button() == Qt::LeftButton) {
const QTextCursor cursor = cursorForPosition(e->pos()); const QTextCursor cursor = cursorForPosition(e->pos());
if (openCppEditorAt(findDestinationFor(cursor))) { if (openCppEditorAt(findLinkAt(cursor))) {
setExtraSelections(OtherSelection, QList<QTextEdit::ExtraSelection>()); setExtraSelections(OtherSelection, QList<QTextEdit::ExtraSelection>());
viewport()->setCursor(Qt::IBeamCursor); viewport()->setCursor(Qt::IBeamCursor);
e->accept(); e->accept();
@@ -1024,7 +1057,7 @@ int CPPEditor::endOfNameAtPosition(int pos)
return pos; return pos;
} }
CPPEditor::Location CPPEditor::locationForSymbol(CPlusPlus::Symbol *symbol) CPPEditor::Link CPPEditor::linkToSymbol(CPlusPlus::Symbol *symbol)
{ {
const QString fileName = QString::fromUtf8(symbol->fileName(), const QString fileName = QString::fromUtf8(symbol->fileName(),
symbol->fileNameLength()); symbol->fileNameLength());
@@ -1037,24 +1070,24 @@ CPPEditor::Location CPPEditor::locationForSymbol(CPlusPlus::Symbol *symbol)
if (symbol->isGenerated()) if (symbol->isGenerated())
column = 0; column = 0;
return Location(fileName, line, column); return Link(fileName, line, column);
} }
bool CPPEditor::openCppEditorAt(const Location &loc) bool CPPEditor::openCppEditorAt(const Link &link)
{ {
if (loc.fileName.isEmpty()) if (link.fileName.isEmpty())
return false; return false;
if (baseTextDocument()->fileName() == loc.fileName) { if (baseTextDocument()->fileName() == link.fileName) {
Core::EditorManager *editorManager = Core::EditorManager::instance(); Core::EditorManager *editorManager = Core::EditorManager::instance();
editorManager->addCurrentPositionToNavigationHistory(); editorManager->addCurrentPositionToNavigationHistory();
gotoLine(loc.line, loc.column); gotoLine(link.line, link.column);
setFocus(); setFocus();
return true; return true;
} }
return TextEditor::BaseTextEditor::openEditorAt(loc.fileName, return TextEditor::BaseTextEditor::openEditorAt(link.fileName,
loc.line, link.line,
loc.column, link.column,
Constants::C_CPPEDITOR); Constants::C_CPPEDITOR);
} }

View File

@@ -128,24 +128,29 @@ private:
int endOfNameAtPosition(int pos); int endOfNameAtPosition(int pos);
struct Location struct Link
{ {
Location(const QString &fileName = QString(), Link(const QString &fileName = QString(),
int line = 0, int line = 0,
int column = 0) int column = 0)
: fileName(fileName) : pos(-1)
, length(-1)
, fileName(fileName)
, line(line) , line(line)
, column(column) , column(column)
{} {}
QString fileName; int pos; // Link position
int line; int length; // Link length
int column;
QString fileName; // Target file
int line; // Target line
int column; // Target column
}; };
Location findDestinationFor(const QTextCursor &); Link findLinkAt(const QTextCursor &);
static Location locationForSymbol(CPlusPlus::Symbol *symbol); static Link linkToSymbol(CPlusPlus::Symbol *symbol);
bool openCppEditorAt(const Location &); bool openCppEditorAt(const Link &);
CppTools::CppModelManagerInterface *m_modelManager; CppTools::CppModelManagerInterface *m_modelManager;