blob: c64448c070440fd1e72e0de6115e8ad9e4fbf3d4 [file] [log] [blame]
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// This file is generated, do not edit.
// File generated by pkg/record_use/tool/generate_syntax.dart.
// ignore_for_file: unused_element, public_member_api_docs
import 'dart:io';
class BoolConstantSyntax extends ConstantSyntax {
BoolConstantSyntax.fromJson(super.json, {super.path}) : super._fromJson();
BoolConstantSyntax({required bool value, super.path = const []})
: super(type: 'bool') {
_value = value;
json.sortOnKey();
}
/// Setup all fields for [BoolConstantSyntax] that are not in
/// [ConstantSyntax].
void setup({required bool value}) {
_value = value;
json.sortOnKey();
}
bool get value => _reader.get<bool>('value');
set _value(bool value) {
json.setOrRemove('value', value);
}
List<String> _validateValue() => _reader.validate<bool>('value');
@override
List<String> validate() => [...super.validate(), ..._validateValue()];
@override
String toString() => 'BoolConstantSyntax($json)';
}
extension BoolConstantSyntaxExtension on ConstantSyntax {
bool get isBoolConstant => type == 'bool';
BoolConstantSyntax get asBoolConstant =>
BoolConstantSyntax.fromJson(json, path: path);
}
class CallSyntax extends JsonObjectSyntax {
factory CallSyntax.fromJson(
Map<String, Object?> json, {
List<Object> path = const [],
}) {
final result = CallSyntax._fromJson(json, path: path);
if (result.isTearoffCall) {
return result.asTearoffCall;
}
if (result.isWithArgumentsCall) {
return result.asWithArgumentsCall;
}
return result;
}
CallSyntax._fromJson(super.json, {super.path = const []}) : super.fromJson();
CallSyntax({
int? at,
required String loadingUnit,
required String type,
super.path = const [],
}) : super() {
_at = at;
_loadingUnit = loadingUnit;
_type = type;
json.sortOnKey();
}
int? get at => _reader.get<int?>('@');
set _at(int? value) {
json.setOrRemove('@', value);
}
List<String> _validateAt() => _reader.validate<int?>('@');
String get loadingUnit => _reader.get<String>('loading_unit');
set _loadingUnit(String value) {
json.setOrRemove('loading_unit', value);
}
List<String> _validateLoadingUnit() =>
_reader.validate<String>('loading_unit');
String get type => _reader.get<String>('type');
set _type(String value) {
json.setOrRemove('type', value);
}
List<String> _validateType() => _reader.validate<String>('type');
@override
List<String> validate() => [
...super.validate(),
..._validateAt(),
..._validateLoadingUnit(),
..._validateType(),
];
@override
String toString() => 'CallSyntax($json)';
}
class ConstantSyntax extends JsonObjectSyntax {
factory ConstantSyntax.fromJson(
Map<String, Object?> json, {
List<Object> path = const [],
}) {
final result = ConstantSyntax._fromJson(json, path: path);
if (result.isInstanceConstant) {
return result.asInstanceConstant;
}
if (result.isNullConstant) {
return result.asNullConstant;
}
if (result.isStringConstant) {
return result.asStringConstant;
}
if (result.isBoolConstant) {
return result.asBoolConstant;
}
if (result.isIntConstant) {
return result.asIntConstant;
}
if (result.isListConstant) {
return result.asListConstant;
}
if (result.isMapConstant) {
return result.asMapConstant;
}
return result;
}
ConstantSyntax._fromJson(super.json, {super.path = const []})
: super.fromJson();
ConstantSyntax({required String type, super.path = const []}) : super() {
_type = type;
json.sortOnKey();
}
String get type => _reader.get<String>('type');
set _type(String value) {
json.setOrRemove('type', value);
}
List<String> _validateType() => _reader.validate<String>('type');
@override
List<String> validate() => [...super.validate(), ..._validateType()];
@override
String toString() => 'ConstantSyntax($json)';
}
class DefinitionSyntax extends JsonObjectSyntax {
DefinitionSyntax.fromJson(super.json, {super.path = const []})
: super.fromJson();
DefinitionSyntax({
required IdentifierSyntax identifier,
String? loadingUnit,
super.path = const [],
}) : super() {
_identifier = identifier;
_loadingUnit = loadingUnit;
json.sortOnKey();
}
IdentifierSyntax get identifier {
final jsonValue = _reader.map$('identifier');
return IdentifierSyntax.fromJson(jsonValue, path: [...path, 'identifier']);
}
set _identifier(IdentifierSyntax value) {
json['identifier'] = value.json;
}
List<String> _validateIdentifier() {
final mapErrors = _reader.validate<Map<String, Object?>>('identifier');
if (mapErrors.isNotEmpty) {
return mapErrors;
}
return identifier.validate();
}
String? get loadingUnit => _reader.get<String?>('loading_unit');
set _loadingUnit(String? value) {
json.setOrRemove('loading_unit', value);
}
List<String> _validateLoadingUnit() =>
_reader.validate<String?>('loading_unit');
@override
List<String> validate() => [
...super.validate(),
..._validateIdentifier(),
..._validateLoadingUnit(),
];
@override
String toString() => 'DefinitionSyntax($json)';
}
class IdentifierSyntax extends JsonObjectSyntax {
IdentifierSyntax.fromJson(super.json, {super.path = const []})
: super.fromJson();
IdentifierSyntax({
required String name,
String? scope,
required String uri,
super.path = const [],
}) : super() {
_name = name;
_scope = scope;
_uri = uri;
json.sortOnKey();
}
String get name => _reader.get<String>('name');
set _name(String value) {
json.setOrRemove('name', value);
}
List<String> _validateName() => _reader.validate<String>('name');
String? get scope => _reader.get<String?>('scope');
set _scope(String? value) {
json.setOrRemove('scope', value);
}
List<String> _validateScope() => _reader.validate<String?>('scope');
String get uri => _reader.get<String>('uri');
set _uri(String value) {
json.setOrRemove('uri', value);
}
List<String> _validateUri() => _reader.validate<String>('uri');
@override
List<String> validate() => [
...super.validate(),
..._validateName(),
..._validateScope(),
..._validateUri(),
];
@override
String toString() => 'IdentifierSyntax($json)';
}
class InstanceSyntax extends JsonObjectSyntax {
InstanceSyntax.fromJson(super.json, {super.path = const []})
: super.fromJson();
InstanceSyntax({
int? at,
required int constantIndex,
required String loadingUnit,
super.path = const [],
}) : super() {
_at = at;
_constantIndex = constantIndex;
_loadingUnit = loadingUnit;
json.sortOnKey();
}
int? get at => _reader.get<int?>('@');
set _at(int? value) {
json.setOrRemove('@', value);
}
List<String> _validateAt() => _reader.validate<int?>('@');
int get constantIndex => _reader.get<int>('constant_index');
set _constantIndex(int value) {
json.setOrRemove('constant_index', value);
}
List<String> _validateConstantIndex() =>
_reader.validate<int>('constant_index');
String get loadingUnit => _reader.get<String>('loading_unit');
set _loadingUnit(String value) {
json.setOrRemove('loading_unit', value);
}
List<String> _validateLoadingUnit() =>
_reader.validate<String>('loading_unit');
@override
List<String> validate() => [
...super.validate(),
..._validateAt(),
..._validateConstantIndex(),
..._validateLoadingUnit(),
];
@override
String toString() => 'InstanceSyntax($json)';
}
class InstanceConstantSyntax extends ConstantSyntax {
InstanceConstantSyntax.fromJson(super.json, {super.path}) : super._fromJson();
InstanceConstantSyntax({JsonObjectSyntax? value, super.path = const []})
: super(type: 'Instance') {
_value = value;
json.sortOnKey();
}
/// Setup all fields for [InstanceConstantSyntax] that are not in
/// [ConstantSyntax].
void setup({required JsonObjectSyntax? value}) {
_value = value;
json.sortOnKey();
}
JsonObjectSyntax? get value {
final jsonValue = _reader.optionalMap('value');
if (jsonValue == null) return null;
return JsonObjectSyntax.fromJson(jsonValue, path: [...path, 'value']);
}
set _value(JsonObjectSyntax? value) {
json.setOrRemove('value', value?.json);
}
List<String> _validateValue() {
final mapErrors = _reader.validate<Map<String, Object?>?>('value');
if (mapErrors.isNotEmpty) {
return mapErrors;
}
return value?.validate() ?? [];
}
@override
List<String> validate() => [...super.validate(), ..._validateValue()];
@override
String toString() => 'InstanceConstantSyntax($json)';
}
extension InstanceConstantSyntaxExtension on ConstantSyntax {
bool get isInstanceConstant => type == 'Instance';
InstanceConstantSyntax get asInstanceConstant =>
InstanceConstantSyntax.fromJson(json, path: path);
}
class IntConstantSyntax extends ConstantSyntax {
IntConstantSyntax.fromJson(super.json, {super.path}) : super._fromJson();
IntConstantSyntax({required int value, super.path = const []})
: super(type: 'int') {
_value = value;
json.sortOnKey();
}
/// Setup all fields for [IntConstantSyntax] that are not in
/// [ConstantSyntax].
void setup({required int value}) {
_value = value;
json.sortOnKey();
}
int get value => _reader.get<int>('value');
set _value(int value) {
json.setOrRemove('value', value);
}
List<String> _validateValue() => _reader.validate<int>('value');
@override
List<String> validate() => [...super.validate(), ..._validateValue()];
@override
String toString() => 'IntConstantSyntax($json)';
}
extension IntConstantSyntaxExtension on ConstantSyntax {
bool get isIntConstant => type == 'int';
IntConstantSyntax get asIntConstant =>
IntConstantSyntax.fromJson(json, path: path);
}
class ListConstantSyntax extends ConstantSyntax {
ListConstantSyntax.fromJson(super.json, {super.path}) : super._fromJson();
ListConstantSyntax({List<Object?>? value, super.path = const []})
: super(type: 'list') {
_value = value;
json.sortOnKey();
}
/// Setup all fields for [ListConstantSyntax] that are not in
/// [ConstantSyntax].
void setup({required List<Object?>? value}) {
_value = value;
json.sortOnKey();
}
List<Object?>? get value => _reader.optionalList<Object?>('value');
set _value(List<Object?>? value) {
json.setOrRemove('value', value);
}
List<String> _validateValue() =>
_reader.validateOptionalList<Object?>('value');
@override
List<String> validate() => [...super.validate(), ..._validateValue()];
@override
String toString() => 'ListConstantSyntax($json)';
}
extension ListConstantSyntaxExtension on ConstantSyntax {
bool get isListConstant => type == 'list';
ListConstantSyntax get asListConstant =>
ListConstantSyntax.fromJson(json, path: path);
}
class LocationSyntax extends JsonObjectSyntax {
LocationSyntax.fromJson(super.json, {super.path = const []})
: super.fromJson();
LocationSyntax({
int? column,
int? line,
required String uri,
super.path = const [],
}) : super() {
_column = column;
_line = line;
_uri = uri;
json.sortOnKey();
}
int? get column => _reader.get<int?>('column');
set _column(int? value) {
json.setOrRemove('column', value);
}
List<String> _validateColumn() => _reader.validate<int?>('column');
int? get line => _reader.get<int?>('line');
set _line(int? value) {
json.setOrRemove('line', value);
}
List<String> _validateLine() => _reader.validate<int?>('line');
String get uri => _reader.get<String>('uri');
set _uri(String value) {
json.setOrRemove('uri', value);
}
List<String> _validateUri() => _reader.validate<String>('uri');
@override
List<String> validate() => [
...super.validate(),
..._validateColumn(),
..._validateLine(),
..._validateUri(),
];
@override
String toString() => 'LocationSyntax($json)';
}
class MapConstantSyntax extends ConstantSyntax {
MapConstantSyntax.fromJson(super.json, {super.path}) : super._fromJson();
MapConstantSyntax({required JsonObjectSyntax value, super.path = const []})
: super(type: 'map') {
_value = value;
json.sortOnKey();
}
/// Setup all fields for [MapConstantSyntax] that are not in
/// [ConstantSyntax].
void setup({required JsonObjectSyntax value}) {
_value = value;
json.sortOnKey();
}
JsonObjectSyntax get value {
final jsonValue = _reader.map$('value');
return JsonObjectSyntax.fromJson(jsonValue, path: [...path, 'value']);
}
set _value(JsonObjectSyntax value) {
json['value'] = value.json;
}
List<String> _validateValue() {
final mapErrors = _reader.validate<Map<String, Object?>>('value');
if (mapErrors.isNotEmpty) {
return mapErrors;
}
return value.validate();
}
@override
List<String> validate() => [...super.validate(), ..._validateValue()];
@override
String toString() => 'MapConstantSyntax($json)';
}
extension MapConstantSyntaxExtension on ConstantSyntax {
bool get isMapConstant => type == 'map';
MapConstantSyntax get asMapConstant =>
MapConstantSyntax.fromJson(json, path: path);
}
class MetadataSyntax extends JsonObjectSyntax {
MetadataSyntax.fromJson(super.json, {super.path = const []})
: super.fromJson();
MetadataSyntax({
required String comment,
required String version,
super.path = const [],
}) : super() {
_comment = comment;
_version = version;
json.sortOnKey();
}
String get comment => _reader.get<String>('comment');
set _comment(String value) {
json.setOrRemove('comment', value);
}
List<String> _validateComment() => _reader.validate<String>('comment');
String get version => _reader.get<String>('version');
set _version(String value) {
json.setOrRemove('version', value);
}
List<String> _validateVersion() => _reader.validate<String>('version');
@override
List<String> validate() => [
...super.validate(),
..._validateComment(),
..._validateVersion(),
];
@override
String toString() => 'MetadataSyntax($json)';
}
class NullConstantSyntax extends ConstantSyntax {
NullConstantSyntax.fromJson(super.json, {super.path}) : super._fromJson();
NullConstantSyntax({super.path = const []}) : super(type: 'Null');
@override
List<String> validate() => [...super.validate()];
@override
String toString() => 'NullConstantSyntax($json)';
}
extension NullConstantSyntaxExtension on ConstantSyntax {
bool get isNullConstant => type == 'Null';
NullConstantSyntax get asNullConstant =>
NullConstantSyntax.fromJson(json, path: path);
}
class RecordedUsesSyntax extends JsonObjectSyntax {
RecordedUsesSyntax.fromJson(super.json, {super.path = const []})
: super.fromJson();
RecordedUsesSyntax({
List<ConstantSyntax>? constants,
List<LocationSyntax>? locations,
required MetadataSyntax metadata,
List<RecordingSyntax>? recordings,
super.path = const [],
}) : super() {
_constants = constants;
_locations = locations;
_metadata = metadata;
_recordings = recordings;
json.sortOnKey();
}
List<ConstantSyntax>? get constants {
final jsonValue = _reader.optionalList('constants');
if (jsonValue == null) return null;
return [
for (final (index, element) in jsonValue.indexed)
ConstantSyntax.fromJson(
element as Map<String, Object?>,
path: [...path, 'constants', index],
),
];
}
set _constants(List<ConstantSyntax>? value) {
if (value == null) {
json.remove('constants');
} else {
json['constants'] = [for (final item in value) item.json];
}
}
List<String> _validateConstants() {
final listErrors = _reader.validateOptionalList<Map<String, Object?>>(
'constants',
);
if (listErrors.isNotEmpty) {
return listErrors;
}
final elements = constants;
if (elements == null) {
return [];
}
return [for (final element in elements) ...element.validate()];
}
List<LocationSyntax>? get locations {
final jsonValue = _reader.optionalList('locations');
if (jsonValue == null) return null;
return [
for (final (index, element) in jsonValue.indexed)
LocationSyntax.fromJson(
element as Map<String, Object?>,
path: [...path, 'locations', index],
),
];
}
set _locations(List<LocationSyntax>? value) {
if (value == null) {
json.remove('locations');
} else {
json['locations'] = [for (final item in value) item.json];
}
}
List<String> _validateLocations() {
final listErrors = _reader.validateOptionalList<Map<String, Object?>>(
'locations',
);
if (listErrors.isNotEmpty) {
return listErrors;
}
final elements = locations;
if (elements == null) {
return [];
}
return [for (final element in elements) ...element.validate()];
}
MetadataSyntax get metadata {
final jsonValue = _reader.map$('metadata');
return MetadataSyntax.fromJson(jsonValue, path: [...path, 'metadata']);
}
set _metadata(MetadataSyntax value) {
json['metadata'] = value.json;
}
List<String> _validateMetadata() {
final mapErrors = _reader.validate<Map<String, Object?>>('metadata');
if (mapErrors.isNotEmpty) {
return mapErrors;
}
return metadata.validate();
}
List<RecordingSyntax>? get recordings {
final jsonValue = _reader.optionalList('recordings');
if (jsonValue == null) return null;
return [
for (final (index, element) in jsonValue.indexed)
RecordingSyntax.fromJson(
element as Map<String, Object?>,
path: [...path, 'recordings', index],
),
];
}
set _recordings(List<RecordingSyntax>? value) {
if (value == null) {
json.remove('recordings');
} else {
json['recordings'] = [for (final item in value) item.json];
}
}
List<String> _validateRecordings() {
final listErrors = _reader.validateOptionalList<Map<String, Object?>>(
'recordings',
);
if (listErrors.isNotEmpty) {
return listErrors;
}
final elements = recordings;
if (elements == null) {
return [];
}
return [for (final element in elements) ...element.validate()];
}
@override
List<String> validate() => [
...super.validate(),
..._validateConstants(),
..._validateLocations(),
..._validateMetadata(),
..._validateRecordings(),
];
@override
String toString() => 'RecordedUsesSyntax($json)';
}
class RecordingSyntax extends JsonObjectSyntax {
RecordingSyntax.fromJson(super.json, {super.path = const []})
: super.fromJson();
RecordingSyntax({
List<CallSyntax>? calls,
required DefinitionSyntax definition,
List<InstanceSyntax>? instances,
super.path = const [],
}) : super() {
_calls = calls;
_definition = definition;
_instances = instances;
json.sortOnKey();
}
List<CallSyntax>? get calls {
final jsonValue = _reader.optionalList('calls');
if (jsonValue == null) return null;
return [
for (final (index, element) in jsonValue.indexed)
CallSyntax.fromJson(
element as Map<String, Object?>,
path: [...path, 'calls', index],
),
];
}
set _calls(List<CallSyntax>? value) {
if (value == null) {
json.remove('calls');
} else {
json['calls'] = [for (final item in value) item.json];
}
}
List<String> _validateCalls() {
final listErrors = _reader.validateOptionalList<Map<String, Object?>>(
'calls',
);
if (listErrors.isNotEmpty) {
return listErrors;
}
final elements = calls;
if (elements == null) {
return [];
}
return [for (final element in elements) ...element.validate()];
}
DefinitionSyntax get definition {
final jsonValue = _reader.map$('definition');
return DefinitionSyntax.fromJson(jsonValue, path: [...path, 'definition']);
}
set _definition(DefinitionSyntax value) {
json['definition'] = value.json;
}
List<String> _validateDefinition() {
final mapErrors = _reader.validate<Map<String, Object?>>('definition');
if (mapErrors.isNotEmpty) {
return mapErrors;
}
return definition.validate();
}
List<InstanceSyntax>? get instances {
final jsonValue = _reader.optionalList('instances');
if (jsonValue == null) return null;
return [
for (final (index, element) in jsonValue.indexed)
InstanceSyntax.fromJson(
element as Map<String, Object?>,
path: [...path, 'instances', index],
),
];
}
set _instances(List<InstanceSyntax>? value) {
if (value == null) {
json.remove('instances');
} else {
json['instances'] = [for (final item in value) item.json];
}
}
List<String> _validateInstances() {
final listErrors = _reader.validateOptionalList<Map<String, Object?>>(
'instances',
);
if (listErrors.isNotEmpty) {
return listErrors;
}
final elements = instances;
if (elements == null) {
return [];
}
return [for (final element in elements) ...element.validate()];
}
@override
List<String> validate() => [
...super.validate(),
..._validateCalls(),
..._validateDefinition(),
..._validateInstances(),
];
@override
String toString() => 'RecordingSyntax($json)';
}
class StringConstantSyntax extends ConstantSyntax {
StringConstantSyntax.fromJson(super.json, {super.path}) : super._fromJson();
StringConstantSyntax({required String value, super.path = const []})
: super(type: 'String') {
_value = value;
json.sortOnKey();
}
/// Setup all fields for [StringConstantSyntax] that are not in
/// [ConstantSyntax].
void setup({required String value}) {
_value = value;
json.sortOnKey();
}
String get value => _reader.get<String>('value');
set _value(String value) {
json.setOrRemove('value', value);
}
List<String> _validateValue() => _reader.validate<String>('value');
@override
List<String> validate() => [...super.validate(), ..._validateValue()];
@override
String toString() => 'StringConstantSyntax($json)';
}
extension StringConstantSyntaxExtension on ConstantSyntax {
bool get isStringConstant => type == 'String';
StringConstantSyntax get asStringConstant =>
StringConstantSyntax.fromJson(json, path: path);
}
class TearoffCallSyntax extends CallSyntax {
TearoffCallSyntax.fromJson(super.json, {super.path}) : super._fromJson();
TearoffCallSyntax({
super.at,
required super.loadingUnit,
super.path = const [],
}) : super(type: 'tearoff');
@override
List<String> validate() => [...super.validate()];
@override
String toString() => 'TearoffCallSyntax($json)';
}
extension TearoffCallSyntaxExtension on CallSyntax {
bool get isTearoffCall => type == 'tearoff';
TearoffCallSyntax get asTearoffCall =>
TearoffCallSyntax.fromJson(json, path: path);
}
class WithArgumentsCallSyntax extends CallSyntax {
WithArgumentsCallSyntax.fromJson(super.json, {super.path})
: super._fromJson();
WithArgumentsCallSyntax({
super.at,
required super.loadingUnit,
Map<String, int>? named,
List<int?>? positional,
super.path = const [],
}) : super(type: 'with_arguments') {
_named = named;
_positional = positional;
json.sortOnKey();
}
/// Setup all fields for [WithArgumentsCallSyntax] that are not in
/// [CallSyntax].
void setup({
required Map<String, int>? named,
required List<int?>? positional,
}) {
_named = named;
_positional = positional;
json.sortOnKey();
}
Map<String, int>? get named => _reader.optionalMap<int>('named');
set _named(Map<String, int>? value) {
_checkArgumentMapKeys(value);
json.setOrRemove('named', value);
}
List<String> _validateNamed() => _reader.validateMap<int>('named');
List<int?>? get positional => _reader.optionalList<int?>('positional');
set _positional(List<int?>? value) {
json.setOrRemove('positional', value);
}
List<String> _validatePositional() =>
_reader.validateOptionalList<int?>('positional');
@override
List<String> validate() => [
...super.validate(),
..._validateNamed(),
..._validatePositional(),
];
@override
String toString() => 'WithArgumentsCallSyntax($json)';
}
extension WithArgumentsCallSyntaxExtension on CallSyntax {
bool get isWithArgumentsCall => type == 'with_arguments';
WithArgumentsCallSyntax get asWithArgumentsCall =>
WithArgumentsCallSyntax.fromJson(json, path: path);
}
class JsonObjectSyntax {
final Map<String, Object?> json;
final List<Object> path;
_JsonReader get _reader => _JsonReader(json, path);
JsonObjectSyntax({this.path = const []}) : json = {};
JsonObjectSyntax.fromJson(this.json, {this.path = const []});
List<String> validate() => [];
}
class _JsonReader {
/// The JSON Object this reader is reading.
final Map<String, Object?> json;
/// The path traversed by readers of the surrounding JSON.
///
/// Contains [String] property keys and [int] indices.
///
/// This is used to give more precise error messages.
final List<Object> path;
_JsonReader(this.json, this.path);
T get<T extends Object?>(String key) {
final value = json[key];
if (value is T) return value;
throwFormatException(value, T, [key]);
}
List<String> validate<T extends Object?>(String key) {
final value = json[key];
if (value is T) return [];
return [
errorString(value, T, [key]),
];
}
List<T> list<T extends Object?>(String key) =>
_castList<T>(get<List<Object?>>(key), key);
List<String> validateList<T extends Object?>(String key) {
final listErrors = validate<List<Object?>>(key);
if (listErrors.isNotEmpty) {
return listErrors;
}
return _validateListElements(get<List<Object?>>(key), key);
}
List<T>? optionalList<T extends Object?>(String key) =>
switch (get<List<Object?>?>(key)?.cast<T>()) {
null => null,
final l => _castList<T>(l, key),
};
List<String> validateOptionalList<T extends Object?>(String key) {
final listErrors = validate<List<Object?>?>(key);
if (listErrors.isNotEmpty) {
return listErrors;
}
final list = get<List<Object?>?>(key);
if (list == null) {
return [];
}
return _validateListElements(list, key);
}
/// [List.cast] but with [FormatException]s.
List<T> _castList<T extends Object?>(List<Object?> list, String key) {
for (final (index, value) in list.indexed) {
if (value is! T) {
throwFormatException(value, T, [key, index]);
}
}
return list.cast();
}
List<String> _validateListElements<T extends Object?>(
List<Object?> list,
String key,
) {
final result = <String>[];
for (final (index, value) in list.indexed) {
if (value is! T) {
result.add(errorString(value, T, [key, index]));
}
}
return result;
}
Map<String, T> map$<T extends Object?>(String key, {RegExp? keyPattern}) {
final map = get<Map<String, Object?>>(key);
final keyErrors = _validateMapKeys(map, key, keyPattern: keyPattern);
if (keyErrors.isNotEmpty) {
throw FormatException(keyErrors.join('\n'));
}
return _castMap<T>(map, key);
}
List<String> validateMap<T extends Object?>(
String key, {
RegExp? keyPattern,
}) {
final mapErrors = validate<Map<String, Object?>>(key);
if (mapErrors.isNotEmpty) {
return mapErrors;
}
final map = get<Map<String, Object?>>(key);
return [
..._validateMapKeys(map, key, keyPattern: keyPattern),
..._validateMapElements<T>(map, key),
];
}
Map<String, T>? optionalMap<T extends Object?>(
String key, {
RegExp? keyPattern,
}) {
final map = get<Map<String, Object?>?>(key);
if (map == null) return null;
final keyErrors = _validateMapKeys(map, key, keyPattern: keyPattern);
if (keyErrors.isNotEmpty) {
throw FormatException(keyErrors.join('\n'));
}
return _castMap<T>(map, key);
}
List<String> validateOptionalMap<T extends Object?>(
String key, {
RegExp? keyPattern,
}) {
final mapErrors = validate<Map<String, Object?>?>(key);
if (mapErrors.isNotEmpty) {
return mapErrors;
}
final map = get<Map<String, Object?>?>(key);
if (map == null) {
return [];
}
return [
..._validateMapKeys(map, key, keyPattern: keyPattern),
..._validateMapElements<T>(map, key),
];
}
/// [Map.cast] but with [FormatException]s.
Map<String, T> _castMap<T extends Object?>(
Map<String, Object?> map_,
String parentKey,
) {
for (final MapEntry(:key, :value) in map_.entries) {
if (value is! T) {
throwFormatException(value, T, [parentKey, key]);
}
}
return map_.cast();
}
List<String> _validateMapKeys(
Map<String, Object?> map_,
String parentKey, {
required RegExp? keyPattern,
}) {
if (keyPattern == null) return [];
final result = <String>[];
for (final key in map_.keys) {
if (!keyPattern.hasMatch(key)) {
result.add(
keyErrorString(key, pattern: keyPattern, pathExtension: [parentKey]),
);
}
}
return result;
}
List<String> _validateMapElements<T extends Object?>(
Map<String, Object?> map_,
String parentKey,
) {
final result = <String>[];
for (final MapEntry(:key, :value) in map_.entries) {
if (value is! T) {
result.add(errorString(value, T, [parentKey, key]));
}
}
return result;
}
List<String> validateMapStringElements<T extends Object?>(
Map<String, String?> map_,
String parentKey, {
RegExp? valuePattern,
}) {
final result = <String>[];
for (final MapEntry(:key, :value) in map_.entries) {
if (value != null &&
valuePattern != null &&
!valuePattern.hasMatch(value)) {
result.add(
errorString(value, T, [parentKey, key], pattern: valuePattern),
);
}
}
return result;
}
String string(String key, RegExp? pattern) {
final value = get<String>(key);
if (pattern != null && !pattern.hasMatch(value)) {
throwFormatException(value, String, [key], pattern: pattern);
}
return value;
}
String? optionalString(String key, RegExp? pattern) {
final value = get<String?>(key);
if (value == null) return null;
if (pattern != null && !pattern.hasMatch(value)) {
throwFormatException(value, String, [key], pattern: pattern);
}
return value;
}
List<String> validateString(String key, RegExp? pattern) {
final errors = validate<String>(key);
if (errors.isNotEmpty) {
return errors;
}
final value = get<String>(key);
if (pattern != null && !pattern.hasMatch(value)) {
return [
errorString(value, String, [key], pattern: pattern),
];
}
return [];
}
List<String> validateOptionalString(String key, RegExp? pattern) {
final errors = validate<String?>(key);
if (errors.isNotEmpty) {
return errors;
}
final value = get<String?>(key);
if (value == null) return [];
if (pattern != null && !pattern.hasMatch(value)) {
return [
errorString(value, String, [key], pattern: pattern),
];
}
return [];
}
List<String>? optionalStringList(String key) => optionalList<String>(key);
List<String> validateOptionalStringList(String key) =>
validateOptionalList<String>(key);
List<String> stringList(String key) => list<String>(key);
List<String> validateStringList(String key) => validateList<String>(key);
Uri path$(String key) => _fileSystemPathToUri(get<String>(key));
List<String> validatePath(String key) => validate<String>(key);
Uri? optionalPath(String key) {
final value = get<String?>(key);
if (value == null) return null;
return _fileSystemPathToUri(value);
}
List<String> validateOptionalPath(String key) => validate<String?>(key);
List<Uri>? optionalPathList(String key) {
final strings = optionalStringList(key);
if (strings == null) {
return null;
}
return [for (final string in strings) _fileSystemPathToUri(string)];
}
List<String> validateOptionalPathList(String key) =>
validateOptionalStringList(key);
static Uri _fileSystemPathToUri(String path) {
if (path.endsWith(Platform.pathSeparator)) {
return Uri.directory(path);
}
return Uri.file(path);
}
String _jsonPathToString(List<Object> pathEnding) =>
[...path, ...pathEnding].join('.');
Never throwFormatException(
Object? value,
Type expectedType,
List<Object> pathExtension, {
RegExp? pattern,
}) {
throw FormatException(
errorString(value, expectedType, pathExtension, pattern: pattern),
);
}
String errorString(
Object? value,
Type expectedType,
List<Object> pathExtension, {
RegExp? pattern,
}) {
final pathString = _jsonPathToString(pathExtension);
if (value == null) {
return "No value was provided for '$pathString'."
' Expected a $expectedType.';
}
final satisfying = pattern == null ? '' : ' satisfying ${pattern.pattern}';
return "Unexpected value '$value' (${value.runtimeType}) for '$pathString'."
' Expected a $expectedType$satisfying.';
}
String keyErrorString(
String key, {
required RegExp pattern,
List<Object> pathExtension = const [],
}) {
final pathString = _jsonPathToString(pathExtension);
return "Unexpected key '$key' in '$pathString'."
' Expected a key satisfying ${pattern.pattern}.';
}
/// Traverses a JSON path, returns `null` if the path cannot be traversed.
Object? tryTraverse(List<String> path) {
Object? json = this.json;
for (final key in path) {
if (json is! Map<String, Object?>) {
return null;
}
json = json[key];
}
return json;
}
}
extension on Map<String, Object?> {
void setOrRemove(String key, Object? value) {
if (value == null) {
remove(key);
} else {
this[key] = value;
}
}
}
extension on List<Uri> {
List<String> toJson() => [for (final uri in this) uri.toFilePath()];
}
extension<K extends Comparable<K>, V extends Object?> on Map<K, V> {
void sortOnKey() {
final result = <K, V>{};
final keysSorted = keys.toList()..sort();
for (final key in keysSorted) {
result[key] = this[key] as V;
}
clear();
addAll(result);
}
}
void _checkArgumentMapKeys(Map<String, Object?>? map, {RegExp? keyPattern}) {
if (map == null) return;
if (keyPattern == null) return;
for (final key in map.keys) {
if (!keyPattern.hasMatch(key)) {
throw ArgumentError.value(
map,
"Unexpected key '$key'."
' Expected a key satisfying ${keyPattern.pattern}.',
);
}
}
}
void _checkArgumentMapStringElements(
Map<String, String?>? map, {
RegExp? valuePattern,
}) {
if (map == null) return;
if (valuePattern == null) return;
for (final entry in map.entries) {
final value = entry.value;
if (value != null && !valuePattern.hasMatch(value)) {
throw ArgumentError.value(
map,
"Unexpected value '$value' under key '${entry.key}'."
' Expected a value satisfying ${valuePattern.pattern}.',
);
}
}
}