<commit_before>package org.jetbrains.plugins.scala
package codeInsight
package hints

import java.lang.{Boolean => JBoolean}

import com.intellij.codeInsight.daemon.impl.HintRenderer
import com.intellij.codeInsight.hints.{ElementProcessingHintPass, InlayInfo, ModificationStampHolder}
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.util.Key
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiElement
import org.jetbrains.plugins.scala.extensions._
import org.jetbrains.plugins.scala.lang.psi.api.ScalaFile
import org.jetbrains.plugins.scala.lang.psi.api.statements.{ScFunction, ScValueOrVariable}
import org.jetbrains.plugins.scala.lang.psi.types.api.JavaArrayType
import org.jetbrains.plugins.scala.lang.psi.types.{ScCompoundType, ScParameterizedType, ScType}
import org.jetbrains.plugins.scala.lang.refactoring.ScTypePresentationExt
import org.jetbrains.plugins.scala.settings.annotations.Definition

class ScalaTypeHintsPass(rootElement: ScalaFile,
                         editor: Editor,
                         stampHolder: ModificationStampHolder)
  extends ElementProcessingHintPass(rootElement, editor, stampHolder) {

  import ScalaTypeHintsPass._

  override def isAvailable(virtualFile: VirtualFile): Boolean = {
    val settings = ScalaCodeInsightSettings.getInstance
    settings.showFunctionReturnType || settings.showPropertyType || settings.showLocalVariableType
  }

  override def collectElementHints(element: PsiElement, collector: kotlin.jvm.functions.Function2[_ >: Integer, _ >: String, kotlin.Unit]): Unit = {
    implicit val settings: ScalaCodeInsightSettings = ScalaCodeInsightSettings.getInstance
    val definition = Definition(element)

    for {
      ReturnType(returnType) <- Some(definition)
      if settings.showObviousType || !isObviousFor(returnType, definition)

      info <- createInlayInfo(definition, returnType)
    } collector.invoke(info.getOffset, info.getText)
  }

  override def getHintKey: Key[JBoolean] = ScalaTypeInlayKey

  override def createRenderer(text: String): HintRenderer = new HintRenderer(text) {
    override def getContextMenuGroupId: String = "TypeHintsMenu"
  }
}

object ScalaTypeHintsPass {

  import Definition._

  private val ScalaTypeInlayKey = Key.create[JBoolean]("SCALA_TYPE_INLAY_KEY")

  private object ReturnType {

    def unapply(definition: Definition)
               (implicit settings: ScalaCodeInsightSettings): Option[ScType] =
      definition match {
        case ValueDefinition(value) => unapply(value)
        case VariableDefinition(variable) => unapply(variable)
        case FunctionDefinition(function) => unapply(function)
        case _ => None
      }

    private def unapply(member: ScValueOrVariable)
                       (implicit settings: ScalaCodeInsightSettings) = {
      val flag = if (member.isLocal) settings.showLocalVariableType else settings.showPropertyType
      if (flag) member.`type`().toOption else None
    }

    private def unapply(member: ScFunction)
                       (implicit settings: ScalaCodeInsightSettings) =
      if (settings.showFunctionReturnType) member.returnType.toOption
      else None
  }

  private def isObviousFor(returnType: ScType, definition: Definition): Boolean =
    definition.hasStableType ||
      definition.bodyCandidate
        .zip(returnType.extractClass)
        .exists {
          case (ReferenceName(name, _), clazz) =>
            !name.mismatchesCamelCase(clazz.name)
          case _ => false
        }

  private def createInlayInfo(definition: Definition, returnType: ScType)
                             (implicit settings: ScalaCodeInsightSettings) = for {
    anchor <- definition.parameterList
    offset = anchor.getTextRange.getEndOffset

    CodeText(codeText) <- Some(returnType)
    suffix = definition match {
      case FunctionDefinition(function) if !function.hasAssign && function.hasUnitResultType => " ="
      case _ => ""
    }
    text = s": " + codeText + suffix
  } yield new InlayInfo(text, offset, false, true, true)

  private[this] object CodeText {

    def unapply(`type`: ScType)
               (implicit settings: ScalaCodeInsightSettings): Option[String] =
      `type` match {<commit_msg>obviousness of type regardless its stability #SCL-14277 fixed<commit_after>package org.jetbrains.plugins.scala
package codeInsight
package hints

import java.lang.{Boolean => JBoolean}

import com.intellij.codeInsight.daemon.impl.HintRenderer
import com.intellij.codeInsight.hints.{ElementProcessingHintPass, InlayInfo, ModificationStampHolder}
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.util.Key
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiElement
import org.jetbrains.plugins.scala.extensions._
import org.jetbrains.plugins.scala.lang.psi.api.ScalaFile
import org.jetbrains.plugins.scala.lang.psi.api.statements.{ScFunction, ScValueOrVariable}
import org.jetbrains.plugins.scala.lang.psi.types.api.JavaArrayType
import org.jetbrains.plugins.scala.lang.psi.types.{ScCompoundType, ScParameterizedType, ScType}
import org.jetbrains.plugins.scala.lang.refactoring.ScTypePresentationExt
import org.jetbrains.plugins.scala.settings.annotations.Definition

class ScalaTypeHintsPass(rootElement: ScalaFile,
                         editor: Editor,
                         stampHolder: ModificationStampHolder)
  extends ElementProcessingHintPass(rootElement, editor, stampHolder) {

  import ScalaTypeHintsPass._

  override def isAvailable(virtualFile: VirtualFile): Boolean = {
    val settings = ScalaCodeInsightSettings.getInstance
    settings.showFunctionReturnType || settings.showPropertyType || settings.showLocalVariableType
  }

  override def collectElementHints(element: PsiElement, collector: kotlin.jvm.functions.Function2[_ >: Integer, _ >: String, kotlin.Unit]): Unit = {
    implicit val settings: ScalaCodeInsightSettings = ScalaCodeInsightSettings.getInstance
    val definition = Definition(element)

    for {
      ReturnType(returnType) <- Some(definition)
      if settings.showObviousType || !isObviousFor(returnType, definition)

      info <- createInlayInfo(definition, returnType)
    } collector.invoke(info.getOffset, info.getText)
  }

  override def getHintKey: Key[JBoolean] = ScalaTypeInlayKey

  override def createRenderer(text: String): HintRenderer = new HintRenderer(text) {
    override def getContextMenuGroupId: String = "TypeHintsMenu"
  }
}

object ScalaTypeHintsPass {

  import Definition._

  private val ScalaTypeInlayKey = Key.create[JBoolean]("SCALA_TYPE_INLAY_KEY")

  private object ReturnType {

    def unapply(definition: Definition)
               (implicit settings: ScalaCodeInsightSettings): Option[ScType] =
      definition match {
        case ValueDefinition(value) => unapply(value)
        case VariableDefinition(variable) => unapply(variable)
        case FunctionDefinition(function) => unapply(function)
        case _ => None
      }

    private def unapply(member: ScValueOrVariable)
                       (implicit settings: ScalaCodeInsightSettings) = {
      val flag = if (member.isLocal) settings.showLocalVariableType else settings.showPropertyType
      if (flag) member.`type`().toOption else None
    }

    private def unapply(member: ScFunction)
                       (implicit settings: ScalaCodeInsightSettings) =
      if (settings.showFunctionReturnType) member.returnType.toOption
      else None
  }

  private def isObviousFor(returnType: ScType, definition: Definition): Boolean =
      definition.bodyCandidate
        .zip(returnType.extractClass)
        .exists {
          case (ReferenceName(name, _), clazz) =>
            !name.mismatchesCamelCase(clazz.name)
          case _ => false
        }

  private def createInlayInfo(definition: Definition, returnType: ScType)
                             (implicit settings: ScalaCodeInsightSettings) = for {
    anchor <- definition.parameterList
    offset = anchor.getTextRange.getEndOffset

    CodeText(codeText) <- Some(returnType)
    suffix = definition match {
      case FunctionDefinition(function) if !function.hasAssign && function.hasUnitResultType => " ="
      case _ => ""
    }
    text = s": " + codeText + suffix
  } yield new InlayInfo(text, offset, false, true, true)

  private[this] object CodeText {

    def unapply(`type`: ScType)
               (implicit settings: ScalaCodeInsightSettings): Option[String] =
      `type` match {
{'fraction_non_alphanumeric': 0.08890720678285445, 'fraction_numerical': 0.0008243052284503062, 'mean_word_length': 3.814625850340136, 'pattern_counts': {'":': 2, '<': 11, '<?xml version=': 0, '>': 25, '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': '7492339', 'n_tokens_mistral': 2453, 'n_tokens_neox': 2353, 'n_words': 482}