Repository: Behat/Gherkin (php)

Issue:
Upstream gherkin breaks if language is not recognised
Cucumber repo has an example with an unknown language, which should cause a parse error. We default back to `en` I believe

Pull request description:
Reject invalid language in gherkin compatibility mode
Closes #156

Patch:
diff --git a/src/GherkinCompatibilityMode.php b/src/GherkinCompatibilityMode.php
index 5d8cff3..6ed5a33 100644
--- a/src/GherkinCompatibilityMode.php
+++ b/src/GherkinCompatibilityMode.php
@@ -31,4 +31,15 @@ enum GherkinCompatibilityMode: string
             default => false,
         };
     }
+
+    /**
+     * @internal
+     */
+    public function shouldIgnoreInvalidLanguage(): bool
+    {
+        return match ($this) {
+            self::LEGACY => true,
+            default => false,
+        };
+    }
 }
diff --git a/src/Lexer.php b/src/Lexer.php
index 8761a7d..73244f4 100644
--- a/src/Lexer.php
+++ b/src/Lexer.php
@@ -37,6 +37,7 @@ class Lexer
     private const CELL_PATTERN = '/(?<!\\\\)(?:\\\\{2})*\K\\|/u';
     private readonly DialectProviderInterface $dialectProvider;
     private GherkinDialect $currentDialect;
+    private GherkinCompatibilityMode $compatibilityMode = GherkinCompatibilityMode::LEGACY;
     /**
      * @var list<string>
      */
@@ -80,6 +81,14 @@ class Lexer
         $this->dialectProvider = $dialectProvider;
     }
 
+    /**
+     * @internal
+     */
+    public function setCompatibilityMode(GherkinCompatibilityMode $compatibilityMode): void
+    {
+        $this->compatibilityMode = $compatibilityMode;
+    }
+
     /**
      * Sets lexer input.
      *
@@ -152,8 +161,10 @@ class Lexer
 
         try {
             $this->currentDialect = $this->dialectProvider->getDialect($language);
-        } catch (NoSuchLanguageException) {
-            // TODO rethrow the exception when introducing the compatibility mode for invalid languages.
+        } catch (NoSuchLanguageException $e) {
+            if (!$this->compatibilityMode->shouldIgnoreInvalidLanguage()) {
+                throw $e;
+            }
         }
         $this->stepKeywordTypesCache = null;
     }
diff --git a/src/Parser.php b/src/Parser.php
index 88007a5..6dfb565 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -73,6 +73,7 @@ class Parser
         $this->input = $input;
         $this->file = $file;
         $this->tags = [];
+        $this->lexer->setCompatibilityMode($this->compatibilityMode);
 
         try {
             $this->lexer->analyse($this->input);


Test patch:
diff --git a/tests/Cucumber/CompatibilityTest.php b/tests/Cucumber/CompatibilityTest.php
index 56f57ed..c181944 100644
--- a/tests/Cucumber/CompatibilityTest.php
+++ b/tests/Cucumber/CompatibilityTest.php
@@ -82,7 +82,6 @@ class CompatibilityTest extends TestCase
             'invalid_language.feature' => 'Invalid language is silently ignored',
         ],
         'gherkin-32' => [
-            'invalid_language.feature' => 'Invalid language is silently ignored',
         ],
     ];
 
diff --git a/tests/ParserTest.php b/tests/ParserTest.php
index 1cdca58..03bc3f3 100644
--- a/tests/ParserTest.php
+++ b/tests/ParserTest.php
@@ -75,9 +75,8 @@ final class ParserTest extends TestCase
         $this->assertSame([], $feature2->getTags());
     }
 
-    public function testParserIgnoresInvalidLanguage(): void
+    public function testParserIgnoresInvalidLanguageInLegacyMode(): void
     {
-        // TODO skip this test for the compatibility mode with cucumber/gherkin
         $feature = $this->createGherkinParser()->parse(
             <<<'FEATURE'
             #language:no-such
@@ -93,9 +92,8 @@ final class ParserTest extends TestCase
         $this->assertCount(1, $feature->getScenarios());
     }
 
-    public function testParserIgnoresInvalidLanguageWithDialectProvider(): void
+    public function testParserIgnoresInvalidLanguageInLegacyModeWithDialectProvider(): void
     {
-        // TODO skip this test for the compatibility mode with cucumber/gherkin
         $feature = $this->createGherkinParser(new Lexer(new CucumberDialectProvider()))->parse(
             <<<'FEATURE'
             #language:no-such