<commit_before>/*
 * Copyright 2005-2010 LAMP/EPFL
 */
// $Id$

package scala.tools.eclipse.javaelements

import org.eclipse.jdt.core.search.{ SearchMatch, SearchPattern, SearchParticipant, TypeDeclarationMatch, TypeReferenceMatch, MethodReferenceMatch, FieldReferenceMatch }

import org.eclipse.jdt.core.compiler.{ CharOperation => CharOp }
import org.eclipse.jdt.internal.compiler.ast.{ SingleTypeReference, TypeDeclaration }
import org.eclipse.jdt.internal.core.search.matching.{ MatchLocator, PossibleMatch }

import scala.tools.nsc.util.{ RangePosition, Position }

import scala.tools.eclipse.ScalaPresentationCompiler
import scala.tools.eclipse.util.ReflectionUtils
import org.eclipse.jdt.internal.core.search.matching.{ PatternLocator, FieldPattern, MethodPattern, TypeReferencePattern, TypeDeclarationPattern, OrPattern };

//FIXME should report all and let matcher to the selection OR only report matcher interest (pre select by type) OR ...

trait ScalaMatchLocator { self: ScalaPresentationCompiler =>
  val OneStar = Array('*')
  val ImpossibleMatch = 0
  val InaccurateMatch = 1
  val AccurateMatch = 2

  def MatchLocator(scu: ScalaCompilationUnit, matchLocator: MatchLocator, possibleMatch: PossibleMatch): Traverser = 
     MatchLocator(scu, matchLocator, matchLocator.pattern, possibleMatch)
  
  def MatchLocator(scu: ScalaCompilationUnit, matchLocator: MatchLocator, 
      pattern: SearchPattern, possibleMatch: PossibleMatch): MatchLocatorTraverser = {
    logger.info("Search pattern " + pattern)
    pattern match {
      case p: OrPattern => 
        val locators = MatchLocatorUtils.orPatterns(p) map { p => MatchLocator(scu, matchLocator, p, possibleMatch) }
        new OrLocator(scu, matchLocator, p, possibleMatch, locators)
      case p: TypeReferencePattern => new TypeReferenceLocator(scu, matchLocator, p, possibleMatch)
      case p: TypeDeclarationPattern => new TypeDeclarationLocator(scu, matchLocator, p, possibleMatch)
      case p: MethodPattern => new MethodLocator(scu, matchLocator, p, possibleMatch)
      case p: FieldPattern => new FieldLocator(scu, matchLocator, p, possibleMatch)
      case p => logger.debug("Could not handle pattern in match request: "+ p); NoLocator
    }
  }
  
  trait MatchLocatorTraverser extends Traverser {
    def scu: ScalaCompilationUnit
    def matchLocator: MatchLocator
    def possibleMatch: PossibleMatch
    
    override def traverse(tree: Tree): Unit = try {
      if (tree.pos.isOpaqueRange && tree.pos.isDefined) {
        report(tree)
        super.traverse(tree)
      }
    } catch {
      case t: TypeError => logError("Error while searching Scala tree", t)
    }
    
    def report(tree: Tree)
    
    import MatchLocatorUtils._
    def report(sm: SearchMatch) = {
      logger.info("found a match: " + sm)
      reportMethod.invoke(matchLocator, sm)
    }

    def checkQualifier(s: Select, className: Array[Char], pat: SearchPattern) =  {
//      println("looking for parent classname " + new String(className))
      (className eq null) || {
        s.qualifier.tpe.baseClasses exists { bc => 
          logger.info("Base class " + bc)
          val res = pat.matchesName(className, bc.name.toChars)
          if (res) 
            println("\t match for " + bc)
          res
        }
      }
    }
    
    def posToLong(pos: Position): Long = pos.startOrPoint << 32 | pos.endOrPoint
    
    /* simplified from org.eclipse.jdt.internal.core.search.matching.PatternLocator */
    /*def qualifiedPattern(simpleNamePattern: Array[Char], qualificationPattern: Array[Char]): Array[Char] =
      // NOTE: if case insensitive search then simpleNamePattern & qualificationPattern are assumed to be lowercase
      if (qualificationPattern == null)
        simpleNamePattern
      else if (simpleNamePattern eq null)
        CharOp.concat(qualificationPattern, OneStar, '.')
      else
        CharOp.concat(qualificationPattern, simpleNamePattern, '.')
    
    /**
     * See whether the given type can occur in a pattern (e.g. type vars cannot)
     */
    def canMatchPattern(tpe: Type): Boolean = tpe match {
      case _ : ErrorType | _ : WildcardType | _ : NoType => false
      case _ => true
    }
    
    def resolveLevelForType(qualifiedPattern: Array[Char], tpe: Type): Int = {
      if (qualifiedPattern eq null) AccurateMatch
      else if (tpe eq null) InaccurateMatch
      else if (!canMatchPattern(tpe)) ImpossibleMatch
      else {
        tpe match {
          case ThisType(_) | SingleType(_,_) => 
          case SingleType(pre, sym) =>
          // pre.sym.type
    // int(2)
  case TypeRef(pre, sym, args) => 
    // pre.sym[targs]
  case RefinedType(parents, defs) =>
    // parent1 with ... with parentn { defs }
  case AnnotatedType(annots, tp, selfsym) =>
    // tp @annots
          case _ => PatternLocator.INACCURATE_MATCH
        }
        
        val qualifiedPackageName = tpe.qualifiedPackageName()
        val qualifiedSourceName = qualifiedSourceName(tpe)
        val fullyQualifiedTypeName = if (qualifiedPackageName.length == 0) qualifiedSourceName
          else CharOp.concat(qualifiedPackageName, qualifiedSourceName, '.')
        if (CharOp.`match`(qualifiedPattern, fullyQualifiedTypeName, this.isCaseSensitive))
          AccurateMatch
        else ImpossibleMatch
      }
    }*/
  }
  
  object NoLocator extends MatchLocatorTraverser {
    def scu: ScalaCompilationUnit = null
    def matchLocator: MatchLocator = null
    def possibleMatch: PossibleMatch = null
    def report(tree: Tree) {}
  }
  
  class OrLocator(val scu: ScalaCompilationUnit, val matchLocator: MatchLocator, 
      val pattern: OrPattern, val possibleMatch: PossibleMatch,
      traversers: Seq[MatchLocatorTraverser]) extends MatchLocatorTraverser {
    def report(tree: Tree) = traversers foreach { t => t.report(tree) }
  }
  
  class MethodLocator(val scu: ScalaCompilationUnit, val matchLocator: MatchLocator, val pattern: MethodPattern, val possibleMatch: PossibleMatch) extends MatchLocatorTraverser {
    def report(tree: Tree) = tree match {
      case t: Select if t.symbol.isMethod => reportMethodReference(t, t.symbol, pattern)
      case t: DefDef => reportMethodReference(t, t.symbol, pattern)
      case _ =>
    }
    
    def parameterSizeMatches(desiredCount: Int, tpe: MethodType): Boolean =
      ((desiredCount == tpe.paramTypes.size)
        || (tpe.paramTypes.last.typeSymbol == definitions.RepeatedParamClass))
    
    def checkSignature(tpe: MethodType, pat: MethodPattern): Boolean =
      (pat.parameterCount == -1) || (parameterSizeMatches(pat.parameterCount, tpe) && {
          val searchedParamTypes = pat.parameterSimpleNames
          val currentParamTypes = tpe.paramTypes
           
          for (i <- 0 to currentParamTypes.size - 1) 
            if (!currentParamTypes(i).baseClasses.exists { bc => 
              pat.matchesName(searchedParamTypes(i), bc.name.toChars)
            }) return false        
          true
      })
    
    def reportMethodReference(tree: Tree, sym: Symbol, pat: MethodPattern) {
      if (!pat.matchesName(pat.selector, sym.name.toChars) || !sym.pos.isDefined) 
        return

      logger.info("Trying " + tree)
        
      val proceed = tree match {
        case t: Select => checkQualifier(t, pat.declaringSimpleName, pat)
        case _ => true
      }
      
      if (proceed) {
        logger.info("Qualifier matched")

        val hit = sym.tpe match {
          case t: MethodType => checkSignature(t, pat)
          case _ => pat.parameterCount <= 0
        }
        
        if (hit) {
          val enclosingElement = scu match {
            case ssf: ScalaSourceFile => ssf.getElementAt(tree.pos.start)
            case _ => null
          }
          
          val accuracy = SearchMatch.A_INACCURATE
          val (offset, length) = if (tree.isDef)
            (tree.pos.startOrPoint + 4, tree.symbol.name.length)
          else (tree.pos.startOrPoint, tree.pos.endOrPoint - tree.pos.startOrPoint)
              
          val insideDocComment = false
          val participant = possibleMatch.document.getParticipant
          val resource = possibleMatch.resource

          report(new MethodReferenceMatch(enclosingElement, accuracy, offset, length, insideDocComment, participant, resource))
        }
      }
    }
  }
 
  class FieldLocator(val scu: ScalaCompilationUnit, val matchLocator: MatchLocator, val pattern: FieldPattern, val possibleMatch: PossibleMatch) extends MatchLocatorTraverser {
    import MatchLocatorUtils._

    def report(tree: Tree) = tree match {
      case s: Select => s.symbol match {
        case sym : MethodSymbol => reportVariableReference(s, pattern)
        case _ =>
      }
      case _ =>
    }<commit_msg>Removed debugging comments, integrated reviews.<commit_after>/*
 * Copyright 2005-2010 LAMP/EPFL
 */
// $Id$

package scala.tools.eclipse.javaelements

import org.eclipse.jdt.core.search.{ SearchMatch, SearchPattern, SearchParticipant, TypeDeclarationMatch, TypeReferenceMatch, MethodReferenceMatch, FieldReferenceMatch }

import org.eclipse.jdt.core.compiler.{ CharOperation => CharOp }
import org.eclipse.jdt.internal.compiler.ast.{ SingleTypeReference, TypeDeclaration }
import org.eclipse.jdt.internal.core.search.matching.{ MatchLocator, PossibleMatch }

import scala.tools.nsc.util.{ RangePosition, Position }

import scala.tools.eclipse.ScalaPresentationCompiler
import scala.tools.eclipse.util.ReflectionUtils
import org.eclipse.jdt.internal.core.search.matching.{ PatternLocator, FieldPattern, MethodPattern, TypeReferencePattern, TypeDeclarationPattern, OrPattern };

//FIXME should report all and let matcher to the selection OR only report matcher interest (pre select by type) OR ...

trait ScalaMatchLocator { self: ScalaPresentationCompiler =>
  val OneStar = Array('*')
  val ImpossibleMatch = 0
  val InaccurateMatch = 1
  val AccurateMatch = 2

  def MatchLocator(scu: ScalaCompilationUnit, matchLocator: MatchLocator, possibleMatch: PossibleMatch): Traverser = 
     MatchLocator(scu, matchLocator, matchLocator.pattern, possibleMatch)
  
  def MatchLocator(scu: ScalaCompilationUnit, matchLocator: MatchLocator, 
      pattern: SearchPattern, possibleMatch: PossibleMatch): MatchLocatorTraverser = {
    logger.info("Search pattern " + pattern)
    pattern match {
      case p: OrPattern => 
        val locators = MatchLocatorUtils.orPatterns(p) map { p => MatchLocator(scu, matchLocator, p, possibleMatch) }
        new OrLocator(scu, matchLocator, p, possibleMatch, locators)
      case p: TypeReferencePattern => new TypeReferenceLocator(scu, matchLocator, p, possibleMatch)
      case p: TypeDeclarationPattern => new TypeDeclarationLocator(scu, matchLocator, p, possibleMatch)
      case p: MethodPattern => new MethodLocator(scu, matchLocator, p, possibleMatch)
      case p: FieldPattern => new FieldLocator(scu, matchLocator, p, possibleMatch)
      case p => logger.debug("Could not handle pattern in match request: "+ p); NoLocator
    }
  }
  
  trait MatchLocatorTraverser extends Traverser {
    def scu: ScalaCompilationUnit
    def matchLocator: MatchLocator
    def possibleMatch: PossibleMatch
    
    override def traverse(tree: Tree): Unit = try {
      if (tree.pos.isOpaqueRange && tree.pos.isDefined) {
        report(tree)
        super.traverse(tree)
      }
    } catch {
      case t: TypeError => logError("Error while searching Scala tree", t)
    }
    
    def report(tree: Tree)
    
    import MatchLocatorUtils._
    def report(sm: SearchMatch) = {
      logger.info("found a match: " + sm)
      reportMethod.invoke(matchLocator, sm)
    }

    def checkQualifier(s: Select, className: Array[Char], pat: SearchPattern) =  {
      (className eq null) || {
        s.qualifier.tpe.baseClasses exists { bc => 
          pat.matchesName(className, bc.name.toChars)
        }
      }
    }
    
    def posToLong(pos: Position): Long = pos.startOrPoint << 32 | pos.endOrPoint
    
    /* simplified from org.eclipse.jdt.internal.core.search.matching.PatternLocator */
    /*def qualifiedPattern(simpleNamePattern: Array[Char], qualificationPattern: Array[Char]): Array[Char] =
      // NOTE: if case insensitive search then simpleNamePattern & qualificationPattern are assumed to be lowercase
      if (qualificationPattern == null)
        simpleNamePattern
      else if (simpleNamePattern eq null)
        CharOp.concat(qualificationPattern, OneStar, '.')
      else
        CharOp.concat(qualificationPattern, simpleNamePattern, '.')
    
    /**
     * See whether the given type can occur in a pattern (e.g. type vars cannot)
     */
    def canMatchPattern(tpe: Type): Boolean = tpe match {
      case _ : ErrorType | _ : WildcardType | _ : NoType => false
      case _ => true
    }
    
    def resolveLevelForType(qualifiedPattern: Array[Char], tpe: Type): Int = {
      if (qualifiedPattern eq null) AccurateMatch
      else if (tpe eq null) InaccurateMatch
      else if (!canMatchPattern(tpe)) ImpossibleMatch
      else {
        tpe match {
          case ThisType(_) | SingleType(_,_) => 
          case SingleType(pre, sym) =>
          // pre.sym.type
    // int(2)
  case TypeRef(pre, sym, args) => 
    // pre.sym[targs]
  case RefinedType(parents, defs) =>
    // parent1 with ... with parentn { defs }
  case AnnotatedType(annots, tp, selfsym) =>
    // tp @annots
          case _ => PatternLocator.INACCURATE_MATCH
        }
        
        val qualifiedPackageName = tpe.qualifiedPackageName()
        val qualifiedSourceName = qualifiedSourceName(tpe)
        val fullyQualifiedTypeName = if (qualifiedPackageName.length == 0) qualifiedSourceName
          else CharOp.concat(qualifiedPackageName, qualifiedSourceName, '.')
        if (CharOp.`match`(qualifiedPattern, fullyQualifiedTypeName, this.isCaseSensitive))
          AccurateMatch
        else ImpossibleMatch
      }
    }*/
  }
  
  object NoLocator extends MatchLocatorTraverser {
    def scu: ScalaCompilationUnit = null
    def matchLocator: MatchLocator = null
    def possibleMatch: PossibleMatch = null
    def report(tree: Tree) {}
  }
  
  class OrLocator(val scu: ScalaCompilationUnit, val matchLocator: MatchLocator, 
      val pattern: OrPattern, val possibleMatch: PossibleMatch,
      traversers: Seq[MatchLocatorTraverser]) extends MatchLocatorTraverser {
    def report(tree: Tree) = traversers foreach { t => t.report(tree) }
  }
  
  class MethodLocator(val scu: ScalaCompilationUnit, val matchLocator: MatchLocator, val pattern: MethodPattern, val possibleMatch: PossibleMatch) extends MatchLocatorTraverser {
    def report(tree: Tree) = tree match {
      case t: Select if t.symbol.isMethod => reportMethodReference(t, t.symbol, pattern)
      case t: DefDef => reportMethodReference(t, t.symbol, pattern)
      case _ =>
    }
    
    /** Does the method type match the desired number of parameters? Correctly handles
     *  vararg methods. 
     *  
     *  TODO: check for curried method definitions
     */
    def parameterSizeMatches(desiredCount: Int, tpe: MethodType): Boolean =
      ((desiredCount == tpe.paramTypes.size)
        || ((desiredCount > tpe.paramTypes.size)
             && (tpe.paramTypes.last.typeSymbol == definitions.RepeatedParamClass))
      )
    
    /** Does the method type match the pattern? */
    def checkSignature(tpe: MethodType, pat: MethodPattern): Boolean =
      (pat.parameterCount == -1) || (parameterSizeMatches(pat.parameterCount, tpe) && {
          val searchedParamTypes = pat.parameterSimpleNames
          val currentParamTypes = tpe.paramTypes
           
          for (i <- 0 to currentParamTypes.size - 1) 
            if (!currentParamTypes(i).baseClasses.exists { bc => 
              pat.matchesName(searchedParamTypes(i), bc.name.toChars)
            }) return false        
          true
      })
    
    def reportMethodReference(tree: Tree, sym: Symbol, pat: MethodPattern) {
      if (!pat.matchesName(pat.selector, sym.name.toChars) || !sym.pos.isDefined) {
        logger.debug("Name didn't match: [%s] pos.isDefined: %b".format(sym.name, sym.pos.isDefined))
        return
      }

      val proceed = tree match {
        case t: Select => checkQualifier(t, pat.declaringSimpleName, pat)
        case _ => true
      }
      
      if (proceed) {
        logger.info("Qualifier matched")

        val hit = sym.tpe match {
          case t: MethodType => checkSignature(t, pat)
          case _ => pat.parameterCount <= 0 // negtive means that pattern can match any number of arguments
        }
        
        if (hit) {
          val enclosingElement = scu match {
            case ssf: ScalaSourceFile => ssf.getElementAt(tree.pos.startOrPoint)
            case _ => null
          }
          
          val accuracy = SearchMatch.A_INACCURATE
          val (offset, length) = if (tree.isDef)
            (tree.pos.startOrPoint + 4, tree.symbol.name.length)
          else (tree.pos.startOrPoint, tree.pos.endOrPoint - tree.pos.startOrPoint)
              
          val insideDocComment = false
          val participant = possibleMatch.document.getParticipant
          val resource = possibleMatch.resource

          report(new MethodReferenceMatch(enclosingElement, accuracy, offset, length, insideDocComment, participant, resource))
        }
      }
    }
  }
 
  class FieldLocator(val scu: ScalaCompilationUnit, val matchLocator: MatchLocator, val pattern: FieldPattern, val possibleMatch: PossibleMatch) extends MatchLocatorTraverser {
    import MatchLocatorUtils._

    def report(tree: Tree) = tree match {
      case s: Select => s.symbol match {
        case sym : MethodSymbol => reportVariableReference(s, pattern)
        case _ =>
      }
      case _ =>
    }
{'fraction_non_alphanumeric': 0.09542564564226635, 'fraction_numerical': 0.0023631350925561244, 'mean_word_length': 2.9576931641059896, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 72, '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': '6820057', 'n_tokens_mistral': 5189, 'n_tokens_neox': 5058, 'n_words': 1296}