Skip to content

Commit 2dd4271

Browse files
author
Daniel Trinh
committed
first attempt at getting relative PlaceAtColumn working
1 parent dacd43c commit 2dd4271

File tree

4 files changed

+356
-299
lines changed

4 files changed

+356
-299
lines changed

scalariform/src/main/scala/scalariform/formatter/ExprFormatter.scala

Lines changed: 73 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -837,41 +837,58 @@ trait ExprFormatter { self: HasFormattingPreferences with AnnotationFormatter wi
837837
val ParamClauses(initialNewlineOpt, paramClausesAndNewlines) = paramClauses
838838
var formatResult: FormatResult = NoFormatResult
839839
var currentFormatterState = formatterState
840+
var index = 0
840841
for ((paramClause, newlineOption) paramClausesAndNewlines) { // TODO: Newlines. // maybe already done in some cases by format(tmplDef)?
841-
842-
val (paramClauseFormatResult, newFormatterState) = formatParamClause(paramClause, doubleIndentParams)(currentFormatterState)
842+
val (paramClauseFormatResult, newFormatterState) = formatParamClause(paramClause, index, doubleIndentParams)(currentFormatterState)
843843
formatResult ++= paramClauseFormatResult
844844
currentFormatterState = newFormatterState
845+
index += 1
845846
}
846847
formatResult
847848
}
848849

849-
private def groupParams(paramClause: ParamClause)(implicit formatterState: FormatterState): List[Either[ConsecutiveSingleLineParams, Param]] = {
850+
private type EitherAlignableParam = Either[ConsecutiveSingleLineParams, Param]
851+
/**
852+
* Groups consecutive single line params in a [[scalariform.parser.ParamClause]] for alignment.
853+
* The head of the return value (and head of the params list in the returned ConsecutiveSingleLineParams is guaranteed
854+
* to be the very first parameter in the paramClause. The other parameters are not necessarily in the order they appear.
855+
* @param paramClause
856+
* @param formatterState
857+
* @return List of grouped params. Left stores a group of parameters that can be aligned together,
858+
* Right stores an unalignable param.
859+
*/
860+
private def groupParams(paramClause: ParamClause)(implicit formatterState: FormatterState): List[EitherAlignableParam] = {
850861
val ParamClause(_, _, firstParamOption, otherParams, _) = paramClause
851862

852-
val paramsList = firstParamOption ++ otherParams.map { case (comma, param) => param }
863+
val paramsList = otherParams.map { case (comma, param) => param }
853864

854-
var isFirstParam = true
865+
def appendParamToGroup(paramToAppend: Param,
866+
groupedParams: List[EitherAlignableParam],
867+
isFirstParam: Boolean): List[EitherAlignableParam] = {
868+
calculateParamSectionLengths(paramToAppend, isFirstParam) match {
855869

856-
paramsList.foldLeft(List[Either[ConsecutiveSingleLineParams, Param]]()) { (groupedParams, nextParam) =>
857-
val lengths = calculateParamSectionLengths(nextParam, isFirstParam) match {
858870
case Some(sectionLengths) =>
859871
groupedParams match {
860872
case Right(param) :: tail =>
861-
Left(ConsecutiveSingleLineParams(List(nextParam), sectionLengths, sectionLengths)) :: groupedParams
873+
Left(ConsecutiveSingleLineParams(List(paramToAppend), sectionLengths, sectionLengths)) :: groupedParams
862874
case Left(existingParams) :: tail =>
863-
Left(existingParams.prepend(nextParam, sectionLengths)) :: tail
875+
Left(existingParams.prepend(paramToAppend, sectionLengths)) :: tail
864876
case Nil =>
865-
Left(ConsecutiveSingleLineParams(List(nextParam), sectionLengths, sectionLengths)) :: Nil
877+
Left(ConsecutiveSingleLineParams(List(paramToAppend), sectionLengths, sectionLengths)) :: Nil
866878
}
867879
case None =>
868-
Right(nextParam) :: groupedParams
880+
Right(paramToAppend) :: groupedParams
869881
}
882+
}
870883

871-
if (isFirstParam) isFirstParam = false
872-
873-
lengths
884+
var paramsGroup = paramsList.foldLeft(List[EitherAlignableParam]()) { (groupedParams, nextParam) =>
885+
appendParamToGroup(nextParam, groupedParams, isFirstParam = false)
886+
}
887+
for (firstParam <- firstParamOption) {
888+
paramsGroup = appendParamToGroup(firstParam, paramsGroup, isFirstParam = true)
874889
}
890+
891+
paramsGroup
875892
}
876893

877894
private case class ConsecutiveSingleLineParams(params: List[Param], maxSectionLengths: ParamSectionLengths, thisSectionLengths: ParamSectionLengths) {
@@ -892,11 +909,6 @@ trait ExprFormatter { self: HasFormattingPreferences with AnnotationFormatter wi
892909
}
893910
}
894911

895-
/**
896-
*
897-
* @param param
898-
* @return Three Ints representing the length of the longest prefix, longest parameter name, and longest type.
899-
*/
900912
private def calculateParamSectionLengths(param: Param, first: Boolean)(implicit formatterState: FormatterState): Option[ParamSectionLengths] = {
901913
val Param(annotations, modifiers, valOrVarOpt, id, paramTypeOpt, defaultValueOpt) = param
902914

@@ -983,7 +995,7 @@ trait ExprFormatter { self: HasFormattingPreferences with AnnotationFormatter wi
983995
}
984996

985997
// TODO: figure out how to preserve relative indentation when first param is on first line,
986-
private def formatParamClause(paramClause: ParamClause, doubleIndentParams: Boolean = false)(implicit formatterState: FormatterState): (FormatResult, FormatterState) = {
998+
private def formatParamClause(paramClause: ParamClause, clauseIndex: Int, doubleIndentParams: Boolean = false)(implicit formatterState: FormatterState): (FormatResult, FormatterState) = {
987999
val ParamClause(lparen, implicitOption, firstParamOption, otherParams, rparen) = paramClause
9881000
val paramIndent = if (doubleIndentParams) 2 else 1
9891001
val relativeToken = paramClause.tokens(1) // TODO
@@ -993,30 +1005,58 @@ trait ExprFormatter { self: HasFormattingPreferences with AnnotationFormatter wi
9931005

9941006
if (formattingPreferences(PreserveDanglingCloseParenthesis))
9951007
formatResult = formatResult.before(rparen, formatterState.currentIndentLevelInstruction)
996-
else
1008+
else if (clauseIndex > 0)
1009+
// Only indent subsequent param clauses if dangling parenthesis are off.
1010+
// This is done because having dangling parenthesis is enough visual distiction
1011+
// to see where new param clauses start/end.
9971012
paramFormatterState = paramFormatterState.indent(paramIndent)
9981013

9991014
if (alignParameters) {
10001015
// Place implicit on it's own line
10011016
for (implicitToken <- paramClause.implicitOption) {
1002-
formatResult = formatResult.before(implicitToken, paramFormatterState.currentIndentLevelInstruction)
1017+
formatResult = formatResult.before(implicitToken, paramFormatterState.indent(paramIndent).currentIndentLevelInstruction)
10031018
}
10041019

10051020
val groupedParams = groupParams(paramClause)
10061021

1022+
var first = true
10071023
groupedParams.foreach {
10081024
case Left(ConsecutiveSingleLineParams(params, maxSectionLengths, thisSectionLengths)) =>
10091025
params.foreach { param =>
10101026
val firstToken = param.firstToken
10111027

1028+
if (first) {
1029+
paramFormatterState = formatterState.alignWithToken(relativeToken)
1030+
1031+
if (hiddenPredecessors(firstToken).containsNewline) {
1032+
formatResult = formatResult.before(firstToken, formatterState.indent(paramIndent).currentIndentLevelInstruction)
1033+
} else if (containsNewline(param) && alignParameters) {
1034+
paramFormatterState = formatterState.alignWithToken(relativeToken)
1035+
}
1036+
first = false
1037+
} else {
1038+
if (hiddenPredecessors(firstToken).containsNewline) {
1039+
formatterState.indent(paramIndent)
1040+
formatResult = formatResult.before(firstToken, paramFormatterState.currentIndentLevelInstruction)
1041+
}
1042+
}
1043+
10121044
// Indent Prefix Or Id
1013-
formatResult = formatResult.before(firstToken, paramFormatterState.currentIndentLevelInstruction)
1045+
// formatResult = formatResult.before(firstToken, paramFormatterState.indent(paramIndent).currentIndentLevelInstruction)
1046+
1047+
// paramFormatterState = paramFormatterState.alignWithToken(relativeToken)
10141048

10151049
// Indent Type
10161050
for ((colon, typeAst) <- param.paramTypeOpt) {
10171051
val typeSpaces = maxSectionLengths.prefixAndIdLength + 1
1018-
1019-
formatResult = formatResult.before(typeAst.firstToken, PlaceAtColumn(paramFormatterState.indentLevel, typeSpaces))
1052+
formatResult = formatResult.before(
1053+
typeAst.firstToken,
1054+
PlaceAtColumn(
1055+
0,
1056+
typeSpaces,
1057+
paramFormatterState.indentRelativeToTokenOption
1058+
)
1059+
)
10201060
}
10211061

10221062
// Indent Default
@@ -1025,7 +1065,14 @@ trait ExprFormatter { self: HasFormattingPreferences with AnnotationFormatter wi
10251065
maxSectionLengths.prefixAndIdLength +
10261066
maxSectionLengths.typeLength + 2
10271067
}
1028-
formatResult = formatResult.before(equal, PlaceAtColumn(paramFormatterState.indentLevel, defaultSpaces))
1068+
formatResult = formatResult.before(
1069+
equal,
1070+
PlaceAtColumn(
1071+
0,
1072+
defaultSpaces,
1073+
paramFormatterState.indentRelativeToTokenOption
1074+
)
1075+
)
10291076
}
10301077
formatResult ++= format(param)(paramFormatterState)
10311078
}
@@ -1048,12 +1095,6 @@ trait ExprFormatter { self: HasFormattingPreferences with AnnotationFormatter wi
10481095
formatResult = formatResult.before(firstToken, formatterState.indent(paramIndent).currentIndentLevelInstruction)
10491096
}
10501097

1051-
// Only indent subsequent param clauses if dangling parenthesis are off.
1052-
// This is done because having dangling parenthesis is enough visual distiction
1053-
// to see where new param clauses start/end.
1054-
if (!formattingPreferences(PreserveDanglingCloseParenthesis))
1055-
paramFormatterState = formatterState.indent(paramIndent)
1056-
10571098
formatResult ++= format(param)(paramFormatterState)
10581099
}
10591100

scalariform/src/main/scala/scalariform/formatter/FormatResult.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,4 @@ case object CompactPreservingGap extends IntertokenFormatInstruction
6363
case class EnsureNewlineAndIndent(indentLevel: Int, relativeTo: Option[Token] = None) extends IntertokenFormatInstruction
6464

6565
/** Places the token at spaces number of spaces after the indent level, padding with spaces if necessary */
66-
case class PlaceAtColumn(indentLevel: Int, spaces: Int) extends IntertokenFormatInstruction
66+
case class PlaceAtColumn(indentLevel: Int, spaces: Int, relativeTo: Option[Token] = None) extends IntertokenFormatInstruction

scalariform/src/main/scala/scalariform/formatter/ScalaFormatter.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,12 @@ abstract class ScalaFormatter extends HasFormattingPreferences with TypeFormatte
162162
builder.append(" ")
163163
else
164164
writeIntertokenCompact()
165-
case PlaceAtColumn(indentLevel, spaces)
165+
case PlaceAtColumn(indentLevel, spaces, relativeTo)
166166
require(!formattingPreferences(IndentWithTabs))
167167
writeIntertokenCompact()
168+
val relativeIndent = relativeTo flatMap tokenIndentMap.get getOrElse 0
168169
val indentLength = Spaces(formattingPreferences(IndentSpaces)).length(indentLevel)
169-
builder.append(" " * (indentLength + spaces - builder.currentColumn))
170+
builder.append(" " * (indentLength + relativeIndent + spaces - builder.currentColumn))
170171
case EnsureNewlineAndIndent(indentLevel, relativeTo)
171172
require(!(formattingPreferences(IndentWithTabs) && relativeTo.isDefined))
172173
val baseIndentOption = relativeTo flatMap tokenIndentMap.get

0 commit comments

Comments
 (0)