Repository: casey/just (rust)

Issue:
`unexport` is not backwards-compatible
Was playing with the new `unexport` syntax for `vim-just` and found some weird-looking backwards-incompatible behavior:
```
# In previous versions of just,
# these would create a recipe called "unexport" with parameters "QT_QPA_PLATFORMTHEME" and foo.
# In current just, they unexport QT_QPA_PLATFORMTHEME and create a recipe "foo"
unexport QT_QPA_PLATFORMTHEME \
foo:
	echo Not Foo
unexport QT_QPA_PLATFORMTHEME foo:
	echo Also Not Foo

# just 1.29.0 accepts this line as if it were the two lines
# unexport QT_QPA_PLATFORMTHEME
# and
# foo := 'bar'
# but shouldn't this actually be an error, as it is in previous just versions?
unexport QT_QPA_PLATFORMTHEME foo := 'bar'

# previous versions of just allowed "unexport" to be a recipe name or variable name
# these are now an error, even though they don't conflict with the documented unexport syntax
unexport := 'foo'

unexport:
	echo Unexport Recipe

unexport blah:
	echo {{quote(blah)}}
```

Pull request description:
Fix unexport syntax conflicts
Fixes #2156.

Patch:
diff --git a/src/parser.rs b/src/parser.rs
index 3e4bb022..9ea372c9 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -340,9 +340,13 @@ impl<'run, 'src> Parser<'run, 'src> {
             self.presume_keyword(Keyword::Export)?;
             items.push(Item::Assignment(self.parse_assignment(true)?));
           }
-          Some(Keyword::Unexport) => {
+          Some(Keyword::Unexport)
+            if self.next_are(&[Identifier, Identifier, Eof])
+              || self.next_are(&[Identifier, Identifier, Eol]) =>
+          {
             self.presume_keyword(Keyword::Unexport)?;
             let name = self.parse_name()?;
+            self.expect_eol()?;
             items.push(Item::Unexport { name });
           }
           Some(Keyword::Import)


Test patch:
diff --git a/tests/unexport.rs b/tests/unexport.rs
index 9ca93e87..af46ea1e 100644
--- a/tests/unexport.rs
+++ b/tests/unexport.rs
@@ -99,6 +99,28 @@ fn unexport_doesnt_override_local_recipe_export() {
     )
     .args(["recipe", "value"])
     .stdout("variable: value\n")
-    .status(0)
+    .run();
+}
+
+#[test]
+fn unexport_does_not_conflict_with_recipe_syntax() {
+  Test::new()
+    .justfile(
+      "
+        unexport foo:
+          @echo {{foo}}
+      ",
+    )
+    .args(["unexport", "bar"])
+    .stdout("bar\n")
+    .run();
+}
+
+#[test]
+fn unexport_does_not_conflict_with_assignment_syntax() {
+  Test::new()
+    .justfile("unexport := 'foo'")
+    .args(["--evaluate", "unexport"])
+    .stdout("foo")
     .run();
 }