<commit_before>package scala.meta.annotations

import java.io.File

import com.intellij.ProjectTopics
import com.intellij.compiler.server.BuildManager
import com.intellij.openapi.editor.markup.GutterIconRenderer
import com.intellij.openapi.module.{JavaModuleType, Module}
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.{ModuleRootAdapter, ModuleRootEvent}
import com.intellij.openapi.util.io.FileUtil
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase
import com.intellij.testFramework.{PsiTestUtil, VfsTestUtil}
import org.jetbrains.plugins.scala.base.DisposableScalaLibraryLoader
import org.jetbrains.plugins.scala.base.libraryLoaders.LibraryLoader
import org.jetbrains.plugins.scala.debugger.{CompilationCache, ScalaVersion}
import org.jetbrains.plugins.scala.extensions.{PsiElementExt, inWriteAction}
import org.jetbrains.plugins.scala.lang.psi.api.statements.ScAnnotationsHolder
import org.jetbrains.plugins.scala.lang.psi.api.toplevel.typedef.ScTypeDefinition
import org.jetbrains.plugins.scala.lang.psi.{ScalaPsiElement, ScalaPsiUtil}
import org.jetbrains.plugins.scala.project.ModuleExt
import org.jetbrains.plugins.scala.project.settings.ScalaCompilerConfiguration
import org.jetbrains.plugins.scala.util.TestUtils
import org.junit.Assert

import scala.meta.ScalaMetaLibrariesOwner.MetaBaseLoader
import scala.meta.{Compilable, ScalaMetaLibrariesOwner}

abstract class MetaAnnotationTestBase extends JavaCodeInsightFixtureTestCase with ScalaMetaLibrariesOwner with Compilable {

  import MetaAnnotationTestBase._

  override implicit lazy val project: Project = getProject
  override def rootProject = getProject
  override def rootModule = myModule

  private lazy val metaDirectory = inWriteAction {
    val baseDir = project.getBaseDir
    baseDir.findChild("meta") match {
      case null => baseDir.createChildDirectory(null, "meta")
      case directory => directory
    }
  }

  override implicit lazy val module: Module = PsiTestUtil.addModule(project, JavaModuleType.getModuleType, "meta", metaDirectory)

  override protected def getTestDataPath: String = TestUtils.getTestDataPath + "/scalameta"

  override def librariesLoaders: Seq[LibraryLoader] =
    Seq(new DisposableScalaLibraryLoader()) ++ additionalLibraries

  override def setUp(): Unit = {
    super.setUp()

    val project = getProject
    project.getMessageBus
      .connect(getTestRootDisposable)
      .subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootAdapter {
        override def rootsChanged(event: ModuleRootEvent) {
          BuildManager.getInstance.clearState(project)
        }
      })

    addRoots(module)
    addRoots(myModule)
    setUpLibraries()

    inWriteAction {
      val modifiableRootModel = myModule.modifiableModel
      modifiableRootModel.addModuleOrderEntry(module)
      modifiableRootModel.commit()
    }
  }

  protected def compileMetaSource(source: String = FileUtil.loadFile(new File(getTestDataPath, s"${getTestName(false)}.scala"))): List[String] = {
    addMetaSource(source)
    val cache = new CompilationCache(module, Seq(version.major, ScalaMetaLibrariesOwner.metaVersion))
    cache.withModuleOutputCache(List[String]()) {
      setUpCompiler
      enableParadisePlugin()
      runMake()
    }
  }

  protected def compileAnnotBody(body: String) = compileMetaSource(mkAnnot(annotName, body))

  protected def addMetaSource(source: String = FileUtil.loadFile(new File(getTestDataPath, s"${getTestName(false)}.scala"))): Unit = {
    VfsTestUtil.createFile(metaDirectory, "meta.scala", source)
  }

  protected def enableParadisePlugin(): Unit = {
    val profile = ScalaCompilerConfiguration.instanceIn(project).defaultProfile
    val settings = profile.getSettings
    settings.plugins :+= MetaParadiseLoader()(module).path
    profile.setSettings(settings)
  }


  protected def checkExpansionEquals(code: String, expectedExpansion: String): Unit = {
    import scala.meta.intellij.psiExt._
    myFixture.configureByText(s"Usage${getTestName(false)}.scala", code)
    val holder = ScalaPsiUtil.getParentOfType(elementAtCaret, classOf[ScAnnotationsHolder]).asInstanceOf[ScAnnotationsHolder]
    holder.getMetaExpansion match {
      case Right(tree) => Assert.assertEquals(expectedExpansion, tree.toString())
      case Left(reason) if reason.nonEmpty => Assert.fail(reason)
      case Left("") => Assert.fail("Expansion was empty - did annotation even run?")
    }
  }

  protected def getGutter: GutterIconRenderer = {
    val gutters = myFixture.findAllGutters()
    Assert.assertEquals("Wrong number of gutters", 1, gutters.size())
    gutters.get(0).asInstanceOf[GutterIconRenderer]
  }

  protected def createFile(text: String): Unit = myFixture.configureByText(s"$testClassName.scala", text)

  // because getElementAtCaret from fixture forces resolve and we don't want that
  protected def elementAtCaret = PsiTreeUtil.getParentOfType(myFixture.getFile.findElementAt(myFixture.getCaretOffset-1), classOf[ScalaPsiElement])
  protected def annotName: String = s"a_${getTestName(true)}".toLowerCase
  protected def testClassName: String = getTestName(false)<commit_msg>fix leaking projects in meta annotation tests<commit_after>package scala.meta.annotations

import java.io.File

import com.intellij.ProjectTopics
import com.intellij.compiler.server.BuildManager
import com.intellij.openapi.editor.markup.GutterIconRenderer
import com.intellij.openapi.module.{JavaModuleType, Module}
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.{ModuleRootAdapter, ModuleRootEvent}
import com.intellij.openapi.util.io.FileUtil
import com.intellij.psi.PsiElement
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase
import com.intellij.testFramework.{PsiTestUtil, VfsTestUtil}
import org.jetbrains.plugins.scala.base.DisposableScalaLibraryLoader
import org.jetbrains.plugins.scala.base.libraryLoaders.LibraryLoader
import org.jetbrains.plugins.scala.debugger.{CompilationCache, ScalaVersion}
import org.jetbrains.plugins.scala.extensions.{PsiElementExt, inWriteAction}
import org.jetbrains.plugins.scala.lang.psi.api.base.ScReferenceElement
import org.jetbrains.plugins.scala.lang.psi.api.statements.ScAnnotationsHolder
import org.jetbrains.plugins.scala.lang.psi.api.toplevel.typedef.ScTypeDefinition
import org.jetbrains.plugins.scala.lang.psi.{ScalaPsiElement, ScalaPsiUtil}
import org.jetbrains.plugins.scala.project.ModuleExt
import org.jetbrains.plugins.scala.project.settings.ScalaCompilerConfiguration
import org.jetbrains.plugins.scala.util.TestUtils
import org.junit.Assert

import scala.meta.ScalaMetaLibrariesOwner.MetaBaseLoader
import scala.meta.{Compilable, ScalaMetaLibrariesOwner}

abstract class MetaAnnotationTestBase extends JavaCodeInsightFixtureTestCase with ScalaMetaLibrariesOwner with Compilable {

  import MetaAnnotationTestBase._

  override implicit def project: Project = getProject
  override implicit protected def module: Module = metaModule
  var metaModule: Module = _
  override def rootProject = getProject
  override def rootModule = myModule

  private lazy val metaDirectory = inWriteAction {
    val baseDir = project.getBaseDir
    baseDir.findChild("meta") match {
      case null => baseDir.createChildDirectory(null, "meta")
      case directory => directory
    }
  }

  override protected def getTestDataPath: String = TestUtils.getTestDataPath + "/scalameta"

  override def librariesLoaders: Seq[LibraryLoader] =
    Seq(new DisposableScalaLibraryLoader()) ++ additionalLibraries

  override def setUp(): Unit = {
    super.setUp()

    val project = getProject
    project.getMessageBus
      .connect(getTestRootDisposable)
      .subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootAdapter {
        override def rootsChanged(event: ModuleRootEvent) {
          BuildManager.getInstance.clearState(project)
        }
      })

    metaModule = PsiTestUtil.addModule(project, JavaModuleType.getModuleType, "meta", metaDirectory)
    addRoots(metaModule)
    addRoots(myModule)
    setUpLibraries()

    inWriteAction {
      val modifiableRootModel = myModule.modifiableModel
      modifiableRootModel.addModuleOrderEntry(metaModule)
      modifiableRootModel.commit()
    }
  }

  override def tearDown(): Unit = {
    tearDownLibraries()
    metaModule = null
    super.tearDown()
  }

  protected def compileMetaSource(source: String = FileUtil.loadFile(new File(getTestDataPath, s"${getTestName(false)}.scala"))): List[String] = {
    addMetaSource(source)
    val cache = new CompilationCache(metaModule, Seq(version.major, ScalaMetaLibrariesOwner.metaVersion))
    cache.withModuleOutputCache(List[String]()) {
      setUpCompiler
      enableParadisePlugin()
      runMake()
    }
  }

  protected def compileAnnotBody(body: String) = compileMetaSource(mkAnnot(annotName, body))

  protected def addMetaSource(source: String = FileUtil.loadFile(new File(getTestDataPath, s"${getTestName(false)}.scala"))): Unit = {
    VfsTestUtil.createFile(metaDirectory, "meta.scala", source)
  }

  protected def enableParadisePlugin(): Unit = {
    val profile = ScalaCompilerConfiguration.instanceIn(project).defaultProfile
    val settings = profile.getSettings
    settings.plugins :+= MetaParadiseLoader()(metaModule).path
    profile.setSettings(settings)
  }


  protected def checkExpansionEquals(code: String, expectedExpansion: String): Unit = {
    import scala.meta.intellij.psiExt._
    myFixture.configureByText(s"Usage${getTestName(false)}.scala", code)
    val holder = ScalaPsiUtil.getParentOfType(elementAtCaret, classOf[ScAnnotationsHolder]).asInstanceOf[ScAnnotationsHolder]
    holder.getMetaExpansion match {
      case Right(tree) => Assert.assertEquals(expectedExpansion, tree.toString())
      case Left(reason) if reason.nonEmpty => Assert.fail(reason)
      case Left("") => Assert.fail("Expansion was empty - did annotation even run?")
    }
  }

  protected def getGutter: GutterIconRenderer = {
    val gutters = myFixture.findAllGutters()
    Assert.assertEquals("Wrong number of gutters", 1, gutters.size())
    gutters.get(0).asInstanceOf[GutterIconRenderer]
  }

  protected def createFile(text: String): Unit = myFixture.configureByText(s"$testClassName.scala", text)

  // because getElementAtCaret from fixture forces resolve and we don't want that
  protected def elementAtCaret = PsiTreeUtil.getParentOfType(myFixture.getFile.findElementAt(myFixture.getCaretOffset-1), classOf[ScalaPsiElement])
  protected def refAtCaret = elementAtCaret match {
    case ref: ScReferenceElement => ref
    case other: PsiElement => PsiTreeUtil.getParentOfType(other, classOf[ScReferenceElement])
  }
  protected def annotName: String = s"a_${getTestName(true)}".toLowerCase
  protected def testClassName: String = getTestName(false)
{'fraction_non_alphanumeric': 0.09262482821804856, 'fraction_numerical': 0.0005497022446174989, 'mean_word_length': 5.273563218390804, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 15, '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': '3629549', 'n_tokens_mistral': 3264, 'n_tokens_neox': 3145, 'n_words': 599}