-
-
Save jpcaruana/826050 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.agitude.fileutils | |
import java.io.File | |
import org.apache.commons.io.FileUtils | |
// Utility object for test purpose only | |
object DummyProject { | |
private val TMP_DIR = new File("tmp") | |
val WEB_PACKAGE = Package("org.agitude.web", "module1") | |
val COMMONS_PACKAGE = Package("org.agitude.commons", "module1") | |
val OTHER_WEB_PACKAGE = Package("org.agitude.web", "module2") | |
def clearProject = FileUtils.deleteDirectory(TMP_DIR) | |
def checker = JavaDirChecker(TMP_DIR) | |
case class Package(path: String, module: String) { | |
require(path matches "[\\.a-z]*") | |
val declaration = "package " + path + ";" | |
val dir = new File(TMP_DIR + "/" + module, path replace ('.', '/')) | |
def addFile(filename: String) = new SomeFile(this, filename) | |
def addClass(className: String) = new JavaClass(this, className) | |
} | |
class SomeFile(aPackage: Package, filename: String) { | |
aPackage.dir mkdirs | |
val file = new File(aPackage.dir, filename) | |
val path = file.getAbsolutePath | |
} | |
class JavaClass(aPackage: Package, className: String) | |
extends SomeFile(aPackage, filename = className + ".java") { | |
FileUtils.writeStringToFile(file, aPackage.declaration) | |
val fullName: String = aPackage.path + "." + className | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.agitude.fileutils | |
import java.io.File | |
import io.Source | |
import collection.Iterator | |
import scala.annotation.tailrec | |
case class JavaDirChecker(directory: File) { | |
require(directory.isDirectory) | |
val files: List[File] = listJavaFiles(directory) | |
val conflicts: List[(String, Set[String])] = extract(files, classPath) | |
val nameCollisions: List[(String, Set[String])] = extract(files, shortName) | |
@tailrec | |
private def extract(list: List[File], description: File => String): List[(String, Set[String])] = { | |
list match { | |
case Nil => Nil | |
case x :: ys => { | |
val (listX, others) = ys partition (file => description(x) == description(file)) | |
if (listX isEmpty) extract(others, description) | |
else (description(x), toPaths(x +: listX)) :: extract(others, description) | |
} | |
} | |
} | |
private def listJavaFiles(f: File): List[File] = { | |
val these = f.listFiles | |
val (directories, files) = these partition (_.isDirectory) | |
(files filter (_.getName endsWith ".java")).toList ++ directories.flatMap(listJavaFiles) | |
} | |
private def packageName(file: File): String = { | |
val source: Source = Source.fromFile(file) | |
val iterator: Iterator[String] = source getLines() filter (_ matches "package .*;") | |
if (iterator.isEmpty) throw new Exception("There should be a package definition in Java file " + file.getAbsolutePath) | |
iterator.next.replaceAll("package (.*);", "$1") | |
} | |
private def shortName(file: File): String = file.getName takeWhile ('.' !=) | |
private def classPath(file: File): String = packageName(file) + "." + shortName(file) | |
private def toPaths(files: List[File]): Set[String] = files map (file => file.getAbsolutePath) toSet | |
} | |
class PrintableResult(result: List[(String, Set[String])]) { | |
def prettyPrint = { | |
result foreach (pair => { | |
println(pair._1) | |
pair._2 foreach (element => println(" " + element)) | |
}) | |
} | |
} | |
object JavaDirChecker { | |
implicit def toPrintable(result: List[(String, Set[String])]): PrintableResult = new PrintableResult(result) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.agitude.fileutils | |
import org.scalatest.{BeforeAndAfterEach, FunSuite} | |
import DummyProject._ | |
import JavaDirChecker._ | |
class JavaDirCheckerTest extends FunSuite with BeforeAndAfterEach { | |
override def beforeEach() = clearProject | |
test("JavaDirChecker returns nothing if no Java File") { | |
WEB_PACKAGE addFile "Toto.txt" | |
OTHER_WEB_PACKAGE addFile "Toto.txt" | |
assert(checker.conflicts isEmpty) | |
} | |
test("JavaDirChecker returns nothing if Java classNames do not conflict") { | |
WEB_PACKAGE addClass "Toto" | |
COMMONS_PACKAGE addClass "Titi" | |
assert(checker.conflicts isEmpty) | |
} | |
test("JavaDirChecker returns nothing if Java packages do not conflict") { | |
WEB_PACKAGE addClass "Toto" | |
COMMONS_PACKAGE addClass "Toto" | |
assert(checker.conflicts isEmpty) | |
} | |
test("JavaDirChecker returns a list of conflicting class names") { | |
val foo = WEB_PACKAGE addClass "Foo" | |
val foo2 = OTHER_WEB_PACKAGE addClass "Foo" | |
val foo3 = COMMONS_PACKAGE addClass "Foo" | |
val bar = WEB_PACKAGE addClass "Bar" | |
val bar2 = COMMONS_PACKAGE addClass "Bar" | |
val gee = WEB_PACKAGE addClass "Gee" | |
assert(checker.conflicts === List((foo.fullName, Set(foo.path, foo2.path)))) | |
assert(checker.nameCollisions === List(("Bar", Set(bar.path, bar2.path)), | |
("Foo", Set(foo.path, foo2.path, foo3.path)))) | |
// The icing on the cake : Pretty Printing | |
println("Pretty Printing Demo ") | |
println("==> Conflicting class definitions:") | |
checker.conflicts.prettyPrint | |
println(" ") | |
println("==> Short Names collisions:") | |
checker.nameCollisions.prettyPrint | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment