override fun doFunction()

in vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/functions/handlers/listFunctions/IndexOfFunctionHandler.kt [30:92]


  override fun doFunction(
    arguments: Arguments,
    editor: VimEditor,
    context: ExecutionContext,
    vimContext: VimLContext,
  ): VimInt {
    val o = arguments[0]
    val expr = arguments[1]
    val opts = arguments.getOrNull(2)

    when (o) {
      is VimList -> {
        if (expr !is VimString && expr !is VimFuncref) {
          throw exExceptionMessage("E1256", 2)
        }

        val funcref = expr as? VimFuncref
        val expression = (expr as? VimString)?.let {
          injector.vimscriptParser.parseExpression(it.value)
        }

        if (opts != null && opts !is VimDictionary) {
          throw exExceptionMessage("E1206", 3)
        }

        val startIndex = opts?.dictionary?.get(VimString("startidx"))?.toVimNumber()?.value ?: 0
        val start = if (startIndex < 0) startIndex + o.values.size else startIndex

        for (i in start until o.values.size) {
          try {
            val index = VimInt(i)
            val value = o.values[i]

            KeyVariable.key = index
            ValueVariable.value = value

            // TODO: Add test for funcref/expression returning wrong type
            val result = funcref?.execute(
              listOf(SimpleExpression(index), SimpleExpression(value)),
              range = null,
              editor,
              context,
              vimContext
            )?.toVimNumber()
              ?: expression?.evaluate(editor, context, vimContext)?.toVimNumber()
              ?: VimInt.ZERO

            if (result.booleanValue) {
              return index
            }
          } finally {
            KeyVariable.key = null
            ValueVariable.value = null
          }
        }
      }

      is VimBlob -> TODO()
      else -> throw exExceptionMessage("E1226", 1)
    }

    return VimInt.MINUS_ONE
  }