4
4
5
5
library dartdoc.model_utils;
6
6
7
+ import 'dart:collection' ;
7
8
import 'dart:convert' ;
8
9
import 'dart:io' ;
9
10
@@ -12,6 +13,7 @@ import 'package:analyzer/src/generated/engine.dart';
12
13
import 'package:analyzer/src/generated/sdk.dart' ;
13
14
import 'package:analyzer/src/generated/source_io.dart' ;
14
15
import 'package:dartdoc/src/model.dart' ;
16
+ import 'package:quiver_hashcode/hashcode.dart' ;
15
17
16
18
import 'config.dart' ;
17
19
@@ -166,3 +168,160 @@ String crossdartifySource(
166
168
}
167
169
return newSource;
168
170
}
171
+
172
+ /// An UnmodifiableListView that computes equality and hashCode based on the
173
+ /// equality and hashCode of its contained objects.
174
+ class _HashableList extends UnmodifiableListView <dynamic > {
175
+ _HashableList (Iterable <dynamic > iterable) : super (iterable);
176
+
177
+ @override
178
+ bool operator == (other) {
179
+ if (other is _HashableList ) {
180
+ if (this .length == other.length) {
181
+ for (var index = 0 ; index < length; ++ index) {
182
+ if (this [index] != other[index]) return false ;
183
+ }
184
+ return true ;
185
+ }
186
+ }
187
+ return false ;
188
+ }
189
+
190
+ @override
191
+ get hashCode => hashObjects (this );
192
+ }
193
+
194
+ /// Extend or use as a mixin to track object-specific cached values, or
195
+ /// instantiate directly to track other values.
196
+ ///
197
+ /// For all methods in this class, the parameter [f] must be a tear-off method
198
+ /// or top level function (not an inline closure) for memoization to work.
199
+ /// [Memoizer] depends on the equality operator on the given function to detect
200
+ /// when we are calling the same function.
201
+ ///
202
+ /// Use:
203
+ ///
204
+ /// ```dart
205
+ /// String aTestFunction(String greeting, String name) => "${greeting}, ${name}";
206
+ /// int aSlowFunction() { doSome(); return expensiveCalculations(); }
207
+ ///
208
+ /// myMemoizer.memoized2(aTestFunction, "Hello, "world");
209
+ /// myMemoizer.memoized(aSlowFunction);
210
+ /// ```
211
+ ///
212
+ /// *Not*:
213
+ ///
214
+ /// ```dart
215
+ /// String aTestFunction(String greeting, String name) => "${greeting}, ${name}";
216
+ ///
217
+ /// myMemoizer.memoized2((a, b) => aTestFunction(a, b), "Hello", "world");
218
+ /// myMemoizer.memoized(() => aSlowFunction());;
219
+ /// ```
220
+ class Memoizer {
221
+ /// Map of a function and its positional parameters (if any), to a value.
222
+ Map <_HashableList , dynamic > _memoizationTable;
223
+
224
+ Memoizer () {
225
+ invalidateMemos ();
226
+ }
227
+
228
+ /// Reset the memoization table, forcing calls of the underlying functions.
229
+ void invalidateMemos () {
230
+ _memoizationTable = new Map ();
231
+ }
232
+
233
+ /// Calls and caches the return value of [f] () if not in the cache, then
234
+ /// returns the cached value of [f] ().
235
+ R memoized <R >(Function f) {
236
+ _HashableList key = new _HashableList ([f]);
237
+ return _memoizationTable.putIfAbsent (key, f);
238
+ }
239
+
240
+ /// Calls and caches the return value of [f] ([param1] ) if not in the cache, then
241
+ /// returns the cached value of [f] ([param1] ).
242
+ R memoized1 <R , A >(R Function (A ) f, A param1) {
243
+ _HashableList key = new _HashableList ([f, param1]);
244
+ return _memoizationTable.putIfAbsent (key, () => f (param1));
245
+ }
246
+
247
+ /// Calls and caches the return value of [f] ([param1] , [param2] ) if not in the
248
+ /// cache, then returns the cached value of [f] ([param1] , [param2] ).
249
+ R memoized2 <R , A , B >(R Function (A , B ) f, A param1, B param2) {
250
+ _HashableList key = new _HashableList ([f, param1, param2]);
251
+ return _memoizationTable.putIfAbsent (key, () => f (param1, param2));
252
+ }
253
+
254
+ /// Calls and caches the return value of [f] ([param1] , [param2] , [param3] ) if
255
+ /// not in the cache, then returns the cached value of [f] ([param1] ,
256
+ /// [param2] , [param3] ).
257
+ R memoized3 <R , A , B , C >(R Function (A , B , C ) f, A param1, B param2, C param3) {
258
+ _HashableList key = new _HashableList ([f, param1, param2, param3]);
259
+ return _memoizationTable.putIfAbsent (key, () => f (param1, param2, param3));
260
+ }
261
+
262
+ /// Calls and caches the return value of [f] ([param1] , [param2] , [param3] ,
263
+ /// [param4] ) if not in the cache, then returns the cached value of
264
+ /// [f] ([param1] , [param2] , [param3] , [param4] ).
265
+ R memoized4 <R , A , B , C , D >(
266
+ R Function (A , B , C , D ) f, A param1, B param2, C param3, D param4) {
267
+ _HashableList key = new _HashableList ([f, param1, param2, param3, param4]);
268
+ return _memoizationTable.putIfAbsent (
269
+ key, () => f (param1, param2, param3, param4));
270
+ }
271
+
272
+ /// Calls and caches the return value of [f] ([param1] , [param2] , [param3] ,
273
+ /// [param4] , [param5] ) if not in the cache, then returns the cached value of [f] (
274
+ /// [param1] , [param2] , [param3] , [param4] , [param5] ).
275
+ R memoized5 <R , A , B , C , D , E >(R Function (A , B , C , D , E ) f, A param1, B param2,
276
+ C param3, D param4, E param5) {
277
+ _HashableList key =
278
+ new _HashableList ([f, param1, param2, param3, param4, param5]);
279
+ return _memoizationTable.putIfAbsent (
280
+ key, () => f (param1, param2, param3, param4, param5));
281
+ }
282
+
283
+ /// Calls and caches the return value of [f] ([param1] , [param2] , [param3] ,
284
+ /// [param4] , [param5] , [param6] ) if not in the cache, then returns the cached
285
+ /// value of [f] ([param1] , [param2] , [param3] , [param4] , [param5] , [param6] ).
286
+ R memoized6 <R , A , B , C , D , E , F >(R Function (A , B , C , D , E , F ) f, A param1,
287
+ B param2, C param3, D param4, E param5, F param6) {
288
+ _HashableList key =
289
+ new _HashableList ([f, param1, param2, param3, param4, param5, param6]);
290
+ return _memoizationTable.putIfAbsent (
291
+ key, () => f (param1, param2, param3, param4, param5, param6));
292
+ }
293
+
294
+ /// Calls and caches the return value of [f] ([param1] , [param2] , [param3] ,
295
+ /// [param4] , [param5] , [param6] , [param7] ) if not in the cache, then returns
296
+ /// the cached value of [f] ([param1] , [param2] , [param3] , [param4] , [param5] ,
297
+ /// [param6] , [param7] ).
298
+ R memoized7 <R , A , B , C , D , E , F , G >(R Function (A , B , C , D , E , F , G ) f,
299
+ A param1, B param2, C param3, D param4, E param5, F param6, G param7) {
300
+ _HashableList key = new _HashableList (
301
+ [f, param1, param2, param3, param4, param5, param6, param7]);
302
+ return _memoizationTable.putIfAbsent (
303
+ key, () => f (param1, param2, param3, param4, param5, param6, param7));
304
+ }
305
+
306
+ /// Calls and caches the return value of [f] ([param1] , [param2] , [param3] ,
307
+ /// [param4] , [param5] , [param6] , [param7] , [param8] ) if not in the cache,
308
+ /// then returns the cached value of [f] ([param1] , [param2] , [param3] ,
309
+ /// [param4] , [param5] , [param6] , [param7] , [param8] ).
310
+ R memoized8 <R , A , B , C , D , E , F , G , H >(
311
+ R Function (A , B , C , D , E , F , G , H ) f,
312
+ A param1,
313
+ B param2,
314
+ C param3,
315
+ D param4,
316
+ E param5,
317
+ F param6,
318
+ G param7,
319
+ H param8) {
320
+ _HashableList key = new _HashableList (
321
+ [f, param1, param2, param3, param4, param5, param6, param7, param8]);
322
+ return _memoizationTable.putIfAbsent (
323
+ key,
324
+ () =>
325
+ f (param1, param2, param3, param4, param5, param6, param7, param8));
326
+ }
327
+ }
0 commit comments