From 505a1f39a4ac3e97630afdd561b87b84d78c2026 Mon Sep 17 00:00:00 2001 From: rajat315315 Date: Wed, 1 Jul 2026 14:29:48 +0530 Subject: [PATCH 1/3] Refactor conditional statements to switch expression in Dictionary class --- .../lucene/analysis/hunspell/Dictionary.java | 206 ++++++++---------- 1 file changed, 90 insertions(+), 116 deletions(-) diff --git a/lucene/analysis/common/src/java/org/apache/lucene/analysis/hunspell/Dictionary.java b/lucene/analysis/common/src/java/org/apache/lucene/analysis/hunspell/Dictionary.java index afba26735023..19257da15e74 100644 --- a/lucene/analysis/common/src/java/org/apache/lucene/analysis/hunspell/Dictionary.java +++ b/lucene/analysis/common/src/java/org/apache/lucene/analysis/hunspell/Dictionary.java @@ -356,134 +356,108 @@ private void readAffixFile(InputStream affixStream, CharsetDecoder decoder, Flag if (line.isEmpty()) continue; String firstWord = line.split("\\s")[0]; - // TODO: convert to a switch? - if ("AF".equals(firstWord)) { - parseAlias(line); - } else if ("AM".equals(firstWord)) { - parseMorphAlias(line); - } else if ("PFX".equals(firstWord)) { - parseAffix( + switch (firstWord) { + case "AF" -> parseAlias(line); + case "AM" -> parseMorphAlias(line); + case "PFX" -> parseAffix( prefixes, prefixContFlags, line, reader, PREFIX, seenPatterns, seenStrips, flags); - } else if ("SFX".equals(firstWord)) { - parseAffix( + case "SFX" -> parseAffix( suffixes, suffixContFlags, line, reader, SUFFIX, seenPatterns, seenStrips, flags); - } else if (line.equals("COMPLEXPREFIXES")) { - complexPrefixes = + case "COMPLEXPREFIXES" -> complexPrefixes = true; // 2-stage prefix+1-stage suffix instead of 2-stage suffix+1-stage prefix - } else if ("CIRCUMFIX".equals(firstWord)) { - circumfix = flagParsingStrategy.parseFlag(singleArgument(reader, line)); - } else if ("KEEPCASE".equals(firstWord)) { - keepcase = flagParsingStrategy.parseFlag(singleArgument(reader, line)); - } else if ("FORCEUCASE".equals(firstWord)) { - forceUCase = flagParsingStrategy.parseFlag(singleArgument(reader, line)); - } else if ("NEEDAFFIX".equals(firstWord) || "PSEUDOROOT".equals(firstWord)) { - needaffix = flagParsingStrategy.parseFlag(singleArgument(reader, line)); - } else if ("ONLYINCOMPOUND".equals(firstWord)) { - onlyincompound = flagParsingStrategy.parseFlag(singleArgument(reader, line)); - } else if ("CHECKSHARPS".equals(firstWord)) { - checkSharpS = true; - } else if ("IGNORE".equals(firstWord)) { - ignore = singleArgument(reader, line).toCharArray(); - Arrays.sort(ignore); - } else if ("ICONV".equals(firstWord) || "OCONV".equals(firstWord)) { - int num = parseNum(reader, line); - ConvTable res = parseConversions(reader, num); - if (line.startsWith("I")) { - iconv = res; - } else { - oconv = res; + case "CIRCUMFIX" -> circumfix = flagParsingStrategy.parseFlag(singleArgument(reader, line)); + case "KEEPCASE" -> keepcase = flagParsingStrategy.parseFlag(singleArgument(reader, line)); + case "FORCEUCASE" -> forceUCase = flagParsingStrategy.parseFlag(singleArgument(reader, line)); + case "NEEDAFFIX", "PSEUDOROOT" -> needaffix = + flagParsingStrategy.parseFlag(singleArgument(reader, line)); + case "ONLYINCOMPOUND" -> onlyincompound = + flagParsingStrategy.parseFlag(singleArgument(reader, line)); + case "CHECKSHARPS" -> checkSharpS = true; + case "IGNORE" -> { + ignore = singleArgument(reader, line).toCharArray(); + Arrays.sort(ignore); } - } else if ("FULLSTRIP".equals(firstWord)) { - fullStrip = true; - } else if ("LANG".equals(firstWord)) { - language = singleArgument(reader, line); - this.alternateCasing = hasLanguage("tr", "az"); - } else if ("BREAK".equals(firstWord)) { - breaks = parseBreaks(reader, line); - } else if ("WORDCHARS".equals(firstWord)) { - wordChars = firstArgument(reader, line); - } else if ("TRY".equals(firstWord)) { - tryChars = firstArgument(reader, line); - } else if ("REP".equals(firstWord)) { - if (tolerateRepRuleCountMismatches()) { - String[] parts = splitBySpace(reader, line, 2, Integer.MAX_VALUE); - // ignore REP N, as actual N may be incorrect - if (parts.length >= 3) { - repTable.add(new RepEntry(parts[1], parts[2])); + case "ICONV", "OCONV" -> { + int num = parseNum(reader, line); + ConvTable res = parseConversions(reader, num); + if (line.startsWith("I")) { + iconv = res; + } else { + oconv = res; } - } else { + } + case "FULLSTRIP" -> fullStrip = true; + case "LANG" -> { + language = singleArgument(reader, line); + this.alternateCasing = hasLanguage("tr", "az"); + } + case "BREAK" -> breaks = parseBreaks(reader, line); + case "WORDCHARS" -> wordChars = firstArgument(reader, line); + case "TRY" -> tryChars = firstArgument(reader, line); + case "REP" -> { + if (tolerateRepRuleCountMismatches()) { + String[] parts = splitBySpace(reader, line, 2, Integer.MAX_VALUE); + // ignore REP N, as actual N may be incorrect + if (parts.length >= 3) { + repTable.add(new RepEntry(parts[1], parts[2])); + } + } else { + int count = parseNum(reader, line); + for (int i = 0; i < count; i++) { + String[] parts = splitBySpace(reader, reader.readLine(), 3, Integer.MAX_VALUE); + repTable.add(new RepEntry(parts[1], parts[2])); + } + } + } + case "MAP" -> { int count = parseNum(reader, line); for (int i = 0; i < count; i++) { - String[] parts = splitBySpace(reader, reader.readLine(), 3, Integer.MAX_VALUE); - repTable.add(new RepEntry(parts[1], parts[2])); + mapTable.add(parseMapEntry(reader, reader.readLine())); } } - } else if ("MAP".equals(firstWord)) { - int count = parseNum(reader, line); - for (int i = 0; i < count; i++) { - mapTable.add(parseMapEntry(reader, reader.readLine())); - } - } else if ("KEY".equals(firstWord)) { - neighborKeyGroups = singleArgument(reader, line).split("\\|"); - } else if ("NOSPLITSUGS".equals(firstWord)) { - enableSplitSuggestions = false; - } else if ("MAXNGRAMSUGS".equals(firstWord)) { - maxNGramSuggestions = Integer.parseInt(singleArgument(reader, line)); - } else if ("MAXDIFF".equals(firstWord)) { - int i = Integer.parseInt(singleArgument(reader, line)); - if (i < 0 || i > 10) { - throw new ParseException("MAXDIFF should be between 0 and 10", reader.getLineNumber()); + case "KEY" -> neighborKeyGroups = singleArgument(reader, line).split("\\|"); + case "NOSPLITSUGS" -> enableSplitSuggestions = false; + case "MAXNGRAMSUGS" -> maxNGramSuggestions = Integer.parseInt(singleArgument(reader, line)); + case "MAXDIFF" -> { + int i = Integer.parseInt(singleArgument(reader, line)); + if (i < 0 || i > 10) { + throw new ParseException("MAXDIFF should be between 0 and 10", reader.getLineNumber()); + } + maxDiff = i; } - maxDiff = i; - } else if ("ONLYMAXDIFF".equals(firstWord)) { - onlyMaxDiff = true; - } else if ("FORBIDDENWORD".equals(firstWord)) { - forbiddenword = flagParsingStrategy.parseFlag(singleArgument(reader, line)); - } else if ("NOSUGGEST".equals(firstWord)) { - noSuggest = flagParsingStrategy.parseFlag(singleArgument(reader, line)); - } else if ("SUBSTANDARD".equals(firstWord)) { - subStandard = flagParsingStrategy.parseFlag(singleArgument(reader, line)); - } else if ("COMPOUNDMIN".equals(firstWord)) { - compoundMin = Math.max(1, parseNum(reader, line)); - } else if ("COMPOUNDWORDMAX".equals(firstWord)) { - compoundMax = Math.max(1, parseNum(reader, line)); - } else if ("COMPOUNDRULE".equals(firstWord)) { - compoundRules = parseCompoundRules(reader, parseNum(reader, line)); - } else if ("COMPOUNDFLAG".equals(firstWord)) { - compoundFlag = flagParsingStrategy.parseFlag(singleArgument(reader, line)); - } else if ("COMPOUNDBEGIN".equals(firstWord)) { - compoundBegin = flagParsingStrategy.parseFlag(singleArgument(reader, line)); - } else if ("COMPOUNDMIDDLE".equals(firstWord)) { - compoundMiddle = flagParsingStrategy.parseFlag(singleArgument(reader, line)); - } else if ("COMPOUNDEND".equals(firstWord)) { - compoundEnd = flagParsingStrategy.parseFlag(singleArgument(reader, line)); - } else if ("COMPOUNDPERMITFLAG".equals(firstWord)) { - compoundPermit = flagParsingStrategy.parseFlag(singleArgument(reader, line)); - } else if ("COMPOUNDFORBIDFLAG".equals(firstWord)) { - compoundForbid = flagParsingStrategy.parseFlag(singleArgument(reader, line)); - } else if ("CHECKCOMPOUNDCASE".equals(firstWord)) { - checkCompoundCase = true; - } else if ("CHECKCOMPOUNDDUP".equals(firstWord)) { - checkCompoundDup = true; - } else if ("CHECKCOMPOUNDREP".equals(firstWord)) { - checkCompoundRep = true; - } else if ("CHECKCOMPOUNDTRIPLE".equals(firstWord)) { - checkCompoundTriple = true; - } else if ("SIMPLIFIEDTRIPLE".equals(firstWord)) { - simplifiedTriple = true; - } else if ("CHECKCOMPOUNDPATTERN".equals(firstWord)) { - int count = parseNum(reader, line); - for (int i = 0; i < count; i++) { - checkCompoundPatterns.add( - new CheckCompoundPattern(reader.readLine(), flagParsingStrategy, this)); + case "ONLYMAXDIFF" -> onlyMaxDiff = true; + case "FORBIDDENWORD" -> forbiddenword = flagParsingStrategy.parseFlag(singleArgument(reader, line)); + case "NOSUGGEST" -> noSuggest = flagParsingStrategy.parseFlag(singleArgument(reader, line)); + case "SUBSTANDARD" -> subStandard = flagParsingStrategy.parseFlag(singleArgument(reader, line)); + case "COMPOUNDMIN" -> compoundMin = Math.max(1, parseNum(reader, line)); + case "COMPOUNDWORDMAX" -> compoundMax = Math.max(1, parseNum(reader, line)); + case "COMPOUNDRULE" -> compoundRules = parseCompoundRules(reader, parseNum(reader, line)); + case "COMPOUNDFLAG" -> compoundFlag = flagParsingStrategy.parseFlag(singleArgument(reader, line)); + case "COMPOUNDBEGIN" -> compoundBegin = flagParsingStrategy.parseFlag(singleArgument(reader, line)); + case "COMPOUNDMIDDLE" -> compoundMiddle = flagParsingStrategy.parseFlag(singleArgument(reader, line)); + case "COMPOUNDEND" -> compoundEnd = flagParsingStrategy.parseFlag(singleArgument(reader, line)); + case "COMPOUNDPERMITFLAG" -> compoundPermit = flagParsingStrategy.parseFlag(singleArgument(reader, line)); + case "COMPOUNDFORBIDFLAG" -> compoundForbid = flagParsingStrategy.parseFlag(singleArgument(reader, line)); + case "CHECKCOMPOUNDCASE" -> checkCompoundCase = true; + case "CHECKCOMPOUNDDUP" -> checkCompoundDup = true; + case "CHECKCOMPOUNDREP" -> checkCompoundRep = true; + case "CHECKCOMPOUNDTRIPLE" -> checkCompoundTriple = true; + case "SIMPLIFIEDTRIPLE" -> simplifiedTriple = true; + case "CHECKCOMPOUNDPATTERN" -> { + int count = parseNum(reader, line); + for (int i = 0; i < count; i++) { + checkCompoundPatterns.add( + new CheckCompoundPattern(reader.readLine(), flagParsingStrategy, this)); + } } - } else if ("SET".equals(firstWord)) { - checkCriticalDirectiveSame( + case "SET" -> checkCriticalDirectiveSame( "SET", reader, decoder.charset(), getDecoder(singleArgument(reader, line)).charset()); - } else if ("FLAG".equals(firstWord)) { - FlagParsingStrategy strategy = getFlagParsingStrategy(line, decoder.charset()); - checkCriticalDirectiveSame( - "FLAG", reader, flagParsingStrategy.getClass(), strategy.getClass()); + case "FLAG" -> { + FlagParsingStrategy strategy = getFlagParsingStrategy(line, decoder.charset()); + checkCriticalDirectiveSame( + "FLAG", reader, flagParsingStrategy.getClass(), strategy.getClass()); + } + default -> {} } } From 7c1c68b0170adcbae31311dfcdeda6fbb71a6729 Mon Sep 17 00:00:00 2001 From: rajat315315 Date: Wed, 1 Jul 2026 14:41:57 +0530 Subject: [PATCH 2/3] Refactor Hunspell dictionary parser to use switch-based dispatch for affix directives --- lucene/CHANGES.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index 42a6e8073576..f2e004c4f651 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -139,6 +139,9 @@ Improvements * GITHUB#15558: Refactor QueryCache for performance. (Sagar Upadhyaya) +* GITHUB#16313: Refactored the Hunspell dictionary parser to use switch-based dispatch for affix directives, + improving readability of the parsing logic. (Rajat Jain) + Optimizations --------------------- * GITHUB#16254: Enable the vectorized findNextGEQ path on aarch64, where it was disabled on cores From a0008f29ec0491ae01cbd0a2f6e18a1e41665954 Mon Sep 17 00:00:00 2001 From: Dawid Weiss Date: Tue, 21 Jul 2026 21:33:17 +0200 Subject: [PATCH 3/3] gradlew tidy --- .../lucene/analysis/hunspell/Dictionary.java | 58 ++++++++++++------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/lucene/analysis/common/src/java/org/apache/lucene/analysis/hunspell/Dictionary.java b/lucene/analysis/common/src/java/org/apache/lucene/analysis/hunspell/Dictionary.java index 19257da15e74..5a0c8f3ae519 100644 --- a/lucene/analysis/common/src/java/org/apache/lucene/analysis/hunspell/Dictionary.java +++ b/lucene/analysis/common/src/java/org/apache/lucene/analysis/hunspell/Dictionary.java @@ -359,19 +359,23 @@ private void readAffixFile(InputStream affixStream, CharsetDecoder decoder, Flag switch (firstWord) { case "AF" -> parseAlias(line); case "AM" -> parseMorphAlias(line); - case "PFX" -> parseAffix( - prefixes, prefixContFlags, line, reader, PREFIX, seenPatterns, seenStrips, flags); - case "SFX" -> parseAffix( - suffixes, suffixContFlags, line, reader, SUFFIX, seenPatterns, seenStrips, flags); - case "COMPLEXPREFIXES" -> complexPrefixes = - true; // 2-stage prefix+1-stage suffix instead of 2-stage suffix+1-stage prefix + case "PFX" -> + parseAffix( + prefixes, prefixContFlags, line, reader, PREFIX, seenPatterns, seenStrips, flags); + case "SFX" -> + parseAffix( + suffixes, suffixContFlags, line, reader, SUFFIX, seenPatterns, seenStrips, flags); + case "COMPLEXPREFIXES" -> + complexPrefixes = + true; // 2-stage prefix+1-stage suffix instead of 2-stage suffix+1-stage prefix case "CIRCUMFIX" -> circumfix = flagParsingStrategy.parseFlag(singleArgument(reader, line)); case "KEEPCASE" -> keepcase = flagParsingStrategy.parseFlag(singleArgument(reader, line)); - case "FORCEUCASE" -> forceUCase = flagParsingStrategy.parseFlag(singleArgument(reader, line)); - case "NEEDAFFIX", "PSEUDOROOT" -> needaffix = - flagParsingStrategy.parseFlag(singleArgument(reader, line)); - case "ONLYINCOMPOUND" -> onlyincompound = - flagParsingStrategy.parseFlag(singleArgument(reader, line)); + case "FORCEUCASE" -> + forceUCase = flagParsingStrategy.parseFlag(singleArgument(reader, line)); + case "NEEDAFFIX", "PSEUDOROOT" -> + needaffix = flagParsingStrategy.parseFlag(singleArgument(reader, line)); + case "ONLYINCOMPOUND" -> + onlyincompound = flagParsingStrategy.parseFlag(singleArgument(reader, line)); case "CHECKSHARPS" -> checkSharpS = true; case "IGNORE" -> { ignore = singleArgument(reader, line).toCharArray(); @@ -426,18 +430,26 @@ private void readAffixFile(InputStream affixStream, CharsetDecoder decoder, Flag maxDiff = i; } case "ONLYMAXDIFF" -> onlyMaxDiff = true; - case "FORBIDDENWORD" -> forbiddenword = flagParsingStrategy.parseFlag(singleArgument(reader, line)); + case "FORBIDDENWORD" -> + forbiddenword = flagParsingStrategy.parseFlag(singleArgument(reader, line)); case "NOSUGGEST" -> noSuggest = flagParsingStrategy.parseFlag(singleArgument(reader, line)); - case "SUBSTANDARD" -> subStandard = flagParsingStrategy.parseFlag(singleArgument(reader, line)); + case "SUBSTANDARD" -> + subStandard = flagParsingStrategy.parseFlag(singleArgument(reader, line)); case "COMPOUNDMIN" -> compoundMin = Math.max(1, parseNum(reader, line)); case "COMPOUNDWORDMAX" -> compoundMax = Math.max(1, parseNum(reader, line)); case "COMPOUNDRULE" -> compoundRules = parseCompoundRules(reader, parseNum(reader, line)); - case "COMPOUNDFLAG" -> compoundFlag = flagParsingStrategy.parseFlag(singleArgument(reader, line)); - case "COMPOUNDBEGIN" -> compoundBegin = flagParsingStrategy.parseFlag(singleArgument(reader, line)); - case "COMPOUNDMIDDLE" -> compoundMiddle = flagParsingStrategy.parseFlag(singleArgument(reader, line)); - case "COMPOUNDEND" -> compoundEnd = flagParsingStrategy.parseFlag(singleArgument(reader, line)); - case "COMPOUNDPERMITFLAG" -> compoundPermit = flagParsingStrategy.parseFlag(singleArgument(reader, line)); - case "COMPOUNDFORBIDFLAG" -> compoundForbid = flagParsingStrategy.parseFlag(singleArgument(reader, line)); + case "COMPOUNDFLAG" -> + compoundFlag = flagParsingStrategy.parseFlag(singleArgument(reader, line)); + case "COMPOUNDBEGIN" -> + compoundBegin = flagParsingStrategy.parseFlag(singleArgument(reader, line)); + case "COMPOUNDMIDDLE" -> + compoundMiddle = flagParsingStrategy.parseFlag(singleArgument(reader, line)); + case "COMPOUNDEND" -> + compoundEnd = flagParsingStrategy.parseFlag(singleArgument(reader, line)); + case "COMPOUNDPERMITFLAG" -> + compoundPermit = flagParsingStrategy.parseFlag(singleArgument(reader, line)); + case "COMPOUNDFORBIDFLAG" -> + compoundForbid = flagParsingStrategy.parseFlag(singleArgument(reader, line)); case "CHECKCOMPOUNDCASE" -> checkCompoundCase = true; case "CHECKCOMPOUNDDUP" -> checkCompoundDup = true; case "CHECKCOMPOUNDREP" -> checkCompoundRep = true; @@ -450,8 +462,12 @@ private void readAffixFile(InputStream affixStream, CharsetDecoder decoder, Flag new CheckCompoundPattern(reader.readLine(), flagParsingStrategy, this)); } } - case "SET" -> checkCriticalDirectiveSame( - "SET", reader, decoder.charset(), getDecoder(singleArgument(reader, line)).charset()); + case "SET" -> + checkCriticalDirectiveSame( + "SET", + reader, + decoder.charset(), + getDecoder(singleArgument(reader, line)).charset()); case "FLAG" -> { FlagParsingStrategy strategy = getFlagParsingStrategy(line, decoder.charset()); checkCriticalDirectiveSame(