forked from qt-creator/qt-creator
QmlDesigner: Add QmlDocumentParser and QmlTypesParser
Task-number: QDS-5174 Task-number: QDS-5228 Change-Id: I0889e8d63b0260aeb0efae1b3c8a373c18ea1f03 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
243
tests/unit/unittest/qmldocumentparser-test.cpp
Normal file
243
tests/unit/unittest/qmldocumentparser-test.cpp
Normal file
@@ -0,0 +1,243 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** 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
|
||||
Reference in New Issue
Block a user