mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 20:28:58 +00:00
feat(coverage): add regular expression idempotency test (#5676)
closes #5634
This commit is contained in:
parent
b9bf54494f
commit
2016bae98c
6 changed files with 63 additions and 6 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -1409,6 +1409,7 @@ dependencies = [
|
|||
"oxc_mangler",
|
||||
"oxc_minifier",
|
||||
"oxc_parser",
|
||||
"oxc_regular_expression",
|
||||
"oxc_semantic",
|
||||
"oxc_sourcemap",
|
||||
"oxc_span",
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@ required-features = ["full"]
|
|||
[dependencies]
|
||||
oxc_allocator = { workspace = true }
|
||||
oxc_ast = { workspace = true }
|
||||
oxc_parser = { workspace = true }
|
||||
oxc_regular_expression = { workspace = true }
|
||||
|
||||
oxc_cfg = { workspace = true, optional = true }
|
||||
oxc_codegen = { workspace = true, optional = true }
|
||||
oxc_diagnostics = { workspace = true }
|
||||
|
|
@ -35,7 +38,6 @@ oxc_index = { workspace = true }
|
|||
oxc_isolated_declarations = { workspace = true, optional = true }
|
||||
oxc_mangler = { workspace = true, optional = true }
|
||||
oxc_minifier = { workspace = true, optional = true }
|
||||
oxc_parser = { workspace = true }
|
||||
oxc_semantic = { workspace = true, optional = true }
|
||||
oxc_sourcemap = { workspace = true, optional = true }
|
||||
oxc_span = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -33,6 +33,11 @@ pub mod parser {
|
|||
pub use oxc_parser::*;
|
||||
}
|
||||
|
||||
pub mod regular_expression {
|
||||
#[doc(inline)]
|
||||
pub use oxc_regular_expression::*;
|
||||
}
|
||||
|
||||
pub mod span {
|
||||
#[doc(inline)]
|
||||
pub use oxc_span::*;
|
||||
|
|
|
|||
|
|
@ -2,8 +2,11 @@ commit: d62fa93c
|
|||
|
||||
parser_test262 Summary:
|
||||
AST Parsed : 43765/43765 (100.00%)
|
||||
Positive Passed: 43765/43765 (100.00%)
|
||||
Positive Passed: 43764/43765 (100.00%)
|
||||
Negative Passed: 4237/4237 (100.00%)
|
||||
Expect to Parse: tasks/coverage/test262/test/annexB/language/literals/regexp/legacy-octal-escape.js
|
||||
|
||||
× Regular Expression mismatch: \03 \3
|
||||
|
||||
× '0'-prefixed octal literals and octal escape sequences are deprecated
|
||||
╭─[test262/test/annexB/language/expressions/template-literal/legacy-octal-escape-sequence-strict.js:19:4]
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ commit: d62fa93c
|
|||
|
||||
semantic_test262 Summary:
|
||||
AST Parsed : 43765/43765 (100.00%)
|
||||
Positive Passed: 43565/43765 (99.54%)
|
||||
Positive Passed: 43564/43765 (99.54%)
|
||||
tasks/coverage/test262/test/annexB/language/function-code/if-decl-else-decl-a-func-block-scoping.js
|
||||
semantic error: Symbol scope ID mismatch:
|
||||
after transform: SymbolId(3): ScopeId(4294967294)
|
||||
|
|
@ -1119,6 +1119,9 @@ semantic error: Symbol scope ID mismatch:
|
|||
after transform: SymbolId(0): ScopeId(4294967294)
|
||||
rebuilt : SymbolId(0): ScopeId(4294967294)
|
||||
|
||||
tasks/coverage/test262/test/annexB/language/literals/regexp/legacy-octal-escape.js
|
||||
semantic error: Regular Expression mismatch: \03 \3
|
||||
|
||||
tasks/coverage/test262/test/language/module-code/eval-rqstd-once.js
|
||||
semantic error: Bindings mismatch:
|
||||
after transform: ScopeId(0): ["dflt1", "dflt2", "dflt3", "global", "ns1", "ns3"]
|
||||
|
|
|
|||
|
|
@ -1,14 +1,19 @@
|
|||
use std::{collections::HashSet, ops::ControlFlow, path::PathBuf};
|
||||
|
||||
use oxc::{
|
||||
ast::{ast::Program, Trivias},
|
||||
allocator::Allocator,
|
||||
ast::{
|
||||
ast::{Program, RegExpFlags},
|
||||
Trivias,
|
||||
},
|
||||
codegen::CodegenOptions,
|
||||
diagnostics::OxcDiagnostic,
|
||||
minifier::CompressOptions,
|
||||
parser::{ParseOptions, ParserReturn},
|
||||
regular_expression::{ParserOptions, PatternParser},
|
||||
semantic::{
|
||||
post_transform_checker::{check_semantic_after_transform, check_semantic_ids},
|
||||
SemanticBuilderReturn,
|
||||
Semantic, SemanticBuilderReturn,
|
||||
},
|
||||
span::{SourceType, Span},
|
||||
transformer::{TransformOptions, TransformerReturn},
|
||||
|
|
@ -78,7 +83,7 @@ impl CompilerInterface for Driver {
|
|||
fn after_semantic(
|
||||
&mut self,
|
||||
program: &mut Program<'_>,
|
||||
_semantic_return: &mut SemanticBuilderReturn,
|
||||
ret: &mut SemanticBuilderReturn,
|
||||
) -> ControlFlow<()> {
|
||||
if self.check_semantic {
|
||||
if let Some(errors) = check_semantic_ids(program) {
|
||||
|
|
@ -86,6 +91,7 @@ impl CompilerInterface for Driver {
|
|||
return ControlFlow::Break(());
|
||||
}
|
||||
};
|
||||
self.check_regular_expressions(&ret.semantic);
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
|
||||
|
|
@ -150,4 +156,41 @@ impl Driver {
|
|||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Idempotency test for printing regular expressions.
|
||||
fn check_regular_expressions(&mut self, semantic: &Semantic<'_>) {
|
||||
let allocator = Allocator::default();
|
||||
for literal in semantic.nodes().iter().filter_map(|node| node.kind().as_reg_exp_literal()) {
|
||||
let Some(pattern) = literal.regex.pattern.as_pattern() else {
|
||||
continue;
|
||||
};
|
||||
let printed1 = pattern.to_string();
|
||||
let flags = literal.regex.flags;
|
||||
let printed2 = match PatternParser::new(
|
||||
&allocator,
|
||||
&printed1,
|
||||
ParserOptions {
|
||||
span_offset: 0,
|
||||
unicode_mode: flags.contains(RegExpFlags::U) || flags.contains(RegExpFlags::V),
|
||||
unicode_sets_mode: flags.contains(RegExpFlags::V),
|
||||
},
|
||||
)
|
||||
.parse()
|
||||
{
|
||||
Ok(pattern) => pattern.to_string(),
|
||||
Err(error) => {
|
||||
self.errors.push(OxcDiagnostic::error(format!(
|
||||
"Failed to re-parse `{}`, printed as `/{printed1}/{flags}`, {error}",
|
||||
literal.span.source_text(semantic.source_text()),
|
||||
)));
|
||||
continue;
|
||||
}
|
||||
};
|
||||
if printed1 != printed2 {
|
||||
self.errors.push(OxcDiagnostic::error(format!(
|
||||
"Regular Expression mismatch: {printed1} {printed2}"
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue