Permalink
Browse files

Add MultilineScaladocCommentsStartOnFirstLine preference (closes #16)

  • Loading branch information...
1 parent e101a6e commit 0c917be22374588df8f8672cc4de2fd041b8107c @mdr mdr committed Apr 7, 2011
View
@@ -5,6 +5,7 @@
* Ability to import/export preferences as properties; --preferencesFile=<path> command-line option
* FIX: incorrect indent behaviour for finally block after a catch block
* Add SpacesWithinPatternBinders preference (issue #15)
+* Add MultilineScaladocCommentsStartOnFirstLine preference (issue #16)
0.0.9 (26/February/11)
View
@@ -146,6 +146,7 @@ Usage::
[+|-]formatXml Enable/disable Format XML literals
[+|-]indentLocalDefs Enable/disable Indent local defs an extra level
[+|-]indentPackageBlocks Enable/disable Indent package blocks
+ [+|-]multilineScaladocCommentsStartOnFirstLine Enable/disable Start multiline Scaladoc comment body on same line as the opening '/**'
[+|-]preserveDanglingCloseParenthesis Enable/disable Allow a newline before a ')' in an argument expression.
[+|-]preserveSpaceBeforeArguments Enable/disable Preserve a space before a parenthesis argument
[+|-]rewriteArrowSymbols Enable/disable Replace arrow tokens with unicode equivalents: => with ⇒, and <- with ←
@@ -357,6 +358,24 @@ Default: ``2``
The number of spaces to use for each level of indentation.
+multilineScaladocCommentsStartOnFirstLine
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Default: ``false``
+
+If ``true``, start a multi-line Scaladoc comment body on same line as the opening comment delimiter::
+
+ /** This method applies f to each
+ * element of the given list.
+ */
+
+If ``false``, start the comment body on a separate line below the opening delimiter::
+
+ /**
+ * This method applies f to each
+ * element of the given list.
+ */
+
preserveDanglingCloseParenthesis
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -68,6 +68,11 @@
/**
* @parameter default-value=false
*/
+ protected int multilineScaladocCommentsStartOnFirstLine;
+
+ /**
+ * @parameter default-value=false
+ */
protected boolean preserveDanglingCloseParenthesis;
/**
@@ -111,6 +116,7 @@ public void execute() throws MojoExecutionException {
formatXml,
indentLocalDefs,
indentPackageBlocks,
+ multilineScaladocCommentsStartOnFirstLine,
preserveDanglingCloseParenthesis,
preserveSpaceBeforeArguments,
rewriteArrowSymbols,
@@ -50,6 +50,7 @@ object MojoFormatter {
formatXml: Boolean,
indentLocalDefs: Boolean,
indentPackageBlocks: Boolean,
+ multilineScaladocCommentsStartOnFirstLine: Boolean,
preserveDanglingCloseParenthesis: Boolean,
preserveSpaceBeforeArguments: Boolean,
rewriteArrowSymbols: Boolean,
@@ -68,6 +69,7 @@ object MojoFormatter {
.setPreference(FormatXml, formatXml)
.setPreference(IndentLocalDefs, indentLocalDefs)
.setPreference(IndentPackageBlocks, indentPackageBlocks)
+ .setPreference(MultilineScaladocCommentsStartOnFirstLine, multilineScaladocCommentsStartOnFirstLine)
.setPreference(PreserveDanglingCloseParenthesis, preserveDanglingCloseParenthesis)
.setPreference(PreserveSpaceBeforeArguments, preserveSpaceBeforeArguments)
.setPreference(RewriteArrowSymbols, rewriteArrowSymbols)
@@ -4,17 +4,26 @@ import scalariform.parser._
import scalariform.utils._
import scalariform.lexer._
import scalariform.formatter.preferences._
+import scala.annotation.tailrec
trait CommentFormatter { self: HasFormattingPreferences with ScalaFormatter
private def getLines(comment: String): (String, List[String]) = {
val prefix = List("/** ", "/**", "/* ", "/*").find(comment.startsWith).get
val (start, rest) = comment.splitAt(prefix.length)
val (contents, _) = rest.splitAt(rest.length - "*/".length)
- val lines = contents.split("""\r?\n([ \t]*\*?[ \t]?)?""", Integer.MAX_VALUE).toList
- (start, lines)
+ val firstLine :: otherLines = contents.split("""\r?\n([ \t]*\*?)?""", Integer.MAX_VALUE).toList
+ val adjustedLines = dropInitialSpaces(firstLine, 1) :: (otherLines map { dropInitialSpaces(_, afterStarSpaces) })
+ (start, adjustedLines)
}
+ @tailrec
+ private def dropInitialSpaces(s: String, maxSpacesToDrop: Int): String =
+ if (maxSpacesToDrop > 0 && s.startsWith(" "))
+ dropInitialSpaces(s drop 1, maxSpacesToDrop - 1)
+ else
+ s
+
private def removeTrailingWhitespace(s: String) = s.reverse.dropWhile(_.isWhitespace).reverse
private def pruneEmptyInitial(lines: List[String]) = lines match {
@@ -24,20 +33,30 @@ trait CommentFormatter { self: HasFormattingPreferences with ScalaFormatter ⇒
private def pruneEmptyFinal(lines: List[String]) = pruneEmptyInitial(lines.reverse).reverse
+ private def afterStarSpaces = if (formattingPreferences(MultilineScaladocCommentsStartOnFirstLine)) 2 else 1
+
def formatComment(comment: HiddenToken, indentLevel: Int): String =
if (comment.text contains '\n') {
val sb = new StringBuilder
val (start, rawLines) = getLines(comment.text)
val lines = pruneEmptyFinal(pruneEmptyInitial(rawLines))
- // println("formatComment: " + (start, lines))
+ val startOnFirstLine = formattingPreferences(MultilineScaladocCommentsStartOnFirstLine)
+
sb.append(start.trim)
+ var firstLine = true
for (line lines) {
val trimmedLine = removeTrailingWhitespace(line)
- sb.append(newlineSequence).indent(indentLevel).append(" *")
- if (!trimmedLine.isEmpty)
- sb.append(" ").append(trimmedLine)
+ if (firstLine && startOnFirstLine) {
+ if (!trimmedLine.isEmpty)
+ sb.append(" ").append(trimmedLine)
+ } else {
+ sb.append(newlineSequence).indent(indentLevel).append(" *")
+ if (!trimmedLine.isEmpty)
+ sb.append(" " * afterStarSpaces).append(trimmedLine)
+ }
+ firstLine = false
}
sb.append(newlineSequence).indent(indentLevel).append(" */")
sb.toString
@@ -63,7 +63,7 @@ object AllPreferences {
val preferences: List[PreferenceDescriptor[_]] = List(RewriteArrowSymbols, IndentSpaces, SpaceBeforeColon, CompactStringConcatenation,
PreserveSpaceBeforeArguments, AlignParameters, DoubleIndentClassDeclaration, FormatXml, IndentPackageBlocks,
AlignSingleLineCaseStatements, AlignSingleLineCaseStatements.MaxArrowIndent, IndentLocalDefs, PreserveDanglingCloseParenthesis,
- SpaceInsideParentheses, SpaceInsideBrackets, SpacesWithinPatternBinders)
+ SpaceInsideParentheses, SpaceInsideBrackets, SpacesWithinPatternBinders, MultilineScaladocCommentsStartOnFirstLine)
val preferencesByKey: Map[String, PreferenceDescriptor[_]] = {
var map: Map[String, PreferenceDescriptor[_]] = Map()
@@ -172,3 +172,9 @@ case object SpacesWithinPatternBinders extends BooleanPreferenceDescriptor {
val description = "Add a space around the @ token in pattern binders"
val defaultValue = true
}
+
+case object MultilineScaladocCommentsStartOnFirstLine extends BooleanPreferenceDescriptor {
+ val key = "multilineScaladocCommentsStartOnFirstLine"
+ val description = "Start multiline Scaladoc comment body on same line as the opening '/**' "
+ val defaultValue = false
+}
@@ -89,4 +89,37 @@ class CommentFormatterTest extends AbstractFormatterTest {
| */
|"""
+ {
+ implicit val formattingPreferences = FormattingPreferences.setPreference(MultilineScaladocCommentsStartOnFirstLine, true)
+
+ """/** This method applies f to each
+ | * element of the given list.
+ | */""" ==>
+ """/** This method applies f to each
+ | * element of the given list.
+ | */
+ |"""
+
+ """/** Foo
+ |Bar
+ |*Baz */""" ==>
+ """/** Foo
+ | * Bar
+ | * Baz
+ | */
+ |"""
+
+ """/** Foo
+ |*/""" ==>
+ """/** Foo
+ | */
+ |"""
+
+ """/**
+ |*/""" ==>
+ """/**
+ | */
+ |"""
+ }
+
}

0 comments on commit 0c917be

Please sign in to comment.