Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(isolated_declarations): add stripInternal #5878

Merged
merged 6 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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,
Expand Down
17 changes: 16 additions & 1 deletion crates/oxc_isolated_declarations/src/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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) }
}),
Expand Down
76 changes: 72 additions & 4 deletions crates/oxc_isolated_declarations/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,29 +24,56 @@ 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 oxc_span::{Atom, GetSpan, 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.
/// <https://www.typescriptlang.org/tsconfig/#stripInternal>
pub strip_internal: bool,
}

pub struct IsolatedDeclarationsReturn<'a> {
pub program: Program<'a>,
pub errors: Vec<OxcDiagnostic>,
}

pub struct IsolatedDeclarations<'a> {
ast: AstBuilder<'a>,

// state
scope: ScopeTree<'a>,
errors: RefCell<Vec<OxcDiagnostic>>,

// options
strip_internal: bool,

/// Start position of `@internal` jsdoc annotations.
internal_annotations: FxHashSet<u32>,
}

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 {
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),
strip_internal,
internal_annotations: is_internal_set,
scope: ScopeTree::new(allocator),
errors: RefCell::new(vec![]),
}
Expand All @@ -71,6 +98,27 @@ impl<'a> IsolatedDeclarations<'a> {
fn error(&self, error: OxcDiagnostic) {
self.errors.borrow_mut().push(error);
}

/// Build the lookup table for jsdoc `@internal`.
fn build_internal_annotations(source_text: &str, trivias: &Trivias) -> FxHashSet<u32> {
let mut set = FxHashSet::default();
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);
}
}
set
}

/// 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)
}
}

impl<'a> IsolatedDeclarations<'a> {
Expand Down Expand Up @@ -104,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 {
Expand Down Expand Up @@ -138,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) }
Expand All @@ -147,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() {
Expand All @@ -157,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)
Expand All @@ -187,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(
Expand All @@ -205,6 +270,9 @@ 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);
}
Expand Down
4 changes: 4 additions & 0 deletions crates/oxc_isolated_declarations/src/signatures.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -13,6 +14,9 @@ impl<'a> IsolatedDeclarations<'a> {
// <name, (requires_inference, first_param_annotation, return_type)>
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 {
Expand Down
14 changes: 9 additions & 5 deletions crates/oxc_isolated_declarations/tests/deno/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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 {}
10 changes: 8 additions & 2 deletions crates/oxc_isolated_declarations/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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,
Expand Down
Original file line number Diff line number Diff line change
@@ -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 {};
}
Loading