Repository: psf/black

Issue:
parser: correctly identify error location on soft-keywords
Currently it only throws the error on the first-seen node (?):

```
(.venv) (3.9.5) [  6:53ÖS ]  [ isidentical@msi:~ ]
 $ cat t.py                                                                                                   140ms
def something():
    match something:
        case t:
            pass

    match arg:
        case t:
            print(t)
        case z := u:
            print(a)
(.venv) (3.9.5) [  6:53ÖS ]  [ isidentical@msi:~ ]
 $ black -tpy310 --fast t.py                                                                                    2ms
error: cannot format t.py: Cannot parse: 2:10:     match something:
Oh no! 💥 💔 💥
1 file failed to reformat.
(.venv) (3.9.5) [  6:53ÖS ]  [ isidentical@msi:~ ]
 $ .venv310/bin/python -m ast t.py                                                                            147ms
Traceback (most recent call last):
 File "t.py", line 9
    case z := u:
           ^^
SyntaxError: expected ':'
```


Discussion:
This is because it tries multiple grammars in parsing.py. I added some print statements:
```
(black) jelle@mbpt-root black % black -t py310 t.py
try <blib2to3.pgen2.grammar.Grammar object at 0x103180d30>
Cannot parse: 9:15:         case z := u:
try <blib2to3.pgen2.grammar.Grammar object at 0x103180cd0>
Cannot parse: 2:10:     match something:
error: cannot format t.py: Cannot parse: 2:10:     match something:
```

I think it shouldn't try other grammars if we're in `-t py310` mode.

Resolving patch:
diff --git a/src/black/parsing.py b/src/black/parsing.py
--- a/src/black/parsing.py
+++ b/src/black/parsing.py
@@ -75,8 +75,10 @@ def get_grammars(target_versions: Set[TargetVersion]) -> List[Grammar]:
         # Python 3.10+
         grammars.append(pygram.python_grammar_soft_keywords)
     # If we have to parse both, try to parse async as a keyword first
-    if not supports_feature(target_versions, Feature.ASYNC_IDENTIFIERS):
-        # Python 3.7+
+    if not supports_feature(
+        target_versions, Feature.ASYNC_IDENTIFIERS
+    ) and not supports_feature(target_versions, Feature.PATTERN_MATCHING):
+        # Python 3.7-3.9
         grammars.append(
             pygram.python_grammar_no_print_statement_no_exec_statement_async_keywords
         )


Test patch:
diff --git a/tests/data/pattern_matching_invalid.py b/tests/data/pattern_matching_invalid.py
new file mode 100644
--- /dev/null
+++ b/tests/data/pattern_matching_invalid.py
@@ -0,0 +1,18 @@
+# First match, no errors
+match something:
+    case bla():
+        pass
+
+# Problem on line 10
+match invalid_case:
+    case valid_case:
+        pass
+    case a := b:
+        pass
+    case valid_case:
+        pass
+
+# No problems either
+match something:
+    case bla():
+        pass
diff --git a/tests/test_format.py b/tests/test_format.py
--- a/tests/test_format.py
+++ b/tests/test_format.py
@@ -200,6 +200,15 @@ def test_python_310(filename: str) -> None:
     assert_format(source, expected, mode, minimum_version=(3, 10))
 
 
+def test_patma_invalid() -> None:
+    source, expected = read_data("pattern_matching_invalid")
+    mode = black.Mode(target_versions={black.TargetVersion.PY310})
+    with pytest.raises(black.parsing.InvalidInput) as exc_info:
+        assert_format(source, expected, mode, minimum_version=(3, 10))
+
+    exc_info.match("Cannot parse: 10:11")
+
+
 def test_docstring_no_string_normalization() -> None:
     """Like test_docstring but with string normalization off."""
     source, expected = read_data("docstring_no_string_normalization")