LCOV - code coverage report
Current view: top level - src - stemmer.dart (source / functions) Coverage Total Hit
Test: lcov.info Lines: 100.0 % 64 64
Test Date: 2026-07-06 21:45:09 Functions: - 0 0

            Line data    Source code
       1              : // Copyright 2026 The Authors
       2              : //
       3              : // Licensed under the Apache License, Version 2.0 (the "License");
       4              : // you may not use this file except in compliance with the License.
       5              : // You may obtain a copy of the License at
       6              : //
       7              : //      https://www.apache.org/licenses/LICENSE-2.0
       8              : //
       9              : // Unless required by applicable law or agreed to in writing, software
      10              : // distributed under the License is distributed on an "AS IS" BASIS,
      11              : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12              : // See the License for the specific language governing permissions and
      13              : // limitations under the License.
      14              : 
      15              : import 'package:intl/locale.dart';
      16              : import 'package:snowball_stemmer/snowball_stemmer.dart';
      17              : 
      18              : /// Reduces words to their base form (stem) using the Snowball algorithm.
      19              : ///
      20              : /// Supports 28 languages (see [Stemmer.new] for the full list). Construct
      21              : /// with a [Locale] and call [stem] on individual tokens.
      22              : ///
      23              : /// ```dart
      24              : /// final stemmer = Stemmer(Locale.parse('en'));
      25              : /// print(stemmer.stem('libraries')); // → 'librari'
      26              : /// print(stemmer.stem('running'));   // → 'run'
      27              : /// ```
      28              : class Stemmer {
      29              :   final Locale _locale;
      30              :   final SnowballStemmer _stemmer;
      31              : 
      32            1 :   Stemmer._internal(Locale locale, SnowballStemmer stemmer)
      33              :     : _locale = locale,
      34              :       _stemmer = stemmer;
      35              : 
      36              :   /// Creates a [Stemmer] for the given [locale].
      37              :   ///
      38              :   /// Throws [ArgumentError] if the locale's language code is not supported.
      39              :   ///
      40              :   /// Supported (ISO 639-1 → Snowball algorithm): `ar` (Arabic), `hy`
      41              :   /// (Armenian), `eu` (Basque), `ca` (Catalan), `da` (Danish), `nl` (Dutch),
      42              :   /// `en` (English), `fi` (Finnish), `fr` (French), `de` (German), `el`
      43              :   /// (Greek), `hi` (Hindi), `hu` (Hungarian), `id` (Indonesian), `ga`
      44              :   /// (Irish), `it` (Italian), `lt` (Lithuanian), `ne` (Nepali), `no`
      45              :   /// (Norwegian), `pt` (Portuguese), `ro` (Romanian), `ru` (Russian), `sr`
      46              :   /// (Serbian), `es` (Spanish), `sv` (Swedish), `ta` (Tamil), `tr` (Turkish),
      47              :   /// `yi` (Yiddish) — every language `package:snowball_stemmer` implements,
      48              :   /// except its generic `porter` variant (an alternate English algorithm,
      49              :   /// not a distinct language — `en` already maps to `Algorithm.english`).
      50            1 :   factory Stemmer(Locale locale) {
      51            1 :     switch (locale.languageCode) {
      52            1 :       case 'ar':
      53            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.arabic));
      54            1 :       case 'hy':
      55            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.armenian));
      56            1 :       case 'eu':
      57            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.basque));
      58            1 :       case 'ca':
      59            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.catalan));
      60            1 :       case 'da':
      61            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.danish));
      62            1 :       case 'nl':
      63            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.dutch));
      64            1 :       case 'en':
      65            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.english));
      66            1 :       case 'fi':
      67            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.finnish));
      68            1 :       case 'fr':
      69            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.french));
      70            1 :       case 'de':
      71            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.german));
      72            1 :       case 'el':
      73            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.greek));
      74            1 :       case 'hi':
      75            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.hindi));
      76            1 :       case 'hu':
      77            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.hungarian));
      78            1 :       case 'id':
      79            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.indonesian));
      80            1 :       case 'ga':
      81            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.irish));
      82            1 :       case 'it':
      83            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.italian));
      84            1 :       case 'lt':
      85            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.lithuanian));
      86            1 :       case 'ne':
      87            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.nepali));
      88            1 :       case 'no':
      89            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.norwegian));
      90            1 :       case 'pt':
      91            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.portuguese));
      92            1 :       case 'ro':
      93            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.romanian));
      94            1 :       case 'ru':
      95            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.russian));
      96            1 :       case 'sr':
      97            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.serbian));
      98            1 :       case 'es':
      99            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.spanish));
     100            1 :       case 'sv':
     101            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.swedish));
     102            1 :       case 'ta':
     103            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.tamil));
     104            1 :       case 'tr':
     105            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.turkish));
     106            1 :       case 'yi':
     107            2 :         return Stemmer._internal(locale, SnowballStemmer(Algorithm.yiddish));
     108              :     }
     109            1 :     throw ArgumentError.value(
     110            1 :       locale.languageCode,
     111              :       'locale.languageCode',
     112              :       'No stemmer available for language',
     113              :     );
     114              :   }
     115              : 
     116              :   /// Returns the stem of [word].
     117              :   ///
     118              :   /// The result is a normalised base form suitable for index lookups; it is
     119              :   /// not guaranteed to be a valid dictionary word.
     120            1 :   String stem(String word) {
     121            2 :     return _stemmer.stem(word);
     122              :   }
     123              : 
     124              :   /// The IETF language code this stemmer was created for (e.g. `'en'`).
     125            3 :   String get languageCode => _locale.languageCode;
     126              : }
        

Generated by: LCOV version 2.0-1