<commit_before>package org.jetbrains.plugins.scala.lang.references

import com.intellij.openapi.util.TextRange
import com.intellij.patterns.PsiJavaElementPattern
import com.intellij.patterns.PsiJavaPatterns.psiElement
import com.intellij.psi._
import com.intellij.psi.impl.source.resolve.reference.ArbitraryPlaceUrlReferenceProvider
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FilePathReferenceProvider
import com.intellij.psi.tree.TokenSet
import com.intellij.util.ProcessingContext
import org.jetbrains.plugins.scala.extensions._
import org.jetbrains.plugins.scala.lang.lexer.ScalaTokenTypes
import org.jetbrains.plugins.scala.lang.psi.api.base.patterns.ScInterpolationPattern
import org.jetbrains.plugins.scala.lang.psi.api.base.{ScInterpolated, ScInterpolatedStringLiteral, ScLiteral}
import org.jetbrains.plugins.scala.lang.psi.api.expr.{ScExpression, ScReferenceExpression}
import org.jetbrains.plugins.scala.lang.psi.impl.ScalaPsiElementFactory
import org.jetbrains.plugins.scala.lang.psi.impl.expr.ScInterpolatedExpressionPrefix

import scala.collection.mutable.ListBuffer

class ScalaReferenceContributor extends PsiReferenceContributor {

  override def registerReferenceProviders(registrar: PsiReferenceRegistrar) {

    def literalCapture: PsiJavaElementPattern.Capture[ScLiteral] = psiElement(classOf[ScLiteral])

    registrar.registerReferenceProvider(literalCapture, new ScalaFilePathReferenceProvider(false))
    registrar.registerReferenceProvider(literalCapture, new InterpolatedStringReferenceProvider())
    registrar.registerReferenceProvider(literalCapture, new ArbitraryPlaceUrlReferenceProvider())
  }
}

private class InterpolatedStringReferenceProvider extends PsiReferenceProvider {

  override def getReferencesByElement(element: PsiElement, context: ProcessingContext): Array[PsiReference] = {
    element match {
      case _: ScInterpolatedStringLiteral => PsiReference.EMPTY_ARRAY
      case l: ScLiteral if (l.isString || l.isMultiLineString) && l.textContains('$') =>
        val interpolated = ScalaPsiElementFactory.createExpressionFromText("s" + l.getText, l.getContext)
        val references = interpolated.getChildren.filter {
          case _: ScInterpolatedExpressionPrefix => false
          case _: ScReferenceExpression             => true
          case _                                    => false
        }
        references.map { ref =>
          new InterpolatedStringPsiReference(ref.asInstanceOf[ScReferenceExpression], l, interpolated)
        }
      case _ => PsiReference.EMPTY_ARRAY
    }
  }
}

private class InterpolatedStringPsiReference(ref: ScReferenceExpression, literal: ScLiteral, interpolated: ScExpression) extends PsiReference {
  override def getCanonicalText: String = ref.getCanonicalText

  override def getElement: PsiElement = literal
<commit_msg>AutoMerge branch 'idea192.x-adkozlov'<commit_after>package org.jetbrains.plugins.scala
package lang
package references

import com.intellij.openapi.util.TextRange
import com.intellij.patterns.PsiJavaElementPattern
import com.intellij.patterns.PsiJavaPatterns.psiElement
import com.intellij.psi._
import com.intellij.psi.impl.source.resolve.reference.ArbitraryPlaceUrlReferenceProvider
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FilePathReferenceProvider
import com.intellij.psi.tree.TokenSet
import com.intellij.util.{IncorrectOperationException, ProcessingContext}
import org.jetbrains.plugins.scala.extensions._
import org.jetbrains.plugins.scala.lang.lexer.ScalaTokenTypes
import org.jetbrains.plugins.scala.lang.psi.api.base.patterns.ScInterpolationPattern
import org.jetbrains.plugins.scala.lang.psi.api.base.{ScInterpolated, ScInterpolatedStringLiteral, ScLiteral}
import org.jetbrains.plugins.scala.lang.psi.api.expr.{ScExpression, ScReferenceExpression}
import org.jetbrains.plugins.scala.lang.psi.impl.ScalaPsiElementFactory.createExpressionFromText

import scala.collection.mutable.ListBuffer

final class ScalaReferenceContributor extends PsiReferenceContributor {

  override def registerReferenceProviders(registrar: PsiReferenceRegistrar) {

    def literalCapture: PsiJavaElementPattern.Capture[ScLiteral] = psiElement(classOf[ScLiteral])

    registrar.registerReferenceProvider(literalCapture, new ScalaFilePathReferenceProvider(false))
    registrar.registerReferenceProvider(literalCapture, new InterpolatedStringReferenceProvider())
    registrar.registerReferenceProvider(literalCapture, new ArbitraryPlaceUrlReferenceProvider())
  }
}

private final class InterpolatedStringReferenceProvider extends PsiReferenceProvider {

  import PsiReference.EMPTY_ARRAY

  override def getReferencesByElement(element: PsiElement, context: ProcessingContext): Array[PsiReference] = element match {
    case _: ScInterpolatedStringLiteral => EMPTY_ARRAY
    case literal: ScLiteral if literal.isString && literal.textContains('$') => // TODO remove this hack
      try {
        val interpolated = createExpressionFromText("s" + literal.getText, literal.getContext)
          .asInstanceOf[ScInterpolatedStringLiteral]

        for {
          child <- interpolated.getInjections.toArray
          if child.isInstanceOf[ScReferenceExpression]
        } yield new InterpolatedStringPsiReference(
          child.asInstanceOf[ScReferenceExpression],
          literal,
          interpolated
        )
      } catch {
        case _: IncorrectOperationException => EMPTY_ARRAY
      }
    case _ => EMPTY_ARRAY
  }
}

private class InterpolatedStringPsiReference(ref: ScReferenceExpression, literal: ScLiteral, interpolated: ScExpression) extends PsiReference {
  override def getCanonicalText: String = ref.getCanonicalText

  override def getElement: PsiElement = literal

{'fraction_non_alphanumeric': 0.07749782797567333, 'fraction_numerical': 0.0005212858384013901, 'mean_word_length': 5.283842794759825, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 14, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3961994', 'n_tokens_mistral': 1601, 'n_tokens_neox': 1553, 'n_words': 264}