From 7f49688157d32cb9a8a49c8acc363ffc81422bb1 Mon Sep 17 00:00:00 2001 From: Sam Cao Date: Fri, 8 Mar 2024 12:23:43 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20Add=20TranspileOptions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rust/src/core.rs | 16 ++-- rust/src/lib.rs | 22 +++--- rust/src/options.rs | 76 +++++++++++++++++++ rust/tests/{test_version.rs => test_core.rs} | 6 +- .../java/com/caoccao/javet/swc4j/Swc4j.java | 4 +- .../com/caoccao/javet/swc4j/Swc4jNative.java | 5 +- .../javet/swc4j/enums/Swc4jMediaType.java | 31 ++++++++ .../swc4j/options/Swc4jTranspileOptions.java | 8 +- .../swc4j/outputs/Swc4jTranspileOutput.java | 18 ++--- .../javet/swc4j/utils/AssertionUtils.java | 36 +++++++++ 10 files changed, 182 insertions(+), 40 deletions(-) create mode 100644 rust/src/options.rs rename rust/tests/{test_version.rs => test_core.rs} (88%) create mode 100644 src/main/java/com/caoccao/javet/swc4j/utils/AssertionUtils.java diff --git a/rust/src/core.rs b/rust/src/core.rs index e2c2df25..cd987aa7 100644 --- a/rust/src/core.rs +++ b/rust/src/core.rs @@ -17,17 +17,19 @@ use deno_ast::*; -pub const VERSION: &'static str = "0.1.0"; +use crate::options; -pub fn transpile<'local>(code: String, media_type: MediaType, file_name: String) { - let url = ModuleSpecifier::parse(&format!("file:///{}", file_name)).unwrap(); +const VERSION: &'static str = "0.1.0"; + +pub fn transpile<'local>(code: String, options: options::TranspileOptions) { + let url = ModuleSpecifier::parse(&format!("file:///{}", options.file_name)).unwrap(); println!("url: {}", url.to_string()); println!("source: {}", code.to_string()); - println!("media_type: {}", media_type.to_string()); + println!("media_type: {}", options.media_type.to_string()); let parsed_source = parse_module(ParseParams { specifier: url.to_string(), text_info: SourceTextInfo::from_string(code.to_string()), - media_type: media_type, + media_type: options.media_type, capture_tokens: false, maybe_syntax: None, scope_analysis: false, @@ -39,6 +41,6 @@ pub fn transpile<'local>(code: String, media_type: MediaType, file_name: String) println!("{}", transpiled_js_code.text); } -pub fn get_version<'local>() -> String { - VERSION.to_string() +pub fn get_version<'local>() -> &'local str { + VERSION } diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 02cd4cde..76f13776 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -15,23 +15,23 @@ * limitations under the License. */ -use jni::objects::JClass; -use jni::sys::{jint, jobject, jstring}; use jni::JNIEnv; +use jni::objects::JClass; +use jni::sys::{jobject, jstring}; +use options::FromJniType; use std::ptr::null_mut; -mod core; -mod utils; - -pub use core::VERSION; +pub mod core; +pub mod options; +pub mod utils; #[no_mangle] pub extern "system" fn Java_com_caoccao_javet_swc4j_Swc4jNative_coreGetVersion<'local>( env: JNIEnv<'local>, _: JClass<'local>, ) -> jstring { - utils::converter::string_to_jstring(&env, core::get_version().as_str()) + utils::converter::string_to_jstring(&env, core::get_version()) } #[no_mangle] @@ -39,12 +39,10 @@ pub extern "system" fn Java_com_caoccao_javet_swc4j_Swc4jNative_coreTranspile<'l mut env: JNIEnv<'local>, _: JClass<'local>, code: jstring, - media_type_id: jint, - file_name: jstring, + options: jobject, ) -> jobject { let code = utils::converter::jstring_to_string(&mut env, code); - let file_name = utils::converter::jstring_to_string(&mut env, file_name); - let media_type = utils::converter::media_type_id_to_media_type(media_type_id); - core::transpile(code, media_type, file_name); + let options = options::TranspileOptions::from_jni_type(&mut env, options); + core::transpile(code, options); null_mut() } diff --git a/rust/src/options.rs b/rust/src/options.rs new file mode 100644 index 00000000..d1036885 --- /dev/null +++ b/rust/src/options.rs @@ -0,0 +1,76 @@ +/* +* Copyright (c) 2024. caoccao.com Sam Cao +* All rights reserved. + +* 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. +*/ + +use jni::objects::JObject; +use jni::sys::jobject; +use jni::JNIEnv; + +use deno_ast::MediaType; + +use crate::utils; + +const METHOD_TRANSPILE_OPTIONS_GET_FILE_NAME: &'static str = "getFileName"; +const SIG_TRANSPILE_OPTIONS_GET_FILE_NAME: &'static str = "()Ljava/lang/String;"; + +const METHOD_TRANSPILE_OPTIONS_GET_MEDIA_TYPE: &'static str = "getMediaType"; +const SIG_TRANSPILE_OPTIONS_GET_MEDIA_TYPE: &'static str = "()Lcom/caoccao/javet/swc4j/enums/Swc4jMediaType;"; + +const METHOD_MEDIA_TYPE_GET_ID: &'static str = "getId"; +const SIG_MEDIA_TYPE_GET_ID: &'static str = "()I"; + +pub trait FromJniType { + fn from_jni_type<'local>(env: &mut JNIEnv<'local>, o: jobject) -> Self; +} + +#[derive(Debug)] +pub struct TranspileOptions { + pub file_name: String, + pub media_type: MediaType, +} + +impl FromJniType for TranspileOptions { + fn from_jni_type<'local>(env: &mut JNIEnv<'local>, o: jobject) -> TranspileOptions { + let o = unsafe { JObject::from_raw(o) }; + // file_name + let file_name = env.call_method( + o.as_ref(), + METHOD_TRANSPILE_OPTIONS_GET_FILE_NAME, + SIG_TRANSPILE_OPTIONS_GET_FILE_NAME, + &[], + ); + let file_name = unsafe { file_name.unwrap().as_jni().l }; + let file_name = utils::converter::jstring_to_string(env, file_name); + // media_type + let media_type = env.call_method( + o.as_ref(), + METHOD_TRANSPILE_OPTIONS_GET_MEDIA_TYPE, + SIG_TRANSPILE_OPTIONS_GET_MEDIA_TYPE, + &[], + ); + let media_type = unsafe { JObject::from_raw(media_type.unwrap().as_jni().l) }; + let media_type = env.call_method( + media_type.as_ref(), + METHOD_MEDIA_TYPE_GET_ID, + SIG_MEDIA_TYPE_GET_ID, + &[], + ); + let media_type = unsafe { media_type.unwrap().as_jni().i }; + let media_type = utils::converter::media_type_id_to_media_type(media_type); + // construct + TranspileOptions { file_name, media_type } + } +} diff --git a/rust/tests/test_version.rs b/rust/tests/test_core.rs similarity index 88% rename from rust/tests/test_version.rs rename to rust/tests/test_core.rs index 63da9cab..117ac779 100644 --- a/rust/tests/test_version.rs +++ b/rust/tests/test_core.rs @@ -15,9 +15,9 @@ * limitations under the License. */ -use swc4j::*; +use swc4j::core::*; #[test] -fn test_version() { - assert_eq!(VERSION, "0.1.0"); +fn test_get_version() { + assert_eq!(get_version(), "0.1.0"); } \ No newline at end of file diff --git a/src/main/java/com/caoccao/javet/swc4j/Swc4j.java b/src/main/java/com/caoccao/javet/swc4j/Swc4j.java index aefdacee..8aad61e5 100644 --- a/src/main/java/com/caoccao/javet/swc4j/Swc4j.java +++ b/src/main/java/com/caoccao/javet/swc4j/Swc4j.java @@ -19,6 +19,7 @@ import com.caoccao.javet.swc4j.exceptions.Swc4jCoreException; import com.caoccao.javet.swc4j.options.Swc4jTranspileOptions; import com.caoccao.javet.swc4j.outputs.Swc4jTranspileOutput; +import com.caoccao.javet.swc4j.utils.AssertionUtils; /** * The type Swc4j. @@ -57,7 +58,6 @@ public Swc4jTranspileOutput transpile(String code) throws Swc4jCoreException { public Swc4jTranspileOutput transpile(String code, Swc4jTranspileOptions options) throws Swc4jCoreException { return (Swc4jTranspileOutput) Swc4jNative.coreTranspile( code, - options.getMediaType().getId(), - options.getFileName()); + AssertionUtils.notNull(options, "Options")); } } diff --git a/src/main/java/com/caoccao/javet/swc4j/Swc4jNative.java b/src/main/java/com/caoccao/javet/swc4j/Swc4jNative.java index d3a875de..bb6432d6 100644 --- a/src/main/java/com/caoccao/javet/swc4j/Swc4jNative.java +++ b/src/main/java/com/caoccao/javet/swc4j/Swc4jNative.java @@ -23,8 +23,5 @@ private Swc4jNative() { static native String coreGetVersion(); - static native Object coreTranspile( - String code, - int mediaTypeId, - String fileName); + static native Object coreTranspile(String code, Object options); } diff --git a/src/main/java/com/caoccao/javet/swc4j/enums/Swc4jMediaType.java b/src/main/java/com/caoccao/javet/swc4j/enums/Swc4jMediaType.java index e5637ed7..411566d2 100644 --- a/src/main/java/com/caoccao/javet/swc4j/enums/Swc4jMediaType.java +++ b/src/main/java/com/caoccao/javet/swc4j/enums/Swc4jMediaType.java @@ -16,6 +16,13 @@ package com.caoccao.javet.swc4j.enums; +import java.util.stream.Stream; + +/** + * The enum Swc4j media type. + * + * @since 0.1.0 + */ public enum Swc4jMediaType { JavaScript(0), Jsx(1), @@ -34,12 +41,36 @@ public enum Swc4jMediaType { SourceMap(14), Unknown(15); + private static final int LENGTH = 16; + private static final Swc4jMediaType[] TYPES = new Swc4jMediaType[LENGTH]; + + static { + Stream.of(values()).forEach(v -> TYPES[v.getId()] = v); + } + private final int id; Swc4jMediaType(int id) { this.id = id; } + /** + * Parse swc4j media type. + * + * @param id the id + * @return the swc4j media type + * @since 0.1.0 + */ + public static Swc4jMediaType parse(int id) { + return id >= 0 && id < LENGTH ? TYPES[id] : Unknown; + } + + /** + * Gets id. + * + * @return the id + * @since 0.1.0 + */ public int getId() { return id; } diff --git a/src/main/java/com/caoccao/javet/swc4j/options/Swc4jTranspileOptions.java b/src/main/java/com/caoccao/javet/swc4j/options/Swc4jTranspileOptions.java index 748197b4..51ba619c 100644 --- a/src/main/java/com/caoccao/javet/swc4j/options/Swc4jTranspileOptions.java +++ b/src/main/java/com/caoccao/javet/swc4j/options/Swc4jTranspileOptions.java @@ -17,13 +17,15 @@ package com.caoccao.javet.swc4j.options; import com.caoccao.javet.swc4j.enums.Swc4jMediaType; +import com.caoccao.javet.swc4j.utils.AssertionUtils; public final class Swc4jTranspileOptions { + public static final String DEFAULT_FILE_NAME = "main.js"; private String fileName; private Swc4jMediaType mediaType; public Swc4jTranspileOptions() { - setFileName(null); + setFileName(DEFAULT_FILE_NAME); setMediaType(Swc4jMediaType.JavaScript); } @@ -36,12 +38,12 @@ public Swc4jMediaType getMediaType() { } public Swc4jTranspileOptions setFileName(String fileName) { - this.fileName = fileName; + this.fileName = AssertionUtils.notNull(fileName, "File name"); return this; } public Swc4jTranspileOptions setMediaType(Swc4jMediaType mediaType) { - this.mediaType = mediaType; + this.mediaType = AssertionUtils.notNull(mediaType, "Media type"); return this; } } diff --git a/src/main/java/com/caoccao/javet/swc4j/outputs/Swc4jTranspileOutput.java b/src/main/java/com/caoccao/javet/swc4j/outputs/Swc4jTranspileOutput.java index 62ba7396..dd45fddd 100644 --- a/src/main/java/com/caoccao/javet/swc4j/outputs/Swc4jTranspileOutput.java +++ b/src/main/java/com/caoccao/javet/swc4j/outputs/Swc4jTranspileOutput.java @@ -18,27 +18,27 @@ public class Swc4jTranspileOutput { protected String code; - protected String map; + protected boolean module; public Swc4jTranspileOutput() { - this(null, null); + this(null); } public Swc4jTranspileOutput(String code) { - this(code, null); + this(code, false); } - public Swc4jTranspileOutput(String code, String map) { + public Swc4jTranspileOutput(String code, boolean module) { setCode(code); - setMap(map); + setModule(module); } public String getCode() { return code; } - public String getMap() { - return map; + public boolean isModule() { + return module; } public Swc4jTranspileOutput setCode(String code) { @@ -46,8 +46,8 @@ public Swc4jTranspileOutput setCode(String code) { return this; } - public Swc4jTranspileOutput setMap(String map) { - this.map = map; + public Swc4jTranspileOutput setModule(boolean module) { + this.module = module; return this; } } diff --git a/src/main/java/com/caoccao/javet/swc4j/utils/AssertionUtils.java b/src/main/java/com/caoccao/javet/swc4j/utils/AssertionUtils.java new file mode 100644 index 00000000..097ce919 --- /dev/null +++ b/src/main/java/com/caoccao/javet/swc4j/utils/AssertionUtils.java @@ -0,0 +1,36 @@ +/* + * 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.utils; + +public final class AssertionUtils { + + private static final String VALUE = "Value"; + + private AssertionUtils() { + } + + public static T notNull(T value) { + return notNull(value, VALUE); + } + + public static T notNull(T value, String name) { + if (value == null) { + throw new NullPointerException(name + " is not nullable"); + } + return value; + } +}