perf(parser): lazily build trivia map instead of build in-place (#903)

closes #898
This commit is contained in:
Boshen 2023-09-12 23:23:56 +08:00 committed by GitHub
parent 95cae98e2b
commit babbc47d61
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 35 additions and 24 deletions

View file

@ -22,7 +22,11 @@ mod visit_mut;
pub use num_bigint::BigUint; pub use num_bigint::BigUint;
pub use crate::{ pub use crate::{
ast_builder::AstBuilder, ast_kind::AstKind, trivia::Trivias, visit::Visit, visit_mut::VisitMut, ast_builder::AstBuilder,
ast_kind::AstKind,
trivia::{Comment, CommentKind, Trivias, TriviasMap},
visit::Visit,
visit_mut::VisitMut,
}; };
// After experimenting with two types of boxed enum variants: // After experimenting with two types of boxed enum variants:

View file

@ -4,16 +4,25 @@ use std::collections::BTreeMap;
use oxc_span::Span; use oxc_span::Span;
/// A vec of trivias from the lexer, tupled by (span.start, span.end).
pub type Trivias = Vec<(u32, u32, CommentKind)>;
/// Trivias such as comments /// Trivias such as comments
/// ///
/// Trivia (called that because it's trivial) represent the parts of the source text that are largely insignificant for normal understanding of the code. /// Trivia (called that because it's trivial) represent the parts of the source text that are largely insignificant for normal understanding of the code.
/// For example: whitespace, comments, and even conflict markers. /// For example: whitespace, comments, and even conflict markers.
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct Trivias { pub struct TriviasMap {
/// Keyed by span.start /// Keyed by span.start
comments: BTreeMap<u32, Comment>, comments: BTreeMap<u32, Comment>,
} }
impl From<Trivias> for TriviasMap {
fn from(trivias: Trivias) -> Self {
Self { comments: trivias.iter().map(|t| (t.0, Comment::new(t.1, t.2))).collect() }
}
}
/// Single or multiline comment /// Single or multiline comment
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
#[allow(unused)] #[allow(unused)]
@ -46,7 +55,7 @@ impl Comment {
} }
} }
impl Trivias { impl TriviasMap {
pub fn comments(&self) -> &BTreeMap<u32, Comment> { pub fn comments(&self) -> &BTreeMap<u32, Comment> {
&self.comments &self.comments
} }

View file

@ -1,4 +1,4 @@
use oxc_ast::Trivias; use oxc_ast::TriviasMap;
use oxc_span::Span; use oxc_span::Span;
use rust_lapper::{Interval, Lapper}; use rust_lapper::{Interval, Lapper};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
@ -28,7 +28,7 @@ impl<'a> DisableDirectives<'a> {
pub struct DisableDirectivesBuilder<'a, 'b> { pub struct DisableDirectivesBuilder<'a, 'b> {
source_text: &'a str, source_text: &'a str,
trivias: &'b Trivias, trivias: &'b TriviasMap,
/// All the disabled rules with their corresponding covering spans /// All the disabled rules with their corresponding covering spans
intervals: Lapper<u32, DisabledRule<'a>>, intervals: Lapper<u32, DisabledRule<'a>>,
/// Start of `eslint-disable` /// Start of `eslint-disable`
@ -38,7 +38,7 @@ pub struct DisableDirectivesBuilder<'a, 'b> {
} }
impl<'a, 'b> DisableDirectivesBuilder<'a, 'b> { impl<'a, 'b> DisableDirectivesBuilder<'a, 'b> {
pub fn new(source_text: &'a str, trivias: &'b Trivias) -> Self { pub fn new(source_text: &'a str, trivias: &'b TriviasMap) -> Self {
Self { Self {
source_text, source_text,
trivias, trivias,

View file

@ -1,5 +1,4 @@
use oxc_ast::Trivias; use oxc_ast::{CommentKind, Trivias};
use oxc_span::Span;
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct TriviaBuilder { pub struct TriviaBuilder {
@ -11,13 +10,13 @@ impl TriviaBuilder {
self.trivias self.trivias
} }
/// skip leading `//`
pub fn add_single_line_comment(&mut self, start: u32, end: u32) { pub fn add_single_line_comment(&mut self, start: u32, end: u32) {
// skip leading `//` self.trivias.push((start + 2, end, CommentKind::SingleLine));
self.trivias.add_single_line_comment(Span::new(start + 2, end));
} }
/// skip leading `/*` and trailing `*/`
pub fn add_multi_line_comment(&mut self, start: u32, end: u32) { pub fn add_multi_line_comment(&mut self, start: u32, end: u32) {
// skip leading `/*` and trailing `*/` self.trivias.push((start + 2, end - 2, CommentKind::MultiLine));
self.trivias.add_multi_line_comment(Span::new(start + 2, end - 2));
} }
} }

View file

@ -4,7 +4,7 @@ use std::{cell::RefCell, path::PathBuf, rc::Rc, sync::Arc};
use itertools::Itertools; use itertools::Itertools;
#[allow(clippy::wildcard_imports)] #[allow(clippy::wildcard_imports)]
use oxc_ast::{ast::*, AstKind, Trivias, Visit}; use oxc_ast::{ast::*, AstKind, Trivias, TriviasMap, Visit};
use oxc_diagnostics::Error; use oxc_diagnostics::Error;
use oxc_span::{Atom, SourceType, Span}; use oxc_span::{Atom, SourceType, Span};
use oxc_syntax::{module_record::ModuleRecord, operator::AssignmentOperator}; use oxc_syntax::{module_record::ModuleRecord, operator::AssignmentOperator};
@ -40,7 +40,7 @@ pub struct SemanticBuilder<'a> {
pub source_type: SourceType, pub source_type: SourceType,
trivias: Rc<Trivias>, trivias: Rc<TriviasMap>,
/// Semantic early errors such as redeclaration errors. /// Semantic early errors such as redeclaration errors.
errors: RefCell<Vec<Error>>, errors: RefCell<Vec<Error>>,
@ -82,7 +82,7 @@ impl<'a> SemanticBuilder<'a> {
let scope = ScopeTree::new(source_type); let scope = ScopeTree::new(source_type);
let current_scope_id = scope.root_scope_id(); let current_scope_id = scope.root_scope_id();
let trivias = Rc::new(Trivias::default()); let trivias = Rc::new(TriviasMap::default());
Self { Self {
source_text, source_text,
source_type, source_type,
@ -106,9 +106,8 @@ impl<'a> SemanticBuilder<'a> {
#[must_use] #[must_use]
pub fn with_trivias(mut self, trivias: Trivias) -> Self { pub fn with_trivias(mut self, trivias: Trivias) -> Self {
let trivias = Rc::new(trivias); self.trivias = Rc::new(TriviasMap::from(trivias));
self.trivias = Rc::clone(&trivias); self.jsdoc = JSDocBuilder::new(self.source_text, &self.trivias);
self.jsdoc = JSDocBuilder::new(self.source_text, &trivias);
self self
} }

View file

@ -1,6 +1,6 @@
use std::{collections::BTreeMap, rc::Rc}; use std::{collections::BTreeMap, rc::Rc};
use oxc_ast::{AstKind, Trivias}; use oxc_ast::{AstKind, TriviasMap};
use oxc_span::{GetSpan, Span}; use oxc_span::{GetSpan, Span};
use super::{JSDoc, JSDocComment}; use super::{JSDoc, JSDocComment};
@ -8,13 +8,13 @@ use super::{JSDoc, JSDocComment};
pub struct JSDocBuilder<'a> { pub struct JSDocBuilder<'a> {
source_text: &'a str, source_text: &'a str,
trivias: Rc<Trivias>, trivias: Rc<TriviasMap>,
docs: BTreeMap<Span, JSDocComment<'a>>, docs: BTreeMap<Span, JSDocComment<'a>>,
} }
impl<'a> JSDocBuilder<'a> { impl<'a> JSDocBuilder<'a> {
pub fn new(source_text: &'a str, trivias: &Rc<Trivias>) -> Self { pub fn new(source_text: &'a str, trivias: &Rc<TriviasMap>) -> Self {
Self { source_text, trivias: Rc::clone(trivias), docs: BTreeMap::default() } Self { source_text, trivias: Rc::clone(trivias), docs: BTreeMap::default() }
} }

View file

@ -13,7 +13,7 @@ use std::{rc::Rc, sync::Arc};
pub use builder::{SemanticBuilder, SemanticBuilderReturn}; pub use builder::{SemanticBuilder, SemanticBuilderReturn};
pub use jsdoc::{JSDoc, JSDocComment, JSDocTag}; pub use jsdoc::{JSDoc, JSDocComment, JSDocTag};
use oxc_ast::{ast::IdentifierReference, AstKind, Trivias}; use oxc_ast::{ast::IdentifierReference, AstKind, TriviasMap};
use oxc_span::SourceType; use oxc_span::SourceType;
pub use oxc_syntax::{ pub use oxc_syntax::{
module_record::ModuleRecord, module_record::ModuleRecord,
@ -39,7 +39,7 @@ pub struct Semantic<'a> {
symbols: SymbolTable, symbols: SymbolTable,
trivias: Rc<Trivias>, trivias: Rc<TriviasMap>,
module_record: Arc<ModuleRecord>, module_record: Arc<ModuleRecord>,
@ -69,7 +69,7 @@ impl<'a> Semantic<'a> {
&self.scopes &self.scopes
} }
pub fn trivias(&self) -> &Trivias { pub fn trivias(&self) -> &TriviasMap {
&self.trivias &self.trivias
} }