Revision control
Copy as Markdown
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef CPP_H
#define CPP_H
#include <translator.h>
#include <QtCore/QSet>
#include <QtCore/QStack>
QT_BEGIN_NAMESPACE
struct HashString
{
HashString() : m_hash(0x80000000) {}
explicit HashString(const QString &str) : m_str(str), m_hash(0x80000000) {}
void setValue(const QString &str) { m_str = str; m_hash = 0x80000000; }
const QString &value() const { return m_str; }
bool operator==(const HashString &other) const { return m_str == other.m_str; }
QString m_str;
mutable uint m_hash; // We use the highest bit as a validity indicator (set => invalid)
};
QDebug operator<<(QDebug debug, const HashString &s);
size_t qHash(const HashString &str, size_t seed = 0);
struct HashStringList {
explicit HashStringList(const QList<HashString> &list) : m_list(list), m_hash(0x80000000) {}
const QList<HashString> &value() const { return m_list; }
bool operator==(const HashStringList &other) const { return m_list == other.m_list; }
QList<HashString> m_list;
mutable uint m_hash; // We use the highest bit as a validity indicator (set => invalid)
};
QDebug operator<<(QDebug debug, const HashStringList &lst);
size_t qHash(const HashStringList &list, size_t seed = 0);
typedef QList<HashString> NamespaceList;
struct Namespace {
Namespace() : classDef(this) { }
~Namespace()
{
qDeleteAll(children);
}
Namespace *parent = nullptr;
QHash<HashString, Namespace *> children;
QHash<HashString, NamespaceList> aliases;
QList<HashStringList> usings;
// Class declarations set no flags and create no namespaces, so they are ignored.
// Class definitions may appear multiple times - but only because we are trying to
// "compile" all sources irrespective of build configuration.
// Nested classes may be forward-declared inside a definition, and defined in another file.
// The latter will detach the class' child list, so clones need a backlink to the original
// definition (either one in case of multiple definitions).
// Namespaces can have tr() functions as well, so we need to track parent definitions for
// them as well. The complication is that we may have to deal with a forrest instead of
// a tree - in that case the parent will be arbitrary. However, it seem likely that
// Q_DECLARE_TR_FUNCTIONS would be used either in "class-like" namespaces with a central
// header or only locally in a file.
Namespace *classDef;
QString trQualification;
bool hasTrFunctions = false;
bool complained = false; // ... that tr functions are missing.
bool isClass = false; // True if this represents a class, false for namespace
};
struct ParseResults {
int fileId;
Namespace rootNamespace;
QSet<const ParseResults *> includes;
};
struct IncludeCycle {
QSet<QString> fileNames;
QSet<const ParseResults *> results;
};
struct CppParserState
{
NamespaceList namespaces;
QStack<qsizetype> namespaceDepths;
NamespaceList functionContext;
QString functionContextUnresolved;
QString pendingContext;
bool operator==(const CppParserState &other) const
{
return namespaces == other.namespaces
&& namespaceDepths == other.namespaceDepths
&& functionContext == other.functionContext
&& functionContextUnresolved == other.functionContextUnresolved
&& pendingContext == other.pendingContext;
}
};
size_t qHash(const CppParserState &s, size_t seed);
struct ResultsCacheKey
{
const QString cleanFile;
const CppParserState parserState;
ResultsCacheKey(const QString &filePath)
: cleanFile(filePath)
{
}
ResultsCacheKey(const QString &filePath, const CppParserState &state)
: cleanFile(filePath),
parserState(state)
{
}
bool operator==(const ResultsCacheKey &other) const
{
return cleanFile == other.cleanFile
&& parserState == other.parserState;
}
};
size_t qHash(const ResultsCacheKey &key, size_t seed);
typedef QHash<ResultsCacheKey, IncludeCycle *> IncludeCycleHash;
typedef QHash<QString, const Translator *> TranslatorHash;
class CppFiles {
public:
static QSet<const ParseResults *> getResults(const ResultsCacheKey &key);
static void setResults(const ResultsCacheKey &key, const ParseResults *results);
static const Translator *getTranslator(const QString &cleanFile);
static void setTranslator(const QString &cleanFile, const Translator *results);
static bool isBlacklisted(const QString &cleanFile);
static void setBlacklisted(const QString &cleanFile);
static void addIncludeCycle(const QSet<QString> &fileNames, const CppParserState &parserState);
private:
static IncludeCycleHash &includeCycles();
static TranslatorHash &translatedFiles();
static QSet<QString> &blacklistedFiles();
};
QT_END_NAMESPACE
#endif // CPP_H