DevToolsExtensionConfig.parse constructor

DevToolsExtensionConfig.parse(
  1. Map<String, Object?> json
)

Implementation

factory DevToolsExtensionConfig.parse(Map<String, Object?> json) {
  // Defaults to the code point for [Icons.extensions_outlined] if null.
  late int codePoint;
  final codePointFromJson = json[materialIconCodePointKey];
  const defaultCodePoint = 0xf03f;
  if (codePointFromJson is String?) {
    codePoint =
        int.tryParse(codePointFromJson ?? '0xf03f') ?? defaultCodePoint;
  } else {
    codePoint = codePointFromJson as int? ?? defaultCodePoint;
  }

  if (json
      case {
        nameKey: final String name,
        pathKey: final String path,
        issueTrackerKey: final String issueTracker,
        versionKey: final String version,
        isPubliclyHostedKey: final String isPubliclyHosted,
      }) {
    final underscoresAndLetters = RegExp(r'^[a-z0-9_]*$');
    if (!underscoresAndLetters.hasMatch(name)) {
      throw StateError(
        'The "name" field in the extension config.yaml should only contain '
        'lowercase letters, numbers, and underscores but instead was '
        '"$name". This should be a valid Dart package name that matches the '
        'package name this extension belongs to.',
      );
    }
    return DevToolsExtensionConfig._(
      name: name,
      path: path,
      issueTrackerLink: issueTracker,
      version: version,
      materialIconCodePoint: codePoint,
      isPubliclyHosted: bool.parse(isPubliclyHosted),
    );
  } else {
    if (!json.keys.contains(isPubliclyHostedKey)) {
      throw StateError(
        'Missing key "$isPubliclyHostedKey" when trying to parse '
        'DevToolsExtensionConfig object.',
      );
    }

    const requiredKeysFromConfigFile = {
      nameKey,
      pathKey,
      issueTrackerKey,
      versionKey,
    };
    // We do not expect the config.yaml file to contain
    // [isPubliclyHostedKey], as this should be inferred.
    final jsonKeysFromConfigFile = Set.of(json.keys.toSet())
      ..remove(isPubliclyHostedKey);

    final diff = requiredKeysFromConfigFile.difference(
      jsonKeysFromConfigFile,
    );

    if (diff.isNotEmpty) {
      throw StateError(
        'Missing required fields ${diff.toString()} in the extension '
        'config.yaml.',
      );
    } else {
      // All the required keys are present, but the value types did not match.
      final sb = StringBuffer();
      for (final entry in json.entries) {
        sb.writeln(
          '   ${entry.key}: ${entry.value} (${entry.value.runtimeType})',
        );
      }
      throw StateError(
        'Unexpected value types in the extension config.yaml. Expected all '
        'values to be of type String, but one or more had a different type:\n'
        '${sb.toString()}',
      );
    }
  }
}