[llvm] [llvm][Support] Add YAMLGenerateSchema for producing YAML schemas (PR #133284)

Scott Linder via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 26 13:01:13 PST 2025


================
@@ -0,0 +1,400 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_YAMLGENERATE_SCHEMA_H
+#define LLVM_SUPPORT_YAMLGENERATE_SCHEMA_H
+
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/YAMLTraits.h"
+
+namespace llvm {
+
+namespace json {
+class Value;
+}
+
+namespace yaml {
+
+class GenerateSchema : public IO {
+public:
+  GenerateSchema(raw_ostream &RO);
+  ~GenerateSchema() override = default;
+
+  IOKind getKind() const override;
+  bool outputting() const override;
+  bool mapTag(StringRef, bool) override;
+  void beginMapping() override;
+  void endMapping() override;
+  bool preflightKey(StringRef, bool, bool, bool &, void *&) override;
+  void postflightKey(void *) override;
+  std::vector<StringRef> keys() override;
+  void beginFlowMapping() override;
+  void endFlowMapping() override;
+  unsigned beginSequence() override;
+  void endSequence() override;
+  bool preflightElement(unsigned, void *&) override;
+  void postflightElement(void *) override;
+  unsigned beginFlowSequence() override;
+  bool preflightFlowElement(unsigned, void *&) override;
+  void postflightFlowElement(void *) override;
+  void endFlowSequence() override;
+  void beginEnumScalar() override;
+  bool matchEnumScalar(StringRef, bool) override;
+  bool matchEnumFallback() override;
+  void endEnumScalar() override;
+  bool beginBitSetScalar(bool &) override;
+  bool bitSetMatch(StringRef, bool) override;
+  void endBitSetScalar() override;
+  void scalarString(StringRef &, QuotingType) override;
+  void blockScalarString(StringRef &) override;
+  void scalarTag(std::string &) override;
+  NodeKind getNodeKind() override;
+  void setError(const Twine &message) override;
+  std::error_code error() override;
+  bool canElideEmptySequence() override;
+
+  bool preflightDocument();
+  void postflightDocument();
+
+  class SchemaNode {
+  public:
+    virtual json::Value toJSON() const = 0;
+
+    virtual ~SchemaNode() = default;
+  };
+
+  enum class PropertyKind : uint8_t {
+    UserDefined,
+    Properties,
+    AdditionalProperties,
+    Required,
+    Optional,
+    Type,
+    Enum,
+    Items,
+    FlowStyle,
+  };
+
+  class SchemaProperty : public SchemaNode {
+    StringRef Name;
+    PropertyKind Kind;
+
+  public:
+    SchemaProperty(StringRef Name, PropertyKind Kind)
+        : Name(Name), Kind(Kind) {}
+
+    PropertyKind getKind() const { return Kind; }
+
+    StringRef getName() const { return Name; }
+  };
+
+  class Schema;
+
+  class UserDefinedProperty final : public SchemaProperty {
+    Schema *Value;
+
+  public:
+    UserDefinedProperty(StringRef Name, Schema *Value)
+        : SchemaProperty(Name, PropertyKind::UserDefined), Value(Value) {}
+
+    Schema *getSchema() const { return Value; }
+
+    json::Value toJSON() const override;
+
+    static bool classof(const SchemaProperty *Property) {
+      return Property->getKind() == PropertyKind::UserDefined;
+    }
+  };
+
+  class PropertiesProperty final : public SchemaProperty,
+                                   SmallVector<UserDefinedProperty *, 8> {
+  public:
+    using BaseVector = SmallVector<UserDefinedProperty *, 8>;
+
+    PropertiesProperty()
+        : SchemaProperty("properties", PropertyKind::Properties) {}
+
+    using BaseVector::begin;
+    using BaseVector::emplace_back;
+    using BaseVector::end;
+    using BaseVector::size;
+
+    json::Value toJSON() const override;
+
+    static bool classof(const SchemaProperty *Property) {
+      return Property->getKind() == PropertyKind::Properties;
+    }
+  };
+
+  class AdditionalPropertiesProperty final : public SchemaProperty {
+    Schema *Value;
+
+  public:
+    AdditionalPropertiesProperty(Schema *Value = nullptr)
+        : SchemaProperty("additionalProperties",
+                         PropertyKind::AdditionalProperties),
+          Value(Value) {}
+
+    Schema *getSchema() const { return Value; }
+
+    void setSchema(Schema *S) { Value = S; }
+
+    json::Value toJSON() const override;
+
+    static bool classof(const SchemaProperty *Property) {
+      return Property->getKind() == PropertyKind::AdditionalProperties;
+    }
+  };
+
+  class RequiredProperty final : public SchemaProperty,
+                                 SmallVector<StringRef, 4> {
+  public:
+    using BaseVector = SmallVector<StringRef, 4>;
+
+    RequiredProperty() : SchemaProperty("required", PropertyKind::Required) {}
+
+    using BaseVector::begin;
+    using BaseVector::emplace_back;
+    using BaseVector::end;
+    using BaseVector::size;
+
+    json::Value toJSON() const override;
+
+    static bool classof(const SchemaProperty *Property) {
+      return Property->getKind() == PropertyKind::Required;
+    }
+  };
+
+  class OptionalProperty final : public SchemaProperty,
+                                 SmallVector<StringRef, 4> {
+  public:
+    using BaseVector = SmallVector<StringRef, 4>;
+
+    OptionalProperty() : SchemaProperty("optional", PropertyKind::Optional) {}
+
+    using BaseVector::begin;
+    using BaseVector::emplace_back;
+    using BaseVector::end;
+    using BaseVector::size;
+
+    json::Value toJSON() const override;
+
+    static bool classof(const SchemaProperty *Property) {
+      return Property->getKind() == PropertyKind::Optional;
+    }
+  };
+
+  class TypeProperty final : public SchemaProperty {
+    StringRef Value;
+
+  public:
+    TypeProperty(StringRef Value)
+        : SchemaProperty("type", PropertyKind::Type), Value(Value) {}
+
+    json::Value toJSON() const override;
+
+    static bool classof(const SchemaProperty *Property) {
+      return Property->getKind() == PropertyKind::Type;
+    }
+  };
+
+  class EnumProperty final : public SchemaProperty, SmallVector<StringRef, 4> {
+  public:
+    using BaseVector = SmallVector<StringRef, 4>;
+
+    EnumProperty() : SchemaProperty("enum", PropertyKind::Enum) {}
+
+    using BaseVector::begin;
+    using BaseVector::emplace_back;
+    using BaseVector::end;
+    using BaseVector::size;
+
+    json::Value toJSON() const override;
+
+    static bool classof(const SchemaProperty *Property) {
+      return Property->getKind() == PropertyKind::Enum;
+    }
+  };
+
+  class ItemsProperty final : public SchemaProperty {
+    Schema *Value;
+
+  public:
+    ItemsProperty(Schema *Value = nullptr)
+        : SchemaProperty("items", PropertyKind::Items), Value(Value) {}
+
+    Schema *getSchema() const { return Value; }
+
+    void setSchema(Schema *S) { Value = S; }
+
+    json::Value toJSON() const override;
+
+    static bool classof(const SchemaProperty *Property) {
+      return Property->getKind() == PropertyKind::Items;
+    }
+  };
+
+  enum class FlowStyle : bool {
+    Block,
+    Flow,
+  };
+
+  class FlowStyleProperty final : public SchemaProperty {
+    FlowStyle Style;
+
+  public:
+    FlowStyleProperty(FlowStyle Style = FlowStyle::Block)
+        : SchemaProperty("flowStyle", PropertyKind::FlowStyle), Style(Style) {}
+
+    void setStyle(FlowStyle S) { Style = S; }
+
+    FlowStyle getStyle() const { return Style; }
+
+    json::Value toJSON() const override;
+
+    static bool classof(const SchemaProperty *Property) {
+      return Property->getKind() == PropertyKind::FlowStyle;
+    }
+  };
+
+  class Schema final : public SchemaNode, SmallVector<SchemaProperty *, 8> {
+  public:
+    using BaseVector = SmallVector<SchemaProperty *, 8>;
+
+    Schema() = default;
+
+    using BaseVector::begin;
+    using BaseVector::emplace_back;
+    using BaseVector::end;
+    using BaseVector::size;
+
+    json::Value toJSON() const override;
+  };
+
+private:
+  std::vector<std::unique_ptr<SchemaNode>> SchemaNodes;
----------------
slinder1 wrote:

Is there a particular reason to represent these as a vector of smart pointers?

The other `IO` classes allocate nodes using `BumpPtrAllocator`s, which makes sense as the lifetime of the nodes is naturally constrained to the containing `IO` class.

https://github.com/llvm/llvm-project/pull/133284


More information about the llvm-commits mailing list