From f6e6c93f710d9bd45acc40916b5293f4051ea53c Mon Sep 17 00:00:00 2001 From: Eberhard Graether Date: Wed, 9 Jul 2014 01:03:28 +0200 Subject: [PATCH] ui: improved code snippet location clicks * activate token of most nested location * show parts of locations with start or end outside of snippet * (fix for multiple parsing of function and method bodies) --- src/app/qt/element/QtCodeSnippet.cpp | 75 ++++++++++++++----- src/app/qt/element/QtCodeSnippet.h | 2 + .../component/controller/CodeController.cpp | 45 +++++------ src/lib/data/Storage.cpp | 33 ++++---- src/lib/data/parser/cxx/ASTVisitor.cpp | 4 +- 5 files changed, 102 insertions(+), 57 deletions(-) diff --git a/src/app/qt/element/QtCodeSnippet.cpp b/src/app/qt/element/QtCodeSnippet.cpp index 9751927a..912d0b44 100644 --- a/src/app/qt/element/QtCodeSnippet.cpp +++ b/src/app/qt/element/QtCodeSnippet.cpp @@ -139,26 +139,37 @@ void QtCodeSnippet::annotateText(const TokenLocationFile& locationFile) { QList extraSelections; - for (const TokenLocationFile::TokenLocationLinePairType& lineItem : locationFile.getTokenLocationLines()) - { - for (const TokenLocationLine::TokenLocationPairType& locationItem : lineItem.second->getTokenLocations()) + locationFile.forEachTokenLocation( + [&](TokenLocation* location) { - TokenLocation* location = locationItem.second.get(); - if (!location->isStartTokenLocation()) + if (location->isEndTokenLocation() && location->getStartTokenLocation()) { - continue; + return; } Annotation annotation; - annotation.start = toTextEditPosition(location->getLineNumber(), location->getColumnNumber() - 1); - annotation.end = toTextEditPosition( - location->getEndTokenLocation()->getLineNumber(), - location->getEndTokenLocation()->getColumnNumber()); + if (location->isStartTokenLocation()) + { + annotation.start = toTextEditPosition(location->getLineNumber(), location->getColumnNumber() - 1); + } + else + { + annotation.start = startTextEditPosition(); + } + + TokenLocation* endLocation = location->getEndTokenLocation(); + if (endLocation) + { + annotation.end = toTextEditPosition(endLocation->getLineNumber(), endLocation->getColumnNumber()); + } + else + { + annotation.end = endTextEditPosition(); + } + annotation.tokenId = location->getTokenId(); m_annotations.push_back(annotation); - QTextEdit::ExtraSelection selection; - Colori color; if (location->getTokenId() == m_activeTokenId) { @@ -169,6 +180,7 @@ void QtCodeSnippet::annotateText(const TokenLocationFile& locationFile) color = ApplicationSettings::getInstance()->getCodeLinkColor(); } + QTextEdit::ExtraSelection selection; selection.format.setBackground(QColor(color.r, color.g, color.b, color.a)); selection.cursor = textCursor(); @@ -178,7 +190,7 @@ void QtCodeSnippet::annotateText(const TokenLocationFile& locationFile) extraSelections.append(selection); } - } + ); setExtraSelections(extraSelections); } @@ -216,14 +228,26 @@ void QtCodeSnippet::updateLineNumberArea(const QRect &rect, int dy) void QtCodeSnippet::clickTokenLocation() { int clickPosition = textCursor().position(); + int diff = endTextEditPosition() + 1; + Id tokenId = 0; + for (Annotation annotation : m_annotations) { if (clickPosition >= annotation.start && clickPosition <= annotation.end) { - m_parentView->activateToken(annotation.tokenId); - return; + int d = annotation.end - annotation.start; + if (d < diff) + { + diff = d; + tokenId = annotation.tokenId; + } } } + + if (tokenId) + { + m_parentView->activateToken(tokenId); + } } void QtCodeSnippet::clearSelection() @@ -236,13 +260,30 @@ void QtCodeSnippet::clearSelection() int QtCodeSnippet::toTextEditPosition(int lineNumber, int columnNumber) const { lineNumber -= m_startLineNumber - 1; - int position = 0; + for (int i = 0; i < lineNumber - 1; i++) { position += document()->findBlockByLineNumber(i).length(); } - position += columnNumber; + position += columnNumber; return position; } + +int QtCodeSnippet::startTextEditPosition() const +{ + return 0; +} + +int QtCodeSnippet::endTextEditPosition() const +{ + int position = 0; + + for (int i = 0; i < document()->blockCount(); i++) + { + position += document()->findBlockByLineNumber(i).length(); + } + + return position - 1; +} diff --git a/src/app/qt/element/QtCodeSnippet.h b/src/app/qt/element/QtCodeSnippet.h index 5ed777a6..813e0300 100644 --- a/src/app/qt/element/QtCodeSnippet.h +++ b/src/app/qt/element/QtCodeSnippet.h @@ -70,6 +70,8 @@ private: }; int toTextEditPosition(int lineNumber, int columnNumber) const; + int startTextEditPosition() const; + int endTextEditPosition() const; QtCodeView* m_parentView; QtHighlighter* m_highlighter; diff --git a/src/lib/component/controller/CodeController.cpp b/src/lib/component/controller/CodeController.cpp index 2a3e8537..93e82367 100644 --- a/src/lib/component/controller/CodeController.cpp +++ b/src/lib/component/controller/CodeController.cpp @@ -26,31 +26,34 @@ void CodeController::setActiveTokenId(Id id) getView()->clearCodeSnippets(); TokenLocationCollection collection = m_locationAccess->getTokenLocationsForTokenId(id); - collection.forEachTokenLocation([&] (TokenLocation* tokenLocation) -> void { - if (tokenLocation->isStartTokenLocation()) + collection.forEachTokenLocation( + [&](TokenLocation* tokenLocation) -> void { - CodeView::CodeSnippetParams params; - const std::string filePath = tokenLocation->getFilePath(); - std::shared_ptr textAccess = TextAccess::createFromFile(filePath); - - unsigned int firstLineNumber = std::max(1, tokenLocation->getLineNumber() - lineRadius); - unsigned int lastLineNumber = std::min( - textAccess->getLineCount(), tokenLocation->getEndTokenLocation()->getLineNumber() + lineRadius - ); - - for (std::string line: textAccess->getLines(firstLineNumber, lastLineNumber)) + if (tokenLocation->isStartTokenLocation()) { - params.code += line; + const std::string filePath = tokenLocation->getFilePath(); + std::shared_ptr textAccess = TextAccess::createFromFile(filePath); + + unsigned int firstLineNumber = std::max(1, tokenLocation->getLineNumber() - lineRadius); + unsigned int lastLineNumber = std::min( + textAccess->getLineCount(), tokenLocation->getEndTokenLocation()->getLineNumber() + lineRadius + ); + + CodeView::CodeSnippetParams params; + for (const std::string& line: textAccess->getLines(firstLineNumber, lastLineNumber)) + { + params.code += line; + } + + params.startLineNumber = firstLineNumber; + params.locationFile = + m_locationAccess->getTokenLocationsForLinesInFile(filePath, firstLineNumber, lastLineNumber); + params.activeTokenId = id; + + getView()->addCodeSnippet(params); } - - params.startLineNumber = firstLineNumber; - params.locationFile = - m_locationAccess->getTokenLocationsForLinesInFile(filePath, firstLineNumber, lastLineNumber); - params.activeTokenId = id; - - getView()->addCodeSnippet(params); } - }); + ); } void CodeController::handleMessage(MessageActivateToken* message) diff --git a/src/lib/data/Storage.cpp b/src/lib/data/Storage.cpp index c2045655..c7751603 100644 --- a/src/lib/data/Storage.cpp +++ b/src/lib/data/Storage.cpp @@ -263,26 +263,25 @@ TokenLocationFile Storage::getTokenLocationsForLinesInFile( TokenLocationFile ret(fileName); TokenLocationFile* locationFile = m_locationCollection.findTokenLocationFileByPath(fileName); - if (locationFile) + if (!locationFile) { - for (unsigned int i = firstLineNumber; i <= lastLineNumber; i++) + return ret; + } + + for (unsigned int i = firstLineNumber; i <= lastLineNumber; i++) + { + TokenLocationLine* locationLine = locationFile->findTokenLocationLineByNumber(i); + if (!locationLine) { - TokenLocationLine* locationLine = locationFile->findTokenLocationLineByNumber(i); - if (locationLine) - { - locationLine->forEachTokenLocation([&] (TokenLocation* tokenLocation) -> void { - if (tokenLocation->getOtherTokenLocation() && - tokenLocation->isStartTokenLocation() && - tokenLocation->getLineNumber() >= firstLineNumber && - tokenLocation->getOtherTokenLocation()->isEndTokenLocation() && - tokenLocation->getOtherTokenLocation()->getLineNumber() <= lastLineNumber) - { - ret.addTokenLocationAsPlainCopy(tokenLocation); - ret.addTokenLocationAsPlainCopy(tokenLocation->getOtherTokenLocation()); - } - }); - } + continue; } + + locationLine->forEachTokenLocation( + [&](TokenLocation* tokenLocation) -> void + { + ret.addTokenLocationAsPlainCopy(tokenLocation); + } + ); } return ret; diff --git a/src/lib/data/parser/cxx/ASTVisitor.cpp b/src/lib/data/parser/cxx/ASTVisitor.cpp index 8024f2dd..8992adc4 100644 --- a/src/lib/data/parser/cxx/ASTVisitor.cpp +++ b/src/lib/data/parser/cxx/ASTVisitor.cpp @@ -141,7 +141,7 @@ bool ASTVisitor::VisitFunctionDecl(clang::FunctionDecl* declaration) getParameters(declaration) ); - if (declaration->hasBody()) + if (declaration->hasBody() && declaration->isThisDeclarationADefinition()) { ASTBodyVisitor bodyVisitor(this, declaration); bodyVisitor.Visit(declaration->getBody()); @@ -176,7 +176,7 @@ bool ASTVisitor::VisitCXXMethodDecl(clang::CXXMethodDecl* declaration) declaration->isStatic() ); - if (declaration->hasBody()) + if (declaration->hasBody() && declaration->isThisDeclarationADefinition()) { ASTBodyVisitor bodyVisitor(this, declaration); bodyVisitor.Visit(declaration->getBody());