Kotlin Library Compatibility Issues and Proposed Fixes
还没有人认领这个 Issue。
评估
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 新手友好度
- 45/100
- Issue 类型
- 缺陷
- 描述清晰度
- 描述清楚
- 活跃度
- 停滞
- 技术栈
- java, kotlin, typescript
- 领域
- tooling
调研方向
从 DtsApi.java 中第 143 行附近的过滤逻辑、第 962-969 行附近的参数处理以及第 248 行附近的 replaceIgnoredNamespaces 开始。使用 MiSnap SDK v5.8.1 重现生成过程,并检查生成的声明。完成的标准是没有空模块、无效的合成参数名或无效的 any 泛型,并且定义能够成功编译。
由索引模型根据 Issue 内容生成。
描述
I have been going through a library and was creating typings for it's various different .aar files. I noticed some issues that have already been highlighted here: https://github.com/NativeScript/android-dts-generator/issues/83 (@NathanWalker) and https://github.com/NativeScript/android-dts-generator/issues/75 (@farfromrefug).
Since I had a build issue with the generated typings I set about investigating the issues. I am proficient in TypeScript, however I'm no expert in terms of Kotlin which meant I could see what the issues were in the typing files, but wasn't sure how to solve them. Therefore, I investigated the issues via Claude Code and the solutions that were generated have solved my issues. The following description was also generated by Claude Code, I did so to make sure that everything that was found is listed accurately:
Summary
While generating TypeScript definitions for Kotlin-based Android libraries (specifically MiSnap SDK v5.8.1), three critical issues were discovered that prevent proper type generation. This document outlines each issue, provides examples, and proposes fixes.
Environment
- DTS Generator Version: 4.0.0
- Test Library: MiSnap SDK v5.8.1 (Kotlin-based Android library)
- Kotlin Version: 1.8.20 (as seen in generated code)
- Java Target: 17
Issue 1: Kotlin Serializer Classes Generate Invalid TypeScript
Problem
Kotlin's
kotlinx.serializationcompiler generates classes with double dollar signs ($$serializer) in their bytecode names. The DTS generator processes these, creating invalid TypeScript with empty module declarations.Example from Bytecode
com/miteksystems/misnap/core/Barcode$$serializer.class com/miteksystems/misnap/core/MiSnapSettings$$serializer.classGenerated TypeScript (Invalid)
export module { // ❌ Empty module name! export module Barcode { export class serializer extends kotlinx.serialization.internal.GeneratedSerializer<com.miteksystems.misnap.core.Barcode> { public static class: java.lang.Class<com.miteksystems.misnap.core.Barcode..serializer>; // ❌ Double dots public static INSTANCE: com.miteksystems.misnap.core.Barcode..serializer; // ❌ Double dots } } }Root Cause
In
DtsApi.javaline 541, the code replaces$with.:String[] currParts = currClass.getClassName().replace('$', '.').split("\\.");For
Barcode$$serializer:
- Replace
$→.:Barcode..serializer- Split on
.:["Barcode", "", "serializer"]- Empty string in array creates
module {(invalid!)Impact
- 63 empty module declarations in test file
- 126 invalid double-dot type references
- TypeScript compilation fails
Proposed Fix
Add
$$serializerto the filtered class list inDtsApi.javaaround line 143:if (currentFileClassname.startsWith("java.util.function") || currentFileClassname.startsWith("android.support.v4.media.routing.MediaRouterJellybeanMr1") || currentFileClassname.startsWith("android.support.v4.media.routing.MediaRouterJellybeanMr2") || currentFileClassname.contains(".debugger.") || currentFileClassname.endsWith("package-info") || currentFileClassname.endsWith("module-info") || currentFileClassname.endsWith("Kt") || currentFileClassname.contains("$$serializer")) { // ← NEW LINE continue; }Why This Fix is Safe
$$serializerclasses are Kotlin compiler internals for serialization- They're never directly used by application code
- Filtering them is similar to filtering other compiler-generated classes (already done for
Ktsuffix)
Issue 2: Kotlin Synthetic Parameter Names Are Invalid TypeScript
Problem
Kotlin compiler generates synthetic setter methods with the parameter name
<set-?>in the LocalVariableTable. The DTS generator reads this directly, creating invalid TypeScript identifiers.Example from Bytecode (javap output)
public final void setInitialDelay(java.lang.Integer); LocalVariableTable: Start Length Slot Name Signature 0 6 0 this Lcom/miteksystems/misnap/core/MiSnapSettings$Analysis; 0 6 1 <set-?> Ljava/lang/Integer;Generated TypeScript (Invalid)
public setInitialDelay(<set-?>: java.lang.Integer): void; // ❌ Invalid identifier public setEnableAiBasedRts(<set-?>: java.lang.Boolean): void; // ❌ Invalid identifier public setMotionDetectorSensitivity(<set-?>: com.miteksystems.misnap.core.MiSnapSettings.Analysis.MotionDetectorSensitivity): void; // ❌ Invalid identifierRoot Cause
In
DtsApi.javalines 962-969, the code reads parameter names from bytecode but doesn't sanitize Kotlin synthetic names:if (localVariable != null) { String name = localVariable.getName(); // No sanitization for <set-?> or other synthetic names! if (reservedJsKeywords.contains(name)) { sb.append(name + "_"); } else { sb.append(name); // Writes <set-?> directly } }Impact
- 68 occurrences in test file
- All Kotlin property setter methods affected
- TypeScript parser fails on angle bracket identifiers
Proposed Fix
Sanitize synthetic parameter names by deriving meaningful names from method names:
if (localVariable != null) { String name = localVariable.getName(); // Sanitize Kotlin synthetic parameter names like <set-?> if (name.startsWith("<") && name.endsWith(">")) { // For setter methods, derive parameter name from method name String methodName = m.getName(); if (methodName.startsWith("set") && methodName.length() > 3) { // setInitialDelay -> initialDelay name = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4); } else { // Fallback to "value" for other synthetic names name = "value"; } } if (reservedJsKeywords.contains(name)) { System.out.println(String.format("Appending _ to reserved JS keyword %s", name)); sb.append(name + "_"); } else { sb.append(name); } }Result After Fix
public setInitialDelay(initialDelay: java.lang.Integer): void; // ✅ Valid and semantic! public setEnableAiBasedRts(enableAiBasedRts: java.lang.Boolean): void; // ✅ Valid and semantic! public setMotionDetectorSensitivity(motionDetectorSensitivity: com.miteksystems.misnap.core.MiSnapSettings.Analysis.MotionDetectorSensitivity): void; // ✅ Valid and semantic!Why This Fix is Safe
- Only affects synthetic Kotlin parameter names (those with
<and>)- Generates semantically meaningful names matching the property being set
- Follows common naming conventions (same pattern as Kotlin itself uses in Kotlin files)
Issue 3: Kotlin Type Generics Create Invalid
any<...>SyntaxProblem
Kotlin standard library types (
kotlin.jvm.functions.*,kotlin.properties.*) are in the "ignored namespaces" list and get replaced withany. However, the regex replacement preserves generic type parameters, creating invalid TypeScript syntax (anyis not a generic type).Example from Bytecode
public final class FragmentViewBindingDelegate<T extends ViewBinding> implements kotlin.properties.ReadOnlyProperty<androidx.fragment.app.Fragment, T>Generated TypeScript (Invalid)
export class FragmentViewBindingDelegate<T> extends any<androidx.fragment.app.Fragment,any> { // ❌ any is not generic! public getViewBindingFactory(): any<globalAndroid.view.View,any>; // ❌ Invalid syntax public constructor(fragment: androidx.fragment.app.Fragment, viewBindingFactory: any<any,any>); // ❌ Invalid syntax }Root Cause
In
DtsApi.javaline 248, the regex pattern doesn't include commas and spaces in the character class for matching generic parameters:String regexFormat = "(?<Replace>%s(?:(?:\\.[a-zA-Z\\d]*)|<[a-zA-Z\\d\\.<>]*>)*)(?<Suffix>[^a-zA-Z\\d]+)"; // ^^^^^^^^^^^^^^ Missing comma and space!When the regex encounters
kotlin.properties.ReadOnlyProperty<Fragment, T>:
- Matches up to:
kotlin.properties.ReadOnlyProperty- Encounters
<which is[^a-zA-Z\d], so it becomes the Suffix- Replacement:
any<+ remaining text- Result:
any<Fragment, T>(invalid!)Impact
- ~30 occurrences across various Kotlin function and property types
- All Kotlin lambda and property delegate types affected
- TypeScript compilation fails
Proposed Fix
Update the regex to include commas, spaces, and match end-of-string:
private String replaceIgnoredNamespaces(String content) { // Updated regex to properly capture generics with commas, spaces, and nested angle brackets // Also matches end of string or line as valid suffix String regexFormat = "(?<Replace>%s(?:(?:\\.[a-zA-Z\\d]*)|<[a-zA-Z\\d\\.<>, ]*>)*)(?<Suffix>[^a-zA-Z\\d]+|$)"; // ^^^^^ Added comma and space // ^^^ Added end-of-string for (String ignoredNamespace : this.getIgnoredNamespaces()) { String regexString = String.format(regexFormat, ignoredNamespace.replace(".", "\\.")); content = content.replaceAll(regexString, "any$2"); regexString = String.format(regexFormat, getGlobalAliasedClassName(ignoredNamespace).replace(".", "\\.")); content = content.replaceAll(regexString, "any$2"); } // replace "extends any" with "extends java.lang.Object" content = content.replace(" extends any ", String.format(" extends %s ", DtsApi.JavaLangObject)); return content; }Result After Fix
export class FragmentViewBindingDelegate<T> extends java.lang.Object { // ✅ Valid TypeScript! public getViewBindingFactory(): any; // ✅ Valid TypeScript! public constructor(fragment: androidx.fragment.app.Fragment, viewBindingFactory: any); // ✅ Valid TypeScript! }Why This Fix is Safe
- Only affects types in the ignored namespaces list (already being replaced with
any)- Properly strips all generic parameters when replacing, creating valid TypeScript
- The regex already existed; this just makes it work correctly for types with commas in generics
Testing Results
Test Environment
- Library: MiSnap SDK v5.8.1 (11 modules)
- Project: NativeScript mobile app
- TypeScript Version: As configured by NativeScript
Before Fixes
- ❌ Empty module declarations: 63
- ❌ Double-dot references: 126
- ❌ Invalid
<set-?>parameters: 68- ❌ Invalid
any<...>syntax: ~30- ❌ Total TypeScript errors: 287+
After Fixes
- ✅ Empty module declarations: 0
- ✅ Double-dot references: 0
- ✅ Invalid parameters: 0
- ✅ Invalid
any<...>syntax: 0- ✅ All type definitions compile successfully
- ✅ NativeScript project runs without issues
Generated File Sizes (Example: misnap-core.d.ts)
- Before: 3,789 lines with errors
- After: 3,096 lines (693 lines of invalid code removed)
- Reduction: 18.3% smaller, 100% valid
Compatibility
These fixes specifically target Kotlin-generated bytecode patterns that are:
- Standard Kotlin compiler output (not library-specific)
- Present in any modern Kotlin Android library
- Not handled by the current generator logic
The fixes are backward compatible - they only affect Kotlin libraries and don't change behavior for Java-only libraries.
Proposed Changes Summary
File:
dts-generator/src/main/java/com/telerik/dts/DtsApi.javaChange 1 (around line 143):
// Add to filtered classes list currentFileClassname.contains("$$serializer")Change 2 (lines 965-976, in
getMethodParamSignaturemethod):// Sanitize Kotlin synthetic parameter names if (name.startsWith("<") && name.endsWith(">")) { String methodName = m.getName(); if (methodName.startsWith("set") && methodName.length() > 3) { name = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4); } else { name = "value"; } }Change 3 (line 249, in
replaceIgnoredNamespacesmethod):// Update regex pattern String regexFormat = "(?<Replace>%s(?:(?:\\.[a-zA-Z\\d]*)|<[a-zA-Z\\d\\.<>, ]*>)*)(?<Suffix>[^a-zA-Z\\d]+|$)";
References
- Kotlin Serialization Docs: https://kotlinlang.org/docs/serialization.html
- Kotlin Bytecode Conventions: https://kotlinlang.org/spec/
- Related Issue: Similar to the 2016 fix for interface static initializers (commit 26a0870)
Tested With:
- MiSnap SDK v5.8.1 (Mitek Systems)
- NativeScript 8.x
- Multiple Kotlin-based AndroidX libraries
Let me know if I should commit the changes so that they can be tested :)
- 主要语言
- Java
- 星标
- 96
- 派生
- 25
- PR 合并指标
- 30 天内没有已合并 PR
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
NativeScript/android-dts-generator 的其他 Issue
-
难度 4/5 3-5 天 新手友好度 35/100
-
难度 4/5 3-5 天 新手友好度 48/100
-
难度 4/5 3-5 天 新手友好度 25/100
-
难度 4/5 3-5 天 新手友好度 30/100
-
难度 4/5 3-5 天 新手友好度 35/100
查看 NativeScript/android-dts-generator 的全部 Issue
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 83/100
jenkinsci/gitlab-plugin#1950 ·
-
It's not necessary to copy the memory block in the readWrite() of org.h2.store.fs.mem.FileMemData未关闭
难度 2/5 1-3 小时 新手友好度 78/100
h2database/h2database#4435 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 78/100
micronaut-projects/micronaut-core#13717 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 72/100
ADORSYS-GIS/token-status-link#145 ·
维护者通常 3 天内回复
-
enhancement
难度 1/5 1 小时以内 新手友好度 88/100
helidon-io/helidon#12721 ·
维护者通常 1 天内回复