From f092b5b32748bb980359deaa7add85ce88105214 Mon Sep 17 00:00:00 2001 From: Gerard Basler Date: Mon, 17 Dec 2012 17:52:26 +0100 Subject: [PATCH 01/15] Add new option `noSpacesAroundMultiImports` to disable reformatting of `import a.b.c.{d, e, f}` into `import a.b.c.{ d, e, f }`. Especially for Java experienced coders this looks more natural. --- .../scala/scalariform/formatter/ExprFormatter.scala | 4 ++++ .../formatter/preferences/PreferenceDescriptor.scala | 10 ++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) mode change 100644 => 100755 scalariform/src/main/scala/scalariform/formatter/ExprFormatter.scala mode change 100644 => 100755 scalariform/src/main/scala/scalariform/formatter/preferences/PreferenceDescriptor.scala diff --git a/scalariform/src/main/scala/scalariform/formatter/ExprFormatter.scala b/scalariform/src/main/scala/scalariform/formatter/ExprFormatter.scala old mode 100644 new mode 100755 index f06d6804..7c950a77 --- a/scalariform/src/main/scala/scalariform/formatter/ExprFormatter.scala +++ b/scalariform/src/main/scala/scalariform/formatter/ExprFormatter.scala @@ -909,9 +909,13 @@ trait ExprFormatter { self: HasFormattingPreferences with AnnotationFormatter wi val newFormatterState = formatterState.copy(inSingleLineBlock = singleLineBlock) if (singleLineBlock) { + if (formattingPreferences(NoSpacesAroundMultiImports)) + formatResult = formatResult.before(firstImportSelector.firstToken, Compact) formatResult ++= format(firstImportSelector) for ((comma, otherImportSelector) ← otherImportSelectors) formatResult ++= format(otherImportSelector) + if (formattingPreferences(NoSpacesAroundMultiImports)) + formatResult = formatResult.before(rbrace, Compact) } else { formatResult = formatResult.before(firstImportSelector.firstToken, formatterState.nextIndentLevelInstruction) formatResult ++= format(firstImportSelector) diff --git a/scalariform/src/main/scala/scalariform/formatter/preferences/PreferenceDescriptor.scala b/scalariform/src/main/scala/scalariform/formatter/preferences/PreferenceDescriptor.scala old mode 100644 new mode 100755 index 48975161..96cb17fa --- a/scalariform/src/main/scala/scalariform/formatter/preferences/PreferenceDescriptor.scala +++ b/scalariform/src/main/scala/scalariform/formatter/preferences/PreferenceDescriptor.scala @@ -64,7 +64,7 @@ object AllPreferences { PreserveSpaceBeforeArguments, AlignParameters, DoubleIndentClassDeclaration, FormatXml, IndentPackageBlocks, AlignSingleLineCaseStatements, AlignSingleLineCaseStatements.MaxArrowIndent, IndentLocalDefs, PreserveDanglingCloseParenthesis, SpaceInsideParentheses, SpaceInsideBrackets, SpacesWithinPatternBinders, MultilineScaladocCommentsStartOnFirstLine, IndentWithTabs, - CompactControlReadability, PlaceScaladocAsterisksBeneathSecondAsterisk) + CompactControlReadability, PlaceScaladocAsterisksBeneathSecondAsterisk, NoSpacesAroundMultiImports) val preferencesByKey: Map[String, PreferenceDescriptor[_]] = { var map: Map[String, PreferenceDescriptor[_]] = Map() @@ -196,4 +196,10 @@ case object PlaceScaladocAsterisksBeneathSecondAsterisk extends BooleanPreferenc val key = "placeScaladocAsterisksBeneathSecondAsterisk" val description = "Place Scaladoc asterisks beneath the second asterisk in the opening '/**', as opposed to the first" val defaultValue = false -} \ No newline at end of file +} + +case object NoSpacesAroundMultiImports extends BooleanPreferenceDescriptor { + val key = "noSpacesAroundMultiImports" + val description = "Don't place spaces around multi imports (Java-style)" + val defaultValue = false +} From c1886686073baf42283de75600ed237295162f1e Mon Sep 17 00:00:00 2001 From: Gerard Basler Date: Tue, 25 Dec 2012 19:03:12 +0100 Subject: [PATCH 02/15] Add multi-line case formatting option. --- .../scala/scalariform/formatter/CaseClauseFormatter.scala | 3 ++- .../formatter/preferences/PreferenceDescriptor.scala | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala b/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala index 9255a4bc..516b2612 100644 --- a/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala +++ b/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala @@ -86,7 +86,8 @@ trait CaseClauseFormatter { self: HasFormattingPreferences with ExprFormatter wi val clauseBodyIsMultiline = containsNewline(pruneTrailingNewline(statSeq)) || statSeq.firstTokenOption.exists(hiddenPredecessors(_).containsNewline) - if (formattedCasePattern.contains('\n') || (first && !clausesAreMultiline) || (!first && !newlineBeforeClause) || clauseBodyIsMultiline) + if (!formattingPreferences(AlignSingleLineCaseStatements.AlignMultiLineCaseStatements) && + (formattedCasePattern.contains('\n') || (first && !clausesAreMultiline) || (!first && !newlineBeforeClause) || clauseBodyIsMultiline)) Right(caseClause) :: otherClausesGrouped else { val arrowAdjust = (if (formattingPreferences(RewriteArrowSymbols)) 1 else casePattern.arrow.length) + 1 diff --git a/scalariform/src/main/scala/scalariform/formatter/preferences/PreferenceDescriptor.scala b/scalariform/src/main/scala/scalariform/formatter/preferences/PreferenceDescriptor.scala index 96cb17fa..daba01d6 100755 --- a/scalariform/src/main/scala/scalariform/formatter/preferences/PreferenceDescriptor.scala +++ b/scalariform/src/main/scala/scalariform/formatter/preferences/PreferenceDescriptor.scala @@ -62,7 +62,7 @@ trait IntegerPreferenceDescriptor extends PreferenceDescriptor[Int] { object AllPreferences { val preferences: List[PreferenceDescriptor[_]] = List(RewriteArrowSymbols, IndentSpaces, SpaceBeforeColon, CompactStringConcatenation, PreserveSpaceBeforeArguments, AlignParameters, DoubleIndentClassDeclaration, FormatXml, IndentPackageBlocks, - AlignSingleLineCaseStatements, AlignSingleLineCaseStatements.MaxArrowIndent, IndentLocalDefs, PreserveDanglingCloseParenthesis, + AlignSingleLineCaseStatements, AlignSingleLineCaseStatements.MaxArrowIndent, AlignSingleLineCaseStatements.AlignMultiLineCaseStatements, IndentLocalDefs, PreserveDanglingCloseParenthesis, SpaceInsideParentheses, SpaceInsideBrackets, SpacesWithinPatternBinders, MultilineScaladocCommentsStartOnFirstLine, IndentWithTabs, CompactControlReadability, PlaceScaladocAsterisksBeneathSecondAsterisk, NoSpacesAroundMultiImports) @@ -142,6 +142,12 @@ case object AlignSingleLineCaseStatements extends BooleanPreferenceDescriptor { val defaultValue = 40 } + case object AlignMultiLineCaseStatements extends BooleanPreferenceDescriptor { + val key = "alignSingleLineCaseStatements.alignMultiLineCaseStatements" + val description = "Align the arrows of consecutive multi-line case statements" + val defaultValue = false + } + } case object IndentLocalDefs extends BooleanPreferenceDescriptor { From 45515d548ce727ae573bdf94b42929cc006ae97a Mon Sep 17 00:00:00 2001 From: Gerard Basler Date: Sun, 13 Jan 2013 19:42:54 +0100 Subject: [PATCH 03/15] Add `GroupByNewLine` option that let's you format blocks in case statements individually (IntelliJ compatibility). --- .../formatter/CaseClauseFormatter.scala | 25 +++- .../preferences/PreferenceDescriptor.scala | 6 + .../main/scala/scalariform/lexer/Token.scala | 2 + .../scala/scalariform/lexer/TokenType.scala | 4 +- .../formatter/CaseClausesFormatterTest.scala | 109 ++++++++++++++++++ 5 files changed, 142 insertions(+), 4 deletions(-) diff --git a/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala b/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala index 516b2612..ecc2a441 100644 --- a/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala +++ b/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala @@ -1,6 +1,6 @@ package scalariform.formatter -import scalariform.lexer.Token +import scalariform.lexer.{TokenType, Token} import scalariform.lexer.Tokens._ import scalariform.parser._ import scalariform.utils.Utils @@ -81,7 +81,7 @@ trait CaseClauseFormatter { self: HasFormattingPreferences with ExprFormatter wi val newlineBeforeClause = hiddenPredecessors(caseClause.firstToken).containsNewline || previousCaseClauseEndsWithNewline(caseClause, caseClausesAstNode) - // To evaluate whether a clause body is multiline, we ignore a trailing newline: + // To evaluate whether a clause body is multiline, we ignore a trailing newline: val prunedStatSeq = pruneTrailingNewline(statSeq) val clauseBodyIsMultiline = containsNewline(pruneTrailingNewline(statSeq)) || statSeq.firstTokenOption.exists(hiddenPredecessors(_).containsNewline) @@ -100,7 +100,26 @@ trait CaseClauseFormatter { self: HasFormattingPreferences with ExprFormatter wi } } } - groupClauses(caseClausesAstNode.caseClauses, first = true) + + val caseClauses: List[CaseClause] = caseClausesAstNode.caseClauses + + val ranges: List[(Int, Int)] = if (formattingPreferences(AlignSingleLineCaseStatements.GroupByNewLine)) { + val newLinesAt = (caseClauses.zipWithIndex.collect { + case (c, i) if c.tokens.exists(_.isNewlines) => i + 1 + }) + + val newLinesWithBeginAndEnd = (if (newLinesAt.contains(0)) List() else List(0)) ++ newLinesAt ++ List(caseClauses.length) + + newLinesWithBeginAndEnd.zip(newLinesWithBeginAndEnd.tail) + } else { + List(0 -> caseClauses.length) + } + + ranges.foldLeft(List[Either[ConsecutiveSingleLineCaseClauses, CaseClause]]()) { + case (acc, (begin, end)) => + val slice = caseClauses.slice(begin, end) + acc ++ groupClauses(slice, first = true) + } } private case class ConsecutiveSingleLineCaseClauses(clauses: List[CaseClause], largestCasePatternLength: Int, smallestCasePatternLength: Int) { diff --git a/scalariform/src/main/scala/scalariform/formatter/preferences/PreferenceDescriptor.scala b/scalariform/src/main/scala/scalariform/formatter/preferences/PreferenceDescriptor.scala index daba01d6..cc2cd1aa 100755 --- a/scalariform/src/main/scala/scalariform/formatter/preferences/PreferenceDescriptor.scala +++ b/scalariform/src/main/scala/scalariform/formatter/preferences/PreferenceDescriptor.scala @@ -148,6 +148,12 @@ case object AlignSingleLineCaseStatements extends BooleanPreferenceDescriptor { val defaultValue = false } + case object GroupByNewLine extends BooleanPreferenceDescriptor { + val key = "alignSingleLineCaseStatements.groupByNewLine" + val description = "Treat blocks that are separated by newlines independently" + val defaultValue = false + } + } case object IndentLocalDefs extends BooleanPreferenceDescriptor { diff --git a/scalariform/src/main/scala/scalariform/lexer/Token.scala b/scalariform/src/main/scala/scalariform/lexer/Token.scala index 365122eb..6e5cb72b 100644 --- a/scalariform/src/main/scala/scalariform/lexer/Token.scala +++ b/scalariform/src/main/scala/scalariform/lexer/Token.scala @@ -27,6 +27,8 @@ case class Token(tokenType: TokenType, text: String, offset: Int, rawText: Strin def isNewline = tokenType.isNewline + def isNewlines = tokenType.isNewlines + @deprecated(message = "Use text instead" /*, since = "0.1.2"*/ ) def getText = text diff --git a/scalariform/src/main/scala/scalariform/lexer/TokenType.scala b/scalariform/src/main/scala/scalariform/lexer/TokenType.scala index 2f51e561..fb64f3ba 100644 --- a/scalariform/src/main/scala/scalariform/lexer/TokenType.scala +++ b/scalariform/src/main/scala/scalariform/lexer/TokenType.scala @@ -2,7 +2,9 @@ package scalariform.lexer case class TokenType(name: String, isXml: Boolean = false) { - def isNewline = this == Tokens.NEWLINE || this == Tokens.NEWLINES + def isNewline = this == Tokens.NEWLINE || isNewlines + + def isNewlines = this == Tokens.NEWLINES def isKeyword = Tokens.KEYWORDS contains this diff --git a/scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala b/scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala index a2e106a6..0a7966d4 100644 --- a/scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala +++ b/scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala @@ -306,4 +306,113 @@ class CaseClausesFormatterTest extends AbstractExpressionFormatterTest { | case elem @ Multi(values @ _*) => |}""" + { + implicit val formattingPreferences = FormattingPreferences.setPreference(AlignSingleLineCaseStatements, true) + .setPreference(AlignSingleLineCaseStatements.AlignMultiLineCaseStatements, true) + + """a match { + |case "once" => + |println("einmal") + |println("nochmal") + |case "many times" => + |println("again") + |println("multiline") + |case _ => + |println("again") + |println("multiline") + |}""" ==> + """a match { + | case "once" => + | println("einmal") + | println("nochmal") + | case "many times" => + | println("again") + | println("multiline") + | case _ => + | println("again") + | println("multiline") + |}""" + } + + { + implicit val formattingPreferences = FormattingPreferences.setPreference(AlignSingleLineCaseStatements, true) + .setPreference(AlignSingleLineCaseStatements.AlignMultiLineCaseStatements, true) + .setPreference(AlignSingleLineCaseStatements.GroupByNewLine, false) + + """a match { + |case "once" => + |println("einmal") + |println("nochmal") + |case "many times" => + |println("again") + |println("multiline") + |case _ => + |println("again") + |println("multiline") + | + |case "after a newline" => + |println("IntelliJ") + |println("formats") + |case "next lines" => + |println("separately") + |}""" ==> + """a match { + | case "once" => + | println("einmal") + | println("nochmal") + | case "many times" => + | println("again") + | println("multiline") + | case _ => + | println("again") + | println("multiline") + | + | case "after a newline" => + | println("IntelliJ") + | println("formats") + | case "next lines" => + | println("separately") + |}""" + } + + { + implicit val formattingPreferences = FormattingPreferences.setPreference(AlignSingleLineCaseStatements, true) + .setPreference(AlignSingleLineCaseStatements.AlignMultiLineCaseStatements, true) + .setPreference(AlignSingleLineCaseStatements.GroupByNewLine, true) + + """a match { + |case "once" => + |println("einmal") + |println("nochmal") + |case "many times" => + |println("again") + |println("multiline") + |case _ => + |println("again") + |println("multiline") + | + |case "after a newline" => + |println("IntelliJ") + |println("formats") + |case "next lines" => + |println("separately") + |}""" ==> + """a match { + | case "once" => + | println("einmal") + | println("nochmal") + | case "many times" => + | println("again") + | println("multiline") + | case _ => + | println("again") + | println("multiline") + | + | case "after a newline" => + | println("IntelliJ") + | println("formats") + | case "next lines" => + | println("separately") + |}""" + } } From 10e60cdcb22e6e4a23fcf9fd1670438d898730d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9rard=20Basler?= Date: Sun, 13 Jan 2013 19:52:58 +0100 Subject: [PATCH 04/15] Update README.rst --- README.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.rst b/README.rst index 7b735c0f..8f279d7e 100644 --- a/README.rst +++ b/README.rst @@ -28,6 +28,15 @@ You can also configure formatting to be run as a save action (Window -> Preferen To set preferences, go to Window -> Preferences -> Scala -> Formatter +Integration with IntelliJ +------------------------- + +IntelliJ already has a built-in Scala code formatter (C-L). +I use the original settings plus `Wraping and Braces` -> `Align columns in case branches`. +In order to achieve exactly the same formatting use the following options:: + +alignSingleLineCaseStatements +alignSingleLineCaseStatements.AlignMultiLineCaseStatements +alignSingleLineCaseStatements.GroupByNewLine + + Integration with Emacs/ENSIME ----------------------------- From 9f34d9de43fe8281c1821c4c725081480055daf8 Mon Sep 17 00:00:00 2001 From: Gerard Basler Date: Mon, 14 Jan 2013 02:07:38 +0100 Subject: [PATCH 05/15] Bugfix for `final` modifier in constructor arguments. --- .../src/main/scala/scalariform/formatter/ScalaFormatter.scala | 2 +- .../scala/scalariform/formatter/TemplateFormatterTest.scala | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/scalariform/src/main/scala/scalariform/formatter/ScalaFormatter.scala b/scalariform/src/main/scala/scalariform/formatter/ScalaFormatter.scala index 29cb2e0b..ed408a05 100644 --- a/scalariform/src/main/scala/scalariform/formatter/ScalaFormatter.scala +++ b/scalariform/src/main/scala/scalariform/formatter/ScalaFormatter.scala @@ -348,7 +348,7 @@ abstract class ScalaFormatter extends HasFormattingPreferences with TypeFormatte return CompactEnsuringGap if (type1 == MINUS && (type2 == INTEGER_LITERAL || type2 == FLOATING_POINT_LITERAL)) return Compact - if (Set(IMPLICIT, VAL, VAR, PRIVATE, PROTECTED, OVERRIDE).contains(type2) && type1 == LPAREN) + if (Set(IMPLICIT, VAL, VAR, PRIVATE, PROTECTED, OVERRIDE, FINAL).contains(type2) && type1 == LPAREN) return Compact if ((type1 == PROTECTED || type1 == PRIVATE) && type2 == LBRACKET) return Compact diff --git a/scalariform/src/test/scala/scalariform/formatter/TemplateFormatterTest.scala b/scalariform/src/test/scala/scalariform/formatter/TemplateFormatterTest.scala index 972bfbef..cc0a2783 100644 --- a/scalariform/src/test/scala/scalariform/formatter/TemplateFormatterTest.scala +++ b/scalariform/src/test/scala/scalariform/formatter/TemplateFormatterTest.scala @@ -195,6 +195,7 @@ class TemplateFormatterTest extends AbstractFormatterTest { "class A(private val b: C)" ==> "class A(private val b: C)" "class A(protected val b: C)" ==> "class A(protected val b: C)" "class A(override val b: C)" ==> "class A(override val b: C)" + "class A(final val b: C)" ==> "class A(final val b: C)" """class C[T <: A {val n: Int |val m :Int}]""" ==> From f197055fa7357e211ce7d5f93c4f328c9f1861a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9rard=20Basler?= Date: Mon, 14 Jan 2013 02:16:58 +0100 Subject: [PATCH 06/15] Update README.rst --- README.rst | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 8f279d7e..b4f91299 100644 --- a/README.rst +++ b/README.rst @@ -34,7 +34,23 @@ Integration with IntelliJ IntelliJ already has a built-in Scala code formatter (C-L). I use the original settings plus `Wraping and Braces` -> `Align columns in case branches`. In order to achieve exactly the same formatting use the following options:: - +alignSingleLineCaseStatements +alignSingleLineCaseStatements.AlignMultiLineCaseStatements +alignSingleLineCaseStatements.GroupByNewLine + + + def formattingPreferences = { + import scalariform.formatter.preferences._ + FormattingPreferences() + .setPreference(AlignParameters, true) + .setPreference(AlignSingleLineCaseStatements, true) + .setPreference(AlignSingleLineCaseStatements.AlignMultiLineCaseStatements, true) + .setPreference(AlignSingleLineCaseStatements.MaxArrowIndent, 120) + .setPreference(AlignSingleLineCaseStatements.GroupByNewLine, true) // IntelliJ compatible + .setPreference(CompactControlReadability, false) + .setPreference(NoSpacesAroundMultiImports, true) + .setPreference(FormatXml, false) + .setPreference(PreserveSpaceBeforeArguments, true) + .setPreference(IndentWithTabs, false) + .setPreference(SpacesWithinPatternBinders, false) // IntelliJ compatible + } Integration with Emacs/ENSIME From 26a73f53159613f77a7a3ce10184477461c998f3 Mon Sep 17 00:00:00 2001 From: Gerard Basler Date: Wed, 16 Jan 2013 09:36:01 +0100 Subject: [PATCH 07/15] Bugfix: align multi line case guards correctly in pattern matches. --- .../formatter/CaseClauseFormatter.scala | 20 +++++++++++++++++- .../formatter/CaseClausesFormatterTest.scala | 21 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) mode change 100644 => 100755 scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala mode change 100644 => 100755 scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala diff --git a/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala b/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala old mode 100644 new mode 100755 index ecc2a441..df7ee244 --- a/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala +++ b/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala @@ -91,7 +91,10 @@ trait CaseClauseFormatter { self: HasFormattingPreferences with ExprFormatter wi Right(caseClause) :: otherClausesGrouped else { val arrowAdjust = (if (formattingPreferences(RewriteArrowSymbols)) 1 else casePattern.arrow.length) + 1 - val casePatternLength = formattedCasePattern.length - arrowAdjust + val casePatternLengthConsideringNewLines = { + formattedCasePattern.split('\n').map(_.length).max + } + val casePatternLength = casePatternLengthConsideringNewLines - arrowAdjust otherClausesGrouped match { case Left(consecutiveSingleLineCaseClauses) :: otherGroups ⇒ Left(consecutiveSingleLineCaseClauses.prepend(caseClause, casePatternLength)) :: otherGroups @@ -134,6 +137,21 @@ trait CaseClauseFormatter { self: HasFormattingPreferences with ExprFormatter wi val CasePattern(caseToken: Token, pattern: Expr, guardOption: Option[Guard], arrow: Token) = casePattern var formatResult: FormatResult = NoFormatResult formatResult ++= format(pattern) + + val beginTokensAfterPipe = List(casePattern.pattern.tokens.head) ++ casePattern.pattern.tokens.zip(casePattern.pattern.tokens.tail).collect { + case (Token(PIPE, _, _, _), b) if b.associatedWhitespaceAndComments.containsNewline => b + } + + val alignBeginTokens: Map[Token, IntertokenFormatInstruction] = beginTokensAfterPipe.zip(beginTokensAfterPipe.tail).flatMap { + case (a, b) => if (b.associatedWhitespaceAndComments.containsNewline) { + Map(b -> EnsureNewlineAndIndent(0, Some(a))) + } else { + Map.empty[Token, IntertokenFormatInstruction] + } + }.toMap + + formatResult ++= FormatResult(alignBeginTokens, Map(), Map()) + for (guard ← guardOption) formatResult ++= format(guard) arrowInstructionOpt foreach { instruction ⇒ formatResult = formatResult.before(arrow, instruction) } diff --git a/scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala b/scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala old mode 100644 new mode 100755 index 0a7966d4..daff0ecc --- a/scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala +++ b/scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala @@ -415,4 +415,25 @@ class CaseClausesFormatterTest extends AbstractExpressionFormatterTest { | println("separately") |}""" } + + { + implicit val formattingPreferences = FormattingPreferences.setPreference(AlignSingleLineCaseStatements, true) + .setPreference(AlignSingleLineCaseStatements.MaxArrowIndent, 200) + .setPreference(AlignSingleLineCaseStatements.AlignMultiLineCaseStatements, true) + .setPreference(AlignSingleLineCaseStatements.GroupByNewLine, true) + + """x match { + |case 1 | 2 | + |3 | 4 | + |5 | 6 => 1 + |case 7 | 8 => 1 + |}""" ==> + """x match { + | case 1 | 2 | + | 3 | 4 | + | 5 | 6 => 1 + | case 7 | 8 => 1 + |}""" + } + } From 2a7146c763101896408f0d2f8e16ea74d0f93fe2 Mon Sep 17 00:00:00 2001 From: Gerard Basler Date: Wed, 16 Jan 2013 18:06:04 +0100 Subject: [PATCH 08/15] Bugfix: non-multi line cases were missing spaces before `=>`. --- .../scala/scalariform/formatter/CaseClauseFormatter.scala | 4 ++-- .../scalariform/formatter/CaseClausesFormatterTest.scala | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala b/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala index df7ee244..d216adf5 100755 --- a/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala +++ b/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala @@ -86,8 +86,8 @@ trait CaseClauseFormatter { self: HasFormattingPreferences with ExprFormatter wi val clauseBodyIsMultiline = containsNewline(pruneTrailingNewline(statSeq)) || statSeq.firstTokenOption.exists(hiddenPredecessors(_).containsNewline) - if (!formattingPreferences(AlignSingleLineCaseStatements.AlignMultiLineCaseStatements) && - (formattedCasePattern.contains('\n') || (first && !clausesAreMultiline) || (!first && !newlineBeforeClause) || clauseBodyIsMultiline)) + if (formattedCasePattern.contains('\n') || (first && !clausesAreMultiline) || (!first && !newlineBeforeClause) || + !formattingPreferences(AlignSingleLineCaseStatements.AlignMultiLineCaseStatements) && clauseBodyIsMultiline) Right(caseClause) :: otherClausesGrouped else { val arrowAdjust = (if (formattingPreferences(RewriteArrowSymbols)) 1 else casePattern.arrow.length) + 1 diff --git a/scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala b/scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala index daff0ecc..dad2aec7 100755 --- a/scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala +++ b/scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala @@ -436,4 +436,11 @@ class CaseClausesFormatterTest extends AbstractExpressionFormatterTest { |}""" } + { + implicit val formattingPreferences = FormattingPreferences.setPreference(AlignSingleLineCaseStatements, true) + .setPreference(AlignSingleLineCaseStatements.AlignMultiLineCaseStatements, true) + + """x match { case _: X => Y }""" ==> + """x match { case _: X => Y }""" + } } From 35593664bdfda3d75de62225d94a185ce12fea4a Mon Sep 17 00:00:00 2001 From: Gerard Basler Date: Sun, 20 Jan 2013 17:41:50 +0100 Subject: [PATCH 09/15] Fix multi line formatting. --- .../formatter/CaseClauseFormatter.scala | 2 +- .../formatter/CaseClausesFormatterTest.scala | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) mode change 100755 => 100644 scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala diff --git a/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala b/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala index d216adf5..ef0004c6 100755 --- a/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala +++ b/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala @@ -86,7 +86,7 @@ trait CaseClauseFormatter { self: HasFormattingPreferences with ExprFormatter wi val clauseBodyIsMultiline = containsNewline(pruneTrailingNewline(statSeq)) || statSeq.firstTokenOption.exists(hiddenPredecessors(_).containsNewline) - if (formattedCasePattern.contains('\n') || (first && !clausesAreMultiline) || (!first && !newlineBeforeClause) || + if (first && !clausesAreMultiline || !first && !newlineBeforeClause || !formattingPreferences(AlignSingleLineCaseStatements.AlignMultiLineCaseStatements) && clauseBodyIsMultiline) Right(caseClause) :: otherClausesGrouped else { diff --git a/scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala b/scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala old mode 100755 new mode 100644 index dad2aec7..1001a9fa --- a/scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala +++ b/scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala @@ -443,4 +443,26 @@ class CaseClausesFormatterTest extends AbstractExpressionFormatterTest { """x match { case _: X => Y }""" ==> """x match { case _: X => Y }""" } + + { + implicit val formattingPreferences = FormattingPreferences.setPreference(AlignSingleLineCaseStatements, true) + .setPreference(AlignSingleLineCaseStatements.AlignMultiLineCaseStatements, true) + .setPreference(AlignSingleLineCaseStatements.MaxArrowIndent, 200) + .setPreference(AlignSingleLineCaseStatements.GroupByNewLine, true) + + """|x match { + | case 1 => A + | case 1234 | + | 5678 => A + | case 5 => A + | case 12345678 => A + |}""" ==> + """|x match { + | case 1 => A + | case 1234 | + | 5678 => A + | case 5 => A + | case 12345678 => A + |}""" + } } From 1ad90f4e146111823b153f9a8304db48e8efbf48 Mon Sep 17 00:00:00 2001 From: Gerard Basler Date: Tue, 22 Jan 2013 08:25:18 +0100 Subject: [PATCH 10/15] Fix newline detection for case clauses. --- .../formatter/CaseClauseFormatter.scala | 10 +++++-- .../formatter/CaseClausesFormatterTest.scala | 29 +++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) mode change 100644 => 100755 scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala diff --git a/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala b/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala index ef0004c6..ece81fc1 100755 --- a/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala +++ b/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala @@ -187,10 +187,14 @@ trait CaseClauseFormatter { self: HasFormattingPreferences with ExprFormatter wi if separator.isNewline } yield separator - private def previousCaseClauseTrailingNewlineOpt(caseClause: CaseClause, caseClauses: CaseClauses): Option[Token] = - Utils.pairWithPrevious(caseClauses.caseClauses).collect { + private def previousCaseClauseTrailingNewlineOpt(caseClause: CaseClause, caseClauses: CaseClauses): Option[Token] = { + val previousCaseClauseOpt = Utils.pairWithPrevious(caseClauses.caseClauses).collect { case (Some(previousClause), `caseClause`) ⇒ previousClause - }.headOption.flatMap(getTrailingNewline) + }.headOption + val hasNewLine = previousCaseClauseOpt.flatMap(getTrailingNewline) + val hasNewLineAtEnd = previousCaseClauseOpt.flatMap(_.statSeq.tokens.lastOption.filter(_.isNewline)) + hasNewLine.orElse(hasNewLineAtEnd) + } private def previousCaseClauseEndsWithNewline(caseClause: CaseClause, caseClauses: CaseClauses): Boolean = previousCaseClauseTrailingNewlineOpt(caseClause, caseClauses).isDefined diff --git a/scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala b/scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala old mode 100644 new mode 100755 index 1001a9fa..1eaeb60f --- a/scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala +++ b/scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala @@ -465,4 +465,33 @@ class CaseClausesFormatterTest extends AbstractExpressionFormatterTest { | case 12345678 => A |}""" } + + { + implicit val formattingPreferences = FormattingPreferences.setPreference(AlignSingleLineCaseStatements, true) + .setPreference(AlignSingleLineCaseStatements.AlignMultiLineCaseStatements, true) + .setPreference(AlignSingleLineCaseStatements.MaxArrowIndent, 200) + + """|x match { + |case AA => a + |case B => b + |}""" ==> + """|x match { + | case AA => a + | case B => b + |}""" + } + + { + implicit val formattingPreferences = FormattingPreferences.setPreference(AlignSingleLineCaseStatements, true) + .setPreference(AlignSingleLineCaseStatements.AlignMultiLineCaseStatements, true) + + """|x match { + |case AA => (s: Int) => 1 + |case B => (s: Int) => 2 + |}""" ==> + """|x match { + | case AA => (s: Int) => 1 + | case B => (s: Int) => 2 + |}""" + } } From 3fc182e87d88557ad6fb42acd40d03d2d5a1dc8d Mon Sep 17 00:00:00 2001 From: Gerard Basler Date: Wed, 30 Jan 2013 21:37:01 +0100 Subject: [PATCH 11/15] Bugfix: format new scopes after `=>` in lambda function correctly. --- .../scala/scalariform/formatter/ExprFormatter.scala | 11 +++++++++-- .../formatter/MiscExpressionFormatterTest.scala | 11 +++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/scalariform/src/main/scala/scalariform/formatter/ExprFormatter.scala b/scalariform/src/main/scala/scalariform/formatter/ExprFormatter.scala index 7c950a77..403c92b6 100755 --- a/scalariform/src/main/scala/scalariform/formatter/ExprFormatter.scala +++ b/scalariform/src/main/scala/scalariform/formatter/ExprFormatter.scala @@ -636,15 +636,22 @@ trait ExprFormatter { self: HasFormattingPreferences with AnnotationFormatter wi (CompactEnsuringGap, indentedState) formatResult = formatResult.before(statSeq.firstToken, instruction) formatResult ++= format(params) + + val hasNewScopeAfterArrow = { + val arrowIndex = statSeq.tokens.indexWhere(_.tokenType == ARROW) + val tokenAfterArrow = statSeq.tokens.lift(arrowIndex + 1) + tokenAfterArrow.map(_.tokenType == lbrace.tokenType).getOrElse(false) + } for (firstToken ← subStatSeq.firstTokenOption) { val instruction = - if (hiddenPredecessors(firstToken).containsNewline || containsNewline(subStatSeq)) + if (hiddenPredecessors(firstToken).containsNewline || containsNewline(subStatSeq) && !hasNewScopeAfterArrow) statFormatterState(subStatSeq.firstStatOpt)(subStatState).currentIndentLevelInstruction else CompactEnsuringGap formatResult = formatResult.before(firstToken, instruction) } - formatResult ++= format(subStatSeq)(subStatState) + val subStatStateAfterArrow = if(hasNewScopeAfterArrow) newFormatterState.indent else subStatState + formatResult ++= format(subStatSeq)(subStatStateAfterArrow) case _ ⇒ val instruction = statSeq.selfReferenceOpt match { case Some((selfReference, arrow)) if !hiddenPredecessors(selfReference.firstToken).containsNewline ⇒ diff --git a/scalariform/src/test/scala/scalariform/formatter/MiscExpressionFormatterTest.scala b/scalariform/src/test/scala/scalariform/formatter/MiscExpressionFormatterTest.scala index bb85f5a3..11e56cd9 100644 --- a/scalariform/src/test/scala/scalariform/formatter/MiscExpressionFormatterTest.scala +++ b/scalariform/src/test/scala/scalariform/formatter/MiscExpressionFormatterTest.scala @@ -771,6 +771,17 @@ class MiscExpressionFormatterTest extends AbstractExpressionFormatterTest { | b => c |}""" + """|a map { + |q => { + |2 * q + |} + |}""" ==> + """|a map { + | q => { + | 2 * q + | } + |}""" + "f()[Foo]" ==> "f()[Foo]" "a [ b . C ] [ d . E ] [ f . G ] " ==> "a[b.C][d.E][f.G]" From 4c8d016b9e93c53bbb64be7208f0a6f9314d505e Mon Sep 17 00:00:00 2001 From: Gerard Basler Date: Mon, 4 Feb 2013 09:04:40 +0100 Subject: [PATCH 12/15] Fix formatting for new scope after arrow. --- .../scala/scalariform/formatter/ExprFormatter.scala | 2 +- .../formatter/MiscExpressionFormatterTest.scala | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) mode change 100644 => 100755 scalariform/src/test/scala/scalariform/formatter/MiscExpressionFormatterTest.scala diff --git a/scalariform/src/main/scala/scalariform/formatter/ExprFormatter.scala b/scalariform/src/main/scala/scalariform/formatter/ExprFormatter.scala index 403c92b6..da4e7bfd 100755 --- a/scalariform/src/main/scala/scalariform/formatter/ExprFormatter.scala +++ b/scalariform/src/main/scala/scalariform/formatter/ExprFormatter.scala @@ -644,7 +644,7 @@ trait ExprFormatter { self: HasFormattingPreferences with AnnotationFormatter wi } for (firstToken ← subStatSeq.firstTokenOption) { val instruction = - if (hiddenPredecessors(firstToken).containsNewline || containsNewline(subStatSeq) && !hasNewScopeAfterArrow) + if (!hasNewScopeAfterArrow && (hiddenPredecessors(firstToken).containsNewline || containsNewline(subStatSeq))) statFormatterState(subStatSeq.firstStatOpt)(subStatState).currentIndentLevelInstruction else CompactEnsuringGap diff --git a/scalariform/src/test/scala/scalariform/formatter/MiscExpressionFormatterTest.scala b/scalariform/src/test/scala/scalariform/formatter/MiscExpressionFormatterTest.scala old mode 100644 new mode 100755 index 11e56cd9..8b3427ad --- a/scalariform/src/test/scala/scalariform/formatter/MiscExpressionFormatterTest.scala +++ b/scalariform/src/test/scala/scalariform/formatter/MiscExpressionFormatterTest.scala @@ -782,6 +782,18 @@ class MiscExpressionFormatterTest extends AbstractExpressionFormatterTest { | } |}""" + """|a map { + |q => + |{ + |2 * q + |} + |}""" ==> + """|a map { + | q => { + | 2 * q + | } + |}""" + "f()[Foo]" ==> "f()[Foo]" "a [ b . C ] [ d . E ] [ f . G ] " ==> "a[b.C][d.E][f.G]" From e79a1f35dc8e2220bee735804a53e1d47ad41a13 Mon Sep 17 00:00:00 2001 From: Gerard Basler Date: Fri, 15 Feb 2013 10:30:09 +0100 Subject: [PATCH 13/15] New option to reformat chained packages. --- README.rst | 16 +++++++++ .../scalariform/formatter/ExprFormatter.scala | 35 +++++++++++++++++-- .../formatter/ScalaFormatter.scala | 7 +++- .../preferences/PreferenceDescriptor.scala | 15 +++++++- .../formatter/PackageFormatterTest.scala | 23 ++++++++++++ 5 files changed, 91 insertions(+), 5 deletions(-) mode change 100644 => 100755 README.rst mode change 100644 => 100755 scalariform/src/main/scala/scalariform/formatter/ScalaFormatter.scala mode change 100644 => 100755 scalariform/src/test/scala/scalariform/formatter/PackageFormatterTest.scala diff --git a/README.rst b/README.rst old mode 100644 new mode 100755 index b4f91299..0246c4cd --- a/README.rst +++ b/README.rst @@ -499,6 +499,22 @@ If ``false``,:: case elem@Multi(values@_*) => +chainedPackageClauses +~~~~~~~~~~~~~~~~~~~~~ + +Default: ``false`` + +Example:: +``` + package com.company.analytics.math.curves.interpolators +``` + +Will be reformatted to:: +``` + package com.company.analytics.math + package curves + package interpolators +``` Scala Style Guide ~~~~~~~~~~~~~~~~~ diff --git a/scalariform/src/main/scala/scalariform/formatter/ExprFormatter.scala b/scalariform/src/main/scala/scalariform/formatter/ExprFormatter.scala index da4e7bfd..af8e3ebf 100755 --- a/scalariform/src/main/scala/scalariform/formatter/ExprFormatter.scala +++ b/scalariform/src/main/scala/scalariform/formatter/ExprFormatter.scala @@ -690,7 +690,7 @@ trait ExprFormatter { self: HasFormattingPreferences with AnnotationFormatter wi } for (stat ← firstStatOpt) - formatResult ++= format(stat)(firstStatFormatterState) + formatResult ++= format(stat, true)(firstStatFormatterState) for ((semi, otherStatOption) ← otherStats) { @@ -709,7 +709,7 @@ trait ExprFormatter { self: HasFormattingPreferences with AnnotationFormatter wi CompactEnsuringGap formatResult = formatResult.before(firstToken, instruction) } - formatResult ++= format(otherStat)(otherStatFormatterState) + formatResult ++= format(otherStat, false)(otherStatFormatterState) } } @@ -717,15 +717,44 @@ trait ExprFormatter { self: HasFormattingPreferences with AnnotationFormatter wi formatResult } - private def format(stat: Stat)(implicit formatterState: FormatterState): FormatResult = + private def format(stat: Stat, firstStat: Boolean)(implicit formatterState: FormatterState): FormatResult = stat match { case expr: Expr ⇒ format(expr) case fullDefOrDcl: FullDefOrDcl ⇒ format(fullDefOrDcl) case import_ : ImportClause ⇒ format(import_) case packageBlock: PackageBlock ⇒ format(packageBlock) + case packageStat: PackageStat ⇒ format(packageStat, firstStat) case _ ⇒ NoFormatResult // TODO } + def format(packageStat: PackageStat, firstPackage: Boolean)(implicit formatterState: FormatterState): FormatResult = { + val PackageStat(packageToken: Token, name: CallExpr) = packageStat + + val packageDepth = if(firstPackage) formattingPreferences(ChainedPackageClauses.PackageDepth) else 1 + + def dotsForPackageNames(name: CallExpr): List[Token] = { + name.exprDotOpt match { + case Some((List(c@CallExpr(_, id, _, _, _)), dot)) => + dot :: dotsForPackageNames(c) + case _ => + Nil + } + } + + val dotsBetweenPackageNames = dotsForPackageNames(name) + + val lineBreaksAfter = dotsBetweenPackageNames.reverse.drop(packageDepth-1) + + var formatResult: FormatResult = NoFormatResult + for { + token <- lineBreaksAfter + } { + formatResult ++= FormatResult(Map(token -> EnsureNewlineAndIndent(0, Some(packageToken))), Map(), Map()) + } + + formatResult + } + def format(packageBlock: PackageBlock)(implicit formatterState: FormatterState): FormatResult = { val PackageBlock(packageToken: Token, name: CallExpr, newlineOpt: Option[Token], lbrace: Token, topStats: StatSeq, rbrace: Token) = packageBlock diff --git a/scalariform/src/main/scala/scalariform/formatter/ScalaFormatter.scala b/scalariform/src/main/scala/scalariform/formatter/ScalaFormatter.scala old mode 100644 new mode 100755 index ed408a05..e6c1792e --- a/scalariform/src/main/scala/scalariform/formatter/ScalaFormatter.scala +++ b/scalariform/src/main/scala/scalariform/formatter/ScalaFormatter.scala @@ -221,7 +221,12 @@ abstract class ScalaFormatter extends HasFormattingPreferences with TypeFormatte val replacement = builder.substring(startPos) positionHintOption match { case Some(positionHint) if hiddenTokens.isEmpty ⇒ - Some(TextEdit(positionHint, length = 0, replacement = replacement)) + instruction match { + case EnsureNewlineAndIndent(indentLevel, Some(Token(PACKAGE, _, _, _))) => + Some(TextEdit(positionHint, length = 1, replacement = replacement + "package ")) + case _ => + Some(TextEdit(positionHint, length = 0, replacement = replacement)) + } case _ ⇒ for { firstToken ← hiddenTokens.firstTokenOption diff --git a/scalariform/src/main/scala/scalariform/formatter/preferences/PreferenceDescriptor.scala b/scalariform/src/main/scala/scalariform/formatter/preferences/PreferenceDescriptor.scala index cc2cd1aa..ed73714d 100755 --- a/scalariform/src/main/scala/scalariform/formatter/preferences/PreferenceDescriptor.scala +++ b/scalariform/src/main/scala/scalariform/formatter/preferences/PreferenceDescriptor.scala @@ -64,7 +64,7 @@ object AllPreferences { PreserveSpaceBeforeArguments, AlignParameters, DoubleIndentClassDeclaration, FormatXml, IndentPackageBlocks, AlignSingleLineCaseStatements, AlignSingleLineCaseStatements.MaxArrowIndent, AlignSingleLineCaseStatements.AlignMultiLineCaseStatements, IndentLocalDefs, PreserveDanglingCloseParenthesis, SpaceInsideParentheses, SpaceInsideBrackets, SpacesWithinPatternBinders, MultilineScaladocCommentsStartOnFirstLine, IndentWithTabs, - CompactControlReadability, PlaceScaladocAsterisksBeneathSecondAsterisk, NoSpacesAroundMultiImports) + CompactControlReadability, PlaceScaladocAsterisksBeneathSecondAsterisk, NoSpacesAroundMultiImports, ChainedPackageClauses, ChainedPackageClauses.PackageDepth) val preferencesByKey: Map[String, PreferenceDescriptor[_]] = { var map: Map[String, PreferenceDescriptor[_]] = Map() @@ -215,3 +215,16 @@ case object NoSpacesAroundMultiImports extends BooleanPreferenceDescriptor { val description = "Don't place spaces around multi imports (Java-style)" val defaultValue = false } + +case object ChainedPackageClauses extends BooleanPreferenceDescriptor { + val key = "chainedPackageClauses" + val description = "Break up chained package clauses" + val defaultValue = false + + case object PackageDepth extends IntegerPreferenceDescriptor { + val key = "chainedPackageClauses.packageDepth" + val description = "Depth of package nesting" + val preferenceType = IntegerPreference(1, 100) + val defaultValue = 4 + } +} diff --git a/scalariform/src/test/scala/scalariform/formatter/PackageFormatterTest.scala b/scalariform/src/test/scala/scalariform/formatter/PackageFormatterTest.scala old mode 100644 new mode 100755 index 4634e8d5..0ef4a5c3 --- a/scalariform/src/test/scala/scalariform/formatter/PackageFormatterTest.scala +++ b/scalariform/src/test/scala/scalariform/formatter/PackageFormatterTest.scala @@ -63,5 +63,28 @@ class PackageFormatterTest extends AbstractFormatterTest { } + """package a.b.c.d.e.f + |""" ==> + """package a.b.c.d + |package e + |package f + |""" + + """package com.company.analytics.math.curves.interpolators + |""" ==> + """package com.company.analytics.math + |package curves + |package interpolators + |""" + + """package a.b.c.d.e.f + |package g.h + |""" ==> + """package a.b.c.d + |package e + |package f + |package g + |package h + |""" } From b91a0be57a3f4b2528da918f5e5d190fcc1bbff4 Mon Sep 17 00:00:00 2001 From: Gerard Basler Date: Fri, 15 Feb 2013 11:06:08 +0100 Subject: [PATCH 14/15] Fix missing chained package format option. --- .../scalariform/formatter/ExprFormatter.scala | 35 ++++++++++--------- .../formatter/PackageFormatterTest.scala | 6 +++- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/scalariform/src/main/scala/scalariform/formatter/ExprFormatter.scala b/scalariform/src/main/scala/scalariform/formatter/ExprFormatter.scala index af8e3ebf..ef59659c 100755 --- a/scalariform/src/main/scala/scalariform/formatter/ExprFormatter.scala +++ b/scalariform/src/main/scala/scalariform/formatter/ExprFormatter.scala @@ -728,28 +728,31 @@ trait ExprFormatter { self: HasFormattingPreferences with AnnotationFormatter wi } def format(packageStat: PackageStat, firstPackage: Boolean)(implicit formatterState: FormatterState): FormatResult = { - val PackageStat(packageToken: Token, name: CallExpr) = packageStat + var formatResult: FormatResult = NoFormatResult + + if (formattingPreferences(ChainedPackageClauses)) { + val PackageStat(packageToken: Token, name: CallExpr) = packageStat - val packageDepth = if(firstPackage) formattingPreferences(ChainedPackageClauses.PackageDepth) else 1 + val packageDepth = if(firstPackage) formattingPreferences(ChainedPackageClauses.PackageDepth) else 1 - def dotsForPackageNames(name: CallExpr): List[Token] = { - name.exprDotOpt match { - case Some((List(c@CallExpr(_, id, _, _, _)), dot)) => - dot :: dotsForPackageNames(c) - case _ => - Nil + def dotsForPackageNames(name: CallExpr): List[Token] = { + name.exprDotOpt match { + case Some((List(c@CallExpr(_, id, _, _, _)), dot)) => + dot :: dotsForPackageNames(c) + case _ => + Nil + } } - } - val dotsBetweenPackageNames = dotsForPackageNames(name) + val dotsBetweenPackageNames = dotsForPackageNames(name) - val lineBreaksAfter = dotsBetweenPackageNames.reverse.drop(packageDepth-1) + val lineBreaksAfter = dotsBetweenPackageNames.reverse.drop(packageDepth-1) - var formatResult: FormatResult = NoFormatResult - for { - token <- lineBreaksAfter - } { - formatResult ++= FormatResult(Map(token -> EnsureNewlineAndIndent(0, Some(packageToken))), Map(), Map()) + for { + token <- lineBreaksAfter + } { + formatResult ++= FormatResult(Map(token -> EnsureNewlineAndIndent(0, Some(packageToken))), Map(), Map()) + } } formatResult diff --git a/scalariform/src/test/scala/scalariform/formatter/PackageFormatterTest.scala b/scalariform/src/test/scala/scalariform/formatter/PackageFormatterTest.scala index 0ef4a5c3..6301657d 100755 --- a/scalariform/src/test/scala/scalariform/formatter/PackageFormatterTest.scala +++ b/scalariform/src/test/scala/scalariform/formatter/PackageFormatterTest.scala @@ -63,6 +63,10 @@ class PackageFormatterTest extends AbstractFormatterTest { } + { + + implicit val formattingPreferences = FormattingPreferences.setPreference(ChainedPackageClauses, true) + """package a.b.c.d.e.f |""" ==> """package a.b.c.d @@ -86,5 +90,5 @@ class PackageFormatterTest extends AbstractFormatterTest { |package g |package h |""" - + } } From 2859652d5fddaa9cf3209c0acf6a15268a523104 Mon Sep 17 00:00:00 2001 From: Gerard Basler Date: Thu, 21 Feb 2013 23:39:24 +0100 Subject: [PATCH 15/15] Fix multi line case clauses formatting. --- .../formatter/CaseClauseFormatter.scala | 4 +-- .../formatter/CaseClausesFormatterTest.scala | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala b/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala index ece81fc1..fedb2ba8 100755 --- a/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala +++ b/scalariform/src/main/scala/scalariform/formatter/CaseClauseFormatter.scala @@ -91,9 +91,7 @@ trait CaseClauseFormatter { self: HasFormattingPreferences with ExprFormatter wi Right(caseClause) :: otherClausesGrouped else { val arrowAdjust = (if (formattingPreferences(RewriteArrowSymbols)) 1 else casePattern.arrow.length) + 1 - val casePatternLengthConsideringNewLines = { - formattedCasePattern.split('\n').map(_.length).max - } + val casePatternLengthConsideringNewLines = formattedCasePattern.split('\n').last.length val casePatternLength = casePatternLengthConsideringNewLines - arrowAdjust otherClausesGrouped match { case Left(consecutiveSingleLineCaseClauses) :: otherGroups ⇒ diff --git a/scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala b/scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala index 1eaeb60f..06b20136 100755 --- a/scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala +++ b/scalariform/src/test/scala/scalariform/formatter/CaseClausesFormatterTest.scala @@ -494,4 +494,30 @@ class CaseClausesFormatterTest extends AbstractExpressionFormatterTest { | case B => (s: Int) => 2 |}""" } + + { + implicit val formattingPreferences = FormattingPreferences.setPreference(AlignSingleLineCaseStatements, true) + .setPreference(AlignSingleLineCaseStatements.AlignMultiLineCaseStatements, true) + .setPreference(AlignSingleLineCaseStatements.MaxArrowIndent, 160) + .setPreference(AlignSingleLineCaseStatements.GroupByNewLine, true) + .setPreference(SpacesWithinPatternBinders, false) + + """|pairs.flatMap { + | case (p1@(t1, MandatoryGridPoint(true) | ExtremalGridPoint), + | (t2, MandatoryGridPoint(true) | ExtremalGridPoint)) => + | val fillPointTime = (t1 + t2) / 2 + | val fillPoint = (fillPointTime, FillingGridPoint) + | Seq(p1, fillPoint) + | case (p1, p2) => Seq(p1) + |}""" ==> + """|pairs.flatMap { + | case (p1@(t1, MandatoryGridPoint(true) | ExtremalGridPoint), + | (t2, MandatoryGridPoint(true) | ExtremalGridPoint)) => + | val fillPointTime = (t1 + t2) / 2 + | val fillPoint = (fillPointTime, FillingGridPoint) + | Seq(p1, fillPoint) + | case (p1, p2) => Seq(p1) + |}""" + } + }