<commit_before>package io.sento.compiler.annotations

import com.google.common.reflect.AbstractInvocationHandler
import io.sento.compiler.reflect.AnnotationSpec
import java.lang.reflect.Method
import java.lang.reflect.Proxy
import java.util.ArrayList
import java.util.HashMap

internal object AnnotationProxy {
  fun <A> create(clazz: Class<A>, spec: AnnotationSpec): A {
    return clazz.cast(Proxy.newProxyInstance(clazz.classLoader, arrayOf(clazz), object : AbstractInvocationHandler() {
      private val cache = HashMap<String, Any?>()

      private val string by lazy(LazyThreadSafetyMode.NONE) {
        cache.map { "${it.key}=${it.value}" }.joinToString(", ")
      }

      init {
        for ((key, value) in spec.values) {
          if (value != null) {
            cache.put(key, resolve(clazz.getMethod(key).returnType, value))
          }
        }
      }

      override fun handleInvocation(proxy: Any, method: Method, args: Array<out Any>): Any? {
        return cache[method.name]
      }

      override fun toString(): String {
        return "@${clazz.canonicalName}($string)"
      }
    }))
  }

  private fun resolve(type: Class<*>, value: Any): Any {
    return when {
      isArray(type) -> resolveArray(type.componentType, value)
      isAnnotation(type) -> resolveAnnotation(type, value)
      else -> resolveValue(type, value)<commit_msg>Make AnnotationProxy more reliable<commit_after>package io.sento.compiler.annotations

import com.google.common.reflect.AbstractInvocationHandler
import io.sento.compiler.reflect.AnnotationSpec
import java.lang.reflect.Method
import java.lang.reflect.Proxy
import java.util.ArrayList
import java.util.HashMap

internal object AnnotationProxy {
  fun <A> create(clazz: Class<A>, spec: AnnotationSpec): A {
    return clazz.cast(Proxy.newProxyInstance(clazz.classLoader, arrayOf(clazz), object : AbstractInvocationHandler() {
      private val cache = HashMap<String, Any?>()

      private val string by lazy(LazyThreadSafetyMode.NONE) {
        cache.map { "${it.key}=${it.value}" }.joinToString(", ")
      }

      init {
        for ((key, value) in spec.values) {
          if (value != null) {
            try {
              cache.put(key, resolve(clazz.getMethod(key).returnType, value))
            } catch (exception: NoSuchMethodException) {
              // just ignore
            }
          }
        }
      }

      override fun handleInvocation(proxy: Any, method: Method, args: Array<out Any>): Any? {
        return cache[method.name]
      }

      override fun toString(): String {
        return "@${clazz.canonicalName}($string)"
      }
    }))
  }

  private fun resolve(type: Class<*>, value: Any): Any {
    return when {
      isArray(type) -> resolveArray(type.componentType, value)
      isAnnotation(type) -> resolveAnnotation(type, value)
      else -> resolveValue(type, value)
{'fraction_non_alphanumeric': 0.12400138937130949, 'fraction_numerical': 0.0, 'mean_word_length': 3.01673640167364, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7062591', 'n_tokens_mistral': 835, 'n_tokens_neox': 823, 'n_words': 188}