Skip to content

Commit

Permalink
✨ feat: Add importsNotUsedAsValues
Browse files Browse the repository at this point in the history
  • Loading branch information
caoccao committed Mar 10, 2024
1 parent c038b26 commit 1e2edc8
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 6 deletions.
1 change: 0 additions & 1 deletion rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,4 @@ crate_type = ["cdylib", "rlib"]
[dependencies]
debug_print = "1.0.0"
deno_ast = { version = "1.0.1", features = ["module_specifier", "transpiling", "transforms"] }
deno_media_type = "0.1.2"
jni = "0.21.1"
12 changes: 11 additions & 1 deletion rust/src/converter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,17 @@ use jni::objects::JString;
use jni::sys::{jboolean, jstring};
use jni::JNIEnv;

use deno_media_type::MediaType;
use deno_ast::{ImportsNotUsedAsValues, MediaType};

pub fn imports_not_used_as_values_id_to_imports_not_used_as_values(
imports_not_used_as_values_id: i32,
) -> ImportsNotUsedAsValues {
match imports_not_used_as_values_id {
1 => ImportsNotUsedAsValues::Remove,
2 => ImportsNotUsedAsValues::Preserve,
_ => ImportsNotUsedAsValues::Error,
}
}

pub fn jboolean_to_bool(b: jboolean) -> bool {
b != 0
Expand Down
71 changes: 68 additions & 3 deletions rust/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,45 @@ use jni::objects::{GlobalRef, JMethodID, JObject};
use jni::sys::jobject;
use jni::JNIEnv;

use deno_ast::MediaType;
use deno_ast::{ImportsNotUsedAsValues, MediaType};

use crate::{converter, jni_utils};

struct JavaImportsNotUsedAsValues {
#[allow(dead_code)]
class: GlobalRef,
method_get_id: JMethodID,
}
unsafe impl Send for JavaImportsNotUsedAsValues {}
unsafe impl Sync for JavaImportsNotUsedAsValues {}

impl JavaImportsNotUsedAsValues {
pub fn new<'local>(env: &mut JNIEnv<'local>) -> Self {
let class = env
.find_class("com/caoccao/javet/swc4j/enums/Swc4jImportsNotUsedAsValues")
.expect("Couldn't find class Swc4jImportsNotUsedAsValues");
let class = env
.new_global_ref(class)
.expect("Couldn't globalize class Swc4jImportsNotUsedAsValues");
let method_get_id = env
.get_method_id(&class, "getId", "()I")
.expect("Couldn't find method Swc4jImportsNotUsedAsValues.getId");
JavaImportsNotUsedAsValues { class, method_get_id }
}

pub fn get_imports_not_used_as_values<'local, 'a>(
&self,
env: &mut JNIEnv<'local>,
obj: &JObject<'a>,
) -> ImportsNotUsedAsValues {
converter::imports_not_used_as_values_id_to_imports_not_used_as_values(jni_utils::get_as_int(
env,
obj.as_ref(),
self.method_get_id,
))
}
}

struct JavaMediaType {
#[allow(dead_code)]
class: GlobalRef,
Expand Down Expand Up @@ -53,6 +88,7 @@ impl JavaMediaType {
struct JavaTranspileOptions {
#[allow(dead_code)]
class: GlobalRef,
method_get_imports_not_used_as_values: JMethodID,
method_get_media_type: JMethodID,
method_get_specifier: JMethodID,
method_get_jsx_factory: JMethodID,
Expand All @@ -79,6 +115,13 @@ impl JavaTranspileOptions {
let class = env
.new_global_ref(class)
.expect("Couldn't globalize class Swc4jTranspileOptions");
let method_get_imports_not_used_as_values = env
.get_method_id(
&class,
"getImportsNotUsedAsValues",
"()Lcom/caoccao/javet/swc4j/enums/Swc4jImportsNotUsedAsValues;",
)
.expect("Couldn't find method Swc4jTranspileOptions.getImportsNotUsedAsValues");
let method_get_media_type = env
.get_method_id(
&class,
Expand Down Expand Up @@ -127,6 +170,7 @@ impl JavaTranspileOptions {
.expect("Couldn't find method Swc4jTranspileOptions.isVarDeclImports");
JavaTranspileOptions {
class,
method_get_imports_not_used_as_values,
method_get_media_type,
method_get_specifier,
method_get_jsx_factory,
Expand All @@ -144,6 +188,14 @@ impl JavaTranspileOptions {
}
}

pub fn get_imports_not_used_as_values<'local, 'a, 'b>(
&self,
env: &mut JNIEnv<'local>,
obj: &JObject<'a>,
) -> JObject<'b> {
jni_utils::get_as_jobject(env, obj, self.method_get_imports_not_used_as_values)
}

pub fn get_jsx_factory<'local, 'a>(&self, env: &mut JNIEnv<'local>, obj: &JObject<'a>) -> String {
jni_utils::get_as_string(env, obj, self.method_get_jsx_factory)
}
Expand Down Expand Up @@ -201,11 +253,13 @@ impl JavaTranspileOptions {
}
}

static mut JAVA_IMPORTS_NOT_USED_AS_VALUES: Option<JavaImportsNotUsedAsValues> = None;
static mut JAVA_MEDIA_TYPE: Option<JavaMediaType> = None;
static mut JAVA_TRANSPILER_OPTIONS: Option<JavaTranspileOptions> = None;

pub fn init<'local>(env: &mut JNIEnv<'local>) {
unsafe {
JAVA_IMPORTS_NOT_USED_AS_VALUES = Some(JavaImportsNotUsedAsValues::new(env));
JAVA_MEDIA_TYPE = Some(JavaMediaType::new(env));
JAVA_TRANSPILER_OPTIONS = Some(JavaTranspileOptions::new(env));
}
Expand All @@ -220,6 +274,10 @@ pub struct TranspileOptions {
/// When emitting a legacy decorator, also emit experimental decorator meta
/// data. Defaults to `false`.
pub emit_metadata: bool,
/// What to do with import statements that only import types i.e. whether to
/// remove them (`Remove`), keep them as side-effect imports (`Preserve`)
/// or error (`Error`). Defaults to `Remove`.
pub imports_not_used_as_values: ImportsNotUsedAsValues,
/// Should the source map be inlined in the emitted code file, or provided
/// as a separate file. Defaults to `true`.
pub inline_source_map: bool,
Expand Down Expand Up @@ -265,6 +323,7 @@ impl Default for TranspileOptions {
fn default() -> Self {
TranspileOptions {
emit_metadata: false,
imports_not_used_as_values: ImportsNotUsedAsValues::Remove,
inline_source_map: true,
inline_sources: true,
jsx_automatic: false,
Expand All @@ -286,8 +345,14 @@ impl FromJniType for TranspileOptions {
fn from_jni_type<'local>(env: &mut JNIEnv<'local>, obj: jobject) -> TranspileOptions {
let obj = unsafe { JObject::from_raw(obj) };
let obj = obj.as_ref();
let java_imports_not_used_as_values = unsafe { JAVA_IMPORTS_NOT_USED_AS_VALUES.as_ref().unwrap() };
let java_media_type = unsafe { JAVA_MEDIA_TYPE.as_ref().unwrap() };
let java_transpiler_options = unsafe { JAVA_TRANSPILER_OPTIONS.as_ref().unwrap() };
let emit_metadata = java_transpiler_options.is_emit_metadata(env, obj);
let imports_not_used_as_values = java_transpiler_options.get_imports_not_used_as_values(env, obj);
let imports_not_used_as_values = imports_not_used_as_values.as_ref();
let imports_not_used_as_values =
java_imports_not_used_as_values.get_imports_not_used_as_values(env, imports_not_used_as_values);
let inline_source_map = java_transpiler_options.is_inline_source_map(env, obj);
let inline_sources = java_transpiler_options.is_inline_sources(env, obj);
let jsx_automatic = java_transpiler_options.is_jsx_automatic(env, obj);
Expand All @@ -297,15 +362,15 @@ impl FromJniType for TranspileOptions {
let jsx_import_source = java_transpiler_options.get_jsx_import_source(env, obj);
let media_type = java_transpiler_options.get_media_type(env, obj);
let media_type = media_type.as_ref();
let java_media_type = unsafe { JAVA_MEDIA_TYPE.as_ref().unwrap() };
let media_type = java_media_type.get_media_type(env, media_type);
let source_map = java_transpiler_options.is_source_map(env, obj);
let specifier = java_transpiler_options.get_specifier(env, obj);
let transform_jsx = java_transpiler_options.is_transform_jsx(env, obj);
let precompile_jsx = java_transpiler_options.is_precompile_jsx(env, obj);
let var_decl_imports =java_transpiler_options.is_var_decl_imports(env, obj);
let var_decl_imports = java_transpiler_options.is_var_decl_imports(env, obj);
TranspileOptions {
emit_metadata,
imports_not_used_as_values,
inline_source_map,
inline_sources,
jsx_automatic,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2024. caoccao.com Sam Cao
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.caoccao.javet.swc4j.enums;

import java.util.stream.Stream;

/**
* What to do with import statements that only import types i.e. whether to
* remove them (`Remove`), keep them as side-effect imports (`Preserve`)
* or error (`Error`). Defaults to `Remove`.
*
* @since 0.1.0
*/
public enum Swc4jImportsNotUsedAsValues {
Remove(0),
Preserve(1),
Error(2);

private static final int LENGTH = 3;
private static final Swc4jImportsNotUsedAsValues[] TYPES = new Swc4jImportsNotUsedAsValues[LENGTH];

static {
Stream.of(values()).forEach(v -> TYPES[v.getId()] = v);
}

private final int id;

Swc4jImportsNotUsedAsValues(int id) {
this.id = id;
}

/**
* Parse swc4j imports not used as values.
*
* @param id the id
* @return the swc4j media type
* @since 0.1.0
*/
public static Swc4jImportsNotUsedAsValues parse(int id) {
return id >= 0 && id < LENGTH ? TYPES[id] : Remove;
}

/**
* Gets id.
*
* @return the id
* @since 0.1.0
*/
public int getId() {
return id;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.caoccao.javet.swc4j.options;

import com.caoccao.javet.swc4j.enums.Swc4jImportsNotUsedAsValues;
import com.caoccao.javet.swc4j.enums.Swc4jMediaType;
import com.caoccao.javet.swc4j.utils.AssertionUtils;

Expand Down Expand Up @@ -44,6 +45,7 @@ public final class Swc4jTranspileOptions {
*/
public static final String DEFAULT_JSX_FRAGMENT_FACTORY = "React.Fragment";
private boolean emitMetadata;
private Swc4jImportsNotUsedAsValues importsNotUsedAsValues;
private boolean inlineSourceMap;
private boolean inlineSources;
private boolean jsxAutomatic;
Expand All @@ -65,6 +67,7 @@ public final class Swc4jTranspileOptions {
*/
public Swc4jTranspileOptions() {
setEmitMetadata(false);
setImportsNotUsedAsValues(Swc4jImportsNotUsedAsValues.Remove);
setJsxAutomatic(false);
setJsxDevelopment(false);
setJsxFactory(DEFAULT_JSX_FACTORY);
Expand All @@ -80,6 +83,18 @@ public Swc4jTranspileOptions() {
setVarDeclImports(false);
}

/**
* What to do with import statements that only import types i.e. whether to
* remove them (`Remove`), keep them as side-effect imports (`Preserve`)
* or error (`Error`). Defaults to `Remove`.
*
* @return the imports not used as values
* @since 0.1.0
*/
public Swc4jImportsNotUsedAsValues getImportsNotUsedAsValues() {
return importsNotUsedAsValues;
}

/**
* When transforming JSX, what value should be used for the JSX factory.
* Defaults to `React.createElement`.
Expand Down Expand Up @@ -242,6 +257,18 @@ public Swc4jTranspileOptions setEmitMetadata(boolean emitMetadata) {
return this;
}

/**
* Sets imports not used as values.
*
* @param importsNotUsedAsValues the imports not used as values
* @return the self
* @since 0.1.0
*/
public Swc4jTranspileOptions setImportsNotUsedAsValues(Swc4jImportsNotUsedAsValues importsNotUsedAsValues) {
this.importsNotUsedAsValues = AssertionUtils.notNull(importsNotUsedAsValues, "Imports not used as values");
return this;
}

/**
* Sets inline source map.
*
Expand Down

0 comments on commit 1e2edc8

Please sign in to comment.