forked from qt-creator/qt-creator
		
	C++ insert definition: Find better insertion point.
Change-Id: Ic424ae7ed4ac6dcda5d96353071ba0415c1815da Reviewed-on: http://codereview.qt.nokia.com/2732 Reviewed-by: Leandro T. C. Melo <leandro.melo@nokia.com>
This commit is contained in:
		@@ -37,6 +37,7 @@
 | 
			
		||||
#include <AST.h>
 | 
			
		||||
#include <ASTVisitor.h>
 | 
			
		||||
#include <TranslationUnit.h>
 | 
			
		||||
#include <Literals.h>
 | 
			
		||||
 | 
			
		||||
#include <coreplugin/icore.h>
 | 
			
		||||
#include <coreplugin/mimedatabase.h>
 | 
			
		||||
@@ -317,6 +318,103 @@ static bool isSourceFile(const QString &fileName)
 | 
			
		||||
    return suffixes.contains(fileInfo.suffix());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
template <class Key, class Value>
 | 
			
		||||
class HighestValue
 | 
			
		||||
{
 | 
			
		||||
    Key _key;
 | 
			
		||||
    Value _value;
 | 
			
		||||
    bool _set;
 | 
			
		||||
public:
 | 
			
		||||
    HighestValue()
 | 
			
		||||
        : _set(false)
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
    HighestValue(const Key &initialKey, const Value &initialValue)
 | 
			
		||||
        : _key(initialKey)
 | 
			
		||||
        , _value(initialValue)
 | 
			
		||||
        , _set(true)
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
    void maybeSet(const Key &key, const Value &value)
 | 
			
		||||
    {
 | 
			
		||||
        if (!_set || key > _key) {
 | 
			
		||||
            _value = value;
 | 
			
		||||
            _key = key;
 | 
			
		||||
            _set = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const Value &get() const
 | 
			
		||||
    {
 | 
			
		||||
        Q_ASSERT(_set);
 | 
			
		||||
        return _value;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class FindMethodDefinitionInsertPoint : protected ASTVisitor
 | 
			
		||||
{
 | 
			
		||||
    QList<const Identifier *> _namespaceNames;
 | 
			
		||||
    int _currentDepth;
 | 
			
		||||
    HighestValue<int, int> _bestToken;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    FindMethodDefinitionInsertPoint(TranslationUnit *translationUnit)
 | 
			
		||||
        : ASTVisitor(translationUnit)
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
    void operator()(Declaration *decl, unsigned *line, unsigned *column)
 | 
			
		||||
    {
 | 
			
		||||
        *line = *column = 0;
 | 
			
		||||
        if (translationUnit()->ast()->lastToken() < 2)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        QList<const Name *> names = LookupContext::fullyQualifiedName(decl);
 | 
			
		||||
        foreach (const Name *name, names) {
 | 
			
		||||
            const Identifier *id = name->asNameId();
 | 
			
		||||
            if (!id)
 | 
			
		||||
                break;
 | 
			
		||||
            _namespaceNames += id;
 | 
			
		||||
        }
 | 
			
		||||
        _currentDepth = 0;
 | 
			
		||||
 | 
			
		||||
        // default to end of file
 | 
			
		||||
        _bestToken.maybeSet(-1, translationUnit()->ast()->lastToken() - 1);
 | 
			
		||||
        accept(translationUnit()->ast());
 | 
			
		||||
        translationUnit()->getTokenEndPosition(_bestToken.get(), line, column);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    bool preVisit(AST *ast)
 | 
			
		||||
    {
 | 
			
		||||
        return ast->asNamespace() || ast->asTranslationUnit() || ast->asLinkageBody();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool visit(NamespaceAST *ast)
 | 
			
		||||
    {
 | 
			
		||||
        if (_currentDepth >= _namespaceNames.size())
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        // ignore anonymous namespaces
 | 
			
		||||
        if (!ast->identifier_token)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        const Identifier *name = translationUnit()->identifier(ast->identifier_token);
 | 
			
		||||
        if (!name->equalTo(_namespaceNames.at(_currentDepth)))
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        // found a good namespace
 | 
			
		||||
        _bestToken.maybeSet(_currentDepth, ast->lastToken() - 2);
 | 
			
		||||
 | 
			
		||||
        ++_currentDepth;
 | 
			
		||||
        accept(ast->linkage_body);
 | 
			
		||||
        --_currentDepth;
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
} // anonymous namespace
 | 
			
		||||
 | 
			
		||||
/// Currently, we return the end of fileName.cpp
 | 
			
		||||
/// \todo take the definitions of the surrounding declarations into account
 | 
			
		||||
QList<InsertionLocation> InsertionPointLocator::methodDefinition(
 | 
			
		||||
@@ -348,13 +446,9 @@ QList<InsertionLocation> InsertionPointLocator::methodDefinition(
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    TranslationUnit *xUnit = doc->translationUnit();
 | 
			
		||||
    unsigned tokenCount = xUnit->tokenCount();
 | 
			
		||||
    if (tokenCount < 2) // no tokens available
 | 
			
		||||
        return result;
 | 
			
		||||
 | 
			
		||||
    unsigned line = 0, column = 0;
 | 
			
		||||
    xUnit->getTokenEndPosition(xUnit->tokenCount() - 2, &line, &column);
 | 
			
		||||
    FindMethodDefinitionInsertPoint finder(doc->translationUnit());
 | 
			
		||||
    finder(declaration, &line, &column);
 | 
			
		||||
 | 
			
		||||
    const QLatin1String prefix("\n\n");
 | 
			
		||||
    result.append(InsertionLocation(target, prefix, QString(), line, column));
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user