FrequencyTrie.java

1
/*******************************************************************************
2
 * Copyright (C) 2026, Leo Galambos
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 *
11
 * 2. Redistributions in binary form must reproduce the above copyright notice,
12
 *    this list of conditions and the following disclaimer in the documentation
13
 *    and/or other materials provided with the distribution.
14
 *
15
 * 3. Neither the name of the copyright holder nor the names of its contributors
16
 *    may be used to endorse or promote products derived from this software
17
 *    without specific prior written permission.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
 * POSSIBILITY OF SUCH DAMAGE.
30
 ******************************************************************************/
31
package org.egothor.stemmer;
32
33
import java.io.DataInputStream;
34
import java.io.DataOutputStream;
35
import java.io.IOException;
36
import java.io.InputStream;
37
import java.io.OutputStream;
38
import java.nio.charset.StandardCharsets;
39
import java.security.MessageDigest;
40
import java.security.NoSuchAlgorithmException;
41
import java.util.ArrayList;
42
import java.util.Arrays;
43
import java.util.Collections;
44
import java.util.IdentityHashMap;
45
import java.util.LinkedHashMap;
46
import java.util.List;
47
import java.util.Locale;
48
import java.util.Map;
49
import java.util.Objects;
50
import java.util.function.IntFunction;
51
import java.util.logging.Level;
52
import java.util.logging.Logger;
53
54
import org.egothor.stemmer.trie.CompiledNode;
55
import org.egothor.stemmer.trie.LocalValueSummary;
56
import org.egothor.stemmer.trie.MutableNode;
57
import org.egothor.stemmer.trie.ReducedNode;
58
import org.egothor.stemmer.trie.ReductionContext;
59
import org.egothor.stemmer.trie.ReductionSignature;
60
61
/**
62
 * Read-only trie mapping {@link String} keys to one or more values with
63
 * frequency tracking.
64
 *
65
 * <p>
66
 * A key may be associated with multiple values. Each value keeps the number of
67
 * times it was inserted during the build phase. The method {@link #get(String)}
68
 * returns the locally most frequent value stored at the terminal node of the
69
 * supplied key, while {@link #getAll(String)} returns all locally stored values
70
 * ordered by descending frequency.
71
 *
72
 * <p>
73
 * If multiple values have the same local frequency, their ordering is
74
 * deterministic. The preferred value is selected by the following tie-breaking
75
 * rules, in order:
76
 * <ol>
77
 * <li>shorter {@link String} representation wins, based on
78
 * {@code value.toString()}</li>
79
 * <li>if the lengths are equal, lexicographically lower {@link String}
80
 * representation wins</li>
81
 * <li>if the textual representations are still equal, first-seen insertion
82
 * order remains stable</li>
83
 * </ol>
84
 *
85
 * <p>
86
 * Values may be stored at any trie node, including internal nodes and leaf
87
 * nodes. Therefore, reduction and canonicalization always operate on both the
88
 * node-local terminal values and the structure of all descendant edges.
89
 *
90
 * @param <V> value type
91
 */
92
@SuppressWarnings({ "PMD.CyclomaticComplexity", "PMD.CouplingBetweenObjects" })
93
public final class FrequencyTrie<V> {
94
95
    /**
96
     * Logger of this class.
97
     */
98
    private static final Logger LOGGER = Logger.getLogger(FrequencyTrie.class.getName());
99
100
    /**
101
     * Domain separator used by the trie fingerprint canonical input.
102
     */
103
    private static final String FINGERPRINT_DOMAIN = "RADIXOR-FREQUENCY-TRIE-FINGERPRINT";
104
105
    /**
106
     * Version of the canonical fingerprint input format.
107
     */
108
    private static final int FINGERPRINT_FORMAT_VERSION = 2;
109
110
    /**
111
     * Root node of the compiled read-only trie.
112
     */
113
    private final CompiledNode<V> root;
114
115
    /**
116
     * Metadata persisted together with this trie.
117
     */
118
    private final TrieMetadata metadata;
119
120
    /**
121
     * Canonical SHA-256 fingerprint bytes. The internal array is never exposed
122
     * directly to callers.
123
     */
124
    private final byte[] fingerprintBytes;
125
126
    /**
127
     * Cached traversal direction used for key lookup.
128
     */
129
    private final WordTraversalDirection lookupTraversalDirection;
130
131
    /**
132
     * Whether lookups require lowercase normalization.
133
     */
134
    private final boolean lowercasesLookupKeys;
135
136
    /**
137
     * Whether lookups require diacritic stripping.
138
     */
139
    private final boolean removeDiacritics;
140
141
    /**
142
     * Shared empty array instance for empty lookup results from
143
     * {@link #getAll(String)}.
144
     */
145
    private final V[] emptyValues;
146
147
    /**
148
     * Binary format magic header.
149
     */
150
    private static final int STREAM_MAGIC = 0x45475452;
151
152
    /**
153
     * Minimum supported stream version constant retained for explicit range checks.
154
     */
155
    private static final int MIN_STREAM_VERSION = 1;
156
157
    /**
158
     * Number of stored values for which {@link #getEntries(String)} can return an
159
     * empty result.
160
     */
161
    private static final int NO_VALUE_COUNT = 0;
162
163
    /**
164
     * Number of stored values for which {@link #getEntries(String)} can use a
165
     * one-item immutable list special case.
166
     */
167
    private static final int SINGLE_VALUE_COUNT = 1;
168
169
    /**
170
     * Binary format version.
171
     */
172
    private static final int STREAM_VERSION = 6;
173
174
    /**
175
     * Version where traversal-direction ordinal is persisted.
176
     */
177
    private static final int TRAVERSAL_VERSION = 2;
178
179
    /**
180
     * Version where compact reduction metadata is persisted.
181
     */
182
    private static final int REDUCTION_VERSION = 3;
183
184
    /**
185
     * Version where case-processing mode ordinal is persisted.
186
     */
187
    private static final int CASE_VERSION = 4;
188
189
    /**
190
     * Version where the persisted metadata switched to a text block.
191
     */
192
    private static final int TEXT_METADATA_VERSION = 5;
193
194
    /**
195
     * Version where contracted accepting nodes are persisted.
196
     */
197
    private static final int ACCEPTING_NODE_VERSION = 6;
198
199
    /**
200
     * Argument name for lookup keys.
201
     */
202
    private static final String ARG_KEY = "key";
203
204
    /**
205
     * Default dense child lookup span in code points used when materializing
206
     * compiled nodes without an explicit override.
207
     * <p>
208
     * Increasing this value increases the chance of direct array indexing for child
209
     * lookup at runtime at the cost of per-node dense table memory for compact
210
     * character spans.
211
     * </p>
212
     */
213
    public static final int DEFAULT_MAX_EXPANDED_INDEX = 512;
214
215
    /**
216
     * Returns the current persisted binary stream format version.
217
     *
218
     * <p>
219
     * This method exists so other components can construct {@link TrieMetadata}
220
     * instances aligned with the currently written binary format without
221
     * duplicating constants.
222
     * </p>
223
     *
224
     * @return current trie stream format version
225
     */
226
    public static int currentFormatVersion() {
227 1 1. currentFormatVersion : replaced int return with 0 for org/egothor/stemmer/FrequencyTrie::currentFormatVersion → KILLED
        return STREAM_VERSION;
228
    }
229
230
    /**
231
     * Receives trie values during visitor-style lookup.
232
     *
233
     * <p>
234
     * Implementations are caller-owned and are not retained by the trie. Returning
235
     * {@code false} stops iteration after the current callback.
236
     * </p>
237
     *
238
     * @param <V> value type
239
     */
240
    @FunctionalInterface
241
    public interface EntrySink<V> {
242
243
        /**
244
         * Accepts one ordered local value.
245
         *
246
         * @param value stored value
247
         * @param count stored local occurrence count
248
         * @param rank  zero-based rank in deterministic local ordering
249
         * @return {@code true} to continue iteration, {@code false} to stop
250
         */
251
        boolean accept(V value, int count, int rank);
252
    }
253
254
    /**
255
     * Creates a new compiled trie instance.
256
     *
257
     * @param arrayFactory array factory
258
     * @param root         compiled root node
259
     * @param metadata     trie metadata describing lookup and persistence semantics
260
     * @throws NullPointerException if any argument is {@code null}
261
     */
262
    private FrequencyTrie(final IntFunction<V[]> arrayFactory, final CompiledNode<V> root,
263
            final TrieMetadata metadata) {
264
        this.root = Objects.requireNonNull(root, "root");
265
        this.metadata = Objects.requireNonNull(metadata, "metadata");
266
        this.fingerprintBytes = computeFingerprintBytes(root, metadata);
267
        this.lookupTraversalDirection = metadata.traversalDirection();
268 1 1. <init> : negated conditional → KILLED
        this.lowercasesLookupKeys = metadata.caseProcessingMode() == CaseProcessingMode.LOWERCASE_WITH_LOCALE_ROOT;
269 1 1. <init> : negated conditional → KILLED
        this.removeDiacritics = metadata.diacriticProcessingMode() == DiacriticProcessingMode.REMOVE;
270
        this.emptyValues = arrayFactory.apply(0);
271
    }
272
273
    /**
274
     * Creates a trie from an already compiled root.
275
     *
276
     * @param arrayFactory array factory
277
     * @param root         compiled root
278
     * @param metadata     trie metadata
279
     * @param <V>          value type
280
     * @return trie instance
281
     */
282
    /* default */ static <V> FrequencyTrie<V> fromCompiled(final IntFunction<V[]> arrayFactory,
283
            final CompiledNode<V> root,
284
            final TrieMetadata metadata) {
285 1 1. fromCompiled : replaced return value with null for org/egothor/stemmer/FrequencyTrie::fromCompiled → KILLED
        return new FrequencyTrie<>(arrayFactory, root, metadata);
286
    }
287
288
    /**
289
     * Returns the most frequent value stored at the node addressed by the supplied
290
     * key.
291
     *
292
     * <p>
293
     * If multiple values have the same local frequency, the returned value is
294
     * selected deterministically by shorter {@code toString()} value first, then by
295
     * lexicographically lower {@code toString()}, and finally by stable first-seen
296
     * order.
297
     *
298
     * <p>
299
     * The supplied key is normalized according to persisted
300
     * {@link TrieMetadata#caseProcessingMode()} before traversal.
301
     * 
302
     * @param key key to resolve
303
     * @return most frequent value, or {@code null} if the key does not exist or no
304
     *         value is stored at the addressed node
305
     * @throws NullPointerException if {@code key} is {@code null}
306
     */
307
    public V get(final String key) {
308
        Objects.requireNonNull(key, ARG_KEY);
309
        final CompiledNode<V> node = findNode(normalizeLookupKey(key));
310 1 1. get : negated conditional → KILLED
        if (node == null) {
311
            return null;
312
        }
313
        final V[] orderedValues = node.orderedValues();
314 1 1. get : negated conditional → KILLED
        if (orderedValues.length == 0) {
315
            return null;
316
        }
317 1 1. get : replaced return value with null for org/egothor/stemmer/FrequencyTrie::get → KILLED
        return orderedValues[0];
318
    }
319
320
    /**
321
     * Returns the preferred value for an already-normalized key.
322
     *
323
     * <p>
324
     * This method bypasses {@link TrieMetadata#caseProcessingMode()} and
325
     * {@link TrieMetadata#diacriticProcessingMode()}. Callers must supply input
326
     * normalized exactly as required by this trie's metadata. It is intended for
327
     * hot paths where normalization is guaranteed by an upstream tokenizer or
328
     * benchmark corpus and repeated lookup-time normalization would be redundant.
329
     * </p>
330
     *
331
     * @param key already-normalized key to resolve
332
     * @return most frequent value, or {@code null} if the key does not exist or no
333
     *         value is stored at the addressed node
334
     * @throws NullPointerException if {@code key} is {@code null}
335
     */
336
    public V getNormalized(final CharSequence key) {
337
        Objects.requireNonNull(key, ARG_KEY);
338
        final CompiledNode<V> node = findNode(key);
339 1 1. getNormalized : negated conditional → KILLED
        if (node == null) {
340
            return null;
341
        }
342
        final V[] orderedValues = node.orderedValues();
343 1 1. getNormalized : negated conditional → KILLED
        if (orderedValues.length == 0) {
344
            return null;
345
        }
346 1 1. getNormalized : replaced return value with null for org/egothor/stemmer/FrequencyTrie::getNormalized → KILLED
        return orderedValues[0];
347
    }
348
349
    /**
350
     * Returns the preferred value for an already-normalized {@link String} key.
351
     *
352
     * <p>
353
     * This overload keeps high-volume string lookup on a monomorphic path and
354
     * avoids the {@link CharSequence} dispatch used by the general overload.
355
     * Callers must supply input normalized exactly as required by this trie's
356
     * metadata.
357
     * </p>
358
     *
359
     * @param key already-normalized key to resolve
360
     * @return most frequent value, or {@code null} if the key does not exist or no
361
     *         value is stored at the addressed node
362
     * @throws NullPointerException if {@code key} is {@code null}
363
     */
364
    public V getNormalizedString(final String key) {
365
        Objects.requireNonNull(key, ARG_KEY);
366
        final CompiledNode<V> node = findNode(key);
367 1 1. getNormalizedString : negated conditional → KILLED
        if (node == null) {
368
            return null;
369
        }
370
        final V[] orderedValues = node.orderedValues();
371 1 1. getNormalizedString : negated conditional → KILLED
        if (orderedValues.length == 0) {
372
            return null;
373
        }
374 1 1. getNormalizedString : replaced return value with null for org/egothor/stemmer/FrequencyTrie::getNormalizedString → KILLED
        return orderedValues[0];
375
    }
376
377
    /**
378
     * Returns all values stored at the node addressed by the supplied key, ordered
379
     * by descending frequency.
380
     *
381
     * <p>
382
     * If multiple values have the same local frequency, the ordering is
383
     * deterministic by shorter {@code toString()} value first, then by
384
     * lexicographically lower {@code toString()}, and finally by stable first-seen
385
     * order.
386
     *
387
     * <p>
388
     * The returned array is a defensive copy.
389
     *
390
     * <p>
391
     * The supplied key is normalized according to persisted
392
     * {@link TrieMetadata#caseProcessingMode()} before traversal.
393
     *
394
     * @param key key to resolve
395
     * @return all values stored at the addressed node, ordered by descending
396
     *         frequency; returns an empty array if the key does not exist or no
397
     *         value is stored at the addressed node
398
     * @throws NullPointerException if {@code key} is {@code null}
399
     */
400
    @SuppressWarnings("PMD.MethodReturnsInternalArray")
401
    public V[] getAll(final String key) {
402
        Objects.requireNonNull(key, ARG_KEY);
403
        final CompiledNode<V> node = findNode(normalizeLookupKey(key));
404 1 1. getAll : negated conditional → KILLED
        if (node == null) {
405 1 1. getAll : replaced return value with null for org/egothor/stemmer/FrequencyTrie::getAll → KILLED
            return this.emptyValues;
406
        }
407
        final V[] orderedValues = node.orderedValues();
408 1 1. getAll : negated conditional → KILLED
        if (orderedValues.length == 0) {
409 1 1. getAll : replaced return value with null for org/egothor/stemmer/FrequencyTrie::getAll → SURVIVED
            return this.emptyValues;
410
        }
411 1 1. getAll : replaced return value with null for org/egothor/stemmer/FrequencyTrie::getAll → KILLED
        return Arrays.copyOf(orderedValues, orderedValues.length);
412
    }
413
414
    /**
415
     * Returns all values stored at the node addressed by the supplied key together
416
     * with their occurrence counts, ordered by the same rules as
417
     * {@link #getAll(String)}.
418
     *
419
     * <p>
420
     * The returned list is aligned with the arrays returned by
421
     * {@link #getAll(String)} and the internal compiled count representation.
422
     *
423
     * <p>
424
     * The returned list is immutable.
425
     *
426
     * <p>
427
     * In reduction modes that merge semantically equivalent subtrees, the returned
428
     * counts may be aggregated across multiple original build-time nodes that were
429
     * reduced into the same canonical compiled node.
430
     *
431
     * @param key key to resolve
432
     * @return immutable ordered list of value-count entries; returns an empty list
433
     *         if the key does not exist or no value is stored at the addressed node
434
     * @throws NullPointerException if {@code key} is {@code null}
435
     */
436
    public List<ValueCount<V>> getEntries(final String key) {
437
        Objects.requireNonNull(key, ARG_KEY);
438
        final CompiledNode<V> node = findNode(normalizeLookupKey(key));
439 1 1. getEntries : negated conditional → KILLED
        if (node == null) {
440
            return List.of();
441
        }
442
443
        final V[] orderedValues = node.orderedValues();
444
        final int valueCount = orderedValues.length;
445 1 1. getEntries : negated conditional → KILLED
        if (valueCount == NO_VALUE_COUNT) {
446
            return List.of();
447
        }
448
449 1 1. getEntries : negated conditional → KILLED
        if (valueCount == SINGLE_VALUE_COUNT) {
450 1 1. getEntries : replaced return value with Collections.emptyList for org/egothor/stemmer/FrequencyTrie::getEntries → KILLED
            return List.of(new ValueCount<>(orderedValues[0], node.orderedCounts()[0]));
451
        }
452
453
        final int[] orderedCounts = node.orderedCounts();
454
        final List<ValueCount<V>> entries = new ArrayList<>(valueCount);
455 2 1. getEntries : changed conditional boundary → KILLED
2. getEntries : negated conditional → KILLED
        for (int index = 0; index < valueCount; index++) {
456
            entries.add(new ValueCount<>(orderedValues[index], orderedCounts[index]));
457
        }
458 1 1. getEntries : replaced return value with Collections.emptyList for org/egothor/stemmer/FrequencyTrie::getEntries → KILLED
        return Collections.unmodifiableList(entries);
459
    }
460
461
    /**
462
     * Visits all values stored at the node addressed by an already-normalized
463
     * {@code char[]} key slice.
464
     *
465
     * <p>
466
     * This method bypasses {@link TrieMetadata#caseProcessingMode()} and
467
     * {@link TrieMetadata#diacriticProcessingMode()}. The caller must provide input
468
     * normalized exactly as required by this trie's metadata. The trie is immutable
469
     * and thread-safe for concurrent reads; the supplied sink is caller-owned and
470
     * is not retained.
471
     * </p>
472
     *
473
     * @param key        normalized key storage
474
     * @param offset     first character offset
475
     * @param length     number of characters to read
476
     * @param sink       value sink
477
     * @param maxResults maximum number of results to visit
478
     * @return number of visited values
479
     * @throws NullPointerException      if {@code key} or {@code sink} is
480
     *                                   {@code null}
481
     * @throws IndexOutOfBoundsException if the key slice is invalid
482
     * @throws IllegalArgumentException  if {@code maxResults} is negative
483
     */
484
    public int getAllNormalized(final char[] key, final int offset, final int length, final EntrySink<? super V> sink,
485
            final int maxResults) {
486
        Objects.requireNonNull(key, ARG_KEY);
487
        Objects.requireNonNull(sink, "sink");
488
        Objects.checkFromIndexSize(offset, length, key.length);
489 1 1. getAllNormalized : removed call to org/egothor/stemmer/FrequencyTrie::validateMaxResults → SURVIVED
        validateMaxResults(maxResults);
490 1 1. getAllNormalized : negated conditional → KILLED
        if (maxResults == 0) {
491
            return 0;
492
        }
493 1 1. getAllNormalized : replaced int return with 0 for org/egothor/stemmer/FrequencyTrie::getAllNormalized → KILLED
        return visitNode(findNode(key, offset, length), sink, maxResults);
494
    }
495
496
    /**
497
     * Visits all values stored at the node addressed by an already-normalized
498
     * character sequence.
499
     *
500
     * @param key        normalized key
501
     * @param sink       value sink
502
     * @param maxResults maximum number of results to visit
503
     * @return number of visited values
504
     * @throws NullPointerException     if {@code key} or {@code sink} is
505
     *                                  {@code null}
506
     * @throws IllegalArgumentException if {@code maxResults} is negative
507
     * @see #getAllNormalized(char[], int, int, EntrySink, int)
508
     */
509
    public int getAllNormalized(final CharSequence key, final EntrySink<? super V> sink, final int maxResults) {
510
        Objects.requireNonNull(key, ARG_KEY);
511
        Objects.requireNonNull(sink, "sink");
512 1 1. getAllNormalized : removed call to org/egothor/stemmer/FrequencyTrie::validateMaxResults → KILLED
        validateMaxResults(maxResults);
513 1 1. getAllNormalized : negated conditional → KILLED
        if (maxResults == 0) {
514
            return 0;
515
        }
516 1 1. getAllNormalized : replaced int return with 0 for org/egothor/stemmer/FrequencyTrie::getAllNormalized → KILLED
        return visitNode(findNode(key), sink, maxResults);
517
    }
518
519
    /**
520
     * Visits the first value stored at the node addressed by an already-normalized
521
     * {@code char[]} key slice.
522
     *
523
     * @param key    normalized key storage
524
     * @param offset first character offset
525
     * @param length number of characters to read
526
     * @param sink   value sink
527
     * @return {@code true} when a value was visited, otherwise {@code false}
528
     * @see #getAllNormalized(char[], int, int, EntrySink, int)
529
     */
530
    public boolean getFirstNormalized(final char[] key, final int offset, final int length,
531
            final EntrySink<? super V> sink) {
532 2 1. getFirstNormalized : replaced boolean return with true for org/egothor/stemmer/FrequencyTrie::getFirstNormalized → NO_COVERAGE
2. getFirstNormalized : negated conditional → NO_COVERAGE
        return getAllNormalized(key, offset, length, sink, 1) == 1;
533
    }
534
535
    /**
536
     * Visits the first value stored at the node addressed by an already-normalized
537
     * character sequence.
538
     *
539
     * @param key  normalized key
540
     * @param sink value sink
541
     * @return {@code true} when a value was visited, otherwise {@code false}
542
     * @see #getAllNormalized(CharSequence, EntrySink, int)
543
     */
544
    public boolean getFirstNormalized(final CharSequence key, final EntrySink<? super V> sink) {
545 2 1. getFirstNormalized : negated conditional → KILLED
2. getFirstNormalized : replaced boolean return with true for org/egothor/stemmer/FrequencyTrie::getFirstNormalized → KILLED
        return getAllNormalized(key, sink, 1) == 1;
546
    }
547
548
    /**
549
     * Visits all values stored at the node addressed by the supplied key, applying
550
     * metadata-driven lookup normalization when required.
551
     *
552
     * <p>
553
     * This method preserves the same lookup normalization semantics as
554
     * {@link #getAll(String)}. It may allocate when metadata requires lowercase or
555
     * diacritic normalization.
556
     * </p>
557
     *
558
     * @param key        key to resolve
559
     * @param sink       value sink
560
     * @param maxResults maximum number of results to visit
561
     * @return number of visited values
562
     */
563
    public int getAll(final CharSequence key, final EntrySink<? super V> sink, final int maxResults) {
564
        Objects.requireNonNull(key, ARG_KEY);
565
        Objects.requireNonNull(sink, "sink");
566 1 1. getAll : removed call to org/egothor/stemmer/FrequencyTrie::validateMaxResults → KILLED
        validateMaxResults(maxResults);
567 1 1. getAll : negated conditional → KILLED
        if (maxResults == 0) {
568
            return 0;
569
        }
570
        final CharSequence normalized = normalizeLookupKey(key);
571 1 1. getAll : replaced int return with 0 for org/egothor/stemmer/FrequencyTrie::getAll → KILLED
        return visitNode(findNode(normalized), sink, maxResults);
572
    }
573
574
    /**
575
     * Visits the first value stored at the node addressed by the supplied key,
576
     * applying metadata-driven lookup normalization when required.
577
     *
578
     * @param key  key to resolve
579
     * @param sink value sink
580
     * @return {@code true} when a value was visited, otherwise {@code false}
581
     * @see #getAll(CharSequence, EntrySink, int)
582
     */
583
    public boolean getFirst(final CharSequence key, final EntrySink<? super V> sink) {
584 2 1. getFirst : replaced boolean return with true for org/egothor/stemmer/FrequencyTrie::getFirst → SURVIVED
2. getFirst : negated conditional → KILLED
        return getAll(key, sink, 1) == 1;
585
    }
586
587
    /**
588
     * Returns the logical key traversal direction used by this trie.
589
     *
590
     * <p>
591
     * The same direction must be used when reconstructing mutable builders or when
592
     * applying patch commands that were generated against keys stored in this trie.
593
     * </p>
594
     *
595
     * @return logical key traversal direction
596
     */
597
    public WordTraversalDirection traversalDirection() {
598 1 1. traversalDirection : replaced return value with null for org/egothor/stemmer/FrequencyTrie::traversalDirection → KILLED
        return this.metadata.traversalDirection();
599
    }
600
601
    /**
602
     * Returns immutable persisted metadata associated with this trie.
603
     *
604
     * @return trie metadata
605
     */
606
    public TrieMetadata metadata() {
607 1 1. metadata : replaced return value with null for org/egothor/stemmer/FrequencyTrie::metadata → KILLED
        return this.metadata;
608
    }
609
610
    /**
611
     * Returns the deterministic SHA-256 fingerprint of this trie.
612
     *
613
     * <p>
614
     * The fingerprint is a canonical model identity, not a Java object identity. It
615
     * includes a fingerprint-domain marker, the fingerprint input format version,
616
     * persisted metadata, and the complete compiled-node structure reachable from
617
     * the root, including edges, child references, local values, and local counts.
618
     * </p>
619
     *
620
     * <p>
621
     * The returned value is stable across JVM runs for equivalent trie content and
622
     * metadata. It does not include object identity, memory layout, runtime cache
623
     * state, absolute file paths, timestamps, or other process-local state.
624
     * </p>
625
     *
626
     * @return 64-character lowercase hexadecimal SHA-256 fingerprint
627
     */
628
    public String getFingerprint() {
629 1 1. getFingerprint : replaced return value with "" for org/egothor/stemmer/FrequencyTrie::getFingerprint → KILLED
        return toLowerHex(this.fingerprintBytes);
630
    }
631
632
    /**
633
     * Returns a defensive copy of the raw SHA-256 fingerprint bytes.
634
     *
635
     * <p>
636
     * The returned array has length {@code 32}. Mutating it does not affect this
637
     * trie.
638
     * </p>
639
     *
640
     * @return defensive copy of the 32-byte SHA-256 fingerprint
641
     */
642
    public byte[] copyFingerprintBytes() {
643 1 1. copyFingerprintBytes : replaced return value with null for org/egothor/stemmer/FrequencyTrie::copyFingerprintBytes → KILLED
        return Arrays.copyOf(this.fingerprintBytes, this.fingerprintBytes.length);
644
    }
645
646
    private static <V> byte[] computeFingerprintBytes(final CompiledNode<V> root, final TrieMetadata metadata) {
647
        final MessageDigest messageDigest = newSha256Digest();
648 1 1. computeFingerprintBytes : removed call to org/egothor/stemmer/FrequencyTrie::updateUtf8 → SURVIVED
        updateUtf8(messageDigest, FINGERPRINT_DOMAIN);
649 1 1. computeFingerprintBytes : removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
        updateInt(messageDigest, FINGERPRINT_FORMAT_VERSION);
650 1 1. computeFingerprintBytes : removed call to org/egothor/stemmer/FrequencyTrie::updateUtf8 → SURVIVED
        updateUtf8(messageDigest, metadata.toTextBlock());
651
652
        final Map<CompiledNode<V>, Integer> nodeIds = new IdentityHashMap<>();
653
        final List<CompiledNode<V>> orderedNodes = new ArrayList<>();
654 1 1. computeFingerprintBytes : removed call to org/egothor/stemmer/FrequencyTrie::assignNodeIds → KILLED
        assignNodeIds(root, nodeIds, orderedNodes);
655
656 1 1. computeFingerprintBytes : removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
        updateInt(messageDigest, nodeIds.get(root));
657 1 1. computeFingerprintBytes : removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
        updateInt(messageDigest, orderedNodes.size());
658
        for (CompiledNode<V> node : orderedNodes) {
659 1 1. computeFingerprintBytes : removed call to org/egothor/stemmer/FrequencyTrie::updateNodeFingerprint → KILLED
            updateNodeFingerprint(messageDigest, node, nodeIds);
660
        }
661 1 1. computeFingerprintBytes : replaced return value with null for org/egothor/stemmer/FrequencyTrie::computeFingerprintBytes → KILLED
        return messageDigest.digest();
662
    }
663
664
    /**
665
     * Returns the root node mainly for diagnostics and tests within the package.
666
     *
667
     * @return compiled root node
668
     */
669
    /* default */ CompiledNode<V> root() {
670 1 1. root : replaced return value with null for org/egothor/stemmer/FrequencyTrie::root → KILLED
        return this.root;
671
    }
672
673
    /**
674
     * Writes this compiled trie to the supplied output stream.
675
     *
676
     * <p>
677
     * The binary format is versioned and preserves canonical shared compiled nodes,
678
     * therefore the serialized representation remains compact even for tries
679
     * reduced by subtree merging.
680
     *
681
     * <p>
682
     * The supplied codec is responsible for persisting individual values of type
683
     * {@code V}.
684
     *
685
     * @param outputStream target output stream
686
     * @param valueCodec   codec used to write values
687
     * @throws NullPointerException if any argument is {@code null}
688
     * @throws IOException          if writing fails
689
     */
690
    public void writeTo(final OutputStream outputStream, final ValueStreamCodec<V> valueCodec) throws IOException {
691
        Objects.requireNonNull(outputStream, "outputStream");
692
        Objects.requireNonNull(valueCodec, "valueCodec");
693
694
        final DataOutputStream dataOutput; // NOPMD
695 1 1. writeTo : negated conditional → KILLED
        if (outputStream instanceof DataOutputStream) {
696
            dataOutput = (DataOutputStream) outputStream;
697
        } else {
698
            dataOutput = new DataOutputStream(outputStream);
699
        }
700
701
        final Map<CompiledNode<V>, Integer> nodeIds = new IdentityHashMap<>();
702
        final List<CompiledNode<V>> orderedNodes = new ArrayList<>();
703 1 1. writeTo : removed call to org/egothor/stemmer/FrequencyTrie::assignNodeIds → KILLED
        assignNodeIds(this.root, nodeIds, orderedNodes);
704
705
        if (LOGGER.isLoggable(Level.FINE)) {
706
            LOGGER.log(Level.FINE, "Writing compiled trie with {0} canonical nodes.", orderedNodes.size());
707
        }
708
709 1 1. writeTo : removed call to java/io/DataOutputStream::writeInt → KILLED
        dataOutput.writeInt(STREAM_MAGIC);
710 1 1. writeTo : removed call to java/io/DataOutputStream::writeInt → KILLED
        dataOutput.writeInt(STREAM_VERSION);
711 1 1. writeTo : removed call to java/io/DataOutputStream::writeInt → KILLED
        dataOutput.writeInt(orderedNodes.size());
712 1 1. writeTo : removed call to java/io/DataOutputStream::writeInt → KILLED
        dataOutput.writeInt(nodeIds.get(this.root));
713 1 1. writeTo : removed call to org/egothor/stemmer/FrequencyTrie::writeMetadata → KILLED
        writeMetadata(dataOutput, this.metadata);
714
715
        for (CompiledNode<V> node : orderedNodes) {
716 1 1. writeTo : removed call to org/egothor/stemmer/FrequencyTrie::writeNode → KILLED
            writeNode(dataOutput, valueCodec, node, nodeIds);
717
        }
718
719 1 1. writeTo : removed call to java/io/DataOutputStream::flush → SURVIVED
        dataOutput.flush();
720
    }
721
722
    /**
723
     * Reads a compiled trie from the supplied input stream.
724
     *
725
     * <p>
726
     * The caller must provide the same value codec semantics that were used during
727
     * persistence as well as the array factory required for typed result arrays.
728
     *
729
     * @param inputStream  source input stream
730
     * @param arrayFactory factory used to create typed arrays
731
     * @param valueCodec   codec used to read values
732
     * @param <V>          value type
733
     * @return deserialized compiled trie
734
     * @throws NullPointerException if any argument is {@code null}
735
     * @throws IOException          if reading fails or the binary format is invalid
736
     */
737
    public static <V> FrequencyTrie<V> readFrom(final InputStream inputStream, final IntFunction<V[]> arrayFactory,
738
            final ValueStreamCodec<V> valueCodec) throws IOException {
739 1 1. readFrom : replaced return value with null for org/egothor/stemmer/FrequencyTrie::readFrom → KILLED
        return readFrom(inputStream, arrayFactory, valueCodec, -1);
740
    }
741
742
    /**
743
     * Reads a compiled trie from the supplied input stream, optionally overriding
744
     * dense child-index span configuration.
745
     * <p>
746
     * This setting is applied only while materializing the in-memory compiled
747
     * representation during load. It is not serialized in {@link TrieMetadata}, so
748
     * each load can independently choose its own runtime lookup trade-off.
749
     * </p>
750
     *
751
     * @param inputStream      source input stream
752
     * @param arrayFactory     array factory used to create typed arrays
753
     * @param valueCodec       codec used to read values
754
     * @param maxExpandedIndex dense lookup span override; zero disables dense
755
     *                         lookup, negative values use
756
     *                         {@link #DEFAULT_MAX_EXPANDED_INDEX}
757
     * @param <V>              value type
758
     * @return deserialized compiled trie
759
     * @throws NullPointerException if any argument is {@code null}
760
     * @throws IOException          if reading fails or the binary format is invalid
761
     */
762
    public static <V> FrequencyTrie<V> readFrom(final InputStream inputStream, final IntFunction<V[]> arrayFactory,
763
            final ValueStreamCodec<V> valueCodec, final int maxExpandedIndex) throws IOException {
764 1 1. readFrom : replaced return value with null for org/egothor/stemmer/FrequencyTrie::readFrom → KILLED
        return CompiledTrieReader.read(inputStream, arrayFactory, valueCodec, maxExpandedIndex);
765
    }
766
767
    /**
768
     * Writes persisted trie metadata.
769
     *
770
     * @param dataOutput output stream
771
     * @param metadata   metadata to serialize
772
     * @throws IOException if writing fails
773
     */
774
    private static void writeMetadata(final DataOutputStream dataOutput, final TrieMetadata metadata)
775
            throws IOException {
776 1 1. writeMetadata : removed call to java/io/DataOutputStream::writeUTF → KILLED
        dataOutput.writeUTF(metadata.toTextBlock());
777
    }
778
779
    /**
780
     * Returns the number of canonical compiled nodes reachable from the root.
781
     *
782
     * <p>
783
     * The returned value reflects the size of the final reduced immutable trie, not
784
     * the number of mutable build-time nodes inserted before reduction. Shared
785
     * canonical subtrees are counted only once.
786
     *
787
     * @return number of canonical compiled nodes in this trie
788
     */
789
    public int size() {
790
        final Map<CompiledNode<V>, Integer> nodeIds = new IdentityHashMap<>();
791
        final List<CompiledNode<V>> orderedNodes = new ArrayList<>();
792 1 1. size : removed call to org/egothor/stemmer/FrequencyTrie::assignNodeIds → KILLED
        assignNodeIds(this.root, nodeIds, orderedNodes);
793 1 1. size : replaced int return with 0 for org/egothor/stemmer/FrequencyTrie::size → KILLED
        return orderedNodes.size();
794
    }
795
796
    /**
797
     * Assigns deterministic identifiers to all canonical compiled nodes reachable
798
     * from the supplied root.
799
     *
800
     * @param node         current node
801
     * @param nodeIds      assigned node identifiers
802
     * @param orderedNodes ordered nodes in identifier order
803
     */
804
    private static <V> void assignNodeIds(final CompiledNode<V> node, final Map<CompiledNode<V>, Integer> nodeIds,
805
            final List<CompiledNode<V>> orderedNodes) {
806 1 1. assignNodeIds : negated conditional → KILLED
        if (nodeIds.containsKey(node)) {
807
            return;
808
        }
809
810
        final int nodeId = orderedNodes.size();
811
        nodeIds.put(node, nodeId);
812
        orderedNodes.add(node);
813
814
        for (CompiledNode<V> child : node.children()) {
815 1 1. assignNodeIds : removed call to org/egothor/stemmer/FrequencyTrie::assignNodeIds → KILLED
            assignNodeIds(child, nodeIds, orderedNodes);
816
        }
817
    }
818
819
    /**
820
     * Writes one compiled node.
821
     *
822
     * @param dataOutput output
823
     * @param valueCodec value codec
824
     * @param node       node to write
825
     * @param nodeIds    node identifiers
826
     * @throws IOException if writing fails
827
     */
828
    private static <V> void writeNode(final DataOutputStream dataOutput, final ValueStreamCodec<V> valueCodec,
829
            final CompiledNode<V> node, final Map<CompiledNode<V>, Integer> nodeIds) throws IOException {
830 1 1. writeNode : removed call to java/io/DataOutputStream::writeBoolean → KILLED
        dataOutput.writeBoolean(node.acceptsRemainingInput());
831 1 1. writeNode : removed call to java/io/DataOutputStream::writeInt → KILLED
        dataOutput.writeInt(node.edgeLabels().length);
832 2 1. writeNode : negated conditional → KILLED
2. writeNode : changed conditional boundary → KILLED
        for (int index = 0; index < node.edgeLabels().length; index++) {
833 1 1. writeNode : removed call to java/io/DataOutputStream::writeChar → KILLED
            dataOutput.writeChar(node.edgeLabels()[index]);
834
            final Integer childNodeId = nodeIds.get(node.children()[index]);
835 1 1. writeNode : negated conditional → KILLED
            if (childNodeId == null) {
836
                throw new IOException("Missing child node identifier during serialization.");
837
            }
838 1 1. writeNode : removed call to java/io/DataOutputStream::writeInt → KILLED
            dataOutput.writeInt(childNodeId);
839
        }
840
841 1 1. writeNode : removed call to java/io/DataOutputStream::writeInt → KILLED
        dataOutput.writeInt(node.orderedValues().length);
842 2 1. writeNode : negated conditional → KILLED
2. writeNode : changed conditional boundary → KILLED
        for (int index = 0; index < node.orderedValues().length; index++) {
843 1 1. writeNode : removed call to org/egothor/stemmer/FrequencyTrie$ValueStreamCodec::write → KILLED
            valueCodec.write(dataOutput, node.orderedValues()[index]);
844 1 1. writeNode : removed call to java/io/DataOutputStream::writeInt → KILLED
            dataOutput.writeInt(node.orderedCounts()[index]);
845
        }
846
    }
847
848
    private static MessageDigest newSha256Digest() {
849
        try {
850 1 1. newSha256Digest : replaced return value with null for org/egothor/stemmer/FrequencyTrie::newSha256Digest → KILLED
            return MessageDigest.getInstance("SHA-256");
851
        } catch (NoSuchAlgorithmException exception) {
852
            throw new IllegalStateException("SHA-256 digest is not available.", exception);
853
        }
854
    }
855
856
    private static <V> void updateNodeFingerprint(final MessageDigest messageDigest, final CompiledNode<V> node,
857
            final Map<CompiledNode<V>, Integer> nodeIds) {
858
        final char[] edgeLabels = node.edgeLabels();
859
        final CompiledNode<V>[] children = node.children();
860
        final V[] values = node.orderedValues();
861
        final int[] counts = node.orderedCounts();
862
863 2 1. updateNodeFingerprint : negated conditional → SURVIVED
2. updateNodeFingerprint : removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
        updateInt(messageDigest, node.acceptsRemainingInput() ? 1 : 0);
864 1 1. updateNodeFingerprint : removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
        updateInt(messageDigest, edgeLabels.length);
865
        for (char edgeLabel : edgeLabels) {
866 1 1. updateNodeFingerprint : removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
            updateInt(messageDigest, edgeLabel);
867
        }
868
        for (CompiledNode<V> child : children) {
869
            final Integer childNodeId = nodeIds.get(child);
870 1 1. updateNodeFingerprint : negated conditional → KILLED
            if (childNodeId == null) {
871
                throw new IllegalStateException("Missing child node identifier during trie fingerprinting.");
872
            }
873 1 1. updateNodeFingerprint : removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
            updateInt(messageDigest, childNodeId);
874
        }
875
876 1 1. updateNodeFingerprint : removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
        updateInt(messageDigest, values.length);
877
        for (V value : values) {
878 1 1. updateNodeFingerprint : removed call to org/egothor/stemmer/FrequencyTrie::updateUtf8 → SURVIVED
            updateUtf8(messageDigest, String.valueOf(value));
879
        }
880
        for (int count : counts) {
881 1 1. updateNodeFingerprint : removed call to org/egothor/stemmer/FrequencyTrie::updateInt → KILLED
            updateInt(messageDigest, count);
882
        }
883
    }
884
885
    private static void updateUtf8(final MessageDigest messageDigest, final String value) {
886
        final byte[] encoded = value.getBytes(StandardCharsets.UTF_8);
887 1 1. updateUtf8 : removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
        updateInt(messageDigest, encoded.length);
888 1 1. updateUtf8 : removed call to java/security/MessageDigest::update → SURVIVED
        messageDigest.update(encoded);
889
    }
890
891
    private static void updateInt(final MessageDigest messageDigest, final int value) {
892 2 1. updateInt : removed call to java/security/MessageDigest::update → SURVIVED
2. updateInt : Replaced Unsigned Shift Right with Shift Left → SURVIVED
        messageDigest.update((byte) (value >>> 24));
893 2 1. updateInt : removed call to java/security/MessageDigest::update → SURVIVED
2. updateInt : Replaced Unsigned Shift Right with Shift Left → SURVIVED
        messageDigest.update((byte) (value >>> 16));
894 2 1. updateInt : removed call to java/security/MessageDigest::update → SURVIVED
2. updateInt : Replaced Unsigned Shift Right with Shift Left → SURVIVED
        messageDigest.update((byte) (value >>> 8));
895 1 1. updateInt : removed call to java/security/MessageDigest::update → KILLED
        messageDigest.update((byte) value);
896
    }
897
898
    private static String toLowerHex(final byte[] digest) {
899 1 1. toLowerHex : Replaced integer multiplication with division → SURVIVED
        final StringBuilder builder = new StringBuilder(digest.length * 2);
900
        for (byte item : digest) {
901 3 1. toLowerHex : Replaced Unsigned Shift Right with Shift Left → KILLED
2. toLowerHex : Replaced bitwise AND with OR → KILLED
3. toLowerHex : Replaced bitwise AND with OR → KILLED
            builder.append(Character.forDigit((item >>> 4) & 0x0F, 16)).append(Character.forDigit(item & 0x0F, 16));
902
        }
903 1 1. toLowerHex : replaced return value with "" for org/egothor/stemmer/FrequencyTrie::toLowerHex → KILLED
        return builder.toString();
904
    }
905
906
    /**
907
     * Internal helper that materializes serialized trie data.
908
     *
909
     * <p>
910
     * Moving reader complexity into this helper keeps the public-facing class from
911
     * accumulating excessive class-level cyclomatic complexity while preserving the
912
     * same binary compatibility contract.
913
     * </p>
914
     */
915
    private static final class CompiledTrieReader {
916
917
        private static <V> FrequencyTrie<V> read(final InputStream inputStream, final IntFunction<V[]> arrayFactory,
918
                final ValueStreamCodec<V> valueCodec, final int maxExpandedIndex) throws IOException {
919
            Objects.requireNonNull(inputStream, "inputStream");
920
            Objects.requireNonNull(arrayFactory, "arrayFactory");
921
            Objects.requireNonNull(valueCodec, "valueCodec");
922 2 1. read : negated conditional → KILLED
2. read : changed conditional boundary → KILLED
            if (maxExpandedIndex < -1) {
923
                throw new IllegalArgumentException("maxExpandedIndex must be >= -1.");
924
            }
925
926
            final DataInputStream dataInput = wrapInputStream(inputStream);
927
            final int magic = dataInput.readInt();
928 1 1. read : negated conditional → KILLED
            if (magic != STREAM_MAGIC) {
929
                throw new IOException("Unsupported trie stream header: " + Integer.toHexString(magic));
930
            }
931
932
            final int version = dataInput.readInt();
933 4 1. read : changed conditional boundary → KILLED
2. read : changed conditional boundary → KILLED
3. read : negated conditional → KILLED
4. read : negated conditional → KILLED
            if (version < MIN_STREAM_VERSION || version > STREAM_VERSION) {
934
                throw new IOException("Unsupported trie stream version: " + version);
935
            }
936
937
            final int nodeCount = dataInput.readInt();
938 2 1. read : changed conditional boundary → SURVIVED
2. read : negated conditional → KILLED
            if (nodeCount < 0) {
939
                throw new IOException("Negative node count: " + nodeCount);
940
            }
941
942
            final int rootNodeId = dataInput.readInt();
943 4 1. read : negated conditional → KILLED
2. read : negated conditional → KILLED
3. read : changed conditional boundary → KILLED
4. read : changed conditional boundary → KILLED
            if (rootNodeId < 0 || rootNodeId >= nodeCount) {
944
                throw new IOException("Invalid root node id: " + rootNodeId);
945
            }
946
947
            final TrieMetadata sourceMetadata = readMetadata(dataInput, version);
948 2 1. read : negated conditional → KILLED
2. read : changed conditional boundary → KILLED
            final int effectiveMaxExpandedIndex = maxExpandedIndex >= 0 ? maxExpandedIndex : DEFAULT_MAX_EXPANDED_INDEX;
949
            final CompiledNode<V>[] nodes = readNodes(dataInput, arrayFactory, valueCodec, nodeCount,
950
                    effectiveMaxExpandedIndex, version);
951
            final CompiledNode<V> rootNode = nodes[rootNodeId];
952
953
            if (LOGGER.isLoggable(Level.FINE)) {
954
                LOGGER.log(Level.FINE, "Read compiled trie with {0} canonical nodes.", nodeCount);
955
            }
956
957 1 1. read : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::read → KILLED
            return new FrequencyTrie<>(arrayFactory, rootNode, sourceMetadata);
958
        }
959
960
        private static DataInputStream wrapInputStream(final InputStream inputStream) {
961 2 1. wrapInputStream : negated conditional → KILLED
2. wrapInputStream : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::wrapInputStream → KILLED
            return inputStream instanceof DataInputStream ? (DataInputStream) inputStream
962
                    : new DataInputStream(inputStream);
963
        }
964
965
        private static TrieMetadata readMetadata(final DataInputStream dataInput, final int version)
966
                throws IOException {
967 2 1. readMetadata : negated conditional → KILLED
2. readMetadata : changed conditional boundary → KILLED
            if (version >= TEXT_METADATA_VERSION) {
968 1 1. readMetadata : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readMetadata → KILLED
                return readTextMetadata(dataInput, version);
969
            }
970
971
            final WordTraversalDirection traversalDirection = readTraversalDirection(dataInput, version);
972 2 1. readMetadata : negated conditional → KILLED
2. readMetadata : changed conditional boundary → KILLED
            if (version < REDUCTION_VERSION) {
973 1 1. readMetadata : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readMetadata → KILLED
                return TrieMetadata.legacy(version, traversalDirection);
974
            }
975
976
            final ReductionSettings reductionSettings = readReductionSettings(dataInput);
977
            final DiacriticProcessingMode diacriticProcessingMode = readEnumByOrdinal(dataInput,
978
                    DiacriticProcessingMode.values(), "diacritic processing mode");
979 2 1. readMetadata : negated conditional → KILLED
2. readMetadata : changed conditional boundary → KILLED
            final CaseProcessingMode caseProcessingMode = version >= CASE_VERSION ? readCaseProcessingMode(dataInput)
980
                    : CaseProcessingMode.LOWERCASE_WITH_LOCALE_ROOT;
981 1 1. readMetadata : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readMetadata → KILLED
            return new TrieMetadata(version, traversalDirection, reductionSettings, diacriticProcessingMode,
982
                    caseProcessingMode);
983
        }
984
985
        private static TrieMetadata readTextMetadata(final DataInputStream dataInput, final int version)
986
                throws IOException {
987
            try {
988 1 1. readTextMetadata : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readTextMetadata → KILLED
                return TrieMetadata.fromTextBlock(version, dataInput.readUTF());
989
            } catch (IllegalArgumentException exception) {
990
                throw new IOException("Invalid metadata block.", exception);
991
            }
992
        }
993
994
        private static WordTraversalDirection readTraversalDirection(final DataInputStream dataInput, final int version)
995
                throws IOException {
996 2 1. readTraversalDirection : negated conditional → KILLED
2. readTraversalDirection : changed conditional boundary → KILLED
            if (version < TRAVERSAL_VERSION) {
997 1 1. readTraversalDirection : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readTraversalDirection → KILLED
                return WordTraversalDirection.BACKWARD;
998
            }
999 1 1. readTraversalDirection : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readTraversalDirection → KILLED
            return readEnumByOrdinal(dataInput, WordTraversalDirection.values(), "traversal direction");
1000
        }
1001
1002
        private static ReductionSettings readReductionSettings(final DataInputStream dataInput) throws IOException {
1003
            final ReductionMode reductionMode = readEnumByOrdinal(dataInput, ReductionMode.values(), "reduction mode");
1004
            final int dominantWinnerMinPercent = dataInput.readInt();
1005
            final int dominantWinnerOverSecondRatio = dataInput.readInt(); // NOPMD
1006 1 1. readReductionSettings : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readReductionSettings → KILLED
            return new ReductionSettings(reductionMode, dominantWinnerMinPercent, dominantWinnerOverSecondRatio);
1007
        }
1008
1009
        private static CaseProcessingMode readCaseProcessingMode(final DataInputStream dataInput) throws IOException {
1010 1 1. readCaseProcessingMode : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readCaseProcessingMode → KILLED
            return readEnumByOrdinal(dataInput, CaseProcessingMode.values(), "case processing mode");
1011
        }
1012
1013
        private static <E extends Enum<E>> E readEnumByOrdinal(final DataInputStream dataInput, final E[] values,
1014
                final String name) throws IOException {
1015
            final int ordinal = dataInput.readInt();
1016 4 1. readEnumByOrdinal : changed conditional boundary → SURVIVED
2. readEnumByOrdinal : negated conditional → KILLED
3. readEnumByOrdinal : changed conditional boundary → KILLED
4. readEnumByOrdinal : negated conditional → KILLED
            if (ordinal < 0 || ordinal >= values.length) {
1017
                throw new IOException("Invalid " + name + " ordinal: " + ordinal);
1018
            }
1019 1 1. readEnumByOrdinal : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readEnumByOrdinal → KILLED
            return values[ordinal];
1020
        }
1021
1022
        private static <V> CompiledNode<V>[] readNodes(final DataInputStream dataInput,
1023
                final IntFunction<V[]> arrayFactory, final ValueStreamCodec<V> valueCodec, final int nodeCount,
1024
                final int maxExpandedIndex, final int version) throws IOException {
1025
            final char[][] edgeLabelsByNode = new char[nodeCount][];
1026
            final int[][] childNodeIdsByNode = new int[nodeCount][];
1027
            @SuppressWarnings("unchecked")
1028
            final V[][] orderedValuesByNode = (V[][]) new Object[nodeCount][];
1029
            final int[][] orderedCountsByNode = new int[nodeCount][];
1030
            final boolean[] acceptsRemainingInputByNode = new boolean[nodeCount];
1031
1032 2 1. readNodes : negated conditional → KILLED
2. readNodes : changed conditional boundary → KILLED
            for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) {
1033 2 1. readNodes : changed conditional boundary → KILLED
2. readNodes : negated conditional → KILLED
                if (version >= ACCEPTING_NODE_VERSION) {
1034
                    acceptsRemainingInputByNode[nodeIndex] = dataInput.readBoolean();
1035
                }
1036
1037
                final int edgeCount = dataInput.readInt();
1038 2 1. readNodes : changed conditional boundary → KILLED
2. readNodes : negated conditional → KILLED
                if (edgeCount < 0) {
1039
                    throw new IOException("Negative edge count at node " + nodeIndex + ": " + edgeCount);
1040
                }
1041
1042
                edgeLabelsByNode[nodeIndex] = new char[edgeCount];
1043
                childNodeIdsByNode[nodeIndex] = new int[edgeCount];
1044
1045 2 1. readNodes : changed conditional boundary → KILLED
2. readNodes : negated conditional → KILLED
                for (int edgeIndex = 0; edgeIndex < edgeCount; edgeIndex++) {
1046
                    edgeLabelsByNode[nodeIndex][edgeIndex] = dataInput.readChar();
1047
                    childNodeIdsByNode[nodeIndex][edgeIndex] = dataInput.readInt();
1048
                }
1049
1050 1 1. readNodes : removed call to org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::validateSerializedEdges → KILLED
                validateSerializedEdges(nodeIndex, edgeLabelsByNode[nodeIndex]);
1051
1052
                final int valueCount = dataInput.readInt();
1053 2 1. readNodes : changed conditional boundary → KILLED
2. readNodes : negated conditional → KILLED
                if (valueCount < 0) {
1054
                    throw new IOException("Negative value count at node " + nodeIndex + ": " + valueCount);
1055
                }
1056 2 1. readNodes : negated conditional → KILLED
2. readNodes : negated conditional → KILLED
                if (acceptsRemainingInputByNode[nodeIndex] && edgeCount != 0) {
1057
                    throw new IOException("Accepting node " + nodeIndex + " cannot have child edges.");
1058
                }
1059 2 1. readNodes : negated conditional → KILLED
2. readNodes : negated conditional → KILLED
                if (acceptsRemainingInputByNode[nodeIndex] && valueCount == 0) {
1060
                    throw new IOException("Accepting node " + nodeIndex + " must store at least one value.");
1061
                }
1062
1063
                orderedValuesByNode[nodeIndex] = arrayFactory.apply(valueCount);
1064
                orderedCountsByNode[nodeIndex] = new int[valueCount];
1065
1066 2 1. readNodes : changed conditional boundary → KILLED
2. readNodes : negated conditional → KILLED
                for (int valueIndex = 0; valueIndex < valueCount; valueIndex++) {
1067
                    orderedValuesByNode[nodeIndex][valueIndex] = valueCodec.read(dataInput);
1068
                    orderedCountsByNode[nodeIndex][valueIndex] = dataInput.readInt();
1069 2 1. readNodes : negated conditional → KILLED
2. readNodes : changed conditional boundary → KILLED
                    if (orderedCountsByNode[nodeIndex][valueIndex] <= 0) {
1070
                        throw new IOException("Non-positive stored count at node " + nodeIndex + ", value index "
1071
                                + valueIndex + ": " + orderedCountsByNode[nodeIndex][valueIndex]);
1072
                    }
1073
                }
1074
            }
1075
1076
            @SuppressWarnings("unchecked")
1077
            final CompiledNode<V>[] nodes = new CompiledNode[nodeCount];
1078
            final boolean[] inProgress = new boolean[nodeCount];
1079
1080 2 1. readNodes : changed conditional boundary → KILLED
2. readNodes : negated conditional → KILLED
            for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) {
1081
                nodes[nodeIndex] = resolveNode(nodeIndex, edgeLabelsByNode, childNodeIdsByNode, orderedValuesByNode,
1082
                        orderedCountsByNode, acceptsRemainingInputByNode, nodes, inProgress, maxExpandedIndex);
1083
            }
1084
1085 1 1. readNodes : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readNodes → KILLED
            return nodes;
1086
        }
1087
1088
        private static <V> CompiledNode<V> resolveNode(final int nodeIndex, final char[][] edgeLabelsByNode,
1089
                final int[][] childNodeIdsByNode, final V[][] orderedValuesByNode, final int[][] orderedCountsByNode,
1090
                final boolean[] acceptsRemainingInputByNode, final CompiledNode<V>[] nodes,
1091
                final boolean[] inProgress, final int maxExpandedIndex) throws IOException {
1092
            final CompiledNode<V> cachedNode = nodes[nodeIndex];
1093 1 1. resolveNode : negated conditional → KILLED
            if (cachedNode != null) {
1094 1 1. resolveNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::resolveNode → KILLED
                return cachedNode;
1095
            }
1096
1097 1 1. resolveNode : negated conditional → KILLED
            if (inProgress[nodeIndex]) {
1098
                throw new IOException(
1099
                        "Invalid serialized node graph: cyclic reference detected at node " + nodeIndex + '.');
1100
            }
1101
            inProgress[nodeIndex] = true;
1102
            try {
1103
                final char[] edgeLabels = edgeLabelsByNode[nodeIndex];
1104
                final int[] childNodeIds = childNodeIdsByNode[nodeIndex];
1105
                final int edgeCount = childNodeIds.length;
1106
                @SuppressWarnings("unchecked")
1107
                final CompiledNode<V>[] children = new CompiledNode[edgeCount];
1108
1109 2 1. resolveNode : negated conditional → KILLED
2. resolveNode : changed conditional boundary → KILLED
                for (int edgeIndex = 0; edgeIndex < edgeCount; edgeIndex++) {
1110
                    final int childNodeId = childNodeIds[edgeIndex];
1111 4 1. resolveNode : changed conditional boundary → SURVIVED
2. resolveNode : negated conditional → KILLED
3. resolveNode : changed conditional boundary → KILLED
4. resolveNode : negated conditional → KILLED
                    if (childNodeId < 0 || childNodeId >= edgeLabelsByNode.length) {
1112
                        throw new IOException("Invalid child node id at node " + nodeIndex + ", edge index " + edgeIndex
1113
                                + ": " + childNodeId);
1114
                    }
1115
                    children[edgeIndex] = resolveNode(childNodeId, edgeLabelsByNode, childNodeIdsByNode,
1116
                            orderedValuesByNode, orderedCountsByNode, acceptsRemainingInputByNode, nodes, inProgress,
1117
                            maxExpandedIndex);
1118
                }
1119
1120
                final CompiledNode<V> node = new CompiledNode<>(edgeLabels, children, orderedValuesByNode[nodeIndex],
1121
                        acceptsRemainingInputByNode[nodeIndex], maxExpandedIndex, orderedCountsByNode[nodeIndex]);
1122
                nodes[nodeIndex] = node;
1123 1 1. resolveNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::resolveNode → KILLED
                return node;
1124
            } finally {
1125
                inProgress[nodeIndex] = false;
1126
            }
1127
        }
1128
1129
        private static void validateSerializedEdges(final int nodeIndex, final char... edgeLabels) throws IOException {
1130 2 1. validateSerializedEdges : changed conditional boundary → KILLED
2. validateSerializedEdges : negated conditional → KILLED
            for (int edgeIndex = 1; edgeIndex < edgeLabels.length; edgeIndex++) {
1131 3 1. validateSerializedEdges : changed conditional boundary → SURVIVED
2. validateSerializedEdges : negated conditional → KILLED
3. validateSerializedEdges : Replaced integer subtraction with addition → KILLED
                if (edgeLabels[edgeIndex - 1] >= edgeLabels[edgeIndex]) {
1132 1 1. validateSerializedEdges : Replaced integer subtraction with addition → KILLED
                    throw new IOException(
1133
                            "Edge labels must be strictly ascending at node " + nodeIndex + ", edge index " + edgeIndex
1134
                                    + ": '" + edgeLabels[edgeIndex - 1] + "' then '" + edgeLabels[edgeIndex] + "'.");
1135
                }
1136
            }
1137
        }
1138
    }
1139
1140
    /**
1141
     * Locates the compiled node for the supplied key.
1142
     *
1143
     * @param key already-normalized key to resolve
1144
     * @return compiled node, or {@code null} if the path does not exist
1145
     */
1146
    private CompiledNode<V> findNode(final String key) {
1147
        CompiledNode<V> current = this.root;
1148 1 1. findNode : negated conditional → KILLED
        if (this.lookupTraversalDirection == WordTraversalDirection.BACKWARD) {
1149 3 1. findNode : changed conditional boundary → KILLED
2. findNode : Replaced integer subtraction with addition → KILLED
3. findNode : negated conditional → KILLED
            for (int traversalOffset = key.length() - 1; traversalOffset >= 0; traversalOffset--) {
1150 1 1. findNode : negated conditional → KILLED
                if (current.acceptsRemainingInput()) {
1151 1 1. findNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → KILLED
                    return current;
1152
                }
1153
                current = current.findChild(key.charAt(traversalOffset));
1154 1 1. findNode : negated conditional → KILLED
                if (current == null) {
1155
                    return null;
1156
                }
1157
            }
1158 1 1. findNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → KILLED
            return current;
1159
        }
1160
1161 2 1. findNode : negated conditional → KILLED
2. findNode : changed conditional boundary → KILLED
        for (int traversalOffset = 0; traversalOffset < key.length(); traversalOffset++) {
1162 1 1. findNode : negated conditional → KILLED
            if (current.acceptsRemainingInput()) {
1163 1 1. findNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → KILLED
                return current;
1164
            }
1165
            current = current.findChild(key.charAt(traversalOffset));
1166 1 1. findNode : negated conditional → KILLED
            if (current == null) {
1167
                return null;
1168
            }
1169
        }
1170 1 1. findNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → KILLED
        return current;
1171
    }
1172
1173
    /**
1174
     * Locates the compiled node for the supplied key.
1175
     *
1176
     * @param key already-normalized key to resolve
1177
     * @return compiled node, or {@code null} if the path does not exist
1178
     */
1179
    private CompiledNode<V> findNode(final CharSequence key) {
1180
        CompiledNode<V> current = this.root;
1181 1 1. findNode : negated conditional → KILLED
        if (this.lookupTraversalDirection == WordTraversalDirection.BACKWARD) {
1182 3 1. findNode : changed conditional boundary → KILLED
2. findNode : Replaced integer subtraction with addition → KILLED
3. findNode : negated conditional → KILLED
            for (int traversalOffset = key.length() - 1; traversalOffset >= 0; traversalOffset--) {
1183 1 1. findNode : negated conditional → KILLED
                if (current.acceptsRemainingInput()) {
1184 1 1. findNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → NO_COVERAGE
                    return current;
1185
                }
1186
                current = current.findChild(key.charAt(traversalOffset));
1187 1 1. findNode : negated conditional → KILLED
                if (current == null) {
1188
                    return null;
1189
                }
1190
            }
1191 1 1. findNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → KILLED
            return current;
1192
        }
1193
1194 2 1. findNode : negated conditional → NO_COVERAGE
2. findNode : changed conditional boundary → NO_COVERAGE
        for (int traversalOffset = 0; traversalOffset < key.length(); traversalOffset++) {
1195 1 1. findNode : negated conditional → NO_COVERAGE
            if (current.acceptsRemainingInput()) {
1196 1 1. findNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → NO_COVERAGE
                return current;
1197
            }
1198
            current = current.findChild(key.charAt(traversalOffset));
1199 1 1. findNode : negated conditional → NO_COVERAGE
            if (current == null) {
1200
                return null;
1201
            }
1202
        }
1203 1 1. findNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → NO_COVERAGE
        return current;
1204
    }
1205
1206
    /**
1207
     * Locates the compiled node for the supplied key slice.
1208
     *
1209
     * @param key    already-normalized key storage
1210
     * @param offset first character offset
1211
     * @param length number of characters to read
1212
     * @return compiled node, or {@code null} if the path does not exist
1213
     */
1214
    private CompiledNode<V> findNode(final char[] key, final int offset, final int length) {
1215
        CompiledNode<V> current = this.root;
1216 1 1. findNode : negated conditional → KILLED
        if (this.lookupTraversalDirection == WordTraversalDirection.BACKWARD) {
1217 4 1. findNode : Replaced integer subtraction with addition → KILLED
2. findNode : Replaced integer addition with subtraction → KILLED
3. findNode : negated conditional → KILLED
4. findNode : changed conditional boundary → KILLED
            for (int traversalOffset = offset + length - 1; traversalOffset >= offset; traversalOffset--) {
1218 1 1. findNode : negated conditional → KILLED
                if (current.acceptsRemainingInput()) {
1219 1 1. findNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → NO_COVERAGE
                    return current;
1220
                }
1221
                current = current.findChild(key[traversalOffset]);
1222 1 1. findNode : negated conditional → KILLED
                if (current == null) {
1223
                    return null;
1224
                }
1225
            }
1226 1 1. findNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → KILLED
            return current;
1227
        }
1228
1229 1 1. findNode : Replaced integer addition with subtraction → NO_COVERAGE
        final int endExclusive = offset + length;
1230 2 1. findNode : negated conditional → NO_COVERAGE
2. findNode : changed conditional boundary → NO_COVERAGE
        for (int traversalOffset = offset; traversalOffset < endExclusive; traversalOffset++) {
1231 1 1. findNode : negated conditional → NO_COVERAGE
            if (current.acceptsRemainingInput()) {
1232 1 1. findNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → NO_COVERAGE
                return current;
1233
            }
1234
            current = current.findChild(key[traversalOffset]);
1235 1 1. findNode : negated conditional → NO_COVERAGE
            if (current == null) {
1236
                return null;
1237
            }
1238
        }
1239 1 1. findNode : replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → NO_COVERAGE
        return current;
1240
    }
1241
1242
    /**
1243
     * Visits node-local values without allocating result containers.
1244
     *
1245
     * @param node       resolved node, or {@code null}
1246
     * @param sink       value sink
1247
     * @param maxResults maximum values to visit
1248
     * @return number of visited values
1249
     */
1250
    private int visitNode(final CompiledNode<V> node, final EntrySink<? super V> sink, final int maxResults) {
1251 1 1. visitNode : negated conditional → KILLED
        if (node == null) {
1252
            return 0;
1253
        }
1254
1255
        final V[] orderedValues = node.orderedValues();
1256
        final int valueCount = Math.min(orderedValues.length, maxResults);
1257 1 1. visitNode : negated conditional → KILLED
        if (valueCount == 0) {
1258
            return 0;
1259
        }
1260
1261
        final int[] orderedCounts = node.orderedCounts();
1262
        int visited = 0;
1263 2 1. visitNode : changed conditional boundary → KILLED
2. visitNode : negated conditional → KILLED
        for (int rank = 0; rank < valueCount; rank++) {
1264 1 1. visitNode : Changed increment from 1 to -1 → KILLED
            visited++;
1265 1 1. visitNode : negated conditional → KILLED
            if (!sink.accept(orderedValues[rank], orderedCounts[rank], rank)) {
1266
                break;
1267
            }
1268
        }
1269 1 1. visitNode : replaced int return with 0 for org/egothor/stemmer/FrequencyTrie::visitNode → KILLED
        return visited;
1270
    }
1271
1272
    /**
1273
     * Validates visitor maximum result count.
1274
     *
1275
     * @param maxResults maximum result count
1276
     */
1277
    private static void validateMaxResults(final int maxResults) {
1278 2 1. validateMaxResults : negated conditional → KILLED
2. validateMaxResults : changed conditional boundary → KILLED
        if (maxResults < 0) {
1279
            throw new IllegalArgumentException("maxResults must be non-negative.");
1280
        }
1281
    }
1282
1283
    /**
1284
     * Applies lookup-time case normalization according to persisted metadata.
1285
     *
1286
     * @param key lookup key
1287
     * @return normalized key for trie traversal
1288
     */
1289
    private String normalizeLookupKey(final String key) {
1290 1 1. normalizeLookupKey : replaced return value with "" for org/egothor/stemmer/FrequencyTrie::normalizeLookupKey → KILLED
        return normalizeLookupKey((CharSequence) key).toString();
1291
    }
1292
1293
    /**
1294
     * Applies lookup-time normalization according to persisted metadata.
1295
     *
1296
     * @param key lookup key
1297
     * @return normalized key for trie traversal
1298
     */
1299
    private CharSequence normalizeLookupKey(final CharSequence key) {
1300 2 1. normalizeLookupKey : negated conditional → SURVIVED
2. normalizeLookupKey : negated conditional → KILLED
        if (!this.lowercasesLookupKeys && !this.removeDiacritics) {
1301 1 1. normalizeLookupKey : replaced return value with null for org/egothor/stemmer/FrequencyTrie::normalizeLookupKey → KILLED
            return key;
1302
        }
1303
1304
        String normalized = key.toString();
1305 1 1. normalizeLookupKey : negated conditional → KILLED
        if (this.lowercasesLookupKeys) {
1306
            normalized = normalized.toLowerCase(Locale.ROOT);
1307
        }
1308 1 1. normalizeLookupKey : negated conditional → KILLED
        if (this.removeDiacritics) {
1309
            normalized = DiacriticStripper.strip(normalized);
1310 1 1. normalizeLookupKey : negated conditional → KILLED
        } else if (this.metadata.diacriticProcessingMode() == DiacriticProcessingMode.AS_IS_AND_STRIPPED_FALLBACK) {
1311
            throw new UnsupportedOperationException(
1312
                    "Diacritic processing mode AS_IS_AND_STRIPPED_FALLBACK is not supported yet.");
1313
        }
1314
1315 1 1. normalizeLookupKey : replaced return value with null for org/egothor/stemmer/FrequencyTrie::normalizeLookupKey → KILLED
        return normalized;
1316
    }
1317
1318
    /**
1319
     * Builder of {@link FrequencyTrie}.
1320
     *
1321
     * <p>
1322
     * The builder is intentionally mutable and optimized for repeated
1323
     * {@link #put(String, Object)} calls. The final trie is created by
1324
     * {@link #build()}, which performs bottom-up subtree reduction and converts the
1325
     * structure to a compact immutable representation optimized for read
1326
     * operations.
1327
     *
1328
     * @param <V> value type
1329
     */
1330
    public static final class Builder<V> {
1331
1332
        /**
1333
         * Logger of this class.
1334
         */
1335
        private static final Logger LOGGER = Logger.getLogger(Builder.class.getName());
1336
1337
        /**
1338
         * Factory used to create typed arrays.
1339
         */
1340
        private final IntFunction<V[]> arrayFactory;
1341
1342
        /**
1343
         * Reduction configuration.
1344
         */
1345
        private final ReductionSettings reductionSettings;
1346
1347
        /**
1348
         * Logical key traversal direction used by this builder.
1349
         */
1350
        private final WordTraversalDirection traversalDirection;
1351
1352
        /**
1353
         * Dictionary case processing mode associated with this builder.
1354
         */
1355
        private final CaseProcessingMode caseProcessingMode;
1356
1357
        /**
1358
         * Dictionary diacritic processing mode associated with this builder.
1359
         */
1360
        private final DiacriticProcessingMode diacriticProcessingMode;
1361
1362
        /**
1363
         * Dense edge lookup span threshold.
1364
         * <p>
1365
         * This value controls a speed/memory trade-off during freezing: dense child
1366
         * lookup tables are allocated only for nodes whose child labels fit in this
1367
         * span.
1368
         * </p>
1369
         */
1370
        private final int maxExpandedIndex;
1371
1372
        /**
1373
         * Mutable root node.
1374
         */
1375
        private final MutableNode<V> root;
1376
1377
        /**
1378
         * Creates a new builder with the provided settings.
1379
         *
1380
         * <p>
1381
         * This constructor preserves the historical Egothor behavior and therefore
1382
         * traverses logical keys from their end toward their beginning.
1383
         * </p>
1384
         *
1385
         * @param arrayFactory      array factory
1386
         * @param reductionSettings reduction configuration
1387
         * @throws NullPointerException if any argument is {@code null}
1388
         */
1389
        public Builder(final IntFunction<V[]> arrayFactory, final ReductionSettings reductionSettings) {
1390
            this(arrayFactory, reductionSettings, WordTraversalDirection.BACKWARD);
1391
        }
1392
1393
        /**
1394
         * Creates a new builder with the provided settings and explicit traversal
1395
         * direction.
1396
         *
1397
         * @param arrayFactory       array factory
1398
         * @param reductionSettings  reduction configuration
1399
         * @param traversalDirection logical key traversal direction
1400
         * @throws NullPointerException if any argument is {@code null}
1401
         */
1402
        public Builder(final IntFunction<V[]> arrayFactory, final ReductionSettings reductionSettings,
1403
                final WordTraversalDirection traversalDirection) {
1404
            this(arrayFactory, reductionSettings, traversalDirection, CaseProcessingMode.LOWERCASE_WITH_LOCALE_ROOT);
1405
        }
1406
1407
        /**
1408
         * Creates a new builder with the provided settings, explicit traversal
1409
         * direction, and explicit case processing mode.
1410
         *
1411
         * @param arrayFactory       array factory
1412
         * @param reductionSettings  reduction configuration
1413
         * @param traversalDirection logical key traversal direction
1414
         * @param caseProcessingMode dictionary case processing mode
1415
         * @throws NullPointerException if any argument is {@code null}
1416
         */
1417
        public Builder(final IntFunction<V[]> arrayFactory, final ReductionSettings reductionSettings,
1418
                final WordTraversalDirection traversalDirection, final CaseProcessingMode caseProcessingMode) {
1419
            this(arrayFactory, reductionSettings, traversalDirection, caseProcessingMode,
1420
                    DiacriticProcessingMode.AS_IS);
1421
        }
1422
1423
        /**
1424
         * Creates a new builder with the provided settings, explicit traversal
1425
         * direction, explicit case processing mode, and explicit diacritic processing
1426
         * mode.
1427
         *
1428
         * @param arrayFactory            array factory
1429
         * @param reductionSettings       reduction configuration
1430
         * @param traversalDirection      logical key traversal direction
1431
         * @param caseProcessingMode      dictionary case processing mode
1432
         * @param diacriticProcessingMode dictionary diacritic processing mode
1433
         * @throws NullPointerException if any argument is {@code null}
1434
         */
1435
        public Builder(final IntFunction<V[]> arrayFactory, final ReductionSettings reductionSettings,
1436
                final WordTraversalDirection traversalDirection, final CaseProcessingMode caseProcessingMode,
1437
                final DiacriticProcessingMode diacriticProcessingMode) {
1438
            this(arrayFactory, reductionSettings, traversalDirection, caseProcessingMode, diacriticProcessingMode,
1439
                    CompiledNode.DEFAULT_MAX_EXPANDED_INDEX);
1440
        }
1441
1442
        /**
1443
         * Creates a new builder with the provided settings, explicit traversal
1444
         * direction, explicit case processing mode, explicit diacritic processing mode,
1445
         * and an explicit dense child lookup threshold.
1446
         *
1447
         * @param arrayFactory            array factory
1448
         * @param reductionSettings       reduction configuration
1449
         * @param traversalDirection      logical key traversal direction
1450
         * @param caseProcessingMode      dictionary case processing mode
1451
         * @param diacriticProcessingMode dictionary diacritic processing mode
1452
         * @param maxExpandedIndex        dense lookup span override; zero disables
1453
         *                                dense lookup. Larger values increase direct
1454
         *                                indexing opportunities while potentially
1455
         *                                increasing materialization memory in nodes
1456
         *                                whose edge label span is within the limit.
1457
         * @throws NullPointerException if any argument is {@code null}
1458
         */
1459
        public Builder(final IntFunction<V[]> arrayFactory, final ReductionSettings reductionSettings,
1460
                final WordTraversalDirection traversalDirection, final CaseProcessingMode caseProcessingMode,
1461
                final DiacriticProcessingMode diacriticProcessingMode, final int maxExpandedIndex) {
1462
            this.arrayFactory = Objects.requireNonNull(arrayFactory, "arrayFactory");
1463
            this.reductionSettings = Objects.requireNonNull(reductionSettings, "reductionSettings");
1464
            this.traversalDirection = Objects.requireNonNull(traversalDirection, "traversalDirection");
1465
            this.caseProcessingMode = Objects.requireNonNull(caseProcessingMode, "caseProcessingMode");
1466
            this.diacriticProcessingMode = Objects.requireNonNull(diacriticProcessingMode, "diacriticProcessingMode");
1467 2 1. <init> : changed conditional boundary → SURVIVED
2. <init> : negated conditional → KILLED
            if (maxExpandedIndex < 0) {
1468
                throw new IllegalArgumentException("maxExpandedIndex must be non-negative.");
1469
            }
1470
            this.maxExpandedIndex = maxExpandedIndex;
1471
            this.root = new MutableNode<>();
1472
        }
1473
1474
        /**
1475
         * Creates a new builder using default thresholds for the supplied reduction
1476
         * mode.
1477
         *
1478
         * <p>
1479
         * This constructor preserves the historical Egothor behavior and therefore
1480
         * traverses logical keys from their end toward their beginning.
1481
         * </p>
1482
         *
1483
         * @param arrayFactory  array factory
1484
         * @param reductionMode reduction mode
1485
         * @throws NullPointerException if any argument is {@code null}
1486
         */
1487
        public Builder(final IntFunction<V[]> arrayFactory, final ReductionMode reductionMode) {
1488
            this(arrayFactory, ReductionSettings.withDefaults(reductionMode), WordTraversalDirection.BACKWARD);
1489
        }
1490
1491
        /**
1492
         * Creates a new builder using default thresholds for the supplied reduction
1493
         * mode and explicit traversal direction.
1494
         *
1495
         * @param arrayFactory       array factory
1496
         * @param reductionMode      reduction mode
1497
         * @param traversalDirection logical key traversal direction
1498
         * @throws NullPointerException if any argument is {@code null}
1499
         */
1500
        public Builder(final IntFunction<V[]> arrayFactory, final ReductionMode reductionMode,
1501
                final WordTraversalDirection traversalDirection) {
1502
            this(arrayFactory, ReductionSettings.withDefaults(reductionMode), traversalDirection);
1503
        }
1504
1505
        /**
1506
         * Stores a value for the supplied key and increments its local frequency.
1507
         *
1508
         * <p>
1509
         * Values are stored at the node addressed by the full key. Since trie values
1510
         * may also appear on internal nodes, an empty key is valid and stores a value
1511
         * directly at the root.
1512
         *
1513
         * @param key   key
1514
         * @param value value
1515
         * @return this builder
1516
         * @throws NullPointerException if {@code key} or {@code value} is {@code null}
1517
         */
1518
        public Builder<V> put(final String key, final V value) {
1519 1 1. put : replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::put → SURVIVED
            return put(key, value, 1);
1520
        }
1521
1522
        /**
1523
         * Builds a compiled read-only trie.
1524
         *
1525
         * @return compiled trie
1526
         */
1527
        public FrequencyTrie<V> build() {
1528
            if (LOGGER.isLoggable(Level.FINE)) {
1529
                LOGGER.log(Level.FINE, "Starting trie compilation with reduction mode {0}.",
1530
                        this.reductionSettings.reductionMode());
1531
            }
1532
1533
            final ReductionContext<V> reductionContext = new ReductionContext<>(this.reductionSettings);
1534
            final ReducedNode<V> reducedRoot = reduce(this.root, reductionContext);
1535
            final CompiledNode<V> compiledRoot = freeze(reducedRoot, new IdentityHashMap<>());
1536
1537
            if (LOGGER.isLoggable(Level.FINE)) {
1538
                LOGGER.log(Level.FINE, "Trie compilation finished. Canonical node count: {0}.",
1539
                        reductionContext.canonicalNodeCount());
1540
            }
1541
1542
            final TrieMetadata metadata = TrieMetadata.forCompilation(this.traversalDirection, this.reductionSettings,
1543
                    this.diacriticProcessingMode, this.caseProcessingMode);
1544 1 1. build : replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::build → KILLED
            return new FrequencyTrie<>(this.arrayFactory, compiledRoot, metadata);
1545
        }
1546
1547
        /**
1548
         * Stores a value for the supplied key and increments its local frequency by the
1549
         * specified positive count.
1550
         *
1551
         * <p>
1552
         * Values are stored at the node addressed by the full key. Since trie values
1553
         * may also appear on internal nodes, an empty key is valid and stores a value
1554
         * directly at the root.
1555
         *
1556
         * <p>
1557
         * This method is functionally equivalent to calling
1558
         * {@link #put(String, Object)} repeatedly {@code count} times, but it avoids
1559
         * unnecessary repeated map updates and is therefore preferable for bulk
1560
         * reconstruction from compiled tries or other aggregated sources.
1561
         *
1562
         * @param key   key
1563
         * @param value value
1564
         * @param count positive frequency increment
1565
         * @return this builder
1566
         * @throws NullPointerException     if {@code key} or {@code value} is
1567
         *                                  {@code null}
1568
         * @throws IllegalArgumentException if {@code count} is less than {@code 1}
1569
         */
1570
        public Builder<V> put(final String key, final V value, final int count) {
1571
            Objects.requireNonNull(key, ARG_KEY);
1572
            Objects.requireNonNull(value, "value");
1573
1574 2 1. put : changed conditional boundary → KILLED
2. put : negated conditional → KILLED
            if (count < 1) { // NOPMD
1575
                throw new IllegalArgumentException("count must be at least 1.");
1576
            }
1577
1578
            final String normalizedKey = normalizeDictionaryKey(key);
1579
1580
            MutableNode<V> current = this.root;
1581 2 1. put : changed conditional boundary → KILLED
2. put : negated conditional → KILLED
            for (int traversalOffset = 0; traversalOffset < normalizedKey.length(); traversalOffset++) {
1582
                final Character edge = normalizedKey
1583
                        .charAt(this.traversalDirection.logicalIndex(normalizedKey.length(), traversalOffset));
1584
                MutableNode<V> child = current.children().get(edge);
1585 1 1. put : negated conditional → KILLED
                if (child == null) {
1586
                    child = new MutableNode<>(); // NOPMD
1587
                    current.children().put(edge, child);
1588
                }
1589
                current = child;
1590
            }
1591
1592
            final Integer previous = current.valueCounts().get(value);
1593 1 1. put : negated conditional → KILLED
            if (previous == null) {
1594
                current.valueCounts().put(value, count);
1595
            } else {
1596 1 1. put : Replaced integer addition with subtraction → KILLED
                current.valueCounts().put(value, previous + count);
1597
            }
1598 1 1. put : replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::put → SURVIVED
            return this;
1599
        }
1600
1601
        /**
1602
         * Applies build-time dictionary-key normalization according to the builder
1603
         * configuration.
1604
         *
1605
         * @param key dictionary key
1606
         * @return normalized key for trie insertion
1607
         */
1608
        private String normalizeDictionaryKey(final String key) {
1609
            String normalized = key;
1610
1611 1 1. normalizeDictionaryKey : negated conditional → KILLED
            if (this.caseProcessingMode == CaseProcessingMode.LOWERCASE_WITH_LOCALE_ROOT) {
1612
                normalized = normalized.toLowerCase(Locale.ROOT);
1613
            }
1614
1615 1 1. normalizeDictionaryKey : negated conditional → KILLED
            if (this.diacriticProcessingMode == DiacriticProcessingMode.REMOVE) {
1616
                normalized = DiacriticStripper.strip(normalized);
1617 1 1. normalizeDictionaryKey : negated conditional → KILLED
            } else if (this.diacriticProcessingMode == DiacriticProcessingMode.AS_IS_AND_STRIPPED_FALLBACK) {
1618
                throw new UnsupportedOperationException(
1619
                        "Diacritic processing mode AS_IS_AND_STRIPPED_FALLBACK is not supported yet.");
1620
            }
1621
1622 1 1. normalizeDictionaryKey : replaced return value with "" for org/egothor/stemmer/FrequencyTrie$Builder::normalizeDictionaryKey → KILLED
            return normalized;
1623
        }
1624
1625
        /**
1626
         * Returns the number of mutable build-time nodes currently reachable from the
1627
         * builder root.
1628
         *
1629
         * <p>
1630
         * This metric is intended mainly for diagnostics and tests that compare the
1631
         * unreduced build-time structure with the final reduced compiled trie.
1632
         *
1633
         * @return number of mutable build-time nodes
1634
         */
1635
        /* default */ int buildTimeSize() {
1636 1 1. buildTimeSize : replaced int return with 0 for org/egothor/stemmer/FrequencyTrie$Builder::buildTimeSize → KILLED
            return countMutableNodes(this.root);
1637
        }
1638
1639
        /**
1640
         * Returns the logical key traversal direction used by this builder.
1641
         *
1642
         * @return logical key traversal direction
1643
         */
1644
        /* default */ WordTraversalDirection traversalDirection() {
1645 1 1. traversalDirection : replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::traversalDirection → NO_COVERAGE
            return this.traversalDirection;
1646
        }
1647
1648
        /**
1649
         * Counts mutable nodes recursively.
1650
         *
1651
         * @param node current node
1652
         * @return reachable mutable node count
1653
         */
1654
        private int countMutableNodes(final MutableNode<V> node) {
1655
            int count = 1;
1656
            for (MutableNode<V> child : node.children().values()) {
1657 1 1. countMutableNodes : Replaced integer addition with subtraction → KILLED
                count += countMutableNodes(child);
1658
            }
1659 1 1. countMutableNodes : replaced int return with 0 for org/egothor/stemmer/FrequencyTrie$Builder::countMutableNodes → KILLED
            return count;
1660
        }
1661
1662
        /**
1663
         * Reduces a mutable node to a canonical reduced node.
1664
         *
1665
         * @param source  source mutable node
1666
         * @param context reduction context
1667
         * @return canonical reduced node
1668
         */
1669
        private ReducedNode<V> reduce(final MutableNode<V> source, final ReductionContext<V> context) {
1670
            Map<Character, ReducedNode<V>> reducedChildren = new LinkedHashMap<>();
1671
1672
            for (Map.Entry<Character, MutableNode<V>> childEntry : source.children().entrySet()) {
1673
                final ReducedNode<V> reducedChild = reduce(childEntry.getValue(), context);
1674
                reducedChildren.put(childEntry.getKey(), reducedChild);
1675
            }
1676
1677
            Map<V, Integer> localCounts = copyCounts(source.valueCounts());
1678
            boolean acceptsRemainingInput = false;
1679 1 1. reduce : negated conditional → KILLED
            if (context.settings().contractUniformSubtrees()) {
1680
                final Map<V, Integer> contractedCounts = contractUniformSubtree(localCounts, reducedChildren);
1681 1 1. reduce : negated conditional → KILLED
                if (!contractedCounts.isEmpty()) {
1682
                    localCounts = contractedCounts;
1683
                    reducedChildren = Collections.emptyMap();
1684
                    acceptsRemainingInput = true;
1685
                }
1686
            }
1687
1688
            final LocalValueSummary<V> localSummary = LocalValueSummary.of(localCounts, this.arrayFactory);
1689
            final ReductionSignature<V> signature = ReductionSignature.create(localSummary, reducedChildren,
1690
                    context.settings(), acceptsRemainingInput);
1691
1692
            ReducedNode<V> canonical = context.lookup(signature);
1693 1 1. reduce : negated conditional → KILLED
            if (canonical == null) {
1694
                canonical = new ReducedNode<>(signature, localCounts, reducedChildren, acceptsRemainingInput);
1695 1 1. reduce : removed call to org/egothor/stemmer/trie/ReductionContext::register → KILLED
                context.register(signature, canonical);
1696 1 1. reduce : replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::reduce → KILLED
                return canonical;
1697
            }
1698
1699 1 1. reduce : removed call to org/egothor/stemmer/trie/ReducedNode::mergeLocalCounts → KILLED
            canonical.mergeLocalCounts(localCounts);
1700 1 1. reduce : removed call to org/egothor/stemmer/trie/ReducedNode::mergeChildren → SURVIVED
            canonical.mergeChildren(reducedChildren);
1701
1702 1 1. reduce : replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::reduce → KILLED
            return canonical;
1703
        }
1704
1705
        /**
1706
         * Returns aggregated local counts when the supplied internal subtree contains
1707
         * one uniform value, otherwise {@code null}.
1708
         *
1709
         * @param localCounts     local counts at the current node
1710
         * @param reducedChildren already reduced children
1711
         * @return single-value aggregate for a uniform non-leaf subtree, otherwise an
1712
         *         empty map
1713
         */
1714
        private Map<V, Integer> contractUniformSubtree(final Map<V, Integer> localCounts,
1715
                final Map<Character, ReducedNode<V>> reducedChildren) {
1716 1 1. contractUniformSubtree : negated conditional → KILLED
            if (reducedChildren.isEmpty()) {
1717
                return Collections.emptyMap();
1718
            }
1719
1720
            V uniformValue = null;
1721
            boolean valueSeen = false;
1722
1723 1 1. contractUniformSubtree : negated conditional → KILLED
            if (!localCounts.isEmpty()) {
1724 1 1. contractUniformSubtree : negated conditional → SURVIVED
                if (localCounts.size() != SINGLE_VALUE_COUNT) {
1725
                    return Collections.emptyMap();
1726
                }
1727
                final Map.Entry<V, Integer> localEntry = localCounts.entrySet().iterator().next();
1728
                uniformValue = localEntry.getKey();
1729
                valueSeen = true;
1730
            }
1731
1732
            for (ReducedNode<V> child : reducedChildren.values()) {
1733 1 1. contractUniformSubtree : negated conditional → KILLED
                if (!isSingleValueLeaf(child)) {
1734
                    return Collections.emptyMap();
1735
                }
1736
                final Map.Entry<V, Integer> childEntry = child.localCounts().entrySet().iterator().next();
1737 2 1. contractUniformSubtree : negated conditional → KILLED
2. contractUniformSubtree : negated conditional → KILLED
                if (valueSeen && !Objects.equals(uniformValue, childEntry.getKey())) {
1738
                    return Collections.emptyMap();
1739
                }
1740
                uniformValue = childEntry.getKey();
1741
                valueSeen = true;
1742
            }
1743
1744 1 1. contractUniformSubtree : negated conditional → KILLED
            if (!valueSeen) {
1745
                return Collections.emptyMap();
1746
            }
1747
1748
            final Map<V, Integer> contractedCounts = new LinkedHashMap<>(SINGLE_VALUE_COUNT);
1749
            contractedCounts.put(uniformValue, SINGLE_VALUE_COUNT);
1750 1 1. contractUniformSubtree : replaced return value with Collections.emptyMap for org/egothor/stemmer/FrequencyTrie$Builder::contractUniformSubtree → KILLED
            return contractedCounts;
1751
        }
1752
1753
        /**
1754
         * Returns whether the reduced node is a leaf with exactly one stored value.
1755
         *
1756
         * @param node node to inspect
1757
         * @return {@code true} when the node can participate in uniform contraction
1758
         */
1759
        private boolean isSingleValueLeaf(final ReducedNode<V> node) {
1760 3 1. isSingleValueLeaf : negated conditional → KILLED
2. isSingleValueLeaf : replaced boolean return with true for org/egothor/stemmer/FrequencyTrie$Builder::isSingleValueLeaf → KILLED
3. isSingleValueLeaf : negated conditional → KILLED
            return node.children().isEmpty() && node.localCounts().size() == SINGLE_VALUE_COUNT;
1761
        }
1762
1763
        /**
1764
         * Freezes a reduced node into an immutable compiled node.
1765
         *
1766
         * @param reducedNode reduced node
1767
         * @param cache       already frozen nodes
1768
         * @return immutable compiled node
1769
         */
1770
        private CompiledNode<V> freeze(final ReducedNode<V> reducedNode,
1771
                final Map<ReducedNode<V>, CompiledNode<V>> cache) {
1772
            final CompiledNode<V> existing = cache.get(reducedNode);
1773 1 1. freeze : negated conditional → KILLED
            if (existing != null) {
1774 1 1. freeze : replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::freeze → KILLED
                return existing;
1775
            }
1776
1777
            final LocalValueSummary<V> localSummary = LocalValueSummary.of(reducedNode.localCounts(),
1778
                    this.arrayFactory);
1779
1780
            final List<Map.Entry<Character, ReducedNode<V>>> childEntries = new ArrayList<>(
1781
                    reducedNode.children().entrySet());
1782 1 1. freeze : removed call to java/util/List::sort → KILLED
            childEntries.sort(Map.Entry.comparingByKey());
1783
1784
            final char[] edges = new char[childEntries.size()];
1785
            @SuppressWarnings("unchecked")
1786
            final CompiledNode<V>[] childNodes = new CompiledNode[childEntries.size()];
1787
1788 2 1. freeze : changed conditional boundary → KILLED
2. freeze : negated conditional → KILLED
            for (int index = 0; index < childEntries.size(); index++) {
1789
                final Map.Entry<Character, ReducedNode<V>> entry = childEntries.get(index);
1790
                edges[index] = entry.getKey();
1791
                childNodes[index] = freeze(entry.getValue(), cache);
1792
            }
1793
1794
            final CompiledNode<V> frozen = new CompiledNode<>(edges, childNodes, localSummary.orderedValues(),
1795
                    reducedNode.acceptsRemainingInput(), this.maxExpandedIndex, localSummary.orderedCounts());
1796
            cache.put(reducedNode, frozen);
1797 1 1. freeze : replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::freeze → KILLED
            return frozen;
1798
        }
1799
1800
        /**
1801
         * Creates a shallow frequency copy preserving deterministic insertion order of
1802
         * first occurrence.
1803
         *
1804
         * @param source source counts
1805
         * @return copied counts
1806
         */
1807
        private Map<V, Integer> copyCounts(final Map<V, Integer> source) {
1808 1 1. copyCounts : replaced return value with Collections.emptyMap for org/egothor/stemmer/FrequencyTrie$Builder::copyCounts → KILLED
            return new LinkedHashMap<>(source);
1809
        }
1810
    }
1811
1812
    /**
1813
     * Codec used to persist values stored in the trie.
1814
     *
1815
     * @param <V> value type
1816
     */
1817
    public interface ValueStreamCodec<V> {
1818
1819
        /**
1820
         * Writes one value to the supplied data output.
1821
         *
1822
         * @param dataOutput target data output
1823
         * @param value      value to write
1824
         * @throws IOException if writing fails
1825
         */
1826
        void write(DataOutputStream dataOutput, V value) throws IOException;
1827
1828
        /**
1829
         * Reads one value from the supplied data input.
1830
         *
1831
         * @param dataInput source data input
1832
         * @return read value
1833
         * @throws IOException if reading fails
1834
         */
1835
        V read(DataInputStream dataInput) throws IOException;
1836
    }
1837
1838
}

Mutations

227

1.1
Location : currentFormatVersion
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidTextualMetadataBlock()]
replaced int return with 0 for org/egothor/stemmer/FrequencyTrie::currentFormatVersion → KILLED

268

1.1
Location : <init>
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:lookupKeepsCaseSensitiveBehaviorWhenMetadataIsAsIs()]
negated conditional → KILLED

269

1.1
Location : <init>
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:diacriticRemoveModeStripsDictionaryAndLookupKeys()]
negated conditional → KILLED

285

1.1
Location : fromCompiled
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldPreserveUniformSubtreeContractionWhenMappingValues()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::fromCompiled → KILLED

310

1.1
Location : get
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyTrieReturnsNullEmptyArrayAndEmptyEntries()]
negated conditional → KILLED

314

1.1
Location : get
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
negated conditional → KILLED

317

1.1
Location : get
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::get → KILLED

339

1.1
Location : getNormalized
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
negated conditional → KILLED

343

1.1
Location : getNormalized
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
negated conditional → KILLED

346

1.1
Location : getNormalized
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::getNormalized → KILLED

367

1.1
Location : getNormalizedString
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
negated conditional → KILLED

371

1.1
Location : getNormalizedString
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
negated conditional → KILLED

374

1.1
Location : getNormalizedString
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::getNormalizedString → KILLED

404

1.1
Location : getAll
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyTrieReturnsNullEmptyArrayAndEmptyEntries()]
negated conditional → KILLED

405

1.1
Location : getAll
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyTrieReturnsNullEmptyArrayAndEmptyEntries()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::getAll → KILLED

408

1.1
Location : getAll
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
negated conditional → KILLED

409

1.1
Location : getAll
Killed by : none
replaced return value with null for org/egothor/stemmer/FrequencyTrie::getAll → SURVIVED
Covering tests

411

1.1
Location : getAll
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::getAll → KILLED

439

1.1
Location : getEntries
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyTrieReturnsNullEmptyArrayAndEmptyEntries()]
negated conditional → KILLED

445

1.1
Location : getEntries
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
negated conditional → KILLED

449

1.1
Location : getEntries
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
negated conditional → KILLED

450

1.1
Location : getEntries
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:getEntriesReturnsSingleItemListForSingleStoredValue()]
replaced return value with Collections.emptyList for org/egothor/stemmer/FrequencyTrie::getEntries → KILLED

455

1.1
Location : getEntries
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
changed conditional boundary → KILLED

2.2
Location : getEntries
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
negated conditional → KILLED

458

1.1
Location : getEntries
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
replaced return value with Collections.emptyList for org/egothor/stemmer/FrequencyTrie::getEntries → KILLED

489

1.1
Location : getAllNormalized
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::validateMaxResults → SURVIVED
Covering tests

490

1.1
Location : getAllNormalized
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
negated conditional → KILLED

493

1.1
Location : getAllNormalized
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
replaced int return with 0 for org/egothor/stemmer/FrequencyTrie::getAllNormalized → KILLED

512

1.1
Location : getAllNormalized
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupHandlesBoundaryCases()]
removed call to org/egothor/stemmer/FrequencyTrie::validateMaxResults → KILLED

513

1.1
Location : getAllNormalized
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
negated conditional → KILLED

516

1.1
Location : getAllNormalized
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
replaced int return with 0 for org/egothor/stemmer/FrequencyTrie::getAllNormalized → KILLED

532

1.1
Location : getFirstNormalized
Killed by : none
replaced boolean return with true for org/egothor/stemmer/FrequencyTrie::getFirstNormalized → NO_COVERAGE

2.2
Location : getFirstNormalized
Killed by : none
negated conditional → NO_COVERAGE

545

1.1
Location : getFirstNormalized
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupHandlesBoundaryCases()]
negated conditional → KILLED

2.2
Location : getFirstNormalized
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupHandlesBoundaryCases()]
replaced boolean return with true for org/egothor/stemmer/FrequencyTrie::getFirstNormalized → KILLED

566

1.1
Location : getAll
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupRejectsNullAndInvalidRangeArguments()]
removed call to org/egothor/stemmer/FrequencyTrie::validateMaxResults → KILLED

567

1.1
Location : getAll
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
negated conditional → KILLED

571

1.1
Location : getAll
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
replaced int return with 0 for org/egothor/stemmer/FrequencyTrie::getAll → KILLED

584

1.1
Location : getFirst
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
negated conditional → KILLED

2.2
Location : getFirst
Killed by : none
replaced boolean return with true for org/egothor/stemmer/FrequencyTrie::getFirst → SURVIVED
Covering tests

598

1.1
Location : traversalDirection
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldPreserveUniformSubtreeContractionWhenMappingValues()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::traversalDirection → KILLED

607

1.1
Location : metadata
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::metadata → KILLED

629

1.1
Location : getFingerprint
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:fingerprintReflectsMetadataAndCompiledTrieContent()]
replaced return value with "" for org/egothor/stemmer/FrequencyTrie::getFingerprint → KILLED

643

1.1
Location : copyFingerprintBytes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:fingerprintReflectsMetadataAndCompiledTrieContent()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::copyFingerprintBytes → KILLED

648

1.1
Location : computeFingerprintBytes
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::updateUtf8 → SURVIVED
Covering tests

649

1.1
Location : computeFingerprintBytes
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
Covering tests

650

1.1
Location : computeFingerprintBytes
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::updateUtf8 → SURVIVED
Covering tests

654

1.1
Location : computeFingerprintBytes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
removed call to org/egothor/stemmer/FrequencyTrie::assignNodeIds → KILLED

656

1.1
Location : computeFingerprintBytes
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
Covering tests

657

1.1
Location : computeFingerprintBytes
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
Covering tests

659

1.1
Location : computeFingerprintBytes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:fingerprintReflectsMetadataAndCompiledTrieContent()]
removed call to org/egothor/stemmer/FrequencyTrie::updateNodeFingerprint → KILLED

661

1.1
Location : computeFingerprintBytes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:fingerprintReflectsMetadataAndCompiledTrieContent()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::computeFingerprintBytes → KILLED

670

1.1
Location : root
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldKeepExactLookupWhenUniformSubtreeContractionIsDisabled()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::root → KILLED

695

1.1
Location : writeTo
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:writeToAndReadFromRejectNullArguments()]
negated conditional → KILLED

703

1.1
Location : writeTo
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:writeToAndReadFromRejectNullArguments()]
removed call to org/egothor/stemmer/FrequencyTrie::assignNodeIds → KILLED

709

1.1
Location : writeTo
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRespectsDenseLookupMaxExpandedIndexOverride()]
removed call to java/io/DataOutputStream::writeInt → KILLED

710

1.1
Location : writeTo
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRespectsDenseLookupMaxExpandedIndexOverride()]
removed call to java/io/DataOutputStream::writeInt → KILLED

711

1.1
Location : writeTo
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRespectsDenseLookupMaxExpandedIndexOverride()]
removed call to java/io/DataOutputStream::writeInt → KILLED

712

1.1
Location : writeTo
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRespectsDenseLookupMaxExpandedIndexOverride()]
removed call to java/io/DataOutputStream::writeInt → KILLED

713

1.1
Location : writeTo
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRespectsDenseLookupMaxExpandedIndexOverride()]
removed call to org/egothor/stemmer/FrequencyTrie::writeMetadata → KILLED

716

1.1
Location : writeTo
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRespectsDenseLookupMaxExpandedIndexOverride()]
removed call to org/egothor/stemmer/FrequencyTrie::writeNode → KILLED

719

1.1
Location : writeTo
Killed by : none
removed call to java/io/DataOutputStream::flush → SURVIVED
Covering tests

739

1.1
Location : readFrom
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::readFrom → KILLED

764

1.1
Location : readFrom
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::readFrom → KILLED

776

1.1
Location : writeMetadata
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRespectsDenseLookupMaxExpandedIndexOverride()]
removed call to java/io/DataOutputStream::writeUTF → KILLED

792

1.1
Location : size
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldContractUniformInternalSubtreeIntoAcceptingLeaf()]
removed call to org/egothor/stemmer/FrequencyTrie::assignNodeIds → KILLED

793

1.1
Location : size
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldContractUniformInternalSubtreeIntoAcceptingLeaf()]
replaced int return with 0 for org/egothor/stemmer/FrequencyTrie::size → KILLED

806

1.1
Location : assignNodeIds
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
negated conditional → KILLED

815

1.1
Location : assignNodeIds
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:lookupKeepsCaseSensitiveBehaviorWhenMetadataIsAsIs()]
removed call to org/egothor/stemmer/FrequencyTrie::assignNodeIds → KILLED

830

1.1
Location : writeNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRespectsDenseLookupMaxExpandedIndexOverride()]
removed call to java/io/DataOutputStream::writeBoolean → KILLED

831

1.1
Location : writeNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRespectsDenseLookupMaxExpandedIndexOverride()]
removed call to java/io/DataOutputStream::writeInt → KILLED

832

1.1
Location : writeNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:writeToAndReadFromRejectNullArguments()]
negated conditional → KILLED

2.2
Location : writeNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:writeToAndReadFromRejectNullArguments()]
changed conditional boundary → KILLED

833

1.1
Location : writeNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRespectsDenseLookupMaxExpandedIndexOverride()]
removed call to java/io/DataOutputStream::writeChar → KILLED

835

1.1
Location : writeNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRespectsDenseLookupMaxExpandedIndexOverride()]
negated conditional → KILLED

838

1.1
Location : writeNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRespectsDenseLookupMaxExpandedIndexOverride()]
removed call to java/io/DataOutputStream::writeInt → KILLED

841

1.1
Location : writeNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRespectsDenseLookupMaxExpandedIndexOverride()]
removed call to java/io/DataOutputStream::writeInt → KILLED

842

1.1
Location : writeNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:writeToAndReadFromRejectNullArguments()]
negated conditional → KILLED

2.2
Location : writeNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:writeToAndReadFromRejectNullArguments()]
changed conditional boundary → KILLED

843

1.1
Location : writeNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRespectsDenseLookupMaxExpandedIndexOverride()]
removed call to org/egothor/stemmer/FrequencyTrie$ValueStreamCodec::write → KILLED

844

1.1
Location : writeNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRespectsDenseLookupMaxExpandedIndexOverride()]
removed call to java/io/DataOutputStream::writeInt → KILLED

850

1.1
Location : newSha256Digest
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::newSha256Digest → KILLED

863

1.1
Location : updateNodeFingerprint
Killed by : none
negated conditional → SURVIVED
Covering tests

2.2
Location : updateNodeFingerprint
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED Covering tests

864

1.1
Location : updateNodeFingerprint
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
Covering tests

866

1.1
Location : updateNodeFingerprint
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
Covering tests

870

1.1
Location : updateNodeFingerprint
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:lookupKeepsCaseSensitiveBehaviorWhenMetadataIsAsIs()]
negated conditional → KILLED

873

1.1
Location : updateNodeFingerprint
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
Covering tests

876

1.1
Location : updateNodeFingerprint
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
Covering tests

878

1.1
Location : updateNodeFingerprint
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::updateUtf8 → SURVIVED
Covering tests

881

1.1
Location : updateNodeFingerprint
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:fingerprintReflectsMetadataAndCompiledTrieContent()]
removed call to org/egothor/stemmer/FrequencyTrie::updateInt → KILLED

887

1.1
Location : updateUtf8
Killed by : none
removed call to org/egothor/stemmer/FrequencyTrie::updateInt → SURVIVED
Covering tests

888

1.1
Location : updateUtf8
Killed by : none
removed call to java/security/MessageDigest::update → SURVIVED
Covering tests

892

1.1
Location : updateInt
Killed by : none
removed call to java/security/MessageDigest::update → SURVIVED
Covering tests

2.2
Location : updateInt
Killed by : none
Replaced Unsigned Shift Right with Shift Left → SURVIVED Covering tests

893

1.1
Location : updateInt
Killed by : none
removed call to java/security/MessageDigest::update → SURVIVED
Covering tests

2.2
Location : updateInt
Killed by : none
Replaced Unsigned Shift Right with Shift Left → SURVIVED Covering tests

894

1.1
Location : updateInt
Killed by : none
removed call to java/security/MessageDigest::update → SURVIVED
Covering tests

2.2
Location : updateInt
Killed by : none
Replaced Unsigned Shift Right with Shift Left → SURVIVED Covering tests

895

1.1
Location : updateInt
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:fingerprintReflectsMetadataAndCompiledTrieContent()]
removed call to java/security/MessageDigest::update → KILLED

899

1.1
Location : toLowerHex
Killed by : none
Replaced integer multiplication with division → SURVIVED
Covering tests

901

1.1
Location : toLowerHex
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:fingerprintReflectsMetadataAndCompiledTrieContent()]
Replaced Unsigned Shift Right with Shift Left → KILLED

2.2
Location : toLowerHex
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:fingerprintReflectsMetadataAndCompiledTrieContent()]
Replaced bitwise AND with OR → KILLED

3.3
Location : toLowerHex
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:fingerprintReflectsMetadataAndCompiledTrieContent()]
Replaced bitwise AND with OR → KILLED

903

1.1
Location : toLowerHex
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:fingerprintReflectsMetadataAndCompiledTrieContent()]
replaced return value with "" for org/egothor/stemmer/FrequencyTrie::toLowerHex → KILLED

922

1.1
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsUnsupportedStreamVersion()]
negated conditional → KILLED

2.2
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsUnsupportedStreamVersion()]
changed conditional boundary → KILLED

928

1.1
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsUnsupportedStreamVersion()]
negated conditional → KILLED

933

1.1
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidTextualMetadataBlock()]
changed conditional boundary → KILLED

2.2
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidRootNodeIdentifier()]
changed conditional boundary → KILLED

3.3
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsUnsupportedStreamVersion()]
negated conditional → KILLED

4.4
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidRootNodeIdentifier()]
negated conditional → KILLED

938

1.1
Location : read
Killed by : none
changed conditional boundary → SURVIVED
Covering tests

2.2
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidRootNodeIdentifier()]
negated conditional → KILLED

943

1.1
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidRootNodeIdentifier()]
negated conditional → KILLED

2.2
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidTextualMetadataBlock()]
negated conditional → KILLED

3.3
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidRootNodeIdentifier()]
changed conditional boundary → KILLED

4.4
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidTextualMetadataBlock()]
changed conditional boundary → KILLED

948

1.1
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
negated conditional → KILLED

2.2
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRespectsDenseLookupMaxExpandedIndexOverride()]
changed conditional boundary → KILLED

957

1.1
Location : read
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::read → KILLED

961

1.1
Location : wrapInputStream
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsUnsupportedStreamVersion()]
negated conditional → KILLED

2.2
Location : wrapInputStream
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsUnsupportedStreamVersion()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::wrapInputStream → KILLED

967

1.1
Location : readMetadata
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidTextualMetadataBlock()]
negated conditional → KILLED

2.2
Location : readMetadata
Killed by : org.egothor.stemmer.CompiledTrieArtifactRegressionTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.CompiledTrieArtifactRegressionTest]/[test-template:shouldKeepGoldenArtifactReadableAndHashStable(org.egothor.stemmer.CompiledTrieArtifactRegressionTest$ArtifactCase)]/[test-template-invocation:#2]
changed conditional boundary → KILLED

968

1.1
Location : readMetadata
Killed by : org.egothor.stemmer.CompiledTrieArtifactRegressionTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.CompiledTrieArtifactRegressionTest]/[test-template:shouldKeepGoldenArtifactReadableAndHashStable(org.egothor.stemmer.CompiledTrieArtifactRegressionTest$ArtifactCase)]/[test-template-invocation:#2]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readMetadata → KILLED

972

1.1
Location : readMetadata
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

2.2
Location : readMetadata
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromParsesVersionThreeMetadata()]
changed conditional boundary → KILLED

973

1.1
Location : readMetadata
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readMetadata → KILLED

979

1.1
Location : readMetadata
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromParsesVersionThreeMetadata()]
negated conditional → KILLED

2.2
Location : readMetadata
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromParsesVersionFourCaseMetadata()]
changed conditional boundary → KILLED

981

1.1
Location : readMetadata
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromParsesVersionThreeMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readMetadata → KILLED

988

1.1
Location : readTextMetadata
Killed by : org.egothor.stemmer.CompiledTrieArtifactRegressionTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.CompiledTrieArtifactRegressionTest]/[test-template:shouldKeepGoldenArtifactReadableAndHashStable(org.egothor.stemmer.CompiledTrieArtifactRegressionTest$ArtifactCase)]/[test-template-invocation:#2]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readTextMetadata → KILLED

996

1.1
Location : readTraversalDirection
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidLegacyMetadataOrdinal()]
negated conditional → KILLED

2.2
Location : readTraversalDirection
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidLegacyMetadataOrdinal()]
changed conditional boundary → KILLED

997

1.1
Location : readTraversalDirection
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readTraversalDirection → KILLED

999

1.1
Location : readTraversalDirection
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readTraversalDirection → KILLED

1006

1.1
Location : readReductionSettings
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromParsesVersionThreeMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readReductionSettings → KILLED

1010

1.1
Location : readCaseProcessingMode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromParsesVersionFourCaseMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readCaseProcessingMode → KILLED

1016

1.1
Location : readEnumByOrdinal
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
negated conditional → KILLED

2.2
Location : readEnumByOrdinal
Killed by : none
changed conditional boundary → SURVIVED
Covering tests

3.3
Location : readEnumByOrdinal
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
changed conditional boundary → KILLED

4.4
Location : readEnumByOrdinal
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidLegacyMetadataOrdinal()]
negated conditional → KILLED

1019

1.1
Location : readEnumByOrdinal
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readEnumByOrdinal → KILLED

1032

1.1
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

2.2
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
changed conditional boundary → KILLED

1033

1.1
Location : readNodes
Killed by : org.egothor.stemmer.StemmerPatchTrieBinaryIOTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.StemmerPatchTrieBinaryIOTest]/[nested-class:ReadTests]/[method:shouldReadMetadataFromPath()]
changed conditional boundary → KILLED

2.2
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

1038

1.1
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsNonPositiveStoredCounts()]
changed conditional boundary → KILLED

2.2
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

1045

1.1
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
changed conditional boundary → KILLED

2.2
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

1050

1.1
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsNonAscendingSerializedEdgeLabels()]
removed call to org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::validateSerializedEdges → KILLED

1053

1.1
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
changed conditional boundary → KILLED

2.2
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

1056

1.1
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

2.2
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldPreserveUniformSubtreeContractionAcrossBinaryRoundTrip()]
negated conditional → KILLED

1059

1.1
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

2.2
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldPreserveUniformSubtreeContractionAcrossBinaryRoundTrip()]
negated conditional → KILLED

1066

1.1
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
changed conditional boundary → KILLED

2.2
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

1069

1.1
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsNonPositiveStoredCounts()]
negated conditional → KILLED

2.2
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsNonPositiveStoredCounts()]
changed conditional boundary → KILLED

1080

1.1
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
changed conditional boundary → KILLED

2.2
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

1085

1.1
Location : readNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::readNodes → KILLED

1093

1.1
Location : resolveNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

1094

1.1
Location : resolveNode
Killed by : org.egothor.stemmer.CompiledTrieArtifactRegressionTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.CompiledTrieArtifactRegressionTest]/[test-template:shouldKeepGoldenArtifactReadableAndHashStable(org.egothor.stemmer.CompiledTrieArtifactRegressionTest$ArtifactCase)]/[test-template-invocation:#2]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::resolveNode → KILLED

1097

1.1
Location : resolveNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsInvalidChildNodeId()]
negated conditional → KILLED

1109

1.1
Location : resolveNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

2.2
Location : resolveNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
changed conditional boundary → KILLED

1111

1.1
Location : resolveNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

2.2
Location : resolveNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
changed conditional boundary → KILLED

3.3
Location : resolveNode
Killed by : none
changed conditional boundary → SURVIVED
Covering tests

4.4
Location : resolveNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

1123

1.1
Location : resolveNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromSupportsLegacyVersionTwoMetadata()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$CompiledTrieReader::resolveNode → KILLED

1130

1.1
Location : validateSerializedEdges
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
changed conditional boundary → KILLED

2.2
Location : validateSerializedEdges
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsCyclicSerializedNodeReferences()]
negated conditional → KILLED

1131

1.1
Location : validateSerializedEdges
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsNonAscendingSerializedEdgeLabels()]
negated conditional → KILLED

2.2
Location : validateSerializedEdges
Killed by : none
changed conditional boundary → SURVIVED
Covering tests

3.3
Location : validateSerializedEdges
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsNonAscendingSerializedEdgeLabels()]
Replaced integer subtraction with addition → KILLED

1132

1.1
Location : validateSerializedEdges
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:readFromRejectsNonAscendingSerializedEdgeLabels()]
Replaced integer subtraction with addition → KILLED

1148

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:lookupKeepsCaseSensitiveBehaviorWhenMetadataIsAsIs()]
negated conditional → KILLED

1149

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:getEntriesReturnsSingleItemListForSingleStoredValue()]
changed conditional boundary → KILLED

2.2
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyTrieReturnsNullEmptyArrayAndEmptyEntries()]
Replaced integer subtraction with addition → KILLED

3.3
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
negated conditional → KILLED

1150

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:getEntriesReturnsSingleItemListForSingleStoredValue()]
negated conditional → KILLED

1151

1.1
Location : findNode
Killed by : org.egothor.stemmer.CompiledTrieArtifactRegressionTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.CompiledTrieArtifactRegressionTest]/[test-template:shouldPreserveRepresentativeSemanticProbes(org.egothor.stemmer.CompiledTrieArtifactRegressionTest$ArtifactCase)]/[test-template-invocation:#3]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → KILLED

1154

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyTrieReturnsNullEmptyArrayAndEmptyEntries()]
negated conditional → KILLED

1158

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → KILLED

1161

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldKeepExactLookupWhenUniformSubtreeContractionIsDisabled()]
negated conditional → KILLED

2.2
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldKeepExactLookupWhenUniformSubtreeContractionIsDisabled()]
changed conditional boundary → KILLED

1162

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldKeepExactLookupWhenUniformSubtreeContractionIsDisabled()]
negated conditional → KILLED

1163

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldContractUniformInternalSubtreeIntoAcceptingLeaf()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → KILLED

1166

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldKeepExactLookupWhenUniformSubtreeContractionIsDisabled()]
negated conditional → KILLED

1170

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldKeepExactLookupWhenUniformSubtreeContractionIsDisabled()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → KILLED

1181

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
negated conditional → KILLED

1182

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
changed conditional boundary → KILLED

2.2
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
Replaced integer subtraction with addition → KILLED

3.3
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
negated conditional → KILLED

1183

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
negated conditional → KILLED

1184

1.1
Location : findNode
Killed by : none
replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → NO_COVERAGE

1187

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
negated conditional → KILLED

1191

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → KILLED

1194

1.1
Location : findNode
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : findNode
Killed by : none
changed conditional boundary → NO_COVERAGE

1195

1.1
Location : findNode
Killed by : none
negated conditional → NO_COVERAGE

1196

1.1
Location : findNode
Killed by : none
replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → NO_COVERAGE

1199

1.1
Location : findNode
Killed by : none
negated conditional → NO_COVERAGE

1203

1.1
Location : findNode
Killed by : none
replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → NO_COVERAGE

1216

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
negated conditional → KILLED

1217

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
Replaced integer subtraction with addition → KILLED

2.2
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
Replaced integer addition with subtraction → KILLED

3.3
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
negated conditional → KILLED

4.4
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
changed conditional boundary → KILLED

1218

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
negated conditional → KILLED

1219

1.1
Location : findNode
Killed by : none
replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → NO_COVERAGE

1222

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
negated conditional → KILLED

1226

1.1
Location : findNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupSupportsCharSlicesAndMetadataAwareKeys()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → KILLED

1229

1.1
Location : findNode
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

1230

1.1
Location : findNode
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : findNode
Killed by : none
changed conditional boundary → NO_COVERAGE

1231

1.1
Location : findNode
Killed by : none
negated conditional → NO_COVERAGE

1232

1.1
Location : findNode
Killed by : none
replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → NO_COVERAGE

1235

1.1
Location : findNode
Killed by : none
negated conditional → NO_COVERAGE

1239

1.1
Location : findNode
Killed by : none
replaced return value with null for org/egothor/stemmer/FrequencyTrie::findNode → NO_COVERAGE

1251

1.1
Location : visitNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
negated conditional → KILLED

1257

1.1
Location : visitNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
negated conditional → KILLED

1263

1.1
Location : visitNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
changed conditional boundary → KILLED

2.2
Location : visitNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
negated conditional → KILLED

1264

1.1
Location : visitNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
Changed increment from 1 to -1 → KILLED

1265

1.1
Location : visitNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
negated conditional → KILLED

1269

1.1
Location : visitNode
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupMatchesGetAllOrderAndGetEntriesCounts()]
replaced int return with 0 for org/egothor/stemmer/FrequencyTrie::visitNode → KILLED

1278

1.1
Location : validateMaxResults
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupRejectsNullAndInvalidRangeArguments()]
negated conditional → KILLED

2.2
Location : validateMaxResults
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:visitorLookupHandlesBoundaryCases()]
changed conditional boundary → KILLED

1290

1.1
Location : normalizeLookupKey
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:lookupKeepsCaseSensitiveBehaviorWhenMetadataIsAsIs()]
replaced return value with "" for org/egothor/stemmer/FrequencyTrie::normalizeLookupKey → KILLED

1300

1.1
Location : normalizeLookupKey
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:lookupAppliesLowercaseNormalizationWhenMetadataRequiresIt()]
negated conditional → KILLED

2.2
Location : normalizeLookupKey
Killed by : none
negated conditional → SURVIVED
Covering tests

1301

1.1
Location : normalizeLookupKey
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:lookupKeepsCaseSensitiveBehaviorWhenMetadataIsAsIs()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::normalizeLookupKey → KILLED

1305

1.1
Location : normalizeLookupKey
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:lookupAppliesLowercaseNormalizationWhenMetadataRequiresIt()]
negated conditional → KILLED

1308

1.1
Location : normalizeLookupKey
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:diacriticRemoveModeStripsDictionaryAndLookupKeys()]
negated conditional → KILLED

1310

1.1
Location : normalizeLookupKey
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyTrieReturnsNullEmptyArrayAndEmptyEntries()]
negated conditional → KILLED

1315

1.1
Location : normalizeLookupKey
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyTrieReturnsNullEmptyArrayAndEmptyEntries()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie::normalizeLookupKey → KILLED

1467

1.1
Location : <init>
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:fallbackDiacriticModeIsNotSupportedYet()]
negated conditional → KILLED

2.2
Location : <init>
Killed by : none
changed conditional boundary → SURVIVED
Covering tests

1519

1.1
Location : put
Killed by : none
replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::put → SURVIVED
Covering tests

1544

1.1
Location : build
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyTrieReturnsNullEmptyArrayAndEmptyEntries()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::build → KILLED

1574

1.1
Location : put
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:fallbackDiacriticModeIsNotSupportedYet()]
changed conditional boundary → KILLED

2.2
Location : put
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:fallbackDiacriticModeIsNotSupportedYet()]
negated conditional → KILLED

1581

1.1
Location : put
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
changed conditional boundary → KILLED

2.2
Location : put
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
negated conditional → KILLED

1585

1.1
Location : put
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:lookupKeepsCaseSensitiveBehaviorWhenMetadataIsAsIs()]
negated conditional → KILLED

1593

1.1
Location : put
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
negated conditional → KILLED

1596

1.1
Location : put
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
Replaced integer addition with subtraction → KILLED

1598

1.1
Location : put
Killed by : none
replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::put → SURVIVED
Covering tests

1611

1.1
Location : normalizeDictionaryKey
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:lookupKeepsCaseSensitiveBehaviorWhenMetadataIsAsIs()]
negated conditional → KILLED

1615

1.1
Location : normalizeDictionaryKey
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:fallbackDiacriticModeIsNotSupportedYet()]
negated conditional → KILLED

1617

1.1
Location : normalizeDictionaryKey
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:fallbackDiacriticModeIsNotSupportedYet()]
negated conditional → KILLED

1622

1.1
Location : normalizeDictionaryKey
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:lookupKeepsCaseSensitiveBehaviorWhenMetadataIsAsIs()]
replaced return value with "" for org/egothor/stemmer/FrequencyTrie$Builder::normalizeDictionaryKey → KILLED

1636

1.1
Location : buildTimeSize
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:reductionMateriallyDecreasesCompiledTrieSizeForRepeatedEquivalentSuffixes()]
replaced int return with 0 for org/egothor/stemmer/FrequencyTrie$Builder::buildTimeSize → KILLED

1645

1.1
Location : traversalDirection
Killed by : none
replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::traversalDirection → NO_COVERAGE

1657

1.1
Location : countMutableNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:reductionMateriallyDecreasesCompiledTrieSizeForRepeatedEquivalentSuffixes()]
Replaced integer addition with subtraction → KILLED

1659

1.1
Location : countMutableNodes
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:reductionMateriallyDecreasesCompiledTrieSizeForRepeatedEquivalentSuffixes()]
replaced int return with 0 for org/egothor/stemmer/FrequencyTrie$Builder::countMutableNodes → KILLED

1679

1.1
Location : reduce
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:lookupKeepsCaseSensitiveBehaviorWhenMetadataIsAsIs()]
negated conditional → KILLED

1681

1.1
Location : reduce
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldContractUniformInternalSubtreeIntoAcceptingLeaf()]
negated conditional → KILLED

1693

1.1
Location : reduce
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:trieRejectsNullLookupKeys()]
negated conditional → KILLED

1695

1.1
Location : reduce
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:dominantReductionMergesQualifiedDominantWinnerNodes()]
removed call to org/egothor/stemmer/trie/ReductionContext::register → KILLED

1696

1.1
Location : reduce
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:trieRejectsNullLookupKeys()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::reduce → KILLED

1699

1.1
Location : reduce
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:dominantReductionMergesQualifiedDominantWinnerNodes()]
removed call to org/egothor/stemmer/trie/ReducedNode::mergeLocalCounts → KILLED

1700

1.1
Location : reduce
Killed by : none
removed call to org/egothor/stemmer/trie/ReducedNode::mergeChildren → SURVIVED
Covering tests

1702

1.1
Location : reduce
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:reductionTakesInternalNodeLocalValuesIntoAccount()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::reduce → KILLED

1716

1.1
Location : contractUniformSubtree
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldContractUniformInternalSubtreeIntoAcceptingLeaf()]
negated conditional → KILLED

1723

1.1
Location : contractUniformSubtree
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldContractUniformInternalSubtreeIntoAcceptingLeaf()]
negated conditional → KILLED

1724

1.1
Location : contractUniformSubtree
Killed by : none
negated conditional → SURVIVED
Covering tests

1733

1.1
Location : contractUniformSubtree
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldContractUniformInternalSubtreeIntoAcceptingLeaf()]
negated conditional → KILLED

1737

1.1
Location : contractUniformSubtree
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldContractUniformInternalSubtreeIntoAcceptingLeaf()]
negated conditional → KILLED

2.2
Location : contractUniformSubtree
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldContractUniformInternalSubtreeIntoAcceptingLeaf()]
negated conditional → KILLED

1744

1.1
Location : contractUniformSubtree
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldContractUniformInternalSubtreeIntoAcceptingLeaf()]
negated conditional → KILLED

1750

1.1
Location : contractUniformSubtree
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldContractUniformInternalSubtreeIntoAcceptingLeaf()]
replaced return value with Collections.emptyMap for org/egothor/stemmer/FrequencyTrie$Builder::contractUniformSubtree → KILLED

1760

1.1
Location : isSingleValueLeaf
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldContractUniformInternalSubtreeIntoAcceptingLeaf()]
negated conditional → KILLED

2.2
Location : isSingleValueLeaf
Killed by : org.egothor.stemmer.CompileTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.CompileTest]/[method:shouldFailWithProcessingErrorWhenOutputExistsAndOverwriteIsNotEnabled()]
replaced boolean return with true for org/egothor/stemmer/FrequencyTrie$Builder::isSingleValueLeaf → KILLED

3.3
Location : isSingleValueLeaf
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:shouldContractUniformInternalSubtreeIntoAcceptingLeaf()]
negated conditional → KILLED

1773

1.1
Location : freeze
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:trieRejectsNullLookupKeys()]
negated conditional → KILLED

1774

1.1
Location : freeze
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:reductionTakesInternalNodeLocalValuesIntoAccount()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::freeze → KILLED

1782

1.1
Location : freeze
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldAllowFurtherModificationsWithoutAffectingSourceTrie()]
removed call to java/util/List::sort → KILLED

1788

1.1
Location : freeze
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:trieRejectsNullLookupKeys()]
changed conditional boundary → KILLED

2.2
Location : freeze
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:trieRejectsNullLookupKeys()]
negated conditional → KILLED

1797

1.1
Location : freeze
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:trieRejectsNullLookupKeys()]
replaced return value with null for org/egothor/stemmer/FrequencyTrie$Builder::freeze → KILLED

1808

1.1
Location : copyCounts
Killed by : org.egothor.stemmer.FrequencyTrieTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieTest]/[method:emptyKeyStoresValuesAtRootNode()]
replaced return value with Collections.emptyMap for org/egothor/stemmer/FrequencyTrie$Builder::copyCounts → KILLED

Active mutators

Tests examined


Report generated by PIT 1.22.1