@@ -21,32 +21,36 @@ public static void Fixup (IList<ClassFile> classes)
21
21
22
22
try {
23
23
var km = KotlinMetadata . FromAnnotation ( kotlin ) ;
24
+ var metadata = km . ParseMetadata ( ) ;
24
25
25
- if ( km . Kind == KotlinMetadataKind . Class ) {
26
- var class_metadata = km . AsClassMetadata ( ) ;
26
+ if ( metadata is null )
27
+ return ;
27
28
28
- FixupClassVisibility ( c , class_metadata ) ;
29
+ // Do fixups only valid for full classes
30
+ var class_metadata = ( metadata as KotlinClass ) ;
29
31
30
- if ( class_metadata . Flags . HasFlag ( KotlinClassFlags . EnumClass ) )
31
- continue ;
32
+ if ( class_metadata != null ) {
33
+ FixupClassVisibility ( c , class_metadata ) ;
32
34
33
35
foreach ( var con in class_metadata . Constructors )
34
36
FixupConstructor ( FindJavaConstructor ( class_metadata , con , c ) , con ) ;
37
+ }
35
38
36
- foreach ( var met in class_metadata . Functions )
37
- FixupFunction ( FindJavaMethod ( class_metadata , met , c ) , met , class_metadata ) ;
39
+ // Do fixups valid for both classes and modules
40
+ // (We pass "class_metadata" even though it's sometimes null because it's
41
+ // used for generic type resolution if available for class types)
42
+ FixupJavaMethods ( c . Methods ) ;
38
43
39
- foreach ( var prop in class_metadata . Properties ) {
40
- var getter = FindJavaPropertyGetter ( class_metadata , prop , c ) ;
41
- var setter = FindJavaPropertySetter ( class_metadata , prop , c ) ;
44
+ foreach ( var met in metadata . Functions )
45
+ FixupFunction ( FindJavaMethod ( class_metadata , met , c ) , met , class_metadata ) ;
42
46
43
- FixupProperty ( getter , setter , prop ) ;
44
- }
45
- } else {
46
- // We don't have explicit support for other types of Kotlin constructs yet,
47
- // so they are unlikely to work. Mark them as private so they don't get bound.
48
- c . AccessFlags = ClassAccessFlags . Private ;
47
+ foreach ( var prop in metadata . Properties ) {
48
+ var getter = FindJavaPropertyGetter ( class_metadata , prop , c ) ;
49
+ var setter = FindJavaPropertySetter ( class_metadata , prop , c ) ;
50
+
51
+ FixupProperty ( getter , setter , prop ) ;
49
52
}
53
+
50
54
} catch ( Exception ex ) {
51
55
Log . Warning ( 0 , $ "class-parse: warning: Unable to parse Kotlin metadata on '{ c . ThisClass . Name } ': { ex } ") ;
52
56
}
@@ -61,25 +65,22 @@ static void FixupClassVisibility (ClassFile klass, KotlinClass metadata)
61
65
klass . AccessFlags = ClassAccessFlags . Private ;
62
66
return ;
63
67
}
68
+ }
64
69
65
- // We don't have explicit support for these types of Kotlin constructs yet,
66
- // so they are unlikely to work. Mark them as private so they don't get bound.
67
- if ( metadata . Flags . HasFlag ( KotlinClassFlags . AnnotationClass ) || metadata . Flags . HasFlag ( KotlinClassFlags . CompanionObject ) || metadata . Flags . HasFlag ( KotlinClassFlags . Object ) ) {
68
- Log . Debug ( $ "Kotlin: Hiding unsupported class { klass . ThisClass . Name . Value } ({ metadata . Flags } )") ;
69
- klass . AccessFlags = ClassAccessFlags . Private ;
70
+ static void FixupJavaMethods ( Methods methods )
71
+ {
72
+ // We do the following method level fixups here because we can operate on all methods,
73
+ // not just ones that have corresponding Kotlin metadata, like FixupFunction does.
74
+
75
+ // Hide Kotlin generated methods like "add-impl" that aren't intended for end users
76
+ foreach ( var method in methods . Where ( m => m . IsPubliclyVisible && m . Name . Contains ( "-impl" ) ) ) {
77
+ Log . Debug ( $ "Kotlin: Hiding implementation method { method . DeclaringType ? . ThisClass . Name . Value } - { method . Name } ") ;
78
+ method . AccessFlags = MethodAccessFlags . Private ;
70
79
}
71
80
72
- foreach ( var method in klass . Methods )
73
- if ( method . Name . Contains ( "-impl" ) ) {
74
- Log . Debug ( $ "Kotlin: Hiding implementation method { method . DeclaringType ? . ThisClass . Name . Value } - { method . Name } ") ;
75
- method . AccessFlags = MethodAccessFlags . Private ;
76
- } else if ( method . Name . Contains ( "-deprecated" ) ) {
77
- Log . Debug ( $ "Kotlin: Hiding deprecated method { method . DeclaringType ? . ThisClass . Name . Value } - { method . Name } ") ;
78
- method . AccessFlags = MethodAccessFlags . Private ;
79
- } else if ( method . AccessFlags . HasFlag ( MethodAccessFlags . Static ) && method . GetParameters ( ) . FirstOrDefault ( ) ? . Name == "$this" ) {
80
- Log . Debug ( $ "Kotlin: Hiding extension method { method . DeclaringType ? . ThisClass . Name . Value } - { method . Name } ") ;
81
- method . AccessFlags = MethodAccessFlags . Private ;
82
- }
81
+ // Better parameter names in extension methods
82
+ foreach ( var method in methods . Where ( m => m . IsPubliclyVisible && m . AccessFlags . HasFlag ( MethodAccessFlags . Static ) ) )
83
+ FixupExtensionMethod ( method ) ;
83
84
}
84
85
85
86
static void FixupConstructor ( MethodInfo method , KotlinConstructor metadata )
@@ -97,16 +98,17 @@ static void FixupConstructor (MethodInfo method, KotlinConstructor metadata)
97
98
98
99
static void FixupFunction ( MethodInfo method , KotlinFunction metadata , KotlinClass kotlinClass )
99
100
{
100
- if ( method is null )
101
+ if ( method is null || ! method . IsPubliclyVisible )
101
102
return ;
102
103
103
104
// Hide function if it isn't Public/Protected
104
- if ( method . IsPubliclyVisible && ! metadata . Flags . IsPubliclyVisible ( ) ) {
105
+ if ( ! metadata . Flags . IsPubliclyVisible ( ) ) {
105
106
Log . Debug ( $ "Kotlin: Hiding internal method { method . DeclaringType ? . ThisClass . Name . Value } - { metadata . GetSignature ( ) } ") ;
106
107
method . AccessFlags = MethodAccessFlags . Private ;
107
108
return ;
108
109
}
109
110
111
+ // Kotlin provides actual parameter names
110
112
var java_parameters = method . GetFilteredParameters ( ) ;
111
113
112
114
for ( var i = 0 ; i < java_parameters . Length ; i ++ ) {
@@ -120,6 +122,18 @@ static void FixupFunction (MethodInfo method, KotlinFunction metadata, KotlinCla
120
122
}
121
123
}
122
124
125
+ static void FixupExtensionMethod ( MethodInfo method )
126
+ {
127
+ // Kotlin "extension" methods give the first parameter an ugly name
128
+ // like "$this$toByteString", we change it to "obj" to be a bit nicer.
129
+ var param = method . GetParameters ( ) ;
130
+
131
+ if ( param . Length > 0 && param [ 0 ] . Name . StartsWith ( "$this$" ) ) {
132
+ Log . Debug ( $ "Kotlin: Renaming extension parameter { method . DeclaringType ? . ThisClass . Name . Value } - { method . Name } - { param [ 0 ] . Name } -> obj") ;
133
+ param [ 0 ] . Name = "obj" ;
134
+ }
135
+ }
136
+
123
137
static void FixupProperty ( MethodInfo getter , MethodInfo setter , KotlinProperty metadata )
124
138
{
125
139
if ( getter is null && setter is null )
@@ -142,7 +156,7 @@ static void FixupProperty (MethodInfo getter, MethodInfo setter, KotlinProperty
142
156
}
143
157
144
158
if ( setter != null ) {
145
- var setter_parameter = setter . GetParameters ( ) [ 0 ] ;
159
+ var setter_parameter = setter . GetParameters ( ) . First ( ) ;
146
160
147
161
if ( setter_parameter . IsUnnamedParameter ( ) && ! metadata . SetterValueParameter . IsUnnamedParameter ( ) ) {
148
162
Log . Debug ( $ "Kotlin: Renaming setter parameter { setter . DeclaringType ? . ThisClass . Name . Value } - { setter . Name } - { setter_parameter . Name } -> { metadata . SetterValueParameter . Name } ") ;
0 commit comments