From 87c2bdb3115cfa22349a16f5fd8e2ebfe45c6c84 Mon Sep 17 00:00:00 2001 From: michael steinkogler Date: Wed, 5 Feb 2020 19:08:49 +0100 Subject: [PATCH] don't process files multiple times - see https://github.com/scalastyle/scalastyle/issues/342 for the original bug - Directory.getFiles now filters out duplicates, returning unique files --- src/main/scala/org/scalastyle/Directory.scala | 31 ++++++++++----- .../scala/org/scalastyle/DirectoryTest.scala | 39 +++++++++++++++++++ 2 files changed, 60 insertions(+), 10 deletions(-) create mode 100644 src/test/scala/org/scalastyle/DirectoryTest.scala diff --git a/src/main/scala/org/scalastyle/Directory.scala b/src/main/scala/org/scalastyle/Directory.scala index e4d17c0b..df6ee7f8 100644 --- a/src/main/scala/org/scalastyle/Directory.scala +++ b/src/main/scala/org/scalastyle/Directory.scala @@ -64,16 +64,27 @@ object Directory { files: Iterable[File], excludeFilter: Option[FileFilter] = None ): Seq[FileSpec] = { - files.flatMap { f => - if (excludeFilter.exists(_.accept(f))) { - Nil - } else if (f.isDirectory) { - privateGetFiles(encoding, f.listFiles, excludeFilter) - } else if (scalaFileFilter.accept(f)) { - Seq(new DirectoryFileSpec(f.getAbsolutePath, encoding, f.getAbsoluteFile)) - } else { - Nil + + def getFilesHelper(currentFiles: Iterable[File], acc: Set[File]): Set[File] = { + currentFiles.headOption match { + case Some(f) => + if (excludeFilter.exists(_.accept(f))) { + getFilesHelper(currentFiles.tail, acc) + } else if (f.isDirectory) { + val newCurrentFiles = currentFiles.tail ++ f.listFiles + getFilesHelper(newCurrentFiles, acc) + } else if (scalaFileFilter.accept(f) && !acc(f)) { + val newAcc = acc + f + getFilesHelper(currentFiles.tail, newAcc) + } else { + getFilesHelper(currentFiles.tail, acc) + } + case None => acc } - }.toSeq + } + + val uniqueFiles = getFilesHelper(files, Set.empty) + uniqueFiles.toSeq.map(f => new DirectoryFileSpec(f.getAbsolutePath, encoding, f.getAbsoluteFile)) } + } diff --git a/src/test/scala/org/scalastyle/DirectoryTest.scala b/src/test/scala/org/scalastyle/DirectoryTest.scala new file mode 100644 index 00000000..fb20e663 --- /dev/null +++ b/src/test/scala/org/scalastyle/DirectoryTest.scala @@ -0,0 +1,39 @@ +package org.scalastyle + +import java.io.File + +import org.junit.{Assert, Test} +import org.scalatestplus.junit.AssertionsForJUnit + +class DirectoryTest extends AssertionsForJUnit { + + private def toFile(s: String) = { + val base = "src/test/resources/testDir/" + new File(base + s) + } + + @Test + def processSingleFileOnlyOnce(): Unit = { + val duplicatedFile = List("dirA/X.scala", "dirA/X.scala") + assertGetFiles(1, duplicatedFile) + } + + @Test + def processDirectoryOnlyOnce(): Unit = { + val duplicatedDir = List("dirA", "dirA") + assertGetFiles(1, duplicatedDir) + } + + @Test + def processFileInProcessDirOnlyOnce(): Unit = { + val duplicatedFileInDir = List("dirB", "dirB/Y.scala") + assertGetFiles(2, duplicatedFileInDir) + } + + + private def assertGetFiles(nrExpectedFiles: Int, inputFiles: Seq[String]): Unit = { + val files = Directory.getFiles(None, inputFiles.map(toFile)) + Assert.assertEquals(nrExpectedFiles, files.size) + } + +}