/************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #include "qmlexpressionundercursor.h" #include #include #include #include using namespace QmlJS; using namespace QmlJS::AST; namespace { class ExpressionUnderCursor { QTextCursor _cursor; Scanner scanner; public: ExpressionUnderCursor() : start(0), end(0) {} int start, end; int startState(const QTextBlock &block) const { int state = block.previous().userState(); if (state == -1) return 0; return state & 0xff; } QString operator()(const QTextCursor &cursor) { return process(cursor); } int startOfExpression(const QList &tokens) const { return startOfExpression(tokens, tokens.size() - 1); } int startOfExpression(const QList &tokens, int index) const { if (index != -1) { const Token &tk = tokens.at(index); if (tk.is(Token::Identifier)) { if (index > 0 && tokens.at(index - 1).is(Token::Dot)) index = startOfExpression(tokens, index - 2); } else if (tk.is(Token::RightParenthesis)) { do { --index; } while (index != -1 && tokens.at(index).isNot(Token::LeftParenthesis)); if (index > 0 && tokens.at(index - 1).is(Token::Identifier)) index = startOfExpression(tokens, index - 1); } else if (tk.is(Token::RightBracket)) { do { --index; } while (index != -1 && tokens.at(index).isNot(Token::LeftBracket)); if (index > 0 && tokens.at(index - 1).is(Token::Identifier)) index = startOfExpression(tokens, index - 1); } } return index; } QString process(const QTextCursor &cursor) { _cursor = cursor; QTextBlock block = _cursor.block(); const QString blockText = block.text().left(cursor.positionInBlock()); scanner.setScanComments(false); const QList tokens = scanner(blockText, startState(block)); int start = startOfExpression(tokens); if (start == -1) return QString(); const Token &tk = tokens.at(start); return blockText.mid(tk.begin(), tokens.last().end() - tk.begin()); } }; } // enf of anonymous namespace using namespace QmlJSEditor; using namespace QmlJSEditor::Internal; QmlExpressionUnderCursor::QmlExpressionUnderCursor() : _expressionNode(0), _expressionOffset(0), _expressionLength(0) {} QmlJS::AST::ExpressionNode *QmlExpressionUnderCursor::operator()(const QTextCursor &cursor) { _expressionNode = 0; _expressionOffset = -1; _expressionLength = -1; ExpressionUnderCursor expressionUnderCursor; _text = expressionUnderCursor(cursor); exprDoc = Document::create(QLatin1String("")); exprDoc->setSource(_text); exprDoc->parseExpression(); _expressionNode = exprDoc->expression(); _expressionOffset = cursor.block().position() + expressionUnderCursor.start; _expressionLength = expressionUnderCursor.end - expressionUnderCursor.start; return _expressionNode; } ExpressionNode *QmlExpressionUnderCursor::expressionNode() const { return _expressionNode; }