Squashed 'third_party/flatbuffers/' changes from d6a8dbd26..338393f85

338393f85 Documentation updates for Optional Scalars (#6014) (#6270)
c27bc2d76 [C++] Add ParseJson(), Parser(Parser&&), update fuzzers (#6284)
bc518a512 Fixed FlexBufferBuilder asserting on duplicate keys
100c59054 Added a few more paths for auto labeler (#6281)
e58c18244 Add --require-explicit-ids to require explicit ids (#6277)
69a8b2a57 idl_gen_json_schema.cpp: Changed generation of array element types (#6253)
25eba6f35 fix typo (#6280)
e1f0f75ba Updated Ms build Action to fix build issue (#6279)
faeb04fbe Add type annotation to unspecified array (#6264)
537212afe [Swift] Adds a format file and reformats the swift project (#6250)
6764f25d9 Adds a fix for enum generation (#6263)

Change-Id: I716bd4d2521fb0a673e50a699cef761e042052b2
git-subtree-dir: third_party/flatbuffers
git-subtree-split: 338393f854eb5ba24761a22cd9316ff5cee4eab0
diff --git a/src/flatc.cpp b/src/flatc.cpp
index 4a9df5f..1233ff9 100644
--- a/src/flatc.cpp
+++ b/src/flatc.cpp
@@ -163,6 +163,7 @@
     "  --reflect-types        Add minimal type reflection to code generation.\n"
     "  --reflect-names        Add minimal type/name reflection.\n"
     "  --root-type T          Select or override the default root_type\n"
+    "  --require-explicit-ids When parsing schemas, require explicit ids (id: x).\n"
     "  --force-defaults       Emit default values in binary output from JSON\n"
     "  --force-empty          When serializing from object API representation,\n"
     "                         force strings and vectors to empty rather than null.\n"
@@ -345,6 +346,8 @@
         opts.mini_reflect = IDLOptions::kTypes;
       } else if (arg == "--reflect-names") {
         opts.mini_reflect = IDLOptions::kTypesAndNames;
+      } else if (arg == "--require-explicit-ids") {
+        opts.require_explicit_ids = true;
       } else if (arg == "--root-type") {
         if (++argi >= argc) Error("missing type following: " + arg, true);
         opts.root_type = argv[argi];
diff --git a/src/idl_gen_json_schema.cpp b/src/idl_gen_json_schema.cpp
index a321b89..76540d1 100644
--- a/src/idl_gen_json_schema.cpp
+++ b/src/idl_gen_json_schema.cpp
@@ -87,17 +87,27 @@
 std::string GenBaseType(const Type &type) {
   if (type.struct_def != nullptr) { return GenTypeRef(type.struct_def); }
   if (type.enum_def != nullptr) { return GenTypeRef(type.enum_def); }
-  if (IsArray(type) || IsVector(type)) {
-    return "\"type\" : \"array\", \"items\" : {" + GenType(type.element) + "}";
+  return GenType(type.base_type);
+}
+
+std::string GenArrayType(const Type &type) {
+  std::string element_type;
+  if (type.struct_def != nullptr) {
+    element_type = GenTypeRef(type.struct_def);
+  } else if (type.enum_def != nullptr) {
+    element_type = GenTypeRef(type.enum_def);
+  } else {
+    element_type = GenType(type.element);
   }
-  return  GenType(type.base_type);
+
+  return "\"type\" : \"array\", \"items\" : {" + element_type + "}";
 }
 
 std::string GenType(const Type &type) {
   switch (type.base_type) {
     case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH();  // fall thru
     case BASE_TYPE_VECTOR: {
-      return GenBaseType(type);
+      return GenArrayType(type);
     }
     case BASE_TYPE_STRUCT: {
       return GenTypeRef(type.struct_def);
@@ -147,13 +157,13 @@
 
   // If indentation is less than 0, that indicates we don't want any newlines
   // either.
-  const std::string NewLine() {
+  std::string NewLine() const {
     return parser_.opts.indent_step >= 0 ? "\n" : "";
   }
 
-  const std::string Indent(int indent) {
-    std::string indentation = "";
-    return indentation.append(indent * std::max(parser_.opts.indent_step, 0), ' ');
+  std::string Indent(int indent) const {
+    const auto num_spaces = indent * std::max(parser_.opts.indent_step, 0);
+    return std::string(num_spaces, ' ');
   }
 
   bool generate() {
@@ -168,7 +178,7 @@
          ++e) {
       code_ += Indent(2) + "\"" + GenFullName(*e) + "\" : {" + NewLine();
       code_ += Indent(3) + GenType("string") + "," + NewLine();
-      std::string enumdef(Indent(3) + "\"enum\": [");
+      auto enumdef(Indent(3) + "\"enum\": [");
       for (auto enum_value = (*e)->Vals().begin();
            enum_value != (*e)->Vals().end(); ++enum_value) {
         enumdef.append("\"" + (*enum_value)->name + "\"");
@@ -189,7 +199,7 @@
            comment_line != comment_lines.cend(); ++comment_line) {
         comment.append(*comment_line);
       }
-      if (comment.size() > 0) {
+      if (!comment.empty()) {
         std::string description;
         if (!EscapeString(comment.c_str(), comment.length(), &description, true,
                           true)) {
@@ -206,13 +216,14 @@
         std::string arrayInfo = "";
         if (IsArray(property->value.type)) {
           arrayInfo = "," + NewLine() + Indent(8) + "\"minItems\": " +
-                      NumToString(property->value.type.fixed_length) +
-                      "," + NewLine() + Indent(8) + "\"maxItems\": " +
+                      NumToString(property->value.type.fixed_length) + "," +
+                      NewLine() + Indent(8) + "\"maxItems\": " +
                       NumToString(property->value.type.fixed_length);
         }
         std::string deprecated_info = "";
         if (property->deprecated) {
-          deprecated_info = "," + NewLine() + Indent(8) + "\"deprecated\" : true,";
+          deprecated_info =
+              "," + NewLine() + Indent(8) + "\"deprecated\" : true,";
         }
         std::string typeLine = Indent(4) + "\"" + property->name + "\"";
         typeLine += " : {" + NewLine() + Indent(8);
@@ -229,8 +240,8 @@
       std::copy_if(properties.begin(), properties.end(),
                    back_inserter(requiredProperties),
                    [](FieldDef const *prop) { return prop->required; });
-      if (requiredProperties.size() > 0) {
-        std::string required_string(Indent(3) + "\"required\" : [");
+      if (!requiredProperties.empty()) {
+        auto required_string(Indent(3) + "\"required\" : [");
         for (auto req_prop = requiredProperties.cbegin();
              req_prop != requiredProperties.cend(); ++req_prop) {
           required_string.append("\"" + (*req_prop)->name + "\"");
@@ -242,7 +253,7 @@
         code_ += required_string + NewLine();
       }
       code_ += Indent(3) + "\"additionalProperties\" : false" + NewLine();
-      std::string closeType(Indent(2) + "}");
+      auto closeType(Indent(2) + "}");
       if (*s != parser_.structs_.vec.back()) { closeType.append(","); }
       code_ += closeType + NewLine();  // close type
     }
@@ -256,15 +267,13 @@
     return true;
   }
 
-  bool save() {
-    const std::string file_path =
+  bool save() const {
+    const auto file_path =
         GeneratedFileName(path_, file_name_, parser_.opts);
     return SaveFile(file_path.c_str(), code_, false);
   }
 
-  const std::string getJson() {
-    return code_;
-  }
+  const std::string getJson() { return code_; }
 };
 }  // namespace jsons
 
diff --git a/src/idl_gen_swift.cpp b/src/idl_gen_swift.cpp
index c377e9f..084bafe 100644
--- a/src/idl_gen_swift.cpp
+++ b/src/idl_gen_swift.cpp
@@ -47,7 +47,7 @@
                  const std::string &file_name)
       : BaseGenerator(parser, path, file_name, "", "_", "swift") {
     namespace_depth = 0;
-    code_.SetPadding("    ");
+    code_.SetPadding("  ");
     static const char *const keywords[] = {
       "associatedtype",
       "class",
@@ -137,7 +137,8 @@
     code_.SetValue("ACCESS", "_accessor");
     code_.SetValue("TABLEOFFSET", "VTOFFSET");
     code_ += "// " + std::string(FlatBuffersGeneratedWarning());
-    code_ += "// swiftlint:disable all\n";
+    code_ += "// swiftlint:disable all";
+    code_ += "// swiftformat:disable all\n";
     code_ += "import FlatBuffers\n";
     // Generate code for all the enum declarations.
 
@@ -1384,7 +1385,6 @@
       const auto &ev = **enum_def.Vals().begin();
       name = Name(ev);
     }
-    std::transform(name.begin(), name.end(), name.begin(), CharToLower);
     return "." + name;
   }
 
diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp
index a87fbce..6d916e5 100644
--- a/src/idl_parser.cpp
+++ b/src/idl_parser.cpp
@@ -2379,11 +2379,18 @@
       if ((*it)->attributes.Lookup("id")) num_id_fields++;
     }
     // If any fields have ids..
-    if (num_id_fields) {
+    if (num_id_fields || opts.require_explicit_ids) {
       // Then all fields must have them.
-      if (num_id_fields != fields.size())
-        return Error(
-            "either all fields or no fields must have an 'id' attribute");
+      if (num_id_fields != fields.size()) {
+        if (opts.require_explicit_ids) {
+          return Error(
+              "all fields must have an 'id' attribute when "
+              "--require-explicit-ids is used");
+        } else {
+          return Error(
+              "either all fields or no fields must have an 'id' attribute");
+        }
+      }
       // Simply sort by id, then the fields are the same as if no ids had
       // been specified.
       std::sort(fields.begin(), fields.end(), compareFieldDefs);
@@ -2850,6 +2857,8 @@
                                });
       ECHECK(err);
       builder->EndMap(start);
+      if (builder->HasDuplicateKeys())
+        return Error("FlexBuffers map has duplicate keys");
       break;
     }
     case '[': {
@@ -2914,6 +2923,15 @@
   return r;
 }
 
+bool Parser::ParseJson(const char *json, const char *json_filename) {
+  FLATBUFFERS_ASSERT(0 == recurse_protection_counter);
+  builder_.Clear();
+  const auto done =
+      !StartParseFile(json, json_filename).Check() && !DoParseJson().Check();
+  FLATBUFFERS_ASSERT(0 == recurse_protection_counter);
+  return done;
+}
+
 CheckedError Parser::StartParseFile(const char *source,
                                     const char *source_filename) {
   file_being_parsed_ = source_filename ? source_filename : "";
@@ -3094,25 +3112,7 @@
     } else if (IsIdent("namespace")) {
       ECHECK(ParseNamespace());
     } else if (token_ == '{') {
-      if (!root_struct_def_)
-        return Error("no root type set to parse json with");
-      if (builder_.GetSize()) {
-        return Error("cannot have more than one json object in a file");
-      }
-      uoffset_t toff;
-      ECHECK(ParseTable(*root_struct_def_, nullptr, &toff));
-      if (opts.size_prefixed) {
-        builder_.FinishSizePrefixed(
-            Offset<Table>(toff),
-            file_identifier_.length() ? file_identifier_.c_str() : nullptr);
-      } else {
-        builder_.Finish(Offset<Table>(toff), file_identifier_.length()
-                                                 ? file_identifier_.c_str()
-                                                 : nullptr);
-      }
-      // Check that JSON file doesn't contain more objects or IDL directives.
-      // Comments after JSON are allowed.
-      EXPECT(kTokenEof);
+      ECHECK(DoParseJson());
     } else if (IsIdent("enum")) {
       ECHECK(ParseEnum(false, nullptr));
     } else if (IsIdent("union")) {
@@ -3163,6 +3163,34 @@
   return NoError();
 }
 
+CheckedError Parser::DoParseJson()
+{
+  if (token_ != '{') {
+    EXPECT('{');
+  } else {
+    if (!root_struct_def_)
+      return Error("no root type set to parse json with");
+    if (builder_.GetSize()) {
+      return Error("cannot have more than one json object in a file");
+    }
+    uoffset_t toff;
+    ECHECK(ParseTable(*root_struct_def_, nullptr, &toff));
+    if (opts.size_prefixed) {
+      builder_.FinishSizePrefixed(
+          Offset<Table>(toff),
+          file_identifier_.length() ? file_identifier_.c_str() : nullptr);
+    } else {
+      builder_.Finish(Offset<Table>(toff), file_identifier_.length()
+                                                ? file_identifier_.c_str()
+                                                : nullptr);
+    }
+  }
+  // Check that JSON file doesn't contain more objects or IDL directives.
+  // Comments after JSON are allowed.
+  EXPECT(kTokenEof);
+  return NoError();
+}
+
 std::set<std::string> Parser::GetIncludedFilesRecursive(
     const std::string &file_name) const {
   std::set<std::string> included_files;