Repository: google/closure-compiler (java)

Issue:
ERROR - Parse error. cannot use keyword 'type' here.
When I tried to compile my ECMAScript 6 program using the Closure Compiler, I ran into this error.

Here is the smallest reproducible test case:

```
var { type } = { type: 1 };
```

And here is the error message I get:

```
test.js:1: ERROR - Parse error. cannot use keyword 'type' here.
var { type } = { type: 1 };
           ^
```

As far as I know, `type` is not a keyword or reserved word in any version of ECMAScript.

----

In addition, this code compiles perfectly fine:

```
var type = 1;
```

So it seems Closure is only treating `type` as a keyword in certain situations.

Pull request description:
Fix spurious parse error on TypeScript keywords
TypeScript specific keywords should be allowed as object literal field names. Fixed the parser to not report errors on them.

Fixes #1135 and #1136

Patch:
diff --git a/src/com/google/javascript/jscomp/parsing/parser/Keywords.java b/src/com/google/javascript/jscomp/parsing/parser/Keywords.java
index a57e3c10a..4d4575138 100644
--- a/src/com/google/javascript/jscomp/parsing/parser/Keywords.java
+++ b/src/com/google/javascript/jscomp/parsing/parser/Keywords.java
@@ -121,6 +121,18 @@ public enum Keywords {
     return get(token) != null;
   }
 
+  public static boolean isTypeScriptSpecificKeyword(String value) {
+    switch (value) {
+      case "declare":
+      case "type":
+      case "module":
+      case "namespace":
+        return true;
+      default:
+        return false;
+    }
+  }
+
   /**
    * Returns true if {@code token} is a "future reserved word" which can
    * be used as a variable identifier, but only in non-strict mode.
diff --git a/src/com/google/javascript/jscomp/parsing/parser/Parser.java b/src/com/google/javascript/jscomp/parsing/parser/Parser.java
index dcc48d2ae..b2131fb36 100644
--- a/src/com/google/javascript/jscomp/parsing/parser/Parser.java
+++ b/src/com/google/javascript/jscomp/parsing/parser/Parser.java
@@ -2431,7 +2431,8 @@ public class Parser {
     if (colon == null) {
       if (name.type != TokenType.IDENTIFIER) {
         reportExpectedError(peekToken(), TokenType.COLON);
-      } else if (Keywords.isKeyword(name.asIdentifier().value)) {
+      } else if (Keywords.isKeyword(name.asIdentifier().value)
+          && !Keywords.isTypeScriptSpecificKeyword(name.asIdentifier().value)) {
         reportError(name, "Cannot use keyword in short object literal");
       }
     }
@@ -3239,7 +3240,8 @@ public class Parser {
       name = eatIdOrKeywordAsId();
       if (!peek(TokenType.COLON)) {
         IdentifierToken idToken = (IdentifierToken) name;
-        if (Keywords.isKeyword(idToken.value)) {
+        if (Keywords.isKeyword(idToken.value)
+            && !Keywords.isTypeScriptSpecificKeyword(idToken.value)) {
           reportError("cannot use keyword '" + name + "' here.");
         }
         if (peek(TokenType.EQUAL)) {


Test patch:
diff --git a/test/com/google/javascript/jscomp/parsing/NewParserTest.java b/test/com/google/javascript/jscomp/parsing/NewParserTest.java
index 421a4230a..98e4f10e8 100644
--- a/test/com/google/javascript/jscomp/parsing/NewParserTest.java
+++ b/test/com/google/javascript/jscomp/parsing/NewParserTest.java
@@ -1025,6 +1025,10 @@ public final class NewParserTest extends BaseJSTypeTestCase {
     testExtendedObjectLiteral("var a = {b};");
     testExtendedObjectLiteral("var a = {b, c};");
     testExtendedObjectLiteral("var a = {b, c: d, e};");
+    testExtendedObjectLiteral("var a = {type};");
+    testExtendedObjectLiteral("var a = {declare};");
+    testExtendedObjectLiteral("var a = {namespace};");
+    testExtendedObjectLiteral("var a = {module};");
 
     parseError("var a = { '!@#$%' };", "':' expected");
     parseError("var a = { 123 };", "':' expected");
@@ -1368,6 +1372,11 @@ public final class NewParserTest extends BaseJSTypeTestCase {
     mode = LanguageMode.ECMASCRIPT6;
     parse("var {if: x, else: y} = foo();");
     parse("var {while: x=1, for: y} = foo();");
+    parse("var {type} = foo();");
+    parse("var {declare} = foo();");
+    parse("var {module} = foo();");
+    parse("var {namespace} = foo();");
+
     parseError("var {while} = foo();", "cannot use keyword 'while' here.");
     parseError("var {implements} = foo();", "cannot use keyword 'implements' here.");
   }