fix(semantic): resolve references to the incorrect symbol (#4280)

close: #3799
related: #3863
This commit is contained in:
Dunqing 2024-07-17 02:50:48 +00:00
parent af4dc0112e
commit 1108f2a700
23 changed files with 198 additions and 72 deletions

View file

@ -348,6 +348,7 @@ impl<'a> AstKind<'a> {
Self::TSConditionalType(_) => "TSConditionalType".into(),
Self::TSMappedType(_) => "TSMappedType".into(),
Self::TSConstructSignatureDeclaration(_) => "TSConstructSignatureDeclaration".into(),
Self::TSModuleReference(_) => "TSModuleReference".into(),
}
}
}

View file

@ -152,6 +152,7 @@ pub enum AstType {
TSSatisfiesExpression,
TSTypeAssertion,
TSImportEqualsDeclaration,
TSModuleReference,
TSExternalModuleReference,
TSNonNullExpression,
Decorator,
@ -321,6 +322,7 @@ pub enum AstKind<'a> {
TSSatisfiesExpression(&'a TSSatisfiesExpression<'a>),
TSTypeAssertion(&'a TSTypeAssertion<'a>),
TSImportEqualsDeclaration(&'a TSImportEqualsDeclaration<'a>),
TSModuleReference(&'a TSModuleReference<'a>),
TSExternalModuleReference(&'a TSExternalModuleReference<'a>),
TSNonNullExpression(&'a TSNonNullExpression<'a>),
Decorator(&'a Decorator<'a>),
@ -491,6 +493,7 @@ impl<'a> GetSpan for AstKind<'a> {
Self::TSSatisfiesExpression(it) => it.span(),
Self::TSTypeAssertion(it) => it.span(),
Self::TSImportEqualsDeclaration(it) => it.span(),
Self::TSModuleReference(it) => it.span(),
Self::TSExternalModuleReference(it) => it.span(),
Self::TSNonNullExpression(it) => it.span(),
Self::Decorator(it) => it.span(),

View file

@ -3939,6 +3939,8 @@ pub mod walk {
#[inline]
pub fn walk_ts_module_reference<'a, V: Visit<'a>>(visitor: &mut V, it: &TSModuleReference<'a>) {
let kind = AstKind::TSModuleReference(visitor.alloc(it));
visitor.enter_node(kind);
match it {
TSModuleReference::ExternalModuleReference(it) => {
visitor.visit_ts_external_module_reference(it)
@ -3947,6 +3949,7 @@ pub mod walk {
visitor.visit_ts_type_name(it.to_ts_type_name())
}
}
visitor.leave_node(kind);
}
#[inline]

View file

@ -4166,6 +4166,8 @@ pub mod walk_mut {
visitor: &mut V,
it: &mut TSModuleReference<'a>,
) {
let kind = AstType::TSModuleReference;
visitor.enter_node(kind);
match it {
TSModuleReference::ExternalModuleReference(it) => {
visitor.visit_ts_external_module_reference(it)
@ -4174,6 +4176,7 @@ pub mod walk_mut {
visitor.visit_ts_type_name(it.to_ts_type_name_mut())
}
}
visitor.leave_node(kind);
}
#[inline]

View file

@ -61,8 +61,8 @@ impl Rule for NoGlobalAssign {
fn run_once(&self, ctx: &LintContext) {
let symbol_table = ctx.symbols();
for reference_id_list in ctx.scopes().root_unresolved_references().values() {
for &reference_id in reference_id_list {
for reference_id_list in ctx.scopes().root_unresolved_references_ids() {
for reference_id in reference_id_list {
let reference = symbol_table.get_reference(reference_id);
if reference.is_write() {
let name = reference.name();

View file

@ -52,7 +52,7 @@ const REFLECT_MUTATION_METHODS: phf::Set<&'static str> =
impl Rule for NoImportAssign {
fn run_on_symbol(&self, symbol_id: SymbolId, ctx: &LintContext<'_>) {
let symbol_table = ctx.semantic().symbols();
if symbol_table.get_flag(symbol_id).is_import_binding() {
if symbol_table.get_flag(symbol_id).is_import() {
let kind = ctx.nodes().kind(symbol_table.get_declaration(symbol_id));
let is_namespace_specifier = matches!(kind, AstKind::ImportNamespaceSpecifier(_));
for reference in symbol_table.get_resolved_references(symbol_id) {

View file

@ -49,8 +49,8 @@ impl Rule for NoUndef {
fn run_once(&self, ctx: &LintContext) {
let symbol_table = ctx.symbols();
for reference_id_list in ctx.scopes().root_unresolved_references().values() {
for &reference_id in reference_id_list {
for reference_id_list in ctx.scopes().root_unresolved_references_ids() {
for reference_id in reference_id_list {
let reference = symbol_table.get_reference(reference_id);
let name = reference.name();

View file

@ -90,15 +90,19 @@ impl Rule for NoConfusingSetTimeout {
let mut jest_reference_id_list: Vec<(ReferenceId, Span)> = vec![];
let mut seen_jest_set_timeout = false;
for reference_ids in scopes.root_unresolved_references().values() {
for reference_ids in scopes.root_unresolved_references_ids() {
collect_jest_reference_id(reference_ids, &mut jest_reference_id_list, ctx);
}
for reference_ids in &symbol_table.resolved_references {
collect_jest_reference_id(reference_ids, &mut jest_reference_id_list, ctx);
collect_jest_reference_id(
reference_ids.iter().copied(),
&mut jest_reference_id_list,
ctx,
);
}
for reference_id_list in scopes.root_unresolved_references().values() {
for reference_id_list in scopes.root_unresolved_references_ids() {
handle_jest_set_time_out(
ctx,
reference_id_list,
@ -111,7 +115,7 @@ impl Rule for NoConfusingSetTimeout {
for reference_id_list in &symbol_table.resolved_references {
handle_jest_set_time_out(
ctx,
reference_id_list,
reference_id_list.iter().copied(),
&jest_reference_id_list,
&mut seen_jest_set_timeout,
&id_to_jest_node_map,
@ -121,7 +125,7 @@ impl Rule for NoConfusingSetTimeout {
}
fn collect_jest_reference_id(
reference_id_list: &Vec<ReferenceId>,
reference_id_list: impl Iterator<Item = ReferenceId>,
jest_reference_list: &mut Vec<(ReferenceId, Span)>,
ctx: &LintContext,
) {
@ -129,7 +133,7 @@ fn collect_jest_reference_id(
let nodes = ctx.nodes();
for reference_id in reference_id_list {
let reference = symbol_table.get_reference(*reference_id);
let reference = symbol_table.get_reference(reference_id);
if !is_jest_call(reference.name()) {
continue;
}
@ -139,13 +143,13 @@ fn collect_jest_reference_id(
let AstKind::MemberExpression(member_expr) = parent_node.kind() else {
continue;
};
jest_reference_list.push((*reference_id, member_expr.span()));
jest_reference_list.push((reference_id, member_expr.span()));
}
}
fn handle_jest_set_time_out<'a>(
ctx: &LintContext<'a>,
reference_id_list: &Vec<ReferenceId>,
reference_id_list: impl Iterator<Item = ReferenceId>,
jest_reference_id_list: &Vec<(ReferenceId, Span)>,
seen_jest_set_timeout: &mut bool,
id_to_jest_node_map: &HashMap<AstNodeId, &PossibleJestNode<'a, '_>>,
@ -154,7 +158,7 @@ fn handle_jest_set_time_out<'a>(
let scopes = ctx.scopes();
let symbol_table = ctx.symbols();
for &reference_id in reference_id_list {
for reference_id in reference_id_list {
let reference = symbol_table.get_reference(reference_id);
let Some(parent_node) = nodes.parent_node(reference.node_id()) else {

View file

@ -53,7 +53,7 @@ impl Rule for NoJasmineGlobals {
.filter(|(key, _)| NON_JASMINE_PROPERTY_NAMES.contains(&key.as_str()));
for (name, reference_ids) in jasmine_references {
for &reference_id in reference_ids {
for &(reference_id, _) in reference_ids {
let reference = symbol_table.get_reference(reference_id);
if let Some((error, help)) = get_non_jasmine_property_messages(name) {
ctx.diagnostic(no_jasmine_globals_diagnostic(error, help, reference.span()));

View file

@ -48,7 +48,7 @@ impl Rule for NoMocksImport {
return;
};
for reference_id in require_reference_ids {
for (reference_id, _) in require_reference_ids {
let reference = ctx.symbols().get_reference(*reference_id);
let Some(parent) = ctx.nodes().parent_node(reference.node_id()) else {
return;

View file

@ -48,7 +48,7 @@ impl Rule for NoDuplicateHead {
}
let flag = symbols.get_flag(symbol_id);
if !flag.is_import_binding() {
if !flag.is_import() {
return;
}

View file

@ -7,7 +7,7 @@ use oxc_ast::{
},
AstKind,
};
use oxc_semantic::{AstNode, ReferenceId};
use oxc_semantic::{AstNode, ReferenceFlag, ReferenceId};
use phf::phf_set;
use crate::LintContext;
@ -159,7 +159,7 @@ pub fn collect_possible_jest_call_node<'a, 'b>(
collect_ids_referenced_to_global(ctx)
.iter()
// set the original of global test function to None
.map(|id| (*id, None)),
.map(|(id, _)| (*id, None)),
);
}
@ -198,7 +198,7 @@ fn collect_ids_referenced_to_import<'a>(
.resolved_references
.iter_enumerated()
.filter_map(|(symbol_id, reference_ids)| {
if ctx.symbols().get_flag(symbol_id).is_import_binding() {
if ctx.symbols().get_flag(symbol_id).is_import() {
let id = ctx.symbols().get_declaration(symbol_id);
let Some(AstKind::ImportDeclaration(import_decl)) = ctx.nodes().parent_kind(id)
else {
@ -236,13 +236,13 @@ fn find_original_name<'a>(import_decl: &'a ImportDeclaration<'a>, name: &str) ->
})
}
fn collect_ids_referenced_to_global(ctx: &LintContext) -> Vec<ReferenceId> {
fn collect_ids_referenced_to_global(ctx: &LintContext) -> Vec<(ReferenceId, ReferenceFlag)> {
ctx.scopes()
.root_unresolved_references()
.iter()
.filter(|(name, _)| JEST_METHOD_NAMES.contains(name.as_str()))
.flat_map(|(_, reference_ids)| reference_ids.clone())
.collect::<Vec<ReferenceId>>()
.collect::<Vec<(ReferenceId, ReferenceFlag)>>()
}
/// join name of the expression. e.g.

View file

@ -251,11 +251,24 @@ impl<'a> Binder for CatchParameter<'a> {
}
}
fn declare_symbol_for_import_specifier(ident: &BindingIdentifier, builder: &mut SemanticBuilder) {
fn declare_symbol_for_import_specifier(
ident: &BindingIdentifier,
is_type: bool,
builder: &mut SemanticBuilder,
) {
let includes = if is_type
|| builder.nodes.parent_kind(builder.current_node_id).is_some_and(
|decl| matches!(decl, AstKind::ImportDeclaration(decl) if decl.import_kind.is_type()),
) {
SymbolFlags::TypeImport
} else {
SymbolFlags::Import
};
let symbol_id = builder.declare_symbol(
ident.span,
&ident.name,
SymbolFlags::ImportBinding,
includes,
SymbolFlags::ImportBindingExcludes,
);
ident.symbol_id.set(Some(symbol_id));
@ -263,25 +276,25 @@ fn declare_symbol_for_import_specifier(ident: &BindingIdentifier, builder: &mut
impl<'a> Binder for ImportSpecifier<'a> {
fn bind(&self, builder: &mut SemanticBuilder) {
declare_symbol_for_import_specifier(&self.local, builder);
declare_symbol_for_import_specifier(&self.local, self.import_kind.is_type(), builder);
}
}
impl<'a> Binder for ImportDefaultSpecifier<'a> {
fn bind(&self, builder: &mut SemanticBuilder) {
declare_symbol_for_import_specifier(&self.local, builder);
declare_symbol_for_import_specifier(&self.local, false, builder);
}
}
impl<'a> Binder for ImportNamespaceSpecifier<'a> {
fn bind(&self, builder: &mut SemanticBuilder) {
declare_symbol_for_import_specifier(&self.local, builder);
declare_symbol_for_import_specifier(&self.local, false, builder);
}
}
impl<'a> Binder for TSImportEqualsDeclaration<'a> {
fn bind(&self, builder: &mut SemanticBuilder) {
declare_symbol_for_import_specifier(&self.id, builder);
declare_symbol_for_import_specifier(&self.id, false, builder);
}
}

View file

@ -353,12 +353,13 @@ impl<'a> SemanticBuilder<'a> {
/// # Panics
pub fn declare_reference(&mut self, reference: Reference) -> ReferenceId {
let reference_name = reference.name().clone();
let reference_flag = *reference.flag();
let reference_id = self.symbols.create_reference(reference);
self.unresolved_references[self.current_scope_depth]
.entry(reference_name)
.or_default()
.push(reference_id);
.push((reference_id, reference_flag));
reference_id
}
@ -385,19 +386,39 @@ impl<'a> SemanticBuilder<'a> {
let parent_refs = iter.nth(self.current_scope_depth - 1).unwrap();
let current_refs = iter.next().unwrap();
let bindings = self.scope.get_bindings(self.current_scope_id);
for (name, reference_ids) in current_refs.drain() {
for (name, mut references) in current_refs.drain() {
// Try to resolve a reference.
// If unresolved, transfer it to parent scope's unresolved references.
let bindings = self.scope.get_bindings(self.current_scope_id);
if let Some(symbol_id) = bindings.get(&name).copied() {
for reference_id in &reference_ids {
self.symbols.references[*reference_id].set_symbol_id(symbol_id);
let symbol_flag = self.symbols.get_flag(symbol_id);
let resolved_references: &mut Vec<_> =
self.symbols.resolved_references[symbol_id].as_mut();
// Reserve space for all references to avoid reallocations.
resolved_references.reserve(references.len());
references.retain(|(id, flag)| {
if flag.is_type() && symbol_flag.is_type()
|| flag.is_value() && symbol_flag.is_value()
{
self.symbols.references[*id].set_symbol_id(symbol_id);
resolved_references.push(*id);
false
} else {
true
}
});
if references.is_empty() {
continue;
}
self.symbols.resolved_references[symbol_id].extend(reference_ids);
} else if let Some(parent_reference_ids) = parent_refs.get_mut(&name) {
parent_reference_ids.extend(reference_ids);
}
if let Some(parent_reference_ids) = parent_refs.get_mut(&name) {
parent_reference_ids.extend(references);
} else {
parent_refs.insert(name, reference_ids);
parent_refs.insert(name, references);
}
}
}
@ -1692,7 +1713,19 @@ impl<'a> SemanticBuilder<'a> {
self.current_reference_flag = ReferenceFlag::Type;
}
AstKind::TSTypeName(_) => {
self.current_reference_flag = ReferenceFlag::Type;
match self.nodes.parent_kind(self.current_node_id) {
Some(AstKind::TSModuleReference(_)) => {
// import A = a;
self.current_reference_flag = ReferenceFlag::Read;
}
Some(AstKind::TSQualifiedName(_)) => {
// import A = a.b
// ^^^ Keep the current reference flag
}
_ => {
self.current_reference_flag = ReferenceFlag::Type;
}
}
}
AstKind::IdentifierReference(ident) => {
self.reference_identifier(ident);

View file

@ -273,7 +273,7 @@ mod tests {
(SourceType::default(), "let a, b; b = a = 1", ReferenceFlag::read_write()),
(SourceType::default(), "let a, b; b = (a = 1)", ReferenceFlag::read_write()),
(SourceType::default(), "let a, b, c; b = c = a", ReferenceFlag::read()),
// sequences return last value in sequence
// sequences return last read_write in sequence
(SourceType::default(), "let a, b; b = (0, a++)", ReferenceFlag::read_write()),
// loops
(
@ -300,7 +300,7 @@ mod tests {
"let a, b; if (b == a) { true } else { false }",
ReferenceFlag::read(),
),
// identifiers not in last value are also considered a read (at
// identifiers not in last read_write are also considered a read (at
// least, or now)
(SourceType::default(), "let a, b; b = (a, 0)", ReferenceFlag::read()),
(SourceType::default(), "let a, b; b = (--a, 0)", ReferenceFlag::read_write()),

View file

@ -63,6 +63,10 @@ impl Reference {
&mut self.flag
}
pub fn flag(&self) -> &ReferenceFlag {
&self.flag
}
/// Returns `true` if the identifier value was read. This is not mutually
/// exclusive with [`#is_write`]
pub fn is_read(&self) -> bool {

View file

@ -3,15 +3,17 @@ use std::hash::BuildHasherDefault;
use indexmap::IndexMap;
use oxc_index::IndexVec;
use oxc_span::CompactStr;
use oxc_syntax::reference::{ReferenceFlag, ReferenceId};
pub use oxc_syntax::scope::{ScopeFlags, ScopeId};
use rustc_hash::{FxHashMap, FxHasher};
use crate::{reference::ReferenceId, symbol::SymbolId, AstNodeId};
use crate::{symbol::SymbolId, AstNodeId};
type FxIndexMap<K, V> = IndexMap<K, V, BuildHasherDefault<FxHasher>>;
type Bindings = FxIndexMap<CompactStr, SymbolId>;
pub(crate) type UnresolvedReferences = FxHashMap<CompactStr, Vec<ReferenceId>>;
pub(crate) type UnresolvedReference = (ReferenceId, ReferenceFlag);
pub(crate) type UnresolvedReferences = FxHashMap<CompactStr, Vec<UnresolvedReference>>;
/// Scope Tree
///
@ -90,6 +92,12 @@ impl ScopeTree {
&self.root_unresolved_references
}
pub fn root_unresolved_references_ids(
&self,
) -> impl Iterator<Item = impl Iterator<Item = ReferenceId> + '_> + '_ {
self.root_unresolved_references.values().map(|v| v.iter().map(|(id, _)| *id))
}
pub fn get_flags(&self, scope_id: ScopeId) -> ScopeFlags {
self.flags[scope_id]
}
@ -140,8 +148,12 @@ impl ScopeTree {
self.get_binding(self.root_scope_id(), name)
}
pub fn add_root_unresolved_reference(&mut self, name: CompactStr, reference_id: ReferenceId) {
self.root_unresolved_references.entry(name).or_default().push(reference_id);
pub fn add_root_unresolved_reference(
&mut self,
name: CompactStr,
reference: UnresolvedReference,
) {
self.root_unresolved_references.entry(name).or_default().push(reference);
}
pub fn has_binding(&self, scope_id: ScopeId, name: &str) -> bool {

View file

@ -180,7 +180,7 @@ fn test_exports_in_namespace() {
return foo();
}
export const x = 2
}
}
",
);
test.has_some_symbol("bar").is_exported().test();
@ -207,11 +207,11 @@ fn test_export_in_invalid_scope() {
fn test_import_assignment() {
SemanticTester::ts("import Foo = require('./foo')")
.has_root_symbol("Foo")
.contains_flags(SymbolFlags::ImportBinding)
.contains_flags(SymbolFlags::Import)
.test();
SemanticTester::ts("import { Foo } from './foo'; import Baz = Foo.Bar.Baz")
.has_root_symbol("Baz")
.contains_flags(SymbolFlags::ImportBinding)
.contains_flags(SymbolFlags::Import)
.test();
}

View file

@ -237,3 +237,45 @@ fn test_ts_infer_type() {
// type C is not referenced
tester.has_symbol("C").has_number_of_references(0).test();
}
#[test]
fn test_value_used_as_type() {
// Type annotations (or any type reference) do not resolve to value symbols
SemanticTester::ts(
"
const x = 1;
function foo(a: x) { }
",
)
.has_root_symbol("x")
.intersects_flags(SymbolFlags::Value)
.has_number_of_references(0)
.test();
// T is a value that gets shadowed by a type. When `T` is referenced within
// a value context, the root `const T` should be the symbol recoreded in the
// reference.
let tester = SemanticTester::ts(
"
const T = 1;
function foo<T extends number>(a: T) {
return a + T;
}
",
);
tester.has_root_symbol("T").has_number_of_reads(1).test();
}
#[test]
fn test_type_used_as_value() {
SemanticTester::ts(
"
type T = number;
let x = T;
",
)
.has_some_symbol("T")
.has_number_of_reads(0)
.test();
}

View file

@ -32,7 +32,7 @@ export type ReferenceFlag = {
Read: 0b1,
Write: 0b10,
Type: 0b100,
ReadWrite: 0b11
Value: 0b11
}
"#;
@ -45,7 +45,7 @@ bitflags! {
const Write = 1 << 1;
// Used in type definitions.
const Type = 1 << 2;
const ReadWrite = Self::Read.bits() | Self::Write.bits();
const Value = Self::Read.bits() | Self::Write.bits();
}
}
@ -59,7 +59,7 @@ impl ReferenceFlag {
}
pub const fn read_write() -> Self {
Self::ReadWrite
Self::Value
}
/// The identifier is read from. It may also be written to.
@ -83,12 +83,16 @@ impl ReferenceFlag {
}
/// The identifier is both read from and written to, e.g `a += 1`.
pub const fn is_read_write(&self) -> bool {
self.contains(Self::ReadWrite)
pub fn is_read_write(&self) -> bool {
self.contains(Self::Read | Self::Write)
}
/// The identifier is used in a type definition.
pub const fn is_type(&self) -> bool {
self.contains(Self::Type)
}
pub const fn is_value(&self) -> bool {
self.intersects(Self::Value)
}
}

View file

@ -46,25 +46,26 @@ bitflags! {
const Class = 1 << 5;
const CatchVariable = 1 << 6; // try {} catch(catch_variable) {}
const Function = 1 << 7;
const ImportBinding = 1 << 8; // Imported ESM binding
const Import = 1 << 8; // Imported ESM binding
const TypeImport = 1 << 9; // Imported ESM type-only binding
// Type specific symbol flags
const TypeAlias = 1 << 9;
const Interface = 1 << 10;
const RegularEnum = 1 << 11;
const ConstEnum = 1 << 12;
const EnumMember = 1 << 13;
const TypeLiteral = 1 << 14;
const TypeParameter = 1 << 15;
const NameSpaceModule = 1 << 16;
const ValueModule = 1 << 17;
const TypeAlias = 1 << 10;
const Interface = 1 << 11;
const RegularEnum = 1 << 12;
const ConstEnum = 1 << 13;
const EnumMember = 1 << 14;
const TypeLiteral = 1 << 15;
const TypeParameter = 1 << 16;
const NameSpaceModule = 1 << 17;
const ValueModule = 1 << 18;
// In a dts file or there is a declare flag
const Ambient = 1 << 18;
const Ambient = 1 << 19;
const Enum = Self::ConstEnum.bits() | Self::RegularEnum.bits();
const Variable = Self::FunctionScopedVariable.bits() | Self::BlockScopedVariable.bits();
const Value = Self::Variable.bits() | Self::Class.bits() | Self::Enum.bits() | Self::ValueModule.bits();
const Type = Self::Class.bits() | Self::Interface.bits() | Self::Enum.bits() | Self::TypeLiteral.bits() | Self::TypeParameter.bits() | Self::TypeAlias.bits();
const Value = Self::Variable.bits() | Self::Class.bits() | Self::Enum.bits() | Self::EnumMember.bits() | Self::ValueModule.bits();
const Type = Self::Class.bits() | Self::Interface.bits() | Self::Enum.bits() | Self::EnumMember.bits() | Self::TypeLiteral.bits() | Self::TypeParameter.bits() | Self::TypeAlias.bits();
/// Variables can be redeclared, but can not redeclare a block-scoped declaration with the
/// same name, or any other value that is not a variable, e.g. ValueModule or Class
@ -75,7 +76,7 @@ bitflags! {
const BlockScopedVariableExcludes = Self::Value.bits();
const ClassExcludes = (Self::Value.bits() | Self::TypeAlias.bits()) & !Self::ValueModule.bits() ;
const ImportBindingExcludes = Self::ImportBinding.bits();
const ImportBindingExcludes = Self::Import.bits() | Self::TypeImport.bits();
// Type specific excludes
const TypeAliasExcludes = Self::Type.bits();
const InterfaceExcludes = Self::Type.bits() & !(Self::Interface.bits() | Self::Class.bits());
@ -94,7 +95,11 @@ impl SymbolFlags {
}
pub fn is_type(&self) -> bool {
!self.intersects(Self::Value)
self.intersects(Self::Type | Self::TypeImport | Self::Import)
}
pub fn is_value(&self) -> bool {
self.intersects(Self::Value | Self::Import | Self::Function)
}
pub fn is_const_variable(&self) -> bool {
@ -121,7 +126,7 @@ impl SymbolFlags {
self.contains(Self::Export)
}
pub fn is_import_binding(&self) -> bool {
self.contains(Self::ImportBinding)
pub fn is_import(&self) -> bool {
self.intersects(Self::Import | Self::TypeImport)
}
}

View file

@ -299,7 +299,7 @@ impl TraverseScoping {
) -> ReferenceId {
let reference = Reference::new(SPAN, name.clone(), AstNodeId::DUMMY, flag);
let reference_id = self.symbols.create_reference(reference);
self.scopes.add_root_unresolved_reference(name, reference_id);
self.scopes.add_root_unresolved_reference(name, (reference_id, flag));
reference_id
}

View file

@ -8,7 +8,7 @@ use super::generated_header;
pub struct AstKindGenerator;
pub const BLACK_LIST: [&str; 66] = [
pub const BLACK_LIST: [&str; 65] = [
"Expression",
"ObjectPropertyKind",
"TemplateElement",
@ -62,7 +62,6 @@ pub const BLACK_LIST: [&str; 66] = [
"TSImportAttributeName",
"TSFunctionType",
"TSConstructorType",
"TSModuleReference",
"TSExportAssignment",
"TSNamespaceExportDeclaration",
"JSDocNullableType",