Skip to content

Commit

Permalink
�feat(semantic): add ReferenceFlags::TSTypeQuery to indicate refere…
Browse files Browse the repository at this point in the history
…nced by `TSTypeQuery` (#4317)

`ReferenceFlags::TSTypeQuery` can be used to help us insist on whether the reference is referenced by the type or not.
  • Loading branch information
Dunqing committed Jul 17, 2024
1 parent 5d17675 commit a88d588
Show file tree
Hide file tree
Showing 13 changed files with 37 additions and 57 deletions.
20 changes: 2 additions & 18 deletions crates/oxc_linter/src/rules/typescript/consistent_type_imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use oxc_ast::{
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_semantic::SymbolId;
use oxc_semantic::{Reference, SymbolId};
use oxc_span::{CompactStr, GetSpan, Span};

use crate::{
Expand Down Expand Up @@ -309,23 +309,7 @@ fn is_only_has_type_references(symbol_id: SymbolId, ctx: &LintContext) -> bool {
if peekable_iter.peek().is_none() {
return false;
}
peekable_iter.all(|reference| {
if reference.is_type() {
return true;
} else if reference.is_read() {
for node in ctx.nodes().iter_parents(reference.node_id()).skip(1) {
return match node.kind() {
// CASE 1:
// `type T = typeof foo` will create a value reference because "foo" must be a value type
// however this value reference is safe to use with type-only imports
AstKind::TSTypeQuery(_) => true,
AstKind::TSTypeName(_) | AstKind::TSQualifiedName(_) => continue,
_ => false,
};
}
}
false
})
peekable_iter.all(Reference::is_type)
}

struct FixOptions<'a, 'b> {
Expand Down
24 changes: 15 additions & 9 deletions crates/oxc_semantic/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1715,15 +1715,17 @@ impl<'a> SemanticBuilder<'a> {
AstKind::TSInterfaceHeritage(_) => {
self.current_reference_flag = ReferenceFlag::Type;
}
AstKind::TSTypeQuery(_) => {
// type A = typeof a;
// ^^^^^^^^
self.current_reference_flag = ReferenceFlag::Read | ReferenceFlag::TSTypeQuery;
}
AstKind::TSTypeName(_) => {
match self.nodes.parent_kind(self.current_node_id) {
Some(
// type A = typeof a;
// ^^^^^^^^
AstKind::TSTypeQuery(_)
// import A = a;
// ^
| AstKind::TSModuleReference(_)
AstKind::TSModuleReference(_),
) => {
self.current_reference_flag = ReferenceFlag::Read;
}
Expand All @@ -1732,7 +1734,9 @@ impl<'a> SemanticBuilder<'a> {
// ^^^ Keep the current reference flag
}
_ => {
self.current_reference_flag = ReferenceFlag::Type;
if !self.current_reference_flag.is_ts_type_query() {
self.current_reference_flag = ReferenceFlag::Type;
}
}
}
}
Expand Down Expand Up @@ -1847,7 +1851,9 @@ impl<'a> SemanticBuilder<'a> {
self.current_reference_flag -= ReferenceFlag::Read;
}
}
AstKind::MemberExpression(_) => self.current_reference_flag = ReferenceFlag::empty(),
AstKind::MemberExpression(_) | AstKind::TSTypeQuery(_) => {
self.current_reference_flag = ReferenceFlag::empty();
}
AstKind::AssignmentTarget(_) => self.current_reference_flag -= ReferenceFlag::Write,
_ => {}
}
Expand All @@ -1873,10 +1879,10 @@ impl<'a> SemanticBuilder<'a> {

/// Resolve reference flags for the current ast node.
fn resolve_reference_usages(&self) -> ReferenceFlag {
if self.current_reference_flag.is_write() || self.current_reference_flag.is_type() {
self.current_reference_flag
} else {
if self.current_reference_flag.is_empty() {
ReferenceFlag::Read
} else {
self.current_reference_flag
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_semantic/src/reference.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,6 @@ impl Reference {
}

pub fn is_type(&self) -> bool {
self.flag.is_type()
self.flag.is_type() || self.flag.is_ts_type_query()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/class/declarati
"node_id": 8
},
{
"flag": "ReferenceFlag(Read)",
"flag": "ReferenceFlag(Read | TSTypeQuery)",
"id": 1,
"name": "A",
"node_id": 13
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,7 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/instantiation-e
"id": 4,
"name": "T",
"node": "TSTypeParameter",
"references": [
{
"flag": "ReferenceFlag(Type)",
"id": 0,
"name": "T",
"node_id": 31
}
]
"references": []
}
]
}
Expand All @@ -75,7 +68,7 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/instantiation-e
"node": "Function(makeBox)",
"references": [
{
"flag": "ReferenceFlag(Read)",
"flag": "ReferenceFlag(Read | TSTypeQuery)",
"id": 0,
"name": "makeBox",
"node_id": 27
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaratio
"node": "VariableDeclarator",
"references": [
{
"flag": "ReferenceFlag(Read)",
"flag": "ReferenceFlag(Read | TSTypeQuery)",
"id": 0,
"name": "arg",
"node_id": 15
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaratio
"node": "VariableDeclarator",
"references": [
{
"flag": "ReferenceFlag(Read)",
"flag": "ReferenceFlag(Read | TSTypeQuery)",
"id": 0,
"name": "k",
"node_id": 21
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaratio
"node": "VariableDeclarator",
"references": [
{
"flag": "ReferenceFlag(Read)",
"flag": "ReferenceFlag(Read | TSTypeQuery)",
"id": 0,
"name": "x",
"node_id": 21
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,7 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaratio
"id": 4,
"name": "T",
"node": "TSTypeParameter",
"references": [
{
"flag": "ReferenceFlag(Type)",
"id": 0,
"name": "T",
"node_id": 33
}
]
"references": []
}
]
}
Expand All @@ -75,7 +68,7 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaratio
"node": "Function(foo)",
"references": [
{
"flag": "ReferenceFlag(Read)",
"flag": "ReferenceFlag(Read | TSTypeQuery)",
"id": 0,
"name": "foo",
"node_id": 29
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ input_file: crates/oxc_semantic/tests/fixtures/typescript-eslint/type-declaratio
"node": "VariableDeclarator",
"references": [
{
"flag": "ReferenceFlag(Read)",
"flag": "ReferenceFlag(Read | TSTypeQuery)",
"id": 0,
"name": "x",
"node_id": 9
Expand Down
7 changes: 7 additions & 0 deletions crates/oxc_syntax/src/reference.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ bitflags! {
const Write = 1 << 1;
// Used in type definitions.
const Type = 1 << 2;
// Used in `typeof xx`
const TSTypeQuery = 1 << 3;
const Value = Self::Read.bits() | Self::Write.bits();
}
}
Expand Down Expand Up @@ -87,6 +89,11 @@ impl ReferenceFlag {
self.contains(Self::Read | Self::Write)
}

/// The identifier is used in a type referenced
pub fn is_ts_type_query(&self) -> bool {
self.contains(Self::TSTypeQuery)
}

/// The identifier is used in a type definition.
pub const fn is_type(&self) -> bool {
self.contains(Self::Type)
Expand Down
4 changes: 1 addition & 3 deletions tasks/coverage/transformer_typescript.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ commit: d8086f14

transformer_typescript Summary:
AST Parsed : 6456/6456 (100.00%)
Positive Passed: 6450/6456 (99.91%)
Positive Passed: 6452/6456 (99.94%)
Mismatch: "compiler/constEnumNamespaceReferenceCausesNoImport2.ts"
Mismatch: "compiler/elidedEmbeddedStatementsReplacedWithSemicolon.ts"
Mismatch: "conformance/dynamicImport/importCallExpressionReturnPromiseOfAny.ts"
Mismatch: "conformance/externalModules/typeOnly/exportDeclaration.ts"
Mismatch: "conformance/externalModules/typeOnly/namespaceImportTypeQuery2.ts"
Mismatch: "conformance/jsx/inline/inlineJsxAndJsxFragPragmaOverridesCompilerOptions.tsx"
5 changes: 2 additions & 3 deletions tasks/transform_conformance/babel.snap.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
commit: 12619ffe

Passed: 473/927
Passed: 474/927

# All Passed:
* babel-preset-react
Expand Down Expand Up @@ -445,14 +445,13 @@ Passed: 473/927
* opts/optimizeConstEnums/input.ts
* opts/rewriteImportExtensions/input.ts

# babel-plugin-transform-typescript (129/151)
# babel-plugin-transform-typescript (130/151)
* class/accessor-allowDeclareFields-false/input.ts
* class/accessor-allowDeclareFields-true/input.ts
* enum/mix-references/input.ts
* enum/ts5.0-const-foldable/input.ts
* exports/declared-types/input.ts
* exports/interface/input.ts
* imports/elide-typeof/input.ts
* imports/only-remove-type-imports/input.ts
* imports/type-only-export-specifier-2/input.ts
* imports/type-only-import-specifier-4/input.ts
Expand Down

0 comments on commit a88d588

Please sign in to comment.