From 7be5c6a4650b082c5b0fc26149108bbf50ea397f Mon Sep 17 00:00:00 2001 From: Boshen Date: Thu, 19 Sep 2024 13:26:23 +0800 Subject: [PATCH 1/4] feat(isolated_declarations): add `stripInternal` --- .../examples/isolated_declarations.rs | 10 +++- crates/oxc_isolated_declarations/src/lib.rs | 48 ++++++++++++++++++- .../tests/deno/mod.rs | 14 ++++-- crates/oxc_isolated_declarations/tests/mod.rs | 10 +++- napi/transform/src/context.rs | 15 +++--- napi/transform/src/isolated_declaration.rs | 26 ++++++++-- napi/transform/src/options.rs | 4 +- napi/transform/src/transformer.rs | 8 ++-- .../benches/isolated_declarations.rs | 12 +++-- .../src/typescript/transpile_runner.rs | 16 +++++-- 10 files changed, 130 insertions(+), 33 deletions(-) diff --git a/crates/oxc_isolated_declarations/examples/isolated_declarations.rs b/crates/oxc_isolated_declarations/examples/isolated_declarations.rs index 77adb46362060..21e33c6444d75 100644 --- a/crates/oxc_isolated_declarations/examples/isolated_declarations.rs +++ b/crates/oxc_isolated_declarations/examples/isolated_declarations.rs @@ -3,7 +3,7 @@ use std::{env, path::Path}; use oxc_allocator::Allocator; use oxc_codegen::{CodeGenerator, CommentOptions}; -use oxc_isolated_declarations::IsolatedDeclarations; +use oxc_isolated_declarations::{IsolatedDeclarations, IsolatedDeclarationsOptions}; use oxc_parser::Parser; use oxc_span::SourceType; @@ -32,7 +32,13 @@ fn main() { println!("Original:\n"); println!("{source_text}\n"); - let id_ret = IsolatedDeclarations::new(&allocator).build(&ret.program); + let id_ret = IsolatedDeclarations::new( + &allocator, + &source_text, + &ret.trivias, + IsolatedDeclarationsOptions { strip_internal: true }, + ) + .build(&ret.program); let printed = CodeGenerator::new() .enable_comment( &source_text, diff --git a/crates/oxc_isolated_declarations/src/lib.rs b/crates/oxc_isolated_declarations/src/lib.rs index 6957006f9a0ef..c6ce582a41d01 100644 --- a/crates/oxc_isolated_declarations/src/lib.rs +++ b/crates/oxc_isolated_declarations/src/lib.rs @@ -24,13 +24,21 @@ use std::{cell::RefCell, collections::VecDeque, mem}; use diagnostics::function_with_assigning_properties; use oxc_allocator::Allocator; #[allow(clippy::wildcard_imports)] -use oxc_ast::{ast::*, AstBuilder, Visit, NONE}; +use oxc_ast::{ast::*, AstBuilder, Trivias, Visit, NONE}; use oxc_diagnostics::OxcDiagnostic; use oxc_span::{Atom, SourceType, SPAN}; use rustc_hash::{FxHashMap, FxHashSet}; use crate::scope::ScopeTree; +#[derive(Debug, Clone, Copy)] +pub struct IsolatedDeclarationsOptions { + /// Do not emit declarations for code that has an @internal annotation in its JSDoc comment. + /// This is an internal compiler option; use at your own risk, because the compiler does not check that the result is valid. + /// + pub strip_internal: bool, +} + pub struct IsolatedDeclarationsReturn<'a> { pub program: Program<'a>, pub errors: Vec, @@ -38,15 +46,27 @@ pub struct IsolatedDeclarationsReturn<'a> { pub struct IsolatedDeclarations<'a> { ast: AstBuilder<'a>, + // state scope: ScopeTree<'a>, errors: RefCell>, + + /// Start position of `@internal` jsdoc markers. + is_internal_set: Option>, } impl<'a> IsolatedDeclarations<'a> { - pub fn new(allocator: &'a Allocator) -> Self { + pub fn new( + allocator: &'a Allocator, + source_text: &str, + trivias: &Trivias, + options: IsolatedDeclarationsOptions, + ) -> Self { Self { ast: AstBuilder::new(allocator), + is_internal_set: options + .strip_internal + .then(|| Self::build_is_internal_set(source_text, trivias)), scope: ScopeTree::new(allocator), errors: RefCell::new(vec![]), } @@ -71,6 +91,30 @@ impl<'a> IsolatedDeclarations<'a> { fn error(&self, error: OxcDiagnostic) { self.errors.borrow_mut().push(error); } + + /// Build the lookup table for jsdoc `@internal`. + fn build_is_internal_set(source_text: &str, trivias: &Trivias) -> FxHashSet { + let mut set = FxHashSet::default(); + for comment in trivias.comments().filter(|c| c.is_jsdoc(source_text)) { + let has_internal = comment + .span + .source_text(source_text) + .lines() + .filter_map(|s| s.trim_start().strip_prefix('*').map(str::trim_start)) + .filter_map(|s| s.split_whitespace().next()) + .any(|s| s == "@internal"); + // Use the first jsdoc comment if there are multiple jsdoc comments for the same node. + if has_internal && !set.contains(&comment.attached_to) { + set.insert(comment.attached_to); + } + } + set + } + + #[allow(unused)] + fn is_internal(&self, span: Span) -> bool { + self.is_internal_set.as_ref().map_or(false, |set| set.contains(&span.start)) + } } impl<'a> IsolatedDeclarations<'a> { diff --git a/crates/oxc_isolated_declarations/tests/deno/mod.rs b/crates/oxc_isolated_declarations/tests/deno/mod.rs index 2f9f110837eeb..211b7f3b37947 100644 --- a/crates/oxc_isolated_declarations/tests/deno/mod.rs +++ b/crates/oxc_isolated_declarations/tests/deno/mod.rs @@ -5,20 +5,24 @@ mod tests { use oxc_allocator::Allocator; use oxc_codegen::CodeGenerator; - use oxc_isolated_declarations::IsolatedDeclarations; + use oxc_isolated_declarations::{IsolatedDeclarations, IsolatedDeclarationsOptions}; use oxc_parser::Parser; use oxc_span::SourceType; fn transform_dts_test(source: &str, expected: &str) { let allocator = Allocator::default(); let source_type = SourceType::from_path("test.ts").unwrap(); - let program = Parser::new(&allocator, source, source_type).parse().program; - - let ret = IsolatedDeclarations::new(&allocator).build(&program); + let ret = Parser::new(&allocator, source, source_type).parse(); + let ret = IsolatedDeclarations::new( + &allocator, + source, + &ret.trivias, + IsolatedDeclarationsOptions { strip_internal: true }, + ) + .build(&ret.program); let actual = CodeGenerator::new().build(&ret.program).source_text; let expected_program = Parser::new(&allocator, expected, source_type).parse().program; let expected = CodeGenerator::new().build(&expected_program).source_text; - assert_eq!(actual.trim(), expected.trim()); } diff --git a/crates/oxc_isolated_declarations/tests/mod.rs b/crates/oxc_isolated_declarations/tests/mod.rs index 722caa1e50953..ad03f31c2c95c 100644 --- a/crates/oxc_isolated_declarations/tests/mod.rs +++ b/crates/oxc_isolated_declarations/tests/mod.rs @@ -4,7 +4,7 @@ use std::{fs, path::Path, sync::Arc}; use oxc_allocator::Allocator; use oxc_codegen::{CodeGenerator, CommentOptions}; -use oxc_isolated_declarations::IsolatedDeclarations; +use oxc_isolated_declarations::{IsolatedDeclarations, IsolatedDeclarationsOptions}; use oxc_parser::Parser; use oxc_span::SourceType; @@ -13,7 +13,13 @@ fn transform(path: &Path, source_text: &str) -> String { let source_type = SourceType::from_path(path).unwrap(); let parser_ret = Parser::new(&allocator, source_text, source_type).parse(); - let id_ret = IsolatedDeclarations::new(&allocator).build(&parser_ret.program); + let id_ret = IsolatedDeclarations::new( + &allocator, + source_text, + &parser_ret.trivias, + IsolatedDeclarationsOptions { strip_internal: true }, + ) + .build(&parser_ret.program); let code = CodeGenerator::new() .enable_comment( source_text, diff --git a/napi/transform/src/context.rs b/napi/transform/src/context.rs index 6a9f8247668c0..68b4500046486 100644 --- a/napi/transform/src/context.rs +++ b/napi/transform/src/context.rs @@ -11,7 +11,7 @@ use oxc_diagnostics::{Error, NamedSource, OxcDiagnostic}; use oxc_parser::{Parser, ParserReturn}; use oxc_span::SourceType; -use crate::TransformOptions; +use crate::{IsolatedDeclarationsOptions, TransformOptions}; #[must_use] pub(crate) struct TransformContext<'a> { @@ -27,7 +27,7 @@ pub(crate) struct TransformContext<'a> { /// Generate `.d.ts` files? /// /// Used by [`crate::transform`]. - declarations: bool, + declarations: Option, /// Path to the file being transformed. filename: &'a str, @@ -53,11 +53,8 @@ impl<'a> TransformContext<'a> { // Options that are added by this napi crates and don't exist in // oxc_transformer. let source_map = options.as_ref().and_then(|o| o.sourcemap).unwrap_or_default(); - let declarations = options - .as_ref() - .and_then(|o| o.typescript.as_ref()) - .and_then(|t| t.declaration) - .unwrap_or_default(); + let declarations = + options.as_ref().and_then(|o| o.typescript.as_ref()).and_then(|t| t.declaration); // Insert options into the cell if provided. Otherwise they will be // initialized to default when first accessed. @@ -103,8 +100,8 @@ impl<'a> TransformContext<'a> { } #[inline] - pub(crate) fn declarations(&self) -> bool { - self.declarations + pub(crate) fn declarations(&self) -> Option<&IsolatedDeclarationsOptions> { + self.declarations.as_ref() } #[inline] diff --git a/napi/transform/src/isolated_declaration.rs b/napi/transform/src/isolated_declaration.rs index 3ffb77a67cfd9..8a7a39ea36bf2 100644 --- a/napi/transform/src/isolated_declaration.rs +++ b/napi/transform/src/isolated_declaration.rs @@ -14,7 +14,16 @@ pub struct IsolatedDeclarationsResult { } #[napi(object)] +#[derive(Default, Clone, Copy)] pub struct IsolatedDeclarationsOptions { + /// Do not emit declarations for code that has an @internal annotation in its JSDoc comment. + /// This is an internal compiler option; use at your own risk, because the compiler does not check that the result is valid. + /// + /// Default: `false` + /// + /// See + pub strip_internal: Option, + pub sourcemap: bool, } @@ -35,7 +44,7 @@ pub fn isolated_declaration( source_type, Some(TransformOptions { sourcemap: Some(options.sourcemap), ..Default::default() }), ); - let transformed_ret = build_declarations(&ctx); + let transformed_ret = build_declarations(&ctx, options); IsolatedDeclarationsResult { code: transformed_ret.source_text, @@ -44,8 +53,19 @@ pub fn isolated_declaration( } } -pub(crate) fn build_declarations(ctx: &TransformContext<'_>) -> CodegenReturn { - let transformed_ret = IsolatedDeclarations::new(ctx.allocator).build(&ctx.program()); +pub(crate) fn build_declarations( + ctx: &TransformContext<'_>, + options: IsolatedDeclarationsOptions, +) -> CodegenReturn { + let transformed_ret = IsolatedDeclarations::new( + ctx.allocator, + ctx.source_text(), + &ctx.trivias, + oxc_isolated_declarations::IsolatedDeclarationsOptions { + strip_internal: options.strip_internal.unwrap_or(false), + }, + ) + .build(&ctx.program()); ctx.add_diagnostics(transformed_ret.errors); ctx.codegen() .enable_comment( diff --git a/napi/transform/src/options.rs b/napi/transform/src/options.rs index 8717836679e4b..bb6753610e1ae 100644 --- a/napi/transform/src/options.rs +++ b/napi/transform/src/options.rs @@ -7,6 +7,8 @@ use oxc_transformer::{ RewriteExtensionsMode, TypeScriptOptions, }; +use crate::IsolatedDeclarationsOptions; + #[napi(object)] #[derive(Default)] pub struct TypeScriptBindingOptions { @@ -22,7 +24,7 @@ pub struct TypeScriptBindingOptions { /// requirements. /// /// @default false - pub declaration: Option, + pub declaration: Option, /// Rewrite or remove TypeScript import/export declaration extensions. /// /// - When set to `rewrite`, it will change `.ts`, `.mts`, `.cts` extensions to `.js`, `.mjs`, `.cjs` respectively. diff --git a/napi/transform/src/transformer.rs b/napi/transform/src/transformer.rs index a3a0c84f8a1f7..a2925cf1af36d 100644 --- a/napi/transform/src/transformer.rs +++ b/napi/transform/src/transformer.rs @@ -80,9 +80,11 @@ pub fn transform( let allocator = Allocator::default(); let ctx = TransformContext::new(&allocator, &filename, &source_text, source_type, options); - let should_build_types = ctx.declarations() && source_type.is_typescript(); - let declarations_result = - should_build_types.then(|| isolated_declaration::build_declarations(&ctx)); + let declarations_result = source_type + .is_typescript() + .then(|| ctx.declarations()) + .flatten() + .map(|options| isolated_declaration::build_declarations(&ctx, *options)); let transpile_result = transpile(&ctx); diff --git a/tasks/benchmark/benches/isolated_declarations.rs b/tasks/benchmark/benches/isolated_declarations.rs index e4911c85a7b8f..3c44c84b563fd 100644 --- a/tasks/benchmark/benches/isolated_declarations.rs +++ b/tasks/benchmark/benches/isolated_declarations.rs @@ -1,6 +1,6 @@ use oxc_allocator::Allocator; use oxc_benchmark::{criterion_group, criterion_main, BenchmarkId, Criterion}; -use oxc_isolated_declarations::IsolatedDeclarations; +use oxc_isolated_declarations::{IsolatedDeclarations, IsolatedDeclarationsOptions}; use oxc_parser::{Parser, ParserReturn}; use oxc_span::SourceType; use oxc_tasks_common::TestFile; @@ -18,9 +18,15 @@ fn bench_isolated_declarations(criterion: &mut Criterion) { group.bench_with_input(id, &file.source_text, |b, source_text| { b.iter_with_large_drop(|| { let allocator = Allocator::default(); - let ParserReturn { program, .. } = + let ParserReturn { program, trivias, .. } = Parser::new(&allocator, source_text, source_type).parse(); - IsolatedDeclarations::new(&allocator).build(&program); + IsolatedDeclarations::new( + &allocator, + source_text, + &trivias, + IsolatedDeclarationsOptions { strip_internal: true }, + ) + .build(&program); }); }); diff --git a/tasks/coverage/src/typescript/transpile_runner.rs b/tasks/coverage/src/typescript/transpile_runner.rs index b399e3fa4ac12..06667c93fb512 100644 --- a/tasks/coverage/src/typescript/transpile_runner.rs +++ b/tasks/coverage/src/typescript/transpile_runner.rs @@ -3,8 +3,12 @@ use std::path::{Path, PathBuf}; use oxc::{ - allocator::Allocator, codegen::CodeGenerator, diagnostics::OxcDiagnostic, - isolated_declarations::IsolatedDeclarations, parser::Parser, span::SourceType, + allocator::Allocator, + codegen::CodeGenerator, + diagnostics::OxcDiagnostic, + isolated_declarations::{IsolatedDeclarations, IsolatedDeclarationsOptions}, + parser::Parser, + span::SourceType, }; use super::{ @@ -174,7 +178,13 @@ fn transpile(path: &Path, source_text: &str) -> (String, Vec) { let allocator = Allocator::default(); let source_type = SourceType::from_path(path).unwrap(); let ret = Parser::new(&allocator, source_text, source_type).parse(); - let ret = IsolatedDeclarations::new(&allocator).build(&ret.program); + let ret = IsolatedDeclarations::new( + &allocator, + source_text, + &ret.trivias, + IsolatedDeclarationsOptions { strip_internal: true }, + ) + .build(&ret.program); let printed = CodeGenerator::new().build(&ret.program).source_text; (printed, ret.errors) } From 1e624a2aaefaa94f857ea13569ff2268ba3c0ffd Mon Sep 17 00:00:00 2001 From: Dunqing Date: Thu, 19 Sep 2024 21:54:31 +0800 Subject: [PATCH 2/4] handle stripInternal option --- crates/oxc_isolated_declarations/src/class.rs | 17 +++- crates/oxc_isolated_declarations/src/lib.rs | 66 ++++++++++----- .../src/signatures.rs | 4 + .../tests/fixtures/strip-internal.ts | 82 +++++++++++++++++++ .../tests/snapshots/strip-internal.snap | 13 +++ 5 files changed, 161 insertions(+), 21 deletions(-) create mode 100644 crates/oxc_isolated_declarations/tests/fixtures/strip-internal.ts create mode 100644 crates/oxc_isolated_declarations/tests/snapshots/strip-internal.snap diff --git a/crates/oxc_isolated_declarations/src/class.rs b/crates/oxc_isolated_declarations/src/class.rs index 4a8a4f2d33e12..a1b70d82dd695 100644 --- a/crates/oxc_isolated_declarations/src/class.rs +++ b/crates/oxc_isolated_declarations/src/class.rs @@ -359,6 +359,10 @@ impl<'a> IsolatedDeclarations<'a> { match element { ClassElement::StaticBlock(_) => {} ClassElement::MethodDefinition(ref method) => { + if self.has_internal_annotation(method.span) { + continue; + } + if !(method.r#type.is_abstract() || method.optional) && method.value.body.is_none() { @@ -439,6 +443,10 @@ impl<'a> IsolatedDeclarations<'a> { elements.push(new_element); } ClassElement::PropertyDefinition(property) => { + if self.has_internal_annotation(property.span) { + continue; + } + if self.report_property_key(&property.key, property.computed) { continue; } @@ -450,6 +458,10 @@ impl<'a> IsolatedDeclarations<'a> { } } ClassElement::AccessorProperty(property) => { + if self.has_internal_annotation(property.span) { + continue; + } + if self.report_property_key(&property.key, property.computed) { return None; } @@ -476,7 +488,10 @@ impl<'a> IsolatedDeclarations<'a> { ); elements.push(new_element); } - ClassElement::TSIndexSignature(_) => elements.push({ + ClassElement::TSIndexSignature(signature) => elements.push({ + if self.has_internal_annotation(signature.span) { + continue; + } // SAFETY: `ast.copy` is unsound! We need to fix. unsafe { self.ast.copy(element) } }), diff --git a/crates/oxc_isolated_declarations/src/lib.rs b/crates/oxc_isolated_declarations/src/lib.rs index c6ce582a41d01..4a61ad075c538 100644 --- a/crates/oxc_isolated_declarations/src/lib.rs +++ b/crates/oxc_isolated_declarations/src/lib.rs @@ -26,7 +26,7 @@ use oxc_allocator::Allocator; #[allow(clippy::wildcard_imports)] use oxc_ast::{ast::*, AstBuilder, Trivias, Visit, NONE}; use oxc_diagnostics::OxcDiagnostic; -use oxc_span::{Atom, SourceType, SPAN}; +use oxc_span::{Atom, GetSpan, SourceType, SPAN}; use rustc_hash::{FxHashMap, FxHashSet}; use crate::scope::ScopeTree; @@ -51,8 +51,11 @@ pub struct IsolatedDeclarations<'a> { scope: ScopeTree<'a>, errors: RefCell>, - /// Start position of `@internal` jsdoc markers. - is_internal_set: Option>, + // options + strip_internal: bool, + + /// Start position of `@internal` jsdoc annotations. + internal_annotations: FxHashSet, } impl<'a> IsolatedDeclarations<'a> { @@ -62,11 +65,15 @@ impl<'a> IsolatedDeclarations<'a> { trivias: &Trivias, options: IsolatedDeclarationsOptions, ) -> Self { + let strip_internal = options.strip_internal; + let is_internal_set = strip_internal + .then(|| Self::build_internal_annotations(source_text, trivias)) + .unwrap_or_default(); + Self { ast: AstBuilder::new(allocator), - is_internal_set: options - .strip_internal - .then(|| Self::build_is_internal_set(source_text, trivias)), + strip_internal, + internal_annotations: is_internal_set, scope: ScopeTree::new(allocator), errors: RefCell::new(vec![]), } @@ -93,16 +100,10 @@ impl<'a> IsolatedDeclarations<'a> { } /// Build the lookup table for jsdoc `@internal`. - fn build_is_internal_set(source_text: &str, trivias: &Trivias) -> FxHashSet { + fn build_internal_annotations(source_text: &str, trivias: &Trivias) -> FxHashSet { let mut set = FxHashSet::default(); - for comment in trivias.comments().filter(|c| c.is_jsdoc(source_text)) { - let has_internal = comment - .span - .source_text(source_text) - .lines() - .filter_map(|s| s.trim_start().strip_prefix('*').map(str::trim_start)) - .filter_map(|s| s.split_whitespace().next()) - .any(|s| s == "@internal"); + for comment in trivias.comments() { + let has_internal = comment.span.source_text(source_text).contains("@internal"); // Use the first jsdoc comment if there are multiple jsdoc comments for the same node. if has_internal && !set.contains(&comment.attached_to) { set.insert(comment.attached_to); @@ -111,9 +112,12 @@ impl<'a> IsolatedDeclarations<'a> { set } - #[allow(unused)] - fn is_internal(&self, span: Span) -> bool { - self.is_internal_set.as_ref().map_or(false, |set| set.contains(&span.start)) + /// Check if the node has an `@internal` annotation. + fn has_internal_annotation(&self, span: Span) -> bool { + if !self.strip_internal { + return false; + } + self.internal_annotations.contains(&span.start) } } @@ -148,6 +152,9 @@ impl<'a> IsolatedDeclarations<'a> { for stmt in Self::remove_function_overloads_implementation(unsafe { self.ast.copy(stmts) }) { if let Some(decl) = stmt.as_declaration() { + if self.has_internal_annotation(decl.span()) { + continue; + } if let Some(decl) = self.transform_declaration(decl, false) { new_ast_stmts.push(Statement::from(decl)); } else { @@ -182,6 +189,9 @@ impl<'a> IsolatedDeclarations<'a> { match_declaration!(Statement) => { match stmt.to_declaration() { Declaration::VariableDeclaration(decl) => { + if self.has_internal_annotation(decl.span) { + continue; + } variables_declarations.push_back( // SAFETY: `ast.copy` is unsound! We need to fix. unsafe { self.ast.copy(&decl.declarations) } @@ -191,6 +201,9 @@ impl<'a> IsolatedDeclarations<'a> { variable_transformed_indexes.push_back(FxHashSet::default()); } Declaration::TSModuleDeclaration(decl) => { + if self.has_internal_annotation(decl.span) { + continue; + } // declare global { ... } or declare module "foo" { ... } // We need to emit it anyway if decl.kind.is_global() || decl.id.is_string_literal() { @@ -201,11 +214,16 @@ impl<'a> IsolatedDeclarations<'a> { } _ => {} } - new_stmts.push(stmt); + if !self.has_internal_annotation(stmt.span()) { + new_stmts.push(stmt); + } } match_module_declaration!(Statement) => { match stmt.to_module_declaration() { ModuleDeclaration::ExportDefaultDeclaration(decl) => { + if self.has_internal_annotation(decl.span) { + continue; + } transformed_indexes.insert(new_stmts.len()); if let Some((var_decl, new_decl)) = self.transform_export_default_declaration(decl) @@ -231,6 +249,9 @@ impl<'a> IsolatedDeclarations<'a> { } ModuleDeclaration::ExportNamedDeclaration(decl) => { + if self.has_internal_annotation(decl.span) { + continue; + } transformed_indexes.insert(new_stmts.len()); if let Some(new_decl) = self.transform_export_named_declaration(decl) { self.scope.visit_declaration( @@ -249,12 +270,17 @@ impl<'a> IsolatedDeclarations<'a> { // We must transform this in the end, because we need to know all references } module_declaration => { + if self.has_internal_annotation(module_declaration.span()) { + continue; + } transformed_indexes.insert(new_stmts.len()); self.scope.visit_module_declaration(module_declaration); } } - new_stmts.push(stmt); + if !self.has_internal_annotation(stmt.span()) { + new_stmts.push(stmt); + } } _ => {} } diff --git a/crates/oxc_isolated_declarations/src/signatures.rs b/crates/oxc_isolated_declarations/src/signatures.rs index bd7d6a61e057b..bb3a29a36f85e 100644 --- a/crates/oxc_isolated_declarations/src/signatures.rs +++ b/crates/oxc_isolated_declarations/src/signatures.rs @@ -1,5 +1,6 @@ use oxc_allocator::{CloneIn, Vec}; use oxc_ast::ast::{TSMethodSignatureKind, TSSignature}; +use oxc_span::GetSpan; use rustc_hash::FxHashMap; use crate::IsolatedDeclarations; @@ -13,6 +14,9 @@ impl<'a> IsolatedDeclarations<'a> { // let mut method_annotations: FxHashMap<_, (bool, _, _)> = FxHashMap::default(); + // Strip internal signatures + signatures.retain(|signature| !self.has_internal_annotation(signature.span())); + signatures.iter_mut().for_each(|signature| { if let TSSignature::TSMethodSignature(method) = signature { let Some(name) = method.key.static_name() else { diff --git a/crates/oxc_isolated_declarations/tests/fixtures/strip-internal.ts b/crates/oxc_isolated_declarations/tests/fixtures/strip-internal.ts new file mode 100644 index 0000000000000..89430bd222bc7 --- /dev/null +++ b/crates/oxc_isolated_declarations/tests/fixtures/strip-internal.ts @@ -0,0 +1,82 @@ +/* +@internal +*/ +class StripInternalClass { + public test() { + console.log("test"); + } +} + +class StripInternalClassFields { + /** + * @internal + */ + internalProperty: string = "internal"; + + // @internal + internalMethod(): void {} +} + +/** +@internal +*/ +function stripInternalFunction() { + console.log("test"); +} + +export { stripInternalFunction, StripInternalClass, StripInternalClassFields }; + +/** +@internal +*/ +export function stripInternalExportedFunction() { + console.log("test"); +} + +/** +@internal*/ +export const stripInternalExportedConst = "test"; + +/** +@internal*/ +export interface StripInternalExportedInterface {} + +export interface StripInternalInterfaceSignatures { + /** + * @internal + */ + internalMethod(): void; + /** + * @internal + */ + internalProperty: number; + /**@internal */ + new (): any; +} + +export type StripInternalTypeSignatures = { + /** + * @internal + */ + internalMethod(): void; + /** + * @internal + */ + internalProperty: number; + /**@internal */ + new (): any; +}; + +export namespace StripInternalNamespaceInner { + /** + * @internal + */ + export function internalFunction() { + console.log("test"); + } +} + +/** + * @internal + */ +export namespace StripInternalNamespace {} \ No newline at end of file diff --git a/crates/oxc_isolated_declarations/tests/snapshots/strip-internal.snap b/crates/oxc_isolated_declarations/tests/snapshots/strip-internal.snap new file mode 100644 index 0000000000000..2814f9fc5b5d6 --- /dev/null +++ b/crates/oxc_isolated_declarations/tests/snapshots/strip-internal.snap @@ -0,0 +1,13 @@ +--- +source: crates/oxc_isolated_declarations/tests/mod.rs +input_file: crates/oxc_isolated_declarations/tests/fixtures/strip-internal.ts +--- +==================== .D.TS ==================== + +declare class StripInternalClassFields {} +export { stripInternalFunction, StripInternalClass, StripInternalClassFields }; +export interface StripInternalInterfaceSignatures {} +export type StripInternalTypeSignatures = {}; +export declare namespace StripInternalNamespaceInner { + export {}; +} From 737ff480d2cbd8e7ec4a826f3aa3b1ccd42b7f4a Mon Sep 17 00:00:00 2001 From: Dunqing Date: Thu, 19 Sep 2024 22:42:10 +0800 Subject: [PATCH 3/4] fix napi build --- napi/transform/index.d.ts | 11 ++++++++++- napi/transform/src/isolated_declaration.rs | 3 +-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/napi/transform/index.d.ts b/napi/transform/index.d.ts index 0cd6dd00d7761..8a753918e9c6a 100644 --- a/napi/transform/index.d.ts +++ b/napi/transform/index.d.ts @@ -21,6 +21,15 @@ export interface Es2015BindingOptions { export declare function isolatedDeclaration(filename: string, sourceText: string, options?: IsolatedDeclarationsOptions | undefined | null): IsolatedDeclarationsResult export interface IsolatedDeclarationsOptions { + /** + * Do not emit declarations for code that has an @internal annotation in its JSDoc comment. + * This is an internal compiler option; use at your own risk, because the compiler does not check that the result is valid. + * + * Default: `false` + * + * See + */ + stripInternal?: boolean sourcemap?: boolean } @@ -249,7 +258,7 @@ export interface TypeScriptBindingOptions { * * @default false */ - declaration?: boolean + declaration?: IsolatedDeclarationsOptions /** * Rewrite or remove TypeScript import/export declaration extensions. * diff --git a/napi/transform/src/isolated_declaration.rs b/napi/transform/src/isolated_declaration.rs index a52f1c6155f37..33fe30e0c3285 100644 --- a/napi/transform/src/isolated_declaration.rs +++ b/napi/transform/src/isolated_declaration.rs @@ -13,9 +13,8 @@ pub struct IsolatedDeclarationsResult { pub errors: Vec, } -#[derive(Debug, Default)] #[napi(object)] -#[derive(Default, Clone, Copy)] +#[derive(Debug, Default, Clone, Copy)] pub struct IsolatedDeclarationsOptions { /// Do not emit declarations for code that has an @internal annotation in its JSDoc comment. /// This is an internal compiler option; use at your own risk, because the compiler does not check that the result is valid. From c2d2749c010421e3569f04f57612edbd0dacfca8 Mon Sep 17 00:00:00 2001 From: Dunqing Date: Thu, 19 Sep 2024 22:50:10 +0800 Subject: [PATCH 4/4] Update --- crates/oxc_isolated_declarations/src/lib.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/oxc_isolated_declarations/src/lib.rs b/crates/oxc_isolated_declarations/src/lib.rs index 4a61ad075c538..80d62e068e2fd 100644 --- a/crates/oxc_isolated_declarations/src/lib.rs +++ b/crates/oxc_isolated_declarations/src/lib.rs @@ -278,9 +278,7 @@ impl<'a> IsolatedDeclarations<'a> { } } - if !self.has_internal_annotation(stmt.span()) { - new_stmts.push(stmt); - } + new_stmts.push(stmt); } _ => {} }