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

import com.intellij.patterns.PlatformPatterns
import org.jetbrains.plugins.scala.lang.lexer.ScalaTokenTypes
import com.intellij.util.ProcessingContext
import com.intellij.codeInsight.completion._
import org.jetbrains.plugins.scala.lang.psi.api.expr.{ScMethodCall, ScAssignStmt, ScReferenceExpression}
import org.jetbrains.plugins.scala.lang.psi.api.base.ScReferenceElement
import com.intellij.codeInsight.lookup.LookupElement
import org.jetbrains.plugins.scala.lang.psi.types.{ScSubstitutor, Nothing, ScType}
import org.jetbrains.plugins.scala.lang.psi.api.statements.ScFunction
import org.jetbrains.plugins.scala.lang.psi.impl.toplevel.synthetic.ScSyntheticFunction
import com.intellij.psi.{PsiMethod, PsiElement}
import org.jetbrains.plugins.scala.lang.psi.api.toplevel.ScTyped

/**
 * User: <NAME>
 * Date: 17.09.2009
 */

class ScalaSmartCompletionContributor extends CompletionContributor {
  extend(CompletionType.SMART, PlatformPatterns.psiElement(ScalaTokenTypes.tIDENTIFIER),
    new CompletionProvider[CompletionParameters] {
      def addCompletions(parameters: CompletionParameters, context: ProcessingContext, result: CompletionResultSet): Unit = {
        val element = parameters.getPosition
        if (element.getNode.getElementType != ScalaTokenTypes.tIDENTIFIER) return
        element.getParent match {
          case ref: ScReferenceExpression => {
            def expectedType: ScType = {
              ref.getParent match {
              // f = ref | f(...) = ref
                case assign: ScAssignStmt if assign.getRExpression == Some(ref) => {
                  val leftExpr = assign.getLExpression
                  leftExpr match {
                    case call: ScMethodCall => {
                      //todo:
                      return Nothing
                    }
                    case _ => {
                      //we can expect that the type is same for left and right parts.
                      return leftExpr.cachedType
                    }
                  }
                }
                case _ => return Nothing //todo:
              }
            }
            val tp = expectedType
            if (tp == Nothing) return
            val variants = ref.getVariants
            for (variant <- variants) {
              variant match {
                case (el: LookupElement, elem: PsiElement, subst: ScSubstitutor) => {
                  def checkType(typez: ScType): Unit = {
                    if (subst.subst(typez) conforms tp) result.addElement(el)
                  }
                  elem match {
                    case fun: ScSyntheticFunction => checkType(fun.retType)
                    case fun: ScFunction => checkType(fun.returnType)
                    case meth: PsiMethod => checkType(ScType.create(meth.getReturnType, meth.getProject))
                    case typed: ScTyped => checkType(typed.calcType)
                    case _ =>
                  }
                }
                case _ =>
              }
            }
          }
          case _ => //todo:
        }
      }
    })
}<commit_msg>Smart completion rewrited in more good style. Smart completion in case: var x: Type = ref<commit_after>package org.jetbrains.plugins.scala.lang.completion

import org.jetbrains.plugins.scala.lang.lexer.ScalaTokenTypes
import com.intellij.util.ProcessingContext
import com.intellij.codeInsight.completion._
import org.jetbrains.plugins.scala.lang.psi.api.base.ScReferenceElement
import com.intellij.codeInsight.lookup.LookupElement
import org.jetbrains.plugins.scala.lang.psi.impl.toplevel.synthetic.ScSyntheticFunction
import org.jetbrains.plugins.scala.lang.psi.api.toplevel.ScTyped
import org.jetbrains.plugins.scala.lang.psi.api.statements.{ScVariableDefinition, ScPatternDefinition, ScFunction}
import org.jetbrains.plugins.scala.lang.psi.api.expr._
import com.intellij.psi.{PsiClass, PsiMethod, PsiElement}
import org.jetbrains.plugins.scala.lang.psi.impl.toplevel.typedef.TypeDefinitionMembers
import org.jetbrains.plugins.scala.lang.psi.ScalaPsiUtil
import collection.mutable.ArrayBuffer
import org.jetbrains.plugins.scala.lang.psi.types.{ScFunctionType, ScSubstitutor, Nothing, ScType}
import com.intellij.patterns.{ElementPattern, StandardPatterns, PlatformPatterns}

/**
 * User: <NAME>
 * Date: 17.09.2009
 */

class ScalaSmartCompletionContributor extends CompletionContributor {
  private def acceptTypes(typez: Seq[ScType], variants: Array[Object], result: CompletionResultSet) {
    if (typez.length == 0 || typez.forall(_ == Nothing)) return
    for (variant <- variants) {
      variant match {
        case (el: LookupElement, elem: PsiElement, subst: ScSubstitutor) => {
          def checkType(tp: ScType): Unit = {
            if (typez.find(subst.subst(tp) conforms _) != None) result.addElement(el)
          }
          elem match {
            case fun: ScSyntheticFunction => checkType(fun.retType)
            case fun: ScFunction => checkType(fun.returnType)
            case meth: PsiMethod => checkType(ScType.create(meth.getReturnType, meth.getProject))
            case typed: ScTyped => checkType(typed.calcType)
            case _ =>
          }
        }
        case _ =>
      }
    }
  }

  private def superParentPattern(clazz: java.lang.Class[_ <: PsiElement]): ElementPattern[PsiElement] = {
    PlatformPatterns.psiElement(ScalaTokenTypes.tIDENTIFIER).withParent(classOf[ScReferenceExpression]).
          withSuperParent(2, clazz)
  }

  /*
    ref = expr
    expr = ref
   */
  extend(CompletionType.SMART, superParentPattern(classOf[ScAssignStmt]), new CompletionProvider[CompletionParameters] {
    def addCompletions(parameters: CompletionParameters, context: ProcessingContext, result: CompletionResultSet): Unit = {
      val element = parameters.getPosition
      val ref = element.getParent.asInstanceOf[ScReferenceExpression]
      val assign = ref.getParent.asInstanceOf[ScAssignStmt]
      if (assign.getRExpression == Some(ref)) {
        assign.getLExpression match {
          case call: ScMethodCall => //todo: it's update method
          case leftExpression: ScExpression => {
            //we can expect that the type is same for left and right parts.
            acceptTypes(Seq[ScType](leftExpression.cachedType), ref.getVariants, result)
          }
        }
      } else { //so it's left expression
        //todo: if right expression exists?
      }
    }
  })

  /*
    val x: Type = ref
    var y: Type = ref
   */
  extend(CompletionType.SMART, StandardPatterns.or[PsiElement](superParentPattern(classOf[ScPatternDefinition]),
    superParentPattern(classOf[ScVariableDefinition])), new CompletionProvider[CompletionParameters] {
    def addCompletions(parameters: CompletionParameters, context: ProcessingContext, result: CompletionResultSet): Unit = {
      val element = parameters.getPosition
      val ref = element.getParent.asInstanceOf[ScReferenceExpression]
      ref.getParent match {
        case patternDefinition: ScPatternDefinition => acceptTypes(Seq[ScType](patternDefinition.getType), ref.getVariants, result)
        case variableDefinition: ScVariableDefinition => acceptTypes(Seq[ScType](variableDefinition.getType), ref.getVariants, result)
      }
    }
  })

  /*
    call(exprs, ref, exprs)
   */
  extend(CompletionType.SMART, superParentPattern(classOf[ScArgumentExprList]), new CompletionProvider[CompletionParameters] {
    def addCompletions(parameters: CompletionParameters, context: ProcessingContext, result: CompletionResultSet): Unit = {
      val element = parameters.getPosition
      val ref = element.getParent.asInstanceOf[ScReferenceExpression]
      val assign = ref.getParent.asInstanceOf[ScArgumentExprList]
      /*val index = arg.exprs.findIndexOf(_ == ref)
      if (index == -1) return
      arg.callExpression match {
        case refExpr: ScReferenceExpression => //todo:
        case expr: ScExpression => {
          val tp = expr.cachedType
          tp match {
            case funType: ScFunctionType => {
              val params = funType.params
              if (params.length > index) {
                typez += params(index)
              }
              return
            }
            case _ =>
          }
          ScType.extractClassType(tp) match {
            case Some((clazz: PsiClass, subst: ScSubstitutor)) => {
              for ( method <- ScalaPsiUtil.getApplyMethods(clazz) ) {
                method match {
                  case fun: ScFunction => {

                  }
                  case method: PsiMethod => {

                  }
                }
              }
            }
            case _ =>
          }
        }
      }*/
    }
  })
}
{'fraction_non_alphanumeric': 0.09377093101138648, 'fraction_numerical': 0.0021210091538289796, 'mean_word_length': 2.278082693011343, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 38, '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': '7063524', 'n_tokens_mistral': 2557, 'n_tokens_neox': 2392, 'n_words': 476}