Repository: denoland/deno_lint
Pull request #1046 (2022-05-17 23:42:22)

refactor: upgrade to deno ast 0.15
Upgrades to deno_ast 0.15


Patch:
diff --git a/.clippy.toml b/.clippy.toml
new file mode 100644
index 0000000..a3c649d
--- /dev/null
+++ b/.clippy.toml
@@ -0,0 +1,10 @@
+# Prefer using `SourcePos` from deno_ast because it abstracts
+# away swc's non-zero-indexed based positioning
+disallowed-methods = [
+  "swc_common::Spanned::span",
+]
+disallowed-types = [
+  "swc_common::BytePos",
+  "swc_common::Span",
+  "swc_common::Spanned",
+]
diff --git a/Cargo.lock b/Cargo.lock
index 73530c5..924cf58 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -235,15 +235,13 @@ dependencies = [
 
 [[package]]
 name = "deno_ast"
-version = "0.14.0"
+version = "0.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc8868538999df5fae866dfe9841750fb57b45be49b948e173ad6a7023c0428c"
+checksum = "a2989afff97ba7da10f186e9a45e946b4ef943b9d4babd2ee7b4b24cc9906b69"
 dependencies = [
  "data-url",
- "dprint-swc-ecma-ast-view",
+ "dprint-swc-ext",
  "serde",
- "swc_atoms",
- "swc_common",
  "swc_ecmascript",
  "text_lines",
  "url",
@@ -251,7 +249,7 @@ dependencies = [
 
 [[package]]
 name = "deno_lint"
-version = "0.29.0"
+version = "0.30.0"
 dependencies = [
  "ansi_term",
  "anyhow",
@@ -288,10 +286,10 @@ dependencies = [
 ]
 
 [[package]]
-name = "dprint-swc-ecma-ast-view"
-version = "0.55.0"
+name = "dprint-swc-ext"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43f9e087f831642347a4b0370824cedf4649b7bff5065c25d53cd73094c014ca"
+checksum = "3df529037ff02f1c43ae8c6cce54d9ad85546ff89cb5c1988f56130c16e16a48"
 dependencies = [
  "bumpalo",
  "num-bigint",
@@ -1147,9 +1145,9 @@ dependencies = [
 
 [[package]]
 name = "swc_common"
-version = "0.17.19"
+version = "0.18.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00edee63ed3957d0842ac91f04010b04a5c240c752924fa53e6ebe72888b523a"
+checksum = "269446a3916d32071ca4c1adb39761fd067bc352ba40e40fca11de881ece8007"
 dependencies = [
  "ahash",
  "ast_node",
@@ -1173,9 +1171,9 @@ dependencies = [
 
 [[package]]
 name = "swc_ecma_ast"
-version = "0.75.0"
+version = "0.78.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72961898fbe56591997e667a1ec6a268383582810351c279a15ec710b6177d33"
+checksum = "6ed68ad13e4489f309ffed9d302337d7c8bde11d00b8b275b7aa7fda4da035bf"
 dependencies = [
  "is-macro",
  "num-bigint",
@@ -1188,9 +1186,9 @@ dependencies = [
 
 [[package]]
 name = "swc_ecma_parser"
-version = "0.100.0"
+version = "0.104.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bb9b2a813b3c5e68d4bfeafa588bffc87546d4d449b2a4b5d3984fac886f3b0"
+checksum = "efb97dc6efc95313dedc5158055cc811da77395ef7b54be61948b5ad097a3671"
 dependencies = [
  "either",
  "enum_kind",
@@ -1208,9 +1206,9 @@ dependencies = [
 
 [[package]]
 name = "swc_ecma_transforms"
-version = "0.142.0"
+version = "0.154.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f20e5e2d8ab843fa0454e049f73f6d99c444a8c0e2320f77028361ab75e2d18e"
+checksum = "2bce21d9e8ff785aaf9b4ac11375d9f5767630fcaf882f72e6af0516224085a6"
 dependencies = [
  "swc_atoms",
  "swc_common",
@@ -1222,13 +1220,14 @@ dependencies = [
 
 [[package]]
 name = "swc_ecma_transforms_base"
-version = "0.75.0"
+version = "0.85.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "404c6ea7ca61ceb2ce1f4ed448d1436a38c31b8c572850f04541c0229c966bbf"
+checksum = "8262876d5387887776f23c4894fbddff26e5f184edadf2375f3dc19fca2b42a4"
 dependencies = [
  "better_scoped_tls",
  "once_cell",
  "phf",
+ "rustc-hash",
  "serde",
  "smallvec",
  "swc_atoms",
@@ -1242,9 +1241,9 @@ dependencies = [
 
 [[package]]
 name = "swc_ecma_utils"
-version = "0.79.0"
+version = "0.85.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80f80b0e71cca39f27c903dad76b33112fe4a8348a0f5555a7cd6801d0ed15ed"
+checksum = "dff9d469b284a48317a695a81346a9609d04ce3a31da4493aac508e0d48a4257"
 dependencies = [
  "indexmap",
  "once_cell",
@@ -1257,9 +1256,9 @@ dependencies = [
 
 [[package]]
 name = "swc_ecma_visit"
-version = "0.61.0"
+version = "0.64.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5ea00a52ba2b971955c62275696d5c59f3cf0cd06db74a66dec378ec9843c78"
+checksum = "f2d3783a0dd1e301ae2945ab1241405f913427f9512ec62756d3d2072f7c21bb"
 dependencies = [
  "num-bigint",
  "swc_atoms",
@@ -1271,9 +1270,9 @@ dependencies = [
 
 [[package]]
 name = "swc_ecmascript"
-version = "0.143.0"
+version = "0.157.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebda93aa6422956c184a9eb5fdb0f0f0ff433169fa15e55ef445e5ad0b5e0abe"
+checksum = "bd35679e1dc392f776b691b125692d90a7bebd5d23ec96699cfe37d8ae8633b1"
 dependencies = [
  "swc_ecma_ast",
  "swc_ecma_parser",
diff --git a/Cargo.toml b/Cargo.toml
index 4ec87a7..c06cde3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "deno_lint"
-version = "0.29.0"
+version = "0.30.0"
 edition = "2021"
 description = "lint for deno"
 authors = ["the Deno authors"]
@@ -22,7 +22,7 @@ default = []
 docs = []
 
 [dependencies]
-deno_ast = { version = "0.14.0", features = ["scopes", "transforms", "utils", "visit", "view", "module_specifier"] }
+deno_ast = { version = "0.15.0", features = ["scopes", "transforms", "utils", "visit", "view", "module_specifier"] }
 log = "0.4.14"
 serde = { version = "1.0.136", features = ["derive"] }
 serde_json = "1.0.79"
diff --git a/examples/dlint/color.rs b/examples/dlint/color.rs
index 6f9bc56..e1671f1 100644
--- a/examples/dlint/color.rs
+++ b/examples/dlint/color.rs
@@ -1,9 +1,11 @@
 // Copyright 2020-2021 the Deno authors. All rights reserved. MIT license.
-use crate::lexer::{lex, MediaType, TokenOrComment};
-use deno_ast::swc::parser::token::{Token, Word};
+use deno_ast::{
+  lex,
+  swc::parser::token::{Token, Word},
+  MediaType, TokenOrComment,
+};
 use if_chain::if_chain;
 use pulldown_cmark::{Options, Parser, Tag};
-use std::convert::TryFrom;
 
 pub fn colorize_markdown(input: &str) -> String {
   let mut options = Options::empty();
@@ -156,7 +158,7 @@ impl MarkdownColorizer {
         if is_start {
           if_chain! {
             if let CodeBlockKind::Fenced(info) = kind;
-            if let Ok(media_type) = MediaType::try_from(&**info);
+            if let Some(media_type) = try_code_block_to_media_type(&**info);
             then {
               self.code_block = Some(CodeBlockLang::Known(media_type))
             } else {
@@ -268,43 +270,43 @@ fn colorize_code_block(lang: CodeBlockLang, src: &str) -> String {
       let mut out_line = String::from(line);
       for item in lex(line, media_type) {
         let offset = out_line.len() - line.len();
-        let span = item.span_as_range();
+        let range = item.range;
 
         out_line.replace_range(
-          span.start + offset..span.end + offset,
+          range.start + offset..range.end + offset,
           &match item.inner {
             TokenOrComment::Token(token) => match token {
               Token::Str { .. } | Token::Template { .. } | Token::BackQuote => {
-                decorate(&line[span], Attribute::Green)
+                decorate(&line[range], Attribute::Green)
               }
-              Token::Regex(_, _) => decorate(&line[span], Attribute::Red),
+              Token::Regex(_, _) => decorate(&line[range], Attribute::Red),
               Token::Num { .. } | Token::BigInt { .. } => {
-                decorate(&line[span], Attribute::Yellow)
+                decorate(&line[range], Attribute::Yellow)
               }
               Token::Word(word) => match word {
                 Word::True | Word::False | Word::Null => {
-                  decorate(&line[span], Attribute::Yellow)
+                  decorate(&line[range], Attribute::Yellow)
                 }
-                Word::Keyword(_) => decorate(&line[span], Attribute::Cyan),
+                Word::Keyword(_) => decorate(&line[range], Attribute::Cyan),
                 Word::Ident(ident) => {
                   if ident == *"undefined" {
-                    decorate(&line[span], Attribute::Gray)
+                    decorate(&line[range], Attribute::Gray)
                   } else if ident == *"Infinity" || ident == *"NaN" {
-                    decorate(&line[span], Attribute::Yellow)
+                    decorate(&line[range], Attribute::Yellow)
                   } else if matches!(
                     ident.as_ref(),
                     "async" | "of" | "enum" | "type" | "interface"
                   ) {
-                    decorate(&line[span], Attribute::Cyan)
+                    decorate(&line[range], Attribute::Cyan)
                   } else {
-                    line[span].to_string()
+                    line[range].to_string()
                   }
                 }
               },
-              _ => line[span].to_string(),
+              _ => line[range].to_string(),
             },
             TokenOrComment::Comment { .. } => {
-              decorate(&line[span], Attribute::Gray)
+              decorate(&line[range], Attribute::Gray)
             }
           },
         );
@@ -346,3 +348,14 @@ where
     self.collect::<Vec<_>>().join(sep)
   }
 }
+
+fn try_code_block_to_media_type(value: &str) -> Option<MediaType> {
+  match value {
+    "javascript" => Some(MediaType::JavaScript),
+    "typescript" => Some(MediaType::TypeScript),
+    "jsx" => Some(MediaType::Jsx),
+    "tsx" => Some(MediaType::Tsx),
+    "dts" => Some(MediaType::Dts),
+    _ => None,
+  }
+}
diff --git a/examples/dlint/control-flow.js b/examples/dlint/control-flow.js
deleted file mode 100644
index 881b989..0000000
--- a/examples/dlint/control-flow.js
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2020-2021 the Deno authors. All rights reserved. MIT license.
-class ControlFlow {
-  static isReachable(stmt) {
-    const { isReachable } = Deno.core.opSync(
-      "op_query_control_flow_by_span",
-      {
-        span: stmt.span,
-      }
-    );
-    return isReachable;
-  }
-
-  static stopsExecution(stmt) {
-    const { stopsExectuion } = Deno.core.opSync(
-      "op_query_control_flow_by_span",
-      {
-        span: stmt.span,
-      }
-    );
-    return stopsExectuion;
-  }
-}
diff --git a/examples/dlint/diagnostics.rs b/examples/dlint/diagnostics.rs
index ce56775..58f1ca7 100644
--- a/examples/dlint/diagnostics.rs
+++ b/examples/dlint/diagnostics.rs
@@ -1,5 +1,6 @@
 // Copyright 2020-2021 the Deno authors. All rights reserved. MIT license.
-use deno_ast::swc::common::BytePos;
+use deno_ast::SourceRange;
+use deno_ast::SourceRanged;
 use deno_ast::SourceTextInfo;
 use deno_lint::diagnostic::LintDiagnostic;
 use std::fmt::Display;
@@ -59,10 +60,10 @@ impl miette::Diagnostic for MietteDiagnostic<'_> {
   fn labels(
     &self,
   ) -> Option<Box<dyn Iterator<Item = miette::LabeledSpan> + '_>> {
-    let len = self.lint_diagnostic.range.end.byte_pos
-      - self.lint_diagnostic.range.start.byte_pos;
+    let len = self.lint_diagnostic.range.end.byte_index
+      - self.lint_diagnostic.range.start.byte_index;
     let start =
-      miette::SourceOffset::from(self.lint_diagnostic.range.start.byte_pos);
+      miette::SourceOffset::from(self.lint_diagnostic.range.start.byte_index);
     let len = miette::SourceOffset::from(len);
     let span = miette::SourceSpan::new(start, len);
     let text = self
@@ -88,12 +89,11 @@ impl miette::SourceCode for MietteSourceCode<'_> {
     context_lines_before: usize,
     context_lines_after: usize,
   ) -> Result<Box<dyn miette::SpanContents<'a> + 'a>, miette::MietteError> {
-    let lo = span.offset();
+    let start_pos = self.source.range().start;
+    let lo = start_pos + span.offset();
     let hi = lo + span.len();
 
-    let start_line_column = self
-      .source
-      .line_and_column_index(BytePos(lo.try_into().unwrap()));
+    let start_line_column = self.source.line_and_column_index(lo);
 
     let start_line_index =
       if context_lines_before > start_line_column.line_index {
@@ -101,24 +101,24 @@ impl miette::SourceCode for MietteSourceCode<'_> {
       } else {
         start_line_column.line_index - context_lines_before
       };
-    let src_start = self.source.line_start(start_line_index).0 as usize;
-    let end_line_column = self
-      .source
-      .line_and_column_index(BytePos(hi.try_into().unwrap()));
+    let src_start = self.source.line_start(start_line_index);
+    let end_line_column = self.source.line_and_column_index(hi);
     let line_count = self.source.lines_count();
     let end_line_index = std::cmp::min(
       end_line_column.line_index + context_lines_after,
-      self.source.text().len(),
+      self.source.text_str().len(),
     );
-    let src_end = self.source.line_end(end_line_index).0 as usize;
-    let src = &self.source.text_str()[src_start..src_end];
+    let src_end = self.source.line_end(end_line_index);
+    let range = SourceRange::new(src_start, src_end);
+    let src_text = range.text_fast(&self.source);
+    let byte_range = range.as_byte_range(start_pos);
     let name = Some(self.filename.to_string());
-    let start = miette::SourceOffset::from(src_start);
-    let len = miette::SourceOffset::from(src_end - src_start);
+    let start = miette::SourceOffset::from(byte_range.start);
+    let len = miette::SourceOffset::from(byte_range.len());
     let span = miette::SourceSpan::new(start, len);
 
     Ok(Box::new(SpanContentsImpl {
-      data: src,
+      data: src_text,
       span,
       line: start_line_column.line_index,
       column: start_line_column.column_index,
diff --git a/examples/dlint/lexer.rs b/examples/dlint/lexer.rs
deleted file mode 100644
index 00cf8ba..0000000
--- a/examples/dlint/lexer.rs
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright 2020-2021 the Deno authors. All rights reserved. MIT license.
-
-//! This module is mostly brought from https://github.com/denoland/deno/blob/96d05829002ef065b8fc84fe70de062cff0e95b3/cli/ast/mod.rs
-
-use deno_ast::swc::ast::EsVersion;
-use deno_ast::swc::common::comments::{
-  Comment, CommentKind, SingleThreadedComments,
-};
-use deno_ast::swc::common::{FileName, SourceMap, Span};
-use deno_ast::swc::parser::lexer::Lexer;
-use deno_ast::swc::parser::token::Token;
-use deno_ast::swc::parser::{EsConfig, StringInput, Syntax, TsConfig};
-use std::convert::TryFrom;
-use std::ops::Range;
-
-static ES_VERSION: EsVersion = EsVersion::Es2021;
-
-pub fn lex(source: &str, media_type: MediaType) -> Vec<LexedItem> {
-  let source_map = SourceMap::default();
-  let source_file = source_map.new_source_file(
-    FileName::Custom(format!("anonymous.{}", media_type.ext())),
-    source.to_string(),
-  );
-  let comments = SingleThreadedComments::default();
-  let lexer = Lexer::new(
-    media_type.syntax(),
-    ES_VERSION,
-    StringInput::from(source_file.as_ref()),
-    Some(&comments),
-  );
-
-  let mut tokens: Vec<LexedItem> = lexer
-    .map(|token| LexedItem {
-      span: token.span,
-      inner: TokenOrComment::Token(token.token),
-    })
-    .collect();
-
-  tokens.extend(flatten_comments(comments).map(|comment| LexedItem {
-    span: comment.span,
-    inner: TokenOrComment::Comment {
-      kind: comment.kind,
-      text: comment.text,
-    },
-  }));
-
-  tokens.sort_by_key(|item| item.span.lo.0);
-
-  tokens
-}
-
-#[derive(Debug, Clone, Copy)]
-pub enum MediaType {
-  JavaScript,
-  TypeScript,
-  Jsx,
-  Tsx,
-  Dts,
-}
-
-impl TryFrom<&str> for MediaType {
-  type Error = ();
-
-  fn try_from(value: &str) -> Result<Self, Self::Error> {
-    match value {
-      "javascript" => Ok(Self::JavaScript),
-      "typescript" => Ok(Self::TypeScript),
-      "jsx" => Ok(Self::Jsx),
-      "tsx" => Ok(Self::Tsx),
-      "dts" => Ok(Self::Dts),
-      _ => Err(()),
-    }
-  }
-}
-
-impl MediaType {
-  fn ext(&self) -> &'static str {
-    use MediaType::*;
-    match *self {
-      JavaScript => "js",
-      TypeScript => "ts",
-      Jsx => "jsx",
-      Tsx => "tsx",
-      Dts => "d.ts",
-    }
-  }
-
-  fn syntax(&self) -> Syntax {
-    fn get_es_config(jsx: bool) -> EsConfig {
-      EsConfig {
-        export_default_from: true,
-        jsx,
-        ..EsConfig::default()
-      }
-    }
-    fn get_ts_config(tsx: bool, dts: bool) -> TsConfig {
-      TsConfig {
-        decorators: true,
-        dts,
-        tsx,
-        ..TsConfig::default()
-      }
-    }
-
-    use MediaType::*;
-    match *self {
-      JavaScript => Syntax::Es(get_es_config(false)),
-      TypeScript => Syntax::Typescript(get_ts_config(false, false)),
-      Jsx => Syntax::Es(get_es_config(true)),
-      Tsx => Syntax::Typescript(get_ts_config(true, false)),
-      Dts => Syntax::Typescript(get_ts_config(false, true)),
-    }
-  }
-}
-
-#[derive(Debug)]
-pub enum TokenOrComment {
-  Token(Token),
-  Comment { kind: CommentKind, text: String },
-}
-
-#[derive(Debug)]
-pub struct LexedItem {
-  pub span: Span,
-  pub inner: TokenOrComment,
-}
-
-impl LexedItem {
-  pub fn span_as_range(&self) -> Range<usize> {
-    self.span.lo.0 as usize..self.span.hi.0 as usize
-  }
-}
-
-fn flatten_comments(
-  comments: SingleThreadedComments,
-) -> impl Iterator<Item = Comment> {
-  let (leading, trailing) = comments.take_all();
-  let mut comments = (*leading).clone().into_inner();
-  comments.extend((*trailing).clone().into_inner());
-  comments.into_iter().flat_map(|el| el.1)
-}
diff --git a/examples/dlint/main.rs b/examples/dlint/main.rs
index 285f4d7..12e4b64 100644
--- a/examples/dlint/main.rs
+++ b/examples/dlint/main.rs
@@ -18,7 +18,6 @@ use std::sync::{Arc, Mutex};
 mod color;
 mod config;
 mod diagnostics;
-mod lexer;
 mod rules;
 
 fn create_cli_app<'a>() -> Command<'a> {
@@ -112,7 +111,7 @@ fn run_linter(
         FileDiagnostics {
           filename: file_path.to_string_lossy().to_string(),
           diagnostics,
-          text_info: parsed_source.source().to_owned(),
+          text_info: parsed_source.text_info().clone(),
         },
       );
 
diff --git a/src/ast_parser.rs b/src/ast_parser.rs
index 6606556..d1f5d97 100644
--- a/src/ast_parser.rs
+++ b/src/ast_parser.rs
@@ -12,7 +12,7 @@ pub(crate) fn parse_program(
   deno_ast::parse_program(deno_ast::ParseParams {
     specifier: file_name.to_string(),
     media_type: MediaType::Unknown,
-    source: deno_ast::SourceTextInfo::from_string(source_code),
+    text_info: deno_ast::SourceTextInfo::from_string(source_code),
     capture_tokens: true,
     maybe_syntax: Some(syntax),
     scope_analysis: true,
diff --git a/src/context.rs b/src/context.rs
index 3ba8080..ea49661 100644
--- a/src/context.rs
+++ b/src/context.rs
@@ -6,129 +6,108 @@ use crate::ignore_directives::{
 };
 use crate::rules::{self, get_all_rules, LintRule};
 use deno_ast::swc::common::comments::Comment;
-use deno_ast::swc::common::BytePos;
-use deno_ast::swc::common::{Span, SyntaxContext};
-use deno_ast::view as ast_view;
-use deno_ast::view::{RootNode, SourceFile};
+use deno_ast::swc::common::SyntaxContext;
 use deno_ast::MediaType;
 use deno_ast::Scope;
+use deno_ast::SourceTextInfo;
+use deno_ast::{
+  view as ast_view, ParsedSource, RootNode, SourcePos, SourceRange,
+};
 use std::collections::{HashMap, HashSet};
 use std::sync::Arc;
 use std::time::Instant;
 
 /// `Context` stores data needed while performing all lint rules to a file.
 pub struct Context<'view> {
-  /// File name on which the lint rule is run
-  file_name: String,
-
-  /// The media type which linter was configured with. Can be used
-  /// to skip checking some rules.
+  parsed_source: ParsedSource,
   media_type: MediaType,
-
-  /// Stores diagnostics that are generated while linting
   diagnostics: Vec<LintDiagnostic>,
-
-  /// Information about the file text.
-  source_file: &'view dyn SourceFile,
-
-  /// The AST view of the program, which for example can be used for getting
-  /// comments
   program: ast_view::Program<'view>,
-
-  /// File-level ignore directive (`deno-lint-ignore-file`)
   file_ignore_directive: Option<FileIgnoreDirective>,
-
-  /// The map that stores line-level ignore directives (`deno-lint-ignore`).
-  /// The key of the map is line number.
   line_ignore_directives: HashMap<usize, LineIgnoreDirective>,
-
-  /// Scope analysis result
   scope: Scope,
-
-  /// Control-flow analysis result
   control_flow: ControlFlow,
-
-  /// The `SyntaxContext` of the top level
-  top_level_ctxt: SyntaxContext,
-
-  /// A value to control whether the node's children will be traversed or not.
   traverse_flow: TraverseFlow,
-
-  /// Whether to check unknown rules
   check_unknown_rules: bool,
 }
 
 impl<'view> Context<'view> {
   #[allow(clippy::too_many_arguments)]
   pub(crate) fn new(
-    file_name: String,
+    parsed_source: ParsedSource,
     media_type: MediaType,
-    source_file: &'view impl SourceFile,
     program: ast_view::Program<'view>,
     file_ignore_directive: Option<FileIgnoreDirective>,
     line_ignore_directives: HashMap<usize, LineIgnoreDirective>,
     scope: Scope,
     control_flow: ControlFlow,
-    top_level_ctxt: SyntaxContext,
     check_unknown_rules: bool,
   ) -> Self {
     Self {
-      file_name,
+      parsed_source,
       media_type,
-      source_file,
       program,
       file_ignore_directive,
       line_ignore_directives,
       scope,
       control_flow,
-      top_level_ctxt,
       diagnostics: Vec::new(),
       traverse_flow: TraverseFlow::default(),
       check_unknown_rules,
     }
   }
+
+  /// File name on which the lint rule is run
   pub fn file_name(&self) -> &str {
-    &self.file_name
+    self.parsed_source.specifier()
   }
 
+  /// The media type which linter was configured with. Can be used
+  /// to skip checking some rules.
   pub fn media_type(&self) -> MediaType {
     self.media_type
   }
 
+  /// Stores diagnostics that are generated while linting
   pub fn diagnostics(&self) -> &[LintDiagnostic] {
     &self.diagnostics
   }
 
-  pub fn source_file(&self) -> &dyn SourceFile {
-    self.source_file
-  }
-
-  pub fn file_text_substring(&self, span: &Span) -> &str {
-    &self.source_file.text()[span.lo.0 as usize..span.hi.0 as usize]
+  /// Information about the file text.
+  pub fn text_info(&self) -> &SourceTextInfo {
+    self.parsed_source.text_info()
   }
 
+  /// The AST view of the program, which for example can be used for getting
+  /// comments
   pub fn program(&self) -> &ast_view::Program<'view> {
     &self.program
   }
 
+  /// File-level ignore directive (`deno-lint-ignore-file`)
   pub fn file_ignore_directive(&self) -> Option<&FileIgnoreDirective> {
     self.file_ignore_directive.as_ref()
   }
 
+  /// The map that stores line-level ignore directives (`deno-lint-ignore`).
+  /// The key of the map is line number.
   pub fn line_ignore_directives(&self) -> &HashMap<usize, LineIgnoreDirective> {
     &self.line_ignore_directives
   }
 
+  /// Scope analysis result
   pub fn scope(&self) -> &Scope {
     &self.scope
   }
 
+  /// Control-flow analysis result
   pub fn control_flow(&self) -> &ControlFlow {
     &self.control_flow
   }
 
-  pub(crate) fn top_level_ctxt(&self) -> SyntaxContext {
-    self.top_level_ctxt
+  /// The `SyntaxContext` of any unresolved identifiers
+  pub(crate) fn unresolved_ctxt(&self) -> SyntaxContext {
+    self.parsed_source.unresolved_context()
   }
 
   pub(crate) fn assert_traverse_init(&self) {
@@ -144,29 +123,21 @@ impl<'view> Context<'view> {
   }
 
   pub fn all_comments(&self) -> impl Iterator<Item = &'view Comment> {
-    self.program.comment_container().unwrap().all_comments()
+    self.program.comment_container().all_comments()
   }
 
   pub fn leading_comments_at(
     &self,
-    lo: BytePos,
+    start: SourcePos,
   ) -> impl Iterator<Item = &'view Comment> {
-    self
-      .program
-      .comment_container()
-      .unwrap()
-      .leading_comments(lo)
+    self.program.comment_container().leading_comments(start)
   }
 
   pub fn trailing_comments_at(
     &self,
-    hi: BytePos,
+    end: SourcePos,
   ) -> impl Iterator<Item = &'view Comment> {
-    self
-      .program
-      .comment_container()
-      .unwrap()
-      .trailing_comments(hi)
+    self.program.comment_container().trailing_comments(end)
   }
 
   /// Mark ignore directives as used if that directive actually suppresses some
@@ -233,7 +204,7 @@ impl<'view> Context<'view> {
         file_ignore.codes().iter().filter(is_unused_code)
       {
         let d = self.create_diagnostic(
-          file_ignore.span(),
+          file_ignore.range(),
           CODE,
           format!("Ignore for code \"{}\" was not used.", unused_code),
           None,
@@ -251,7 +222,7 @@ impl<'view> Context<'view> {
         line_ignore.codes().iter().filter(is_unused_code)
       {
         let d = self.create_diagnostic(
-          line_ignore.span(),
+          line_ignore.range(),
           CODE,
           format!("Ignore for code \"{}\" was not used.", unused_code),
           None,
@@ -278,7 +249,7 @@ impl<'view> Context<'view> {
         file_ignore.codes().keys().filter(is_unknown_rule)
       {
         let d = self.create_diagnostic(
-          file_ignore.span(),
+          file_ignore.range(),
           rules::ban_unknown_rule_code::CODE,
           format!("Unknown rule for code \"{}\"", unknown_rule_code),
           None,
@@ -292,7 +263,7 @@ impl<'view> Context<'view> {
         line_ignore.codes().keys().filter(is_unknown_rule)
       {
         let d = self.create_diagnostic(
-          line_ignore.span(),
+          line_ignore.range(),
           rules::ban_unknown_rule_code::CODE,
           format!("Unknown rule for code \"{}\"", unknown_rule_code),
           None,
@@ -321,47 +292,52 @@ impl<'view> Context<'view> {
 
   pub fn add_diagnostic(
     &mut self,
-    span: Span,
+    range: SourceRange,
     code: impl ToString,
     message: impl ToString,
   ) {
-    let diagnostic =
-      self.create_diagnostic(span, code.to_string(), message.to_string(), None);
+    let diagnostic = self.create_diagnostic(
+      range,
+      code.to_string(),
+      message.to_string(),
+      None,
+    );
     self.diagnostics.push(diagnostic);
   }
 
   pub fn add_diagnostic_with_hint(
     &mut self,
-    span: Span,
+    range: SourceRange,
     code: impl ToString,
     message: impl ToString,
     hint: impl ToString,
   ) {
     let diagnostic =
-      self.create_diagnostic(span, code, message, Some(hint.to_string()));
+      self.create_diagnostic(range, code, message, Some(hint.to_string()));
     self.diagnostics.push(diagnostic);
   }
 
   pub(crate) fn create_diagnostic(
     &self,
-    span: Span,
+    range: SourceRange,
     code: impl ToString,
     message: impl ToString,
     maybe_hint: Option<String>,
   ) -> LintDiagnostic {
     let time_start = Instant::now();
+    let text_info = self.text_info();
     let start = Position::new(
-      span.lo(),
-      self.source_file.line_and_column_index(span.lo()),
+      range.start.as_byte_index(text_info.range().start),
+      text_info.line_and_column_index(range.start),
     );
     let end = Position::new(
-      span.hi(),
-      self.source_file.line_and_column_index(span.hi()),
+      range.end.as_byte_index(text_info.range().start),
+      text_info.line_and_column_index(range.end),
     );
 
     let diagnostic = LintDiagnostic {
       range: Range { start, end },
-      filename: self.file_name.clone(),
+      filename: self.file_name().to_string(),
       message: message.to_string(),
       code: code.to_string(),
       hint: maybe_hint,
diff --git a/src/control_flow/mod.rs b/src/control_flow/mod.rs
index c5120d9..aaf625f 100644
--- a/src/control_flow/mod.rs
+++ b/src/control_flow/mod.rs
@@ -4,12 +4,13 @@
 mod analyze_test;
 
 use deno_ast::swc::ast::*;
-use deno_ast::swc::common::{BytePos, Spanned};
+use deno_ast::swc::utils::ExprCtx;
 use deno_ast::swc::{
-  utils::{ident::IdentLike, ExprExt, Id, Value},
+  utils::{ExprExt, Value},
   visit::{noop_visit_type, Visit, VisitWith},
 };
-use deno_ast::view::ProgramRef;
+use deno_ast::SourceRangedForSpanned;
+use deno_ast::{ParsedSource, SourcePos};
 use std::{
   collections::{BTreeMap, HashSet},
   mem::take,
@@ -17,28 +18,32 @@ use std::{
 
 #[derive(Debug, Clone)]
 pub struct ControlFlow {
-  meta: BTreeMap<BytePos, Metadata>,
+  meta: BTreeMap<SourcePos, Metadata>,
 }
 
 impl ControlFlow {
-  pub fn analyze(program: ProgramRef) -> Self {
+  pub fn analyze(parsed_source: &ParsedSource) -> Self {
     let mut v = Analyzer {
       scope: Scope::new(None, BlockKind::Program),
       info: Default::default(),
+      expr_ctxt: ExprCtx {
+        unresolved_ctxt: parsed_source.unresolved_context(),
+        is_unresolved_ref_safe: false,
+      },
     };
-    match program {
-      ProgramRef::Module(module) => module.visit_with(&mut v),
-      ProgramRef::Script(script) => script.visit_with(&mut v),
+    match parsed_source.program_ref() {
+      Program::Module(module) => module.visit_with(&mut v),
+      Program::Script(script) => script.visit_with(&mut v),
     }
     ControlFlow { meta: v.info }
   }
 
-  /// lo can be extracted from span of
+  /// start_pos can be extracted from range of
   ///
-  /// - All statements (including stmt.span())
+  /// - All statements (including stmt.range())
   /// - [SwitchCase]
-  pub fn meta(&self, lo: BytePos) -> Option<&Metadata> {
-    self.meta.get(&lo)
+  pub fn meta(&self, start_pos: SourcePos) -> Option<&Metadata> {
+    self.meta.get(&start_pos)
   }
 }
 
@@ -85,7 +90,8 @@ impl Metadata {
 #[derive(Debug)]
 struct Analyzer<'a> {
   scope: Scope<'a>,
-  info: BTreeMap<BytePos, Metadata>,
+  info: BTreeMap<SourcePos, Metadata>,
+  expr_ctxt: ExprCtx,
 }
 
 #[derive(Debug)]
@@ -220,7 +226,7 @@ impl Analyzer<'_> {
   pub(super) fn with_child_scope<F>(
     &mut self,
     kind: BlockKind,
-    lo: BytePos,
+    start_pos: SourcePos,
     op: F,
   ) where
     F: for<'any> FnOnce(&mut Analyzer<'any>),
@@ -230,6 +236,7 @@ impl Analyzer<'_> {
       let mut child = Analyzer {
         info: take(&mut self.info),
         scope: Scope::new(Some(&self.scope), kind.clone()),
+        expr_ctxt: self.expr_ctxt.clone(),
       };
       match kind {
         BlockKind::Function => {}
@@ -277,7 +284,9 @@ impl Analyzer<'_> {
         BlockKind::Program => {}
         BlockKind::Function => {
           match end {
-            End::Forced { .. } | End::Continue => self.mark_as_end(lo, end),
+            End::Forced { .. } | End::Continue => {
+              self.mark_as_end(start_pos, end)
+            }
             _ => { /* valid code is supposed to be unreachable here */ }
           }
           self.scope.end = prev_end;
@@ -286,11 +295,11 @@ impl Analyzer<'_> {
         BlockKind::If => {}
         BlockKind::Loop => match end {
           End::Break | End::Continue => {
-            self.mark_as_end(lo, end);
+            self.mark_as_end(start_pos, end);
             self.scope.end = prev_end;
           }
           e => {
-            self.mark_as_end(lo, e);
+            self.mark_as_end(start_pos, e);
             self.scope.end = Some(e);
           }
         },
@@ -303,21 +312,21 @@ impl Analyzer<'_> {
           }
         }
         BlockKind::Catch => {
-          self.mark_as_end(lo, end);
+          self.mark_as_end(start_pos, end);
         }
         BlockKind::Finally => {
-          self.mark_as_end(lo, end);
+          self.mark_as_end(start_pos, end);
         }
       }
     }
   }
 
-  fn get_end_reason(&self, lo: BytePos) -> Option<End> {
-    self.info.get(&lo).and_then(|md| md.end)
+  fn get_end_reason(&self, start: SourcePos) -> Option<End> {
+    self.info.get(&start).and_then(|md| md.end)
   }
 
   /// Mark a statement as finisher - finishes execution - and expose it.
-  fn mark_as_end(&mut self, lo: BytePos, end: End) {
+  fn mark_as_end(&mut self, start: SourcePos, end: End) {
     let new_end = match self.scope.end {
       // `End::Continue` doesn't mean much about execution status, just indicating that execution has
       // not yet stopped so far. So if `End::Forced` or `End::Break` comes and the current
@@ -331,7 +340,7 @@ impl Analyzer<'_> {
       Some(e) => e.merge_forced(end).or(self.scope.end),
     };
 
-    self.info.entry(lo).or_default().end = new_end;
+    self.info.entry(start).or_default().end = new_end;
   }
 
   /// Visits statement or block. This method handles break and continue.
@@ -344,7 +353,7 @@ impl Analyzer<'_> {
     // break, continue **may** make execution end
     match s {
       Stmt::Break(..) | Stmt::Continue(..) => {
-        self.mark_as_end(s.span().lo, End::Break)
+        self.mark_as_end(s.start(), End::Break)
       }
       _ => {}
     }
@@ -356,12 +365,12 @@ impl Visit for Analyzer<'_> {
 
   fn visit_return_stmt(&mut self, n: &ReturnStmt) {
     n.visit_children_with(self);
-    self.mark_as_end(n.span().lo, End::forced_return());
+    self.mark_as_end(n.start(), End::forced_return());
   }
 
   fn visit_throw_stmt(&mut self, n: &ThrowStmt) {
     n.visit_children_with(self);
-    self.mark_as_end(n.span().lo, End::forced_throw());
+    self.mark_as_end(n.start(), End::forced_throw());
   }
 
   fn visit_break_stmt(&mut self, n: &BreakStmt) {
@@ -381,9 +390,9 @@ impl Visit for Analyzer<'_> {
     s.visit_children_with(self);
 
     if let Some(end) = self.scope.end {
-      self.mark_as_end(s.span.lo, end);
+      self.mark_as_end(s.start(), end);
     } else {
-      self.mark_as_end(s.span.lo, End::Continue);
+      self.mark_as_end(s.start(), End::Continue);
     }
   }
 
@@ -417,37 +426,37 @@ impl Visit for Analyzer<'_> {
   }
 
   fn visit_arrow_expr(&mut self, n: &ArrowExpr) {
-    self.with_child_scope(BlockKind::Function, n.span().lo, |a| {
+    self.with_child_scope(BlockKind::Function, n.start(), |a| {
       n.visit_children_with(a);
     })
   }
 
   fn visit_function(&mut self, n: &Function) {
-    self.with_child_scope(BlockKind::Function, n.span().lo, |a| {
+    self.with_child_scope(BlockKind::Function, n.start(), |a| {
       n.visit_children_with(a);
     })
   }
 
   fn visit_catch_clause(&mut self, n: &CatchClause) {
-    self.with_child_scope(BlockKind::Catch, n.span().lo, |a| {
+    self.with_child_scope(BlockKind::Catch, n.start(), |a| {
       n.visit_children_with(a);
     });
   }
 
   fn visit_constructor(&mut self, n: &Constructor) {
-    self.with_child_scope(BlockKind::Function, n.span.lo, |a| {
+    self.with_child_scope(BlockKind::Function, n.start(), |a| {
       n.visit_children_with(a);
     });
   }
 
   fn visit_getter_prop(&mut self, n: &GetterProp) {
-    self.with_child_scope(BlockKind::Function, n.span.lo, |a| {
+    self.with_child_scope(BlockKind::Function, n.start(), |a| {
       n.visit_children_with(a);
     })
   }
 
   fn visit_setter_prop(&mut self, n: &SetterProp) {
-    self.with_child_scope(BlockKind::Function, n.span.lo, |a| {
+    self.with_child_scope(BlockKind::Function, n.start(), |a| {
       n.visit_children_with(a);
     })
   }
@@ -461,7 +470,7 @@ impl Visit for Analyzer<'_> {
       let forced_end = n
         .cases
         .iter()
-        .filter_map(|case| self.get_end_reason(case.span.lo))
+        .filter_map(|case| self.get_end_reason(case.start()))
         .fold(
           Some(End::Forced {
             ret: false,
@@ -483,7 +492,7 @@ impl Visit for Analyzer<'_> {
       }
     };
 
-    self.mark_as_end(n.span.lo, end);
+    self.mark_as_end(n.start(), end);
 
     if !matches!(end, End::Forced { .. }) {
       self.scope.end = prev_end;
@@ -494,7 +503,7 @@ impl Visit for Analyzer<'_> {
     let prev_end = self.scope.end;
     let mut case_end = None;
 
-    self.with_child_scope(BlockKind::Case, n.span.lo, |a| {
+    self.with_child_scope(BlockKind::Case, n.start(), |a| {
       n.cons.visit_with(a);
 
       if a.scope.found_break.is_some() {
@@ -505,9 +514,9 @@ impl Visit for Analyzer<'_> {
     });
 
     if let Some(end) = case_end {
-      self.mark_as_end(n.span.lo, end);
+      self.mark_as_end(n.start(), end);
     } else {
-      self.mark_as_end(n.span.lo, End::Continue);
+      self.mark_as_end(n.start(), End::Continue);
     }
 
     self.scope.end = prev_end;
@@ -518,38 +527,38 @@ impl Visit for Analyzer<'_> {
 
     let prev_end = self.scope.end;
 
-    self.with_child_scope(BlockKind::If, n.cons.span().lo, |a| {
+    self.with_child_scope(BlockKind::If, n.cons.start(), |a| {
       a.visit_stmt_or_block(&n.cons);
     });
 
-    let cons_reason = self.get_end_reason(n.cons.span().lo);
+    let cons_reason = self.get_end_reason(n.cons.start());
 
     match &n.alt {
       Some(alt) => {
-        self.with_child_scope(BlockKind::If, alt.span().lo, |a| {
+        self.with_child_scope(BlockKind::If, alt.start(), |a| {
           a.visit_stmt_or_block(alt);
         });
-        let alt_reason = self.get_end_reason(alt.span().lo);
+        let alt_reason = self.get_end_reason(alt.start());
 
         match (cons_reason, alt_reason) {
           (Some(x), Some(y)) if x.is_forced() && y.is_forced() => {
             // This `unwrap` is safe; `x` and `y` are surely `Some(End::Forced { .. })`
             let end = x.merge_forced(y).unwrap();
-            self.mark_as_end(n.span.lo, end);
+            self.mark_as_end(n.start(), end);
           }
           (Some(End::Break), Some(End::Break))
           | (Some(End::Forced { .. }), Some(End::Break))
           | (Some(End::Break), Some(End::Forced { .. })) => {
-            self.mark_as_end(n.span.lo, End::Break);
+            self.mark_as_end(n.start(), End::Break);
           }
           // TODO: Check for continue
           _ => {
-            self.mark_as_end(n.span.lo, End::Continue);
+            self.mark_as_end(n.start(), End::Continue);
           }
         }
       }
       None => {
-        self.mark_as_end(n.span.lo, End::Continue);
+        self.mark_as_end(n.start(), End::Continue);
         self.scope.end = prev_end;
       }
     }
@@ -586,7 +595,7 @@ impl Visit for Analyzer<'_> {
       false
     };
 
-    self.info.entry(n.span().lo).or_default().unreachable = unreachable;
+    self.info.entry(n.start()).or_default().unreachable = unreachable;
 
     n.visit_children_with(self);
   }
@@ -599,25 +608,27 @@ impl Visit for Analyzer<'_> {
     n.test.visit_with(self);
 
     let mut forced_end = None;
+    let expr_ctxt = self.expr_ctxt.clone();
 
-    self.with_child_scope(BlockKind::Loop, n.body.span().lo, |a| {
+    self.with_child_scope(BlockKind::Loop, n.body.start(), |a| {
       n.body.visit_with(a);
 
       let has_break = matches!(a.scope.found_break, Some(None));
 
       if !has_break {
-        let end = match a.get_end_reason(n.body.span().lo) {
+        let end = match a.get_end_reason(n.body.start()) {
           Some(e) if e.is_forced() => e,
           _ => End::forced_infinite_loop(),
         };
         match &n.test {
           None => {
-            a.mark_as_end(n.span.lo, end);
+            a.mark_as_end(n.start(), end);
             forced_end = Some(end);
           }
           Some(test) => {
-            if matches!(test.as_bool(), (_, Value::Known(true))) {
-              a.mark_as_end(n.span.lo, end);
+            if matches!(test.cast_to_bool(&expr_ctxt), (_, Value::Known(true)))
+            {
+              a.mark_as_end(n.start(), end);
               forced_end = Some(end);
             }
           }
@@ -625,14 +636,14 @@ impl Visit for Analyzer<'_> {
       }
 
       if forced_end.is_none() || has_break {
-        a.mark_as_end(n.body.span().lo, End::Continue);
+        a.mark_as_end(n.body.start(), End::Continue);
         a.scope.end = Some(End::Continue);
       }
     });
   }
 
   fn visit_for_of_stmt(&mut self, n: &ForOfStmt) {
-    let body_lo = n.body.span().lo;
+    let body_lo = n.body.start();
 
     n.right.visit_with(self);
 
@@ -647,7 +658,7 @@ impl Visit for Analyzer<'_> {
   }
 
   fn visit_for_in_stmt(&mut self, n: &ForInStmt) {
-    let body_lo = n.body.span().lo;
+    let body_lo = n.body.start();
 
     n.right.visit_with(self);
 
@@ -662,13 +673,14 @@ impl Visit for Analyzer<'_> {
   }
 
   fn visit_while_stmt(&mut self, n: &WhileStmt) {
-    let body_lo = n.body.span().lo;
+    let body_lo = n.body.start();
+    let expr_ctxt = self.expr_ctxt.clone();
 
     self.with_child_scope(BlockKind::Loop, body_lo, |a| {
       n.body.visit_with(a);
 
       let unconditionally_enter =
-        matches!(n.test.as_bool(), (_, Value::Known(true)));
+        matches!(n.test.cast_to_bool(&expr_ctxt), (_, Value::Known(true)));
       let end_reason = a.get_end_reason(body_lo);
       let return_or_throw = end_reason.map_or(false, |e| e.is_forced());
       let has_break = matches!(a.scope.found_break, Some(None));
@@ -692,15 +704,17 @@ impl Visit for Analyzer<'_> {
   }
 
   fn visit_do_while_stmt(&mut self, n: &DoWhileStmt) {
-    let body_lo = n.body.span().lo;
+    let body_lo = n.body.start();
+    let expr_ctxt = self.expr_ctxt.clone();
 
     self.with_child_scope(BlockKind::Loop, body_lo, |a| {
       n.body.visit_with(a);
 
       let end_reason = a.get_end_reason(body_lo);
       let return_or_throw = end_reason.map_or(false, |e| e.is_forced());
-      let infinite_loop = matches!(n.test.as_bool(), (_, Value::Known(true)))
-        && a.scope.found_break.is_none();
+      let infinite_loop =
+        matches!(n.test.cast_to_bool(&expr_ctxt), (_, Value::Known(true)))
+          && a.scope.found_break.is_none();
       let has_break = matches!(a.scope.found_break, Some(None));
 
       if return_or_throw && !has_break {
@@ -720,7 +734,7 @@ impl Visit for Analyzer<'_> {
 
     match self.get_end_reason(body_lo) {
       Some(e) if e.is_forced() => {
-        self.mark_as_end(n.span.lo, e);
+        self.mark_as_end(n.start(), e);
       }
       _ => {}
     }
@@ -776,7 +790,7 @@ impl Visit for Analyzer<'_> {
     if let Some(finalizer) = &n.finalizer {
       let try_catch_end = self.scope.end;
       self.scope.end = prev_end;
-      self.with_child_scope(BlockKind::Finally, finalizer.span.lo, |a| {
+      self.with_child_scope(BlockKind::Finally, finalizer.start(), |a| {
         n.finalizer.visit_with(a);
       });
       match (try_catch_end, self.scope.end) {
@@ -791,13 +805,13 @@ impl Visit for Analyzer<'_> {
     }
 
     if let Some(end) = self.scope.end {
-      self.mark_as_end(n.span.lo, end);
+      self.mark_as_end(n.start(), end);
     }
     self.scope.may_throw |= old_throw;
   }
 
   fn visit_labeled_stmt(&mut self, n: &LabeledStmt) {
-    self.with_child_scope(BlockKind::Label(n.label.to_id()), n.span.lo, |a| {
+    self.with_child_scope(BlockKind::Label(n.label.to_id()), n.start(), |a| {
       a.visit_stmt_or_block(&n.body);
     });
   }
diff --git a/src/diagnostic.rs b/src/diagnostic.rs
index fa53c24..550a2fb 100644
--- a/src/diagnostic.rs
+++ b/src/diagnostic.rs
@@ -12,18 +12,16 @@ pub struct Position {
   /// The 0-indexed column index.
   #[serde(rename(serialize = "col"))]
   pub column_index: usize,
-  pub byte_pos: usize,
+  #[serde(rename(serialize = "bytePos"))]
+  pub byte_index: usize,
 }
 
 impl Position {
-  pub fn new(
-    byte_pos: deno_ast::swc::common::BytePos,
-    loc: deno_ast::LineAndColumnIndex,
-  ) -> Self {
+  pub fn new(byte_index: usize, loc: deno_ast::LineAndColumnIndex) -> Self {
     Position {
       line_index: loc.line_index,
       column_index: loc.column_index,
-      byte_pos: byte_pos.0 as usize,
+      byte_index,
     }
   }
 }
diff --git a/src/ignore_directives.rs b/src/ignore_directives.rs
index 2ac919c..398a769 100644
--- a/src/ignore_directives.rs
+++ b/src/ignore_directives.rs
@@ -1,10 +1,12 @@
+use deno_ast::SourceRange;
+use deno_ast::SourceRanged;
+use deno_ast::SourceRangedForSpanned;
+use deno_ast::SourceTextInfoProvider;
 // Copyright 2020-2021 the Deno authors. All rights reserved. MIT license.
 use deno_ast::swc::common::comments::Comment;
 use deno_ast::swc::common::comments::CommentKind;
-use deno_ast::swc::common::Span;
-use deno_ast::swc::common::Spanned;
 use deno_ast::view as ast_view;
-use deno_ast::view::RootNode;
+use deno_ast::RootNode;
 use once_cell::sync::Lazy;
 use regex::Regex;
 use std::collections::HashMap;
@@ -20,14 +22,14 @@ impl DirectiveKind for File {}
 
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub struct IgnoreDirective<T: DirectiveKind> {
-  span: Span,
+  range: SourceRange,
   codes: HashMap<String, CodeStatus>,
   _marker: std::marker::PhantomData<T>,
 }
 
 impl<T: DirectiveKind> IgnoreDirective<T> {
-  pub fn span(&self) -> Span {
-    self.span
+  pub fn range(&self) -> SourceRange {
+    self.range
   }
 
   /// If the directive has no codes specified, it means all the rules should be
@@ -71,13 +73,12 @@ pub fn parse_line_ignore_directives(
 ) -> HashMap<usize, LineIgnoreDirective> {
   program
     .comment_container()
-    .unwrap()
     .all_comments()
     .filter_map(|comment| {
       parse_ignore_comment(ignore_diagnostic_directive, comment).map(
         |directive| {
           (
-            program.source_file().unwrap().line_index(directive.span.lo),
+            program.text_info().line_index(directive.range().start),
             directive,
           )
         },
@@ -99,22 +100,22 @@ pub fn parse_file_ignore_directives(
   //    comments.
   // 3. Shebang, and the program is empty. The file's leading comments are the
   //    program's trailing comments.
-  let (has_shebang, first_item_span) = match program {
+  let (has_shebang, first_item_range) = match program {
     ast_view::Program::Module(module) => (
       module.shebang().is_some(),
-      module.body.get(0).map(Spanned::span),
+      module.body.get(0).map(SourceRanged::range),
     ),
     ast_view::Program::Script(script) => (
       script.shebang().is_some(),
-      script.body.get(0).map(Spanned::span),
+      script.body.get(0).map(SourceRanged::range),
     ),
   };
 
-  let comments = program.comment_container().unwrap();
-  let mut initial_comments = match (has_shebang, first_item_span) {
-    (false, _) => comments.leading_comments(program.span().lo()),
-    (true, Some(span)) => comments.leading_comments(span.lo()),
-    (true, None) => comments.trailing_comments(program.span().hi()),
+  let comments = program.comment_container();
+  let mut initial_comments = match (has_shebang, first_item_range) {
+    (false, _) => comments.leading_comments(program.start()),
+    (true, Some(range)) => comments.leading_comments(range.start),
+    (true, None) => comments.trailing_comments(program.end()),
   };
   initial_comments
     .find_map(|comment| parse_ignore_comment(ignore_global_directive, comment))
@@ -153,7 +154,7 @@ fn parse_ignore_comment<T: DirectiveKind>(
         .collect();
 
       return Some(IgnoreDirective::<T> {
-        span: comment.span,
+        range: comment.range(),
         codes,
         _marker: std::marker::PhantomData,
       });
diff --git a/src/lib.rs b/src/lib.rs
index 83676c9..779f8d2 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,5 +1,8 @@
 // Copyright 2020-2021 the Deno authors. All rights reserved. MIT license.
 
+#![deny(clippy::disallowed_methods)]
+#![deny(clippy::disallowed_types)]
+
 #[macro_use]
 extern crate log;
 
diff --git a/src/linter.rs b/src/linter.rs
index 47e6e56..5d5e3b0 100644
--- a/src/linter.rs
+++ b/src/linter.rs
@@ -14,8 +14,6 @@ use deno_ast::Scope;
 use std::sync::Arc;
 use std::time::Instant;
 
-pub use deno_ast::view::SourceFile;
-
 #[derive(Default)]
 pub struct LinterBuilder {
   ignore_file_directive: String,
@@ -159,7 +157,7 @@ impl Linter {
       .rules
       .iter()
       .any(|a| a.code() == (BanUnknownRuleCode).code());
-    let control_flow = ControlFlow::analyze(parsed_source.program_ref().into());
+    let control_flow = ControlFlow::analyze(parsed_source);
     let diagnostics = parsed_source.with_view(|pg| {
       let file_ignore_directive =
         parse_file_ignore_directives(&self.ignore_file_directive, pg);
@@ -177,15 +175,13 @@ impl Linter {
       let scope = Scope::analyze(pg);
 
       let mut context = Context::new(
-        parsed_source.specifier().to_string(),
+        parsed_source.clone(),
         self.media_type,
-        parsed_source.source(),
         pg,
         file_ignore_directive,
         line_ignore_directives,
         scope,
         control_flow,
-        parsed_source.top_level_context(),
         check_unknown_rules,
       );
 
diff --git a/src/rules/adjacent_overload_signatures.rs b/src/rules/adjacent_overload_signatures.rs
index 9655f18..3daf7f8 100644
--- a/src/rules/adjacent_overload_signatures.rs
+++ b/src/rules/adjacent_overload_signatures.rs
@@ -3,8 +3,7 @@ use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::swc_util::StringRepr;
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
-use deno_ast::view as ast_view;
+use deno_ast::{view as ast_view, SourceRanged};
 use derive_more::Display;
 use std::collections::HashSet;
 use std::sync::Arc;
@@ -100,7 +99,7 @@ impl Handler for AdjacentOverloadSignaturesHandler {
 fn check<'a, T, U>(items: T, ctx: &'a mut Context)
 where
   T: IntoIterator<Item = &'a U>,
-  U: ExtractMethod + Spanned + 'a,
+  U: ExtractMethod + SourceRanged + 'a,
 {
   let mut seen_methods = HashSet::new();
   let mut last_method = None;
@@ -109,7 +108,7 @@ where
       if seen_methods.contains(&method) && last_method.as_ref() != Some(&method)
       {
         ctx.add_diagnostic_with_hint(
-          item.span(),
+          item.range(),
           CODE,
           AdjacentOverloadSignaturesMessage::ShouldBeAdjacent(
             method.to_string(),
diff --git a/src/rules/ban_ts_comment.rs b/src/rules/ban_ts_comment.rs
index ee59c7e..4cd1d3f 100644
--- a/src/rules/ban_ts_comment.rs
+++ b/src/rules/ban_ts_comment.rs
@@ -3,7 +3,8 @@ use super::{Context, LintRule};
 use crate::{Program, ProgramRef};
 use deno_ast::swc::common::comments::Comment;
 use deno_ast::swc::common::comments::CommentKind;
-use deno_ast::swc::common::Span;
+use deno_ast::SourceRange;
+use deno_ast::SourceRangedForSpanned;
 use once_cell::sync::Lazy;
 use regex::Regex;
 use std::sync::Arc;
@@ -51,9 +52,14 @@ impl DirectiveKind {
 }
 
 impl BanTsComment {
-  fn report(&self, context: &mut Context, span: Span, kind: DirectiveKind) {
+  fn report(
+    &self,
+    context: &mut Context,
+    range: SourceRange,
+    kind: DirectiveKind,
+  ) {
     context.add_diagnostic_with_hint(
-      span,
+      range,
       CODE,
       kind.as_message(),
       kind.as_hint(),
@@ -83,15 +89,15 @@ impl LintRule for BanTsComment {
     context: &mut Context,
     _program: Program,
   ) {
-    let mut violated_comment_spans = Vec::new();
+    let mut violated_comment_ranges = Vec::new();
 
-    violated_comment_spans.extend(context.all_comments().filter_map(|c| {
+    violated_comment_ranges.extend(context.all_comments().filter_map(|c| {
       let kind = check_comment(c)?;
-      Some((c.span, kind))
+      Some((c.range(), kind))
     }));
 
-    for (span, kind) in violated_comment_spans {
-      self.report(context, span, kind);
+    for (range, kind) in violated_comment_ranges {
+      self.report(context, range, kind);
     }
   }
 
diff --git a/src/rules/ban_types.rs b/src/rules/ban_types.rs
index 3db1b89..797a15c 100644
--- a/src/rules/ban_types.rs
+++ b/src/rules/ban_types.rs
@@ -2,9 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
-use deno_ast::view as ast_view;
 use deno_ast::view::{TsEntityName, TsKeywordTypeKind};
+use deno_ast::{view as ast_view, SourceRanged};
 use if_chain::if_chain;
 use std::convert::TryFrom;
 use std::sync::Arc;
@@ -116,12 +115,12 @@ impl Handler for BanTypesHandler {
   ) {
     if_chain! {
       if let TsEntityName::Ident(ident) = &ts_type_ref.type_name;
-      if ident.span().ctxt == ctx.top_level_ctxt();
+      if ident.ctxt() == ctx.unresolved_ctxt();
       if ctx.scope().is_global(&ident.to_id());
       if let Ok(banned_type) = BannedType::try_from(ident.sym().as_ref());
       then {
         ctx.add_diagnostic_with_hint(
-          ts_type_ref.span(),
+          ts_type_ref.range(),
           CODE,
           banned_type.as_message(),
           banned_type.as_hint(),
@@ -137,7 +136,7 @@ impl Handler for BanTypesHandler {
   ) {
     if ts_type_lit.members.is_empty() {
       ctx.add_diagnostic_with_hint(
-        ts_type_lit.span(),
+        ts_type_lit.range(),
         CODE,
         BannedType::EmptyObjectLiteral.as_message(),
         BannedType::EmptyObjectLiteral.as_hint(),
@@ -152,7 +151,7 @@ impl Handler for BanTypesHandler {
   ) {
     if TsKeywordTypeKind::TsObjectKeyword == ts_keyword_type.keyword_kind() {
       ctx.add_diagnostic_with_hint(
-        ts_keyword_type.span(),
+        ts_keyword_type.range(),
         CODE,
         BannedType::LowerObject.as_message(),
         BannedType::LowerObject.as_hint(),
diff --git a/src/rules/ban_untagged_ignore.rs b/src/rules/ban_untagged_ignore.rs
index cca1f56..8f79df9 100644
--- a/src/rules/ban_untagged_ignore.rs
+++ b/src/rules/ban_untagged_ignore.rs
@@ -1,7 +1,7 @@
 // Copyright 2020-2021 the Deno authors. All rights reserved. MIT license.
 use super::{Context, LintRule};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Span;
+use deno_ast::SourceRange;
 use std::sync::Arc;
 
 #[derive(Debug)]
@@ -31,22 +31,22 @@ impl LintRule for BanUntaggedIgnore {
     context: &mut Context,
     _program: Program,
   ) {
-    let mut violated_spans: Vec<Span> = context
+    let mut violated_ranges: Vec<SourceRange> = context
       .file_ignore_directive()
       .iter()
-      .filter_map(|d| d.ignore_all().then(|| d.span()))
+      .filter_map(|d| d.ignore_all().then(|| d.range()))
       .collect();
 
-    violated_spans.extend(
+    violated_ranges.extend(
       context
         .line_ignore_directives()
         .values()
-        .filter_map(|d| d.ignore_all().then(|| d.span())),
+        .filter_map(|d| d.ignore_all().then(|| d.range())),
     );
 
-    for span in violated_spans {
+    for range in violated_ranges {
       context.add_diagnostic_with_hint(
-        span,
+        range,
         CODE,
         "Ignore directive requires lint rule name(s)",
         "Add one or more lint rule names.  E.g. // deno-lint-ignore adjacent-overload-signatures",
diff --git a/src/rules/ban_untagged_todo.rs b/src/rules/ban_untagged_todo.rs
index 84cfd9f..3c79797 100644
--- a/src/rules/ban_untagged_todo.rs
+++ b/src/rules/ban_untagged_todo.rs
@@ -3,6 +3,7 @@ use super::{Context, LintRule};
 use crate::{Program, ProgramRef};
 use deno_ast::swc::common::comments::Comment;
 use deno_ast::swc::common::comments::CommentKind;
+use deno_ast::SourceRangedForSpanned;
 use once_cell::sync::Lazy;
 use regex::Regex;
 use std::sync::Arc;
@@ -32,18 +33,18 @@ impl LintRule for BanUntaggedTodo {
     context: &mut Context,
     _program: Program,
   ) {
-    let mut violated_comment_spans = Vec::new();
+    let mut violated_comment_ranges = Vec::new();
 
-    violated_comment_spans.extend(context.all_comments().filter_map(|c| {
+    violated_comment_ranges.extend(context.all_comments().filter_map(|c| {
       if check_comment(c) {
-        Some(c.span)
+        Some(c.range())
       } else {
         None
       }
     }));
 
-    for span in violated_comment_spans {
-      context.add_diagnostic_with_hint(span, CODE, MESSAGE, HINT);
+    for range in violated_comment_ranges {
+      context.add_diagnostic_with_hint(range, CODE, MESSAGE, HINT);
     }
   }
 
diff --git a/src/rules/camelcase.rs b/src/rules/camelcase.rs
index 8f61f3f..ed4b92d 100644
--- a/src/rules/camelcase.rs
+++ b/src/rules/camelcase.rs
@@ -3,9 +3,7 @@ use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::swc_util::StringRepr;
 use crate::ProgramRef;
-use deno_ast::swc::common::Span;
-use deno_ast::swc::common::Spanned;
-use deno_ast::view as ast_view;
+use deno_ast::{view as ast_view, SourceRange, SourceRanged};
 use once_cell::sync::Lazy;
 use regex::{Captures, Regex};
 use std::collections::{BTreeMap, BTreeSet};
@@ -342,17 +340,17 @@ impl IdentToCheck {
 #[derive(Default)]
 struct CamelcaseHandler {
   /// Accumulated errors to report
-  errors: BTreeMap<Span, IdentToCheck>,
+  errors: BTreeMap<SourceRange, IdentToCheck>,
   /// Already visited identifiers
-  visited: BTreeSet<Span>,
+  visited: BTreeSet<SourceRange>,
 }
 
 impl CamelcaseHandler {
   /// Report accumulated errors, consuming `self`.
   fn report_errors(self, ctx: &mut Context) {
-    for (span, error_ident) in self.errors {
+    for (range, error_ident) in self.errors {
       ctx.add_diagnostic_with_hint(
-        span,
+        range,
         CODE,
         error_ident.to_message(),
         error_ident.to_hint(),
@@ -361,10 +359,10 @@ impl CamelcaseHandler {
   }
 
   /// Check if this ident is underscored only when it's not yet visited.
-  fn check_ident<S: Spanned>(&mut self, span: &S, ident: IdentToCheck) {
-    let span = span.span();
-    if self.visited.insert(span) && is_underscored(ident.get_ident_name()) {
-      self.errors.insert(span, ident);
+  fn check_ident<S: SourceRanged>(&mut self, range: &S, ident: IdentToCheck) {
+    let range = range.range();
+    if self.visited.insert(range) && is_underscored(ident.get_ident_name()) {
+      self.errors.insert(range, ident);
     }
   }
 
diff --git a/src/rules/constructor_super.rs b/src/rules/constructor_super.rs
index c148326..d57440a 100644
--- a/src/rules/constructor_super.rs
+++ b/src/rules/constructor_super.rs
@@ -2,9 +2,7 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Span;
-use deno_ast::swc::common::Spanned;
-use deno_ast::view as ast_view;
+use deno_ast::{view as ast_view, SourceRange, SourceRanged};
 use if_chain::if_chain;
 use std::sync::Arc;
 
@@ -82,25 +80,25 @@ fn inherits_from_non_constructor(class: &ast_view::Class) -> bool {
   matches!(&class.super_class, Some(ast_view::Expr::Lit(_)))
 }
 
-fn super_call_spans(constructor: &ast_view::Constructor) -> Vec<Span> {
+fn super_call_ranges(constructor: &ast_view::Constructor) -> Vec<SourceRange> {
   if let Some(block_stmt) = &constructor.body {
     block_stmt
       .stmts
       .iter()
-      .filter_map(extract_super_span)
+      .filter_map(extract_super_range)
       .collect()
   } else {
     vec![]
   }
 }
 
-fn extract_super_span(stmt: &ast_view::Stmt) -> Option<Span> {
+fn extract_super_range(stmt: &ast_view::Stmt) -> Option<SourceRange> {
   if_chain! {
     if let ast_view::Stmt::Expr(expr) = stmt;
     if let ast_view::Expr::Call(call) = expr.expr;
     if matches!(&call.callee, ast_view::Callee::Super(_));
     then {
-      Some(call.span())
+      Some(call.range())
     } else {
       None
     }
@@ -112,7 +110,7 @@ fn return_before_super<'a, 'view>(
 ) -> Option<&'a ast_view::ReturnStmt<'view>> {
   if let Some(block_stmt) = &constructor.body {
     for stmt in &block_stmt.stmts {
-      if extract_super_span(stmt).is_some() {
+      if extract_super_range(stmt).is_some() {
         return None;
       }
 
@@ -139,7 +137,7 @@ fn check_constructor(
     if ret.arg.is_none() && class.super_class.is_some() {
       let kind = DiagnosticKind::NoSuper;
       ctx.add_diagnostic_with_hint(
-        cons.span(),
+        cons.range(),
         CODE,
         kind.message(),
         kind.hint(),
@@ -151,7 +149,7 @@ fn check_constructor(
   if inherits_from_non_constructor(class) {
     let kind = DiagnosticKind::UnnecessaryConstructor;
     ctx.add_diagnostic_with_hint(
-      cons.span(),
+      cons.range(),
       CODE,
       kind.message(),
       kind.hint(),
@@ -159,13 +157,13 @@ fn check_constructor(
     return;
   }
 
-  let super_calls = super_call_spans(cons);
+  let super_calls = super_call_ranges(cons);
 
   // in case where there are more than one `super()` calls.
-  for exceeded_super_span in super_calls.iter().skip(1) {
+  for exceeded_super_range in super_calls.iter().skip(1) {
     let kind = DiagnosticKind::TooManySuper;
     ctx.add_diagnostic_with_hint(
-      *exceeded_super_span,
+      *exceeded_super_range,
       CODE,
       kind.message(),
       kind.hint(),
@@ -176,7 +174,7 @@ fn check_constructor(
     (true, true) => {
       let kind = DiagnosticKind::NoSuper;
       ctx.add_diagnostic_with_hint(
-        cons.span(),
+        cons.range(),
         CODE,
         kind.message(),
         kind.hint(),
diff --git a/src/rules/default_param_last.rs b/src/rules/default_param_last.rs
index 825a824..e12516f 100644
--- a/src/rules/default_param_last.rs
+++ b/src/rules/default_param_last.rs
@@ -2,8 +2,7 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
-use deno_ast::view as ast_view;
+use deno_ast::{view as ast_view, SourceRanged};
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -83,7 +82,7 @@ where
       ast_view::Pat::Assign(pat) => {
         if has_seen_normal_param {
           ctx.add_diagnostic_with_hint(
-            pat.span(),
+            pat.range(),
             CODE,
             DefaultParamLastMessage::DefaultLast,
             DefaultParamLastHint::MoveToEnd,
diff --git a/src/rules/eqeqeq.rs b/src/rules/eqeqeq.rs
index bba369f..62c91cc 100644
--- a/src/rules/eqeqeq.rs
+++ b/src/rules/eqeqeq.rs
@@ -3,8 +3,7 @@ use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
 use deno_ast::swc::ast::BinaryOp;
-use deno_ast::swc::common::Spanned;
-use deno_ast::view as ast_view;
+use deno_ast::{view as ast_view, SourceRanged};
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -70,7 +69,7 @@ impl Handler for EqeqeqHandler {
       } else {
         (EqeqeqMessage::ExpectedNotEqual, EqeqeqHint::UseNoteqeq)
       };
-      context.add_diagnostic_with_hint(bin_expr.span(), CODE, message, hint)
+      context.add_diagnostic_with_hint(bin_expr.range(), CODE, message, hint)
     }
   }
 }
diff --git a/src/rules/explicit_function_return_type.rs b/src/rules/explicit_function_return_type.rs
index 0b0681b..6b16253 100644
--- a/src/rules/explicit_function_return_type.rs
+++ b/src/rules/explicit_function_return_type.rs
@@ -2,8 +2,7 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
-use deno_ast::view as ast_view;
+use deno_ast::{view as ast_view, SourceRanged};
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -65,7 +64,7 @@ impl Handler for ExplicitFunctionReturnTypeHandler {
 
     if function.return_type.is_none() && !is_method_setter {
       context.add_diagnostic_with_hint(
-        function.span(),
+        function.range(),
         CODE,
         ExplicitFunctionReturnTypeMessage::MissingRetType,
         ExplicitFunctionReturnTypeHint::AddRetType,
diff --git a/src/rules/explicit_module_boundary_types.rs b/src/rules/explicit_module_boundary_types.rs
index 61246e2..ed75c7e 100644
--- a/src/rules/explicit_module_boundary_types.rs
+++ b/src/rules/explicit_module_boundary_types.rs
@@ -2,8 +2,7 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::ProgramRef;
-use deno_ast::swc::common::{Span, Spanned};
-use deno_ast::view as ast_view;
+use deno_ast::{view as ast_view, SourceRange, SourceRanged};
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -103,7 +102,7 @@ fn check_class(class: &ast_view::Class, ctx: &mut Context) {
 fn check_fn(function: &ast_view::Function, ctx: &mut Context) {
   if function.return_type.is_none() {
     ctx.add_diagnostic_with_hint(
-      function.span(),
+      function.range(),
       CODE,
       ExplicitModuleBoundaryTypesMessage::MissingRetType,
       ExplicitModuleBoundaryTypesHint::AddRetType,
@@ -117,7 +116,7 @@ fn check_fn(function: &ast_view::Function, ctx: &mut Context) {
 fn check_arrow(arrow: &ast_view::ArrowExpr, ctx: &mut Context) {
   if arrow.return_type.is_none() {
     ctx.add_diagnostic_with_hint(
-      arrow.span(),
+      arrow.range(),
       CODE,
       ExplicitModuleBoundaryTypesMessage::MissingRetType,
       ExplicitModuleBoundaryTypesHint::AddRetType,
@@ -128,14 +127,18 @@ fn check_arrow(arrow: &ast_view::ArrowExpr, ctx: &mut Context) {
   }
 }
 
-fn check_ann(ann: Option<&ast_view::TsTypeAnn>, span: Span, ctx: &mut Context) {
+fn check_ann(
+  ann: Option<&ast_view::TsTypeAnn>,
+  range: SourceRange,
+  ctx: &mut Context,
+) {
   if let Some(ann) = ann {
     if let ast_view::TsType::TsKeywordType(keyword_type) = ann.type_ann {
       if ast_view::TsKeywordTypeKind::TsAnyKeyword
         == keyword_type.keyword_kind()
       {
         ctx.add_diagnostic_with_hint(
-          span,
+          range,
           CODE,
           ExplicitModuleBoundaryTypesMessage::MissingArgType,
           ExplicitModuleBoundaryTypesHint::AddArgTypes,
@@ -144,7 +147,7 @@ fn check_ann(ann: Option<&ast_view::TsTypeAnn>, span: Span, ctx: &mut Context) {
     }
   } else {
     ctx.add_diagnostic_with_hint(
-      span,
+      range,
       CODE,
       ExplicitModuleBoundaryTypesMessage::MissingArgType,
       ExplicitModuleBoundaryTypesHint::AddArgTypes,
@@ -155,15 +158,17 @@ fn check_ann(ann: Option<&ast_view::TsTypeAnn>, span: Span, ctx: &mut Context) {
 fn check_pat(pat: &ast_view::Pat, ctx: &mut Context) {
   match pat {
     ast_view::Pat::Ident(ident) => {
-      check_ann(ident.type_ann, ident.id.span(), ctx)
+      check_ann(ident.type_ann, ident.id.range(), ctx)
     }
-    ast_view::Pat::Array(array) => check_ann(array.type_ann, array.span(), ctx),
-    ast_view::Pat::Rest(rest) => check_ann(rest.type_ann, rest.span(), ctx),
+    ast_view::Pat::Array(array) => {
+      check_ann(array.type_ann, array.range(), ctx)
+    }
+    ast_view::Pat::Rest(rest) => check_ann(rest.type_ann, rest.range(), ctx),
     ast_view::Pat::Object(object) => {
-      check_ann(object.type_ann, object.span(), ctx)
+      check_ann(object.type_ann, object.range(), ctx)
     }
     ast_view::Pat::Assign(assign) => {
-      check_ann(assign.type_ann, assign.span(), ctx)
+      check_ann(assign.type_ann, assign.range(), ctx)
     }
     _ => {}
   };
diff --git a/src/rules/for_direction.rs b/src/rules/for_direction.rs
index bcee493..19e2a6c 100644
--- a/src/rules/for_direction.rs
+++ b/src/rules/for_direction.rs
@@ -5,9 +5,8 @@ use crate::{Program, ProgramRef};
 use deno_ast::swc::ast::AssignOp;
 use deno_ast::swc::ast::BinaryOp;
 use deno_ast::swc::ast::UpdateOp;
-use deno_ast::swc::common::Spanned;
-use deno_ast::view as ast_view;
 use deno_ast::view::{AssignExpr, Expr, Pat, PatOrExpr, UnaryOp, UpdateExpr};
+use deno_ast::{view as ast_view, SourceRanged};
 use std::sync::Arc;
 
 #[derive(Debug)]
@@ -151,7 +150,7 @@ impl Handler for ForDirectionHandler {
 
       if update_direction == wrong_direction {
         context.add_diagnostic_with_hint(
-          for_stmt.span(),
+          for_stmt.range(),
           "for-direction",
           MESSAGE,
           HINT,
diff --git a/src/rules/getter_return.rs b/src/rules/getter_return.rs
index 5d16db5..012f65f 100644
--- a/src/rules/getter_return.rs
+++ b/src/rules/getter_return.rs
@@ -7,10 +7,11 @@ use deno_ast::swc::ast::{
   FnExpr, GetterProp, MemberProp, MethodKind, MethodProp, PrivateMethod, Prop,
   PropName, PropOrSpread, ReturnStmt,
 };
-use deno_ast::swc::common::{Span, Spanned};
 use deno_ast::swc::visit::noop_visit_type;
 use deno_ast::swc::visit::Visit;
 use deno_ast::swc::visit::VisitWith;
+use deno_ast::SourceRange;
+use deno_ast::SourceRangedForSpanned;
 use derive_more::Display;
 use std::collections::BTreeMap;
 use std::sync::Arc;
@@ -68,7 +69,7 @@ impl LintRule for GetterReturn {
 
 struct GetterReturnVisitor<'c, 'view> {
   context: &'c mut Context<'view>,
-  errors: BTreeMap<Span, GetterReturnMessage>,
+  errors: BTreeMap<SourceRange, GetterReturnMessage>,
   /// If this visitor is currently in a getter, its name is stored.
   getter_name: Option<String>,
   // `true` if a getter contains as least one return statement.
@@ -86,9 +87,9 @@ impl<'c, 'view> GetterReturnVisitor<'c, 'view> {
   }
 
   fn report(&mut self) {
-    for (span, msg) in &self.errors {
+    for (range, msg) in &self.errors {
       self.context.add_diagnostic_with_hint(
-        *span,
+        *range,
         CODE,
         msg,
         GetterReturnHint::Return,
@@ -96,9 +97,9 @@ impl<'c, 'view> GetterReturnVisitor<'c, 'view> {
     }
   }
 
-  fn report_expected(&mut self, span: Span) {
+  fn report_expected(&mut self, range: SourceRange) {
     self.errors.insert(
-      span,
+      range,
       GetterReturnMessage::Expected(
         self
           .getter_name
@@ -108,9 +109,9 @@ impl<'c, 'view> GetterReturnVisitor<'c, 'view> {
     );
   }
 
-  fn report_always_expected(&mut self, span: Span) {
+  fn report_always_expected(&mut self, range: SourceRange) {
     self.errors.insert(
-      span,
+      range,
       GetterReturnMessage::ExpectedAlways(
         self
           .getter_name
@@ -120,7 +121,11 @@ impl<'c, 'view> GetterReturnVisitor<'c, 'view> {
     );
   }
 
-  fn check_getter(&mut self, getter_body_span: Span, getter_span: Span) {
+  fn check_getter(
+    &mut self,
+    getter_body_range: SourceRange,
+    getter_range: SourceRange,
+  ) {
     if self.getter_name.is_none() {
       return;
     }
@@ -128,14 +133,14 @@ impl<'c, 'view> GetterReturnVisitor<'c, 'view> {
     if self
       .context
       .control_flow()
-      .meta(getter_body_span.lo)
+      .meta(getter_body_range.start)
       .unwrap()
       .continues_execution()
     {
       if self.has_return {
-        self.report_always_expected(getter_span);
+        self.report_always_expected(getter_range);
       } else {
-        self.report_expected(getter_span);
+        self.report_expected(getter_range);
       }
     }
   }
@@ -203,7 +208,7 @@ impl<'c, 'view> Visit for GetterReturnVisitor<'c, 'view> {
       class_method.visit_children_with(a);
 
       if let Some(body) = &class_method.function.body {
-        a.check_getter(body.span, class_method.span);
+        a.check_getter(body.range(), class_method.range());
       }
     });
   }
@@ -216,7 +221,7 @@ impl<'c, 'view> Visit for GetterReturnVisitor<'c, 'view> {
       private_method.visit_children_with(a);
 
       if let Some(body) = &private_method.function.body {
-        a.check_getter(body.span, private_method.span);
+        a.check_getter(body.range(), private_method.range());
       }
     });
   }
@@ -227,7 +232,7 @@ impl<'c, 'view> Visit for GetterReturnVisitor<'c, 'view> {
       getter_prop.visit_children_with(a);
 
       if let Some(body) = &getter_prop.body {
-        a.check_getter(body.span, getter_prop.span);
+        a.check_getter(body.range(), getter_prop.range());
       }
     });
   }
@@ -267,7 +272,7 @@ impl<'c, 'view> Visit for GetterReturnVisitor<'c, 'view> {
                   a.set_getter_name(&fn_expr.ident);
                   if let Some(body) = &fn_expr.function.body {
                     body.visit_children_with(a);
-                    a.check_getter(body.span, prop.span());
+                    a.check_getter(body.range(), prop.range());
                   }
                 } else if let Expr::Arrow(arrow_expr) = &*kv_prop.value {
                   a.set_default_getter_name();
@@ -275,7 +280,7 @@ impl<'c, 'view> Visit for GetterReturnVisitor<'c, 'view> {
                     &arrow_expr.body
                   {
                     block_stmt.visit_children_with(a);
-                    a.check_getter(block_stmt.span, prop.span());
+                    a.check_getter(block_stmt.range(), prop.range());
                   }
                 }
               });
@@ -292,7 +297,7 @@ impl<'c, 'view> Visit for GetterReturnVisitor<'c, 'view> {
 
                 if let Some(body) = &method_prop.function.body {
                   body.visit_children_with(a);
-                  a.check_getter(body.span, prop.span());
+                  a.check_getter(body.range(), prop.range());
                 }
               });
             }
@@ -306,7 +311,7 @@ impl<'c, 'view> Visit for GetterReturnVisitor<'c, 'view> {
     if self.getter_name.is_some() {
       self.has_return = true;
       if return_stmt.arg.is_none() {
-        self.report_expected(return_stmt.span);
+        self.report_expected(return_stmt.range());
       }
     }
   }
diff --git a/src/rules/no_array_constructor.rs b/src/rules/no_array_constructor.rs
index c89b8a8..f80b1d5 100644
--- a/src/rules/no_array_constructor.rs
+++ b/src/rules/no_array_constructor.rs
@@ -2,9 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Span;
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{CallExpr, Callee, Expr, ExprOrSpread, NewExpr};
+use deno_ast::{SourceRange, SourceRanged};
 use std::sync::Arc;
 
 #[derive(Debug)]
@@ -49,9 +48,13 @@ impl LintRule for NoArrayConstructor {
   }
 }
 
-fn check_args(args: Vec<&ExprOrSpread>, span: Span, context: &mut Context) {
+fn check_args(
+  args: Vec<&ExprOrSpread>,
+  range: SourceRange,
+  context: &mut Context,
+) {
   if args.len() != 1 {
-    context.add_diagnostic_with_hint(span, CODE, MESSAGE, HINT);
+    context.add_diagnostic_with_hint(range, CODE, MESSAGE, HINT);
   }
 }
 
@@ -69,9 +72,9 @@ impl Handler for NoArrayConstructorHandler {
       }
       match &new_expr.args {
         Some(args) => {
-          check_args(args.to_vec(), new_expr.span(), context);
+          check_args(args.to_vec(), new_expr.range(), context);
         }
-        None => check_args(vec![], new_expr.span(), context),
+        None => check_args(vec![], new_expr.range(), context),
       };
     }
   }
@@ -86,7 +89,7 @@ impl Handler for NoArrayConstructorHandler {
         return;
       }
 
-      check_args((&*call_expr.args).to_vec(), call_expr.span(), context);
+      check_args((&*call_expr.args).to_vec(), call_expr.range(), context);
     }
   }
 }
diff --git a/src/rules/no_async_promise_executor.rs b/src/rules/no_async_promise_executor.rs
index 34b340f..cae04f8 100644
--- a/src/rules/no_async_promise_executor.rs
+++ b/src/rules/no_async_promise_executor.rs
@@ -2,8 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{Expr, NewExpr, ParenExpr};
+use deno_ast::SourceRanged;
 use std::sync::Arc;
 
 #[derive(Debug)]
@@ -72,7 +72,7 @@ impl Handler for NoAsyncPromiseExecutorHandler {
         if let Some(first_arg) = args.get(0) {
           if is_async_function(&first_arg.expr) {
             context.add_diagnostic_with_hint(
-              new_expr.span(),
+              new_expr.range(),
               CODE,
               MESSAGE,
               HINT,
diff --git a/src/rules/no_await_in_loop.rs b/src/rules/no_await_in_loop.rs
index 0f88689..20ec4ad 100644
--- a/src/rules/no_await_in_loop.rs
+++ b/src/rules/no_await_in_loop.rs
@@ -2,9 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
-use deno_ast::view as ast_view;
 use deno_ast::view::NodeTrait;
+use deno_ast::{view as ast_view, SourceRanged};
 use std::sync::Arc;
 
 #[derive(Debug)]
@@ -66,7 +65,7 @@ impl Handler for NoAwaitInLoopHandler {
           // except for the case where the given `await_expr` is contained in the `right` part.
           // e.g. for (const x of await xs) { ... }
           //                      ^^^^^^^^ <-------- `right` part
-          !right.span().contains(await_expr.span())
+          !right.range().contains(&await_expr.range())
         }
         ForStmt(stmt) => {
           // When it encounters `ForStmt`, we should treat it as `inside_loop = true`
@@ -76,7 +75,7 @@ impl Handler for NoAwaitInLoopHandler {
           stmt
             .init
             .as_ref()
-            .map_or(true, |init| !init.span().contains(await_expr.span()))
+            .map_or(true, |init| !init.range().contains(&await_expr.range()))
         }
         WhileStmt(_) | DoWhileStmt(_) => true,
         _ => {
@@ -90,7 +89,7 @@ impl Handler for NoAwaitInLoopHandler {
     }
 
     if inside_loop(await_expr, await_expr.as_node()) {
-      ctx.add_diagnostic_with_hint(await_expr.span(), CODE, MESSAGE, HINT);
+      ctx.add_diagnostic_with_hint(await_expr.range(), CODE, MESSAGE, HINT);
     }
   }
 }
diff --git a/src/rules/no_case_declarations.rs b/src/rules/no_case_declarations.rs
index bf39aa0..d83ab20 100644
--- a/src/rules/no_case_declarations.rs
+++ b/src/rules/no_case_declarations.rs
@@ -2,8 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{Decl, Stmt, SwitchCase, VarDeclKind};
+use deno_ast::SourceRanged;
 use std::sync::Arc;
 
 #[derive(Debug)]
@@ -65,7 +65,7 @@ impl Handler for NoCaseDeclarationsHandler {
 
       if is_lexical_decl {
         context.add_diagnostic_with_hint(
-          switch_case.span(),
+          switch_case.range(),
           CODE,
           MESSAGE,
           HINT,
diff --git a/src/rules/no_class_assign.rs b/src/rules/no_class_assign.rs
index 829ff99..a92e9f6 100644
--- a/src/rules/no_class_assign.rs
+++ b/src/rules/no_class_assign.rs
@@ -7,6 +7,7 @@ use deno_ast::swc::visit::noop_visit_type;
 use deno_ast::swc::visit::VisitAll;
 use deno_ast::swc::visit::VisitAllWith;
 use deno_ast::BindingKind;
+use deno_ast::SourceRangedForSpanned;
 use std::sync::Arc;
 
 #[derive(Debug)]
@@ -67,7 +68,7 @@ impl<'c, 'view> VisitAll for NoClassAssignVisitor<'c, 'view> {
       if let Some(var) = var {
         if let BindingKind::Class = var.kind() {
           self.context.add_diagnostic_with_hint(
-            assign_expr.span,
+            assign_expr.range(),
             CODE,
             MESSAGE,
             HINT,
diff --git a/src/rules/no_compare_neg_zero.rs b/src/rules/no_compare_neg_zero.rs
index cb9139d..dccf392 100644
--- a/src/rules/no_compare_neg_zero.rs
+++ b/src/rules/no_compare_neg_zero.rs
@@ -7,8 +7,8 @@ use deno_ast::swc::ast::Expr::Lit;
 use deno_ast::swc::ast::Lit::Num;
 use deno_ast::swc::ast::UnaryExpr;
 use deno_ast::swc::ast::UnaryOp::Minus;
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{BinExpr, BinaryOp, Expr};
+use deno_ast::SourceRanged;
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -72,7 +72,7 @@ impl Handler for NoCompareNegZeroHandler {
 
     if bin_expr.left.is_neg_zero() || bin_expr.right.is_neg_zero() {
       context.add_diagnostic_with_hint(
-        bin_expr.span(),
+        bin_expr.range(),
         CODE,
         NoCompareNegZeroMessage::Unexpected,
         NoCompareNegZeroHint::ObjectIs,
diff --git a/src/rules/no_cond_assign.rs b/src/rules/no_cond_assign.rs
index 61efc09..bd25e11 100644
--- a/src/rules/no_cond_assign.rs
+++ b/src/rules/no_cond_assign.rs
@@ -2,9 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Span;
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{CondExpr, DoWhileStmt, Expr, ForStmt, IfStmt, WhileStmt};
+use deno_ast::{SourceRange, SourceRanged};
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -63,9 +62,9 @@ impl LintRule for NoCondAssign {
 struct NoCondAssignHandler;
 
 impl NoCondAssignHandler {
-  fn add_diagnostic(&mut self, span: Span, ctx: &mut Context) {
+  fn add_diagnostic(&mut self, range: SourceRange, ctx: &mut Context) {
     ctx.add_diagnostic_with_hint(
-      span,
+      range,
       CODE,
       NoCondAssignMessage::Unexpected,
       NoCondAssignHint::ChangeOrMove,
@@ -75,7 +74,7 @@ impl NoCondAssignHandler {
   fn check_condition(&mut self, condition: &Expr, ctx: &mut Context) {
     match condition {
       Expr::Assign(assign) => {
-        self.add_diagnostic(assign.span(), ctx);
+        self.add_diagnostic(assign.range(), ctx);
       }
       Expr::Bin(bin) => {
         if bin.op() == deno_ast::swc::ast::BinaryOp::LogicalOr {
diff --git a/src/rules/no_const_assign.rs b/src/rules/no_const_assign.rs
index 2f3a4d8..6e0071a 100644
--- a/src/rules/no_const_assign.rs
+++ b/src/rules/no_const_assign.rs
@@ -2,13 +2,11 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Span;
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{
   ArrayPat, AssignExpr, Expr, Ident, ObjectPat, ObjectPatProp, Pat, PatOrExpr,
   UpdateExpr,
 };
-use deno_ast::BindingKind;
+use deno_ast::{BindingKind, SourceRange, SourceRanged};
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -59,49 +57,49 @@ impl LintRule for NoConstAssign {
 
 struct NoConstAssignHandler;
 
-fn check_pat(pat: &Pat, span: Span, ctx: &mut Context) {
+fn check_pat(pat: &Pat, range: SourceRange, ctx: &mut Context) {
   match pat {
     Pat::Ident(ident) => {
-      check_scope_for_const(span, ident.id, ctx);
+      check_scope_for_const(range, ident.id, ctx);
     }
     Pat::Assign(assign) => {
-      check_pat(&assign.left, span, ctx);
+      check_pat(&assign.left, range, ctx);
     }
     Pat::Array(array) => {
-      check_array_pat(array, span, ctx);
+      check_array_pat(array, range, ctx);
     }
     Pat::Object(object) => {
-      check_obj_pat(object, span, ctx);
+      check_obj_pat(object, range, ctx);
     }
     _ => {}
   }
 }
 
-fn check_obj_pat(object: &ObjectPat, span: Span, ctx: &mut Context) {
+fn check_obj_pat(object: &ObjectPat, range: SourceRange, ctx: &mut Context) {
   if !object.props.is_empty() {
     for prop in object.props.iter() {
       if let ObjectPatProp::Assign(assign_prop) = prop {
-        check_scope_for_const(assign_prop.key.span(), assign_prop.key, ctx);
+        check_scope_for_const(assign_prop.key.range(), assign_prop.key, ctx);
       } else if let ObjectPatProp::KeyValue(kv_prop) = prop {
-        check_pat(&kv_prop.value, span, ctx);
+        check_pat(&kv_prop.value, range, ctx);
       }
     }
   }
 }
 
-fn check_array_pat(array: &ArrayPat, span: Span, ctx: &mut Context) {
+fn check_array_pat(array: &ArrayPat, range: SourceRange, ctx: &mut Context) {
   if !array.elems.is_empty() {
     for elem in array.elems.iter().flatten() {
-      check_pat(elem, span, ctx);
+      check_pat(elem, range, ctx);
     }
   }
 }
 
-fn check_scope_for_const(span: Span, name: &Ident, ctx: &mut Context) {
+fn check_scope_for_const(range: SourceRange, name: &Ident, ctx: &mut Context) {
   if let Some(v) = ctx.scope().var_by_ident(name) {
     if let BindingKind::Const = v.kind() {
       ctx.add_diagnostic_with_hint(
-        span,
+        range,
         CODE,
         NoConstantAssignMessage::Unexpected,
         NoConstantAssignHint::Remove,
@@ -115,18 +113,18 @@ impl Handler for NoConstAssignHandler {
     match &assign_expr.left {
       PatOrExpr::Expr(pat_expr) => {
         if let Expr::Ident(ident) = pat_expr {
-          check_scope_for_const(assign_expr.span(), ident, ctx);
+          check_scope_for_const(assign_expr.range(), ident, ctx);
         }
       }
       PatOrExpr::Pat(boxed_pat) => {
-        check_pat(boxed_pat, assign_expr.span(), ctx)
+        check_pat(boxed_pat, assign_expr.range(), ctx)
       }
     };
   }
 
   fn update_expr(&mut self, update_expr: &UpdateExpr, ctx: &mut Context) {
     if let Expr::Ident(ident) = update_expr.arg {
-      check_scope_for_const(update_expr.span(), ident, ctx);
+      check_scope_for_const(update_expr.range(), ident, ctx);
     }
   }
 }
diff --git a/src/rules/no_constant_condition.rs b/src/rules/no_constant_condition.rs
index e01d43b..ae51cd0 100644
--- a/src/rules/no_constant_condition.rs
+++ b/src/rules/no_constant_condition.rs
@@ -2,9 +2,9 @@
 use super::{Context, LintRule};
 use crate::ProgramRef;
 use deno_ast::swc::ast::{BinaryOp, CondExpr, Expr, IfStmt, Lit, UnaryOp};
-use deno_ast::swc::common::Span;
-use deno_ast::swc::common::Spanned;
 use deno_ast::swc::visit::{noop_visit_type, VisitAll, VisitAllWith};
+use deno_ast::SourceRange;
+use deno_ast::SourceRangedForSpanned;
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -67,9 +67,9 @@ impl<'c, 'view> NoConstantConditionVisitor<'c, 'view> {
     Self { context }
   }
 
-  fn add_diagnostic(&mut self, span: Span) {
+  fn add_diagnostic(&mut self, range: SourceRange) {
     self.context.add_diagnostic_with_hint(
-      span,
+      range,
       CODE,
       NoConstantConditionMessage::Unexpected,
       NoConstantConditionHint::Remove,
@@ -179,8 +179,8 @@ impl<'c, 'view> NoConstantConditionVisitor<'c, 'view> {
 
   fn report(&mut self, condition: &Expr) {
     if self.is_constant(condition, None, true) {
-      let span = condition.span();
-      self.add_diagnostic(span);
+      let range = condition.range();
+      self.add_diagnostic(range);
     }
   }
 }
diff --git a/src/rules/no_control_regex.rs b/src/rules/no_control_regex.rs
index 7791902..721ab37 100644
--- a/src/rules/no_control_regex.rs
+++ b/src/rules/no_control_regex.rs
@@ -3,9 +3,8 @@ use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::swc_util::extract_regex;
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Span;
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{CallExpr, Callee, Expr, NewExpr, Regex};
+use deno_ast::{SourceRange, SourceRanged};
 use derive_more::Display;
 use std::iter::Peekable;
 use std::str::Chars;
@@ -66,16 +65,16 @@ impl LintRule for NoControlRegex {
 
 struct NoControlRegexHandler;
 
-fn add_diagnostic(span: Span, cp: u64, ctx: &mut Context) {
+fn add_diagnostic(range: SourceRange, cp: u64, ctx: &mut Context) {
   ctx.add_diagnostic_with_hint(
-    span,
+    range,
     CODE,
     NoControlRegexMessage::Unexpected(cp),
     NoControlRegexHint::DisableOrRework,
   );
 }
 
-fn check_regex(regex: &str, span: Span, ctx: &mut Context) {
+fn check_regex(regex: &str, range: SourceRange, ctx: &mut Context) {
   let mut iter = regex.chars().peekable();
   while let Some(ch) = iter.next() {
     if ch != '\\' {
@@ -85,7 +84,7 @@ fn check_regex(regex: &str, span: Span, ctx: &mut Context) {
       Some('x') => {
         if let Some(cp) = read_hex_n(&mut iter, 2) {
           if cp <= 31 {
-            add_diagnostic(span, cp, ctx);
+            add_diagnostic(range, cp, ctx);
             return;
           }
         }
@@ -98,7 +97,7 @@ fn check_regex(regex: &str, span: Span, ctx: &mut Context) {
         };
         if let Some(cp) = cp {
           if cp <= 31 {
-            add_diagnostic(span, cp, ctx);
+            add_diagnostic(range, cp, ctx);
             return;
           }
         }
@@ -134,14 +133,14 @@ fn read_hex_until_brace(iter: &mut Peekable<Chars>) -> Option<u64> {
 
 impl Handler for NoControlRegexHandler {
   fn regex(&mut self, regex: &Regex, ctx: &mut Context) {
-    check_regex(regex.inner.exp.to_string().as_str(), regex.span(), ctx);
+    check_regex(regex.inner.exp.to_string().as_str(), regex.range(), ctx);
   }
 
   fn new_expr(&mut self, new_expr: &NewExpr, ctx: &mut Context) {
     if let Expr::Ident(ident) = new_expr.callee {
       if let Some(args) = &new_expr.args {
         if let Some(regex) = extract_regex(ctx.scope(), ident, args) {
-          check_regex(regex.as_str(), new_expr.span(), ctx);
+          check_regex(regex.as_str(), new_expr.range(), ctx);
         }
       }
     }
@@ -150,7 +149,7 @@ impl Handler for NoControlRegexHandler {
   fn call_expr(&mut self, call_expr: &CallExpr, ctx: &mut Context) {
     if let Callee::Expr(Expr::Ident(ident)) = &call_expr.callee {
       if let Some(regex) = extract_regex(ctx.scope(), ident, &call_expr.args) {
-        check_regex(regex.as_str(), call_expr.span(), ctx);
+        check_regex(regex.as_str(), call_expr.range(), ctx);
       }
     }
   }
diff --git a/src/rules/no_debugger.rs b/src/rules/no_debugger.rs
index 9970d25..4da9b38 100644
--- a/src/rules/no_debugger.rs
+++ b/src/rules/no_debugger.rs
@@ -2,8 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::DebuggerStmt;
+use deno_ast::SourceRanged;
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -60,7 +60,7 @@ struct NoDebuggerHandler;
 impl Handler for NoDebuggerHandler {
   fn debugger_stmt(&mut self, debugger_stmt: &DebuggerStmt, ctx: &mut Context) {
     ctx.add_diagnostic_with_hint(
-      debugger_stmt.span(),
+      debugger_stmt.range(),
       CODE,
       NoDebuggerMessage::Unexpected,
       NoDebuggerHint::Remove,
diff --git a/src/rules/no_delete_var.rs b/src/rules/no_delete_var.rs
index 7588667..83a77b3 100644
--- a/src/rules/no_delete_var.rs
+++ b/src/rules/no_delete_var.rs
@@ -2,8 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{Expr, UnaryExpr, UnaryOp};
+use deno_ast::SourceRanged;
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -69,7 +69,7 @@ impl Handler for NoDeleteVarHandler {
 
     if let Expr::Ident(_) = unary_expr.arg {
       ctx.add_diagnostic_with_hint(
-        unary_expr.span(),
+        unary_expr.range(),
         CODE,
         NoDeleteVarMessage::Unexpected,
         NoDeleteVarHint::Remove,
diff --git a/src/rules/no_deprecated_deno_api.rs b/src/rules/no_deprecated_deno_api.rs
index 2665f4d..473aef0 100644
--- a/src/rules/no_deprecated_deno_api.rs
+++ b/src/rules/no_deprecated_deno_api.rs
@@ -3,9 +3,7 @@ use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
 use deno_ast::swc::atoms::JsWord;
-use deno_ast::swc::common::Spanned;
-use deno_ast::swc::utils::ident::IdentLike;
-use deno_ast::view as ast_view;
+use deno_ast::{view as ast_view, SourceRanged};
 use if_chain::if_chain;
 use std::convert::TryFrom;
 use std::sync::Arc;
@@ -192,7 +190,7 @@ impl Handler for NoDeprecatedDenoApiHandler {
       if let Ok(deprecated_api) = DeprecatedApi::try_from((obj_symbol, prop_symbol));
       then {
         ctx.add_diagnostic_with_hint(
-          member_expr.span(),
+          member_expr.range(),
           CODE,
           deprecated_api.message(),
           deprecated_api.hint(),
@@ -214,7 +212,7 @@ impl Handler for NoDeprecatedDenoApiHandler {
       then {
         let deprecated_api = DeprecatedApi::File;
         ctx.add_diagnostic_with_hint(
-          qualified_name.span(),
+          qualified_name.range(),
           CODE,
           deprecated_api.message(),
           deprecated_api.hint(),
diff --git a/src/rules/no_dupe_args.rs b/src/rules/no_dupe_args.rs
index 3b7d4b1..39779ed 100644
--- a/src/rules/no_dupe_args.rs
+++ b/src/rules/no_dupe_args.rs
@@ -2,9 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Span;
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{ArrowExpr, Function, Param, Pat};
+use deno_ast::{SourceRange, SourceRanged};
 use derive_more::Display;
 use std::collections::{BTreeSet, HashSet};
 use std::sync::Arc;
@@ -62,14 +61,14 @@ impl LintRule for NoDupeArgs {
 #[derive(Default)]
 struct NoDupeArgsHandler {
   /// Accumulated errors to report
-  error_spans: BTreeSet<Span>,
+  error_ranges: BTreeSet<SourceRange>,
 }
 
 impl NoDupeArgsHandler {
   fn report_errors(self, ctx: &mut Context) {
-    for span in &self.error_spans {
+    for range in &self.error_ranges {
       ctx.add_diagnostic_with_hint(
-        *span,
+        *range,
         CODE,
         NoDupeArgsMessage::Unexpected,
         NoDupeArgsHint::RenameOrRemove,
@@ -77,7 +76,7 @@ impl NoDupeArgsHandler {
     }
   }
 
-  fn check_pats<'a, 'b, I>(&'a mut self, span: Span, pats: I)
+  fn check_pats<'a, 'b, I>(&'a mut self, range: SourceRange, pats: I)
   where
     I: Iterator<Item = &'b Pat<'b>>,
   {
@@ -87,7 +86,7 @@ impl NoDupeArgsHandler {
       match &pat {
         Pat::Ident(ident) => {
           if !seen.insert(ident.id.inner.as_ref()) {
-            self.error_spans.insert(span);
+            self.error_ranges.insert(range);
           }
         }
         _ => continue,
@@ -95,22 +94,22 @@ impl NoDupeArgsHandler {
     }
   }
 
-  fn check_params<'a, 'b, I>(&'a mut self, span: Span, params: I)
+  fn check_params<'a, 'b, I>(&'a mut self, range: SourceRange, params: I)
   where
     I: Iterator<Item = &'b &'b Param<'b>>,
   {
     let pats = params.map(|param| &param.pat);
-    self.check_pats(span, pats);
+    self.check_pats(range, pats);
   }
 }
 
 impl Handler for NoDupeArgsHandler {
   fn function(&mut self, function: &Function, _ctx: &mut Context) {
-    self.check_params(function.span(), function.params.iter());
+    self.check_params(function.range(), function.params.iter());
   }
 
   fn arrow_expr(&mut self, arrow_expr: &ArrowExpr, _ctx: &mut Context) {
-    self.check_pats(arrow_expr.span(), arrow_expr.params.iter());
+    self.check_pats(arrow_expr.range(), arrow_expr.params.iter());
   }
 }
 
diff --git a/src/rules/no_dupe_class_members.rs b/src/rules/no_dupe_class_members.rs
index b7d7735..827ad49 100644
--- a/src/rules/no_dupe_class_members.rs
+++ b/src/rules/no_dupe_class_members.rs
@@ -5,8 +5,9 @@ use deno_ast::swc::ast::{
   BigInt, Bool, Class, ClassMethod, ComputedPropName, Expr, Ident, Lit,
   MethodKind, Null, Number, PropName, Str, Tpl,
 };
-use deno_ast::swc::common::Span;
 use deno_ast::swc::visit::{noop_visit_type, Visit, VisitWith};
+use deno_ast::SourceRange;
+use deno_ast::SourceRangedForSpanned;
 use derive_more::Display;
 use std::cmp::Ordering;
 use std::collections::BTreeMap;
@@ -69,9 +70,9 @@ impl<'c, 'view> NoDupeClassMembersVisitor<'c, 'view> {
     Self { context }
   }
 
-  fn add_diagnostic(&mut self, span: Span, name: &str) {
+  fn add_diagnostic(&mut self, range: SourceRange, name: &str) {
     self.context.add_diagnostic_with_hint(
-      span,
+      range,
       CODE,
       NoDupeClassMembersMessage::Duplicate(name.to_string()),
       NoDupeClassMembersHint::RenameOrRemove,
@@ -91,7 +92,7 @@ impl<'c, 'view> Visit for NoDupeClassMembersVisitor<'c, 'view> {
 
 struct ClassVisitor<'a, 'b, 'view> {
   root_visitor: &'b mut NoDupeClassMembersVisitor<'a, 'view>,
-  appeared_methods: BTreeMap<MethodToCheck, Vec<(Span, String)>>,
+  appeared_methods: BTreeMap<MethodToCheck, Vec<(SourceRange, String)>>,
 }
 
 impl<'a, 'b, 'view> ClassVisitor<'a, 'b, 'view> {
@@ -110,8 +111,8 @@ impl<'a, 'b, 'view> ClassVisitor<'a, 'b, 'view> {
       .values()
       .filter(|m| m.len() >= 2)
       .flatten()
-      .for_each(|(span, name)| {
-        root_visitor.add_diagnostic(*span, name);
+      .for_each(|(range, name)| {
+        root_visitor.add_diagnostic(*range, name);
       });
   }
 }
@@ -137,7 +138,7 @@ impl<'a, 'b, 'view> Visit for ClassVisitor<'a, 'b, 'view> {
           .appeared_methods
           .entry(m)
           .or_insert_with(Vec::new)
-          .push((class_method.span, name));
+          .push((class_method.range(), name));
       }
     }
     class_method.visit_children_with(self);
diff --git a/src/rules/no_dupe_else_if.rs b/src/rules/no_dupe_else_if.rs
index ac7882b..28b42b0 100644
--- a/src/rules/no_dupe_else_if.rs
+++ b/src/rules/no_dupe_else_if.rs
@@ -2,9 +2,9 @@
 use super::{Context, LintRule};
 use crate::ProgramRef;
 use deno_ast::swc::ast::{BinExpr, BinaryOp, Expr, IfStmt, ParenExpr, Stmt};
-use deno_ast::swc::common::{Span, Spanned};
 use deno_ast::swc::utils::drop_span;
 use deno_ast::swc::visit::{noop_visit_type, VisitAll, VisitAllWith};
+use deno_ast::{SourceRange, SourceRangedForSpanned};
 use derive_more::Display;
 use std::collections::HashSet;
 use std::sync::Arc;
@@ -66,14 +66,14 @@ impl LintRule for NoDupeElseIf {
 /// [eslint/no-dupe-else-if.js](https://github.com/eslint/eslint/blob/master/lib/rules/no-dupe-else-if.js).
 struct NoDupeElseIfVisitor<'c, 'view> {
   context: &'c mut Context<'view>,
-  checked_span: HashSet<Span>,
+  checked_ranges: HashSet<SourceRange>,
 }
 
 impl<'c, 'view> NoDupeElseIfVisitor<'c, 'view> {
   fn new(context: &'c mut Context<'view>) -> Self {
     Self {
       context,
-      checked_span: HashSet::new(),
+      checked_ranges: HashSet::new(),
     }
   }
 }
@@ -82,11 +82,11 @@ impl<'c, 'view> VisitAll for NoDupeElseIfVisitor<'c, 'view> {
   noop_visit_type!();
 
   fn visit_if_stmt(&mut self, if_stmt: &IfStmt) {
-    let span = if_stmt.test.span();
+    let range = if_stmt.test.range();
 
     // This check is necessary to avoid outputting the same errors multiple times.
-    if !self.checked_span.contains(&span) {
-      self.checked_span.insert(span);
+    if !self.checked_ranges.contains(&range) {
+      self.checked_ranges.insert(range);
       let span_dropped_test = drop_span(if_stmt.test.clone());
       let mut appeared_conditions: Vec<Vec<Vec<Expr>>> = Vec::new();
       append_test(&mut appeared_conditions, *span_dropped_test);
@@ -97,8 +97,8 @@ impl<'c, 'view> VisitAll for NoDupeElseIfVisitor<'c, 'view> {
           ref test, ref alt, ..
         }) = &**cur
         {
-          // preserve the span before dropping
-          let span = test.span();
+          // preserve the range before dropping
+          let range = test.range();
           let span_dropped_test = drop_span(test.clone());
           let mut current_condition_to_check: Vec<Vec<Vec<Expr>>> =
             mk_condition_to_check(*span_dropped_test.clone())
@@ -126,7 +126,7 @@ impl<'c, 'view> VisitAll for NoDupeElseIfVisitor<'c, 'view> {
               .any(|or_operands| or_operands.is_empty())
             {
               self.context.add_diagnostic_with_hint(
-                span,
+                range,
                 CODE,
                 NoDupeElseIfMessage::Unexpected,
                 NoDupeElseIfHint::RemoveOrRework,
@@ -135,7 +135,7 @@ impl<'c, 'view> VisitAll for NoDupeElseIfVisitor<'c, 'view> {
             }
           }
 
-          self.checked_span.insert(span);
+          self.checked_ranges.insert(range);
           append_test(&mut appeared_conditions, *span_dropped_test);
           next = alt.as_ref();
         } else {
diff --git a/src/rules/no_dupe_keys.rs b/src/rules/no_dupe_keys.rs
index af3103b..3b61853 100644
--- a/src/rules/no_dupe_keys.rs
+++ b/src/rules/no_dupe_keys.rs
@@ -3,12 +3,11 @@ use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::swc_util::StringRepr;
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Span;
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{
   GetterProp, KeyValueProp, MethodProp, ObjectLit, Prop, PropOrSpread,
   SetterProp,
 };
+use deno_ast::{SourceRange, SourceRanged};
 use derive_more::Display;
 use std::collections::hash_map::Entry;
 use std::collections::HashMap;
@@ -65,9 +64,14 @@ impl LintRule for NoDupeKeys {
 struct NoDupeKeysHandler;
 
 impl NoDupeKeysHandler {
-  fn report(&mut self, span: Span, key: impl Into<String>, ctx: &mut Context) {
+  fn report(
+    &mut self,
+    range: SourceRange,
+    key: impl Into<String>,
+    ctx: &mut Context,
+  ) {
     ctx.add_diagnostic_with_hint(
-      span,
+      range,
       CODE,
       NoDupeKeysMessage::Duplicate(key.into()),
       NoDupeKeysHint::RemoveOrRename,
@@ -76,7 +80,7 @@ impl NoDupeKeysHandler {
 
   fn check_key<S: Into<String>>(
     &mut self,
-    obj_span: Span,
+    obj_range: SourceRange,
     key: Option<S>,
     keys: &mut HashMap<String, PropertyInfo>,
     ctx: &mut Context,
@@ -86,7 +90,7 @@ impl NoDupeKeysHandler {
 
       match keys.entry(key) {
         Entry::Occupied(occupied) => {
-          self.report(obj_span, occupied.key(), ctx);
+          self.report(obj_range, occupied.key(), ctx);
         }
         Entry::Vacant(vacant) => {
           vacant.insert(PropertyInfo::default());
@@ -97,7 +101,7 @@ impl NoDupeKeysHandler {
 
   fn check_getter<S: Into<String>>(
     &mut self,
-    obj_span: Span,
+    obj_range: SourceRange,
     key: Option<S>,
     keys: &mut HashMap<String, PropertyInfo>,
     ctx: &mut Context,
@@ -110,7 +114,7 @@ impl NoDupeKeysHandler {
           if occupied.get().setter_only() {
             occupied.get_mut().getter = true;
           } else {
-            self.report(obj_span, occupied.key(), ctx);
+            self.report(obj_range, occupied.key(), ctx);
           }
         }
         Entry::Vacant(vacant) => {
@@ -125,7 +129,7 @@ impl NoDupeKeysHandler {
 
   fn check_setter<S: Into<String>>(
     &mut self,
-    obj_span: Span,
+    obj_range: SourceRange,
     key: Option<S>,
     keys: &mut HashMap<String, PropertyInfo>,
     ctx: &mut Context,
@@ -138,7 +142,7 @@ impl NoDupeKeysHandler {
           if occupied.get().getter_only() {
             occupied.get_mut().setter = true;
           } else {
-            self.report(obj_span, occupied.key(), ctx);
+            self.report(obj_range, occupied.key(), ctx);
           }
         }
         Entry::Vacant(vacant) => {
@@ -170,27 +174,27 @@ impl PropertyInfo {
 
 impl Handler for NoDupeKeysHandler {
   fn object_lit(&mut self, obj_lit: &ObjectLit, ctx: &mut Context) {
-    let span = obj_lit.span();
+    let range = obj_lit.range();
     let mut keys: HashMap<String, PropertyInfo> = HashMap::new();
 
     for prop in &obj_lit.props {
       if let PropOrSpread::Prop(prop) = prop {
         match prop {
           Prop::Shorthand(ident) => {
-            self.check_key(span, Some(ident.inner.as_ref()), &mut keys, ctx);
+            self.check_key(range, Some(ident.inner.as_ref()), &mut keys, ctx);
           }
           Prop::KeyValue(KeyValueProp { key, .. }) => {
-            self.check_key(span, key.string_repr(), &mut keys, ctx);
+            self.check_key(range, key.string_repr(), &mut keys, ctx);
           }
           Prop::Assign(_) => {}
           Prop::Getter(GetterProp { key, .. }) => {
-            self.check_getter(span, key.string_repr(), &mut keys, ctx);
+            self.check_getter(range, key.string_repr(), &mut keys, ctx);
           }
           Prop::Setter(SetterProp { key, .. }) => {
-            self.check_setter(span, key.string_repr(), &mut keys, ctx);
+            self.check_setter(range, key.string_repr(), &mut keys, ctx);
           }
           Prop::Method(MethodProp { key, .. }) => {
-            self.check_key(span, key.string_repr(), &mut keys, ctx);
+            self.check_key(range, key.string_repr(), &mut keys, ctx);
           }
         }
       }
diff --git a/src/rules/no_duplicate_case.rs b/src/rules/no_duplicate_case.rs
index 966d845..b17d388 100644
--- a/src/rules/no_duplicate_case.rs
+++ b/src/rules/no_duplicate_case.rs
@@ -5,6 +5,7 @@ use deno_ast::swc::ast::{Expr, SwitchStmt};
 use deno_ast::swc::utils::drop_span;
 use deno_ast::swc::visit::noop_visit_type;
 use deno_ast::swc::visit::{VisitAll, VisitAllWith};
+use deno_ast::SourceRangedForSpanned;
 use derive_more::Display;
 use std::collections::HashSet;
 use std::sync::Arc;
@@ -79,7 +80,7 @@ impl<'c, 'view> VisitAll for NoDuplicateCaseVisitor<'c, 'view> {
         let span_dropped_test = drop_span(test.clone());
         if !seen.insert(span_dropped_test) {
           self.context.add_diagnostic_with_hint(
-            case.span,
+            case.range(),
             CODE,
             NoDuplicateCaseMessage::Unexpected,
             NoDuplicateCaseHint::RemoveOrRename,
diff --git a/src/rules/no_empty.rs b/src/rules/no_empty.rs
index d4af0fc..662f919 100644
--- a/src/rules/no_empty.rs
+++ b/src/rules/no_empty.rs
@@ -2,8 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{ArrowExpr, BlockStmt, Constructor, Function, SwitchStmt};
+use deno_ast::{SourceRanged, SourceRangedForSpanned};
 use std::sync::Arc;
 
 #[derive(Debug)]
@@ -57,7 +57,7 @@ impl Handler for NoEmptyHandler {
       && !block_stmt.contains_comments(ctx)
     {
       ctx.add_diagnostic_with_hint(
-        block_stmt.span(),
+        block_stmt.range(),
         CODE,
         "Empty block statement",
         "Add code or comment to the empty block",
@@ -68,7 +68,7 @@ impl Handler for NoEmptyHandler {
   fn switch_stmt(&mut self, switch: &SwitchStmt, ctx: &mut Context) {
     if switch.cases.is_empty() {
       ctx.add_diagnostic_with_hint(
-        switch.span(),
+        switch.range(),
         CODE,
         "Empty switch statement",
         "Add case statement(s) to the empty switch, or remove",
@@ -85,7 +85,7 @@ impl ContainsComments for BlockStmt<'_> {
   fn contains_comments(&self, context: &Context) -> bool {
     context
       .all_comments()
-      .any(|comment| self.span().contains(comment.span))
+      .any(|comment| self.range().contains(&comment.range()))
   }
 }
 
diff --git a/src/rules/no_empty_character_class.rs b/src/rules/no_empty_character_class.rs
index 149c386..ca56f95 100644
--- a/src/rules/no_empty_character_class.rs
+++ b/src/rules/no_empty_character_class.rs
@@ -2,8 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::Regex;
+use deno_ast::SourceRanged;
 use once_cell::sync::Lazy;
 use std::sync::Arc;
 
@@ -50,7 +50,7 @@ struct NoEmptyCharacterClassVisitor;
 
 impl Handler for NoEmptyCharacterClassVisitor {
   fn regex(&mut self, regex: &Regex, ctx: &mut Context) {
-    let raw_regex = ctx.file_text_substring(&regex.span());
+    let raw_regex = regex.text_fast(&ctx.text_info());
 
     static RULE_REGEX: Lazy<regex::Regex> = Lazy::new(|| {
       /* reference : [eslint no-empty-character-class](https://github.com/eslint/eslint/blob/master/lib/rules/no-empty-character-class.js#L13)
@@ -70,7 +70,7 @@ impl Handler for NoEmptyCharacterClassVisitor {
     });
 
     if !RULE_REGEX.is_match(raw_regex) {
-      ctx.add_diagnostic_with_hint(regex.span(), CODE, MESSAGE, HINT);
+      ctx.add_diagnostic_with_hint(regex.range(), CODE, MESSAGE, HINT);
     }
   }
 }
diff --git a/src/rules/no_empty_enum.rs b/src/rules/no_empty_enum.rs
index 7a970d5..0c9e8bd 100644
--- a/src/rules/no_empty_enum.rs
+++ b/src/rules/no_empty_enum.rs
@@ -2,8 +2,7 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
-use deno_ast::view as ast_view;
+use deno_ast::{view as ast_view, SourceRanged};
 use std::sync::Arc;
 
 #[derive(Debug)]
@@ -56,7 +55,7 @@ impl Handler for NoEmptyEnumHandler {
     ctx: &mut Context,
   ) {
     if enum_decl.members.is_empty() {
-      ctx.add_diagnostic(enum_decl.span(), CODE, MESSAGE);
+      ctx.add_diagnostic(enum_decl.range(), CODE, MESSAGE);
     }
   }
 }
diff --git a/src/rules/no_empty_interface.rs b/src/rules/no_empty_interface.rs
index 2257f8e..4a60c2c 100644
--- a/src/rules/no_empty_interface.rs
+++ b/src/rules/no_empty_interface.rs
@@ -2,8 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::TsInterfaceDecl;
+use deno_ast::SourceRanged;
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -74,7 +74,7 @@ impl Handler for NoEmptyInterfaceHandler {
     if interface_decl.extends.len() <= 1 && interface_decl.body.body.is_empty()
     {
       ctx.add_diagnostic_with_hint(
-        interface_decl.span(),
+        interface_decl.range(),
         CODE,
         if interface_decl.extends.is_empty() {
           NoEmptyInterfaceMessage::EmptyObject
diff --git a/src/rules/no_empty_pattern.rs b/src/rules/no_empty_pattern.rs
index a11cc46..819656e 100644
--- a/src/rules/no_empty_pattern.rs
+++ b/src/rules/no_empty_pattern.rs
@@ -4,6 +4,7 @@ use crate::ProgramRef;
 use deno_ast::swc::ast::{ArrayPat, ObjectPat, ObjectPatProp};
 use deno_ast::swc::visit::noop_visit_type;
 use deno_ast::swc::visit::Visit;
+use deno_ast::SourceRangedForSpanned;
 use std::sync::Arc;
 
 #[derive(Debug)]
@@ -71,9 +72,12 @@ impl<'c, 'view> Visit for NoEmptyPatternVisitor<'c, 'view> {
   fn visit_object_pat(&mut self, obj_pat: &ObjectPat) {
     if obj_pat.props.is_empty() {
       if obj_pat.type_ann.is_none() {
-        self
-          .context
-          .add_diagnostic_with_hint(obj_pat.span, CODE, MESSAGE, HINT)
+        self.context.add_diagnostic_with_hint(
+          obj_pat.range(),
+          CODE,
+          MESSAGE,
+          HINT,
+        )
       }
     } else {
       for prop in &obj_pat.props {
@@ -84,9 +88,12 @@ impl<'c, 'view> Visit for NoEmptyPatternVisitor<'c, 'view> {
 
   fn visit_array_pat(&mut self, arr_pat: &ArrayPat) {
     if arr_pat.elems.is_empty() {
-      self
-        .context
-        .add_diagnostic_with_hint(arr_pat.span, CODE, MESSAGE, HINT)
+      self.context.add_diagnostic_with_hint(
+        arr_pat.range(),
+        CODE,
+        MESSAGE,
+        HINT,
+      )
     } else {
       for element in arr_pat.elems.iter().flatten() {
         if let deno_ast::swc::ast::Pat::Object(obj_pat) = element {
diff --git a/src/rules/no_eval.rs b/src/rules/no_eval.rs
index 4172314..26322bd 100644
--- a/src/rules/no_eval.rs
+++ b/src/rules/no_eval.rs
@@ -3,9 +3,8 @@ use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::swc_util::StringRepr;
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Span;
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{CallExpr, Callee, Expr, ParenExpr, VarDeclarator};
+use deno_ast::{SourceRange, SourceRanged};
 use std::sync::Arc;
 
 #[derive(Debug)]
@@ -48,16 +47,16 @@ impl NoEvalHandler {
   fn maybe_add_diagnostic(
     &mut self,
     source: &dyn StringRepr,
-    span: Span,
+    range: SourceRange,
     ctx: &mut Context,
   ) {
     if source.string_repr().as_deref() == Some("eval") {
-      self.add_diagnostic(span, ctx);
+      self.add_diagnostic(range, ctx);
     }
   }
 
-  fn add_diagnostic(&mut self, span: Span, ctx: &mut Context) {
-    ctx.add_diagnostic_with_hint(span, CODE, MESSAGE, HINT);
+  fn add_diagnostic(&mut self, range: SourceRange, ctx: &mut Context) {
+    ctx.add_diagnostic_with_hint(range, CODE, MESSAGE, HINT);
   }
 
   fn handle_paren_callee(&mut self, p: &ParenExpr, ctx: &mut Context) {
@@ -65,12 +64,14 @@ impl NoEvalHandler {
       // Nested paren callee ((eval))('var foo = 0;')
       Expr::Paren(paren) => self.handle_paren_callee(paren, ctx),
       // Single argument callee: (eval)('var foo = 0;')
-      Expr::Ident(ident) => self.maybe_add_diagnostic(ident, ident.span(), ctx),
+      Expr::Ident(ident) => {
+        self.maybe_add_diagnostic(ident, ident.range(), ctx)
+      }
       // Multiple arguments callee: (0, eval)('var foo = 0;')
       Expr::Seq(seq) => {
         for expr in &seq.exprs {
           if let Expr::Ident(ident) = expr {
-            self.maybe_add_diagnostic(*ident, ident.span(), ctx)
+            self.maybe_add_diagnostic(*ident, ident.range(), ctx)
           }
         }
       }
@@ -82,7 +83,7 @@ impl NoEvalHandler {
 impl Handler for NoEvalHandler {
   fn var_declarator(&mut self, v: &VarDeclarator, ctx: &mut Context) {
     if let Some(Expr::Ident(ident)) = &v.init {
-      self.maybe_add_diagnostic(*ident, v.span(), ctx);
+      self.maybe_add_diagnostic(*ident, v.range(), ctx);
     }
   }
 
@@ -90,7 +91,7 @@ impl Handler for NoEvalHandler {
     if let Callee::Expr(expr) = &call_expr.callee {
       match expr {
         Expr::Ident(ident) => {
-          self.maybe_add_diagnostic(*ident, call_expr.span(), ctx)
+          self.maybe_add_diagnostic(*ident, call_expr.range(), ctx)
         }
         Expr::Paren(paren) => self.handle_paren_callee(paren, ctx),
         _ => {}
diff --git a/src/rules/no_ex_assign.rs b/src/rules/no_ex_assign.rs
index 233a8b2..187764c 100644
--- a/src/rules/no_ex_assign.rs
+++ b/src/rules/no_ex_assign.rs
@@ -2,12 +2,10 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Span;
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{
   ArrayPat, AssignExpr, Expr, Ident, ObjectPat, ObjectPatProp, Pat, PatOrExpr,
 };
-use deno_ast::BindingKind;
+use deno_ast::{BindingKind, SourceRange, SourceRanged};
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -61,49 +59,49 @@ impl LintRule for NoExAssign {
 
 struct NoExAssignHandler;
 
-fn check_pat(pat: &Pat, span: Span, ctx: &mut Context) {
+fn check_pat(pat: &Pat, range: SourceRange, ctx: &mut Context) {
   match pat {
     Pat::Ident(ident) => {
-      check_scope_for_const(span, ident.id, ctx);
+      check_scope_for_const(range, ident.id, ctx);
     }
     Pat::Assign(assign) => {
-      check_pat(&assign.left, span, ctx);
+      check_pat(&assign.left, range, ctx);
     }
     Pat::Array(array) => {
-      check_array_pat(array, span, ctx);
+      check_array_pat(array, range, ctx);
     }
     Pat::Object(object) => {
-      check_obj_pat(object, span, ctx);
+      check_obj_pat(object, range, ctx);
     }
     _ => {}
   }
 }
 
-fn check_obj_pat(object: &ObjectPat, span: Span, ctx: &mut Context) {
+fn check_obj_pat(object: &ObjectPat, range: SourceRange, ctx: &mut Context) {
   if !object.props.is_empty() {
     for prop in object.props.iter() {
       if let ObjectPatProp::Assign(assign_prop) = prop {
-        check_scope_for_const(assign_prop.key.span(), assign_prop.key, ctx);
+        check_scope_for_const(assign_prop.key.range(), assign_prop.key, ctx);
       } else if let ObjectPatProp::KeyValue(kv_prop) = prop {
-        check_pat(&kv_prop.value, span, ctx);
+        check_pat(&kv_prop.value, range, ctx);
       }
     }
   }
 }
 
-fn check_array_pat(array: &ArrayPat, span: Span, ctx: &mut Context) {
+fn check_array_pat(array: &ArrayPat, range: SourceRange, ctx: &mut Context) {
   if !array.elems.is_empty() {
     for elem in array.elems.iter().flatten() {
-      check_pat(elem, span, ctx);
+      check_pat(elem, range, ctx);
     }
   }
 }
 
-fn check_scope_for_const(span: Span, name: &Ident, ctx: &mut Context) {
+fn check_scope_for_const(range: SourceRange, name: &Ident, ctx: &mut Context) {
   if let Some(v) = ctx.scope().var_by_ident(name) {
     if let BindingKind::CatchClause = v.kind() {
       ctx.add_diagnostic_with_hint(
-        span,
+        range,
         CODE,
         NoExAssignMessage::NotAllowed,
         NoExAssignHint::UseDifferent,
@@ -117,11 +115,11 @@ impl Handler for NoExAssignHandler {
     match &assign_expr.left {
       PatOrExpr::Expr(pat_expr) => {
         if let Expr::Ident(ident) = pat_expr {
-          check_scope_for_const(assign_expr.span(), ident, ctx);
+          check_scope_for_const(assign_expr.range(), ident, ctx);
         }
       }
       PatOrExpr::Pat(boxed_pat) => {
-        check_pat(boxed_pat, assign_expr.span(), ctx)
+        check_pat(boxed_pat, assign_expr.range(), ctx)
       }
     };
   }
diff --git a/src/rules/no_explicit_any.rs b/src/rules/no_explicit_any.rs
index f29a076..0fa64de 100644
--- a/src/rules/no_explicit_any.rs
+++ b/src/rules/no_explicit_any.rs
@@ -3,8 +3,8 @@ use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
 use deno_ast::swc::ast::TsKeywordTypeKind::TsAnyKeyword;
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::TsKeywordType;
+use deno_ast::SourceRanged;
 use std::sync::Arc;
 
 #[derive(Debug)]
@@ -54,7 +54,12 @@ impl Handler for NoExplicitAnyHandler {
     ctx: &mut Context,
   ) {
     if ts_keyword_type.keyword_kind() == TsAnyKeyword {
-      ctx.add_diagnostic_with_hint(ts_keyword_type.span(), CODE, MESSAGE, HINT);
+      ctx.add_diagnostic_with_hint(
+        ts_keyword_type.range(),
+        CODE,
+        MESSAGE,
+        HINT,
+      );
     }
   }
 }
diff --git a/src/rules/no_external_imports.rs b/src/rules/no_external_imports.rs
index 1bc70a7..e6d04f0 100644
--- a/src/rules/no_external_imports.rs
+++ b/src/rules/no_external_imports.rs
@@ -2,9 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::ImportDecl;
-use deno_ast::ModuleSpecifier;
+use deno_ast::{ModuleSpecifier, SourceRanged};
 use derive_more::Display;
 use std::ffi::OsStr;
 use std::path::Path;
@@ -71,7 +70,7 @@ impl NoExternalImportHandler {
 
     if parsed_src.is_ok() && file_name != Some("deps") {
       ctx.add_diagnostic_with_hint(
-        decl.span(),
+        decl.range(),
         CODE,
         NoExternalImportMessage::Unexpected,
         NoExternalImportHint::CreateDependencyFile,
diff --git a/src/rules/no_extra_boolean_cast.rs b/src/rules/no_extra_boolean_cast.rs
index ac7e8d7..c2410da 100644
--- a/src/rules/no_extra_boolean_cast.rs
+++ b/src/rules/no_extra_boolean_cast.rs
@@ -2,12 +2,13 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Span;
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{
   CallExpr, Callee, CondExpr, DoWhileStmt, Expr, ExprOrSpread, ForStmt, Ident,
   IfStmt, NewExpr, ParenExpr, UnaryExpr, UnaryOp, WhileStmt,
 };
+use deno_ast::SourceRange;
+use deno_ast::SourceRanged;
+use deno_ast::SourceRangedForSpanned;
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -65,18 +66,18 @@ impl LintRule for NoExtraBooleanCast {
 
 struct NoExtraBooleanCastHandler;
 
-fn unexpected_call(span: Span, ctx: &mut Context) {
+fn unexpected_call(range: SourceRange, ctx: &mut Context) {
   ctx.add_diagnostic_with_hint(
-    span,
+    range,
     CODE,
     NoExtraBooleanCastMessage::BooleanCall,
     NoExtraBooleanCastHint::BooleanCall,
   );
 }
 
-fn unexpected_negation(span: Span, ctx: &mut Context) {
+fn unexpected_negation(range: SourceRange, ctx: &mut Context) {
   ctx.add_diagnostic_with_hint(
-    span,
+    range,
     CODE,
     NoExtraBooleanCastMessage::DoubleNegation,
     NoExtraBooleanCastHint::DoubleNegation,
@@ -89,11 +90,11 @@ fn check_condition(expr: &Expr, ctx: &mut Context) {
       ref callee, inner, ..
     }) => {
       if callee_is_boolean(callee) {
-        unexpected_call(inner.span, ctx);
+        unexpected_call(inner.range(), ctx);
       }
     }
     Expr::Unary(UnaryExpr { inner, ref arg, .. }) if has_n_bang(arg, 1) => {
-      unexpected_negation(inner.span, ctx);
+      unexpected_negation(inner.range(), ctx);
     }
     Expr::Paren(ParenExpr { ref expr, .. }) => {
       check_condition(expr, ctx);
@@ -105,26 +106,26 @@ fn check_condition(expr: &Expr, ctx: &mut Context) {
 fn check_unary_expr(unary_expr: &UnaryExpr, ctx: &mut Context) {
   if unary_expr.op() == UnaryOp::Bang {
     let expr = &unary_expr.arg;
-    check_unary_expr_internal(unary_expr.span(), expr, ctx);
+    check_unary_expr_internal(unary_expr.range(), expr, ctx);
   }
 }
 
 fn check_unary_expr_internal(
-  unary_expr_span: Span,
+  unary_expr_range: SourceRange,
   internal_expr: &Expr,
   ctx: &mut Context,
 ) {
   match internal_expr {
     Expr::Call(CallExpr { ref callee, .. }) => {
       if callee_is_boolean(callee) {
-        unexpected_call(unary_expr_span, ctx);
+        unexpected_call(unary_expr_range, ctx);
       }
     }
     Expr::Unary(UnaryExpr { ref arg, .. }) if has_n_bang(arg, 1) => {
-      unexpected_negation(unary_expr_span, ctx);
+      unexpected_negation(unary_expr_range, ctx);
     }
     Expr::Paren(ParenExpr { ref expr, .. }) => {
-      check_unary_expr_internal(unary_expr_span, expr, ctx);
+      check_unary_expr_internal(unary_expr_range, expr, ctx);
     }
     _ => (),
   }
diff --git a/src/rules/no_extra_non_null_assertion.rs b/src/rules/no_extra_non_null_assertion.rs
index 6166a11..e085d01 100644
--- a/src/rules/no_extra_non_null_assertion.rs
+++ b/src/rules/no_extra_non_null_assertion.rs
@@ -5,12 +5,12 @@ use crate::handler::Handler;
 use crate::handler::Traverse;
 use crate::Program;
 use crate::ProgramRef;
-use deno_ast::swc::common::Span;
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::Expr;
 use deno_ast::view::OptChainBase;
 use deno_ast::view::OptChainExpr;
 use deno_ast::view::TsNonNullExpr;
+use deno_ast::SourceRange;
+use deno_ast::SourceRanged;
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -64,9 +64,9 @@ impl LintRule for NoExtraNonNullAssertion {
 
 struct NoExtraNonNullAssertionHandler;
 
-fn add_diagnostic(span: Span, ctx: &mut Context) {
+fn add_diagnostic(range: SourceRange, ctx: &mut Context) {
   ctx.add_diagnostic_with_hint(
-    span,
+    range,
     CODE,
     NoExtraNonNullAssertionMessage::Unexpected,
     NoExtraNonNullAssertionHint::Remove,
@@ -74,14 +74,14 @@ fn add_diagnostic(span: Span, ctx: &mut Context) {
 }
 
 fn check_expr_for_nested_non_null_assert(
-  span: Span,
+  range: SourceRange,
   expr: &Expr,
   ctx: &mut Context,
 ) {
   match expr {
-    Expr::TsNonNull(_) => add_diagnostic(span, ctx),
+    Expr::TsNonNull(_) => add_diagnostic(range, ctx),
     Expr::Paren(paren_expr) => {
-      check_expr_for_nested_non_null_assert(span, &paren_expr.expr, ctx)
+      check_expr_for_nested_non_null_assert(range, &paren_expr.expr, ctx)
     }
     _ => {}
   }
@@ -94,7 +94,7 @@ impl Handler for NoExtraNonNullAssertionHandler {
     ctx: &mut Context,
   ) {
     check_expr_for_nested_non_null_assert(
-      ts_non_null_expr.span(),
+      ts_non_null_expr.range(),
       &ts_non_null_expr.expr,
       ctx,
     );
@@ -109,7 +109,7 @@ impl Handler for NoExtraNonNullAssertionHandler {
       OptChainBase::Member(member_expr) => &member_expr.obj,
       OptChainBase::Call(call_expr) => &call_expr.callee,
     };
-    check_expr_for_nested_non_null_assert(opt_chain_expr.span(), expr, ctx);
+    check_expr_for_nested_non_null_assert(opt_chain_expr.range(), expr, ctx);
   }
 }
 
diff --git a/src/rules/no_extra_semi.rs b/src/rules/no_extra_semi.rs
index 7e88f07..8d96713 100644
--- a/src/rules/no_extra_semi.rs
+++ b/src/rules/no_extra_semi.rs
@@ -6,6 +6,7 @@ use deno_ast::swc::ast::{
   Stmt, WhileStmt, WithStmt,
 };
 use deno_ast::swc::visit::{noop_visit_type, Visit, VisitWith};
+use deno_ast::SourceRangedForSpanned;
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -72,7 +73,7 @@ impl<'c, 'view> Visit for NoExtraSemiVisitor<'c, 'view> {
 
   fn visit_empty_stmt(&mut self, empty_stmt: &EmptyStmt) {
     self.context.add_diagnostic_with_hint(
-      empty_stmt.span,
+      empty_stmt.range(),
       CODE,
       NoExtraSemiMessage::Unnecessary,
       NoExtraSemiHint::Remove,
diff --git a/src/rules/no_fallthrough.rs b/src/rules/no_fallthrough.rs
index 8d628ac..fb27066 100644
--- a/src/rules/no_fallthrough.rs
+++ b/src/rules/no_fallthrough.rs
@@ -1,11 +1,12 @@
 // Copyright 2020-2021 the Deno authors. All rights reserved. MIT license.
 use super::{Context, LintRule};
 use crate::ProgramRef;
-use deno_ast::swc::common::{comments::Comment, Span, Spanned, DUMMY_SP};
+use deno_ast::swc::common::comments::Comment;
 use deno_ast::swc::{
   ast::*,
   visit::{noop_visit_type, Visit, VisitWith},
 };
+use deno_ast::{SourceRange, SourceRanged, SourceRangedForSpanned};
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -68,20 +69,22 @@ impl<'c, 'view> Visit for NoFallthroughVisitor<'c, 'view> {
 
   fn visit_switch_cases(&mut self, cases: &[SwitchCase]) {
     let mut should_emit_err = false;
-    let mut prev_span = DUMMY_SP;
+    let mut prev_range = None;
 
     'cases: for (case_idx, case) in cases.iter().enumerate() {
       case.visit_with(self);
 
       if should_emit_err {
-        let comments = self.context.leading_comments_at(case.span.lo);
+        let comments = self.context.leading_comments_at(case.start());
         if !allow_fall_through(comments) {
-          self.context.add_diagnostic_with_hint(
-            prev_span,
-            CODE,
-            NoFallthroughMessage::Unexpected,
-            NoFallthroughHint::BreakOrComment,
-          );
+          if let Some(prev_range) = prev_range.take() {
+            self.context.add_diagnostic_with_hint(
+              prev_range,
+              CODE,
+              NoFallthroughMessage::Unexpected,
+              NoFallthroughHint::BreakOrComment,
+            );
+          }
         }
       }
       should_emit_err = true;
@@ -90,18 +93,18 @@ impl<'c, 'view> Visit for NoFallthroughVisitor<'c, 'view> {
       // Handle return / throw / break / continue
       for (idx, stmt) in case.cons.iter().enumerate() {
         let last = idx + 1 == case.cons.len();
-        let metadata = self.context.control_flow().meta(stmt.span().lo);
+        let metadata = self.context.control_flow().meta(stmt.start());
         stops_exec |= metadata.map(|v| v.stops_execution()).unwrap_or(false);
         if stops_exec {
           should_emit_err = false;
         }
 
         if last {
-          let comments = self.context.trailing_comments_at(stmt.span().hi);
+          let comments = self.context.trailing_comments_at(stmt.end());
           if allow_fall_through(comments) {
             should_emit_err = false;
             // User comment beats everything
-            prev_span = case.span;
+            prev_range = Some(case.range());
             continue 'cases;
           }
         }
@@ -111,16 +114,11 @@ impl<'c, 'view> Visit for NoFallthroughVisitor<'c, 'view> {
         || matches!(case.cons.as_slice(), [Stmt::Block(b)] if b.stmts.is_empty());
 
       if case_idx + 1 < cases.len() && empty {
-        let span = Span {
-          lo: case.span.lo(),
-          hi: cases[case_idx + 1].span.lo(),
-          ctxt: case.span.ctxt,
-        };
-        // todo(dsherret): use `span.line_start_fast(context.program)` and
+        let range = SourceRange::new(case.start(), cases[case_idx + 1].start());
+        // todo(dsherret): use `range.line_start_fast(context.program)` and
         // `line_end_fast` when switching to ast_view
-        let span_line_count = self
-          .context
-          .file_text_substring(&span)
+        let range_line_count = range
+          .text_fast(&self.context.text_info())
           .chars()
           .filter(|c| *c == '\n')
           .count()
@@ -129,10 +127,10 @@ impl<'c, 'view> Visit for NoFallthroughVisitor<'c, 'view> {
         // This means there are no statements detected so we must detect case
         // bodies made up of only new lines by counting the total amount of new lines.
         // If there's more than 2 new lines and `case.cons` is empty this indicates the case body only contains new lines.
-        should_emit_err = span_line_count > 2;
+        should_emit_err = range_line_count > 2;
       }
 
-      prev_span = case.span;
+      prev_range = Some(case.range());
     }
   }
 }
diff --git a/src/rules/no_func_assign.rs b/src/rules/no_func_assign.rs
index 7189011..cf7937f 100644
--- a/src/rules/no_func_assign.rs
+++ b/src/rules/no_func_assign.rs
@@ -6,6 +6,7 @@ use deno_ast::swc::ast::AssignExpr;
 use deno_ast::swc::visit::noop_visit_type;
 use deno_ast::swc::visit::{VisitAll, VisitAllWith};
 use deno_ast::BindingKind;
+use deno_ast::SourceRangedForSpanned;
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -80,7 +81,7 @@ impl<'c, 'view> VisitAll for NoFuncAssignVisitor<'c, 'view> {
       if let Some(var) = var {
         if let BindingKind::Function = var.kind() {
           self.context.add_diagnostic_with_hint(
-            assign_expr.span,
+            assign_expr.range(),
             CODE,
             NoFuncAssignMessage::Unexpected,
             NoFuncAssignHint::RemoveOrRework,
diff --git a/src/rules/no_global_assign.rs b/src/rules/no_global_assign.rs
index 59c6125..a86daf0 100644
--- a/src/rules/no_global_assign.rs
+++ b/src/rules/no_global_assign.rs
@@ -2,13 +2,13 @@
 use super::{Context, LintRule};
 use crate::ProgramRef;
 use crate::{globals::GLOBALS, swc_util::find_lhs_ids};
-use deno_ast::swc::common::Span;
+use deno_ast::swc::ast::Id;
 use deno_ast::swc::{
   ast::*,
-  utils::ident::IdentLike,
-  utils::Id,
   visit::{noop_visit_type, Visit, VisitWith},
 };
+use deno_ast::SourceRange;
+use deno_ast::SourceRangedForSpanned;
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -69,8 +69,8 @@ impl<'c, 'view> NoGlobalAssignVisitor<'c, 'view> {
     Self { context }
   }
 
-  fn check(&mut self, span: Span, id: Id) {
-    if id.1 != self.context.top_level_ctxt() {
+  fn check(&mut self, range: SourceRange, id: Id) {
+    if id.1 != self.context.unresolved_ctxt() {
       return;
     }
 
@@ -85,7 +85,7 @@ impl<'c, 'view> NoGlobalAssignVisitor<'c, 'view> {
       // If global can be overwritten then don't need to report anything
       if !global.1 {
         self.context.add_diagnostic_with_hint(
-          span,
+          range,
           CODE,
           NoGlobalAssignMessage::NotAllowed,
           NoGlobalAssignHint::Remove,
@@ -102,13 +102,13 @@ impl<'c, 'view> Visit for NoGlobalAssignVisitor<'c, 'view> {
     let idents: Vec<Ident> = find_lhs_ids(&e.left);
 
     for ident in idents {
-      self.check(ident.span, ident.to_id());
+      self.check(ident.range(), ident.to_id());
     }
   }
 
   fn visit_update_expr(&mut self, e: &UpdateExpr) {
     if let Expr::Ident(i) = &*e.arg {
-      self.check(e.span, i.to_id());
+      self.check(e.range(), i.to_id());
     } else {
       e.visit_children_with(self);
     }
diff --git a/src/rules/no_import_assign.rs b/src/rules/no_import_assign.rs
index 25ea87d..39773d3 100644
--- a/src/rules/no_import_assign.rs
+++ b/src/rules/no_import_assign.rs
@@ -1,14 +1,14 @@
 // Copyright 2020-2021 the Deno authors. All rights reserved. MIT license.
 use super::{Context, LintRule};
 use crate::ProgramRef;
-use deno_ast::swc::common::Span;
-use deno_ast::swc::common::Spanned;
-use deno_ast::swc::{
-  ast::*,
-  utils::ident::IdentLike,
-  visit::{noop_visit_type, Visit, VisitWith},
-};
 use deno_ast::BindingKind;
+use deno_ast::{
+  swc::{
+    ast::*,
+    visit::{noop_visit_type, Visit, VisitWith},
+  },
+  SourceRange, SourceRangedForSpanned,
+};
 use std::sync::Arc;
 
 #[derive(Debug)]
@@ -58,12 +58,12 @@ impl<'c, 'view> NoImportAssignVisitor<'c, 'view> {
     Self { context }
   }
 
-  fn check(&mut self, span: Span, i: &Ident, is_assign_to_prop: bool) {
+  fn check(&mut self, range: SourceRange, i: &Ident, is_assign_to_prop: bool) {
     let var = self.context.scope().var(&i.to_id());
     if var.map_or(false, |v| v.kind() == BindingKind::NamespaceImport) {
       self
         .context
-        .add_diagnostic_with_hint(span, CODE, MESSAGE, HINT);
+        .add_diagnostic_with_hint(range, CODE, MESSAGE, HINT);
       return;
     }
 
@@ -72,26 +72,31 @@ impl<'c, 'view> NoImportAssignVisitor<'c, 'view> {
     {
       self
         .context
-        .add_diagnostic_with_hint(span, CODE, MESSAGE, HINT);
+        .add_diagnostic_with_hint(range, CODE, MESSAGE, HINT);
     }
   }
 
-  fn check_assign(&mut self, span: Span, lhs: &Expr, is_assign_to_prop: bool) {
+  fn check_assign(
+    &mut self,
+    range: SourceRange,
+    lhs: &Expr,
+    is_assign_to_prop: bool,
+  ) {
     if let Expr::Ident(lhs) = &lhs {
-      self.check(span, lhs, is_assign_to_prop);
+      self.check(range, lhs, is_assign_to_prop);
     }
   }
 
-  fn check_expr(&mut self, span: Span, e: &Expr) {
+  fn check_expr(&mut self, range: SourceRange, e: &Expr) {
     match e {
       Expr::Ident(i) => {
-        self.check(span, i, false);
+        self.check(range, i, false);
       }
-      Expr::Member(e) => self.check_assign(span, &e.obj, true),
-      Expr::Paren(e) => self.check_expr(span, &e.expr),
+      Expr::Member(e) => self.check_assign(range, &e.obj, true),
+      Expr::Paren(e) => self.check_expr(range, &e.expr),
       Expr::OptChain(e) => match &e.base {
         OptChainBase::Call(e) => self.visit_opt_call(e),
-        OptChainBase::Member(e) => self.check_expr(span, &e.obj),
+        OptChainBase::Member(e) => self.check_expr(range, &e.obj),
       },
       _ => e.visit_children_with(self),
     }
@@ -168,10 +173,10 @@ impl<'c, 'view> Visit for NoImportAssignVisitor<'c, 'view> {
   fn visit_pat(&mut self, n: &Pat) {
     match n {
       Pat::Ident(i) => {
-        self.check(i.id.span, &i.id, false);
+        self.check(i.id.range(), &i.id, false);
       }
       Pat::Expr(e) => {
-        self.check_expr(n.span(), e);
+        self.check_expr(n.range(), e);
       }
       _ => {
         n.visit_children_with(self);
@@ -183,10 +188,10 @@ impl<'c, 'view> Visit for NoImportAssignVisitor<'c, 'view> {
     if let Pat::Expr(e) = &*n.arg {
       match &**e {
         Expr::Ident(i) => {
-          self.check(i.span, i, true);
+          self.check(i.range(), i, true);
         }
         _ => {
-          self.check_expr(e.span(), e);
+          self.check_expr(e.range(), e);
         }
       }
     } else {
@@ -197,7 +202,7 @@ impl<'c, 'view> Visit for NoImportAssignVisitor<'c, 'view> {
   fn visit_assign_expr(&mut self, n: &AssignExpr) {
     match &n.left {
       PatOrExpr::Expr(e) => {
-        self.check_expr(n.span, e);
+        self.check_expr(n.range(), e);
       }
       PatOrExpr::Pat(p) => {
         p.visit_with(self);
@@ -207,18 +212,18 @@ impl<'c, 'view> Visit for NoImportAssignVisitor<'c, 'view> {
   }
 
   fn visit_assign_pat_prop(&mut self, n: &AssignPatProp) {
-    self.check(n.key.span, &n.key, false);
+    self.check(n.key.range(), &n.key, false);
 
     n.value.visit_children_with(self);
   }
 
   fn visit_update_expr(&mut self, n: &UpdateExpr) {
-    self.check_expr(n.span, &n.arg);
+    self.check_expr(n.range(), &n.arg);
   }
 
   fn visit_unary_expr(&mut self, n: &UnaryExpr) {
     if let UnaryOp::Delete = n.op {
-      self.check_expr(n.span, &n.arg);
+      self.check_expr(n.range(), &n.arg);
     } else {
       n.arg.visit_with(self);
     }
@@ -230,7 +235,7 @@ impl<'c, 'view> Visit for NoImportAssignVisitor<'c, 'view> {
     if let Callee::Expr(callee) = &n.callee {
       if let Some(arg) = n.args.first() {
         if self.modifies_first(callee) {
-          self.check_assign(n.span, &arg.expr, true);
+          self.check_assign(n.range(), &arg.expr, true);
         }
       }
     }
@@ -241,7 +246,7 @@ impl<'c, 'view> Visit for NoImportAssignVisitor<'c, 'view> {
 
     if let Some(arg) = n.args.first() {
       if self.modifies_first(&*n.callee) {
-        self.check_assign(n.span, &arg.expr, true);
+        self.check_assign(n.range(), &arg.expr, true);
       }
     }
   }
diff --git a/src/rules/no_inferrable_types.rs b/src/rules/no_inferrable_types.rs
index 932c31c..ad817c8 100644
--- a/src/rules/no_inferrable_types.rs
+++ b/src/rules/no_inferrable_types.rs
@@ -7,8 +7,9 @@ use deno_ast::swc::ast::{
   TsKeywordTypeKind, TsType, TsTypeAnn, TsTypeRef, UnaryExpr, VarDecl,
 };
 use deno_ast::swc::ast::{Callee, PropName};
-use deno_ast::swc::common::Span;
 use deno_ast::swc::visit::{VisitAll, VisitAllWith};
+use deno_ast::SourceRange;
+use deno_ast::SourceRangedForSpanned;
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -69,25 +70,35 @@ impl<'c, 'view> NoInferrableTypesVisitor<'c, 'view> {
     Self { context }
   }
 
-  fn add_diagnostic_helper(&mut self, span: Span) {
+  fn add_diagnostic_helper(&mut self, range: SourceRange) {
     self.context.add_diagnostic_with_hint(
-      span,
+      range,
       CODE,
       NoInferrableTypesMessage::NotAllowed,
       NoInferrableTypesHint::Remove,
     )
   }
 
-  fn check_callee(&mut self, callee: &Callee, span: Span, expected_sym: &str) {
+  fn check_callee(
+    &mut self,
+    callee: &Callee,
+    range: SourceRange,
+    expected_sym: &str,
+  ) {
     if let Callee::Expr(expr) = &callee {
-      self.check_callee_expr(expr, span, expected_sym);
+      self.check_callee_expr(expr, range, expected_sym);
     }
   }
 
-  fn check_callee_expr(&mut self, expr: &Expr, span: Span, expected_sym: &str) {
+  fn check_callee_expr(
+    &mut self,
+    expr: &Expr,
+    range: SourceRange,
+    expected_sym: &str,
+  ) {
     if let Expr::Ident(value) = expr {
       if value.sym == *expected_sym {
-        self.add_diagnostic_helper(span);
+        self.add_diagnostic_helper(range);
       }
     }
   }
@@ -100,29 +111,29 @@ impl<'c, 'view> NoInferrableTypesVisitor<'c, 'view> {
     &mut self,
     value: &Expr,
     ts_type: &TsKeywordType,
-    span: Span,
+    range: SourceRange,
   ) {
     use TsKeywordTypeKind::*;
     match ts_type.kind {
       TsBigIntKeyword => match &*value {
         Expr::Lit(Lit::BigInt(_)) => {
-          self.add_diagnostic_helper(span);
+          self.add_diagnostic_helper(range);
         }
         Expr::Call(CallExpr { callee, .. }) => {
-          self.check_callee(callee, span, "BigInt");
+          self.check_callee(callee, range, "BigInt");
         }
         Expr::Unary(UnaryExpr { arg, .. }) => match &**arg {
           Expr::Lit(Lit::BigInt(_)) => {
-            self.add_diagnostic_helper(span);
+            self.add_diagnostic_helper(range);
           }
           Expr::Call(CallExpr { callee, .. }) => {
-            self.check_callee(callee, span, "BigInt");
+            self.check_callee(callee, range, "BigInt");
           }
           Expr::OptChain(OptChainExpr {
             base: OptChainBase::Call(OptCall { callee, .. }),
             ..
           }) => {
-            self.check_callee_expr(callee, span, "BigInt");
+            self.check_callee_expr(callee, range, "BigInt");
           }
           _ => {}
         },
@@ -130,59 +141,59 @@ impl<'c, 'view> NoInferrableTypesVisitor<'c, 'view> {
           base: OptChainBase::Call(OptCall { callee, .. }),
           ..
         }) => {
-          self.check_callee_expr(callee, span, "BigInt");
+          self.check_callee_expr(callee, range, "BigInt");
         }
         _ => {}
       },
       TsBooleanKeyword => match &*value {
         Expr::Lit(Lit::Bool(_)) => {
-          self.add_diagnostic_helper(span);
+          self.add_diagnostic_helper(range);
         }
         Expr::Call(CallExpr { callee, .. }) => {
-          self.check_callee(callee, span, "Boolean");
+          self.check_callee(callee, range, "Boolean");
         }
         Expr::Unary(UnaryExpr { op, .. }) => {
           if op.to_string() == "!" {
-            self.add_diagnostic_helper(span);
+            self.add_diagnostic_helper(range);
           }
         }
         Expr::OptChain(OptChainExpr {
           base: OptChainBase::Call(OptCall { callee, .. }),
           ..
         }) => {
-          self.check_callee_expr(callee, span, "Boolean");
+          self.check_callee_expr(callee, range, "Boolean");
         }
         _ => {}
       },
       TsNumberKeyword => match &*value {
         Expr::Lit(Lit::Num(_)) => {
-          self.add_diagnostic_helper(span);
+          self.add_diagnostic_helper(range);
         }
         Expr::Call(CallExpr { callee, .. }) => {
-          self.check_callee(callee, span, "Number");
+          self.check_callee(callee, range, "Number");
         }
         Expr::Ident(ident) => {
           if self.is_nan_or_infinity(ident) {
-            self.add_diagnostic_helper(span);
+            self.add_diagnostic_helper(range);
           }
         }
         Expr::Unary(UnaryExpr { arg, .. }) => match &**arg {
           Expr::Lit(Lit::Num(_)) => {
-            self.add_diagnostic_helper(span);
+            self.add_diagnostic_helper(range);
           }
           Expr::Call(CallExpr { callee, .. }) => {
-            self.check_callee(callee, span, "Number");
+            self.check_callee(callee, range, "Number");
           }
           Expr::Ident(ident) => {
             if self.is_nan_or_infinity(ident) {
-              self.add_diagnostic_helper(span);
+              self.add_diagnostic_helper(range);
             }
           }
           Expr::OptChain(OptChainExpr {
             base: OptChainBase::Call(OptCall { callee, .. }),
             ..
           }) => {
-            self.check_callee_expr(callee, span, "Number");
+            self.check_callee_expr(callee, range, "Number");
           }
           _ => {}
         },
@@ -190,53 +201,53 @@ impl<'c, 'view> NoInferrableTypesVisitor<'c, 'view> {
           base: OptChainBase::Call(OptCall { callee, .. }),
           ..
         }) => {
-          self.check_callee_expr(callee, span, "Number");
+          self.check_callee_expr(callee, range, "Number");
         }
         _ => {}
       },
       TsNullKeyword => {
         if let Expr::Lit(Lit::Null(_)) = &*value {
-          self.add_diagnostic_helper(span);
+          self.add_diagnostic_helper(range);
         }
       }
       TsStringKeyword => match &*value {
         Expr::Lit(Lit::Str(_)) => {
-          self.add_diagnostic_helper(span);
+          self.add_diagnostic_helper(range);
         }
         Expr::Tpl(_) => {
-          self.add_diagnostic_helper(span);
+          self.add_diagnostic_helper(range);
         }
         Expr::Call(CallExpr { callee, .. }) => {
-          self.check_callee(callee, span, "String");
+          self.check_callee(callee, range, "String");
         }
         Expr::OptChain(OptChainExpr {
           base: OptChainBase::Call(OptCall { callee, .. }),
           ..
         }) => {
-          self.check_callee_expr(callee, span, "String");
+          self.check_callee_expr(callee, range, "String");
         }
         _ => {}
       },
       TsSymbolKeyword => {
         if let Expr::Call(CallExpr { callee, .. }) = &*value {
-          self.check_callee(callee, span, "Symbol");
+          self.check_callee(callee, range, "Symbol");
         } else if let Expr::OptChain(OptChainExpr {
           base: OptChainBase::Call(OptCall { callee, .. }),
           ..
         }) = &*value
         {
-          self.check_callee_expr(callee, span, "Symbol");
+          self.check_callee_expr(callee, range, "Symbol");
         }
       }
       TsUndefinedKeyword => match &*value {
         Expr::Ident(ident) => {
           if ident.sym == *"undefined" {
-            self.add_diagnostic_helper(span);
+            self.add_diagnostic_helper(range);
           }
         }
         Expr::Unary(UnaryExpr { op, .. }) => {
           if op.to_string() == "void" {
-            self.add_diagnostic_helper(span);
+            self.add_diagnostic_helper(range);
           }
         }
         _ => {}
@@ -245,27 +256,32 @@ impl<'c, 'view> NoInferrableTypesVisitor<'c, 'view> {
     }
   }
 
-  fn check_ref_type(&mut self, value: &Expr, ts_type: &TsTypeRef, span: Span) {
+  fn check_ref_type(
+    &mut self,
+    value: &Expr,
+    ts_type: &TsTypeRef,
+    range: SourceRange,
+  ) {
     if let TsEntityName::Ident(ident) = &ts_type.type_name {
       if ident.sym != *"RegExp" {
         return;
       }
       match &*value {
         Expr::Lit(Lit::Regex(_)) => {
-          self.add_diagnostic_helper(span);
+          self.add_diagnostic_helper(range);
         }
         Expr::Call(CallExpr { callee, .. }) => {
-          self.check_callee(callee, span, "RegExp");
+          self.check_callee(callee, range, "RegExp");
         }
         Expr::New(NewExpr { callee, .. }) => {
           if let Expr::Ident(ident) = &**callee {
             if ident.sym == *"RegExp" {
-              self.add_diagnostic_helper(span);
+              self.add_diagnostic_helper(range);
             }
           } else if let Expr::OptChain(opt_chain) = &**callee {
             if let OptChainBase::Call(OptCall { callee, .. }) = &opt_chain.base
             {
-              self.check_callee_expr(callee, span, "RegExp");
+              self.check_callee_expr(callee, range, "RegExp");
             }
           }
         }
@@ -273,18 +289,23 @@ impl<'c, 'view> NoInferrableTypesVisitor<'c, 'view> {
           base: OptChainBase::Call(OptCall { callee, .. }),
           ..
         }) => {
-          self.check_callee_expr(callee, span, "RegExp");
+          self.check_callee_expr(callee, range, "RegExp");
         }
         _ => {}
       }
     }
   }
 
-  fn check_ts_type(&mut self, value: &Expr, ts_type: &TsTypeAnn, span: Span) {
+  fn check_ts_type(
+    &mut self,
+    value: &Expr,
+    ts_type: &TsTypeAnn,
+    range: SourceRange,
+  ) {
     if let TsType::TsKeywordType(ts_type) = &*ts_type.type_ann {
-      self.check_keyword_type(value, ts_type, span);
+      self.check_keyword_type(value, ts_type, range);
     } else if let TsType::TsTypeRef(ts_type) = &*ts_type.type_ann {
-      self.check_ref_type(value, ts_type, span);
+      self.check_ref_type(value, ts_type, range);
     }
   }
 }
@@ -295,7 +316,11 @@ impl<'c, 'view> VisitAll for NoInferrableTypesVisitor<'c, 'view> {
       if let Pat::Assign(assign_pat) = &param.pat {
         if let Pat::Ident(ident) = &*assign_pat.left {
           if let Some(ident_type_ann) = &ident.type_ann {
-            self.check_ts_type(&assign_pat.right, ident_type_ann, param.span);
+            self.check_ts_type(
+              &assign_pat.right,
+              ident_type_ann,
+              param.range(),
+            );
           }
         }
       }
@@ -310,7 +335,7 @@ impl<'c, 'view> VisitAll for NoInferrableTypesVisitor<'c, 'view> {
             self.check_ts_type(
               &assign_pat.right,
               ident_type_ann,
-              assign_pat.span,
+              assign_pat.range(),
             );
           }
         }
@@ -325,7 +350,7 @@ impl<'c, 'view> VisitAll for NoInferrableTypesVisitor<'c, 'view> {
     if let Some(init) = &prop.value {
       if let PropName::Ident(_) = &prop.key {
         if let Some(ident_type_ann) = &prop.type_ann {
-          self.check_ts_type(init, ident_type_ann, prop.span);
+          self.check_ts_type(init, ident_type_ann, prop.range());
         }
       }
     }
@@ -337,7 +362,7 @@ impl<'c, 'view> VisitAll for NoInferrableTypesVisitor<'c, 'view> {
     }
     if let Some(init) = &prop.value {
       if let Some(ident_type_ann) = &prop.type_ann {
-        self.check_ts_type(init, ident_type_ann, prop.span);
+        self.check_ts_type(init, ident_type_ann, prop.range());
       }
     }
   }
@@ -347,7 +372,7 @@ impl<'c, 'view> VisitAll for NoInferrableTypesVisitor<'c, 'view> {
       if let Some(init) = &decl.init {
         if let Pat::Ident(ident) = &decl.name {
           if let Some(ident_type_ann) = &ident.type_ann {
-            self.check_ts_type(init, ident_type_ann, decl.span);
+            self.check_ts_type(init, ident_type_ann, decl.range());
           }
         }
       }
@@ -393,7 +418,6 @@ mod tests {
       "const a = /a/",
       "const a = RegExp('a')",
       "const a = RegExp?.('a')",
-      "const a = new RegExp?.('a')",
       "const a = 'str'",
       r#"const a = "str""#,
       "const a = `str`",
@@ -638,13 +662,6 @@ mod tests {
           hint: NoInferrableTypesHint::Remove,
         }
       ],
-      "const a: RegExp = new RegExp?.('a')": [
-        {
-          col: 6,
-          message: NoInferrableTypesMessage::NotAllowed,
-          hint: NoInferrableTypesHint::Remove,
-        }
-      ],
       "const a: string = 'str'": [
         {
           col: 6,
diff --git a/src/rules/no_inner_declarations.rs b/src/rules/no_inner_declarations.rs
index 78f2483..ae72c5c 100644
--- a/src/rules/no_inner_declarations.rs
+++ b/src/rules/no_inner_declarations.rs
@@ -5,11 +5,11 @@ use deno_ast::swc::ast::{
   ArrowExpr, BlockStmtOrExpr, Constructor, Decl, DefaultDecl, FnDecl, Function,
   ModuleDecl, ModuleItem, Script, Stmt, VarDecl, VarDeclKind,
 };
-use deno_ast::swc::common::Span;
-use deno_ast::swc::common::Spanned;
 use deno_ast::swc::visit::{
   noop_visit_type, Visit, VisitAll, VisitAllWith, VisitWith,
 };
+use deno_ast::SourceRange;
+use deno_ast::SourceRangedForSpanned;
 use derive_more::Display;
 use std::collections::HashSet;
 use std::sync::Arc;
@@ -70,7 +70,7 @@ impl LintRule for NoInnerDeclarations {
 }
 
 struct ValidDeclsVisitor {
-  valid_decls: HashSet<Span>,
+  valid_decls: HashSet<SourceRange>,
 }
 
 impl ValidDeclsVisitor {
@@ -93,11 +93,11 @@ impl ValidDeclsVisitor {
   fn check_decl(&mut self, decl: &Decl) {
     match decl {
       Decl::Fn(fn_decl) => {
-        self.valid_decls.insert(fn_decl.span());
+        self.valid_decls.insert(fn_decl.range());
       }
       Decl::Var(var_decl) => {
         if var_decl.kind == VarDeclKind::Var {
-          self.valid_decls.insert(var_decl.span());
+          self.valid_decls.insert(var_decl.range());
         }
       }
       _ => {}
@@ -124,7 +124,7 @@ impl VisitAll for ValidDeclsVisitor {
         }
         ModuleDecl::ExportDefaultDecl(default_export) => {
           if let DefaultDecl::Fn(fn_expr) = &default_export.decl {
-            self.valid_decls.insert(fn_expr.span());
+            self.valid_decls.insert(fn_expr.range());
           }
         }
         _ => {}
@@ -158,12 +158,15 @@ impl VisitAll for ValidDeclsVisitor {
 
 struct NoInnerDeclarationsVisitor<'c, 'view> {
   context: &'c mut Context<'view>,
-  valid_decls: HashSet<Span>,
+  valid_decls: HashSet<SourceRange>,
   in_function: bool,
 }
 
 impl<'c, 'view> NoInnerDeclarationsVisitor<'c, 'view> {
-  fn new(context: &'c mut Context<'view>, valid_decls: HashSet<Span>) -> Self {
+  fn new(
+    context: &'c mut Context<'view>,
+    valid_decls: HashSet<SourceRange>,
+  ) -> Self {
     Self {
       context,
       valid_decls,
@@ -173,7 +176,7 @@ impl<'c, 'view> NoInnerDeclarationsVisitor<'c, 'view> {
 }
 
 impl<'c, 'view> NoInnerDeclarationsVisitor<'c, 'view> {
-  fn add_diagnostic(&mut self, span: Span, kind: &str) {
+  fn add_diagnostic(&mut self, range: SourceRange, kind: &str) {
     let root = if self.in_function {
       "function"
     } else {
@@ -181,7 +184,7 @@ impl<'c, 'view> NoInnerDeclarationsVisitor<'c, 'view> {
     };
 
     self.context.add_diagnostic_with_hint(
-      span,
+      range,
       CODE,
       NoInnerDeclarationsMessage::Move(kind.to_string(), root.to_string()),
       NoInnerDeclarationsHint::Move,
@@ -207,20 +210,20 @@ impl<'c, 'view> Visit for NoInnerDeclarationsVisitor<'c, 'view> {
   }
 
   fn visit_fn_decl(&mut self, decl: &FnDecl) {
-    let span = decl.span();
+    let range = decl.range();
 
-    if !self.valid_decls.contains(&span) {
-      self.add_diagnostic(span, "function");
+    if !self.valid_decls.contains(&range) {
+      self.add_diagnostic(range, "function");
     }
 
     decl.visit_children_with(self);
   }
 
   fn visit_var_decl(&mut self, decl: &VarDecl) {
-    let span = decl.span();
+    let range = decl.range();
 
-    if decl.kind == VarDeclKind::Var && !self.valid_decls.contains(&span) {
-      self.add_diagnostic(span, "variable");
+    if decl.kind == VarDeclKind::Var && !self.valid_decls.contains(&range) {
+      self.add_diagnostic(range, "variable");
     }
 
     decl.visit_children_with(self);
diff --git a/src/rules/no_invalid_regexp.rs b/src/rules/no_invalid_regexp.rs
index c2e03de..5e830bb 100644
--- a/src/rules/no_invalid_regexp.rs
+++ b/src/rules/no_invalid_regexp.rs
@@ -4,9 +4,10 @@ use crate::js_regex::*;
 use crate::ProgramRef;
 use deno_ast::swc::ast::Expr;
 use deno_ast::swc::ast::ExprOrSpread;
-use deno_ast::swc::common::Span;
 use deno_ast::swc::visit::noop_visit_type;
 use deno_ast::swc::visit::Visit;
+use deno_ast::SourceRange;
+use deno_ast::SourceRangedForSpanned;
 use std::sync::Arc;
 
 #[derive(Debug)]
@@ -72,7 +73,7 @@ impl<'c, 'view> NoInvalidRegexpVisitor<'c, 'view> {
     &mut self,
     callee: &Expr,
     args: &[ExprOrSpread],
-    span: Span,
+    range: SourceRange,
   ) {
     if let Expr::Ident(ident) = callee {
       if ident.sym != *"RegExp" || args.is_empty() {
@@ -81,16 +82,16 @@ impl<'c, 'view> NoInvalidRegexpVisitor<'c, 'view> {
       if let Some(pattern) = &check_expr_for_string_literal(&*args[0].expr) {
         if args.len() > 1 {
           if let Some(flags) = &check_expr_for_string_literal(&*args[1].expr) {
-            self.check_regex(pattern, flags, span);
+            self.check_regex(pattern, flags, range);
             return;
           }
         }
-        self.check_regex(pattern, "", span);
+        self.check_regex(pattern, "", range);
       }
     }
   }
 
-  fn check_regex(&mut self, pattern: &str, flags: &str, span: Span) {
+  fn check_regex(&mut self, pattern: &str, flags: &str, range: SourceRange) {
     if self.check_for_invalid_flags(flags)
       || (!flags.is_empty()
         && self.check_for_invalid_pattern(pattern, flags.contains('u')))
@@ -99,7 +100,7 @@ impl<'c, 'view> NoInvalidRegexpVisitor<'c, 'view> {
     {
       self
         .context
-        .add_diagnostic_with_hint(span, CODE, MESSAGE, HINT);
+        .add_diagnostic_with_hint(range, CODE, MESSAGE, HINT);
     }
   }
 
@@ -116,12 +117,12 @@ impl<'c, 'view> Visit for NoInvalidRegexpVisitor<'c, 'view> {
   noop_visit_type!();
 
   fn visit_regex(&mut self, regex: &deno_ast::swc::ast::Regex) {
-    self.check_regex(&regex.exp, &regex.flags, regex.span);
+    self.check_regex(&regex.exp, &regex.flags, regex.range());
   }
 
   fn visit_call_expr(&mut self, call_expr: &deno_ast::swc::ast::CallExpr) {
     if let deno_ast::swc::ast::Callee::Expr(expr) = &call_expr.callee {
-      self.handle_call_or_new_expr(&*expr, &call_expr.args, call_expr.span);
+      self.handle_call_or_new_expr(&*expr, &call_expr.args, call_expr.range());
     }
   }
 
@@ -130,7 +131,7 @@ impl<'c, 'view> Visit for NoInvalidRegexpVisitor<'c, 'view> {
       self.handle_call_or_new_expr(
         &*new_expr.callee,
         new_expr.args.as_ref().unwrap(),
-        new_expr.span,
+        new_expr.range(),
       );
     }
   }
diff --git a/src/rules/no_invalid_triple_slash_reference.rs b/src/rules/no_invalid_triple_slash_reference.rs
index ed565fe..4005e7e 100644
--- a/src/rules/no_invalid_triple_slash_reference.rs
+++ b/src/rules/no_invalid_triple_slash_reference.rs
@@ -2,8 +2,8 @@
 use super::{Context, LintRule};
 use crate::{Program, ProgramRef};
 use deno_ast::swc::common::comments::{Comment, CommentKind};
-use deno_ast::swc::common::Span;
 use deno_ast::MediaType;
+use deno_ast::{SourceRange, SourceRangedForSpanned};
 use once_cell::sync::Lazy;
 use regex::Regex;
 use std::sync::Arc;
@@ -43,7 +43,7 @@ impl LintRule for NoInvalidTripleSlashReference {
       .filter_map(|comment| check_comment(comment, is_js_like))
     {
       context.add_diagnostic_with_hint(
-        report_kind.span(),
+        report_kind.range(),
         CODE,
         report_kind.as_message(),
         report_kind.as_hint(),
@@ -61,10 +61,10 @@ impl LintRule for NoInvalidTripleSlashReference {
 enum ReportKind {
   /// In JavaScript files, the directives other than `types`, `path` and `lib` are not allowed. This variant
   /// represents such invalid directives in JavaScript.
-  InvalidDirectiveInJs(Span),
+  InvalidDirectiveInJs(SourceRange),
 
   /// Represents an unsupported or badly-formed directive
-  InvalidDirective(Span),
+  InvalidDirective(SourceRange),
 }
 
 impl ReportKind {
@@ -92,11 +92,11 @@ impl ReportKind {
     }
   }
 
-  fn span(&self) -> Span {
+  fn range(&self) -> SourceRange {
     use ReportKind::*;
     match *self {
-      InvalidDirectiveInJs(span) => span,
-      InvalidDirective(span) => span,
+      InvalidDirectiveInJs(range) => range,
+      InvalidDirective(range) => range,
     }
   }
 }
@@ -134,7 +134,7 @@ fn check_comment(comment: &Comment, is_js_like: bool) -> Option<ReportKind> {
     {
       None
     } else {
-      Some(ReportKind::InvalidDirectiveInJs(comment.span))
+      Some(ReportKind::InvalidDirectiveInJs(comment.range()))
     }
   } else if is_path_ref(&comment.text)
     || is_types_ref(&comment.text)
@@ -143,7 +143,7 @@ fn check_comment(comment: &Comment, is_js_like: bool) -> Option<ReportKind> {
   {
     None
   } else {
-    Some(ReportKind::InvalidDirective(comment.span))
+    Some(ReportKind::InvalidDirective(comment.range()))
   }
 }
 
@@ -165,8 +165,17 @@ fn is_no_default_lib_ref(s: &str) -> bool {
 
 #[cfg(test)]
 mod tests {
+  use deno_ast::SourceRange;
+  use deno_ast::StartSourcePos;
+
   use super::*;
-  use deno_ast::swc::common::DUMMY_SP;
+
+  fn dummy_range() -> SourceRange {
+    SourceRange::new(
+      StartSourcePos::START_SOURCE_POS.into(),
+      StartSourcePos::START_SOURCE_POS.into(),
+    )
+  }
 
   #[test]
   fn test_is_path_ref() {
@@ -227,14 +236,14 @@ mod tests {
   fn line(text: &str) -> Comment {
     Comment {
       kind: CommentKind::Line,
-      span: DUMMY_SP,
+      span: dummy_range().into(),
       text: text.to_string(),
     }
   }
   fn block(text: &str) -> Comment {
     Comment {
       kind: CommentKind::Block,
-      span: DUMMY_SP,
+      span: dummy_range().into(),
       text: text.to_string(),
     }
   }
@@ -273,7 +282,7 @@ mod tests {
     ];
     for invalid_comment in &invalid_comments {
       let report_kind = check_comment(invalid_comment, true).unwrap();
-      assert_eq!(report_kind, ReportKind::InvalidDirectiveInJs(DUMMY_SP))
+      assert_eq!(report_kind, ReportKind::InvalidDirectiveInJs(dummy_range()))
     }
   }
 
@@ -300,7 +309,7 @@ mod tests {
     ];
     for invalid_comment in &invalid_comments {
       let report_kind = check_comment(invalid_comment, false).unwrap();
-      assert_eq!(report_kind, ReportKind::InvalidDirective(DUMMY_SP))
+      assert_eq!(report_kind, ReportKind::InvalidDirective(dummy_range()))
     }
   }
 
@@ -344,11 +353,11 @@ mod tests {
   #[test]
   fn triple_slash_reference_invalid() {
     let (not_types_in_js_msg, not_types_in_js_hint) = {
-      let r = ReportKind::InvalidDirectiveInJs(DUMMY_SP);
+      let r = ReportKind::InvalidDirectiveInJs(dummy_range());
       (r.as_message(), r.as_hint())
     };
     let (invalid_directive_msg, invalid_directive_hint) = {
-      let r = ReportKind::InvalidDirective(DUMMY_SP);
+      let r = ReportKind::InvalidDirective(dummy_range());
       (r.as_message(), r.as_hint())
     };
 
diff --git a/src/rules/no_irregular_whitespace.rs b/src/rules/no_irregular_whitespace.rs
index 3f3c8d9..46769d4 100644
--- a/src/rules/no_irregular_whitespace.rs
+++ b/src/rules/no_irregular_whitespace.rs
@@ -1,8 +1,8 @@
 // Copyright 2020-2021 the Deno authors. All rights reserved. MIT license.
 use super::{Context, LintRule};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::{hygiene::SyntaxContext, BytePos, Span};
-use deno_ast::view::RootNode;
+use deno_ast::{RootNode, SourceRangedForSpanned};
+use deno_ast::{SourceRange, SourceRanged};
 use derive_more::Display;
 use once_cell::sync::Lazy;
 use regex::{Matches, Regex};
@@ -61,23 +61,20 @@ impl LintRule for NoIrregularWhitespace {
     context: &mut Context,
     program: Program,
   ) {
-    let file_span = context.source_file().span();
-    let mut check_span = |span: Span| {
-      let whitespace_text = context.source_file().text()
-        [span.lo().0 as usize..span.hi().0 as usize]
-        .to_string();
+    let file_range = context.text_info().range();
+    let mut check_range = |range: SourceRange| {
+      let whitespace_text = range.text_fast(&context.text_info()).to_string();
       for whitespace_matches in
         test_for_whitespace(&whitespace_text).into_iter()
       {
         for whitespace_match in whitespace_matches {
-          let range = whitespace_match.range();
-          let span = Span::new(
-            span.lo() + BytePos(range.start as u32),
-            span.lo() + BytePos(range.end as u32),
-            SyntaxContext::empty(),
+          let whitespace_range = whitespace_match.range();
+          let range = SourceRange::new(
+            range.start + whitespace_range.start,
+            range.start + whitespace_range.end,
           );
           context.add_diagnostic_with_hint(
-            span,
+            range,
             CODE,
             NoIrregularWhitespaceMessage::NotAllowed,
             HINT,
@@ -85,14 +82,14 @@ impl LintRule for NoIrregularWhitespace {
         }
       }
     };
-    let mut last_end = BytePos(0);
+    let mut last_end = file_range.start.as_source_pos();
 
-    for token in program.token_container().unwrap().tokens {
-      check_span(Span::new(last_end, token.span.lo(), Default::default()));
-      last_end = token.span.hi();
+    for token in program.token_container().tokens {
+      check_range(SourceRange::new(last_end, token.start()));
+      last_end = token.end();
     }
 
-    check_span(Span::new(last_end, file_span.hi(), Default::default()));
+    check_range(SourceRange::new(last_end, file_range.end));
   }
 
   #[cfg(feature = "docs")]
diff --git a/src/rules/no_misused_new.rs b/src/rules/no_misused_new.rs
index a8c57ee..5c1b0e1 100644
--- a/src/rules/no_misused_new.rs
+++ b/src/rules/no_misused_new.rs
@@ -2,12 +2,12 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{
   ClassDecl, ClassMember, Expr, Ident, PropName, TsEntityName, TsInterfaceDecl,
   TsType, TsTypeAliasDecl, TsTypeAnn,
   TsTypeElement::{TsConstructSignatureDecl, TsMethodSignature},
 };
+use deno_ast::SourceRanged;
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -91,7 +91,7 @@ impl Handler for NoMisusedNewHandler {
           if let Expr::Ident(ident) = signature.key {
             if is_constructor_keyword(ident) {
               ctx.add_diagnostic_with_hint(
-                ident.span(),
+                ident.range(),
                 CODE,
                 NoMisusedNewMessage::TypeAlias,
                 NoMisusedNewHint::NotType,
@@ -111,7 +111,7 @@ impl Handler for NoMisusedNewHandler {
             if is_constructor_keyword(ident) {
               // constructor
               ctx.add_diagnostic_with_hint(
-                signature.span(),
+                signature.range(),
                 CODE,
                 NoMisusedNewMessage::Interface,
                 NoMisusedNewHint::NotInterface,
@@ -124,7 +124,7 @@ impl Handler for NoMisusedNewHandler {
             && match_parent_type(n.id, signature.type_ann.as_ref().unwrap())
           {
             ctx.add_diagnostic_with_hint(
-              signature.span(),
+              signature.range(),
               CODE,
               NoMisusedNewMessage::Interface,
               NoMisusedNewHint::NotInterface,
@@ -157,7 +157,7 @@ impl Handler for NoMisusedNewHandler {
         {
           // new
           ctx.add_diagnostic_with_hint(
-            method.span(),
+            method.range(),
             CODE,
             NoMisusedNewMessage::NewMethod,
             NoMisusedNewHint::RenameMethod,
diff --git a/src/rules/no_namespace.rs b/src/rules/no_namespace.rs
index c864876..ca9b078 100644
--- a/src/rules/no_namespace.rs
+++ b/src/rules/no_namespace.rs
@@ -2,9 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
-use deno_ast::view as ast_view;
 use deno_ast::view::NodeTrait;
+use deno_ast::{view as ast_view, SourceRanged};
 use std::sync::Arc;
 
 #[derive(Debug)]
@@ -71,7 +70,7 @@ impl Handler for NoNamespaceHandler {
     }
 
     if !inside_ambient_context(module_decl.as_node()) {
-      ctx.add_diagnostic_with_hint(module_decl.span(), CODE, MESSAGE, HINT);
+      ctx.add_diagnostic_with_hint(module_decl.range(), CODE, MESSAGE, HINT);
     }
   }
 }
diff --git a/src/rules/no_new_symbol.rs b/src/rules/no_new_symbol.rs
index c8f9636..cafdcd5 100644
--- a/src/rules/no_new_symbol.rs
+++ b/src/rules/no_new_symbol.rs
@@ -2,8 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{Expr, NewExpr};
+use deno_ast::SourceRanged;
 use if_chain::if_chain;
 use std::sync::Arc;
 
@@ -53,7 +53,7 @@ impl Handler for NoNewSymbolHandler {
       if *ident.sym() == *"Symbol";
       if ctx.scope().var(&ident.to_id()).is_none();
       then {
-        ctx.add_diagnostic(new_expr.span(), CODE, MESSAGE);
+        ctx.add_diagnostic(new_expr.range(), CODE, MESSAGE);
       }
     }
   }
diff --git a/src/rules/no_non_null_asserted_optional_chain.rs b/src/rules/no_non_null_asserted_optional_chain.rs
index 857d179..8b3b684 100644
--- a/src/rules/no_non_null_asserted_optional_chain.rs
+++ b/src/rules/no_non_null_asserted_optional_chain.rs
@@ -2,13 +2,11 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{Callee, Expr, TsNonNullExpr};
+use deno_ast::{SourceRange, SourceRanged};
 use derive_more::Display;
 use std::sync::Arc;
 
-use deno_ast::swc::common::Span;
-
 #[derive(Debug)]
 pub struct NoNonNullAssertedOptionalChain;
 
@@ -52,13 +50,13 @@ impl LintRule for NoNonNullAssertedOptionalChain {
 struct NoNonNullAssertedOptionalChainHandler;
 
 fn check_expr_for_nested_optional_assert(
-  span: Span,
+  range: SourceRange,
   expr: &Expr,
   ctx: &mut Context,
 ) {
   if let Expr::OptChain(_) = expr {
     ctx.add_diagnostic(
-      span,
+      range,
       CODE,
       NoNonNullAssertedOptionalChainMessage::WrongAssertion,
     );
@@ -74,7 +72,7 @@ impl Handler for NoNonNullAssertedOptionalChainHandler {
     match ts_non_null_expr.expr {
       Expr::Member(member_expr) => {
         check_expr_for_nested_optional_assert(
-          ts_non_null_expr.span(),
+          ts_non_null_expr.range(),
           &member_expr.obj,
           ctx,
         );
@@ -82,14 +80,14 @@ impl Handler for NoNonNullAssertedOptionalChainHandler {
       Expr::Call(call_expr) => {
         if let Callee::Expr(expr) = &call_expr.callee {
           check_expr_for_nested_optional_assert(
-            ts_non_null_expr.span(),
+            ts_non_null_expr.range(),
             expr,
             ctx,
           );
         }
       }
       Expr::Paren(paren_expr) => check_expr_for_nested_optional_assert(
-        ts_non_null_expr.span(),
+        ts_non_null_expr.range(),
         &paren_expr.expr,
         ctx,
       ),
@@ -97,7 +95,7 @@ impl Handler for NoNonNullAssertedOptionalChainHandler {
     };
 
     check_expr_for_nested_optional_assert(
-      ts_non_null_expr.span(),
+      ts_non_null_expr.range(),
       &ts_non_null_expr.expr,
       ctx,
     );
diff --git a/src/rules/no_non_null_assertion.rs b/src/rules/no_non_null_assertion.rs
index 955a19d..6f060a5 100644
--- a/src/rules/no_non_null_assertion.rs
+++ b/src/rules/no_non_null_assertion.rs
@@ -2,8 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::TsNonNullExpr;
+use deno_ast::SourceRanged;
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -55,7 +55,7 @@ impl Handler for NoNonNullAssertionHandler {
   ) {
     if !non_null_expr.parent().is::<TsNonNullExpr>() {
       ctx.add_diagnostic(
-        non_null_expr.span(),
+        non_null_expr.range(),
         CODE,
         NoNonNullAssertionMessage::Unexpected,
       );
diff --git a/src/rules/no_obj_calls.rs b/src/rules/no_obj_calls.rs
index 4d57625..681846d 100644
--- a/src/rules/no_obj_calls.rs
+++ b/src/rules/no_obj_calls.rs
@@ -2,9 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Span;
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{CallExpr, Callee, Expr, Ident, NewExpr};
+use deno_ast::{SourceRange, SourceRanged};
 use std::sync::Arc;
 
 #[derive(Debug)]
@@ -49,14 +48,14 @@ impl LintRule for NoObjCalls {
 
 struct NoObjCallsHandler;
 
-fn check_callee(callee: &Ident, span: Span, ctx: &mut Context) {
+fn check_callee(callee: &Ident, range: SourceRange, ctx: &mut Context) {
   if matches!(
     callee.sym().as_ref(),
     "Math" | "JSON" | "Reflect" | "Atomics"
   ) && ctx.scope().var(&callee.to_id()).is_none()
   {
     ctx.add_diagnostic(
-      span,
+      range,
       "no-obj-calls",
       get_message(callee.sym().as_ref()),
     );
@@ -66,13 +65,13 @@ fn check_callee(callee: &Ident, span: Span, ctx: &mut Context) {
 impl Handler for NoObjCallsHandler {
   fn call_expr(&mut self, call_expr: &CallExpr, ctx: &mut Context) {
     if let Callee::Expr(Expr::Ident(ident)) = call_expr.callee {
-      check_callee(ident, call_expr.span(), ctx);
+      check_callee(ident, call_expr.range(), ctx);
     }
   }
 
   fn new_expr(&mut self, new_expr: &NewExpr, ctx: &mut Context) {
     if let Expr::Ident(ident) = new_expr.callee {
-      check_callee(ident, new_expr.span(), ctx);
+      check_callee(ident, new_expr.range(), ctx);
     }
   }
 }
diff --git a/src/rules/no_octal.rs b/src/rules/no_octal.rs
index b4dc6e8..c450934 100644
--- a/src/rules/no_octal.rs
+++ b/src/rules/no_octal.rs
@@ -2,8 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::Number;
+use deno_ast::SourceRanged;
 use once_cell::sync::Lazy;
 use regex::Regex;
 use std::sync::Arc;
@@ -52,10 +52,10 @@ impl Handler for NoOctalHandler {
   fn number(&mut self, literal_num: &Number, ctx: &mut Context) {
     static OCTAL: Lazy<Regex> = Lazy::new(|| Regex::new(r"^0[0-9]").unwrap());
 
-    let raw_number = ctx.file_text_substring(&literal_num.span());
+    let raw_number = literal_num.text_fast(&ctx.text_info());
 
     if OCTAL.is_match(raw_number) {
-      ctx.add_diagnostic_with_hint(literal_num.span(), CODE, MESSAGE, HINT);
+      ctx.add_diagnostic_with_hint(literal_num.range(), CODE, MESSAGE, HINT);
     }
   }
 }
diff --git a/src/rules/no_prototype_builtins.rs b/src/rules/no_prototype_builtins.rs
index 3075390..665b303 100644
--- a/src/rules/no_prototype_builtins.rs
+++ b/src/rules/no_prototype_builtins.rs
@@ -2,8 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{CallExpr, Callee, Expr, MemberProp};
+use deno_ast::SourceRanged;
 use std::sync::Arc;
 
 const BANNED_PROPERTIES: &[&str] =
@@ -67,7 +67,7 @@ impl Handler for NoPrototypeBuiltinsHandler {
     if let MemberProp::Ident(ident) = member_expr.prop {
       let prop_name = ident.sym().as_ref();
       if BANNED_PROPERTIES.contains(&prop_name) {
-        ctx.add_diagnostic(call_expr.span(), CODE, get_message(prop_name));
+        ctx.add_diagnostic(call_expr.range(), CODE, get_message(prop_name));
       }
     }
   }
diff --git a/src/rules/no_redeclare.rs b/src/rules/no_redeclare.rs
index b9d7817..945ffc9 100644
--- a/src/rules/no_redeclare.rs
+++ b/src/rules/no_redeclare.rs
@@ -1,11 +1,12 @@
 // Copyright 2020-2021 the Deno authors. All rights reserved. MIT license.
 use super::{Context, LintRule};
 use crate::ProgramRef;
+use deno_ast::swc::ast::Id;
 use deno_ast::swc::visit::noop_visit_type;
 use deno_ast::swc::{
-  ast::*, utils::find_ids, utils::ident::IdentLike, utils::Id, visit::Visit,
-  visit::VisitWith,
+  ast::*, utils::find_pat_ids, visit::Visit, visit::VisitWith,
 };
+use deno_ast::SourceRangedForSpanned;
 use std::sync::Arc;
 
 use std::collections::HashSet;
@@ -52,7 +53,7 @@ impl LintRule for NoRedeclare {
 
 struct NoRedeclareVisitor<'c, 'view> {
   context: &'c mut Context<'view>,
-  /// TODO(kdy1): Change this to HashMap<Id, Vec<Span>> and use those spans to point previous bindings/
+  /// TODO(kdy1): Change this to HashMap<Id, Vec<SourceRange>> and use those ranges to point previous bindings/
   bindings: HashSet<Id>,
 }
 
@@ -61,7 +62,7 @@ impl<'c, 'view> NoRedeclareVisitor<'c, 'view> {
     let id = i.to_id();
 
     if !self.bindings.insert(id) {
-      self.context.add_diagnostic(i.span, CODE, MESSAGE);
+      self.context.add_diagnostic(i.range(), CODE, MESSAGE);
     }
   }
 }
@@ -80,7 +81,7 @@ impl<'c, 'view> Visit for NoRedeclareVisitor<'c, 'view> {
   }
 
   fn visit_var_declarator(&mut self, v: &VarDeclarator) {
-    let ids: Vec<Ident> = find_ids(&v.name);
+    let ids: Vec<Ident> = find_pat_ids(&v.name);
 
     for id in ids {
       self.declare(&id);
@@ -88,7 +89,7 @@ impl<'c, 'view> Visit for NoRedeclareVisitor<'c, 'view> {
   }
 
   fn visit_param(&mut self, p: &Param) {
-    let ids: Vec<Ident> = find_ids(&p.pat);
+    let ids: Vec<Ident> = find_pat_ids(&p.pat);
 
     for id in ids {
       self.declare(&id);
diff --git a/src/rules/no_regex_spaces.rs b/src/rules/no_regex_spaces.rs
index 840ce64..3d08ff5 100644
--- a/src/rules/no_regex_spaces.rs
+++ b/src/rules/no_regex_spaces.rs
@@ -3,9 +3,8 @@ use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::swc_util::extract_regex;
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Span;
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{CallExpr, Callee, Expr, NewExpr, Regex};
+use deno_ast::{SourceRange, SourceRanged};
 use once_cell::sync::Lazy;
 use std::sync::Arc;
 
@@ -49,7 +48,7 @@ impl LintRule for NoRegexSpaces {
 
 struct NoRegexSpacesHandler;
 
-fn check_regex(regex: &str, span: Span, ctx: &mut Context) {
+fn check_regex(regex: &str, range: SourceRange, ctx: &mut Context) {
   static DOUBLE_SPACE: Lazy<regex::Regex> =
     Lazy::new(|| regex::Regex::new(r"(?u) {2}").unwrap());
   static BRACKETS: Lazy<regex::Regex> =
@@ -72,7 +71,7 @@ fn check_regex(regex: &str, span: Span, ctx: &mut Context) {
       .iter()
       .all(|v| mtch.start() < v.0 || v.1 <= mtch.start());
     if *not_in_classes {
-      ctx.add_diagnostic(span, CODE, MESSAGE);
+      ctx.add_diagnostic(range, CODE, MESSAGE);
       return;
     }
   }
@@ -80,14 +79,14 @@ fn check_regex(regex: &str, span: Span, ctx: &mut Context) {
 
 impl Handler for NoRegexSpacesHandler {
   fn regex(&mut self, regex: &Regex, ctx: &mut Context) {
-    check_regex(regex.inner.exp.to_string().as_str(), regex.span(), ctx);
+    check_regex(regex.inner.exp.to_string().as_str(), regex.range(), ctx);
   }
 
   fn new_expr(&mut self, new_expr: &NewExpr, ctx: &mut Context) {
     if let Expr::Ident(ident) = new_expr.callee {
       if let Some(args) = &new_expr.args {
         if let Some(regex) = extract_regex(ctx.scope(), ident, args) {
-          check_regex(regex.as_str(), new_expr.span(), ctx);
+          check_regex(regex.as_str(), new_expr.range(), ctx);
         }
       }
     }
@@ -96,7 +95,7 @@ impl Handler for NoRegexSpacesHandler {
   fn call_expr(&mut self, call_expr: &CallExpr, ctx: &mut Context) {
     if let Callee::Expr(Expr::Ident(ident)) = &call_expr.callee {
       if let Some(regex) = extract_regex(ctx.scope(), ident, &call_expr.args) {
-        check_regex(regex.as_str(), call_expr.span(), ctx);
+        check_regex(regex.as_str(), call_expr.range(), ctx);
       }
     }
   }
diff --git a/src/rules/no_self_assign.rs b/src/rules/no_self_assign.rs
index 6319e88..f962500 100644
--- a/src/rules/no_self_assign.rs
+++ b/src/rules/no_self_assign.rs
@@ -16,9 +16,10 @@ use deno_ast::swc::ast::Pat;
 use deno_ast::swc::ast::PatOrExpr;
 use deno_ast::swc::ast::Prop;
 use deno_ast::swc::ast::PropOrSpread;
-use deno_ast::swc::common::Span;
 use deno_ast::swc::visit::noop_visit_type;
 use deno_ast::swc::visit::{VisitAll, VisitAllWith};
+use deno_ast::SourceRange;
+use deno_ast::SourceRangedForSpanned;
 use derive_more::Display;
 
 #[derive(Debug)]
@@ -80,9 +81,9 @@ impl<'c, 'view> NoSelfAssignVisitor<'c, 'view> {
     Self { context }
   }
 
-  fn add_diagnostic(&mut self, span: Span, name: impl ToString) {
+  fn add_diagnostic(&mut self, range: SourceRange, name: impl ToString) {
     self.context.add_diagnostic_with_hint(
-      span,
+      range,
       CODE,
       NoSelfAssignMessage::Invalid(name.to_string()),
       NoSelfAssignHint::Mistake,
@@ -160,7 +161,7 @@ impl<'c, 'view> NoSelfAssignVisitor<'c, 'view> {
         MemberProp::PrivateName(name) => name.string_repr(),
       }
       .expect("Should be identifier");
-      self.add_diagnostic(right.span, name);
+      self.add_diagnostic(right.range(), name);
     }
   }
 
@@ -170,7 +171,7 @@ impl<'c, 'view> NoSelfAssignVisitor<'c, 'view> {
 
   fn check_same_ident(&mut self, left: &Ident, right: &Ident) {
     if self.are_same_ident(left, right) {
-      self.add_diagnostic(right.span, &right.sym);
+      self.add_diagnostic(right.range(), &right.sym);
     }
   }
 
diff --git a/src/rules/no_setter_return.rs b/src/rules/no_setter_return.rs
index 6f93d1b..47cf955 100644
--- a/src/rules/no_setter_return.rs
+++ b/src/rules/no_setter_return.rs
@@ -2,9 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
-use deno_ast::view as ast_view;
 use deno_ast::view::NodeTrait;
+use deno_ast::{view as ast_view, SourceRanged};
 use std::sync::Arc;
 
 #[derive(Debug)]
@@ -76,7 +75,7 @@ impl Handler for NoSetterReturnHandler {
     }
 
     if inside_setter(return_stmt.as_node()) {
-      ctx.add_diagnostic(return_stmt.span(), CODE, MESSAGE);
+      ctx.add_diagnostic(return_stmt.range(), CODE, MESSAGE);
     }
   }
 }
diff --git a/src/rules/no_shadow_restricted_names.rs b/src/rules/no_shadow_restricted_names.rs
index 2c4a976..3355e00 100644
--- a/src/rules/no_shadow_restricted_names.rs
+++ b/src/rules/no_shadow_restricted_names.rs
@@ -2,11 +2,11 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{
   ArrowExpr, AssignExpr, CatchClause, Expr, FnDecl, FnExpr, Ident,
   ObjectPatProp, Pat, PatOrExpr, VarDecl,
 };
+use deno_ast::SourceRanged;
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -104,7 +104,7 @@ fn check_shadowing(ident: &Ident, ctx: &mut Context) {
 
 fn report_shadowing(ident: &Ident, ctx: &mut Context) {
   ctx.add_diagnostic(
-    ident.span(),
+    ident.range(),
     CODE,
     NoShadowRestrictedNamesMessage::Shadowing(ident.sym().to_string()),
   );
diff --git a/src/rules/no_sparse_arrays.rs b/src/rules/no_sparse_arrays.rs
index 9a526a8..b5219e1 100644
--- a/src/rules/no_sparse_arrays.rs
+++ b/src/rules/no_sparse_arrays.rs
@@ -2,8 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::ArrayLit;
+use deno_ast::SourceRanged;
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -51,7 +51,7 @@ impl Handler for NoSparseArraysHandler {
   fn array_lit(&mut self, array_lit: &ArrayLit, ctx: &mut Context) {
     if array_lit.elems.iter().any(|e| e.is_none()) {
       ctx.add_diagnostic(
-        array_lit.span(),
+        array_lit.range(),
         CODE,
         NoSparseArraysMessage::Disallowed,
       );
diff --git a/src/rules/no_this_alias.rs b/src/rules/no_this_alias.rs
index 8205055..3b9c22d 100644
--- a/src/rules/no_this_alias.rs
+++ b/src/rules/no_this_alias.rs
@@ -2,8 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{Expr, Pat, VarDecl};
+use deno_ast::SourceRanged;
 use if_chain::if_chain;
 use std::sync::Arc;
 
@@ -54,7 +54,7 @@ impl Handler for NoThisAliasHandler {
         if matches!(&init, Expr::This(_));
         if matches!(&decl.name, Pat::Ident(_));
         then {
-          ctx.add_diagnostic(var_decl.span(), CODE, MESSAGE);
+          ctx.add_diagnostic(var_decl.range(), CODE, MESSAGE);
         }
       }
     }
diff --git a/src/rules/no_this_before_super.rs b/src/rules/no_this_before_super.rs
index f3b4e9f..76274b3 100644
--- a/src/rules/no_this_before_super.rs
+++ b/src/rules/no_this_before_super.rs
@@ -2,10 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Span;
-use deno_ast::swc::common::Spanned;
-use deno_ast::view as ast_view;
 use deno_ast::view::NodeTrait;
+use deno_ast::{view as ast_view, SourceRange, SourceRanged};
 use std::sync::Arc;
 
 #[derive(Debug)]
@@ -101,14 +99,14 @@ impl Handler for NoThisBeforeSuperHandler {
 
     if let Some(body) = cons.body {
       for stmt in &body.stmts {
-        let mut checker = SuperCallChecker::new(stmt.span());
+        let mut checker = SuperCallChecker::new(stmt.range());
         checker.traverse(*stmt, ctx);
         match checker.result() {
           None => (),
           Some(FirstAppeared::SuperCalled) => break,
-          Some(FirstAppeared::ThisAccessed(span))
-          | Some(FirstAppeared::SuperAccessed(span)) => {
-            ctx.add_diagnostic_with_hint(span, CODE, MESSAGE, HINT);
+          Some(FirstAppeared::ThisAccessed(range))
+          | Some(FirstAppeared::SuperAccessed(range)) => {
+            ctx.add_diagnostic_with_hint(range, CODE, MESSAGE, HINT);
           }
         }
       }
@@ -118,20 +116,20 @@ impl Handler for NoThisBeforeSuperHandler {
 
 enum FirstAppeared {
   SuperCalled,
-  SuperAccessed(Span),
-  ThisAccessed(Span),
+  SuperAccessed(SourceRange),
+  ThisAccessed(SourceRange),
 }
 
 struct SuperCallChecker {
   first_appeared: Option<FirstAppeared>,
-  root_span: Span,
+  root_range: SourceRange,
 }
 
 impl SuperCallChecker {
-  fn new(root_span: Span) -> Self {
+  fn new(root_range: SourceRange) -> Self {
     Self {
       first_appeared: None,
-      root_span,
+      root_range,
     }
   }
 
@@ -144,9 +142,12 @@ impl SuperCallChecker {
   }
 
   fn node_is_inside_function(&self, node: ast_view::Node) -> bool {
-    fn inside_function(root_span: Span, cur_node: ast_view::Node) -> bool {
+    fn inside_function(
+      root_range: SourceRange,
+      cur_node: ast_view::Node,
+    ) -> bool {
       // Stop recursion if the current node gets out of root_node.
-      if !root_span.contains(cur_node.span()) {
+      if !root_range.contains(&cur_node.range()) {
         return false;
       }
 
@@ -157,10 +158,10 @@ impl SuperCallChecker {
         return true;
       }
 
-      inside_function(root_span, cur_node.parent().unwrap())
+      inside_function(root_range, cur_node.parent().unwrap())
     }
 
-    inside_function(self.root_span, node)
+    inside_function(self.root_range, node)
   }
 }
 
@@ -171,7 +172,8 @@ impl Handler for SuperCallChecker {
     }
 
     if self.yet_appeared() {
-      self.first_appeared = Some(FirstAppeared::ThisAccessed(this_expr.span()));
+      self.first_appeared =
+        Some(FirstAppeared::ThisAccessed(this_expr.range()));
     }
   }
 
@@ -181,7 +183,7 @@ impl Handler for SuperCallChecker {
     }
 
     if self.yet_appeared() {
-      self.first_appeared = Some(FirstAppeared::SuperAccessed(super_.span()));
+      self.first_appeared = Some(FirstAppeared::SuperAccessed(super_.range()));
     }
   }
 
diff --git a/src/rules/no_throw_literal.rs b/src/rules/no_throw_literal.rs
index dcd9d37..0d5f815 100644
--- a/src/rules/no_throw_literal.rs
+++ b/src/rules/no_throw_literal.rs
@@ -2,8 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{Expr, ThrowStmt};
+use deno_ast::SourceRanged;
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -54,12 +54,12 @@ impl Handler for NoThrowLiteralHandler {
   fn throw_stmt(&mut self, throw_stmt: &ThrowStmt, ctx: &mut Context) {
     match throw_stmt.arg {
       Expr::Lit(_) => ctx.add_diagnostic(
-        throw_stmt.span(),
+        throw_stmt.range(),
         CODE,
         NoThrowLiteralMessage::ErrObjectExpected,
       ),
       Expr::Ident(ident) if *ident.sym() == *"undefined" => ctx.add_diagnostic(
-        throw_stmt.span(),
+        throw_stmt.range(),
         CODE,
         NoThrowLiteralMessage::Undefined,
       ),
diff --git a/src/rules/no_top_level_await.rs b/src/rules/no_top_level_await.rs
index 08a9b22..6926fb0 100644
--- a/src/rules/no_top_level_await.rs
+++ b/src/rules/no_top_level_await.rs
@@ -2,9 +2,9 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::NodeTrait;
 use deno_ast::view::{self as ast_view};
+use deno_ast::SourceRanged;
 use if_chain::if_chain;
 use std::sync::Arc;
 
@@ -50,7 +50,7 @@ impl Handler for NoTopLevelAwaitHandler {
     ctx: &mut Context,
   ) {
     if !is_node_inside_function(await_expr) {
-      ctx.add_diagnostic(await_expr.span(), CODE, MESSAGE);
+      ctx.add_diagnostic(await_expr.range(), CODE, MESSAGE);
     }
   }
 
@@ -63,7 +63,7 @@ impl Handler for NoTopLevelAwaitHandler {
       if for_of_stmt.await_token().is_some();
       if !is_node_inside_function(for_of_stmt);
       then {
-        ctx.add_diagnostic(for_of_stmt.span(), CODE, MESSAGE)
+        ctx.add_diagnostic(for_of_stmt.range(), CODE, MESSAGE)
       }
     }
   }
diff --git a/src/rules/no_undef.rs b/src/rules/no_undef.rs
index ee4962b..1a81e4b 100644
--- a/src/rules/no_undef.rs
+++ b/src/rules/no_undef.rs
@@ -4,9 +4,9 @@ use crate::globals::GLOBALS;
 use crate::ProgramRef;
 use deno_ast::swc::{
   ast::*,
-  utils::ident::IdentLike,
   visit::{noop_visit_type, Visit, VisitWith},
 };
+use deno_ast::SourceRangedForSpanned;
 use std::sync::Arc;
 
 #[derive(Debug)]
@@ -53,7 +53,7 @@ impl<'c, 'view> NoUndefVisitor<'c, 'view> {
     //
     // function foo(Map) { ... }
     //
-    if ident.span.ctxt != self.context.top_level_ctxt() {
+    if ident.span.ctxt != self.context.unresolved_ctxt() {
       return;
     }
 
@@ -73,7 +73,7 @@ impl<'c, 'view> NoUndefVisitor<'c, 'view> {
     }
 
     self.context.add_diagnostic(
-      ident.span,
+      ident.range(),
       "no-undef",
       format!("{} is not defined", ident.sym),
     )
diff --git a/src/rules/no_unreachable.rs b/src/rules/no_unreachable.rs
index cc21a36..0b04792 100644
--- a/src/rules/no_unreachable.rs
+++ b/src/rules/no_unreachable.rs
@@ -2,9 +2,9 @@
 use super::{Context, LintRule};
 use crate::ProgramRef;
 use deno_ast::swc::ast::{Decl, Stmt, VarDecl, VarDeclKind};
-use deno_ast::swc::common::Spanned;
 use deno_ast::swc::visit::Visit;
 use deno_ast::swc::visit::VisitWith;
+use deno_ast::SourceRangedForSpanned;
 use std::sync::Arc;
 
 #[derive(Debug)]
@@ -79,9 +79,9 @@ impl<'c, 'view> Visit for NoUnreachableVisitor<'c, 'view> {
       _ => {}
     }
 
-    if let Some(meta) = self.context.control_flow().meta(stmt.span().lo) {
+    if let Some(meta) = self.context.control_flow().meta(stmt.start()) {
       if meta.unreachable {
-        self.context.add_diagnostic(stmt.span(), CODE, MESSAGE)
+        self.context.add_diagnostic(stmt.range(), CODE, MESSAGE)
       }
     }
   }
diff --git a/src/rules/no_unsafe_finally.rs b/src/rules/no_unsafe_finally.rs
index b37576c..078c6ef 100644
--- a/src/rules/no_unsafe_finally.rs
+++ b/src/rules/no_unsafe_finally.rs
@@ -2,9 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::{Span, Spanned};
-use deno_ast::view as ast_view;
 use deno_ast::view::NodeTrait;
+use deno_ast::{view as ast_view, SourceRange, SourceRanged};
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -78,8 +77,8 @@ impl Handler for NoUnsafeFinallyHandler {
     ctx: &mut Context,
   ) {
     let kind = StmtKind::Break(break_stmt.label);
-    if stmt_inside_finally(break_stmt.span(), kind, break_stmt.as_node()) {
-      add_diagnostic_with_hint(ctx, break_stmt.span(), kind);
+    if stmt_inside_finally(break_stmt.range(), kind, break_stmt.as_node()) {
+      add_diagnostic_with_hint(ctx, break_stmt.range(), kind);
     }
   }
 
@@ -89,9 +88,9 @@ impl Handler for NoUnsafeFinallyHandler {
     ctx: &mut Context,
   ) {
     let kind = StmtKind::Continue(continue_stmt.label);
-    if stmt_inside_finally(continue_stmt.span(), kind, continue_stmt.as_node())
+    if stmt_inside_finally(continue_stmt.range(), kind, continue_stmt.as_node())
     {
-      add_diagnostic_with_hint(ctx, continue_stmt.span(), kind);
+      add_diagnostic_with_hint(ctx, continue_stmt.range(), kind);
     }
   }
 
@@ -101,8 +100,8 @@ impl Handler for NoUnsafeFinallyHandler {
     ctx: &mut Context,
   ) {
     let kind = StmtKind::Return;
-    if stmt_inside_finally(return_stmt.span(), kind, return_stmt.as_node()) {
-      add_diagnostic_with_hint(ctx, return_stmt.span(), kind);
+    if stmt_inside_finally(return_stmt.range(), kind, return_stmt.as_node()) {
+      add_diagnostic_with_hint(ctx, return_stmt.range(), kind);
     }
   }
 
@@ -112,8 +111,8 @@ impl Handler for NoUnsafeFinallyHandler {
     ctx: &mut Context,
   ) {
     let kind = StmtKind::Throw;
-    if stmt_inside_finally(throw_stmt.span(), kind, throw_stmt.as_node()) {
-      add_diagnostic_with_hint(ctx, throw_stmt.span(), kind);
+    if stmt_inside_finally(throw_stmt.range(), kind, throw_stmt.as_node()) {
+      add_diagnostic_with_hint(ctx, throw_stmt.range(), kind);
     }
   }
 }
@@ -144,9 +143,9 @@ impl<'a> StmtKind<'a> {
   }
 }
 
-/// Checks if the given span is contained in a `finally` block
+/// Checks if the given range is contained in a `finally` block
 fn stmt_inside_finally(
-  stmt_span: Span,
+  stmt_range: SourceRange,
   stmt_kind: StmtKind,
   cur_node: ast_view::Node,
 ) -> bool {
@@ -174,10 +173,10 @@ fn stmt_inside_finally(
         ..
       }),
       _,
-    ) if f.span().contains(stmt_span) => true,
+    ) if f.range().contains(&stmt_range) => true,
     _ => {
       if let Some(parent) = cur_node.parent() {
-        stmt_inside_finally(stmt_span, stmt_kind, parent)
+        stmt_inside_finally(stmt_range, stmt_kind, parent)
       } else {
         false
       }
@@ -187,11 +186,11 @@ fn stmt_inside_finally(
 
 fn add_diagnostic_with_hint(
   ctx: &mut Context,
-  span: Span,
+  range: SourceRange,
   stmt_kind: StmtKind,
 ) {
   ctx.add_diagnostic_with_hint(
-    span,
+    range,
     CODE,
     NoUnsafeFinallyMessage::from(stmt_kind),
     HINT,
diff --git a/src/rules/no_unsafe_negation.rs b/src/rules/no_unsafe_negation.rs
index ef44f75..7b2eba0 100644
--- a/src/rules/no_unsafe_negation.rs
+++ b/src/rules/no_unsafe_negation.rs
@@ -2,8 +2,7 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
-use deno_ast::view as ast_view;
+use deno_ast::{view as ast_view, SourceRanged};
 use derive_more::Display;
 use if_chain::if_chain;
 use std::sync::Arc;
@@ -63,7 +62,7 @@ impl Handler for NoUnsafeNegationHandler {
       if unary_expr.op() == UnaryOp::Bang;
       then {
         ctx.add_diagnostic_with_hint(
-          bin_expr.span(),
+          bin_expr.range(),
           CODE,
           NoUnsafeNegationMessage::Unexpected(bin_expr.op().to_string()),
           HINT,
diff --git a/src/rules/no_unused_labels.rs b/src/rules/no_unused_labels.rs
index 739de70..3570e40 100644
--- a/src/rules/no_unused_labels.rs
+++ b/src/rules/no_unused_labels.rs
@@ -2,8 +2,7 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
-use deno_ast::view as ast_view;
+use deno_ast::{view as ast_view, SourceRanged};
 use derive_more::Display;
 use if_chain::if_chain;
 use std::sync::Arc;
@@ -110,7 +109,7 @@ impl Handler for NoUnusedLabelsHandler {
       if !label.used;
       then {
         ctx.add_diagnostic(
-          labeled_stmt.span(),
+          labeled_stmt.range(),
           CODE,
           NoUnusedLabelsMessage::Unused(label.name),
         );
diff --git a/src/rules/no_unused_vars.rs b/src/rules/no_unused_vars.rs
index d4c27c3..11253c5 100644
--- a/src/rules/no_unused_vars.rs
+++ b/src/rules/no_unused_vars.rs
@@ -1,6 +1,7 @@
 // Copyright 2020-2021 the Deno authors. All rights reserved. MIT license.
 use super::{Context, LintRule};
 use crate::ProgramRef;
+use deno_ast::swc::ast::Id;
 use deno_ast::swc::ast::{
   ArrowExpr, AssignPatProp, CallExpr, CatchClause, ClassDecl, ClassMethod,
   ClassProp, Constructor, Decl, DefaultDecl, ExportDecl, ExportDefaultDecl,
@@ -13,9 +14,9 @@ use deno_ast::swc::ast::{
   VarDeclarator,
 };
 use deno_ast::swc::atoms::js_word;
-use deno_ast::swc::utils::ident::IdentLike;
-use deno_ast::swc::utils::{find_ids, Id};
+use deno_ast::swc::utils::find_pat_ids;
 use deno_ast::swc::visit::{Visit, VisitWith};
+use deno_ast::SourceRangedForSpanned;
 use derive_more::Display;
 use if_chain::if_chain;
 use std::collections::HashSet;
@@ -373,7 +374,7 @@ impl Visit for Collector {
   }
 
   fn visit_var_declarator(&mut self, declarator: &VarDeclarator) {
-    let declaring_ids: Vec<Id> = find_ids(&declarator.name);
+    let declaring_ids: Vec<Id> = find_pat_ids(&declarator.name);
     self.with_cur_defining(declaring_ids, |a| {
       declarator.name.visit_with(a);
       declarator.init.visit_with(a);
@@ -452,7 +453,7 @@ impl<'c, 'view> NoUnusedVarVisitor<'c, 'view> {
     if !self.used_vars.contains(&inner.to_id()) {
       // The variable is not used.
       self.context.add_diagnostic_with_hint(
-        inner.span,
+        inner.range(),
         CODE,
         ident.to_message(),
         ident.to_hint(),
@@ -463,7 +464,7 @@ impl<'c, 'view> NoUnusedVarVisitor<'c, 'view> {
 
 impl<'c, 'view> Visit for NoUnusedVarVisitor<'c, 'view> {
   fn visit_arrow_expr(&mut self, expr: &ArrowExpr) {
-    let declared_idents: Vec<Ident> = find_ids(&expr.params);
+    let declared_idents: Vec<Ident> = find_pat_ids(&expr.params);
 
     for ident in declared_idents {
       self.handle_id(IdentKind::Other(&ident));
@@ -493,7 +494,7 @@ impl<'c, 'view> Visit for NoUnusedVarVisitor<'c, 'view> {
   }
 
   fn visit_var_declarator(&mut self, declarator: &VarDeclarator) {
-    let declared_idents: Vec<Ident> = find_ids(&declarator.name);
+    let declared_idents: Vec<Ident> = find_pat_ids(&declarator.name);
 
     for ident in declared_idents {
       self.handle_id(IdentKind::Other(&ident));
@@ -512,7 +513,7 @@ impl<'c, 'view> Visit for NoUnusedVarVisitor<'c, 'view> {
   }
 
   fn visit_catch_clause(&mut self, clause: &CatchClause) {
-    let declared_idents: Vec<Ident> = find_ids(&clause.param);
+    let declared_idents: Vec<Ident> = find_pat_ids(&clause.param);
 
     for ident in declared_idents {
       self.handle_id(IdentKind::Other(&ident));
@@ -561,7 +562,7 @@ impl<'c, 'view> Visit for NoUnusedVarVisitor<'c, 'view> {
   }
 
   fn visit_param(&mut self, param: &Param) {
-    let declared_idents: Vec<Ident> = find_ids(&param.pat);
+    let declared_idents: Vec<Ident> = find_pat_ids(&param.pat);
 
     for ident in declared_idents {
       self.handle_id(IdentKind::Other(&ident));
diff --git a/src/rules/no_var.rs b/src/rules/no_var.rs
index 2ebb194..77049d3 100644
--- a/src/rules/no_var.rs
+++ b/src/rules/no_var.rs
@@ -2,8 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{VarDecl, VarDeclKind};
+use deno_ast::SourceRanged;
 use std::sync::Arc;
 #[derive(Debug)]
 pub struct NoVar;
@@ -47,7 +47,7 @@ struct NoVarHandler;
 impl Handler for NoVarHandler {
   fn var_decl(&mut self, var_decl: &VarDecl, ctx: &mut Context) {
     if var_decl.decl_kind() == VarDeclKind::Var {
-      ctx.add_diagnostic(var_decl.span(), CODE, MESSAGE);
+      ctx.add_diagnostic(var_decl.range(), CODE, MESSAGE);
     }
   }
 }
diff --git a/src/rules/no_window_prefix.rs b/src/rules/no_window_prefix.rs
index 0107f3e..2f21842 100644
--- a/src/rules/no_window_prefix.rs
+++ b/src/rules/no_window_prefix.rs
@@ -3,9 +3,7 @@ use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
 use deno_ast::swc::atoms::JsWord;
-use deno_ast::swc::common::Spanned;
-use deno_ast::swc::utils::ident::IdentLike;
-use deno_ast::view as ast_view;
+use deno_ast::{view as ast_view, SourceRanged};
 use if_chain::if_chain;
 use once_cell::sync::Lazy;
 use std::collections::HashSet;
@@ -256,7 +254,7 @@ impl Handler for NoWindowPrefixHandler {
       if PROPERTY_DENY_LIST.contains(prop_symbol.as_ref());
       then {
         ctx.add_diagnostic_with_hint(
-          member_expr.span(),
+          member_expr.range(),
           CODE,
           MESSAGE,
           HINT,
diff --git a/src/rules/no_with.rs b/src/rules/no_with.rs
index 68a8f8d..d4628c3 100644
--- a/src/rules/no_with.rs
+++ b/src/rules/no_with.rs
@@ -2,8 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
 use deno_ast::view as ast_view;
+use deno_ast::SourceRanged;
 use std::sync::Arc;
 
 #[derive(Debug)]
@@ -47,7 +47,7 @@ struct NoWithHandler;
 
 impl Handler for NoWithHandler {
   fn with_stmt(&mut self, with_stmt: &ast_view::WithStmt, ctx: &mut Context) {
-    ctx.add_diagnostic(with_stmt.span(), CODE, MESSAGE);
+    ctx.add_diagnostic(with_stmt.range(), CODE, MESSAGE);
   }
 }
 
diff --git a/src/rules/prefer_as_const.rs b/src/rules/prefer_as_const.rs
index de690f7..5eb9a9c 100644
--- a/src/rules/prefer_as_const.rs
+++ b/src/rules/prefer_as_const.rs
@@ -2,11 +2,11 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::{Span, Spanned};
 use deno_ast::view::{
   ArrayPat, BindingIdent, Expr, Lit, ObjectPat, Pat, TsAsExpr, TsLit, TsType,
   TsTypeAnn, TsTypeAssertion, VarDecl,
 };
+use deno_ast::{SourceRange, SourceRanged};
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -62,28 +62,33 @@ impl LintRule for PreferAsConst {
 
 struct PreferAsConstHandler;
 
-fn add_diagnostic_helper(span: Span, ctx: &mut Context) {
+fn add_diagnostic_helper(range: SourceRange, ctx: &mut Context) {
   ctx.add_diagnostic_with_hint(
-    span,
+    range,
     CODE,
     PreferAsConstMessage::ExpectedConstAssertion,
     PreferAsConstHint::AddAsConst,
   );
 }
 
-fn compare(type_ann: &TsType, expr: &Expr, span: Span, ctx: &mut Context) {
+fn compare(
+  type_ann: &TsType,
+  expr: &Expr,
+  range: SourceRange,
+  ctx: &mut Context,
+) {
   if let TsType::TsLitType(lit_type) = &*type_ann {
     if let Expr::Lit(expr_lit) = &*expr {
       match (expr_lit, &lit_type.lit) {
         (Lit::Str(value_literal), TsLit::Str(type_literal)) => {
           if value_literal.value() == type_literal.value() {
-            add_diagnostic_helper(span, ctx)
+            add_diagnostic_helper(range, ctx)
           }
         }
         (Lit::Num(value_literal), TsLit::Number(type_literal)) => {
           if (value_literal.value() - type_literal.value()).abs() < f64::EPSILON
           {
-            add_diagnostic_helper(span, ctx)
+            add_diagnostic_helper(range, ctx)
           }
         }
         _ => {}
@@ -97,7 +102,7 @@ impl Handler for PreferAsConstHandler {
     compare(
       &as_expr.type_ann,
       &as_expr.expr,
-      as_expr.type_ann.span(),
+      as_expr.type_ann.range(),
       ctx,
     );
   }
@@ -110,7 +115,7 @@ impl Handler for PreferAsConstHandler {
     compare(
       &type_assertion.type_ann,
       &type_assertion.expr,
-      type_assertion.type_ann.span(),
+      type_assertion.type_ann.range(),
       ctx,
     );
   }
@@ -123,7 +128,7 @@ impl Handler for PreferAsConstHandler {
         | Pat::Ident(BindingIdent { type_ann, .. }) = &decl.name
         {
           if let Some(TsTypeAnn { type_ann, .. }) = &type_ann {
-            compare(type_ann, init, type_ann.span(), ctx);
+            compare(type_ann, init, type_ann.range(), ctx);
           }
         }
       }
diff --git a/src/rules/prefer_ascii.rs b/src/rules/prefer_ascii.rs
index f6ca9c1..701d323 100644
--- a/src/rules/prefer_ascii.rs
+++ b/src/rules/prefer_ascii.rs
@@ -1,7 +1,7 @@
 // Copyright 2020-2021 the Deno authors. All rights reserved. MIT license.
 use super::{Context, LintRule};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::{BytePos, Span};
+use deno_ast::SourceRange;
 use std::sync::Arc;
 
 #[derive(Debug)]
@@ -37,22 +37,20 @@ impl LintRule for PreferAscii {
   ) {
     let mut not_asciis = Vec::new();
 
-    let mut src_chars = context.source_file().text().char_indices().peekable();
+    let text_info = context.text_info();
+    let mut src_chars = text_info.text_str().char_indices().peekable();
+    let start_pos = text_info.range().start;
     while let Some((i, c)) = src_chars.next() {
       if let Some(&(pi, _)) = src_chars.peek() {
         if (pi > i + 1) || !c.is_ascii() {
-          let span = Span::new(
-            BytePos(i as u32),
-            BytePos(pi as u32),
-            Default::default(),
-          );
-          not_asciis.push((c, span));
+          let range = SourceRange::new(start_pos + i, start_pos + pi);
+          not_asciis.push((c, range));
         }
       }
     }
 
-    for (c, span) in not_asciis {
-      context.add_diagnostic_with_hint(span, CODE, MESSAGE, hint(c));
+    for (c, range) in not_asciis {
+      context.add_diagnostic_with_hint(range, CODE, MESSAGE, hint(c));
     }
   }
 
diff --git a/src/rules/prefer_const.rs b/src/rules/prefer_const.rs
index 9b3edaf..efd6d5d 100644
--- a/src/rules/prefer_const.rs
+++ b/src/rules/prefer_const.rs
@@ -9,10 +9,11 @@ use deno_ast::swc::ast::{
   VarDeclKind, VarDeclOrExpr, VarDeclOrPat, WhileStmt, WithStmt,
 };
 use deno_ast::swc::atoms::JsWord;
-use deno_ast::swc::common::{Span, Spanned};
-use deno_ast::swc::utils::find_ids;
+use deno_ast::swc::utils::find_pat_ids;
 use deno_ast::swc::visit::noop_visit_type;
 use deno_ast::swc::visit::{Visit, VisitWith};
+use deno_ast::SourceRangedForSpanned;
+use deno_ast::{SourceRange, SourceRanged};
 use derive_more::Display;
 use std::cell::RefCell;
 use std::collections::{BTreeMap, HashMap};
@@ -84,7 +85,7 @@ type Scope = Rc<RefCell<RawScope>>;
 #[derive(Debug)]
 struct RawScope {
   parent: Option<Scope>,
-  variables: BTreeMap<JsWord, Span>,
+  variables: BTreeMap<JsWord, SourceRange>,
 }
 
 impl RawScope {
@@ -98,22 +99,22 @@ impl RawScope {
 
 #[derive(Debug)]
 struct DeclInfo {
-  /// the span of its declaration
-  span: Span,
+  /// the range of its declaration
+  range: SourceRange,
   /// `true` if this is declared in the other scope
   in_other_scope: bool,
 }
 
-/// Looks for the declaration span of the given variable by traversing from the given scope to the parents.
-/// Returns `None` if no matching span is found. Most likely it means the variable is not declared
+/// Looks for the declaration range of the given variable by traversing from the given scope to the parents.
+/// Returns `None` if no matching range is found. Most likely it means the variable is not declared
 /// with `let`.
 fn get_decl_by_ident(scope: Scope, ident: &Ident) -> Option<DeclInfo> {
   let mut cur_scope = Some(scope);
   let mut is_current_scope = true;
   while let Some(cur) = cur_scope {
-    if let Some(&span) = cur.borrow().variables.get(&ident.sym) {
+    if let Some(&range) = cur.borrow().variables.get(&ident.sym) {
       return Some(DeclInfo {
-        span,
+        range,
         in_other_scope: !is_current_scope,
       });
     }
@@ -147,15 +148,15 @@ impl VarStatus {
 
 #[derive(Default, Debug)]
 struct DisjointSet {
-  /// Key: span of ident, Value: span of parent node
-  /// This map is supposed to contain all spans of variable declarations.
-  parents: BTreeMap<Span, Span>,
+  /// Key: range of ident, Value: range of parent node
+  /// This map is supposed to contain all ranges of variable declarations.
+  parents: BTreeMap<SourceRange, SourceRange>,
 
-  /// Key: span of ident (representative of the group)
+  /// Key: range of ident (representative of the group)
   /// Value: pair of the following values:
   ///        - status of variables in this tree
   ///        - the maximum height of this tree, which is used for optimization
-  roots: HashMap<Span, (VarStatus, usize)>,
+  roots: HashMap<SourceRange, (VarStatus, usize)>,
 }
 
 impl DisjointSet {
@@ -163,10 +164,10 @@ impl DisjointSet {
     Self::default()
   }
 
-  fn proceed_status(&mut self, span: Span, force_reassigned: bool) {
+  fn proceed_status(&mut self, range: SourceRange, force_reassigned: bool) {
     // This unwrap is safe if VariableCollector works fine.
     // If it panics, it means a bug in implementation.
-    let root = self.get_root(span).unwrap();
+    let root = self.get_root(range).unwrap();
     let (ref mut st, _) = self.roots.get_mut(&root).unwrap();
     if force_reassigned {
       st.force_reassigned();
@@ -175,33 +176,33 @@ impl DisjointSet {
     }
   }
 
-  fn add_root(&mut self, span: Span, status: VarStatus) {
-    if self.parents.contains_key(&span) {
+  fn add_root(&mut self, range: SourceRange, status: VarStatus) {
+    if self.parents.contains_key(&range) {
       return;
     }
-    self.parents.insert(span, span);
-    self.roots.insert(span, (status, 1));
+    self.parents.insert(range, range);
+    self.roots.insert(range, (status, 1));
   }
 
-  fn get_root(&mut self, span: Span) -> Option<Span> {
-    match self.parents.get(&span) {
+  fn get_root(&mut self, range: SourceRange) -> Option<SourceRange> {
+    match self.parents.get(&range) {
       None => None,
-      Some(&par_span) if span == par_span => Some(span),
-      Some(&par_span) => {
-        let root = self.get_root(par_span);
-        if let (Some(root_span), Some(par)) =
-          (root, self.parents.get_mut(&span))
+      Some(&par_range) if range == par_range => Some(range),
+      Some(&par_range) => {
+        let root = self.get_root(par_range);
+        if let (Some(root_range), Some(par)) =
+          (root, self.parents.get_mut(&range))
         {
-          *par = root_span;
+          *par = root_range;
         }
         root
       }
     }
   }
 
-  fn unite(&mut self, span1: Span, span2: Span) -> Option<()> {
-    let rs1 = self.get_root(span1)?;
-    let rs2 = self.get_root(span2)?;
+  fn unite(&mut self, range1: SourceRange, range2: SourceRange) -> Option<()> {
+    let rs1 = self.get_root(range1)?;
+    let rs2 = self.get_root(range2)?;
     if rs1 == rs2 {
       return None;
     }
@@ -231,7 +232,7 @@ impl DisjointSet {
     Some(())
   }
 
-  fn dump(&mut self) -> Vec<Span> {
+  fn dump(&mut self) -> Vec<SourceRange> {
     self
       .parents
       .clone()
@@ -251,7 +252,7 @@ impl DisjointSet {
 #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)]
 enum ScopeRange {
   Global,
-  Block(Span),
+  Block(SourceRange),
 }
 
 #[derive(Debug)]
@@ -271,9 +272,9 @@ impl VariableCollector {
   }
 
   fn insert_var(&mut self, ident: &Ident, status: VarStatus) {
-    self.var_groups.add_root(ident.span, status);
+    self.var_groups.add_root(ident.range(), status);
     let mut scope = self.scopes.get(&self.cur_scope).unwrap().borrow_mut();
-    scope.variables.insert(ident.sym.clone(), ident.span);
+    scope.variables.insert(ident.sym.clone(), ident.range());
   }
 
   fn insert_vars(&mut self, idents: &[&Ident], status: VarStatus) {
@@ -288,7 +289,7 @@ impl VariableCollector {
         // If there are more than one idents, they need to be grouped
         for i in others {
           self.insert_var(i, status);
-          self.var_groups.unite(first.span, i.span);
+          self.var_groups.unite(first.range(), i.range());
         }
       }
     }
@@ -308,17 +309,17 @@ impl VariableCollector {
 
   fn with_child_scope<F, S>(&mut self, node: S, op: F)
   where
-    S: Spanned,
+    S: SourceRangedForSpanned,
     F: FnOnce(&mut VariableCollector),
   {
     let parent_scope_range = self.cur_scope;
     let parent_scope = self.scopes.get(&parent_scope_range).map(Rc::clone);
     let child_scope = RawScope::new(parent_scope);
     self.scopes.insert(
-      ScopeRange::Block(node.span()),
+      ScopeRange::Block(node.range()),
       Rc::new(RefCell::new(child_scope)),
     );
-    self.cur_scope = ScopeRange::Block(node.span());
+    self.cur_scope = ScopeRange::Block(node.range());
     op(self);
     self.cur_scope = parent_scope_range;
   }
@@ -347,7 +348,7 @@ impl Visit for VariableCollector {
     self.with_child_scope(function, |a| {
       for param in &function.params {
         param.visit_children_with(a);
-        let idents: Vec<Ident> = find_ids(&param.pat);
+        let idents: Vec<Ident> = find_pat_ids(&param.pat);
         for ident in idents {
           a.insert_var(&ident, VarStatus::Reassigned);
         }
@@ -362,7 +363,7 @@ impl Visit for VariableCollector {
     self.with_child_scope(arrow_expr, |a| {
       for param in &arrow_expr.params {
         param.visit_children_with(a);
-        let idents: Vec<Ident> = find_ids(param);
+        let idents: Vec<Ident> = find_pat_ids(param);
         for ident in idents {
           a.insert_var(&ident, VarStatus::Reassigned);
         }
@@ -529,7 +530,7 @@ impl Visit for VariableCollector {
   fn visit_catch_clause(&mut self, catch_clause: &CatchClause) {
     self.with_child_scope(catch_clause, |a| {
       if let Some(param) = &catch_clause.param {
-        let idents: Vec<Ident> = find_ids(param);
+        let idents: Vec<Ident> = find_pat_ids(param);
         for ident in idents {
           a.insert_var(&ident, VarStatus::Reassigned);
         }
@@ -566,7 +567,7 @@ impl Visit for VariableCollector {
               }
               TsParamPropParam::Assign(assign_pat) => {
                 assign_pat.visit_children_with(a);
-                let idents: Vec<Ident> = find_ids(&assign_pat.left);
+                let idents: Vec<Ident> = find_pat_ids(&assign_pat.left);
                 for ident in idents {
                   a.insert_var(&ident, VarStatus::Reassigned);
                 }
@@ -575,7 +576,7 @@ impl Visit for VariableCollector {
           }
           ParamOrTsParamProp::Param(param) => {
             param.visit_children_with(a);
-            let idents: Vec<Ident> = find_ids(&param.pat);
+            let idents: Vec<Ident> = find_pat_ids(&param.pat);
             for ident in idents {
               a.insert_var(&ident, VarStatus::Reassigned);
             }
@@ -672,23 +673,23 @@ impl<'c, 'view> PreferConstVisitor<'c, 'view> {
     }
   }
 
-  fn report(&mut self, span: Span) {
-    let span_text = self.context.file_text_substring(&span).to_string();
+  fn report(&mut self, range: SourceRange) {
+    let range_text = range.text_fast(&self.context.text_info()).to_string();
     self.context.add_diagnostic_with_hint(
-      span,
+      range,
       CODE,
-      PreferConstMessage::NeverReassigned(span_text),
+      PreferConstMessage::NeverReassigned(range_text),
       PreferConstHint::UseConst,
     );
   }
 
   fn with_child_scope<F, S>(&mut self, node: &S, op: F)
   where
-    S: Spanned,
+    S: SourceRangedForSpanned,
     F: FnOnce(&mut Self),
   {
     let parent_scope_range = self.cur_scope;
-    self.cur_scope = ScopeRange::Block(node.span());
+    self.cur_scope = ScopeRange::Block(node.range());
     op(self);
     self.cur_scope = parent_scope_range;
   }
@@ -727,17 +728,18 @@ impl<'c, 'view> PreferConstVisitor<'c, 'view> {
       [decl] => {
         self
           .var_groups
-          .proceed_status(decl.span, force_reassigned || decl.in_other_scope);
+          .proceed_status(decl.range, force_reassigned || decl.in_other_scope);
       }
       [first, others @ ..] => {
-        self
-          .var_groups
-          .proceed_status(first.span, force_reassigned || first.in_other_scope);
+        self.var_groups.proceed_status(
+          first.range,
+          force_reassigned || first.in_other_scope,
+        );
         for s in others {
           self
             .var_groups
-            .proceed_status(s.span, force_reassigned || s.in_other_scope);
-          self.var_groups.unite(first.span, s.span);
+            .proceed_status(s.range, force_reassigned || s.in_other_scope);
+          self.var_groups.unite(first.range, s.range);
         }
       }
     }
@@ -750,16 +752,16 @@ impl<'c, 'view> Visit for PreferConstVisitor<'c, 'view> {
   fn visit_module(&mut self, module: &Module) {
     module.visit_children_with(self);
     // After visiting all nodes, reports errors.
-    for span in self.var_groups.dump() {
-      self.report(span);
+    for range in self.var_groups.dump() {
+      self.report(range);
     }
   }
 
   fn visit_script(&mut self, script: &Script) {
     script.visit_children_with(self);
     // After visiting all nodes, reports errors.
-    for span in self.var_groups.dump() {
-      self.report(span);
+    for range in self.var_groups.dump() {
+      self.report(range);
     }
   }
 
@@ -772,7 +774,7 @@ impl<'c, 'view> Visit for PreferConstVisitor<'c, 'view> {
     assign_expr.visit_children_with(self);
 
     let idents: Vec<Ident> = match &assign_expr.left {
-      PatOrExpr::Pat(pat) => find_ids(pat), // find_ids doesn't work for Expression
+      PatOrExpr::Pat(pat) => find_pat_ids(pat), // find_pat_ids doesn't work for Expression
       PatOrExpr::Expr(expr) if expr.is_ident() => {
         let ident = (**expr).clone().expect_ident();
         vec![ident]
diff --git a/src/rules/prefer_namespace_keyword.rs b/src/rules/prefer_namespace_keyword.rs
index 5c608b9..42dcc83 100644
--- a/src/rules/prefer_namespace_keyword.rs
+++ b/src/rules/prefer_namespace_keyword.rs
@@ -2,8 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{TsModuleDecl, TsModuleName};
+use deno_ast::SourceRanged;
 use once_cell::sync::Lazy;
 use regex::Regex;
 use std::sync::Arc;
@@ -54,11 +54,11 @@ impl Handler for PreferNamespaceKeywordHandler {
     static KEYWORD: Lazy<Regex> =
       Lazy::new(|| Regex::new(r"(declare\s)?(?P<keyword>\w+)").unwrap());
 
-    let snippet = ctx.file_text_substring(&mod_decl.span());
+    let snippet = mod_decl.text_fast(&ctx.text_info());
     if let Some(capt) = KEYWORD.captures(snippet) {
       let keyword = capt.name("keyword").unwrap().as_str();
       if keyword == "module" && !mod_decl.global() {
-        ctx.add_diagnostic(mod_decl.span(), CODE, MESSAGE)
+        ctx.add_diagnostic(mod_decl.range(), CODE, MESSAGE)
       }
     }
   }
diff --git a/src/rules/prefer_primordials.rs b/src/rules/prefer_primordials.rs
index 689c5ce..6ebdb34 100644
--- a/src/rules/prefer_primordials.rs
+++ b/src/rules/prefer_primordials.rs
@@ -2,11 +2,9 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
-use deno_ast::swc::utils::ident::IdentLike;
-use deno_ast::view as ast_view;
 use deno_ast::view::NodeTrait;
 use deno_ast::Scope;
+use deno_ast::{view as ast_view, SourceRanged};
 use if_chain::if_chain;
 use std::sync::Arc;
 
@@ -108,10 +106,10 @@ impl Handler for PreferPrimordialsHandler {
         return true;
       }
       if let Some(decl) = node.to::<ast_view::VarDeclarator>() {
-        return decl.name.span().contains(orig.span());
+        return decl.name.range().contains(&orig.range());
       }
       if let Some(kv) = node.to::<ast_view::KeyValueProp>() {
-        return kv.key.span().contains(orig.span());
+        return kv.key.range().contains(&orig.range());
       }
 
       match node.parent() {
@@ -132,7 +130,7 @@ impl Handler for PreferPrimordialsHandler {
     if TARGETS.contains(&ident.sym().as_ref())
       && !is_shadowed(ident, ctx.scope())
     {
-      ctx.add_diagnostic_with_hint(ident.span(), CODE, MESSAGE, HINT);
+      ctx.add_diagnostic_with_hint(ident.range(), CODE, MESSAGE, HINT);
     }
   }
 
@@ -145,7 +143,7 @@ impl Handler for PreferPrimordialsHandler {
       if expr_or_spread.inner.spread.is_some();
       if !expr_or_spread.inner.expr.is_new();
       then {
-        ctx.add_diagnostic_with_hint(expr_or_spread.span(), CODE, MESSAGE, HINT);
+        ctx.add_diagnostic_with_hint(expr_or_spread.range(), CODE, MESSAGE, HINT);
       }
     }
   }
@@ -157,7 +155,7 @@ impl Handler for PreferPrimordialsHandler {
   ) {
     if !for_of_stmt.right.is::<ast_view::NewExpr>() {
       ctx.add_diagnostic_with_hint(
-        for_of_stmt.right.span(),
+        for_of_stmt.right.range(),
         CODE,
         MESSAGE,
         HINT,
@@ -186,7 +184,7 @@ impl Handler for PreferPrimordialsHandler {
     // primordials.ArrayPrototypeFilter([1, 2, 3], (val) => val % 2 === 0)
     // ```
     if let Expr::Array(_) = &member_expr.obj {
-      ctx.add_diagnostic_with_hint(member_expr.span(), CODE, MESSAGE, HINT);
+      ctx.add_diagnostic_with_hint(member_expr.range(), CODE, MESSAGE, HINT);
       return;
     }
 
@@ -200,7 +198,7 @@ impl Handler for PreferPrimordialsHandler {
       if let Expr::Ident(ident) = &member_expr.obj;
       if TARGETS.contains(&ident.sym().as_ref());
       then {
-        ctx.add_diagnostic_with_hint(member_expr.span(), CODE, MESSAGE, HINT);
+        ctx.add_diagnostic_with_hint(member_expr.range(), CODE, MESSAGE, HINT);
       }
     }
   }
@@ -210,7 +208,7 @@ impl Handler for PreferPrimordialsHandler {
     if matches!(bin_expr.op(), BinaryOp::InstanceOf)
       || matches!(bin_expr.op(), BinaryOp::In)
     {
-      ctx.add_diagnostic_with_hint(bin_expr.span(), CODE, MESSAGE, HINT);
+      ctx.add_diagnostic_with_hint(bin_expr.range(), CODE, MESSAGE, HINT);
     }
   }
 }
diff --git a/src/rules/require_await.rs b/src/rules/require_await.rs
index 0802ec7..637ef55 100644
--- a/src/rules/require_await.rs
+++ b/src/rules/require_await.rs
@@ -4,7 +4,6 @@ use crate::handler::{Handler, Traverse};
 use crate::swc_util::StringRepr;
 use crate::ProgramRef;
 
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{NodeTrait, Program};
 use derive_more::Display;
 use std::sync::Arc;
@@ -270,7 +269,7 @@ fn process_function<'a, N>(
   function_info: FunctionInfo,
   ctx: &mut Context,
 ) where
-  N: NodeTrait<'a> + Spanned,
+  N: NodeTrait<'a>,
 {
   let mut function_handler = FunctionHandler {
     function_info: Some(Box::new(function_info)),
@@ -284,7 +283,7 @@ fn process_function<'a, N>(
 
   if let Some(message) = function_info.should_report() {
     ctx.add_diagnostic_with_hint(
-      node.span(),
+      node.range(),
       CODE,
       message,
       RequireAwaitHint::RemoveOrUse,
diff --git a/src/rules/require_yield.rs b/src/rules/require_yield.rs
index 216b912..e66b709 100644
--- a/src/rules/require_yield.rs
+++ b/src/rules/require_yield.rs
@@ -10,6 +10,7 @@ use deno_ast::swc::ast::PrivateMethod;
 use deno_ast::swc::ast::YieldExpr;
 use deno_ast::swc::visit::noop_visit_type;
 use deno_ast::swc::visit::Visit;
+use deno_ast::SourceRangedForSpanned;
 use std::sync::Arc;
 
 #[derive(Debug)]
@@ -76,7 +77,7 @@ impl<'c, 'view> RequireYieldVisitor<'c, 'view> {
       // is non-empty
       if let Some(body) = &function.body {
         if !body.stmts.is_empty() && yield_count == 0 {
-          self.context.add_diagnostic(function.span, CODE, MESSAGE);
+          self.context.add_diagnostic(function.range(), CODE, MESSAGE);
         }
       }
     }
diff --git a/src/rules/single_var_declarator.rs b/src/rules/single_var_declarator.rs
index 4949db3..a2694a1 100644
--- a/src/rules/single_var_declarator.rs
+++ b/src/rules/single_var_declarator.rs
@@ -4,6 +4,7 @@ use crate::ProgramRef;
 use deno_ast::swc::ast::VarDecl;
 use deno_ast::swc::visit::noop_visit_type;
 use deno_ast::swc::visit::Visit;
+use deno_ast::SourceRangedForSpanned;
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -61,7 +62,7 @@ impl<'c, 'view> Visit for SingleVarDeclaratorVisitor<'c, 'view> {
   fn visit_var_decl(&mut self, var_decl: &VarDecl) {
     if var_decl.decls.len() > 1 {
       self.context.add_diagnostic(
-        var_decl.span,
+        var_decl.range(),
         CODE,
         SingleVarDeclaratorMessage::Unexpected,
       );
diff --git a/src/rules/triple_slash_reference.rs b/src/rules/triple_slash_reference.rs
index 8c19c16..8bb41c5 100644
--- a/src/rules/triple_slash_reference.rs
+++ b/src/rules/triple_slash_reference.rs
@@ -3,7 +3,8 @@ use super::{Context, LintRule};
 use crate::ProgramRef;
 use deno_ast::swc::common::comments::Comment;
 use deno_ast::swc::common::comments::CommentKind;
-use deno_ast::swc::common::Span;
+use deno_ast::SourceRange;
+use deno_ast::SourceRangedForSpanned;
 use derive_more::Display;
 use once_cell::sync::Lazy;
 use regex::Regex;
@@ -21,8 +22,12 @@ enum TripleSlashReferenceMessage {
 }
 
 impl TripleSlashReference {
-  fn report(&self, context: &mut Context, span: Span) {
-    context.add_diagnostic(span, CODE, TripleSlashReferenceMessage::Unexpected);
+  fn report(&self, context: &mut Context, range: SourceRange) {
+    context.add_diagnostic(
+      range,
+      CODE,
+      TripleSlashReferenceMessage::Unexpected,
+    );
   }
 }
 
@@ -36,18 +41,18 @@ impl LintRule for TripleSlashReference {
   }
 
   fn lint_program(&self, context: &mut Context, _program: ProgramRef<'_>) {
-    let mut violated_comment_spans = Vec::new();
+    let mut violated_comment_ranges = Vec::new();
 
-    violated_comment_spans.extend(context.all_comments().filter_map(|c| {
+    violated_comment_ranges.extend(context.all_comments().filter_map(|c| {
       if check_comment(c) {
-        Some(c.span)
+        Some(c.range())
       } else {
         None
       }
     }));
 
-    for span in violated_comment_spans {
-      self.report(context, span);
+    for range in violated_comment_ranges {
+      self.report(context, range);
     }
   }
 
diff --git a/src/rules/use_isnan.rs b/src/rules/use_isnan.rs
index 4ad9572..4ef3100 100644
--- a/src/rules/use_isnan.rs
+++ b/src/rules/use_isnan.rs
@@ -2,8 +2,8 @@
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
 use deno_ast::view::{BinExpr, BinaryOp, Expr, Ident, SwitchStmt};
+use deno_ast::SourceRanged;
 use derive_more::Display;
 use std::sync::Arc;
 
@@ -79,7 +79,7 @@ impl Handler for UseIsNaNHandler {
       if let Expr::Ident(ident) = bin_expr.left {
         if is_nan_identifier(ident) {
           ctx.add_diagnostic(
-            bin_expr.span(),
+            bin_expr.range(),
             CODE,
             UseIsNaNMessage::Comparison,
           );
@@ -88,7 +88,7 @@ impl Handler for UseIsNaNHandler {
       if let Expr::Ident(ident) = bin_expr.right {
         if is_nan_identifier(ident) {
           ctx.add_diagnostic(
-            bin_expr.span(),
+            bin_expr.range(),
             CODE,
             UseIsNaNMessage::Comparison,
           );
@@ -101,7 +101,7 @@ impl Handler for UseIsNaNHandler {
     if let Expr::Ident(ident) = switch_stmt.discriminant {
       if is_nan_identifier(ident) {
         ctx.add_diagnostic(
-          switch_stmt.span(),
+          switch_stmt.range(),
           CODE,
           UseIsNaNMessage::SwitchUnmatched,
         );
@@ -111,7 +111,11 @@ impl Handler for UseIsNaNHandler {
     for case in &switch_stmt.cases {
       if let Some(Expr::Ident(ident)) = &case.test {
         if is_nan_identifier(ident) {
-          ctx.add_diagnostic(case.span(), CODE, UseIsNaNMessage::CaseUnmatched);
+          ctx.add_diagnostic(
+            case.range(),
+            CODE,
+            UseIsNaNMessage::CaseUnmatched,
+          );
         }
       }
     }
diff --git a/src/rules/valid_typeof.rs b/src/rules/valid_typeof.rs
index 8a59dc6..0090c7a 100644
--- a/src/rules/valid_typeof.rs
+++ b/src/rules/valid_typeof.rs
@@ -7,8 +7,8 @@ use deno_ast::swc::ast::BinaryOp::{EqEq, EqEqEq, NotEq, NotEqEq};
 use deno_ast::swc::ast::Expr::{Lit, Tpl, Unary};
 use deno_ast::swc::ast::Lit::Str;
 use deno_ast::swc::ast::UnaryOp::TypeOf;
-use deno_ast::swc::common::Spanned;
 use deno_ast::swc::visit::{noop_visit_type, Visit};
+use deno_ast::SourceRangedForSpanned;
 use std::sync::Arc;
 
 #[derive(Debug)]
@@ -70,7 +70,7 @@ impl<'c, 'view> Visit for ValidTypeofVisitor<'c, 'view> {
           Unary(unary) if unary.op == TypeOf => {}
           Lit(Str(str)) => {
             if !is_valid_typeof_string(&str.value) {
-              self.context.add_diagnostic(str.span, CODE, MESSAGE);
+              self.context.add_diagnostic(str.range(), CODE, MESSAGE);
             }
           }
           Tpl(tpl) => {
@@ -78,11 +78,11 @@ impl<'c, 'view> Visit for ValidTypeofVisitor<'c, 'view> {
               .string_repr()
               .map_or(false, |s| !is_valid_typeof_string(&s))
             {
-              self.context.add_diagnostic(tpl.span, CODE, MESSAGE);
+              self.context.add_diagnostic(tpl.range(), CODE, MESSAGE);
             }
           }
           _ => {
-            self.context.add_diagnostic(operand.span(), CODE, MESSAGE);
+            self.context.add_diagnostic(operand.range(), CODE, MESSAGE);
           }
         }
       }
diff --git a/src/swc_util.rs b/src/swc_util.rs
index 695caf5..cc95d4a 100644
--- a/src/swc_util.rs
+++ b/src/swc_util.rs
@@ -4,7 +4,7 @@ use deno_ast::swc::ast::{
   MemberProp, Null, Number, PatOrExpr, PrivateName, Prop, PropName,
   PropOrSpread, Regex, Str, Tpl,
 };
-use deno_ast::swc::utils::{find_ids, ident::IdentLike};
+use deno_ast::swc::utils::{find_pat_ids, ident::IdentLike};
 use deno_ast::view as ast_view;
 use deno_ast::Scope;
 
@@ -297,6 +297,6 @@ where
       Expr::Ident(i) => vec![I::from_ident(i)],
       _ => vec![],
     },
-    PatOrExpr::Pat(p) => find_ids(p),
+    PatOrExpr::Pat(p) => find_pat_ids(p),
   }
 }
diff --git a/tools/scaffold.ts b/tools/scaffold.ts
index 05845a8..982bad9 100755
--- a/tools/scaffold.ts
+++ b/tools/scaffold.ts
@@ -99,7 +99,7 @@ export function genRustContent(
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
+use deno_ast::SourceRanged;
 use deno_ast::view as ast_view;
 use std::sync::Arc;
 
@@ -144,7 +144,7 @@ impl Handler for ${pascalCasedLintName}Handler {
 
   // This is an example
   fn with_stmt(&mut self, with_stmt: &ast_view::WithStmt, ctx: &mut Context) {
-    ctx.add_diagnostic_with_hint(with_stmt.span(), CODE, MESSAGE, HINT);
+    ctx.add_diagnostic_with_hint(with_stmt.range(), CODE, MESSAGE, HINT);
   }
 }
 


Test patch:
diff --git a/examples/dlint/plugins/test_plugin1.js b/examples/dlint/plugins/test_plugin1.js
deleted file mode 100644
index 2d24f7c..0000000
--- a/examples/dlint/plugins/test_plugin1.js
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2020-2021 the Deno authors. All rights reserved. MIT license.
-export default class LintRule extends Visitor {
-  static ruleCode() {
-    return "some-rule-code";
-  }
-
-  visitImportDeclaration(e) {
-    this.addDiagnostic({
-      span: e.span,
-      message: "foo",
-    });
-    return e;
-  }
-}
diff --git a/examples/dlint/plugins/test_plugin2.js b/examples/dlint/plugins/test_plugin2.js
deleted file mode 100644
index 84621ac..0000000
--- a/examples/dlint/plugins/test_plugin2.js
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2020-2021 the Deno authors. All rights reserved. MIT license.
-export default class LintRule extends Visitor {
-  static ruleCode() {
-    return "forbidden-ident-name";
-  }
-
-  visitIdentifier(n) {
-    if (n.value === "forbiddenIdentifier") {
-      this.addDiagnostic({
-        span: n.span,
-        message: "forbidden identifier name",
-      });
-    }
-    return n;
-  }
-}
diff --git a/examples/dlint/plugins/test_plugin3.js b/examples/dlint/plugins/test_plugin3.js
deleted file mode 100644
index f9d9ec0..0000000
--- a/examples/dlint/plugins/test_plugin3.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2020-2021 the Deno authors. All rights reserved. MIT license.
-export default class LintRule extends Visitor {
-  static ruleCode() {
-    return "no-unreachable-return-statement";
-  }
-
-  visitReturnStatement(stmt) {
-    /** @type {(boolean|null)} */
-    const reachable = ControlFlow.isReachable(stmt);
-
-    if (reachable === false) {
-      this.addDiagnostic({
-        span: stmt.span,
-        message: "unreachable return statement detected",
-      });
-    }
-
-    return stmt;
-  }
-}
diff --git a/src/control_flow/analyze_test.rs b/src/control_flow/analyze_test.rs
index 2903c99..57b4954 100644
--- a/src/control_flow/analyze_test.rs
+++ b/src/control_flow/analyze_test.rs
@@ -1,17 +1,17 @@
 // Copyright 2020-2021 the Deno authors. All rights reserved. MIT license.
 use super::{ControlFlow, End, Metadata};
 use crate::test_util;
-use deno_ast::swc::common::BytePos;
+use deno_ast::StartSourcePos;
 
 fn analyze_flow(src: &str) -> ControlFlow {
   let parsed_source = test_util::parse(src);
-  ControlFlow::analyze(parsed_source.program_ref().into())
+  ControlFlow::analyze(&parsed_source)
 }
 
 macro_rules! assert_flow {
   ($flow:ident, $lo:expr, $unreachable:expr, $end:expr) => {
     assert_eq!(
-      $flow.meta(BytePos($lo)).unwrap(),
+      $flow.meta(StartSourcePos::START_SOURCE_POS + $lo).unwrap(),
       &Metadata {
         unreachable: $unreachable,
         end: $end,
diff --git a/tools/tests/scaffold_test.ts b/tools/tests/scaffold_test.ts
index 35ce64f..a92cc75 100644
--- a/tools/tests/scaffold_test.ts
+++ b/tools/tests/scaffold_test.ts
@@ -91,7 +91,7 @@ Deno.test("the content of .rs", () => {
 use super::{Context, LintRule};
 use crate::handler::{Handler, Traverse};
 use crate::{Program, ProgramRef};
-use deno_ast::swc::common::Spanned;
+use deno_ast::SourceRanged;
 use deno_ast::view as ast_view;
 use std::sync::Arc;
 
@@ -136,7 +136,7 @@ impl Handler for FooBarBazHandler {
 
   // This is an example
   fn with_stmt(&mut self, with_stmt: &ast_view::WithStmt, ctx: &mut Context) {
-    ctx.add_diagnostic_with_hint(with_stmt.span(), CODE, MESSAGE, HINT);
+    ctx.add_diagnostic_with_hint(with_stmt.range(), CODE, MESSAGE, HINT);
   }
 }