From de4e19afe6820c9e166b77eab70cc5e8f987edde Mon Sep 17 00:00:00 2001 From: "detail-app[bot]" <180357370+detail-app[bot]@users.noreply.github.com> Date: Sun, 6 Sep 2026 13:59:05 +0000 Subject: [PATCH] fix(retrieval): keep final release in Oxford-comma version lists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The shorthand comparison-chain regex consumed exactly one connector per step, so an Oxford-comma enumeration ending in ", and " put two connectors in sequence; the comma matched, the next token was "and" not a digit, and the chain returned — silently dropping the final requested release (e.g. "Java SE 21, 25, and 26" extracted as [21, 25]). - widen the comma connector alternative to optionally span ", and" in one lookingAt() step so the final release is collected before the chain ends - single-connector chains (/, vs, +, &, bare and) stay untouched: the optional group only fires after a comma --- .../javachat/util/QueryVersionExtractor.java | 3 ++- .../javachat/util/QueryVersionExtractorTest.java | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/williamcallahan/javachat/util/QueryVersionExtractor.java b/src/main/java/com/williamcallahan/javachat/util/QueryVersionExtractor.java index c0dbb0e1..b99f7127 100644 --- a/src/main/java/com/williamcallahan/javachat/util/QueryVersionExtractor.java +++ b/src/main/java/com/williamcallahan/javachat/util/QueryVersionExtractor.java @@ -15,7 +15,8 @@ public final class QueryVersionExtractor { private static final Pattern EXPLICIT_QUANTITY_SUFFIX_PATTERN = Pattern.compile("[\\s-]+(?:days?|hours?|minutes?|seconds?|times|lines?)\\b", Pattern.CASE_INSENSITIVE); private static final Pattern SHORTHAND_VERSION_PATTERN = Pattern.compile( - "^\\s*(?:,|and\\b|vs(?:\\.|\\b)|versus\\b|\\+|/|&)\\s*(\\d{1,3})\\b", Pattern.CASE_INSENSITIVE); + "^\\s*(?:,(?:\\s*and\\b)?|and\\b|vs(?:\\.|\\b)|versus\\b|\\+|/|&)\\s*(\\d{1,3})\\b", + Pattern.CASE_INSENSITIVE); private QueryVersionExtractor() {} diff --git a/src/test/java/com/williamcallahan/javachat/util/QueryVersionExtractorTest.java b/src/test/java/com/williamcallahan/javachat/util/QueryVersionExtractorTest.java index 26482cec..a496cdcd 100644 --- a/src/test/java/com/williamcallahan/javachat/util/QueryVersionExtractorTest.java +++ b/src/test/java/com/williamcallahan/javachat/util/QueryVersionExtractorTest.java @@ -23,6 +23,20 @@ void extractsComparisonShorthandAfterAnExplicitVersion() { assertEquals(List.of("21", "22", "25"), QueryVersionExtractor.extractVersionNumbers("Java 21/22/25 streams")); } + @Test + void extractsOxfordCommaEnumerationWithoutDroppingFinalRelease() { + // Oxford-comma form keeps the final release (the bug: ", and" was two connectors in sequence) + assertEquals(List.of("21", "25", "26"), QueryVersionExtractor.extractVersionNumbers("Java SE 21, 25, and 26")); + // Longer Oxford-comma chain generalizes beyond three releases + assertEquals( + List.of("21", "22", "23", "25"), + QueryVersionExtractor.extractVersionNumbers("Java 21, 22, 23, and 25")); + // All-comma chain (no trailing "and") keeps every release + assertEquals(List.of("21", "22", "25"), QueryVersionExtractor.extractVersionNumbers("Java 21, 22, 25")); + // Non-Oxford "and" (no comma before "and") keeps every release + assertEquals(List.of("21", "22", "25"), QueryVersionExtractor.extractVersionNumbers("Java 21, 22 and 25")); + } + @Test void ignoresUnprefixedNumbersOutsideAComparisonChain() { assertEquals(List.of("21"), QueryVersionExtractor.extractVersionNumbers("Java 21 with 50 examples"));