aboutsummaryrefslogtreecommitdiffstats
path: root/tools/qmltc/qmltcvisitor.h
blob: 755fe02171bd014883f55a19e92950babe7122fa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0

#ifndef QMLTCVISITOR_H
#define QMLTCVISITOR_H

#include <QtCore/qstring.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qlist.h>

#include <QtQml/private/qqmlirbuilder_p.h>
#include <private/qqmljsimportvisitor_p.h>
#include <private/qqmljslogger_p.h>

QT_BEGIN_NAMESPACE

class QmltcVisitor : public QQmlJSImportVisitor
{
    void findCppIncludes();
    void postVisitResolve(const QHash<QQmlJSScope::ConstPtr, QList<QQmlJSMetaPropertyBinding>>
                                  &qmlIrOrderedBindings);
    void setupAliases();
    void checkForNamingCollisionsWithCpp(const QQmlJSScope::ConstPtr &type);

public:
    QmltcVisitor(const QQmlJSScope::Ptr &target, QQmlJSImporter *importer, QQmlJSLogger *logger,
                 const QString &implicitImportDirectory,
                 const QStringList &qmldirFiles = QStringList());

    bool visit(QQmlJS::AST::UiObjectDefinition *) override;
    void endVisit(QQmlJS::AST::UiObjectDefinition *) override;

    bool visit(QQmlJS::AST::UiObjectBinding *) override;
    void endVisit(QQmlJS::AST::UiObjectBinding *) override;

    bool visit(QQmlJS::AST::UiScriptBinding *) override;

    bool visit(QQmlJS::AST::UiPublicMember *) override;

    bool visit(QQmlJS::AST::UiInlineComponent *) override;

    void endVisit(QQmlJS::AST::UiProgram *) override;

    QList<QQmlJSScope::ConstPtr> qmlTypesWithQmlBases() const { return m_qmlTypesWithQmlBases; }
    QSet<QString> cppIncludeFiles() const { return m_cppIncludes; }

    qsizetype creationIndex(const QQmlJSScope::ConstPtr &type) const
    {
        Q_ASSERT(m_pureTypeIndices.contains(type));
        Q_ASSERT(type->scopeType() == QQmlJSScope::QMLScope);
        return m_pureTypeIndices[type];
    }

    qsizetype qmlComponentIndex(const QQmlJSScope::ConstPtr &type) const
    {
        Q_ASSERT(type->scopeType() == QQmlJSScope::QMLScope);
        return m_syntheticTypeIndices.value(type, -1);
    }

    qsizetype qmlIrObjectIndex(const QQmlJSScope::ConstPtr &type) const
    {
        Q_ASSERT(type->scopeType() == QQmlJSScope::QMLScope);
        Q_ASSERT(m_qmlIrObjectIndices.contains(type));
        return m_qmlIrObjectIndices[type];
    }

    /*! \internal
        Returns a runtime index counterpart of `id: foo` for \a type. Returns -1
        if \a type does not have an id.
    */
    int runtimeId(const QQmlJSScope::ConstPtr &type) const
    {
        // NB: this function is expected to be called for "pure" types
        Q_ASSERT(!m_typesWithId.contains(type) || m_typesWithId[type] != -1);
        return m_typesWithId.value(type, -1);
    }

    /*! \internal
        Returns all encountered QML types.
    */
    QList<QQmlJSScope::ConstPtr> allQmlTypes() const { return qmlTypes(); }

    /*! \internal
        Returns encountered QML types which return \c false in
        \c{isComponentRootElement()}. Called "pure", because these are the ones
        that are not wrapped into QQmlComponent. Pure QML types can be created
        through direct constructor invocation.
    */
    QList<QQmlJSScope::ConstPtr> pureQmlTypes() const { return m_pureQmlTypes; }

    /*! \internal
        Returns \c true when \a type has deferred bindings. Returns \c false
        otherwise.
    */
    bool hasDeferredBindings(const QQmlJSScope::ConstPtr &type) const
    {
        return m_typesWithDeferredBindings.contains(type);
    }

    enum Mode { Import, Compile };
    void setMode(Mode mode) { m_mode = mode; }

protected:
    QStringList m_qmlTypeNames; // names of QML types arranged as a stack
    QHash<QString, int> m_qmlTypeNameCounts;
    QList<QQmlJSScope::ConstPtr> m_qmlTypesWithQmlBases; // QML types with composite/QML base types
    QSet<QString> m_cppIncludes; // all C++ includes found from QQmlJSScope hierarchy
    QList<QQmlJSScope::ConstPtr> m_pureQmlTypes; // the ones not under QQmlComponent

    QHash<QQmlJSScope::ConstPtr, qsizetype> m_pureTypeIndices;
    QHash<QQmlJSScope::ConstPtr, qsizetype> m_syntheticTypeIndices;
    QHash<QQmlJSScope::ConstPtr, qsizetype> m_qmlIrObjectIndices;

    QSet<QQmlJSScope::ConstPtr> m_typesWithDeferredBindings;

    // prefer allQmlTypes or pureQmlTypes. this function is misleading in qmltc
    QList<QQmlJSScope::ConstPtr> qmlTypes() const { return QQmlJSImportVisitor::qmlTypes(); }

    QHash<QQmlJSScope::ConstPtr, int> m_typesWithId;

    Mode m_mode = Mode::Import;
};

QT_END_NAMESPACE

#endif // QMLTCVISITOR_H