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

import com.intellij.psi.{PsiElement, PsiModifierListOwner}
import org.jetbrains.plugins.scala.lang.psi.api.expr.ScExpression
import org.jetbrains.plugins.scala.lang.psi.api.statements.{ScAnnotationsHolder, ScFunction, ScValue}
import org.jetbrains.plugins.scala.lang.psi.api.toplevel.ScModifierListOwner

/**
  * @author <NAME>
  */
trait Declaration {
  def visibility: Visibility

  def isImplicit: Boolean

  def isConstant: Boolean

  def hasUnitType: Boolean

  def typeMatches(patterns: Set[String]): Boolean

  def isAnnotatedWith(annotations: Set[String]): Boolean
}

object Declaration {
  def apply(element: PsiElement): Declaration = new PhysycalDeclaration(element)

  def apply(element: PsiElement, newVisibility: Visibility): Declaration = new PhysycalDeclaration(element) {
    override def visibility: Visibility = newVisibility
  }

  def apply(visibility: Visibility = Visibility.Default,
            isImplicit: Boolean = false,
            isConstant: Boolean = false,
            hasUnitType: Boolean = false): Declaration =
    SyntheticDeclaration(visibility, isImplicit, isConstant, hasUnitType)

  private class PhysycalDeclaration(element: PsiElement) extends Declaration {
    override def visibility: Visibility = element match {
      case owner: ScModifierListOwner =>
        if (owner.hasModifierPropertyScala("private")) Visibility.Private
        else if (owner.hasModifierPropertyScala("protected")) Visibility.Protected
        else Visibility.Default
      case owner: PsiModifierListOwner =>
        if (owner.hasModifierProperty("public")) Visibility.Default
        else if (owner.hasModifierProperty("private")) Visibility.Private
        else Visibility.Protected
      case _ => Visibility.Default
    }

    override def isImplicit: Boolean = element match {
      case owner: ScModifierListOwner => owner.hasModifierPropertyScala("implicit")
      case _ => false
    }

    override def isConstant: Boolean = element match {
      case value: ScValue => value.hasModifierPropertyScala("final")
      case _ => false
    }

    override def hasUnitType: Boolean = element match {
      case f: ScFunction => f.hasUnitResultType
      case e: ScExpression => e.getType().exists(_.isUnit)
      case _ => false
    }

    override def typeMatches(patterns: Set[String]): Boolean = false

    override def isAnnotatedWith(annotations: Set[String]): Boolean = element match {
      case holder: ScAnnotationsHolder => annotations.exists(holder.hasAnnotation)
      case _ => false
    }
  }

  private case class SyntheticDeclaration(visibility: Visibility,
                                          isImplicit: Boolean,
                                          isConstant: Boolean,
                                          hasUnitType: Boolean) extends Declaration {
    override def typeMatches(patterns: Set[String]): Boolean = false

    override def isAnnotatedWith(annotations: Set[String]): Boolean = false
  }
}<commit_msg>Declaration.typeMatches, #SCL-11618<commit_after>package org.jetbrains.plugins.scala.settings

import com.intellij.psi.{PsiElement, PsiModifierListOwner}
import org.jetbrains.plugins.scala.lang.psi.api.statements.{ScAnnotationsHolder, ScFunction, ScValue}
import org.jetbrains.plugins.scala.lang.psi.api.toplevel.ScModifierListOwner
import org.jetbrains.plugins.scala.lang.psi.types.ScType
import org.jetbrains.plugins.scala.lang.psi.types.result.Typeable

import scala.util.matching.Regex

/**
  * @author <NAME>
  */
trait Declaration {
  def visibility: Visibility

  def isImplicit: Boolean

  def isConstant: Boolean

  def hasUnitType: Boolean

  def typeMatches(patterns: Set[String]): Boolean

  def isAnnotatedWith(annotations: Set[String]): Boolean
}

object Declaration {
  private val AsteriskPattern = new Regex("(.*)\\*(.*)")

  def apply(element: PsiElement): Declaration = new PhysycalDeclaration(element)

  def apply(element: PsiElement, newVisibility: Visibility): Declaration = new PhysycalDeclaration(element) {
    override def visibility: Visibility = newVisibility
  }

  def apply(visibility: Visibility = Visibility.Default,
            isImplicit: Boolean = false,
            isConstant: Boolean = false,
            hasUnitType: Boolean = false): Declaration =
    SyntheticDeclaration(visibility, isImplicit, isConstant, hasUnitType)

  private class PhysycalDeclaration(element: PsiElement) extends Declaration {
    override def visibility: Visibility = element match {
      case owner: ScModifierListOwner =>
        if (owner.hasModifierPropertyScala("private")) Visibility.Private
        else if (owner.hasModifierPropertyScala("protected")) Visibility.Protected
        else Visibility.Default
      case owner: PsiModifierListOwner =>
        if (owner.hasModifierProperty("public")) Visibility.Default
        else if (owner.hasModifierProperty("private")) Visibility.Private
        else Visibility.Protected
      case _ => Visibility.Default
    }

    override def isImplicit: Boolean = element match {
      case owner: ScModifierListOwner => owner.hasModifierPropertyScala("implicit")
      case _ => false
    }

    override def isConstant: Boolean = element match {
      case value: ScValue => value.hasModifierPropertyScala("final")
      case _ => false
    }

    override def hasUnitType: Boolean = element match {
      case f: ScFunction => f.hasUnitResultType
      case v: Typeable => v.getType().exists(_.isUnit)
      case _ => false
    }

    override def typeMatches(patterns: Set[String]): Boolean = element match {
      case v: Typeable => v.getType().exists(t => patterns.exists(matches(t, _)))
      case _ => false
    }

    override def isAnnotatedWith(annotations: Set[String]): Boolean = element match {
      case holder: ScAnnotationsHolder => annotations.exists(holder.hasAnnotation)
      case _ => false
    }
  }

  private def matches(t: ScType, pattern: String): Boolean = {
    val s = t.canonicalText.stripPrefix("_root_.")

    pattern match {
      case AsteriskPattern(prefix, suffix) =>
        s.length > prefix.length + suffix.length && s.startsWith(prefix) && s.endsWith(suffix)
      case plainText =>
        s == plainText
    }
  }

  private case class SyntheticDeclaration(visibility: Visibility,
                                          isImplicit: Boolean,
                                          isConstant: Boolean,
                                          hasUnitType: Boolean) extends Declaration {
    override def typeMatches(patterns: Set[String]): Boolean = false

    override def isAnnotatedWith(annotations: Set[String]): Boolean = false
  }
}
{'fraction_non_alphanumeric': 0.092063966522194, 'fraction_numerical': 0.0007472724555372889, 'mean_word_length': 3.309079201545396, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7057138', 'n_tokens_mistral': 1827, 'n_tokens_neox': 1753, 'n_words': 438}