Merge pull request #14484 from aibaars/ts53-js

JS: Support import attributes
This commit is contained in:
Arthur Baars
2023-10-16 10:47:49 +02:00
committed by GitHub
18 changed files with 2734 additions and 1418 deletions

View File

@@ -0,0 +1,7 @@
---
category: minorAnalysis
---
* [Import attributes](https://github.com/tc39/proposal-import-attributes) are now supported in JavaScript code.
Note that import attributes are an evolution of an earlier proposal called "import assertions", which were implemented in TypeScript 4.5.
The QL library includes new predicates named `getImportAttributes()` that should be used in favor of the now deprecated `getImportAssertion()`;
in addition, the `getImportAttributes()` method of the `DynamicImportExpr` has been renamed to `getImportOptions()`.

View File

@@ -91,14 +91,27 @@ class ImportDeclaration extends Stmt, Import, @import_declaration {
override PathExpr getImportedPath() { result = this.getChildExpr(-1) }
/**
* Gets the object literal passed as part of the `assert` clause in this import declaration.
* Gets the object literal passed as part of the `with` (or `assert`) clause in this import declaration.
*
* For example, this gets the `{ type: "json" }` object literal in the following:
* ```js
* import foo from "foo" with { type: "json" };
* import foo from "foo" assert { type: "json" };
* ```
*/
ObjectExpr getImportAssertion() { result = this.getChildExpr(-10) }
ObjectExpr getImportAttributes() { result = this.getChildExpr(-10) }
/**
* DEPRECATED: use `getImportAttributes` instead.
* Gets the object literal passed as part of the `with` (or `assert`) clause in this import declaration.
*
* For example, this gets the `{ type: "json" }` object literal in the following:
* ```js
* import foo from "foo" with { type: "json" };
* import foo from "foo" assert { type: "json" };
* ```
*/
deprecated ObjectExpr getImportAssertion() { result = this.getImportAttributes() }
/** Gets the `i`th import specifier of this import declaration. */
ImportSpecifier getSpecifier(int i) { result = this.getChildExpr(i) }
@@ -322,17 +335,33 @@ abstract class ExportDeclaration extends Stmt, @export_declaration {
override string getAPrimaryQlClass() { result = "ExportDeclaration" }
/**
* Gets the object literal passed as part of the `assert` clause, if this is
* Gets the object literal passed as part of the `with` (or `assert`) clause, if this is
* a re-export declaration.
*
* For example, this gets the `{ type: "json" }` expression in each of the following:
* ```js
* export { x } from 'foo' assert { type: "json" };
* export { x } from 'foo' with { type: "json" };
* export * from 'foo' with { type: "json" };
* export * as x from 'foo' with { type: "json" };
* export * from 'foo' assert { type: "json" };
* export * as x from 'foo' assert { type: "json" };
* ```
*/
ObjectExpr getImportAssertion() { result = this.getChildExpr(-10) }
ObjectExpr getImportAttributes() { result = this.getChildExpr(-10) }
/**
* DEPRECATED: use `getImportAttributes` instead.
* Gets the object literal passed as part of the `with` (or `assert`) clause, if this is
* a re-export declaration.
*
* For example, this gets the `{ type: "json" }` expression in each of the following:
* ```js
* export { x } from 'foo' with { type: "json" };
* export * from 'foo' with { type: "json" };
* export * as x from 'foo' with { type: "json" };
* export * from 'foo' assert { type: "json" };
* ```
*/
deprecated ObjectExpr getImportAssertion() { result = this.getImportAttributes() }
}
/**

View File

@@ -2807,7 +2807,7 @@ class FunctionBindExpr extends @bind_expr, Expr {
*
* ```
* import("fs")
* import("foo", { assert: { type: "json" }})
* import("foo", { with: { type: "json" }})
* ```
*/
class DynamicImportExpr extends @dynamic_import, Expr, Import {
@@ -2823,12 +2823,23 @@ class DynamicImportExpr extends @dynamic_import, Expr, Import {
/**
* Gets the second "argument" to the import expression, that is, the `Y` in `import(X, Y)`.
*
* For example, gets the `{ assert: { type: "json" }}` expression in the following:
* For example, gets the `{ with: { type: "json" }}` expression in the following:
* ```js
* import('foo', { assert: { type: "json" }})
* import('foo', { with: { type: "json" }})
* ```
*/
Expr getImportAttributes() { result = this.getChildExpr(1) }
Expr getImportOptions() { result = this.getChildExpr(1) }
/**
* DEPRECATED: use `getImportOptions` instead.
* Gets the second "argument" to the import expression, that is, the `Y` in `import(X, Y)`.
*
* For example, gets the `{ with: { type: "json" }}` expression in the following:
* ```js
* import('foo', { with: { type: "json" }})
* ```
*/
deprecated Expr getImportAttributes() { result = this.getImportOptions() }
override Module getEnclosingModule() { result = this.getTopLevel() }

View File

@@ -1,13 +1,24 @@
import "module" with { type: "json" };
import * as v1 from "module" with { type: "json" };
import { v2 } from "module" with { type: "json" };
import v3 from "module" with { type: "json" };
export { v4 } from "module" with { type: "json" };
export * from "module" with { type: "json" };
export * as v5 from "module" with { type: "json" };
const v6 = import("module", { with: { type: "json" } });
import "module" // missing semicolon
assert({type: "json"}); // function call, not import assertion
import "module" assert { type: "json" };
import * as v1 from "module" assert { type: "json" };
import { v2 } from "module" assert { type: "json" };
import v3 from "module" assert { type: "json" };
export { v4 } from "module" assert { type: "json" };
export { v7 } from "module" assert { type: "json" };
export * from "module" assert { type: "json" };
export * as v5 from "module" assert { type: "json" };
const v6 = import("module", { assert: { type: "json" } });
import "module" // missing semicolon
assert({type: "json"}); // function call, not import assertion

View File

@@ -1,20 +1,28 @@
getImportAssertionFromImport
| js-import-assertions.js:1:1:1:40 | import ... son" }; | js-import-assertions.js:1:24:1:39 | { type: "json" } |
| js-import-assertions.js:2:1:2:53 | import ... son" }; | js-import-assertions.js:2:37:2:52 | { type: "json" } |
| js-import-assertions.js:3:1:3:52 | import ... son" }; | js-import-assertions.js:3:36:3:51 | { type: "json" } |
| js-import-assertions.js:4:1:4:48 | import ... son" }; | js-import-assertions.js:4:32:4:47 | { type: "json" } |
getImportAttributesFromImport
| js-import-assertions.js:1:1:1:38 | import ... son" }; | js-import-assertions.js:1:22:1:37 | { type: "json" } |
| js-import-assertions.js:2:1:2:51 | import ... son" }; | js-import-assertions.js:2:35:2:50 | { type: "json" } |
| js-import-assertions.js:3:1:3:50 | import ... son" }; | js-import-assertions.js:3:34:3:49 | { type: "json" } |
| js-import-assertions.js:4:1:4:46 | import ... son" }; | js-import-assertions.js:4:30:4:45 | { type: "json" } |
| js-import-assertions.js:15:1:15:40 | import ... son" }; | js-import-assertions.js:15:24:15:39 | { type: "json" } |
| js-import-assertions.js:16:1:16:53 | import ... son" }; | js-import-assertions.js:16:37:16:52 | { type: "json" } |
| js-import-assertions.js:17:1:17:52 | import ... son" }; | js-import-assertions.js:17:36:17:51 | { type: "json" } |
| js-import-assertions.js:18:1:18:48 | import ... son" }; | js-import-assertions.js:18:32:18:47 | { type: "json" } |
| ts-import-assertions.ts:3:1:3:40 | import ... son" }; | ts-import-assertions.ts:3:24:3:39 | { type: "json" } |
| ts-import-assertions.ts:4:1:4:53 | import ... son" }; | ts-import-assertions.ts:4:37:4:52 | { type: "json" } |
| ts-import-assertions.ts:5:1:5:52 | import ... son" }; | ts-import-assertions.ts:5:36:5:51 | { type: "json" } |
| ts-import-assertions.ts:6:1:6:48 | import ... son" }; | ts-import-assertions.ts:6:32:6:47 | { type: "json" } |
getImportAssertionFromExport
| js-import-assertions.js:6:1:6:52 | export ... son" }; | js-import-assertions.js:6:36:6:51 | { type: "json" } |
| js-import-assertions.js:7:1:7:47 | export ... son" }; | js-import-assertions.js:7:31:7:46 | { type: "json" } |
| js-import-assertions.js:8:1:8:53 | export ... son" }; | js-import-assertions.js:8:37:8:52 | { type: "json" } |
getImportAttributesFromExport
| js-import-assertions.js:6:1:6:50 | export ... son" }; | js-import-assertions.js:6:34:6:49 | { type: "json" } |
| js-import-assertions.js:7:1:7:45 | export ... son" }; | js-import-assertions.js:7:29:7:44 | { type: "json" } |
| js-import-assertions.js:8:1:8:51 | export ... son" }; | js-import-assertions.js:8:35:8:50 | { type: "json" } |
| js-import-assertions.js:20:1:20:52 | export ... son" }; | js-import-assertions.js:20:36:20:51 | { type: "json" } |
| js-import-assertions.js:21:1:21:47 | export ... son" }; | js-import-assertions.js:21:31:21:46 | { type: "json" } |
| js-import-assertions.js:22:1:22:53 | export ... son" }; | js-import-assertions.js:22:37:22:52 | { type: "json" } |
| ts-import-assertions.ts:8:1:8:52 | export ... son" }; | ts-import-assertions.ts:8:36:8:51 | { type: "json" } |
| ts-import-assertions.ts:9:1:9:47 | export ... son" }; | ts-import-assertions.ts:9:31:9:46 | { type: "json" } |
| ts-import-assertions.ts:10:1:10:53 | export ... son" }; | ts-import-assertions.ts:10:37:10:52 | { type: "json" } |
getImportAttributes
| js-import-assertions.js:10:12:10:57 | import( ... n" } }) | js-import-assertions.js:10:29:10:56 | { asser ... on" } } |
getImportOptions
| js-import-assertions.js:10:12:10:55 | import( ... n" } }) | js-import-assertions.js:10:29:10:54 | { with: ... on" } } |
| js-import-assertions.js:24:12:24:57 | import( ... n" } }) | js-import-assertions.js:24:29:24:56 | { asser ... on" } } |
| ts-import-assertions.ts:12:12:12:57 | import( ... n" } }) | ts-import-assertions.ts:12:29:12:56 | { asser ... on" } } |
errors

View File

@@ -1,13 +1,13 @@
import javascript
query Expr getImportAssertionFromImport(ImportDeclaration decl) {
result = decl.getImportAssertion()
query Expr getImportAttributesFromImport(ImportDeclaration decl) {
result = decl.getImportAttributes()
}
query Expr getImportAssertionFromExport(ExportDeclaration decl) {
result = decl.getImportAssertion()
query Expr getImportAttributesFromExport(ExportDeclaration decl) {
result = decl.getImportAttributes()
}
query Expr getImportAttributes(DynamicImportExpr imprt) { result = imprt.getImportAttributes() }
query Expr getImportOptions(DynamicImportExpr imprt) { result = imprt.getImportOptions() }
query JSParseError errors() { any() }