2727import java .util .Objects ;
2828import java .util .function .Predicate ;
2929
30+ import kotlin .jvm .JvmClassMappingKt ;
31+ import kotlin .reflect .KClass ;
3032import kotlin .reflect .KFunction ;
3133import kotlin .reflect .KParameter ;
3234import kotlin .reflect .KProperty ;
35+ import kotlin .reflect .KType ;
36+ import kotlin .reflect .full .KClasses ;
3337import kotlin .reflect .jvm .ReflectJvmMapping ;
3438import org .jspecify .annotations .NonNull ;
3539import org .jspecify .annotations .NullMarked ;
@@ -181,8 +185,23 @@ private static class KotlinDelegate {
181185
182186 public static Nullness forMethodReturnType (Method method ) {
183187 KFunction <?> function = ReflectJvmMapping .getKotlinFunction (method );
184- if (function != null && ReflectJvmMapping .getJavaType (function .getReturnType ()) != void .class ) {
185- return (function .getReturnType ().isMarkedNullable () ? Nullness .NULLABLE : Nullness .NON_NULL );
188+ if (function == null ) {
189+ String methodName = method .getName ();
190+ if (methodName .startsWith ("get" )) {
191+ String propertyName = accessorToPropertyName (methodName );
192+ KClass <?> kClass = JvmClassMappingKt .getKotlinClass (method .getDeclaringClass ());
193+ for (KProperty <?> property : KClasses .getMemberProperties (kClass )) {
194+ if (property .getName ().equals (propertyName )) {
195+ return (property .getReturnType ().isMarkedNullable () ? Nullness .NULLABLE : Nullness .NON_NULL );
196+ }
197+ }
198+ }
199+ }
200+ else {
201+ KType type = function .getReturnType ();
202+ if (ReflectJvmMapping .getJavaType (type ) != void .class ) {
203+ return (type .isMarkedNullable () ? Nullness .NULLABLE : Nullness .NON_NULL );
204+ }
186205 }
187206 return Nullness .UNSPECIFIED ;
188207 }
@@ -200,23 +219,40 @@ public static Nullness forParameter(Executable executable, int parameterIndex) {
200219 KParameter .Kind .INSTANCE .equals (p .getKind ()));
201220 }
202221 if (function == null ) {
203- return Nullness .UNSPECIFIED ;
222+ String methodName = executable .getName ();
223+ if (methodName .startsWith ("set" )) {
224+ String propertyName = accessorToPropertyName (methodName );
225+ KClass <?> kClass = JvmClassMappingKt .getKotlinClass (executable .getDeclaringClass ());
226+ for (KProperty <?> property : KClasses .getMemberProperties (kClass )) {
227+ if (property .getName ().equals (propertyName )) {
228+ return (property .getReturnType ().isMarkedNullable () ? Nullness .NULLABLE : Nullness .NON_NULL );
229+ }
230+ }
231+ }
204232 }
205- int i = 0 ;
206- for (KParameter kParameter : function .getParameters ()) {
207- if (predicate .test (kParameter ) && parameterIndex == i ++) {
208- return (kParameter .getType ().isMarkedNullable () ? Nullness .NULLABLE : Nullness .NON_NULL );
233+ else {
234+ int i = 0 ;
235+ for (KParameter kParameter : function .getParameters ()) {
236+ if (predicate .test (kParameter ) && parameterIndex == i ++) {
237+ return (kParameter .getType ().isMarkedNullable () ? Nullness .NULLABLE : Nullness .NON_NULL );
238+ }
209239 }
210240 }
211241 return Nullness .UNSPECIFIED ;
212242 }
213243
214244 public static Nullness forField (Field field ) {
215245 KProperty <?> property = ReflectJvmMapping .getKotlinProperty (field );
216- if (property != null && property . getReturnType (). isMarkedNullable () ) {
217- return Nullness .NULLABLE ;
246+ if (property != null ) {
247+ return ( property . getReturnType (). isMarkedNullable () ? Nullness .NULLABLE : Nullness . NON_NULL ) ;
218248 }
219- return Nullness .NON_NULL ;
249+ return Nullness .UNSPECIFIED ;
250+ }
251+
252+ private static String accessorToPropertyName (String method ) {
253+ char [] methodNameChars = method .toCharArray ();
254+ methodNameChars [3 ] = Character .toLowerCase (methodNameChars [3 ]);
255+ return new String (methodNameChars , 3 , methodNameChars .length - 3 );
220256 }
221257
222258 }
0 commit comments