forked from qt-creator/qt-creator
		
	
		
			
	
	
		
			244 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			244 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|   | /****************************************************************************
 | ||
|  | ** | ||
|  | ** Copyright (C) 2017 The Qt Company Ltd. | ||
|  | ** Contact: https://www.qt.io/licensing/
 | ||
|  | ** | ||
|  | ** This file is part of Qt Creator. | ||
|  | ** | ||
|  | ** 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 The Qt Company. For licensing terms | ||
|  | ** and conditions see https://www.qt.io/terms-conditions. For further
 | ||
|  | ** information use the contact form at https://www.qt.io/contact-us.
 | ||
|  | ** | ||
|  | ** GNU General Public License Usage | ||
|  | ** Alternatively, this file may be used under the terms of the GNU | ||
|  | ** General Public License version 3 as published by the Free Software | ||
|  | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT | ||
|  | ** included in the packaging of this file. Please review the following | ||
|  | ** information to ensure the GNU General Public License requirements will | ||
|  | ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
 | ||
|  | ** | ||
|  | ****************************************************************************/ | ||
|  | 
 | ||
|  | #include "googletest.h"
 | ||
|  | 
 | ||
|  | #include <sqlitedatabase.h>
 | ||
|  | 
 | ||
|  | #include <projectstorage/projectstorage.h>
 | ||
|  | #include <projectstorage/qmldocumentparser.h>
 | ||
|  | #include <projectstorage/sourcepathcache.h>
 | ||
|  | 
 | ||
|  | namespace { | ||
|  | 
 | ||
|  | namespace Storage = QmlDesigner::Storage; | ||
|  | using QmlDesigner::ModuleId; | ||
|  | using QmlDesigner::SourceContextId; | ||
|  | using QmlDesigner::SourceId; | ||
|  | 
 | ||
|  | MATCHER_P(HasPrototype, prototype, std::string(negation ? "isn't " : "is ") + PrintToString(prototype)) | ||
|  | { | ||
|  |     const Storage::Type &type = arg; | ||
|  | 
 | ||
|  |     return Storage::ImportedTypeName{prototype} == type.prototype; | ||
|  | } | ||
|  | 
 | ||
|  | MATCHER_P3(IsPropertyDeclaration, | ||
|  |            name, | ||
|  |            typeName, | ||
|  |            traits, | ||
|  |            std::string(negation ? "isn't " : "is ") | ||
|  |                + PrintToString(Storage::PropertyDeclaration{name, typeName, traits})) | ||
|  | { | ||
|  |     const Storage::PropertyDeclaration &propertyDeclaration = arg; | ||
|  | 
 | ||
|  |     return propertyDeclaration.name == name | ||
|  |            && Storage::ImportedTypeName{typeName} == propertyDeclaration.typeName | ||
|  |            && propertyDeclaration.traits == traits; | ||
|  | } | ||
|  | 
 | ||
|  | MATCHER_P2(IsFunctionDeclaration, | ||
|  |            name, | ||
|  |            returnTypeName, | ||
|  |            std::string(negation ? "isn't " : "is ") | ||
|  |                + PrintToString(Storage::FunctionDeclaration{name, returnTypeName})) | ||
|  | { | ||
|  |     const Storage::FunctionDeclaration &declaration = arg; | ||
|  | 
 | ||
|  |     return declaration.name == name && declaration.returnTypeName == returnTypeName; | ||
|  | } | ||
|  | 
 | ||
|  | MATCHER_P(IsSignalDeclaration, | ||
|  |           name, | ||
|  |           std::string(negation ? "isn't " : "is ") + PrintToString(Storage::SignalDeclaration{name})) | ||
|  | { | ||
|  |     const Storage::SignalDeclaration &declaration = arg; | ||
|  | 
 | ||
|  |     return declaration.name == name; | ||
|  | } | ||
|  | 
 | ||
|  | MATCHER_P2(IsParameter, | ||
|  |            name, | ||
|  |            typeName, | ||
|  |            std::string(negation ? "isn't " : "is ") | ||
|  |                + PrintToString(Storage::ParameterDeclaration{name, typeName})) | ||
|  | { | ||
|  |     const Storage::ParameterDeclaration &declaration = arg; | ||
|  | 
 | ||
|  |     return declaration.name == name && declaration.typeName == typeName; | ||
|  | } | ||
|  | 
 | ||
|  | MATCHER_P(IsEnumeration, | ||
|  |           name, | ||
|  |           std::string(negation ? "isn't " : "is ") | ||
|  |               + PrintToString(Storage::EnumerationDeclaration{name, {}})) | ||
|  | { | ||
|  |     const Storage::EnumerationDeclaration &declaration = arg; | ||
|  | 
 | ||
|  |     return declaration.name == name; | ||
|  | } | ||
|  | 
 | ||
|  | MATCHER_P(IsEnumerator, | ||
|  |           name, | ||
|  |           std::string(negation ? "isn't " : "is ") | ||
|  |               + PrintToString(Storage::EnumeratorDeclaration{name})) | ||
|  | { | ||
|  |     const Storage::EnumeratorDeclaration &declaration = arg; | ||
|  | 
 | ||
|  |     return declaration.name == name && !declaration.hasValue; | ||
|  | } | ||
|  | 
 | ||
|  | MATCHER_P2(IsEnumerator, | ||
|  |            name, | ||
|  |            value, | ||
|  |            std::string(negation ? "isn't " : "is ") | ||
|  |                + PrintToString(Storage::EnumeratorDeclaration{name, value, true})) | ||
|  | { | ||
|  |     const Storage::EnumeratorDeclaration &declaration = arg; | ||
|  | 
 | ||
|  |     return declaration.name == name && declaration.value == value && declaration.hasValue; | ||
|  | } | ||
|  | 
 | ||
|  | class QmlDocumentParser : public ::testing::Test | ||
|  | { | ||
|  | public: | ||
|  | protected: | ||
|  |     Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; | ||
|  |     QmlDesigner::ProjectStorage<Sqlite::Database> storage{database, database.isInitialized()}; | ||
|  |     QmlDesigner::SourcePathCache<QmlDesigner::ProjectStorage<Sqlite::Database>> sourcePathCache{ | ||
|  |         storage}; | ||
|  |     QmlDesigner::QmlDocumentParser parser{sourcePathCache}; | ||
|  |     Storage::Imports imports; | ||
|  |     SourceId qmlFileSourceId{sourcePathCache.sourceId("path/to/qmlfile.qml")}; | ||
|  |     SourceContextId qmlFileSourceContextId{sourcePathCache.sourceContextId(qmlFileSourceId)}; | ||
|  |     SourceId directorySourceId{sourcePathCache.sourceId("path/to/.")}; | ||
|  |     ModuleId directoryModuleId{&directorySourceId}; | ||
|  | }; | ||
|  | 
 | ||
|  | TEST_F(QmlDocumentParser, Prototype) | ||
|  | { | ||
|  |     auto type = parser.parse("Example{}", imports, qmlFileSourceId, qmlFileSourceContextId); | ||
|  | 
 | ||
|  |     ASSERT_THAT(type, HasPrototype(Storage::ImportedType("Example"))); | ||
|  | } | ||
|  | 
 | ||
|  | TEST_F(QmlDocumentParser, DISABLED_QualifiedPrototype) | ||
|  | { | ||
|  |     auto type = parser.parse("import Example as Example\n Example.Item{}", | ||
|  |                              imports, | ||
|  |                              qmlFileSourceId, | ||
|  |                              qmlFileSourceContextId); | ||
|  | 
 | ||
|  |     ASSERT_THAT(type, | ||
|  |                 HasPrototype(Storage::QualifiedImportedType( | ||
|  |                     "Item", Storage::Import{"Example", Storage::Version{}, qmlFileSourceId}))); | ||
|  | } | ||
|  | 
 | ||
|  | TEST_F(QmlDocumentParser, Properties) | ||
|  | { | ||
|  |     auto type = parser.parse("Example{\n property int foo\n}", | ||
|  |                              imports, | ||
|  |                              qmlFileSourceId, | ||
|  |                              qmlFileSourceContextId); | ||
|  | 
 | ||
|  |     ASSERT_THAT(type.propertyDeclarations, | ||
|  |                 UnorderedElementsAre(IsPropertyDeclaration("foo", | ||
|  |                                                            Storage::ImportedType{"int"}, | ||
|  |                                                            Storage::PropertyDeclarationTraits::None))); | ||
|  | } | ||
|  | 
 | ||
|  | TEST_F(QmlDocumentParser, DISABLED_Imports) | ||
|  | { | ||
|  |     ModuleId fooDirectoryModuleId{&sourcePathCache.sourceId("path/to/foo/.")}; | ||
|  |     auto type = parser.parse("import QtQuick\n import \"../foo\"\nExample{}", | ||
|  |                              imports, | ||
|  |                              qmlFileSourceId, | ||
|  |                              qmlFileSourceContextId); | ||
|  | 
 | ||
|  |     ASSERT_THAT(imports, | ||
|  |                 UnorderedElementsAre( | ||
|  |                     Storage::Import{Storage::Version{}, directoryModuleId, qmlFileSourceId}, | ||
|  |                     Storage::Import{Storage::Version{}, fooDirectoryModuleId, qmlFileSourceId}, | ||
|  |                     Storage::Import{"QML", Storage::Version{1, 0}, qmlFileSourceId}, | ||
|  |                     Storage::Import{"QtQml", Storage::Version{6, 0}, qmlFileSourceId}, | ||
|  |                     Storage::Import{"QtQuick", Storage::Version{}, qmlFileSourceId})); | ||
|  | } | ||
|  | 
 | ||
|  | TEST_F(QmlDocumentParser, Functions) | ||
|  | { | ||
|  |     auto type = parser.parse( | ||
|  |         "Example{\n function someScript(x, y) {}\n function otherFunction() {}\n}", | ||
|  |         imports, | ||
|  |         qmlFileSourceId, | ||
|  |         qmlFileSourceContextId); | ||
|  | 
 | ||
|  |     ASSERT_THAT(type.functionDeclarations, | ||
|  |                 UnorderedElementsAre(AllOf(IsFunctionDeclaration("otherFunction", ""), | ||
|  |                                            Field(&Storage::FunctionDeclaration::parameters, IsEmpty())), | ||
|  |                                      AllOf(IsFunctionDeclaration("someScript", ""), | ||
|  |                                            Field(&Storage::FunctionDeclaration::parameters, | ||
|  |                                                  ElementsAre(IsParameter("x", ""), | ||
|  |                                                              IsParameter("y", "")))))); | ||
|  | } | ||
|  | 
 | ||
|  | TEST_F(QmlDocumentParser, Signals) | ||
|  | { | ||
|  |     auto type = parser.parse("Example{\n signal someSignal(int x, real y)\n signal signal2()\n}", | ||
|  |                              imports, | ||
|  |                              qmlFileSourceId, | ||
|  |                              qmlFileSourceContextId); | ||
|  | 
 | ||
|  |     ASSERT_THAT(type.signalDeclarations, | ||
|  |                 UnorderedElementsAre(AllOf(IsSignalDeclaration("someSignal"), | ||
|  |                                            Field(&Storage::SignalDeclaration::parameters, | ||
|  |                                                  ElementsAre(IsParameter("x", "int"), | ||
|  |                                                              IsParameter("y", "real")))), | ||
|  |                                      AllOf(IsSignalDeclaration("signal2"), | ||
|  |                                            Field(&Storage::SignalDeclaration::parameters, IsEmpty())))); | ||
|  | } | ||
|  | 
 | ||
|  | TEST_F(QmlDocumentParser, Enumeration) | ||
|  | { | ||
|  |     auto type = parser.parse("Example{\n enum Color{red, green, blue=10, white}\n enum " | ||
|  |                              "State{On,Off}\n}", | ||
|  |                              imports, | ||
|  |                              qmlFileSourceId, | ||
|  |                              qmlFileSourceContextId); | ||
|  | 
 | ||
|  |     ASSERT_THAT(type.enumerationDeclarations, | ||
|  |                 UnorderedElementsAre( | ||
|  |                     AllOf(IsEnumeration("Color"), | ||
|  |                           Field(&Storage::EnumerationDeclaration::enumeratorDeclarations, | ||
|  |                                 ElementsAre(IsEnumerator("red", 0), | ||
|  |                                             IsEnumerator("green", 1), | ||
|  |                                             IsEnumerator("blue", 10), | ||
|  |                                             IsEnumerator("white", 11)))), | ||
|  |                     AllOf(IsEnumeration("State"), | ||
|  |                           Field(&Storage::EnumerationDeclaration::enumeratorDeclarations, | ||
|  |                                 ElementsAre(IsEnumerator("On", 0), IsEnumerator("Off", 1)))))); | ||
|  | } | ||
|  | 
 | ||
|  | } // namespace
 |