forked from qt-creator/qt-creator
QmlJS: Move SemanticInfo from qmljseditor to qmljstools
This will allow us to remove the qmljsinspector->qmljseditor dependency. Change-Id: I234cf8645edb614e8b1f559a0f9bb6d43e2254c3 Reviewed-by: Fawzi Mohamed <fawzi.mohamed@nokia.com>
This commit is contained in:
@@ -45,14 +45,9 @@
|
||||
|
||||
#include <qmljs/qmljsbind.h>
|
||||
#include <qmljs/qmljsevaluate.h>
|
||||
#include <qmljs/qmljsdocument.h>
|
||||
#include <qmljs/qmljsicontextpane.h>
|
||||
#include <qmljs/qmljsmodelmanagerinterface.h>
|
||||
#include <qmljs/qmljsscopebuilder.h>
|
||||
#include <qmljs/qmljsutils.h>
|
||||
#include <qmljs/parser/qmljsastvisitor_p.h>
|
||||
#include <qmljs/parser/qmljsast_p.h>
|
||||
#include <qmljs/parser/qmljsengine_p.h>
|
||||
|
||||
#include <qmljstools/qmljsindenter.h>
|
||||
#include <qmljstools/qmljsqtstylecodeformatter.h>
|
||||
@@ -105,6 +100,7 @@ using namespace QmlJS;
|
||||
using namespace QmlJS::AST;
|
||||
using namespace QmlJSEditor;
|
||||
using namespace QmlJSEditor::Internal;
|
||||
using namespace QmlJSTools;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -451,208 +447,9 @@ protected:
|
||||
|
||||
};
|
||||
|
||||
// ### does not necessarily give the full AST path!
|
||||
// intentionally does not contain lists like
|
||||
// UiImportList, SourceElements, UiObjectMemberList
|
||||
class AstPath: protected AST::Visitor
|
||||
{
|
||||
QList<AST::Node *> _path;
|
||||
unsigned _offset;
|
||||
|
||||
public:
|
||||
QList<AST::Node *> operator()(AST::Node *node, unsigned offset)
|
||||
{
|
||||
_offset = offset;
|
||||
_path.clear();
|
||||
accept(node);
|
||||
return _path;
|
||||
}
|
||||
|
||||
protected:
|
||||
using AST::Visitor::visit;
|
||||
|
||||
void accept(AST::Node *node)
|
||||
{
|
||||
if (node)
|
||||
node->accept(this);
|
||||
}
|
||||
|
||||
bool containsOffset(AST::SourceLocation start, AST::SourceLocation end)
|
||||
{
|
||||
return _offset >= start.begin() && _offset <= end.end();
|
||||
}
|
||||
|
||||
bool handle(AST::Node *ast,
|
||||
AST::SourceLocation start, AST::SourceLocation end,
|
||||
bool addToPath = true)
|
||||
{
|
||||
if (containsOffset(start, end)) {
|
||||
if (addToPath)
|
||||
_path.append(ast);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool handleLocationAst(T *ast, bool addToPath = true)
|
||||
{
|
||||
return handle(ast, ast->firstSourceLocation(), ast->lastSourceLocation(), addToPath);
|
||||
}
|
||||
|
||||
virtual bool preVisit(AST::Node *node)
|
||||
{
|
||||
if (Statement *stmt = node->statementCast()) {
|
||||
return handleLocationAst(stmt);
|
||||
} else if (ExpressionNode *exp = node->expressionCast()) {
|
||||
return handleLocationAst(exp);
|
||||
} else if (UiObjectMember *ui = node->uiObjectMemberCast()) {
|
||||
return handleLocationAst(ui);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool visit(AST::UiQualifiedId *ast)
|
||||
{
|
||||
AST::SourceLocation first = ast->identifierToken;
|
||||
AST::SourceLocation last;
|
||||
for (AST::UiQualifiedId *it = ast; it; it = it->next)
|
||||
last = it->identifierToken;
|
||||
if (containsOffset(first, last))
|
||||
_path.append(ast);
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool visit(AST::UiProgram *ast)
|
||||
{
|
||||
_path.append(ast);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool visit(AST::Program *ast)
|
||||
{
|
||||
_path.append(ast);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool visit(AST::UiImport *ast)
|
||||
{
|
||||
return handleLocationAst(ast);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
||||
|
||||
AST::Node *SemanticInfo::rangeAt(int cursorPosition) const
|
||||
{
|
||||
AST::Node *declaringMember = 0;
|
||||
|
||||
for (int i = ranges.size() - 1; i != -1; --i) {
|
||||
const Range &range = ranges.at(i);
|
||||
|
||||
if (range.begin.isNull() || range.end.isNull()) {
|
||||
continue;
|
||||
} else if (cursorPosition >= range.begin.position() && cursorPosition <= range.end.position()) {
|
||||
declaringMember = range.ast;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return declaringMember;
|
||||
}
|
||||
|
||||
// ### the name and behavior of this function is dubious
|
||||
QmlJS::AST::Node *SemanticInfo::declaringMemberNoProperties(int cursorPosition) const
|
||||
{
|
||||
AST::Node *node = rangeAt(cursorPosition);
|
||||
|
||||
if (UiObjectDefinition *objectDefinition = cast<UiObjectDefinition*>(node)) {
|
||||
const QString &name = objectDefinition->qualifiedTypeNameId->name.toString();
|
||||
if (!name.isEmpty() && name.at(0).isLower()) {
|
||||
QList<AST::Node *> path = rangePath(cursorPosition);
|
||||
if (path.size() > 1)
|
||||
return path.at(path.size() - 2);
|
||||
} else if (name.contains("GradientStop")) {
|
||||
QList<AST::Node *> path = rangePath(cursorPosition);
|
||||
if (path.size() > 2)
|
||||
return path.at(path.size() - 3);
|
||||
}
|
||||
} else if (UiObjectBinding *objectBinding = cast<UiObjectBinding*>(node)) {
|
||||
const QString &name = objectBinding->qualifiedTypeNameId->name.toString();
|
||||
if (name.contains("Gradient")) {
|
||||
QList<AST::Node *> path = rangePath(cursorPosition);
|
||||
if (path.size() > 1)
|
||||
return path.at(path.size() - 2);
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
QList<AST::Node *> SemanticInfo::rangePath(int cursorPosition) const
|
||||
{
|
||||
QList<AST::Node *> path;
|
||||
|
||||
foreach (const Range &range, ranges) {
|
||||
if (range.begin.isNull() || range.end.isNull()) {
|
||||
continue;
|
||||
} else if (cursorPosition >= range.begin.position() && cursorPosition <= range.end.position()) {
|
||||
path += range.ast;
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
ScopeChain SemanticInfo::scopeChain(const QList<QmlJS::AST::Node *> &path) const
|
||||
{
|
||||
Q_ASSERT(m_rootScopeChain);
|
||||
|
||||
if (path.isEmpty())
|
||||
return *m_rootScopeChain;
|
||||
|
||||
ScopeChain scope = *m_rootScopeChain;
|
||||
ScopeBuilder builder(&scope);
|
||||
builder.push(path);
|
||||
return scope;
|
||||
}
|
||||
|
||||
QList<AST::Node *> SemanticInfo::astPath(int pos) const
|
||||
{
|
||||
QList<AST::Node *> result;
|
||||
if (! document)
|
||||
return result;
|
||||
|
||||
AstPath astPath;
|
||||
return astPath(document->ast(), pos);
|
||||
}
|
||||
|
||||
AST::Node *SemanticInfo::astNodeAt(int pos) const
|
||||
{
|
||||
const QList<AST::Node *> path = astPath(pos);
|
||||
if (path.isEmpty())
|
||||
return 0;
|
||||
return path.last();
|
||||
}
|
||||
|
||||
bool SemanticInfo::isValid() const
|
||||
{
|
||||
if (document && context && m_rootScopeChain)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int SemanticInfo::revision() const
|
||||
{
|
||||
if (document)
|
||||
return document->editorRevision();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
QmlJSTextEditorWidget::QmlJSTextEditorWidget(QWidget *parent) :
|
||||
TextEditor::BaseTextEditorWidget(parent),
|
||||
m_outlineCombo(0),
|
||||
@@ -664,7 +461,7 @@ QmlJSTextEditorWidget::QmlJSTextEditorWidget(QWidget *parent) :
|
||||
m_findReferences(new FindReferences(this)),
|
||||
m_semanticHighlighter(new SemanticHighlighter(this))
|
||||
{
|
||||
qRegisterMetaType<QmlJSEditor::SemanticInfo>("QmlJSEditor::SemanticInfo");
|
||||
qRegisterMetaType<QmlJSTools::SemanticInfo>("QmlJSTools::SemanticInfo");
|
||||
|
||||
m_semanticInfoUpdater = new SemanticInfoUpdater(this);
|
||||
m_semanticInfoUpdater->start();
|
||||
@@ -731,8 +528,8 @@ QmlJSTextEditorWidget::QmlJSTextEditorWidget(QWidget *parent) :
|
||||
connect(this->document(), SIGNAL(modificationChanged(bool)), this, SLOT(modificationChanged(bool)));
|
||||
}
|
||||
|
||||
connect(m_semanticInfoUpdater, SIGNAL(updated(QmlJSEditor::SemanticInfo)),
|
||||
this, SLOT(acceptNewSemanticInfo(QmlJSEditor::SemanticInfo)));
|
||||
connect(m_semanticInfoUpdater, SIGNAL(updated(QmlJSTools::SemanticInfo)),
|
||||
this, SLOT(acceptNewSemanticInfo(QmlJSTools::SemanticInfo)));
|
||||
|
||||
connect(this, SIGNAL(refactorMarkerClicked(TextEditor::RefactorMarker)),
|
||||
SLOT(onRefactorMarkerClicked(TextEditor::RefactorMarker)));
|
||||
|
Reference in New Issue
Block a user