<commit_before>package org.jetbrains.plugins.scala
package codeInsight
package intention
package types

import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction
import com.intellij.openapi.project.Project
import com.intellij.openapi.editor.Editor
import lang.psi.api.expr.{ScGenericCall, ScMethodCall, ScReferenceExpression}
import lang.psi.types.result.TypingContext
import lang.psi.types.nonvalue.ScTypePolymorphicType
import lang.psi.api.statements.ScFunction
import extensions._
import com.intellij.psi.{PsiTypeParameterListOwner, PsiIdentifier, PsiElement}
import lang.psi.ScalaPsiUtil
import lang.psi.types.ScType
import lang.psi.impl.ScalaPsiElementFactory

// TODO move messages to the localisation bundle.
class ToggleTypeArgs extends PsiElementBaseIntentionAction {
  def getFamilyName = "Toggle Type Args"

  def isAvailable(project: Project, editor: Editor, element: PsiElement) = {
    check(element) match {
      case MethodCallWithInferedTypeArgs(call, inferred) =>
        val args = inferred.map(ScType.urlText).mkString("[", ", ", "]")
        setText("Explicitly provide inferred type arguments: %s".format(args))
        true
      case _ => false
    }
  }

  override def invoke(project: Project, editor: Editor, element: PsiElement) {
    check(element) match {
      case MethodCallWithInferedTypeArgs(call, inferred) =>
        val methodCallText = call.getText
        val x = call.getInvokedExpr.getTextLength
        val (start, end) = methodCallText.splitAt(x)
        val args = inferred.map(ScType.canonicalText).mkString("[", ", ", "]")
        val newMethodCallText = start + args + end
        val newMethodCall = ScalaPsiElementFactory.createExpressionFromText(newMethodCallText, call.getManager)
        call.replace(newMethodCall)
      case Other =>
    }
  }

  private def check(element: PsiElement): TypeArgResult = {
    val refExprOpt = for {
      re <- element.getContext.asOptionOf[ScReferenceExpression]
    } yield re

    val genericCallOpt = for {
      re <- refExprOpt
      gc <- re.getContext.asOptionOf[ScGenericCall]
    } yield gc

    val referencedTypeParamOwner = for {
      re <- refExprOpt
      resolveResult <- re.advancedResolve
      typeParamOwner <- resolveResult.element.asOptionOf[PsiTypeParameterListOwner] // TODO follow aliases
    } yield (resolveResult, typeParamOwner)

    val typeParamsOpt = for {
      re <- refExprOpt
      mc <- re.getContext.asOptionOf[ScMethodCall]
      mcTpe <- mc.getNonValueType(TypingContext.empty).toOption
      tpTpe <- mcTpe.asOptionOf[ScTypePolymorphicType]
      val pts = tpTpe.polymorphicTypeSubstitutor
    } yield (mc, tpTpe.typeParameters, pts)

    // TODO: calls to constructors, java generic methods/constructors.
    // TODO: detect if the provided arguments could be omitted without changing the result type of the method call,
    //       and offer to remove them.
    val result = (referencedTypeParamOwner, genericCallOpt, typeParamsOpt) match {
      case (Some((resolveResult, typeParamOwner)), None, Some((mc, typeParams, subst))) =>
        val tps = typeParamOwner.getTypeParameters
        val inferredTypes = tps.map {tp =>
          val key = (tp.getName, ScalaPsiUtil.getPsiElementId(tp))
          subst.tvMap.get(key)
        }
        if (inferredTypes.contains(None)) Other else MethodCallWithInferedTypeArgs(mc, inferredTypes.map(_.get))
      case _ => Other
    }
    result
  }

  sealed abstract class TypeArgResult
  case class MethodCallWithInferedTypeArgs(call: ScMethodCall, inferredArgs: Seq[ScType]) extends TypeArgResult
  case object Other extends TypeArgResult
}<commit_msg>fix tooltip text<commit_after>package org.jetbrains.plugins.scala
package codeInsight
package intention
package types

import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction
import com.intellij.openapi.project.Project
import com.intellij.openapi.editor.Editor
import lang.psi.api.expr.{ScGenericCall, ScMethodCall, ScReferenceExpression}
import lang.psi.types.result.TypingContext
import lang.psi.types.nonvalue.ScTypePolymorphicType
import lang.psi.api.statements.ScFunction
import extensions._
import com.intellij.psi.{PsiTypeParameterListOwner, PsiIdentifier, PsiElement}
import lang.psi.ScalaPsiUtil
import lang.psi.types.ScType
import lang.psi.impl.ScalaPsiElementFactory

// TODO move messages to the localisation bundle.
class ToggleTypeArgs extends PsiElementBaseIntentionAction {
  def getFamilyName = "Toggle Type Args"

  def isAvailable(project: Project, editor: Editor, element: PsiElement) = {
    check(element) match {
      case MethodCallWithInferedTypeArgs(call, inferred) =>
        val args = inferred.map(ScType.presentableText).mkString("[", ", ", "]")
        setText("Explicitly provide inferred type arguments: %s".format(args))
        true
      case _ => false
    }
  }

  override def invoke(project: Project, editor: Editor, element: PsiElement) {
    check(element) match {
      case MethodCallWithInferedTypeArgs(call, inferred) =>
        val methodCallText = call.getText
        val x = call.getInvokedExpr.getTextLength
        val (start, end) = methodCallText.splitAt(x)
        val args = inferred.map(ScType.canonicalText).mkString("[", ", ", "]")
        val newMethodCallText = start + args + end
        val newMethodCall = ScalaPsiElementFactory.createExpressionFromText(newMethodCallText, call.getManager)
        call.replace(newMethodCall)
      case Other =>
    }
  }

  private def check(element: PsiElement): TypeArgResult = {
    val refExprOpt = for {
      re <- element.getContext.asOptionOf[ScReferenceExpression]
    } yield re

    val genericCallOpt = for {
      re <- refExprOpt
      gc <- re.getContext.asOptionOf[ScGenericCall]
    } yield gc

    val referencedTypeParamOwner = for {
      re <- refExprOpt
      resolveResult <- re.advancedResolve
      typeParamOwner <- resolveResult.element.asOptionOf[PsiTypeParameterListOwner] // TODO follow aliases
    } yield (resolveResult, typeParamOwner)

    val typeParamsOpt = for {
      re <- refExprOpt
      mc <- re.getContext.asOptionOf[ScMethodCall]
      mcTpe <- mc.getNonValueType(TypingContext.empty).toOption
      tpTpe <- mcTpe.asOptionOf[ScTypePolymorphicType]
      val pts = tpTpe.polymorphicTypeSubstitutor
    } yield (mc, tpTpe.typeParameters, pts)

    // TODO: calls to constructors, java generic methods/constructors.
    // TODO: detect if the provided arguments could be omitted without changing the result type of the method call,
    //       and offer to remove them.
    val result = (referencedTypeParamOwner, genericCallOpt, typeParamsOpt) match {
      case (Some((resolveResult, typeParamOwner)), None, Some((mc, typeParams, subst))) =>
        val tps = typeParamOwner.getTypeParameters
        val inferredTypes = tps.map {tp =>
          val key = (tp.getName, ScalaPsiUtil.getPsiElementId(tp))
          subst.tvMap.get(key)
        }
        if (inferredTypes.contains(None)) Other else MethodCallWithInferedTypeArgs(mc, inferredTypes.map(_.get))
      case _ => Other
    }
    result
  }

  sealed abstract class TypeArgResult
  case class MethodCallWithInferedTypeArgs(call: ScMethodCall, inferredArgs: Seq[ScType]) extends TypeArgResult
  case object Other extends TypeArgResult
}
{'fraction_non_alphanumeric': 0.08987532538703932, 'fraction_numerical': 0.0, 'mean_word_length': 3.737183646982479, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 17, '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': '3526524', 'n_tokens_mistral': 2165, 'n_tokens_neox': 2099, 'n_words': 500}