parseMetadata method

AnalysisResult parseMetadata()

JSON decode current file and return CustomType.

The JSON is expected to contain metadata for a single data class.

Implementation

AnalysisResult parseMetadata() {
  final enumTypes = <EnumType>[];
  final customTypes = <CustomType>[];
  final json = readAsStringSync().jsonDecode;
  final className = json.stringNode("className").data;

  if (json.hasKey("members")) {
    final data = json.arrayOrNull<dynamic>("members");
    if (data != null) {
      final members = <TypeMember>[];

      for (final object in data) {
        final name = object["name"] as String;
        final type = object["type"] as String;
        final nullable = object["nullable"] as bool;

        final memberType = type.toAbstractType(nullable: nullable);
        switch (memberType) {
          case EnumType() || CustomType() || NonCanonicalType():
            final debugFile = parent.resolve(
                "$metadataMarkerPrefix${memberType.className.toLowerCase()}.json");
            if (debugFile.existsSync()) {
              final result = debugFile.parseMetadata();
              final parentOrNull = result.parent;
              if (parentOrNull is CustomType) {
                customTypes.add(parentOrNull);
              }
              if (parentOrNull is EnumType) {
                enumTypes.add(parentOrNull);
              }
              customTypes.addAll(result.childrenCustomTypes);
              enumTypes.addAll(result.childrenEnumTypes);
            } else {
              "Found ${memberType.runtimeType} but no source (Does not exist: ${debugFile.path})"
                  .log();
            }
          case StandardType():
            ;
          case UndeterminedAsDynamic():
            ;
        }

        members.add(
          TypeMember(
            name: name,
            type: memberType,
          ),
        );
      }

      return AnalysisResult(
        parent: CustomType(
          className: className,
          members: members,
        ),
        childrenCustomTypes: customTypes.toSet(),
        childrenEnumTypes: enumTypes.toSet(),
      ).normalizeParentTypeMembers();
    }
  }

  if (json.hasKey("values")) {
    final values = json.arrayOrNull<String>("values") ?? [];
    final valuesJSON = json.hasKey("valuesJSON")
        ? json.arrayOrNull<String>("valuesJSON") ?? <String>[]
        : <String>[];

    final enumType = EnumType(
      className: className,
      values: values,
      valuesJSON: valuesJSON,
    );

    enumTypes.add(enumType);
    return AnalysisResult(
      parent: null,
      childrenCustomTypes: customTypes.toSet(),
      childrenEnumTypes: enumTypes.toSet(),
    );
  }

  "Example of CustomType metadata JSON file:".log(context: """
  {
  "className": "MyResponse",
  "members": [
    {
        "name": "a1",
        "type": "int",
        "nullable": false
    },
    {
          "name": "a2",
          "type": "String",
          "nullable": true
    }
  ]
}""");

  "Example of EnumType metadata JSON file:".log(context: """
  {
      "className": "MyResponse",
      "values": [
        "FOO",
        "BAR"
      ],
      "valuesJSON": [
        "foo",
        "bar"
      ],
    }""");

  throw SquintException("Unable to parse metadata file.");
}