| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef TOOLS_FIDL_FIDLC_INCLUDE_FIDL_JSON_GENERATOR_H_ |
| #define TOOLS_FIDL_FIDLC_INCLUDE_FIDL_JSON_GENERATOR_H_ |
| |
| #include <memory> |
| #include <sstream> |
| #include <string> |
| #include <string_view> |
| #include <vector> |
| |
| #include "flat_ast.h" |
| #include "json_writer.h" |
| |
| namespace fidl { |
| |
| struct NameSpan { |
| explicit NameSpan(const SourceSpan& span) |
| : filename(span.source_file().filename()), length(span.data().length()) { |
| span.SourceLine(&position); |
| } |
| |
| // TODO(fxbug.dev/7920): We are incorrectly assuming that the provided name is not |
| // anonymous, and relying on callers to avoid derefencing a nullptr |
| // location. |
| explicit NameSpan(const flat::Name& name) : NameSpan(name.span().value()) { |
| assert(name.span().has_value() && "NameSpan was passed an anonymous name"); |
| } |
| |
| const std::string filename; |
| SourceFile::Position position; |
| const size_t length; |
| }; |
| |
| // Methods or functions named "Emit..." are the actual interface to |
| // the JSON output. |
| |
| // Methods named "Generate..." directly generate JSON output via the |
| // "Emit" routines. |
| |
| // Methods named "Produce..." indirectly generate JSON output by calling |
| // the Generate methods, and should not call the "Emit" functions |
| // directly. |
| |
| // |JsonWriter| requires the derived type as a template parameter so it can |
| // match methods declared with parameter overrides in the derived class. |
| class JSONGenerator : public utils::JsonWriter<JSONGenerator> { |
| public: |
| // "using" is required for overridden methods, so the implementations in |
| // both the base class and in this derived class are visible when matching |
| // parameter types |
| using utils::JsonWriter<JSONGenerator>::Generate; |
| using utils::JsonWriter<JSONGenerator>::GenerateArray; |
| |
| explicit JSONGenerator(const flat::Library* library, bool omit_locations = false) |
| : JsonWriter(json_file_), library_(library), omit_locations_(omit_locations) {} |
| |
| ~JSONGenerator() = default; |
| |
| std::ostringstream Produce(); |
| |
| // Specializing for structs to avoid printing request/response structs, which are |
| // handled separately. |
| void GenerateArray(std::vector<std::unique_ptr<flat::Struct>>::const_iterator begin, |
| std::vector<std::unique_ptr<flat::Struct>>::const_iterator end) { |
| EmitArrayBegin(); |
| |
| bool is_first = true; |
| for (std::vector<std::unique_ptr<flat::Struct>>::const_iterator it = begin; it != end; ++it) { |
| if ((*it)->is_request_or_response) |
| continue; |
| if (is_first) { |
| Indent(); |
| EmitNewlineWithIndent(); |
| is_first = false; |
| } else { |
| EmitArraySeparator(); |
| } |
| Generate(**it); |
| } |
| if (!is_first) { |
| Outdent(); |
| EmitNewlineWithIndent(); |
| } |
| |
| EmitArrayEnd(); |
| } |
| |
| void Generate(const flat::Decl* decl); |
| |
| void Generate(SourceSpan value); |
| void Generate(NameSpan value); |
| |
| void Generate(types::HandleSubtype value); |
| void Generate(types::Nullability value); |
| |
| void Generate(const raw::Identifier& value); |
| void Generate(const raw::Attribute& value); |
| void Generate(const raw::AttributeList& value); |
| void Generate(const raw::Ordinal64& value); |
| |
| void Generate(const TypeShape& type_shape); |
| void Generate(const FieldShape& type_shape); |
| |
| void Generate(const flat::Name& value); |
| void Generate(const flat::Type* value); |
| void Generate(const flat::Constant& value); |
| void Generate(const flat::ConstantValue& value); |
| void Generate(const flat::Bits& value); |
| void Generate(const flat::Bits::Member& value); |
| void Generate(const flat::Const& value); |
| void Generate(const flat::Enum& value); |
| void Generate(const flat::Enum::Member& value); |
| void Generate(const flat::Protocol& value); |
| void Generate(const flat::Protocol::MethodWithInfo& value); |
| void Generate(const flat::LiteralConstant& value); |
| void Generate(const flat::Resource& value); |
| void Generate(const flat::Resource::Property& value); |
| void Generate(const flat::Service& value); |
| void Generate(const flat::Service::Member& value); |
| void Generate(const flat::Struct& value); |
| void Generate(const flat::Struct* value); |
| void Generate(const flat::Struct::Member& value, bool is_request_or_response = false); |
| void Generate(const flat::Table& value); |
| void Generate(const flat::Table::Member& value); |
| void Generate(const flat::Union& value); |
| void Generate(const flat::Union::Member& value); |
| void Generate(const flat::TypeConstructor::FromTypeAlias& value); |
| void Generate(const flat::TypeConstructor& value); |
| void Generate(const flat::TypeAlias& value); |
| void Generate(const flat::Library* library); |
| |
| private: |
| void GenerateTypeAndFromTypeAlias(const flat::TypeConstructor& value, |
| Position position = Position::kSubsequent); |
| void GenerateRequest(const std::string& prefix, const flat::Struct& value); |
| void GenerateDeclarationsEntry(int count, const flat::Name& name, std::string_view decl_kind); |
| void GenerateDeclarationsMember(const flat::Library* library, |
| Position position = Position::kSubsequent); |
| void GenerateExternalDeclarationsEntry(int count, const flat::Name& name, |
| std::string_view decl_kind, |
| std::optional<types::Resourceness> maybe_resourceness); |
| void GenerateExternalDeclarationsMember(const flat::Library* library, |
| Position position = Position::kSubsequent); |
| void GenerateTypeShapes(const flat::Object& object); |
| void GenerateTypeShapes(std::string prefix, const flat::Object& object, |
| bool is_request_or_response = false); |
| void GenerateFieldShapes(const flat::Struct::Member& struct_member, |
| bool is_request_or_response = false); |
| |
| const flat::Library* library_; |
| // TODO(fxbug.dev/70247): this is a temporary setting used during the syntax |
| // migration to allow directly comparing the IR from the old and new syntax |
| // to ensure that no semantic information has changed. |
| const bool omit_locations_; |
| std::ostringstream json_file_; |
| }; |
| |
| } // namespace fidl |
| |
| #endif // TOOLS_FIDL_FIDLC_INCLUDE_FIDL_JSON_GENERATOR_H_ |