2012-10-02 09:12:39 +02:00
|
|
|
/****************************************************************************
|
2012-02-07 15:30:33 +01:00
|
|
|
**
|
2016-01-15 14:58:39 +01:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2012-02-07 15:30:33 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2012-02-07 15:30:33 +01: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
|
2016-01-15 14:58:39 +01:00
|
|
|
** 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.
|
2012-02-07 15:30:33 +01:00
|
|
|
**
|
2016-01-15 14:58:39 +01:00
|
|
|
** 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.
|
2012-02-07 15:30:33 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2012-02-07 15:30:33 +01:00
|
|
|
|
2016-03-18 07:55:01 +01:00
|
|
|
#pragma once
|
2012-02-07 15:30:33 +01:00
|
|
|
|
|
|
|
|
#include "utils_global.h"
|
|
|
|
|
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QHash>
|
|
|
|
|
#include <QVector>
|
|
|
|
|
#include <QStringList>
|
|
|
|
|
#include <QDateTime>
|
2012-04-23 17:39:02 +02:00
|
|
|
|
|
|
|
|
QT_FORWARD_DECLARE_CLASS(QVariant)
|
2012-02-07 15:30:33 +01:00
|
|
|
|
|
|
|
|
namespace Utils {
|
|
|
|
|
|
|
|
|
|
class JsonStringValue;
|
|
|
|
|
class JsonDoubleValue;
|
|
|
|
|
class JsonIntValue;
|
|
|
|
|
class JsonObjectValue;
|
|
|
|
|
class JsonArrayValue;
|
|
|
|
|
class JsonBooleanValue;
|
|
|
|
|
class JsonNullValue;
|
|
|
|
|
|
2013-07-10 11:50:46 +02:00
|
|
|
class QTCREATOR_UTILS_EXPORT JsonMemoryPool
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
~JsonMemoryPool();
|
|
|
|
|
|
|
|
|
|
inline void *allocate(size_t size)
|
|
|
|
|
{
|
2018-07-23 10:45:40 +02:00
|
|
|
auto obj = new char[size];
|
2013-07-10 11:50:46 +02:00
|
|
|
_objs.append(obj);
|
|
|
|
|
return obj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
QVector<char *> _objs;
|
|
|
|
|
};
|
|
|
|
|
|
2012-02-07 15:30:33 +01:00
|
|
|
/*!
|
|
|
|
|
* \brief The JsonValue class
|
|
|
|
|
*/
|
|
|
|
|
class QTCREATOR_UTILS_EXPORT JsonValue
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
enum Kind {
|
|
|
|
|
String,
|
|
|
|
|
Double,
|
|
|
|
|
Int,
|
|
|
|
|
Object,
|
|
|
|
|
Array,
|
|
|
|
|
Boolean,
|
|
|
|
|
Null,
|
|
|
|
|
Unknown
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
virtual ~JsonValue();
|
|
|
|
|
|
|
|
|
|
Kind kind() const { return m_kind; }
|
|
|
|
|
static QString kindToString(Kind kind);
|
|
|
|
|
|
2018-05-07 17:33:02 +02:00
|
|
|
virtual JsonStringValue *toString() { return nullptr; }
|
|
|
|
|
virtual JsonDoubleValue *toDouble() { return nullptr; }
|
|
|
|
|
virtual JsonIntValue *toInt() { return nullptr; }
|
|
|
|
|
virtual JsonObjectValue *toObject() { return nullptr; }
|
|
|
|
|
virtual JsonArrayValue *toArray() { return nullptr; }
|
|
|
|
|
virtual JsonBooleanValue *toBoolean() { return nullptr; }
|
|
|
|
|
virtual JsonNullValue *toNull() { return nullptr; }
|
2012-02-07 15:30:33 +01:00
|
|
|
|
2013-07-10 11:50:46 +02:00
|
|
|
static JsonValue *create(const QString &s, JsonMemoryPool *pool);
|
|
|
|
|
void *operator new(size_t size, JsonMemoryPool *pool);
|
|
|
|
|
void operator delete(void *);
|
|
|
|
|
void operator delete(void *, JsonMemoryPool *);
|
2012-02-07 15:30:33 +01:00
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
JsonValue(Kind kind);
|
|
|
|
|
|
|
|
|
|
private:
|
2013-07-10 11:50:46 +02:00
|
|
|
static JsonValue *build(const QVariant &varixant, JsonMemoryPool *pool);
|
2012-02-07 15:30:33 +01:00
|
|
|
|
|
|
|
|
Kind m_kind;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \brief The JsonStringValue class
|
|
|
|
|
*/
|
|
|
|
|
class QTCREATOR_UTILS_EXPORT JsonStringValue : public JsonValue
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
JsonStringValue(const QString &value)
|
|
|
|
|
: JsonValue(String)
|
|
|
|
|
, m_value(value)
|
|
|
|
|
{}
|
|
|
|
|
|
2018-05-07 15:07:21 +02:00
|
|
|
JsonStringValue *toString() override { return this; }
|
2012-02-07 15:30:33 +01:00
|
|
|
|
|
|
|
|
const QString &value() const { return m_value; }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
QString m_value;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \brief The JsonDoubleValue class
|
|
|
|
|
*/
|
|
|
|
|
class QTCREATOR_UTILS_EXPORT JsonDoubleValue : public JsonValue
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
JsonDoubleValue(double value)
|
|
|
|
|
: JsonValue(Double)
|
|
|
|
|
, m_value(value)
|
|
|
|
|
{}
|
|
|
|
|
|
2018-05-07 15:07:21 +02:00
|
|
|
JsonDoubleValue *toDouble() override { return this; }
|
2012-02-07 15:30:33 +01:00
|
|
|
|
|
|
|
|
double value() const { return m_value; }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
double m_value;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \brief The JsonIntValue class
|
|
|
|
|
*/
|
|
|
|
|
class QTCREATOR_UTILS_EXPORT JsonIntValue : public JsonValue
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
JsonIntValue(int value)
|
|
|
|
|
: JsonValue(Int)
|
|
|
|
|
, m_value(value)
|
|
|
|
|
{}
|
|
|
|
|
|
2018-05-07 15:07:21 +02:00
|
|
|
JsonIntValue *toInt() override { return this; }
|
2012-02-07 15:30:33 +01:00
|
|
|
|
|
|
|
|
int value() const { return m_value; }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
int m_value;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \brief The JsonObjectValue class
|
|
|
|
|
*/
|
|
|
|
|
class QTCREATOR_UTILS_EXPORT JsonObjectValue : public JsonValue
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
JsonObjectValue()
|
|
|
|
|
: JsonValue(Object)
|
|
|
|
|
{}
|
|
|
|
|
|
2018-05-07 15:07:21 +02:00
|
|
|
JsonObjectValue *toObject() override { return this; }
|
2012-02-07 15:30:33 +01:00
|
|
|
|
|
|
|
|
void addMember(const QString &name, JsonValue *value) { m_members.insert(name, value); }
|
|
|
|
|
bool hasMember(const QString &name) const { return m_members.contains(name); }
|
|
|
|
|
JsonValue *member(const QString &name) const { return m_members.value(name); }
|
|
|
|
|
QHash<QString, JsonValue *> members() const { return m_members; }
|
|
|
|
|
bool isEmpty() const { return m_members.isEmpty(); }
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
JsonObjectValue(Kind kind)
|
|
|
|
|
: JsonValue(kind)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
QHash<QString, JsonValue *> m_members;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \brief The JsonArrayValue class
|
|
|
|
|
*/
|
|
|
|
|
class QTCREATOR_UTILS_EXPORT JsonArrayValue : public JsonValue
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
JsonArrayValue()
|
|
|
|
|
: JsonValue(Array)
|
|
|
|
|
{}
|
|
|
|
|
|
2018-05-07 15:07:21 +02:00
|
|
|
JsonArrayValue *toArray() override { return this; }
|
2012-02-07 15:30:33 +01:00
|
|
|
|
|
|
|
|
void addElement(JsonValue *value) { m_elements.append(value); }
|
|
|
|
|
QList<JsonValue *> elements() const { return m_elements; }
|
|
|
|
|
int size() const { return m_elements.size(); }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
QList<JsonValue *> m_elements;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \brief The JsonBooleanValue class
|
|
|
|
|
*/
|
|
|
|
|
class QTCREATOR_UTILS_EXPORT JsonBooleanValue : public JsonValue
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
JsonBooleanValue(bool value)
|
|
|
|
|
: JsonValue(Boolean)
|
|
|
|
|
, m_value(value)
|
|
|
|
|
{}
|
|
|
|
|
|
2018-05-07 15:07:21 +02:00
|
|
|
JsonBooleanValue *toBoolean() override { return this; }
|
2012-02-07 15:30:33 +01:00
|
|
|
|
|
|
|
|
bool value() const { return m_value; }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
bool m_value;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class QTCREATOR_UTILS_EXPORT JsonNullValue : public JsonValue
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
JsonNullValue()
|
|
|
|
|
: JsonValue(Null)
|
|
|
|
|
{}
|
|
|
|
|
|
2018-05-07 15:07:21 +02:00
|
|
|
JsonNullValue *toNull() override { return this; }
|
2012-02-07 15:30:33 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class JsonSchemaManager;
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \brief The JsonSchema class
|
|
|
|
|
*
|
|
|
|
|
* [NOTE: This is an incomplete implementation and a work in progress.]
|
|
|
|
|
*
|
|
|
|
|
* This class provides an interface for traversing and evaluating a JSON schema, as described
|
|
|
|
|
* in the draft http://tools.ietf.org/html/draft-zyp-json-schema-03.
|
|
|
|
|
*
|
|
|
|
|
* JSON schemas are recursive in concept. This means that a particular attribute from a schema
|
|
|
|
|
* might be also another schema. Therefore, the basic working principle of this API is that
|
|
|
|
|
* from within some schema, one can investigate its attributes and if necessary "enter" a
|
|
|
|
|
* corresponding nested schema. Afterwards, it's expected that one would "leave" such nested
|
|
|
|
|
* schema.
|
|
|
|
|
*
|
2013-10-07 13:34:40 +02:00
|
|
|
* All functions assume that the current "context" is a valid schema. Once an instance of this
|
2012-02-07 15:30:33 +01:00
|
|
|
* class is created the root schema is put on top of the stack.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
class QTCREATOR_UTILS_EXPORT JsonSchema
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
bool isTypeConstrained() const;
|
|
|
|
|
bool acceptsType(const QString &type) const;
|
|
|
|
|
QStringList validTypes() const;
|
|
|
|
|
|
|
|
|
|
// Applicable on schemas of any type.
|
|
|
|
|
bool required() const;
|
|
|
|
|
|
|
|
|
|
bool hasTypeSchema() const;
|
|
|
|
|
void enterNestedTypeSchema();
|
|
|
|
|
|
|
|
|
|
bool hasUnionSchema() const;
|
|
|
|
|
int unionSchemaSize() const;
|
|
|
|
|
bool maybeEnterNestedUnionSchema(int index);
|
|
|
|
|
|
|
|
|
|
void leaveNestedSchema();
|
|
|
|
|
|
|
|
|
|
// Applicable on schemas of type number/integer.
|
|
|
|
|
bool hasMinimum() const;
|
|
|
|
|
bool hasMaximum() const;
|
|
|
|
|
bool hasExclusiveMinimum();
|
|
|
|
|
bool hasExclusiveMaximum();
|
|
|
|
|
double minimum() const;
|
|
|
|
|
double maximum() const;
|
|
|
|
|
|
|
|
|
|
// Applicable on schemas of type string.
|
|
|
|
|
QString pattern() const;
|
|
|
|
|
int minimumLength() const;
|
|
|
|
|
int maximumLength() const;
|
|
|
|
|
|
|
|
|
|
// Applicable on schemas of type object.
|
|
|
|
|
QStringList properties() const;
|
|
|
|
|
bool hasPropertySchema(const QString &property) const;
|
|
|
|
|
void enterNestedPropertySchema(const QString &property);
|
|
|
|
|
|
|
|
|
|
// Applicable on schemas of type array.
|
|
|
|
|
bool hasAdditionalItems() const;
|
|
|
|
|
|
|
|
|
|
bool hasItemSchema() const;
|
|
|
|
|
void enterNestedItemSchema();
|
|
|
|
|
|
|
|
|
|
bool hasItemArraySchema() const;
|
|
|
|
|
int itemArraySchemaSize() const;
|
|
|
|
|
bool maybeEnterNestedArraySchema(int index);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
friend class JsonSchemaManager;
|
|
|
|
|
JsonSchema(JsonObjectValue *rootObject, const JsonSchemaManager *manager);
|
|
|
|
|
Q_DISABLE_COPY(JsonSchema)
|
|
|
|
|
|
|
|
|
|
enum EvaluationMode {
|
|
|
|
|
Normal,
|
|
|
|
|
Array,
|
|
|
|
|
Union
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void enter(JsonObjectValue *ov, EvaluationMode eval = Normal, int index = -1);
|
|
|
|
|
bool maybeEnter(JsonValue *v, EvaluationMode eval, int index);
|
|
|
|
|
void evaluate(EvaluationMode eval, int index);
|
|
|
|
|
void leave();
|
|
|
|
|
|
|
|
|
|
JsonObjectValue *resolveReference(JsonObjectValue *ov) const;
|
|
|
|
|
JsonObjectValue *resolveBase(JsonObjectValue *ov) const;
|
|
|
|
|
|
|
|
|
|
JsonObjectValue *currentValue() const;
|
|
|
|
|
int currentIndex() const;
|
|
|
|
|
|
|
|
|
|
JsonObjectValue *rootValue() const;
|
|
|
|
|
|
|
|
|
|
static JsonStringValue *getStringValue(const QString &name, JsonObjectValue *value);
|
|
|
|
|
static JsonObjectValue *getObjectValue(const QString &name, JsonObjectValue *value);
|
|
|
|
|
static JsonBooleanValue *getBooleanValue(const QString &name, JsonObjectValue *value);
|
|
|
|
|
static JsonArrayValue *getArrayValue(const QString &name, JsonObjectValue *value);
|
|
|
|
|
static JsonDoubleValue *getDoubleValue(const QString &name, JsonObjectValue *value);
|
|
|
|
|
|
|
|
|
|
static QStringList validTypes(JsonObjectValue *v);
|
|
|
|
|
static bool typeMatches(const QString &expected, const QString &actual);
|
|
|
|
|
static bool isCheckableType(const QString &s);
|
|
|
|
|
|
|
|
|
|
QStringList properties(JsonObjectValue *v) const;
|
|
|
|
|
JsonObjectValue *propertySchema(const QString &property, JsonObjectValue *v) const;
|
2013-10-07 13:34:40 +02:00
|
|
|
// TODO: Similar functions for other attributes which require looking into base schemas.
|
2012-02-07 15:30:33 +01:00
|
|
|
|
|
|
|
|
static bool maybeSchemaName(const QString &s);
|
|
|
|
|
|
2015-10-09 13:33:27 +02:00
|
|
|
static QString kType();
|
|
|
|
|
static QString kProperties();
|
|
|
|
|
static QString kPatternProperties();
|
|
|
|
|
static QString kAdditionalProperties();
|
|
|
|
|
static QString kItems();
|
|
|
|
|
static QString kAdditionalItems();
|
|
|
|
|
static QString kRequired();
|
|
|
|
|
static QString kDependencies();
|
|
|
|
|
static QString kMinimum();
|
|
|
|
|
static QString kMaximum();
|
|
|
|
|
static QString kExclusiveMinimum();
|
|
|
|
|
static QString kExclusiveMaximum();
|
|
|
|
|
static QString kMinItems();
|
|
|
|
|
static QString kMaxItems();
|
|
|
|
|
static QString kUniqueItems();
|
|
|
|
|
static QString kPattern();
|
|
|
|
|
static QString kMinLength();
|
|
|
|
|
static QString kMaxLength();
|
|
|
|
|
static QString kTitle();
|
|
|
|
|
static QString kDescription();
|
|
|
|
|
static QString kExtends();
|
|
|
|
|
static QString kRef();
|
2012-02-07 15:30:33 +01:00
|
|
|
|
|
|
|
|
struct Context
|
|
|
|
|
{
|
|
|
|
|
JsonObjectValue *m_value;
|
|
|
|
|
EvaluationMode m_eval;
|
|
|
|
|
int m_index;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
QVector<Context> m_schemas;
|
|
|
|
|
const JsonSchemaManager *m_manager;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \brief The JsonSchemaManager class
|
|
|
|
|
*/
|
|
|
|
|
class QTCREATOR_UTILS_EXPORT JsonSchemaManager
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
JsonSchemaManager(const QStringList &searchPaths);
|
|
|
|
|
~JsonSchemaManager();
|
|
|
|
|
|
2014-07-15 23:33:17 +03:00
|
|
|
JsonSchema *schemaForFile(const QString &fileName) const;
|
|
|
|
|
JsonSchema *schemaByName(const QString &baseName) const;
|
2012-02-07 15:30:33 +01:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
struct JsonSchemaData
|
|
|
|
|
{
|
2018-05-07 17:33:02 +02:00
|
|
|
JsonSchemaData(const QString &absoluteFileName, JsonSchema *schema = nullptr)
|
2012-02-07 15:30:33 +01:00
|
|
|
: m_absoluteFileName(absoluteFileName)
|
|
|
|
|
, m_schema(schema)
|
|
|
|
|
{}
|
|
|
|
|
QString m_absoluteFileName;
|
2014-07-15 23:33:17 +03:00
|
|
|
JsonSchema *m_schema;
|
2012-02-07 15:30:33 +01:00
|
|
|
QDateTime m_lastParseAttempt;
|
|
|
|
|
};
|
|
|
|
|
|
2014-07-15 23:33:17 +03:00
|
|
|
JsonSchema *parseSchema(const QString &schemaFileName) const;
|
2012-02-07 15:30:33 +01:00
|
|
|
|
|
|
|
|
QStringList m_searchPaths;
|
|
|
|
|
mutable QHash<QString, JsonSchemaData> m_schemas;
|
2013-07-10 11:50:46 +02:00
|
|
|
mutable JsonMemoryPool m_pool;
|
2012-02-07 15:30:33 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
} // namespace Utils
|