fix(es/lints): Ignore identifiers used as types while checking for duplicate bindings (#3869)

This commit is contained in:
magic-akari 2022-03-06 01:29:21 +08:00 committed by GitHub
parent 2fdc5f625d
commit d10e66285b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 5 deletions

View File

@ -1,5 +1,6 @@
use std::collections::hash_map::Entry;
use ahash::AHashSet;
use swc_common::{collections::AHashMap, errors::HANDLER, Span};
use swc_ecma_ast::*;
use swc_ecma_utils::ident::IdentLike;
@ -14,6 +15,7 @@ pub fn duplicate_bindings() -> Box<dyn Rule> {
#[derive(Debug, Default)]
struct DuplicateBindings {
bindings: AHashMap<Id, Span>,
type_bindings: AHashSet<Id>,
var_decl_kind: Option<VarDeclKind>,
is_pat_decl: bool,
@ -50,6 +52,22 @@ impl DuplicateBindings {
impl Visit for DuplicateBindings {
noop_visit_type!();
fn visit_module(&mut self, m: &Module) {
m.visit_with(&mut TypeCollector {
type_bindings: &mut self.type_bindings,
});
m.visit_children_with(self);
}
fn visit_script(&mut self, s: &Script) {
s.visit_with(&mut TypeCollector {
type_bindings: &mut self.type_bindings,
});
s.visit_children_with(self);
}
fn visit_assign_pat_prop(&mut self, p: &AssignPatProp) {
p.visit_children_with(self);
@ -88,19 +106,25 @@ impl Visit for DuplicateBindings {
fn visit_import_default_specifier(&mut self, s: &ImportDefaultSpecifier) {
s.visit_children_with(self);
self.add(&s.local, false);
if !self.type_bindings.contains(&s.local.to_id()) {
self.add(&s.local, false);
}
}
fn visit_import_named_specifier(&mut self, s: &ImportNamedSpecifier) {
s.visit_children_with(self);
self.add(&s.local, false);
if !s.is_type_only && !self.type_bindings.contains(&s.local.to_id()) {
self.add(&s.local, false);
}
}
fn visit_import_star_as_specifier(&mut self, s: &ImportStarAsSpecifier) {
s.visit_children_with(self);
self.add(&s.local, false);
if !self.type_bindings.contains(&s.local.to_id()) {
self.add(&s.local, false);
}
}
fn visit_pat(&mut self, p: &Pat) {
@ -126,3 +150,17 @@ impl Visit for DuplicateBindings {
self.var_decl_kind = old_var_decl_kind;
}
}
struct TypeCollector<'a> {
type_bindings: &'a mut AHashSet<Id>,
}
impl Visit for TypeCollector<'_> {
fn visit_ts_entity_name(&mut self, n: &TsEntityName) {
n.visit_children_with(self);
if let TsEntityName::Ident(ident) = n {
self.type_bindings.insert(ident.to_id());
}
}
}

View File

@ -7,7 +7,7 @@ use swc_ecma_lints::{
rules::{all, LintParams},
};
use swc_ecma_parser::{lexer::Lexer, Parser, Syntax};
use swc_ecma_transforms_base::resolver::resolver_with_mark;
use swc_ecma_transforms_base::resolver::{resolver_with_mark, ts_resolver};
use swc_ecma_utils::HANDLER;
use swc_ecma_visit::VisitMutWith;
@ -43,7 +43,11 @@ fn pass(input: PathBuf) {
let mut m = parser.parse_module().unwrap();
let top_level_mark = Mark::fresh(Mark::root());
m.visit_mut_with(&mut resolver_with_mark(top_level_mark));
if input.extension().unwrap() == "ts" || input.extension().unwrap() == "tsx" {
m.visit_mut_with(&mut ts_resolver(top_level_mark));
} else {
m.visit_mut_with(&mut resolver_with_mark(top_level_mark));
}
let top_level_ctxt = SyntaxContext::empty().apply_mark(top_level_mark);

View File

@ -0,0 +1,2 @@
import { Context, createContext } from "react";
export const Context: Context<null> = createContext<null>(null);