From 194b9c073fa2018706565a85933871a92c6ca247 Mon Sep 17 00:00:00 2001 From: Kelvin Kavisi <68240897+kekavc24@users.noreply.github.com> Date: Sun, 3 Dec 2023 15:08:27 +0000 Subject: [PATCH] refactor: clean up & optimize code > simplify pair definition using Dart records > apply changes to `NodeData` object > add method to return shortest key path for recursive rename > update replacer to use shortest key path --- .../data/matched_node_data.dart | 14 +++- .../yaml_transformers/data/node_data.dart | 62 +++++++------- .../data/pair_definition/key.dart | 24 ------ .../data/pair_definition/pair_definition.dart | 81 ++++++++++++------- .../data/pair_definition/value.dart | 32 -------- .../replacers/key_replacer.dart | 10 ++- 6 files changed, 99 insertions(+), 124 deletions(-) delete mode 100644 lib/src/core/yaml_transformers/data/pair_definition/key.dart delete mode 100644 lib/src/core/yaml_transformers/data/pair_definition/value.dart diff --git a/lib/src/core/yaml_transformers/data/matched_node_data.dart b/lib/src/core/yaml_transformers/data/matched_node_data.dart index 51f8dd1..dd76c73 100644 --- a/lib/src/core/yaml_transformers/data/matched_node_data.dart +++ b/lib/src/core/yaml_transformers/data/matched_node_data.dart @@ -60,13 +60,19 @@ class MatchedNodeData { return (indexMap: indexMap, keys: keys); } - /// Get path of keys upto the last renameable key - String getPathToLastKey() { + /// Get list of keys upto the last renameable key + Iterable getUptoLastRenameable() { + // Get max final keyRecord = getMatchedKeysIndex(); - final lastIndex = keyRecord.indexMap.values.max; // Get max + final lastIndex = keyRecord.indexMap.values.max; // Keys to be taken, include last index plus one - return keyRecord.keys.take(lastIndex + 1).join('/'); + return keyRecord.keys.take(lastIndex + 1); + } + + /// Get path of keys upto the last renameable key + String getPathToLastKey() { + return getUptoLastRenameable().join('/'); } @override diff --git a/lib/src/core/yaml_transformers/data/node_data.dart b/lib/src/core/yaml_transformers/data/node_data.dart index fca6a12..fe1b3a8 100644 --- a/lib/src/core/yaml_transformers/data/node_data.dart +++ b/lib/src/core/yaml_transformers/data/node_data.dart @@ -8,12 +8,34 @@ part of '../yaml_transformer.dart'; class NodeData { const NodeData._(this.precedingKeys, this.key, this.value); + /// Create with default constructor + factory NodeData.skeleton({ + required List precedingKeys, + required Key key, + required Value value, + }) { + return NodeData._(precedingKeys, key, value); + } + + /// Create using List path and key + factory NodeData.stringSkeleton({ + required List path, + required String key, + required String value, + }) { + return NodeData.skeleton( + precedingKeys: path.map((e) => createKey(value: e)).toList(), + key: createKey(value: key), + value: createValue(value: value), + ); + } + /// Create from the root anchor key factory NodeData.fromRoot({required String key, required dynamic value}) { return NodeData._( const [], - _createPairType(isKey: true, value: key), - _createPairType(isKey: false, value: value), + createKey(value: key), + createValue(value: value), ); } @@ -30,13 +52,8 @@ class NodeData { }) { return NodeData._( [...parent.precedingKeys, parent.key], - _createPairType( - isKey: true, - value: current.key, - level: indices.isEmpty ? Level.normal : Level.nested, - indices: indices, - ), - _createPairType(isKey: false, value: current.value), + createKey(value: current.key as String?, indices: indices), + createValue(value: current.value), ); } @@ -56,12 +73,7 @@ class NodeData { return NodeData._( [...parent.precedingKeys], parent.key, - _createPairType( - isKey: false, - value: terminalValue, - level: indices.isEmpty ? Level.normal : Level.nested, - indices: indices, - ), + createValue(value: terminalValue, indices: indices), ); } @@ -139,23 +151,3 @@ class NodeData { precedingKeys.isNotEmpty && precedingKeys.any((element) => element.isNested()); } - -/// Creates a specialized PairType -T _createPairType({ - required bool isKey, - required dynamic value, - Level? level, - List? indices, -}) { - return isKey - ? Key( - value: value as String, - level: level ?? Level.normal, - indices: indices ?? [], - ) as T - : Value( - value: isTerminal(value) ? value.toString() : value, - level: level ?? Level.normal, - indices: indices ?? [], - ) as T; -} diff --git a/lib/src/core/yaml_transformers/data/pair_definition/key.dart b/lib/src/core/yaml_transformers/data/pair_definition/key.dart deleted file mode 100644 index d0177d8..0000000 --- a/lib/src/core/yaml_transformers/data/pair_definition/key.dart +++ /dev/null @@ -1,24 +0,0 @@ -part of 'pair_definition.dart'; - -/// Defines the key of a key/value pair in a Map -@immutable -final class Key extends PairType { - Key({ - required this.value, - required super.level, - required super.indices, - }); - - /// Value of this key - final String? value; - - @override - bool operator ==(Object other) => - other is Key && other.value == value && super._isSameLevel(other); - - @override - int get hashCode => Object.hashAll([super.level, super.indices, value]); - - @override - String toString() => value ?? ''; -} diff --git a/lib/src/core/yaml_transformers/data/pair_definition/pair_definition.dart b/lib/src/core/yaml_transformers/data/pair_definition/pair_definition.dart index 282b6c5..2fd03b3 100644 --- a/lib/src/core/yaml_transformers/data/pair_definition/pair_definition.dart +++ b/lib/src/core/yaml_transformers/data/pair_definition/pair_definition.dart @@ -1,32 +1,59 @@ -import 'package:magical_version_bump/src/utils/typedefs/typedefs.dart'; -import 'package:meta/meta.dart'; - -part 'key.dart'; -part 'value.dart'; - -/// Level of a key/value in a map -enum Level { - /// Direct value of a key - normal, - - /// Nested in a list - nested +/// Custom key/value definition +/// +/// `value` - indicates the actual value +/// `indices` - indicates the list of indices when nested in 1 or more lists +typedef PairType = ({T? value, List indices}); + +/// A key in a custom key/value definition +/// +/// See [PairType] +typedef Key = PairType; + +/// A value in a custom key/value definition +/// +/// See [PairType] +typedef Value = PairType; + +T _pairType({ + required dynamic value, + required List indices, +}) { + return (value: value, indices: indices) as T; } -/// Forms the base class for a key/value in a map -abstract base class PairType { - PairType({required this.level, required this.indices}); - - /// Level in based on parent key - final Level level; - - /// List of indices in order of nested level - final List indices; +/// Create key +Key createKey({String? value, List? indices}) => _pairType( + value: value, + indices: indices ?? [], + ); + +/// Creates a list of keys +List createListOfKeys({ + required List keys, + required Map> linkedIndices, +}) { + return keys + .map((e) => createKey(value: e, indices: linkedIndices[e])) + .toList(); +} - /// Checks whether this key is nested - bool isNested() => level == Level.nested; +/// Create value +Value createValue({required dynamic value, List? indices}) => _pairType( + value: value, + indices: indices ?? [], + ); + +/// Creates a list of keys +List createListOfValues({ + required List keys, + required Map> linkedIndices, +}) { + return keys + .map((e) => createValue(value: e, indices: linkedIndices[e])) + .toList(); +} - /// Checks whether they are on the same level - bool _isSameLevel(PairType other) => - level == other.level && collectionsMatch(indices, other.indices); +extension PairTypeExtension on PairType { + /// Checks if nested in a list + bool isNested() => this.indices.isNotEmpty; } diff --git a/lib/src/core/yaml_transformers/data/pair_definition/value.dart b/lib/src/core/yaml_transformers/data/pair_definition/value.dart deleted file mode 100644 index df193e2..0000000 --- a/lib/src/core/yaml_transformers/data/pair_definition/value.dart +++ /dev/null @@ -1,32 +0,0 @@ -part of 'pair_definition.dart'; - -/// Defines the value of a key/value pair -@immutable -final class Value extends PairType { - Value({ - required this.value, - required super.level, - required super.indices, - }); - - /// Value of this value - final dynamic value; - - @override - bool operator ==(Object other) => - other is Value && _dataIsSame(other.value) && super._isSameLevel(other); - - @override - int get hashCode => Object.hashAll([super.level, super.indices, value]); - - bool _dataIsSame(dynamic other) { - if (value.runtimeType != other.runtimeType) return false; - - if (value is String) return value == other; - - return collectionsMatch(value, other); - } - - @override - String toString() => value.toString(); -} diff --git a/lib/src/core/yaml_transformers/replacers/key_replacer.dart b/lib/src/core/yaml_transformers/replacers/key_replacer.dart index 7d965e2..8714461 100644 --- a/lib/src/core/yaml_transformers/replacers/key_replacer.dart +++ b/lib/src/core/yaml_transformers/replacers/key_replacer.dart @@ -52,10 +52,16 @@ class MagicalRenamer extends Replacer { checkForKey: true, ); + // Get path to last renameable key inclusive of last key + final pathToLastKey = [...matchedNodeData.getUptoLastRenameable()]; + + // Remove last which will act as our pseudo target + final target = pathToLastKey.removeLast(); + final updatedMap = modifiable.updateIndexedMap( null, - target: matchedNodeData.nodeData.key, - path: matchedNodeData.nodeData.precedingKeys, + target: target, + path: pathToLastKey, keyAndReplacement: replacementPair, value: null, );