1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
32 **************************************************************************/
34 #include "addpropertyvisitor.h"
36 #include <qmljs/parser/qmljsast_p.h>
37 #include <qmljs/parser/qmljsengine_p.h>
39 using namespace QmlDesigner;
40 using namespace QmlDesigner::Internal;
41 using namespace QmlJS;
42 using namespace QmlJS::AST;
44 AddPropertyVisitor::AddPropertyVisitor(QmlDesigner::TextModifier &modifier,
45 quint32 parentLocation,
48 QmlRefactoring::PropertyType propertyType,
49 const QStringList &propertyOrder):
50 QMLRewriter(modifier),
51 m_parentLocation(parentLocation),
54 m_propertyType(propertyType),
55 m_propertyOrder(propertyOrder)
59 bool AddPropertyVisitor::visit(QmlJS::AST::UiObjectDefinition *ast)
64 if (ast->firstSourceLocation().offset == m_parentLocation) {
65 // FIXME: change this to use the QmlJS::Rewriter class
66 addInMembers(ast->initializer);
70 return !didRewriting();
73 bool AddPropertyVisitor::visit(QmlJS::AST::UiObjectBinding *ast)
78 if (ast->qualifiedTypeNameId->identifierToken.offset == m_parentLocation) {
79 // FIXME: change this to use the QmlJS::Rewriter class
80 addInMembers(ast->initializer);
84 return !didRewriting();
87 // FIXME: duplicate code in the QmlJS::Rewriter class, remove this
88 void AddPropertyVisitor::addInMembers(QmlJS::AST::UiObjectInitializer *initializer)
90 UiObjectMemberList *insertAfter = searchMemberToInsertAfter(initializer->members, m_name, m_propertyOrder);
91 SourceLocation endOfPreviousMember;
92 SourceLocation startOfNextMember;
95 if (insertAfter == 0 || insertAfter->member == 0) {
96 // insert as first member
97 endOfPreviousMember = initializer->lbraceToken;
99 if (initializer->members && initializer->members->member)
100 startOfNextMember = initializer->members->member->firstSourceLocation();
102 startOfNextMember = initializer->rbraceToken;
104 depth = calculateIndentDepth(endOfPreviousMember) + indentDepth();
106 endOfPreviousMember = insertAfter->member->lastSourceLocation();
108 if (insertAfter->next && insertAfter->next->member)
109 startOfNextMember = insertAfter->next->member->firstSourceLocation();
111 startOfNextMember = initializer->rbraceToken;
113 depth = calculateIndentDepth(endOfPreviousMember);
115 const bool isOneLiner = endOfPreviousMember.startLine == startOfNextMember.startLine;
116 bool needsPreceedingSemicolon = false;
117 bool needsTrailingSemicolon = false;
120 if (insertAfter == 0) { // we're inserting after an lbrace
121 if (initializer->members) { // we're inserting before a member (and not the rbrace)
122 needsTrailingSemicolon = m_propertyType == QmlRefactoring::ScriptBinding;
124 } else { // we're inserting after a member, not after the lbrace
125 if (endOfPreviousMember.isValid()) { // there already is a semicolon after the previous member
126 if (insertAfter->next && insertAfter->next->member) { // and the after us there is a member, not an rbrace, so:
127 needsTrailingSemicolon = m_propertyType == QmlRefactoring::ScriptBinding;
129 } else { // there is no semicolon after the previous member (probably because there is an rbrace after us/it, so:
130 needsPreceedingSemicolon = true;
135 QString newPropertyTemplate;
136 switch (m_propertyType) {
137 case QmlRefactoring::ArrayBinding:
138 newPropertyTemplate = QLatin1String("%1: [\n%2\n]");
139 m_value = addIndentation(m_value, 4);
142 case QmlRefactoring::ObjectBinding:
143 newPropertyTemplate = QLatin1String("%1: %2");
146 case QmlRefactoring::ScriptBinding:
147 newPropertyTemplate = QLatin1String("%1: %2");
151 Q_ASSERT(!"unknown property type");
155 if (needsPreceedingSemicolon)
156 newPropertyTemplate.prepend(QLatin1Char(';'));
157 newPropertyTemplate.prepend(QLatin1Char(' '));
158 if (needsTrailingSemicolon)
159 newPropertyTemplate.append(QLatin1Char(';'));
162 newPropertyTemplate.prepend(QLatin1Char('\n'));
165 const QString newPropertyText = addIndentation(newPropertyTemplate.arg(m_name, m_value), depth);
166 replace(endOfPreviousMember.end(), 0, newPropertyText);
168 setDidRewriting(true);