| 
									
										
										
										
											2012-10-02 09:12:39 +02:00
										 |  |  | /****************************************************************************
 | 
					
						
							| 
									
										
										
										
											2010-06-30 17:51:21 +02:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2013-01-28 17:12:19 +01:00
										 |  |  | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). | 
					
						
							| 
									
										
										
										
											2012-10-02 09:12:39 +02:00
										 |  |  | ** Contact: http://www.qt-project.org/legal
 | 
					
						
							| 
									
										
										
										
											2010-06-30 17:51:21 +02:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2012-10-02 09:12:39 +02:00
										 |  |  | ** This file is part of Qt Creator. | 
					
						
							| 
									
										
										
										
											2010-06-30 17:51:21 +02:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2012-10-02 09:12:39 +02:00
										 |  |  | ** Commercial License Usage | 
					
						
							|  |  |  | ** Licensees holding valid commercial Qt licenses may use this file in | 
					
						
							|  |  |  | ** accordance with the commercial license agreement provided with the | 
					
						
							|  |  |  | ** Software or, alternatively, in accordance with the terms contained in | 
					
						
							|  |  |  | ** a written agreement between you and Digia.  For licensing terms and | 
					
						
							|  |  |  | ** conditions see http://qt.digia.com/licensing.  For further information
 | 
					
						
							|  |  |  | ** use the contact form at http://qt.digia.com/contact-us.
 | 
					
						
							| 
									
										
										
										
											2010-06-30 17:51:21 +02:00
										 |  |  | ** | 
					
						
							|  |  |  | ** GNU Lesser General Public License Usage | 
					
						
							| 
									
										
										
										
											2012-10-02 09:12:39 +02:00
										 |  |  | ** 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, Digia gives you certain additional | 
					
						
							|  |  |  | ** rights.  These rights are described in the Digia Qt LGPL Exception | 
					
						
							| 
									
										
										
										
											2010-12-17 16:01:08 +01:00
										 |  |  | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2012-10-02 09:12:39 +02:00
										 |  |  | ****************************************************************************/ | 
					
						
							| 
									
										
										
										
											2010-06-30 17:51:21 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "qmljspropertyreader.h"
 | 
					
						
							|  |  |  | #include "qmljsdocument.h"
 | 
					
						
							|  |  |  | #include <qmljs/parser/qmljsast_p.h>
 | 
					
						
							| 
									
										
										
										
											2011-10-07 14:04:06 +02:00
										 |  |  | #include <qmljs/qmljsutils.h>
 | 
					
						
							| 
									
										
										
										
											2010-06-30 17:51:21 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-15 10:42:41 +01:00
										 |  |  | #include <QLinearGradient>
 | 
					
						
							| 
									
										
										
										
											2011-01-20 14:03:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-30 17:51:21 +02:00
										 |  |  | namespace QmlJS { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using namespace AST; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline QString deEscape(const QString &value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QString result = value; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result.replace(QLatin1String("\\\\"), QLatin1String("\\")); | 
					
						
							|  |  |  |     result.replace(QLatin1String("\\\""), QLatin1String("\"")); | 
					
						
							|  |  |  |     result.replace(QLatin1String("\\\t"), QLatin1String("\t")); | 
					
						
							|  |  |  |     result.replace(QLatin1String("\\\r"), QLatin1String("\r")); | 
					
						
							|  |  |  |     result.replace(QLatin1String("\\\n"), QLatin1String("\n")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline QString stripQuotes(const QString &str) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if ((str.startsWith(QLatin1Char('"')) && str.endsWith(QLatin1Char('"'))) | 
					
						
							|  |  |  |             || (str.startsWith(QLatin1Char('\'')) && str.endsWith(QLatin1Char('\'')))) | 
					
						
							|  |  |  |         return str.mid(1, str.length() - 2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return str; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool isLiteralValue(ExpressionNode *expr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (cast<NumericLiteral*>(expr)) | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     else if (cast<StringLiteral*>(expr)) | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     else if (UnaryPlusExpression *plusExpr = cast<UnaryPlusExpression*>(expr)) | 
					
						
							|  |  |  |         return isLiteralValue(plusExpr->expression); | 
					
						
							|  |  |  |     else if (UnaryMinusExpression *minusExpr = cast<UnaryMinusExpression*>(expr)) | 
					
						
							|  |  |  |         return isLiteralValue(minusExpr->expression); | 
					
						
							|  |  |  |     else if (cast<TrueLiteral*>(expr)) | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     else if (cast<FalseLiteral*>(expr)) | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline bool isLiteralValue(UiScriptBinding *script) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!script || !script->statement) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ExpressionStatement *exprStmt = cast<ExpressionStatement *>(script->statement); | 
					
						
							|  |  |  |     if (exprStmt) | 
					
						
							|  |  |  |         return isLiteralValue(exprStmt->expression); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-15 14:12:27 +02:00
										 |  |  | static inline QString textAt(const Document::Ptr doc, | 
					
						
							| 
									
										
										
										
											2010-06-30 17:51:21 +02:00
										 |  |  |                                   const SourceLocation &from, | 
					
						
							|  |  |  |                                   const SourceLocation &to) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return doc->source().mid(from.offset, to.end() - from.begin()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline int propertyType(const QString &typeName) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (typeName == QLatin1String("bool")) | 
					
						
							|  |  |  |         return QMetaType::type("bool"); | 
					
						
							|  |  |  |     else if (typeName == QLatin1String("color")) | 
					
						
							|  |  |  |         return QMetaType::type("QColor"); | 
					
						
							|  |  |  |     else if (typeName == QLatin1String("date")) | 
					
						
							|  |  |  |         return QMetaType::type("QDate"); | 
					
						
							|  |  |  |     else if (typeName == QLatin1String("int")) | 
					
						
							|  |  |  |         return QMetaType::type("int"); | 
					
						
							|  |  |  |     else if (typeName == QLatin1String("real")) | 
					
						
							|  |  |  |         return QMetaType::type("double"); | 
					
						
							|  |  |  |     else if (typeName == QLatin1String("double")) | 
					
						
							|  |  |  |         return QMetaType::type("double"); | 
					
						
							|  |  |  |     else if (typeName == QLatin1String("string")) | 
					
						
							|  |  |  |         return QMetaType::type("QString"); | 
					
						
							|  |  |  |     else if (typeName == QLatin1String("url")) | 
					
						
							|  |  |  |         return QMetaType::type("QUrl"); | 
					
						
							|  |  |  |     else if (typeName == QLatin1String("variant")) | 
					
						
							|  |  |  |         return QMetaType::type("QVariant"); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool isEnum(AST::Statement *ast); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool isEnum(AST::ExpressionNode *ast) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!ast) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (FieldMemberExpression *memberExpr = cast<AST::FieldMemberExpression*>(ast)) | 
					
						
							|  |  |  |         return isEnum(memberExpr->base); | 
					
						
							|  |  |  |     else if (cast<IdentifierExpression*>(ast)) | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool isEnum(AST::Statement *ast) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!ast) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												Remove braces for single lines of conditions
#!/usr/bin/env ruby
Dir.glob('**/*.cpp') { |file|
  # skip ast (excluding paste, astpath, and canv'ast'imer)
  next if file =~ /ast[^eip]|keywords\.|qualifiers|preprocessor|names.cpp/i
  s = File.read(file)
  next if s.include?('qlalr')
  orig = s.dup
  s.gsub!(/\n *if [^\n]*{\n[^\n]*\n\s+}(\s+else if [^\n]* {\n[^\n]*\n\s+})*(\s+else {\n[^\n]*\n\s+})?\n/m) { |m|
    res = $&
    if res =~ /^\s*(\/\/|[A-Z_]{3,})/ # C++ comment or macro (Q_UNUSED, SDEBUG), do not touch braces
      res
    else
      res.gsub!('} else', 'else')
      res.gsub!(/\n +} *\n/m, "\n")
      res.gsub(/ *{$/, '')
    end
  }
  s.gsub!(/ *$/, '')
  File.open(file, 'wb').write(s) if s != orig
}
Change-Id: I3b30ee60df0986f66c02132c65fc38a3fbb6bbdc
Reviewed-by: hjk <qthjk@ovi.com>
											
										 
											2013-01-08 03:32:53 +02:00
										 |  |  |     if (ExpressionStatement *exprStmt = cast<ExpressionStatement*>(ast)) | 
					
						
							| 
									
										
										
										
											2010-06-30 17:51:21 +02:00
										 |  |  |         return isEnum(exprStmt->expression); | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-09 18:09:01 +02:00
										 |  |  | static QString cleanupSemicolon(const QString &str) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QString out = str; | 
					
						
							|  |  |  |     while (out.endsWith(QLatin1Char(';'))) | 
					
						
							|  |  |  |         out.chop(1); | 
					
						
							|  |  |  |     return out; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-30 17:51:21 +02:00
										 |  |  | } // anonymous namespace
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-15 14:12:27 +02:00
										 |  |  | PropertyReader::PropertyReader(Document::Ptr doc, AST::UiObjectInitializer *ast) | 
					
						
							| 
									
										
										
										
											2010-06-30 17:51:21 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-15 14:12:27 +02:00
										 |  |  |     m_ast = ast; | 
					
						
							|  |  |  |     m_doc = doc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!m_doc) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-30 17:51:21 +02:00
										 |  |  |     for (UiObjectMemberList *members = ast->members; members; members = members->next) { | 
					
						
							|  |  |  |         UiObjectMember *member = members->member; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (UiScriptBinding *property = AST::cast<UiScriptBinding *>(member)) { | 
					
						
							|  |  |  |             if (!property->qualifiedId) | 
					
						
							|  |  |  |                 continue; // better safe than sorry.
 | 
					
						
							| 
									
										
										
										
											2011-10-07 14:04:06 +02:00
										 |  |  |             const QString propertyName = toString(property->qualifiedId); | 
					
						
							| 
									
										
										
										
											2010-07-09 18:09:01 +02:00
										 |  |  |             const QString astValue = cleanupSemicolon(textAt(doc, | 
					
						
							| 
									
										
										
										
											2010-06-30 17:51:21 +02:00
										 |  |  |                               property->statement->firstSourceLocation(), | 
					
						
							| 
									
										
										
										
											2010-07-09 18:09:01 +02:00
										 |  |  |                               property->statement->lastSourceLocation())); | 
					
						
							| 
									
										
										
										
											2010-06-30 17:51:21 +02:00
										 |  |  |             if (isLiteralValue(property)) { | 
					
						
							|  |  |  |                 m_properties.insert(propertyName, QVariant(deEscape(stripQuotes(astValue)))); | 
					
						
							|  |  |  |             } else if (isEnum(property->statement)) { //enum
 | 
					
						
							|  |  |  |                  m_properties.insert(propertyName, QVariant(astValue)); | 
					
						
							| 
									
										
										
										
											2010-07-15 14:12:27 +02:00
										 |  |  |                  m_bindingOrEnum.append(propertyName); | 
					
						
							| 
									
										
										
										
											2010-06-30 17:51:21 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         } else if (UiObjectDefinition *objectDefinition = cast<UiObjectDefinition *>(member)) { //font { bold: true }
 | 
					
						
							| 
									
										
										
										
											2011-09-13 09:57:24 +02:00
										 |  |  |             const QString propertyName = objectDefinition->qualifiedTypeNameId->name.toString(); | 
					
						
							| 
									
										
										
										
											2010-06-30 17:51:21 +02:00
										 |  |  |             if (!propertyName.isEmpty() && !propertyName.at(0).isUpper()) { | 
					
						
							|  |  |  |                 for (UiObjectMemberList *iter = objectDefinition->initializer->members; iter; iter = iter->next) { | 
					
						
							|  |  |  |                     UiObjectMember *objectMember = iter->member; | 
					
						
							|  |  |  |                     if (UiScriptBinding *property = cast<UiScriptBinding *>(objectMember)) { | 
					
						
							| 
									
										
										
										
											2011-10-07 14:04:06 +02:00
										 |  |  |                         const QString propertyNamePart2 = toString(property->qualifiedId); | 
					
						
							| 
									
										
										
										
											2010-07-09 18:09:01 +02:00
										 |  |  |                         const QString astValue = cleanupSemicolon(textAt(doc, | 
					
						
							| 
									
										
										
										
											2010-06-30 17:51:21 +02:00
										 |  |  |                             property->statement->firstSourceLocation(), | 
					
						
							| 
									
										
										
										
											2010-07-09 18:09:01 +02:00
										 |  |  |                             property->statement->lastSourceLocation())); | 
					
						
							| 
									
										
										
										
											2010-06-30 17:51:21 +02:00
										 |  |  |                         if (isLiteralValue(property)) { | 
					
						
							| 
									
										
										
										
											2012-11-27 20:20:02 +02:00
										 |  |  |                             m_properties.insert(propertyName + QLatin1Char('.') + propertyNamePart2, | 
					
						
							|  |  |  |                                                 QVariant(deEscape(stripQuotes(astValue)))); | 
					
						
							| 
									
										
										
										
											2010-06-30 17:51:21 +02:00
										 |  |  |                         } else if (isEnum(property->statement)) { //enum
 | 
					
						
							| 
									
										
										
										
											2012-11-27 20:20:02 +02:00
										 |  |  |                             m_properties.insert(propertyName + QLatin1Char('.') + propertyNamePart2, QVariant(astValue)); | 
					
						
							|  |  |  |                             m_bindingOrEnum.append(propertyName + QLatin1Char('.') + propertyNamePart2); | 
					
						
							| 
									
										
										
										
											2010-07-15 14:12:27 +02:00
										 |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else if (UiObjectBinding* objectBinding = cast<UiObjectBinding *>(member)) { | 
					
						
							|  |  |  |             UiObjectInitializer *initializer = objectBinding->initializer; | 
					
						
							|  |  |  |             const QString astValue = cleanupSemicolon(textAt(doc, | 
					
						
							|  |  |  |                               initializer->lbraceToken, | 
					
						
							|  |  |  |                               initializer->rbraceToken)); | 
					
						
							| 
									
										
										
										
											2011-09-13 09:57:24 +02:00
										 |  |  |             const QString propertyName = objectBinding->qualifiedId->name.toString(); | 
					
						
							| 
									
										
										
										
											2010-07-15 14:12:27 +02:00
										 |  |  |             m_properties.insert(propertyName, QVariant(astValue)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-21 12:57:11 +02:00
										 |  |  | QLinearGradient PropertyReader::parseGradient(const QString &propertyName,  bool *isBound) const | 
					
						
							| 
									
										
										
										
											2010-07-15 14:12:27 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     if (!m_doc) | 
					
						
							|  |  |  |         return QLinearGradient(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-21 12:57:11 +02:00
										 |  |  |     *isBound = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-15 14:12:27 +02:00
										 |  |  |     for (UiObjectMemberList *members = m_ast->members; members; members = members->next) { | 
					
						
							|  |  |  |         UiObjectMember *member = members->member; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (UiObjectBinding* objectBinding = cast<UiObjectBinding *>(member)) { | 
					
						
							|  |  |  |             UiObjectInitializer *initializer = objectBinding->initializer; | 
					
						
							|  |  |  |             const QString astValue = cleanupSemicolon(textAt(m_doc, | 
					
						
							|  |  |  |                                                              initializer->lbraceToken, | 
					
						
							|  |  |  |                                                              initializer->rbraceToken)); | 
					
						
							| 
									
										
										
										
											2011-09-13 09:57:24 +02:00
										 |  |  |             const QString objectPropertyName = objectBinding->qualifiedId->name.toString(); | 
					
						
							|  |  |  |             const QString typeName = objectBinding->qualifiedTypeNameId->name.toString(); | 
					
						
							| 
									
										
										
										
											2012-11-27 20:20:02 +02:00
										 |  |  |             if (objectPropertyName == propertyName && typeName.contains(QLatin1String("Gradient"))) { | 
					
						
							| 
									
										
										
										
											2010-07-15 14:12:27 +02:00
										 |  |  |                 QLinearGradient gradient; | 
					
						
							|  |  |  |                 QVector<QGradientStop> stops; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 for (UiObjectMemberList *members = initializer->members; members; members = members->next) { | 
					
						
							|  |  |  |                     UiObjectMember *member = members->member; | 
					
						
							|  |  |  |                     if (UiObjectDefinition *objectDefinition = cast<UiObjectDefinition *>(member)) { | 
					
						
							|  |  |  |                         PropertyReader localParser(m_doc, objectDefinition->initializer); | 
					
						
							| 
									
										
										
										
											2012-11-27 20:20:02 +02:00
										 |  |  |                         if (localParser.hasProperty(QLatin1String("color")) && localParser.hasProperty(QLatin1String("position"))) { | 
					
						
							|  |  |  |                             QColor color = QmlJS::toQColor(localParser.readProperty(QLatin1String("color")).toString()); | 
					
						
							|  |  |  |                             qreal position = localParser.readProperty(QLatin1String("position")).toReal(); | 
					
						
							|  |  |  |                             if (localParser.isBindingOrEnum(QLatin1String("color")) || localParser.isBindingOrEnum(QLatin1String("position"))) | 
					
						
							| 
									
										
										
										
											2010-07-21 12:57:11 +02:00
										 |  |  |                                 *isBound = true; | 
					
						
							| 
									
										
										
										
											2010-07-15 14:12:27 +02:00
										 |  |  |                             stops.append( QPair<qreal, QColor>(position, color)); | 
					
						
							| 
									
										
										
										
											2010-06-30 17:51:21 +02:00
										 |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2010-07-15 14:12:27 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 gradient.setStops(stops); | 
					
						
							|  |  |  |                 return gradient; | 
					
						
							| 
									
										
										
										
											2010-06-30 17:51:21 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-07-15 14:12:27 +02:00
										 |  |  |     return QLinearGradient(); | 
					
						
							| 
									
										
										
										
											2010-06-30 17:51:21 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2010-07-15 14:12:27 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-30 17:51:21 +02:00
										 |  |  | } //QmlJS
 |