Repository: alangpierce/sucrase
Pull request #722 (2022-07-14 00:59:08)

Fix parse failure in TS when default-importing the name "type"
The token `from` is actually a `tt.name`, so we can use our existing lookahead
to distinguish that case. The line `import type from from './foo';` is invalid,
so we know that `from` after `type` is always a true `from` token, meaning that
`type` is just the imported name.

Also add a TODO comment to the babel test checker with a little more thoughts on
how to approach the remaining flagged issues.

codecov[bot]: # [Codecov](https://codecov.io/gh/alangpierce/sucrase/pull/722?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alan+Pierce) Report
> Merging [#722](https://codecov.io/gh/alangpierce/sucrase/pull/722?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alan+Pierce) (abb8d56) into [main](https://codecov.io/gh/alangpierce/sucrase/commit/f9aeb43f63793767e3061b6306b8fe7c85e68360?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alan+Pierce) (f9aeb43) will **increase** coverage by `0.01%`.
> The diff coverage is `100.00%`.

```diff
@@            Coverage Diff             @@
##             main     #722      +/-   ##
==========================================
+ Coverage   87.03%   87.05%   +0.01%     
==========================================
  Files          54       54              
  Lines        5702     5702              
  Branches     1343     1343              
==========================================
+ Hits         4963     4964       +1     
  Misses        470      470              
+ Partials      269      268       -1     
```


| [Impacted Files](https://codecov.io/gh/alangpierce/sucrase/pull/722?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alan+Pierce) | Coverage Δ | |
|---|---|---|
| [src/parser/traverser/statement.ts](https://codecov.io/gh/alangpierce/sucrase/pull/722/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alan+Pierce#diff-c3JjL3BhcnNlci90cmF2ZXJzZXIvc3RhdGVtZW50LnRz) | `83.44% <100.00%> (+0.16%)` | :arrow_up: |

:mega: Codecov can now indicate which changes are the most critical in Pull Requests. [Learn more](https://about.codecov.io/product/feature/runtime-insights/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alan+Pierce)

github-actions[bot]: ## Benchmark results
**Before this PR:** 330.1 thousand lines per second
**After this PR:**  332.4 thousand lines per second

**Measured change:** 0.7% faster (1.06% slower to 1.79% faster)
**Summary:** Likely no significant difference

Patch:
diff --git a/src/parser/traverser/statement.ts b/src/parser/traverser/statement.ts
index dbb6d28..24ccfc9 100644
--- a/src/parser/traverser/statement.ts
+++ b/src/parser/traverser/statement.ts
@@ -1088,8 +1088,8 @@ export function parseImport(): void {
     return;
   }
   if (isTypeScriptEnabled && isContextual(ContextualKeyword._type)) {
-    const lookahead = lookaheadType();
-    if (lookahead === tt.name) {
+    const lookahead = lookaheadTypeAndKeyword();
+    if (lookahead.type === tt.name && lookahead.contextualKeyword !== ContextualKeyword._from) {
       // One of these `import type` cases:
       // import type T = require('T');
       // import type A from 'A';
@@ -1100,7 +1100,7 @@ export function parseImport(): void {
       }
       // If this is an `import type...from` statement, then we already ate the
       // type token, so proceed to the regular import parser.
-    } else if (lookahead === tt.star || lookahead === tt.braceL) {
+    } else if (lookahead.type === tt.star || lookahead.type === tt.braceL) {
       // One of these `import type` cases, in which case we can eat the type token
       // and proceed as normal:
       // import type * as A from 'A';


Test patch:
diff --git a/spec-compliance-tests/babel-tests/check-babel-tests.ts b/spec-compliance-tests/babel-tests/check-babel-tests.ts
index 6ecae67..324beef 100644
--- a/spec-compliance-tests/babel-tests/check-babel-tests.ts
+++ b/spec-compliance-tests/babel-tests/check-babel-tests.ts
@@ -13,6 +13,18 @@ const FIXTURES_DIR = `${BABEL_TESTS_DIR}/packages/babel-parser/test/fixtures`;
 const BABEL_REPO_URL = "https://github.com/babel/babel.git";
 const BABEL_REVISION = "bcf8b2273b8cba44c9b93c8977f05d508bfc1b91";
 
+/*
+ * TODO: Work through these failures to better understand and characterize them.
+ *
+ * There seem to be a few categories of test failures:
+ * - Real errors that should be fixed when possible.
+ * - Cases that are so obscure and hard to implement that Sucrase intentionally
+ *   skips them. These should ideally have an inline explanation here.
+ * - Cases that are unsupported in Sucrase but are flagged as failures, e.g.
+ *   syntax not part of the spec that is supported by Babel. Many of these may
+ *   be possible to fix automatically by improving the step where we run Babel
+ *   to see if it also fails.
+ */
 const KNOWN_FAILURES = `
 es2015/let/let-declaration-in-escape-id
 es2015/yield/accessor-name-inst-computed-yield-expr
@@ -72,7 +84,6 @@ typescript/import/export-import
 typescript/import/export-import-require
 typescript/import/export-import-type-as-identifier
 typescript/import/export-import-type-require
-typescript/import/import-default-id-type
 typescript/import/type-asi
 typescript/import/type-equals-require
 `
diff --git a/test/typescript-test.ts b/test/typescript-test.ts
index b220202..d4f64d1 100644
--- a/test/typescript-test.ts
+++ b/test/typescript-test.ts
@@ -2225,6 +2225,32 @@ describe("typescript transform", () => {
     );
   });
 
+  it("allows a default import named type in ESM mode", () => {
+    assertTypeScriptESMResult(
+      `
+      import type from './type';
+      console.log(type);
+    `,
+      `
+      import type from './type';
+      console.log(type);
+    `,
+    );
+  });
+
+  it("allows a default import named type in CJS mode", () => {
+    assertTypeScriptResult(
+      `
+      import type from './type';
+      console.log(type);
+    `,
+      `"use strict";${IMPORT_DEFAULT_PREFIX}
+      var _type = require('./type'); var _type2 = _interopRequireDefault(_type);
+      console.log(_type2.default);
+    `,
+    );
+  });
+
   it("parses and removes named import type statements in ESM mode", () => {
     assertTypeScriptESMResult(
       `