diff --git a/core/src/ast/traits.rs b/core/src/ast/traits.rs index c8544158f..4b7ef09d9 100644 --- a/core/src/ast/traits.rs +++ b/core/src/ast/traits.rs @@ -26,6 +26,7 @@ pub struct TraitMethod { pub output_type: Option, pub lifetimes: LifetimeEnv, pub attrs: Attrs, + pub docs: Docs, } impl Trait { @@ -100,6 +101,7 @@ impl Trait { output_type, lifetimes, attrs: fct_attrs, + docs: Docs::from_attrs(&fct.attrs), }); } } diff --git a/core/src/hir/lowering.rs b/core/src/hir/lowering.rs index 66f65301a..f312eb0cc 100644 --- a/core/src/hir/lowering.rs +++ b/core/src/hir/lowering.rs @@ -461,6 +461,7 @@ impl<'ast> LoweringContext<'ast> { output: Box::new(output), name: Some(self.lower_ident(&name, "trait name")?), attrs: Some(attrs), + docs: Some(ast_trait_method.docs.clone()), }) } @@ -930,6 +931,7 @@ impl<'ast> LoweringContext<'ast> { }), name: None, attrs: None, + docs: None, }))) } ast::TypeName::Unit => { diff --git a/core/src/hir/methods.rs b/core/src/hir/methods.rs index a11116e30..d4b35dd79 100644 --- a/core/src/hir/methods.rs +++ b/core/src/hir/methods.rs @@ -55,6 +55,7 @@ pub struct Callback { pub output: Box>, // this will be used in Rust (note: can technically be a callback, or void) pub name: Option, pub attrs: Option, + pub docs: Option, } // uninstantiatable; represents no callback allowed diff --git a/example/kotlin/somelib/src/main/kotlin/dev/diplomattest/somelib/DataProvider.kt b/example/kotlin/somelib/src/main/kotlin/dev/diplomattest/somelib/DataProvider.kt index 6c39afecf..9e132c2b1 100644 --- a/example/kotlin/somelib/src/main/kotlin/dev/diplomattest/somelib/DataProvider.kt +++ b/example/kotlin/somelib/src/main/kotlin/dev/diplomattest/somelib/DataProvider.kt @@ -11,7 +11,10 @@ internal interface DataProviderLib: Library { fun icu4x_DataProvider_new_static_mv1(): Pointer fun icu4x_DataProvider_returns_result_mv1(): ResultUnitUnit } - +/** An data provider, capable of loading data keys from some source. +* +*See the [Rust documentation for `icu_provider`](https://docs.rs/icu_provider/latest/icu_provider/index.html) for more information. +*/ class DataProvider internal constructor ( internal val handle: Pointer, // These ensure that anything that is borrowed is kept alive and not cleaned @@ -29,6 +32,8 @@ class DataProvider internal constructor ( internal val libClass: Class = DataProviderLib::class.java internal val lib: DataProviderLib = Native.load("somelib", libClass) + /** See the [Rust documentation for `get_static_provider`](https://docs.rs/icu_testdata/latest/icu_testdata/fn.get_static_provider.html) for more information. + */ fun newStatic(): DataProvider { val returnVal = lib.icu4x_DataProvider_new_static_mv1(); @@ -39,6 +44,8 @@ class DataProvider internal constructor ( return returnOpaque } + /** This exists as a regression test for https://github.com/rust-diplomat/diplomat/issues/155 + */ fun returnsResult(): Res { val returnVal = lib.icu4x_DataProvider_returns_result_mv1(); diff --git a/example/kotlin/somelib/src/main/kotlin/dev/diplomattest/somelib/FixedDecimal.kt b/example/kotlin/somelib/src/main/kotlin/dev/diplomattest/somelib/FixedDecimal.kt index 3ee675df0..dd8800a52 100644 --- a/example/kotlin/somelib/src/main/kotlin/dev/diplomattest/somelib/FixedDecimal.kt +++ b/example/kotlin/somelib/src/main/kotlin/dev/diplomattest/somelib/FixedDecimal.kt @@ -12,7 +12,8 @@ internal interface FixedDecimalLib: Library { fun icu4x_FixedDecimal_multiply_pow10_mv1(handle: Pointer, power: Short): Unit fun icu4x_FixedDecimal_to_string_mv1(handle: Pointer, write: Pointer): ResultUnitUnit } - +/** See the [Rust documentation for `FixedDecimal`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html) for more information. +*/ class FixedDecimal internal constructor ( internal val handle: Pointer, // These ensure that anything that is borrowed is kept alive and not cleaned @@ -30,6 +31,8 @@ class FixedDecimal internal constructor ( internal val libClass: Class = FixedDecimalLib::class.java internal val lib: FixedDecimalLib = Native.load("somelib", libClass) + /** Construct an [`FixedDecimal`] from an integer. + */ fun new_(v: Int): FixedDecimal { val returnVal = lib.icu4x_FixedDecimal_new_mv1(v); @@ -41,12 +44,20 @@ class FixedDecimal internal constructor ( } } + /** Multiply the [`FixedDecimal`] by a given power of ten. + * + *See the [Rust documentation for `multiply_pow10`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.multiply_pow10) for more information. + */ fun multiplyPow10(power: Short): Unit { val returnVal = lib.icu4x_FixedDecimal_multiply_pow10_mv1(handle, power); } + /** Format the [`FixedDecimal`] as a string. + * + *See the [Rust documentation for `write_to`](https://docs.rs/fixed_decimal/latest/fixed_decimal/struct.FixedDecimal.html#method.write_to) for more information. + */ fun toString_(): Res { val write = DW.lib.diplomat_buffer_write_create(0) val returnVal = lib.icu4x_FixedDecimal_to_string_mv1(handle, write); diff --git a/example/kotlin/somelib/src/main/kotlin/dev/diplomattest/somelib/FixedDecimalFormatter.kt b/example/kotlin/somelib/src/main/kotlin/dev/diplomattest/somelib/FixedDecimalFormatter.kt index 75cefd215..fa8a0a961 100644 --- a/example/kotlin/somelib/src/main/kotlin/dev/diplomattest/somelib/FixedDecimalFormatter.kt +++ b/example/kotlin/somelib/src/main/kotlin/dev/diplomattest/somelib/FixedDecimalFormatter.kt @@ -11,7 +11,10 @@ internal interface FixedDecimalFormatterLib: Library { fun icu4x_FixedDecimalFormatter_try_new_mv1(locale: Pointer, provider: Pointer, options: FixedDecimalFormatterOptionsNative): ResultPointerUnit fun icu4x_FixedDecimalFormatter_format_write_mv1(handle: Pointer, value: Pointer, write: Pointer): Unit } - +/** An Fixed Decimal Format object, capable of formatting a [`FixedDecimal`] as a string. +* +*See the [Rust documentation for `FixedDecimalFormatter`](https://docs.rs/icu/latest/icu/decimal/struct.FixedDecimalFormatter.html) for more information. +*/ class FixedDecimalFormatter internal constructor ( internal val handle: Pointer, // These ensure that anything that is borrowed is kept alive and not cleaned @@ -29,6 +32,10 @@ class FixedDecimalFormatter internal constructor ( internal val libClass: Class = FixedDecimalFormatterLib::class.java internal val lib: FixedDecimalFormatterLib = Native.load("somelib", libClass) + /** Creates a new [`FixedDecimalFormatter`] from locale data. + * + *See the [Rust documentation for `try_new`](https://docs.rs/icu/latest/icu/decimal/struct.FixedDecimalFormatter.html#method.try_new) for more information. + */ fun tryNew(locale: Locale, provider: DataProvider, options: FixedDecimalFormatterOptions): Res { val returnVal = lib.icu4x_FixedDecimalFormatter_try_new_mv1(locale.handle, provider.handle, options.nativeStruct); @@ -44,6 +51,10 @@ class FixedDecimalFormatter internal constructor ( } } + /** Formats a [`FixedDecimal`] to a string. + * + *See the [Rust documentation for `format`](https://docs.rs/icu/latest/icu/decimal/struct.FixedDecimalFormatter.html#method.format) for more information. + */ fun formatWrite(value: FixedDecimal): String { val write = DW.lib.diplomat_buffer_write_create(0) val returnVal = lib.icu4x_FixedDecimalFormatter_format_write_mv1(handle, value.handle, write); diff --git a/example/kotlin/somelib/src/main/kotlin/dev/diplomattest/somelib/Locale.kt b/example/kotlin/somelib/src/main/kotlin/dev/diplomattest/somelib/Locale.kt index ee1274abc..9fac83be9 100644 --- a/example/kotlin/somelib/src/main/kotlin/dev/diplomattest/somelib/Locale.kt +++ b/example/kotlin/somelib/src/main/kotlin/dev/diplomattest/somelib/Locale.kt @@ -10,7 +10,10 @@ internal interface LocaleLib: Library { fun icu4x_Locale_destroy_mv1(handle: Pointer) fun icu4x_Locale_new_mv1(name: Slice): Pointer } - +/** An Locale, capable of representing strings like `"en-US"`. +* +*See the [Rust documentation for `Locale`](https://docs.rs/icu/latest/icu/locid/struct.Locale.html) for more information. +*/ class Locale internal constructor ( internal val handle: Pointer, // These ensure that anything that is borrowed is kept alive and not cleaned @@ -28,6 +31,8 @@ class Locale internal constructor ( internal val libClass: Class = LocaleLib::class.java internal val lib: LocaleLib = Native.load("somelib", libClass) + /** Construct an [`Locale`] from a locale identifier represented as a string. + */ fun new_(name: String): Locale { val (nameMem, nameSlice) = PrimitiveArrayTools.readUtf8(name) diff --git a/feature_tests/kotlin/somelib/src/main/kotlin/dev/diplomattest/somelib/Foo.kt b/feature_tests/kotlin/somelib/src/main/kotlin/dev/diplomattest/somelib/Foo.kt index 6218fd049..01498fdad 100644 --- a/feature_tests/kotlin/somelib/src/main/kotlin/dev/diplomattest/somelib/Foo.kt +++ b/feature_tests/kotlin/somelib/src/main/kotlin/dev/diplomattest/somelib/Foo.kt @@ -70,6 +70,8 @@ class Foo internal constructor ( return returnOpaque } + /** Test that the extraction logic correctly pins the right fields + */ fun extractFromBounds(bounds: BorrowedFieldsWithBounds, anotherString: String): Foo { val (anotherStringMem, anotherStringSlice) = PrimitiveArrayTools.readUtf8(anotherString) diff --git a/feature_tests/kotlin/somelib/src/main/kotlin/dev/diplomattest/somelib/Opaque.kt b/feature_tests/kotlin/somelib/src/main/kotlin/dev/diplomattest/somelib/Opaque.kt index de5bcf325..6270b33aa 100644 --- a/feature_tests/kotlin/somelib/src/main/kotlin/dev/diplomattest/somelib/Opaque.kt +++ b/feature_tests/kotlin/somelib/src/main/kotlin/dev/diplomattest/somelib/Opaque.kt @@ -98,6 +98,12 @@ class Opaque internal constructor ( return returnString } + /** See the [Rust documentation for `something`](https://docs.rs/Something/latest/struct.Something.html#method.something) for more information. + * + *See the [Rust documentation for `something_else`](https://docs.rs/Something/latest/struct.Something.html#method.something_else) for more information. + * + *Additional information: [1](https://docs.rs/Something/latest/struct.Something.html#method.something_small), [2](https://docs.rs/SomethingElse/latest/struct.SomethingElse.html#method.something) + */ fun assertStruct(s: MyStruct): Unit { val returnVal = lib.Opaque_assert_struct(handle, s.nativeStruct); diff --git a/tool/src/kotlin/formatter.rs b/tool/src/kotlin/formatter.rs index b2e3963be..58fdb3d6d 100644 --- a/tool/src/kotlin/formatter.rs +++ b/tool/src/kotlin/formatter.rs @@ -1,8 +1,9 @@ use diplomat_core::hir::{ self, borrowing_param::{LifetimeEdge, LifetimeEdgeKind}, - FloatType, IntSizeType, IntType, LifetimeEnv, MaybeStatic, PrimitiveType, Slice, - StringEncoding, StructPathLike, TraitId, TyPosition, Type, TypeContext, TypeId, + Docs, DocsUrlGenerator, FloatType, IntSizeType, IntType, LifetimeEnv, MaybeStatic, + PrimitiveType, Slice, StringEncoding, StructPathLike, TraitId, TyPosition, Type, TypeContext, + TypeId, }; use heck::ToLowerCamelCase; use std::{borrow::Cow, iter::once}; @@ -11,6 +12,8 @@ use std::{borrow::Cow, iter::once}; pub(super) struct KotlinFormatter<'tcx> { tcx: &'tcx TypeContext, strip_prefix: Option, + /// For generating doc.rs links + docs_url_gen: &'tcx DocsUrlGenerator, } const INVALID_METHOD_NAMES: &[&str] = &[ @@ -19,8 +22,16 @@ const INVALID_METHOD_NAMES: &[&str] = &[ const DISALLOWED_CORE_TYPES: &[&str] = &["Object", "String"]; impl<'tcx> KotlinFormatter<'tcx> { - pub fn new(tcx: &'tcx TypeContext, strip_prefix: Option) -> Self { - Self { tcx, strip_prefix } + pub fn new( + tcx: &'tcx TypeContext, + strip_prefix: Option, + docs_url_gen: &'tcx DocsUrlGenerator, + ) -> Self { + Self { + tcx, + strip_prefix, + docs_url_gen, + } } pub fn fmt_void(&self) -> &'static str { @@ -44,6 +55,13 @@ impl<'tcx> KotlinFormatter<'tcx> { "String" } + pub fn fmt_docs(&self, docs: &Docs) -> String { + docs.to_markdown(self.docs_url_gen) + .trim() + .replace('\n', "\n*") + .replace(" \n", "\n") + } + pub fn fmt_primitive_slice(&self, ty: PrimitiveType) -> String { format!("{}Array", self.fmt_primitive_as_kt(ty)) } @@ -450,7 +468,9 @@ pub mod test { } }; let tcx = new_tcx(tk_stream); - let formatter = KotlinFormatter::new(&tcx, None); + let docs_urls = std::collections::HashMap::new(); + let docs_generator = &diplomat_core::hir::DocsUrlGenerator::with_base_urls(None, docs_urls); + let formatter = KotlinFormatter::new(&tcx, None, docs_generator); let opaques = tcx.opaques(); assert!(!opaques.is_empty()); let mut all_types = tcx.all_types(); diff --git a/tool/src/kotlin/mod.rs b/tool/src/kotlin/mod.rs index 51edb8b63..74e942d39 100644 --- a/tool/src/kotlin/mod.rs +++ b/tool/src/kotlin/mod.rs @@ -1,10 +1,10 @@ use askama::Template; use diplomat_core::hir::borrowing_param::{BorrowedLifetimeInfo, ParamBorrowInfo}; use diplomat_core::hir::{ - self, BackendAttrSupport, Borrow, Callback, InputOnly, Lifetime, LifetimeEnv, Lifetimes, - MaybeOwn, MaybeStatic, Method, Mutability, OpaquePath, Optional, OutType, Param, PrimitiveType, - ReturnableStructDef, SelfType, Slice, SpecialMethod, StringEncoding, StructField, StructPath, - StructPathLike, TraitIdGetter, TyPosition, Type, TypeContext, TypeDef, + self, BackendAttrSupport, Borrow, Callback, DocsUrlGenerator, InputOnly, Lifetime, LifetimeEnv, + Lifetimes, MaybeOwn, MaybeStatic, Method, Mutability, OpaquePath, Optional, OutType, Param, + PrimitiveType, ReturnableStructDef, SelfType, Slice, SpecialMethod, StringEncoding, + StructField, StructPath, StructPathLike, TraitIdGetter, TyPosition, Type, TypeContext, TypeDef, }; use diplomat_core::hir::{ReturnType, SuccessType}; @@ -56,6 +56,7 @@ struct KotlinConfig { pub(crate) fn run<'tcx>( tcx: &'tcx TypeContext, conf_path: Option<&Path>, + docs_url_gen: &'tcx DocsUrlGenerator, ) -> (FileMap, ErrorStore<'tcx, String>) { let conf_path = conf_path.expect("Kotlin library needs to be called with config"); @@ -68,8 +69,7 @@ pub(crate) fn run<'tcx>( } = toml::from_str::(&conf_str) .expect("Failed to parse config. Required fields are `domain` and `lib_name`"); let use_finalizers_not_cleaners = use_finalizers_not_cleaners.unwrap_or(false); - - let formatter = KotlinFormatter::new(tcx, None); + let formatter = KotlinFormatter::new(tcx, None, docs_url_gen); let files = FileMap::default(); let errors = ErrorStore::default(); @@ -1207,6 +1207,7 @@ returnVal.option() ?: return null return_expression, write_return, slice_conversions, + docs: self.formatter.fmt_docs(&method.docs), } .render() .expect("Failed to render string for method") @@ -1347,6 +1348,7 @@ returnVal.option() ?: return null special_methods: SpecialMethodsImpl, callback_params: &'a [CallbackParamInfo], use_finalizers_not_cleaners: bool, + docs: String, } ( @@ -1363,6 +1365,7 @@ returnVal.option() ?: return null special_methods: SpecialMethodsImpl::new(special_methods), callback_params: self.callback_params.as_ref(), use_finalizers_not_cleaners, + docs: self.formatter.fmt_docs(&ty.docs), } .render() .expect("failed to generate struct"), @@ -1437,6 +1440,7 @@ returnVal.option() ?: return null ffi_cast_type_name: Cow<'d, str>, field_type: Cow<'d, str>, native_to_kt: Cow<'d, str>, + docs: String, } #[derive(Template)] @@ -1451,6 +1455,7 @@ returnVal.option() ?: return null native_methods: &'a [NativeMethodInfo], callback_params: &'a [CallbackParamInfo], lifetimes: Vec>, + docs: String, } let fields = ty @@ -1469,6 +1474,7 @@ returnVal.option() ?: return null &ty.lifetimes, &field.ty, ), + docs: self.formatter.fmt_docs(&field.docs), } }) .collect(); @@ -1485,6 +1491,7 @@ returnVal.option() ?: return null native_methods: native_methods.as_ref(), callback_params: self.callback_params.as_ref(), lifetimes, + docs: self.formatter.fmt_docs(&ty.docs), } .render() .expect("Failed to render struct template"), @@ -1578,6 +1585,10 @@ returnVal.option() ?: return null input_params_and_types: native_input_params_and_types.join(", "), non_native_params_and_types, input_params: native_input_names.join(", "), + docs: match &method.docs { + Some(method_docs) => self.formatter.fmt_docs(method_docs), + None => "".to_string(), + }, } } @@ -1614,6 +1625,7 @@ returnVal.option() ?: return null trait_methods: &'a [TraitMethodInfo], trait_method_names: &'a str, callback_params: &'a [CallbackParamInfo], + docs: String, } ( @@ -1625,6 +1637,7 @@ returnVal.option() ?: return null trait_methods: trait_methods.as_ref(), callback_params: self.callback_params.as_ref(), trait_method_names: &trait_method_names.join(", "), + docs: self.formatter.fmt_docs(&trt.docs), } .render() .expect("Failed to render trait template"), @@ -1746,6 +1759,7 @@ returnVal.option() ?: return null companion_methods: &'d [String], native_methods: &'d [NativeMethodInfo], callback_params: &'d [CallbackParamInfo], + docs: String, } let variants = EnumVariants::new(ty); @@ -1759,6 +1773,7 @@ returnVal.option() ?: return null companion_methods: companion_methods.as_ref(), native_methods: native_methods.as_ref(), callback_params: self.callback_params.as_ref(), + docs: self.formatter.fmt_docs(&ty.docs), } .render() .unwrap_or_else(|err| panic!("Failed to render Enum {{type_name}}\n\tcause: {err}")); @@ -1942,6 +1957,7 @@ struct MethodTpl<'a> { return_expression: Cow<'a, str>, write_return: bool, slice_conversions: Vec>, + docs: String, } struct NativeMethodInfo { @@ -1956,6 +1972,7 @@ struct TraitMethodInfo { native_output_type: String, return_modification: String, non_native_params_and_types: String, + docs: String, } #[derive(Template)] @@ -1974,7 +1991,7 @@ struct CallbackParamInfo { mod test { use std::cell::RefCell; - use std::collections::BTreeSet; + use std::collections::{BTreeSet, HashMap}; use diplomat_core::hir::TypeDef; use quote::quote; @@ -2025,7 +2042,10 @@ mod test { .expect("Failed to generate first opaque def") { let error_store = ErrorStore::default(); - let formatter = KotlinFormatter::new(&tcx, None); + let docs_urls = HashMap::new(); + let docs_generator = + diplomat_core::hir::DocsUrlGenerator::with_base_urls(None, docs_urls); + let formatter = KotlinFormatter::new(&tcx, None, &docs_generator); let mut callback_params = Vec::new(); let mut ty_gen_cx = TyGenContext { tcx: &tcx, @@ -2060,6 +2080,7 @@ mod test { i: i32, } + /// Documentation for the struct pub struct MyNativeStruct<'b> { a: bool, b: i8, @@ -2069,6 +2090,7 @@ mod test { f: i32, g: u32, h: i64, + /// Documentation for the struct field `i` i: u64, j: DiplomatChar, k: f32, @@ -2108,7 +2130,10 @@ mod test { .expect("Failed to generate first opaque def") { let error_store = ErrorStore::default(); - let formatter = KotlinFormatter::new(&tcx, None); + let docs_urls = HashMap::new(); + let docs_generator = + diplomat_core::hir::DocsUrlGenerator::with_base_urls(None, docs_urls); + let formatter = KotlinFormatter::new(&tcx, None, &docs_generator); let mut callback_params = Vec::new(); let mut ty_gen_cx = TyGenContext { tcx: &tcx, @@ -2157,7 +2182,10 @@ mod test { .expect("Failed to generate first opaque def") { let eror_store = ErrorStore::default(); - let formatter = KotlinFormatter::new(&tcx, None); + let docs_urls = HashMap::new(); + let docs_generator = + diplomat_core::hir::DocsUrlGenerator::with_base_urls(None, docs_urls); + let formatter = KotlinFormatter::new(&tcx, None, &docs_generator); let mut callback_params = Vec::new(); let mut ty_gen_cx = TyGenContext { tcx: &tcx, @@ -2263,7 +2291,10 @@ mod test { .expect("Failed to generate first opaque def") { let eror_store = ErrorStore::default(); - let formatter = KotlinFormatter::new(&tcx, None); + let docs_urls = HashMap::new(); + let docs_generator = + diplomat_core::hir::DocsUrlGenerator::with_base_urls(None, docs_urls); + let formatter = KotlinFormatter::new(&tcx, None, &docs_generator); let mut callback_params = Vec::new(); let mut ty_gen_cx = TyGenContext { tcx: &tcx, @@ -2311,7 +2342,10 @@ mod test { .expect("Failed to generate first opaque def") { let eror_store = ErrorStore::default(); - let formatter = KotlinFormatter::new(&tcx, None); + let docs_urls = HashMap::new(); + let docs_generator = + diplomat_core::hir::DocsUrlGenerator::with_base_urls(None, docs_urls); + let formatter = KotlinFormatter::new(&tcx, None, &docs_generator); let mut callback_params = Vec::new(); let mut ty_gen_cx = TyGenContext { tcx: &tcx, @@ -2343,7 +2377,9 @@ mod test { One, Two, } + /// Documentation for this trait! pub trait TesterTrait { + /// Trait function docs fn test_trait_fn(&self, x: i32, y: i32, z: u8) -> i32; fn test_void_trait_fn(&self); fn test_struct_trait_fn(&self, s: TraitTestingStruct) -> i32; @@ -2371,7 +2407,9 @@ mod test { let mut all_traits = tcx.all_traits(); let (_id, trait_def) = all_traits.next().expect("Failed to generate trait"); let error_store = ErrorStore::default(); - let formatter = KotlinFormatter::new(&tcx, None); + let docs_urls = HashMap::new(); + let docs_generator = diplomat_core::hir::DocsUrlGenerator::with_base_urls(None, docs_urls); + let formatter = KotlinFormatter::new(&tcx, None, &docs_generator); let mut callback_params = Vec::new(); let mut ty_gen_cx = TyGenContext { tcx: &tcx, diff --git a/tool/src/kotlin/snapshots/diplomat_tool__kotlin__test__struct.snap b/tool/src/kotlin/snapshots/diplomat_tool__kotlin__test__struct.snap index 44c624da3..313a0e3db 100644 --- a/tool/src/kotlin/snapshots/diplomat_tool__kotlin__test__struct.snap +++ b/tool/src/kotlin/snapshots/diplomat_tool__kotlin__test__struct.snap @@ -1,6 +1,6 @@ --- source: tool/src/kotlin/mod.rs -assertion_line: 2064 +assertion_line: 2150 expression: struct_code --- package dev.gigapixel.somelib @@ -36,6 +36,8 @@ internal class MyNativeStructNative: Structure(), Structure.ByValue { internal var g: Int = 0; @JvmField internal var h: Long = 0; + /** Documentation for the struct field `i` + */ @JvmField internal var i: Long = 0; @JvmField @@ -105,6 +107,8 @@ internal class DiplomatCallback_MyNativeStruct_test_multi_arg_callback_diplomatC } } } +/** Documentation for the struct +*/ class MyNativeStruct internal constructor ( internal val nativeStruct: MyNativeStructNative, internal val bEdges: List diff --git a/tool/src/kotlin/snapshots/diplomat_tool__kotlin__test__trait_gen.snap b/tool/src/kotlin/snapshots/diplomat_tool__kotlin__test__trait_gen.snap index 492eb18fd..7738f91f4 100644 --- a/tool/src/kotlin/snapshots/diplomat_tool__kotlin__test__trait_gen.snap +++ b/tool/src/kotlin/snapshots/diplomat_tool__kotlin__test__trait_gen.snap @@ -1,6 +1,6 @@ --- source: tool/src/kotlin/mod.rs -assertion_line: 2380 +assertion_line: 2424 expression: result --- package dev.gigapixel.somelib @@ -10,8 +10,11 @@ import com.sun.jna.Library import com.sun.jna.Native import com.sun.jna.Pointer import com.sun.jna.Structure - +/** Documentation for this trait! +*/ interface TesterTrait { + /** Trait function docs + */ fun testTraitFn(x: Int, y: Int, z: UByte): Int; fun testVoidTraitFn(): Unit; fun testStructTraitFn(s: TraitTestingStruct): Int; diff --git a/tool/src/lib.rs b/tool/src/lib.rs index 11adb8e6c..dbf7b714d 100644 --- a/tool/src/lib.rs +++ b/tool/src/lib.rs @@ -98,7 +98,7 @@ pub fn gen( } demo_gen::run(entry, &tcx, docs_url_gen, conf) } - "kotlin" => kotlin::run(&tcx, library_config), + "kotlin" => kotlin::run(&tcx, library_config, docs_url_gen), o => panic!("Unknown target: {}", o), }; diff --git a/tool/templates/kotlin/Enum.kt.jinja b/tool/templates/kotlin/Enum.kt.jinja index 331c3ca9f..da1ea6c12 100644 --- a/tool/templates/kotlin/Enum.kt.jinja +++ b/tool/templates/kotlin/Enum.kt.jinja @@ -19,6 +19,10 @@ internal interface {{type_name}}Lib: Library { {% endif -%} {% let variants_for_decl = variants -%} {%- let variants_for_native = variants -%} +{% if !docs.is_empty() -%} +/** {{docs}} +*/ +{% endif -%} enum class {{type_name}} {%- match variants_for_decl -%} {%- when EnumVariants::NonContiguous with (variants) %}(val inner: Int) { diff --git a/tool/templates/kotlin/Method.kt.jinja b/tool/templates/kotlin/Method.kt.jinja index 17a5d9bba..a5ed89a2e 100644 --- a/tool/templates/kotlin/Method.kt.jinja +++ b/tool/templates/kotlin/Method.kt.jinja @@ -1,4 +1,8 @@ +{%- if !docs.is_empty() %} +/** {{docs}} +*/ +{%- endif %} {{ declaration }} { {%- for slice_conv in slice_conversions %}{{slice_conv|indent(4)}}{% endfor %} {% if write_return %}val write = DW.lib.diplomat_buffer_write_create(0){% endif %} diff --git a/tool/templates/kotlin/Opaque.kt.jinja b/tool/templates/kotlin/Opaque.kt.jinja index 7139a4a0e..d90d72b48 100644 --- a/tool/templates/kotlin/Opaque.kt.jinja +++ b/tool/templates/kotlin/Opaque.kt.jinja @@ -24,7 +24,10 @@ internal interface {{type_name}}Lib: Library { typealias {{type_name}}IteratorItem = {{iter_ty}} {%- when None %} {%- endmatch %} - +{% if !docs.is_empty() -%} +/** {{docs}} +*/ +{%- endif %} class {{type_name}} internal constructor ( internal val handle: Pointer, // These ensure that anything that is borrowed is kept alive and not cleaned diff --git a/tool/templates/kotlin/Struct.kt.jinja b/tool/templates/kotlin/Struct.kt.jinja index e8c75f2b6..19730feca 100644 --- a/tool/templates/kotlin/Struct.kt.jinja +++ b/tool/templates/kotlin/Struct.kt.jinja @@ -16,6 +16,10 @@ internal interface {{type_name}}Lib: Library { internal class {{type_name}}Native: Structure(), Structure.ByValue { {%- for field in fields %} + {% if !field.docs.is_empty() -%} + /** {{field.docs}} + */ + {% endif -%} @JvmField internal var {{field.name}}: {{field.ffi_cast_type_name}} = {{field.ffi_type_default}}; {%- endfor %} @@ -34,6 +38,10 @@ internal class {{type_name}}Native: Structure(), Structure.ByValue { {%- endfor %} {% endif -%} +{% if !docs.is_empty() -%} +/** {{docs}} +*/ +{% endif -%} class {{type_name}} internal constructor ( {% if !fields.is_empty() -%} internal val nativeStruct: {{type_name}}Native{% if !lifetimes.is_empty() %},{% endif %}{% endif -%} diff --git a/tool/templates/kotlin/Trait.kt.jinja b/tool/templates/kotlin/Trait.kt.jinja index 1ab68c63b..a98b2670f 100644 --- a/tool/templates/kotlin/Trait.kt.jinja +++ b/tool/templates/kotlin/Trait.kt.jinja @@ -5,9 +5,16 @@ import com.sun.jna.Library import com.sun.jna.Native import com.sun.jna.Pointer import com.sun.jna.Structure - +{% if !docs.is_empty() -%} +/** {{docs}} +*/ +{%- endif %} interface {{trait_name}} { {%- for m in trait_methods %} + {%- if !m.docs.is_empty() %} + /** {{m.docs}} + */ + {%- endif %} fun {{m.name}}({{m.non_native_params_and_types}}): {{m.output_type}}; {%- endfor %} }