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

import com.intellij.lang.LanguageParserDefinitions
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.impl.compiled.ClsStubBuilderFactory

import com.intellij.psi.stubs.{PsiFileStubImpl, PsiFileStub}
import com.intellij.psi.tree.IStubFileElementType
import com.intellij.psi.{PsiManager, PsiFile}
import lang.psi.api.ScalaFile
import lang.psi.impl.ScalaPsiElementFactory
import decompiler.DecompilerUtil.DecompilationResult
import com.intellij.openapi.project.{Project, ProjectManager}
import reflect.NameTransformer
import scala.annotation.tailrec
import java.io.IOException
import org.jetbrains.plugins.scala.lang.psi.stubs.elements.StubVersion

/**
 * @author ilyas
 */

object ScClsStubBuilderFactory {
  def canBeProcessed(file: VirtualFile): Boolean = {
    try {
      canBeProcessed(file, file.contentsToByteArray())
    } catch {
      case ex: IOException => false
      case u: UnsupportedOperationException => false //why we need to handle this?
    }
  }
  
  def canBeProcessed(file: VirtualFile, bytes: Array[Byte]): Boolean = {
    val name: String = file.getNameWithoutExtension
    if (name.endsWith("$")) {
      val parent: VirtualFile = file.getParent
      @tailrec
      def checkName(name: String): Boolean = {
        val child: VirtualFile = parent.findChild(name + ".class")
        if (child != null) {
          val res = DecompilerUtil.isScalaFile(child)
          if (res) return true //let's handle it separately to avoid giving it for Java.
        }
        val index = name.lastIndexOf("$")
        if (index == -1) return false
        var newName = name.substring(0, index)
        while (newName.endsWith("$")) newName = newName.dropRight(1)
        checkName(newName)
      }
      if (checkName(name.dropRight(1))) return true
    }
    DecompilerUtil.isScalaFile(file, bytes)
  }
}

class ScClsStubBuilderFactory extends ClsStubBuilderFactory[ScalaFile] {
  override def getStubVersion: Int = StubVersion.STUB_VERSION
  
  def buildFileStub(vFile: VirtualFile, bytes: Array[Byte]): PsiFileStub[ScalaFile] = {
    buildFileStub(vFile, bytes, ProjectManager.getInstance().getDefaultProject)
  }

  override def buildFileStub(vFile: VirtualFile, bytes: Array[Byte], project: Project): PsiFileStub[ScalaFile] = {
    val DecompilationResult(_, source, text, _) = DecompilerUtil.decompile(vFile, bytes)<commit_msg>Fixed performance problem with decompiler.<commit_after>package org.jetbrains.plugins.scala
package decompiler

import com.intellij.lang.LanguageParserDefinitions
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.impl.compiled.ClsStubBuilderFactory

import com.intellij.psi.stubs.{PsiFileStubImpl, PsiFileStub}
import com.intellij.psi.tree.IStubFileElementType
import com.intellij.psi.{PsiManager, PsiFile}
import lang.psi.api.ScalaFile
import lang.psi.impl.ScalaPsiElementFactory
import decompiler.DecompilerUtil.DecompilationResult
import com.intellij.openapi.project.{Project, ProjectManager}
import reflect.NameTransformer
import scala.annotation.tailrec
import java.io.IOException
import org.jetbrains.plugins.scala.lang.psi.stubs.elements.StubVersion

/**
 * @author ilyas
 */

object ScClsStubBuilderFactory {
  def canBeProcessed(file: VirtualFile): Boolean = {
    try {
      canBeProcessed(file, file.contentsToByteArray())
    } catch {
      case ex: IOException => false
      case u: UnsupportedOperationException => false //why we need to handle this?
    }
  }
  
  def canBeProcessed(file: VirtualFile, bytes: => Array[Byte]): Boolean = {
    val name: String = file.getNameWithoutExtension
    if (name.endsWith("$")) {
      val parent: VirtualFile = file.getParent
      @tailrec
      def checkName(name: String): Boolean = {
        val child: VirtualFile = parent.findChild(name + ".class")
        if (child != null) {
          val res = DecompilerUtil.isScalaFile(child)
          if (res) return true //let's handle it separately to avoid giving it for Java.
        }
        val index = name.lastIndexOf("$")
        if (index == -1) return false
        var newName = name.substring(0, index)
        while (newName.endsWith("$")) newName = newName.dropRight(1)
        checkName(newName)
      }
      if (checkName(name.dropRight(1))) return true
    }
    DecompilerUtil.isScalaFile(file, bytes)
  }
}

class ScClsStubBuilderFactory extends ClsStubBuilderFactory[ScalaFile] {
  override def getStubVersion: Int = StubVersion.STUB_VERSION
  
  def buildFileStub(vFile: VirtualFile, bytes: Array[Byte]): PsiFileStub[ScalaFile] = {
    buildFileStub(vFile, bytes, ProjectManager.getInstance().getDefaultProject)
  }

  override def buildFileStub(vFile: VirtualFile, bytes: Array[Byte], project: Project): PsiFileStub[ScalaFile] = {
    val DecompilationResult(_, source, text, _) = DecompilerUtil.decompile(vFile, bytes)
{'fraction_non_alphanumeric': 0.10293518141051773, 'fraction_numerical': 0.0016306563391765185, 'mean_word_length': 4.084974093264249, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 8, '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': '3404641', 'n_tokens_mistral': 1505, 'n_tokens_neox': 1513, 'n_words': 329}