Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,27 @@ To override the configuration for Scala/Java files or add a configuration for so
headerMappings := headerMappings.value + (HeaderFileType.scala -> HeaderCommentStyle.cppStyleLineComment)
```

#### Custom comment creators

You can customize how content gets created by providing your own
`CommentCreator`. For example, this would be a (crude) way to preserve the
copyright year in existing headers but still update the rest:

CommentStyle.cStyleBlockComment.copy(commentCreator = new CommentCreator() {
val Pattern = "(?s).*?(\\d{4}(-\\d{4})?).*".r
def findYear(header: String): Option[String] = header match {
case Pattern(years, _) => Some(years)
case _ => None
}
override def apply(text: String, existingText: Option[String]): String = {
val newText = CommentStyle.cStyleBlockComment.commentCreator.apply(text, existingText)
existingText
.flatMap(findYear)
.map(year => newText.replace("2017", year))
.getOrElse(newText)
}
})

### Excluding files

To exclude some files, use the [sbt's file filters](http://www.scala-sbt.org/0.13/docs/Howto-Customizing-Paths.html#Include%2Fexclude+files+in+the+source+directory):
Expand Down
22 changes: 15 additions & 7 deletions src/main/scala/de/heikoseeberger/sbtheader/CommentStyle.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,23 @@ import scala.util.matching.Regex
*/
final case class CommentStyle(commentCreator: CommentCreator, pattern: Regex) {

def apply(licenseText: String, existingHeader: Option[String]): String =
commentCreator(licenseText, existingHeader) + newLine + newLine

def apply(license: License, existingHeader: Option[String]): String =
apply(license.text, existingHeader)

def apply(licenseText: String): String =
commentCreator(licenseText) + newLine + newLine
apply(licenseText, None)

def apply(license: License): String =
apply(license.text)
}

sealed trait CommentCreator {
def apply(text: String): String
trait CommentCreator {
def apply(text: String, existingText: Option[String] = None): String

def apply(text: String): String = apply(text, None)
}

object CommentStyle {
Expand All @@ -60,7 +68,7 @@ object CommentStyle {

object TwirlStyleFramedBlockCommentCreator extends CommentCreator {

def apply(text: String): String = {
def apply(text: String, existingText: Option[String]): String = {
val maxLineLength = text.lines.map(_.length).max

def fillLine(line: String) =
Expand All @@ -80,7 +88,7 @@ object TwirlStyleFramedBlockCommentCreator extends CommentCreator {

final class LineCommentCreator(linePrefix: String) extends CommentCreator {

override def apply(text: String): String = {
override def apply(text: String, existingText: Option[String]): String = {
def prependWithLinePrefix(s: String) =
s match {
case "" => if (!linePrefix.trim.isEmpty) linePrefix else ""
Expand All @@ -96,10 +104,10 @@ final class CommentBlockCreator(blockPrefix: String, linePrefix: String, blockSu

private val lineCommentCreator = new LineCommentCreator(linePrefix)

def apply(text: String): String =
def apply(text: String, existingText: Option[String]): String =
blockPrefix + newLine + lineCommentCreator(text) + newLine + blockSuffix
}

object IdentityCommentCreator extends CommentCreator {
override def apply(text: String) = text
override def apply(text: String, existingText: Option[String]) = text
}
30 changes: 17 additions & 13 deletions src/main/scala/de/heikoseeberger/sbtheader/HeaderCreator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ final class HeaderCreator private (fileType: FileType,

private val crlf = """(?s)(?:.*)(\r\n)(?:.*)""".r
private val cr = """(?s)(?:.*)(\r)(?:.*)""".r
private val headerText = commentStyle(license)
private val headerPattern = commentStyle.pattern

private val (firstLine, text) = {
Expand Down Expand Up @@ -67,21 +66,26 @@ final class HeaderCreator private (fileType: FileType,
case _ => "\n"
}

private val headerNewLine =
headerText match {
case crlf(_) => "\r\n"
case cr(_) => "\r"
case _ => "\n"
}

private val newHeaderText = headerText.replace(headerNewLine, fileNewLine)
private def newHeaderText(existingHeader: Option[String]) = {
val headerText = commentStyle(license, existingHeader)
val headerNewLine =
headerText match {
case crlf(_) => "\r\n"
case cr(_) => "\r"
case _ => "\n"
}
headerText.replace(headerNewLine, fileNewLine)
}

private val modifiedText =
text match {
case headerPattern(`headerText`, _) => None
case headerPattern(_, body) => Some(firstLine + newHeaderText + body)
case body if body.isEmpty => None
case body => Some(firstLine + newHeaderText + body.replaceAll("""^\s+""", "")) // Trim left
case headerPattern(existingText, body) =>
val newText = newHeaderText(Some(existingText))
if (newText == existingText) None
else Some(firstLine + newText + body.replaceAll("""^\s+""", "")) // Trim left
case body if body.isEmpty => None
case body =>
Some(firstLine + newHeaderText(None) + body.replaceAll("""^\s+""", "")) // Trim left
}
log.debug(s"Modified text of file is:$newLine$modifiedText")

Expand Down
43 changes: 41 additions & 2 deletions src/test/scala/de/heikoseeberger/sbtheader/HeaderCreatorSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -179,12 +179,51 @@ final class HeaderCreatorSpec extends WordSpec with Matchers {
)
}
}

"given a file with an existing copyright year" should {
val yearPreservingStyle =
CommentStyle.cStyleBlockComment.copy(commentCreator = new CommentCreator() {
val Pattern = "(?s).*?(\\d{4}(-\\d{4})?).*".r
def findYear(header: String): Option[String] = header match {
case Pattern(years, _) => Some(years)
case _ => None
}
override def apply(text: String, existingText: Option[String]): String = {
val newText = CommentStyle.cStyleBlockComment.commentCreator.apply(text, existingText)
existingText
.flatMap(findYear)
.map(year => newText.replace("2017", year))
.getOrElse(newText)
}
})
val licenseText = "Copyright 2017 MyCorp, Inc <https://mycorp.com>"

"allow updating the header retaining the copyright year" in {
val fileContent = """/*
| * Copyright 2016 MyCorp http://mycorp.com
| */
|This is the file content
|""".stripMargin

createHeader(fileContent, licenseText, commentCreator = yearPreservingStyle) shouldBe Some(
"""/*
| * Copyright 2016 MyCorp, Inc <https://mycorp.com>
| */
|
|This is the file content
|""".stripMargin
)
}
}
}

private def createHeader(fileContent: String, header: String, fileType: FileType = FileType.sh) =
private def createHeader(fileContent: String,
header: String,
fileType: FileType = FileType.sh,
commentCreator: CommentStyle = hashLineComment) =
HeaderCreator(
fileType,
hashLineComment,
commentCreator,
Custom(header),
new StubLogger,
new ByteArrayInputStream(fileContent.getBytes)
Expand Down