forked from qt-creator/qt-creator
C++ function link: Disable function links on name change.
Change-Id: Ib5e3a3a381568347a7a465f956f7daad15f10ab0 Reviewed-on: http://codereview.qt.nokia.com/3596 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@nokia.com>
This commit is contained in:
@@ -2161,10 +2161,11 @@ void CPPEditorWidget::updateFunctionDeclDefLink()
|
|||||||
{
|
{
|
||||||
const int pos = textCursor().selectionStart();
|
const int pos = textCursor().selectionStart();
|
||||||
|
|
||||||
// if there's already a link, abort it if the cursor is outside
|
// if there's already a link, abort it if the cursor is outside or the name changed
|
||||||
if (m_declDefLink
|
if (m_declDefLink
|
||||||
&& (pos < m_declDefLink->linkSelection.selectionStart()
|
&& (pos < m_declDefLink->linkSelection.selectionStart()
|
||||||
|| pos > m_declDefLink->linkSelection.selectionEnd())) {
|
|| pos > m_declDefLink->linkSelection.selectionEnd()
|
||||||
|
|| m_declDefLink->nameSelection.selectedText() != m_declDefLink->nameInitial)) {
|
||||||
abortDeclDefLink();
|
abortDeclDefLink();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@@ -64,9 +64,14 @@ FunctionDeclDefLinkFinder::FunctionDeclDefLinkFinder(QObject *parent)
|
|||||||
void FunctionDeclDefLinkFinder::onFutureDone()
|
void FunctionDeclDefLinkFinder::onFutureDone()
|
||||||
{
|
{
|
||||||
QSharedPointer<FunctionDeclDefLink> link = m_watcher.result();
|
QSharedPointer<FunctionDeclDefLink> link = m_watcher.result();
|
||||||
if (link)
|
if (link) {
|
||||||
link->linkSelection = m_scannedSelection;
|
link->linkSelection = m_scannedSelection;
|
||||||
|
link->nameSelection = m_nameSelection;
|
||||||
|
if (m_nameSelection.selectedText() != link->nameInitial)
|
||||||
|
link.clear();
|
||||||
|
}
|
||||||
m_scannedSelection = QTextCursor();
|
m_scannedSelection = QTextCursor();
|
||||||
|
m_nameSelection = QTextCursor();
|
||||||
if (link)
|
if (link)
|
||||||
emit foundLink(link);
|
emit foundLink(link);
|
||||||
}
|
}
|
||||||
@@ -79,7 +84,8 @@ QTextCursor FunctionDeclDefLinkFinder::scannedSelection() const
|
|||||||
// parent is either a FunctionDefinitionAST or a SimpleDeclarationAST
|
// parent is either a FunctionDefinitionAST or a SimpleDeclarationAST
|
||||||
// line and column are 1-based
|
// line and column are 1-based
|
||||||
static bool findDeclOrDef(const Document::Ptr &doc, int line, int column,
|
static bool findDeclOrDef(const Document::Ptr &doc, int line, int column,
|
||||||
DeclarationAST **parent, FunctionDeclaratorAST **funcDecl)
|
DeclarationAST **parent, DeclaratorAST **decl,
|
||||||
|
FunctionDeclaratorAST **funcDecl)
|
||||||
{
|
{
|
||||||
QList<AST *> path = ASTPath(doc)(line, column);
|
QList<AST *> path = ASTPath(doc)(line, column);
|
||||||
|
|
||||||
@@ -89,29 +95,29 @@ static bool findDeclOrDef(const Document::Ptr &doc, int line, int column,
|
|||||||
// with a FunctionDeclarator postfix
|
// with a FunctionDeclarator postfix
|
||||||
FunctionDefinitionAST *funcDef = 0;
|
FunctionDefinitionAST *funcDef = 0;
|
||||||
SimpleDeclarationAST *simpleDecl = 0;
|
SimpleDeclarationAST *simpleDecl = 0;
|
||||||
DeclaratorAST *decl = 0;
|
*decl = 0;
|
||||||
for (int i = path.size() - 1; i > 0; --i) {
|
for (int i = path.size() - 1; i > 0; --i) {
|
||||||
AST *ast = path.at(i);
|
AST *ast = path.at(i);
|
||||||
if (ast->asCompoundStatement() || ast->asCtorInitializer())
|
if (ast->asCompoundStatement() || ast->asCtorInitializer())
|
||||||
break;
|
break;
|
||||||
if ((funcDef = ast->asFunctionDefinition()) != 0) {
|
if ((funcDef = ast->asFunctionDefinition()) != 0) {
|
||||||
*parent = funcDef;
|
*parent = funcDef;
|
||||||
decl = funcDef->declarator;
|
*decl = funcDef->declarator;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((simpleDecl = ast->asSimpleDeclaration()) != 0) {
|
if ((simpleDecl = ast->asSimpleDeclaration()) != 0) {
|
||||||
*parent = simpleDecl;
|
*parent = simpleDecl;
|
||||||
if (!simpleDecl->declarator_list || !simpleDecl->declarator_list->value)
|
if (!simpleDecl->declarator_list || !simpleDecl->declarator_list->value)
|
||||||
break;
|
break;
|
||||||
decl = simpleDecl->declarator_list->value;
|
*decl = simpleDecl->declarator_list->value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!*parent || !decl)
|
if (!*parent || !*decl)
|
||||||
return false;
|
return false;
|
||||||
if (!decl->postfix_declarator_list || !decl->postfix_declarator_list->value)
|
if (!(*decl)->postfix_declarator_list || !(*decl)->postfix_declarator_list->value)
|
||||||
return false;
|
return false;
|
||||||
*funcDecl = decl->postfix_declarator_list->value->asFunctionDeclarator();
|
*funcDecl = (*decl)->postfix_declarator_list->value->asFunctionDeclarator();
|
||||||
return *funcDecl;
|
return *funcDecl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,6 +136,19 @@ static void declDefLinkStartEnd(const CppTools::CppRefactoringFileConstPtr &file
|
|||||||
*end = file->endOf(funcDecl->rparen_token);
|
*end = file->endOf(funcDecl->rparen_token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DeclaratorIdAST *getDeclaratorId(DeclaratorAST *declarator)
|
||||||
|
{
|
||||||
|
if (!declarator || !declarator->core_declarator)
|
||||||
|
return 0;
|
||||||
|
if (DeclaratorIdAST *id = declarator->core_declarator->asDeclaratorId()) {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
if (NestedDeclaratorAST *nested = declarator->core_declarator->asNestedDeclarator()) {
|
||||||
|
return getDeclaratorId(nested->declarator);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static QSharedPointer<FunctionDeclDefLink> findLinkHelper(QSharedPointer<FunctionDeclDefLink> link, CppTools::CppRefactoringChanges changes)
|
static QSharedPointer<FunctionDeclDefLink> findLinkHelper(QSharedPointer<FunctionDeclDefLink> link, CppTools::CppRefactoringChanges changes)
|
||||||
{
|
{
|
||||||
QSharedPointer<FunctionDeclDefLink> noResult;
|
QSharedPointer<FunctionDeclDefLink> noResult;
|
||||||
@@ -160,8 +179,9 @@ static QSharedPointer<FunctionDeclDefLink> findLinkHelper(QSharedPointer<Functio
|
|||||||
|
|
||||||
DeclarationAST *targetParent = 0;
|
DeclarationAST *targetParent = 0;
|
||||||
FunctionDeclaratorAST *targetFuncDecl = 0;
|
FunctionDeclaratorAST *targetFuncDecl = 0;
|
||||||
|
DeclaratorAST *targetDeclarator = 0;
|
||||||
if (!findDeclOrDef(targetFile->cppDocument(), target->line(), target->column(),
|
if (!findDeclOrDef(targetFile->cppDocument(), target->line(), target->column(),
|
||||||
&targetParent, &targetFuncDecl))
|
&targetParent, &targetDeclarator, &targetFuncDecl))
|
||||||
return noResult;
|
return noResult;
|
||||||
|
|
||||||
// the parens are necessary for finding good places for changes
|
// the parens are necessary for finding good places for changes
|
||||||
@@ -191,7 +211,9 @@ void FunctionDeclDefLinkFinder::startFindLinkAt(
|
|||||||
// check if cursor is on function decl/def
|
// check if cursor is on function decl/def
|
||||||
DeclarationAST *parent = 0;
|
DeclarationAST *parent = 0;
|
||||||
FunctionDeclaratorAST *funcDecl = 0;
|
FunctionDeclaratorAST *funcDecl = 0;
|
||||||
if (!findDeclOrDef(doc, cursor.blockNumber() + 1, cursor.columnNumber() + 1, &parent, &funcDecl))
|
DeclaratorAST *declarator = 0;
|
||||||
|
if (!findDeclOrDef(doc, cursor.blockNumber() + 1, cursor.columnNumber() + 1,
|
||||||
|
&parent, &declarator, &funcDecl))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// find the start/end offsets
|
// find the start/end offsets
|
||||||
@@ -214,8 +236,16 @@ void FunctionDeclDefLinkFinder::startFindLinkAt(
|
|||||||
m_scannedSelection.setPosition(start, QTextCursor::KeepAnchor);
|
m_scannedSelection.setPosition(start, QTextCursor::KeepAnchor);
|
||||||
m_scannedSelection.setKeepPositionOnInsert(true);
|
m_scannedSelection.setKeepPositionOnInsert(true);
|
||||||
|
|
||||||
|
// build selection for the name
|
||||||
|
DeclaratorIdAST *declId = getDeclaratorId(declarator);
|
||||||
|
m_nameSelection = cursor;
|
||||||
|
m_nameSelection.setPosition(sourceFile->endOf(declId));
|
||||||
|
m_nameSelection.setPosition(sourceFile->startOf(declId), QTextCursor::KeepAnchor);
|
||||||
|
m_nameSelection.setKeepPositionOnInsert(true);
|
||||||
|
|
||||||
// set up a base result
|
// set up a base result
|
||||||
QSharedPointer<FunctionDeclDefLink> result(new FunctionDeclDefLink);
|
QSharedPointer<FunctionDeclDefLink> result(new FunctionDeclDefLink);
|
||||||
|
result->nameInitial = m_nameSelection.selectedText();
|
||||||
result->sourceDocument = doc;
|
result->sourceDocument = doc;
|
||||||
result->sourceFunction = funcDecl->symbol;
|
result->sourceFunction = funcDecl->symbol;
|
||||||
result->sourceDeclaration = parent;
|
result->sourceDeclaration = parent;
|
||||||
@@ -255,19 +285,6 @@ static bool namesEqual(const Name *n1, const Name *n2)
|
|||||||
return n1 == n2 || (n1 && n2 && n1->isEqualTo(n2));
|
return n1 == n2 || (n1 && n2 && n1->isEqualTo(n2));
|
||||||
}
|
}
|
||||||
|
|
||||||
static DeclaratorIdAST *getDeclaratorId(DeclaratorAST *declarator)
|
|
||||||
{
|
|
||||||
if (!declarator || !declarator->core_declarator)
|
|
||||||
return 0;
|
|
||||||
if (DeclaratorIdAST *id = declarator->core_declarator->asDeclaratorId()) {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
if (NestedDeclaratorAST *nested = declarator->core_declarator->asNestedDeclarator()) {
|
|
||||||
return getDeclaratorId(nested->declarator);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FunctionDeclDefLink::apply(CPPEditorWidget *editor, bool jumpToMatch)
|
void FunctionDeclDefLink::apply(CPPEditorWidget *editor, bool jumpToMatch)
|
||||||
{
|
{
|
||||||
Snapshot snapshot = editor->semanticInfo().snapshot;
|
Snapshot snapshot = editor->semanticInfo().snapshot;
|
||||||
|
@@ -71,6 +71,7 @@ private slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
QTextCursor m_scannedSelection;
|
QTextCursor m_scannedSelection;
|
||||||
|
QTextCursor m_nameSelection;
|
||||||
QFutureWatcher<QSharedPointer<FunctionDeclDefLink> > m_watcher;
|
QFutureWatcher<QSharedPointer<FunctionDeclDefLink> > m_watcher;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -92,6 +93,11 @@ public:
|
|||||||
Utils::ChangeSet changes(const CPlusPlus::Snapshot &snapshot, int targetOffset = -1);
|
Utils::ChangeSet changes(const CPlusPlus::Snapshot &snapshot, int targetOffset = -1);
|
||||||
|
|
||||||
QTextCursor linkSelection;
|
QTextCursor linkSelection;
|
||||||
|
|
||||||
|
// stored to allow aborting when the name is changed
|
||||||
|
QTextCursor nameSelection;
|
||||||
|
QString nameInitial;
|
||||||
|
|
||||||
// 1-based line and column
|
// 1-based line and column
|
||||||
unsigned targetLine;
|
unsigned targetLine;
|
||||||
unsigned targetColumn;
|
unsigned targetColumn;
|
||||||
|
Reference in New Issue
Block a user