<commit_before>package org.jetbrains.plugins.scala
package injection

import com.intellij.lang.injection.{MultiHostRegistrar, MultiHostInjector}
import collection.JavaConversions._
import org.intellij.plugins.intelliLang.Configuration
import java.util.ArrayList
import com.intellij.openapi.util.{Trinity, TextRange}
import org.intellij.plugins.intelliLang.inject.InjectedLanguage
import org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport
import com.intellij.openapi.extensions.Extensions
import org.intellij.plugins.intelliLang.inject.InjectorUtils
import lang.psi.api.base.patterns.ScReferencePattern
import lang.psi.api.expr._
import lang.psi.api.statements.{ScFunction, ScPatternDefinition, ScVariableDefinition}
import lang.psi.api.base.{ScReferenceElement, ScLiteral}
import com.intellij.psi._

/**
 * <NAME>
 */

class ScalaLanguageInjector(myInjectionConfiguration: Configuration) extends MultiHostInjector {
  def elementsToInjectIn = List(classOf[ScLiteral], classOf[ScInfixExpr])

  private def literalsOf(host: PsiElement): Seq[ScLiteral] = {
    if(host.getParent.isInstanceOf[ScInfixExpr])
      return Seq.empty // process top-level expressions only

    val expressions = host.depthFirst.filter(_.isInstanceOf[ScExpression]).toList

    val suitable = expressions.forall(_ match {
      case l: ScLiteral if l.isString => true
      case r: ScReferenceExpression if r.getText == "+" => true
      case _: ScInfixExpr => true
      case _ => false
    })

    if(suitable)
      expressions.filter(_.isInstanceOf[ScLiteral]).map(_.asInstanceOf[ScLiteral])
    else
      Seq.empty
  }

  def getLanguagesToInject(registrar: MultiHostRegistrar, host: PsiElement) {
    val literals = literalsOf(host)

    if(literals.isEmpty) return

    val expression = host.asInstanceOf[ScExpression]
    // TODO implicit conversion checking (SCL-2599), disabled (performance reasons)
    val annotationOwner = annotationOwnerFor(expression)//.orElse(implicitAnnotationOwnerFor(literal))
    val languageId = annotationOwner.flatMap(extractLanguage(_, myInjectionConfiguration.getLanguageAnnotationClass))
    val language = languageId.flatMap(it => InjectedLanguage.findLanguageById(it).toOption)

    language.foreach { it =>
      registrar.startInjecting(it)

      literals.foreach { literal =>
        registrar.addPlace("", "", literal.asInstanceOf[PsiLanguageInjectionHost],
          ScalaStringLiteralManipulator.getLiteralRange(literal.getText))
      }

      registrar.doneInjecting()
    }

    if (language.isDefined) return

    var done = false

    Extensions.getExtensions(LanguageInjectionSupport.EP_NAME).find(_.getId == "scala").foreach { support =>
      myInjectionConfiguration.getInjections(support.getId)
              .view.takeWhile(_ => !done).filter(_.acceptsPsiElement(host)).foreach { injection =>
        val language = InjectedLanguage.findLanguageById(injection.getInjectedLanguageId)
        if (language != null) {
          val injectedLanguage = InjectedLanguage.create(injection.getInjectedLanguageId, injection.getPrefix, injection.getSuffix, false)
          val list = new ArrayList[Trinity[PsiLanguageInjectionHost, InjectedLanguage, TextRange]]
          for (range <- injection.getInjectedArea(host)) {
            list.add(Trinity.create(host.asInstanceOf[PsiLanguageInjectionHost], injectedLanguage, range))
          }
          InjectorUtils.registerInjection(language, list, host.getContainingFile, registrar)
          InjectorUtils.registerSupport(support, true, registrar)
          done = true
        }
      }
    }
  }

  def annotationOwnerFor(literal: ScExpression): Option[PsiAnnotationOwner] = literal.getParent match {
    case pattern: ScPatternDefinition => Some(pattern)
    case variable: ScVariableDefinition => Some(variable)
    case _: ScArgumentExprList => parameterOf(literal)
    case assignment: ScAssignStmt => assignmentTarget(assignment)
    case _ => None
  }

  def implicitAnnotationOwnerFor(literal: ScLiteral): Option[PsiAnnotationOwner] = {
    literal.getImplicitConversions._2.flatMap(_.asOptionOf(classOf[ScFunction])).flatMap(_.parameters.headOption)
  }

  private def assignmentTarget(assignment: ScAssignStmt): Option[PsiAnnotationOwner] = {<commit_msg>Concatenation support for pattern injection<commit_after>package org.jetbrains.plugins.scala
package injection

import com.intellij.lang.injection.{MultiHostRegistrar, MultiHostInjector}
import collection.JavaConversions._
import org.intellij.plugins.intelliLang.Configuration
import java.util.ArrayList
import com.intellij.openapi.util.{Trinity, TextRange}
import org.intellij.plugins.intelliLang.inject.InjectedLanguage
import org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport
import com.intellij.openapi.extensions.Extensions
import org.intellij.plugins.intelliLang.inject.InjectorUtils
import lang.psi.api.base.patterns.ScReferencePattern
import lang.psi.api.expr._
import lang.psi.api.statements.{ScFunction, ScPatternDefinition, ScVariableDefinition}
import lang.psi.api.base.{ScReferenceElement, ScLiteral}
import com.intellij.psi._

/**
 * <NAME>
 */

class ScalaLanguageInjector(myInjectionConfiguration: Configuration) extends MultiHostInjector {
  override def elementsToInjectIn = List(classOf[ScLiteral], classOf[ScInfixExpr])

  override def getLanguagesToInject(registrar: MultiHostRegistrar, host: PsiElement) {
    val literals = literalsOf(host)

    if (literals.isEmpty) return

    if (injectUsingAnnotation(registrar, host, literals)) return

    injectUsingPatterns(registrar, host, literals)
  }

  private def literalsOf(host: PsiElement): Seq[ScLiteral] = {
    if(host.getParent.isInstanceOf[ScInfixExpr])
      return Seq.empty // process top-level expressions only

    val expressions = host.depthFirst.filter(_.isInstanceOf[ScExpression]).toList

    val suitable = expressions.forall(_ match {
      case l: ScLiteral if l.isString => true
      case r: ScReferenceExpression if r.getText == "+" => true
      case _: ScInfixExpr => true
      case _ => false
    })

    if(suitable)
      expressions.filter(_.isInstanceOf[ScLiteral]).map(_.asInstanceOf[ScLiteral])
    else
      Seq.empty
  }

  def injectUsingAnnotation(registrar: MultiHostRegistrar, host: PsiElement, literals: scala.Seq[ScLiteral]): Boolean = {
    val expression = host.asInstanceOf[ScExpression]
    // TODO implicit conversion checking (SCL-2599), disabled (performance reasons)
    val annotationOwner = annotationOwnerFor(expression) //.orElse(implicitAnnotationOwnerFor(literal))
    val languageId = annotationOwner.flatMap(extractLanguage(_, myInjectionConfiguration.getLanguageAnnotationClass))
    val language = languageId.flatMap(it => InjectedLanguage.findLanguageById(it).toOption)

    language.foreach { it =>
      registrar.startInjecting(it)
      literals.foreach { literal =>
        registrar.addPlace("", "", literal.asInstanceOf[PsiLanguageInjectionHost],
          ScalaStringLiteralManipulator.getLiteralRange(literal.getText))
      }
      registrar.doneInjecting()
    }

    language.isDefined
  }

  def injectUsingPatterns(registrar: MultiHostRegistrar, host: PsiElement, literals: scala.Seq[ScLiteral]) {
    var done = false

    Extensions.getExtensions(LanguageInjectionSupport.EP_NAME).find(_.getId == "scala").foreach{support =>
      myInjectionConfiguration.getInjections(support.getId).view // non-strict evaluation
              .takeWhile(_ => !done).filter(_.acceptsPsiElement(host)).foreach{injection =>
        val language = InjectedLanguage.findLanguageById(injection.getInjectedLanguageId)
        if (language != null) {
          val injectedLanguage = InjectedLanguage.create(injection.getInjectedLanguageId, injection.getPrefix, injection.getSuffix, false)
          val list = new ArrayList[Trinity[PsiLanguageInjectionHost, InjectedLanguage, TextRange]]
          literals.foreach { literal =>
            for (range <- injection.getInjectedArea(literal)) {
              list.add(Trinity.create(literal, injectedLanguage, range))
            }
          }
          InjectorUtils.registerInjection(language, list, host.getContainingFile, registrar)
          InjectorUtils.registerSupport(support, true, registrar)
          done = true
        }
      }
    }
  }

  def annotationOwnerFor(literal: ScExpression): Option[PsiAnnotationOwner] = literal.getParent match {
    case pattern: ScPatternDefinition => Some(pattern)
    case variable: ScVariableDefinition => Some(variable)
    case _: ScArgumentExprList => parameterOf(literal)
    case assignment: ScAssignStmt => assignmentTarget(assignment)
    case _ => None
  }

  def implicitAnnotationOwnerFor(literal: ScLiteral): Option[PsiAnnotationOwner] = {
    literal.getImplicitConversions._2.flatMap(_.asOptionOf(classOf[ScFunction])).flatMap(_.parameters.headOption)
  }

  private def assignmentTarget(assignment: ScAssignStmt): Option[PsiAnnotationOwner] = {
{'fraction_non_alphanumeric': 0.09701909121357598, 'fraction_numerical': 0.0011164452383610583, 'mean_word_length': 4.522811344019729, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 36, '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': '3437299', 'n_tokens_mistral': 2549, 'n_tokens_neox': 2498, 'n_words': 445}