Line data Source code
1 : import 'package:enum_assist/src/util/enum_helpers.dart';
2 : import 'package:enum_assist/src/util/util.dart';
3 : import 'package:enum_assist_annotation/enum_assist_annotation.dart';
4 : import 'package:meta/meta.dart';
5 : import 'package:source_gen/source_gen.dart';
6 :
7 : /// {@template enum_assist.additional_extension_config}
8 : /// The configuration for the additional extension.
9 : /// {@endtemplate}
10 : class AdditionalExtensionConfig {
11 : /// {@macro enum_assist.additional_extension_config}
12 1 : AdditionalExtensionConfig._({
13 : required this.methodName,
14 : required this.valueType,
15 : required this.methodType,
16 : required this.defaultValue,
17 : required this.className,
18 : required this.valueClassType,
19 : required this.docComment,
20 : });
21 :
22 : /// {@macro enum_assist.additional_extension.default_value}
23 : final String methodName;
24 :
25 : /// {@macro enum_assist.additional_extension.default_value}
26 : final String valueType;
27 :
28 : /// {@macro enum_assist.additional_extension.method_type}
29 : final MethodType methodType;
30 :
31 : /// {@macro enum_assist.additional_extension.default_value}
32 : final String? defaultValue;
33 :
34 : /// name of the class used to create the extension
35 : final String className;
36 :
37 : /// type of class used to create the value
38 : final String valueClassType;
39 :
40 : /// {@macro enum_assist.additional_extension.doc_comment}
41 : final String? docComment;
42 :
43 : /// returns the formatted [docComment]
44 1 : String getDocComment() {
45 1 : if (docComment == null) return '/// @nodoc';
46 :
47 1 : return docComment!
48 : // prepend "/// " to each line that starts with anything other than a line break
49 1 : .replaceAllMapped(
50 4 : RegExp('^(.)', multiLine: true), (match) => '/// ${match.group(0)}')
51 :
52 : /// prepend "/// " to each line that starts with a line break
53 3 : .replaceAllMapped(RegExp(r'^\n', multiLine: true), (_) => '///\n');
54 : }
55 :
56 : /// checks if the [valueType] is nullable
57 3 : bool get isValueTypeNullable => isTypeAsStringNullable(valueType);
58 :
59 : /// used for testing
60 : ///
61 : /// {@macro enum_assist.additional_extension_config}
62 1 : @visibleForTesting
63 : static AdditionalExtensionConfig manual({
64 : String methodName = 'manual',
65 : String valueType = 'String',
66 : MethodType methodType = MethodType.map,
67 : String? defaultValue,
68 : String className = 'Manual',
69 : String valueClassType = 'String',
70 : String? docComment,
71 : }) {
72 1 : return AdditionalExtensionConfig._(
73 : methodName: methodName,
74 : valueType: valueType,
75 : methodType: methodType,
76 : defaultValue: defaultValue,
77 : className: className,
78 : valueClassType: valueClassType,
79 : docComment: docComment,
80 : );
81 : }
82 :
83 : /// resolve the [AdditionalExtensionConfig] from a `ConstantReader`
84 0 : static AdditionalExtensionConfig? resolve(ConstantReader reader) {
85 : const methodNameKey = 'methodName';
86 : const methodTypeKey = 'methodType';
87 : const defaultValueKey = 'defaultValue';
88 : const docCommentKey = 'docComment';
89 :
90 0 : final methodNameValue = reader.peek(methodNameKey)?.stringValue;
91 0 : if (methodNameValue == null) throw _methodNameException(methodNameKey);
92 :
93 0 : final methodTypeObj = reader.peek(methodTypeKey)?.objectValue;
94 : if (methodTypeObj == null) {
95 0 : throw _methodTypeException(methodTypeKey, methodNameValue);
96 : }
97 :
98 : final methodTypeValue =
99 0 : getEnumFromDartObject(methodTypeObj, MethodType.values);
100 : if (methodTypeValue == null) {
101 0 : throw _methodTypeException(methodTypeKey, methodNameValue);
102 : }
103 :
104 0 : final defaultValueValue = reader.peek(defaultValueKey)?.stringValue;
105 :
106 0 : if (_isMissingDefaultValue(defaultValueValue, methodTypeValue)) {
107 0 : throw _defaultValueException(
108 : defaultValueKey,
109 : methodTypeKey,
110 : methodNameValue,
111 : );
112 : }
113 :
114 0 : final classDetails = '${reader.objectValue}';
115 :
116 0 : final match = RegExp(r'(Map|MaybeMap)Extension<.*[, ]?>(?=\s\(\()')
117 0 : .firstMatch(classDetails)
118 0 : ?.group(0);
119 :
120 : if (match == null) {
121 0 : throw MissingValueException(
122 0 : 'Could not locate the Type arguements for $classDetails',
123 : );
124 : }
125 :
126 0 : final cleanMatch = match.replaceAll(RegExp('(Map|MaybeMap)Extension'), '');
127 : final typeArguments =
128 0 : cleanMatch.substring(1, cleanMatch.length - 1).split(', ');
129 :
130 0 : final valueType = typeArguments[0];
131 0 : final valueClassType = typeArguments[1];
132 0 : final className = reader.objectValue.type!.element!.displayName;
133 0 : final docCommentValue = reader.peek(docCommentKey)?.stringValue;
134 :
135 0 : return AdditionalExtensionConfig._(
136 : methodName: methodNameValue,
137 : valueType: valueType,
138 : methodType: methodTypeValue,
139 : defaultValue: defaultValueValue,
140 : className: className,
141 : valueClassType: valueClassType,
142 : docComment: docCommentValue,
143 : );
144 : }
145 :
146 0 : static MissingValueException<String> _methodTypeException(
147 : String key, String methodName) {
148 0 : return MissingValueException(
149 : 'Missing value "$key" in method "$methodName". '
150 : 'Choose `map` or `maybeMap`',
151 : );
152 : }
153 :
154 0 : static MissingValueException<String> _methodNameException(String key) {
155 0 : return MissingValueException(
156 : 'Missing value "$key"! Make sure you have '
157 : 'everything configured',
158 : );
159 : }
160 :
161 0 : static MissingValueException<String> _defaultValueException(
162 : String key, String typeKey, String methodName) {
163 0 : return MissingValueException(
164 : 'Missing value "$key" in method "$methodName". '
165 : 'the "$key" is required if the "$typeKey" is `maybeMap`',
166 : );
167 : }
168 :
169 0 : @override
170 : String toString() {
171 : return '''
172 0 : methodName: $methodName,
173 0 : valueType: $valueType,
174 0 : methodType: $methodType,
175 0 : defaultValue: $defaultValue,
176 0 : className: $className,
177 0 : valueClassType: $valueClassType,
178 0 : docCommentValue: $docComment,
179 0 : ''';
180 : }
181 : }
182 :
183 0 : bool _isMissingDefaultValue<T>(T defaultValue, MethodType methodType) {
184 0 : return methodType.maybeMap(
185 0 : orElse: () {
186 : return false;
187 : },
188 0 : maybeMap: () {
189 : if (defaultValue == null) return true;
190 : return false;
191 : },
192 : )();
193 : }
|