<commit_before>// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.testFramework.rules

import com.intellij.openapi.util.io.FileUtil
import com.intellij.testFramework.PlatformTestUtil
import com.intellij.testFramework.UsefulTestCase
import org.junit.rules.ExternalResource
import org.junit.runner.Description
import org.junit.runners.model.Statement
import java.io.File
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.util.concurrent.atomic.AtomicInteger

/**
 * An improved variant of [org.junit.rules.TemporaryFolder] with lazy init, no symlinks in a temporary directory path, better directory name,
 * and more convenient [newFile], [newDirectory] methods.
 */
class TempDirectory : ExternalResource() {
  private var name: String? = null
  private val nextDirNameSuffix = AtomicInteger()
  private var myRoot: File? = null

  val root: File
    get() {
      if (myRoot == null) {
        checkNotNull(name) { "apply() was not called" }
        myRoot = Files.createTempDirectory(UsefulTestCase.TEMP_DIR_MARKER + name + '_').toRealPath().toFile()
      }
      return myRoot!!
    }
  
  override fun apply(base: Statement,
                     description: Description): Statement {
    name = PlatformTestUtil.lowercaseFirstLetter(FileUtil.sanitizeFileName(description.methodName, false), true)
    return super.apply(base, description)
  }

  override fun after() {
    if (myRoot != null) {
      val path = myRoot!!.toPath()
      myRoot = null
      name = null
      FileUtil.delete(path)
    }
  }

  /**
   * Creates a new directory with the given relative path from the root temp directory. Throws an exception if such a directory already exists.
   */
  fun newDirectory(relativePath: String): File {
    val dir = Paths.get(root.path, relativePath)
    require(!Files.exists(dir)) { "Already exists: $dir" }
    makeDirectories(dir)
    return dir.toFile()
  }

  /**
   * Creates a new directory with random name under the root temp directory.
   */
  fun newDirectory(): File {
    return FileUtil.createTempDirectory(root, "dir" + nextDirNameSuffix.incrementAndGet(), null)
  }

  /**
   * Creates a new file with the given relative path from the root temp directory. Throws an exception if such a file already exists.
   */
  @JvmOverloads
  fun newFile(relativePath: String, content: ByteArray? = null): File {
    val file = Paths.get(root.path, relativePath)
    require(!Files.exists(file)) { "Already exists: $file" }
    makeDirectories(file.parent)
    Files.createFile(file)
    if (content != null) {
      Files.write(file, content)
    }
    return file.toFile()
  }

  @Deprecated("use newDirectory(relativePath) instead", ReplaceWith("newDirectory(relativePath)"))
  fun newFolder(relativePath: String): File {
    return newDirectory(relativePath)
  }

  @Deprecated("use newDirectory() instead", ReplaceWith("newDirectory()"))
  fun newFolder(): File {
    return newDirectory()
  }

  private fun makeDirectories(path: Path) {
    if (!Files.isDirectory(path)) {
      makeDirectories(path.parent)
      Files.createDirectory(path)
    }
  }
}<commit_msg>[test framework] add method to create a virtual directory in TempDirectory rule<commit_after>// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.testFramework.rules

import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.testFramework.PlatformTestUtil
import com.intellij.testFramework.UsefulTestCase
import com.intellij.testFramework.VfsTestUtil
import org.junit.rules.ExternalResource
import org.junit.runner.Description
import org.junit.runners.model.Statement
import java.io.File
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.util.concurrent.atomic.AtomicInteger

/**
 * An improved variant of [org.junit.rules.TemporaryFolder] with lazy init, no symlinks in a temporary directory path, better directory name,
 * and more convenient [newFile], [newDirectory] methods.
 */
class TempDirectory : ExternalResource() {
  private var name: String? = null
  private val nextDirNameSuffix = AtomicInteger()
  private var myRoot: File? = null
  private var myVirtualFileRoot: VirtualFile? = null

  val root: File
    get() {
      if (myRoot == null) {
        checkNotNull(name) { "apply() was not called" }
        myRoot = Files.createTempDirectory(UsefulTestCase.TEMP_DIR_MARKER + name + '_').toRealPath().toFile()
      }
      return myRoot!!
    }

  private val virtualFileRoot: VirtualFile
    get() {
      if (myVirtualFileRoot == null) {
        myVirtualFileRoot = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(root)
        checkNotNull(myVirtualFileRoot) { "Cannot find virtual file by $root" }
        VfsUtil.markDirtyAndRefresh(false, true, true, myVirtualFileRoot)
      }
      return myVirtualFileRoot!!
    }

  override fun apply(base: Statement,
                     description: Description): Statement {
    name = PlatformTestUtil.lowercaseFirstLetter(FileUtil.sanitizeFileName(description.methodName, false), true)
    return super.apply(base, description)
  }

  override fun after() {
    if (myRoot != null) {
      val path = myRoot!!.toPath()
      myVirtualFileRoot = null
      myRoot = null
      name = null
      FileUtil.delete(path)
    }
  }

  /**
   * Creates a new directory with the given relative path from the root temp directory. Throws an exception if such a directory already exists.
   */
  fun newDirectory(relativePath: String): File {
    val dir = Paths.get(root.path, relativePath)
    require(!Files.exists(dir)) { "Already exists: $dir" }
    makeDirectories(dir)
    return dir.toFile()
  }

  /**
   * Creates a new directory with random name under the root temp directory.
   */
  fun newDirectory(): File {
    return FileUtil.createTempDirectory(root, "dir" + nextDirNameSuffix.incrementAndGet(), null)
  }

  /**
   * Creates a new file with the given relative path from the root temp directory. Throws an exception if such a file already exists.
   */
  @JvmOverloads
  fun newFile(relativePath: String, content: ByteArray? = null): File {
    val file = Paths.get(root.path, relativePath)
    require(!Files.exists(file)) { "Already exists: $file" }
    makeDirectories(file.parent)
    Files.createFile(file)
    if (content != null) {
      Files.write(file, content)
    }
    return file.toFile()
  }

  /**
   * Creates a new virtual directory with the given relative path from the root temp directory. Throws an exception if such a directory already exists.
   */
  fun newVirtualDirectory(relativePath: String): VirtualFile {
    val existing = virtualFileRoot.findFileByRelativePath(relativePath)
    require(existing == null) { "Already exists: ${existing!!.path}"}
    return VfsTestUtil.createDir(virtualFileRoot, relativePath)
  }

  @Deprecated("use newDirectory(relativePath) instead", ReplaceWith("newDirectory(relativePath)"))
  fun newFolder(relativePath: String): File {
    return newDirectory(relativePath)
  }

  @Deprecated("use newDirectory() instead", ReplaceWith("newDirectory()"))
  fun newFolder(): File {
    return newDirectory()
  }

  private fun makeDirectories(path: Path) {
    if (!Files.isDirectory(path)) {
      makeDirectories(path.parent)
      Files.createDirectory(path)
    }
  }
}
{'fraction_non_alphanumeric': 0.1014265148540767, 'fraction_numerical': 0.0026174584478471405, 'mean_word_length': 3.764339152119701, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '261338', 'n_tokens_mistral': 2234, 'n_tokens_neox': 2183, 'n_words': 627}