Skip to content

Commit 8dbd8d4

Browse files
authored
Merge pull request #7235 from dotty-staging/generalize-indent
Make indentation significant in old-style control syntax
2 parents 3d7bb5b + 5331caf commit 8dbd8d4

File tree

18 files changed

+223
-65
lines changed

18 files changed

+223
-65
lines changed

compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2588,7 +2588,8 @@ class JSCodeGen()(implicit ctx: Context) {
25882588
sym.info.paramNamess.flatten.zip(sym.info.paramInfoss.flatten)
25892589

25902590
val wereRepeated = ctx.atPhase(ctx.elimRepeatedPhase) {
2591-
val list = for ((name, tpe) <- paramNamesAndTypes)
2591+
val list =
2592+
for ((name, tpe) <- paramNamesAndTypes)
25922593
yield (name -> tpe.isRepeatedParam)
25932594
list.toMap
25942595
}

compiler/src/dotty/tools/dotc/config/ScalaSettings.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class ScalaSettings extends Settings.SettingGroup {
5252
val oldSyntax: Setting[Boolean] = BooleanSetting("-old-syntax", "Require `(...)` around conditions")
5353
val indent: Setting[Boolean] = BooleanSetting("-indent", "allow significant indentation")
5454
val noindent: Setting[Boolean] = BooleanSetting("-noindent", "require classical {...} syntax, indentation is not significant")
55+
val YindentColons: Setting[Boolean] = BooleanSetting("-Yindent-colons", "allow colons at ends-of-lines to start indentation blocks")
5556

5657
/** Decompiler settings */
5758
val printTasty: Setting[Boolean] = BooleanSetting("-print-tasty", "Prints the raw tasty.") withAbbreviation "--print-tasty"

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@ object Parsers {
735735
}
736736
})
737737
canRewrite &= (in.isAfterLineEnd || statCtdTokens.contains(in.token)) // test (5)
738-
if (canRewrite) {
738+
if (canRewrite && (!colonRequired || in.colonSyntax)) {
739739
val openingPatchStr =
740740
if (!colonRequired) ""
741741
else if (testChar(startOpening - 1, Chars.isOperatorPart(_))) " :"
@@ -1218,7 +1218,7 @@ object Parsers {
12181218
}
12191219

12201220
def possibleTemplateStart(): Unit = {
1221-
in.observeIndented()
1221+
in.observeIndented(noIndentTemplateTokens, nme.derives)
12221222
newLineOptWhenFollowedBy(LBRACE)
12231223
}
12241224

@@ -1636,8 +1636,11 @@ object Parsers {
16361636
if (rewriteToOldSyntax()) revertToParens(t)
16371637
in.nextToken()
16381638
}
1639-
else if (rewriteToNewSyntax(t.span))
1640-
dropParensOrBraces(t.span.start, s"${tokenString(altToken)}")
1639+
else {
1640+
in.observeIndented(noIndentAfterConditionTokens)
1641+
if (rewriteToNewSyntax(t.span))
1642+
dropParensOrBraces(t.span.start, s"${tokenString(altToken)}")
1643+
}
16411644
t
16421645
}
16431646
else {
@@ -2296,6 +2299,7 @@ object Parsers {
22962299
dropParensOrBraces(start, if (in.token == YIELD || in.token == DO) "" else "do")
22972300
}
22982301
}
2302+
in.observeIndented(noIndentAfterEnumeratorTokens)
22992303
res
23002304
}
23012305
else {
@@ -3539,15 +3543,14 @@ object Parsers {
35393543

35403544
/** TemplateOpt = [Template]
35413545
*/
3542-
def templateOpt(constr: DefDef): Template =
3543-
possibleBracesStart()
3546+
def templateOpt(constr: DefDef): Template = {
3547+
possibleTemplateStart()
35443548
if (in.token == EXTENDS || isIdent(nme.derives))
35453549
template(constr)
3546-
else {
3547-
possibleTemplateStart()
3550+
else
35483551
if (in.isNestedStart) template(constr)
35493552
else Template(constr, Nil, Nil, EmptyValDef, Nil)
3550-
}
3553+
}
35513554

35523555
/** TemplateBody ::= [nl] `{' TemplateStatSeq `}'
35533556
*/

compiler/src/dotty/tools/dotc/parsing/Scanners.scala

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -152,12 +152,15 @@ object Scanners {
152152
val rewriteNoIndent = ctx.settings.noindent.value && rewrite
153153

154154
val noindentSyntax =
155-
ctx.settings.noindent.value ||
156-
ctx.settings.oldSyntax.value ||
157-
isScala2Mode
155+
ctx.settings.noindent.value
156+
|| ctx.settings.oldSyntax.value
157+
|| isScala2Mode
158158
val indentSyntax =
159-
(if (Config.defaultIndent) !noindentSyntax else ctx.settings.indent.value) ||
160-
rewriteNoIndent
159+
(if (Config.defaultIndent) !noindentSyntax else ctx.settings.indent.value)
160+
|| rewriteNoIndent
161+
val colonSyntax =
162+
ctx.settings.YindentColons.value
163+
|| rewriteNoIndent
161164

162165
if (rewrite) {
163166
val s = ctx.settings
@@ -532,18 +535,21 @@ object Scanners {
532535
}
533536
}
534537

535-
def observeIndented(): Unit =
538+
def observeIndented(unless: BitSet, unlessSoftKW: TermName = EmptyTermName): Unit =
536539
if (indentSyntax && isAfterLineEnd && token != INDENT) {
537540
val newLineInserted = token == NEWLINE || token == NEWLINES
538541
val nextOffset = if (newLineInserted) next.offset else offset
542+
val nextToken = if (newLineInserted) next.token else token
539543
val nextWidth = indentWidth(nextOffset)
540544
val lastWidth = currentRegion match {
541545
case r: Indented => r.width
542546
case r: InBraces => r.width
543547
case _ => nextWidth
544548
}
545549

546-
if (lastWidth < nextWidth) {
550+
if (lastWidth < nextWidth
551+
&& !unless.contains(nextToken)
552+
&& (unlessSoftKW.isEmpty || token != IDENTIFIER || name != unlessSoftKW)) {
547553
currentRegion = Indented(nextWidth, Set(), COLONEOL, currentRegion)
548554
if (!newLineInserted) next.copyFrom(this)
549555
offset = nextOffset
@@ -590,7 +596,7 @@ object Scanners {
590596
lookahead()
591597
val atEOL = isAfterLineEnd
592598
reset()
593-
if (atEOL) token = COLONEOL
599+
if (colonSyntax && atEOL) token = COLONEOL
594600
case EOF | RBRACE =>
595601
currentRegion match {
596602
case r: Indented if !r.isOutermost =>

compiler/src/dotty/tools/dotc/parsing/Tokens.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,10 @@ object Tokens extends TokensCommon {
281281
*/
282282
final val startParamOrGivenTypeTokens: BitSet = startParamTokens | BitSet(GIVEN, ERASED)
283283

284+
final val noIndentTemplateTokens = BitSet(EXTENDS)
285+
final val noIndentAfterConditionTokens = BitSet(THEN, DO)
286+
final val noIndentAfterEnumeratorTokens = BitSet(YIELD, DO)
287+
284288
final val scala3keywords = BitSet(ENUM, ERASED, GIVEN, IMPLIED)
285289

286290
final val softModifierNames = Set(nme.inline, nme.opaque)

compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2174,7 +2174,8 @@ object messages {
21742174
def symLocation(sym: Symbol) = {
21752175
val lineDesc =
21762176
if (sym.span.exists && sym.span != sym.owner.span)
2177-
s" at line ${sym.sourcePos.line + 1}" else ""
2177+
s" at line ${sym.sourcePos.line + 1}"
2178+
else ""
21782179
i"in ${sym.owner}${lineDesc}"
21792180
}
21802181
val clashDescription =

compiler/src/dotty/tools/dotc/transform/Mixin.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
254254

255255
def setters(mixin: ClassSymbol): List[Tree] =
256256
for (setter <- mixin.info.decls.filter(setr => setr.isSetter && !wasOneOf(setr, Deferred)))
257-
yield transformFollowing(DefDef(mkForwarderSym(setter.asTerm), unitLiteral.withSpan(cls.span)))
257+
yield transformFollowing(DefDef(mkForwarderSym(setter.asTerm), unitLiteral.withSpan(cls.span)))
258258

259259
def mixinForwarders(mixin: ClassSymbol): List[Tree] =
260260
for (meth <- mixin.info.decls.toList if needsMixinForwarder(meth))
@@ -263,7 +263,6 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase =>
263263
transformFollowing(polyDefDef(mkForwarderSym(meth.asTerm, Bridge), forwarderRhsFn(meth)))
264264
}
265265

266-
267266
cpy.Template(impl)(
268267
constr =
269268
if (cls.is(Trait)) cpy.DefDef(impl.constr)(vparamss = Nil :: Nil)

compiler/src/dotty/tools/dotc/typer/Applications.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -890,8 +890,8 @@ trait Applications extends Compatibility {
890890
case err: ErrorType => cpy.Apply(tree)(fun1, proto.unforcedTypedArgs).withType(err)
891891
case TryDynamicCallType => typedDynamicApply(tree, pt)
892892
case _ =>
893-
if originalProto.isDropped then fun1
894-
else if fun1.symbol == defn.Compiletime_summonFrom then
893+
if (originalProto.isDropped) fun1
894+
else if (fun1.symbol == defn.Compiletime_summonFrom)
895895
// Special handling of `summonFrom { ... }`.
896896
// We currently cannot use a macro for that since unlike other inline methods
897897
// summonFrom needs to expand lazily. For instance, in

compiler/src/dotty/tools/dotc/typer/Inliner.scala

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,7 +1252,8 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
12521252
|""".stripMargin
12531253
ctx.error(msg, inlinedFrom.sourcePos)
12541254
EmptyTree
1255-
} else {
1255+
}
1256+
else {
12561257
val evaluatedSplice = Splicer.splice(body, inlinedFrom.sourcePos, MacroClassLoader.fromContext)(ctx1)
12571258

12581259
val inlinedNormailizer = new TreeMap {
@@ -1270,10 +1271,10 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
12701271
/** Return the set of symbols that are refered at level -1 by the tree and defined in the current run.
12711272
* This corresponds to the symbols that will need to be interpreted.
12721273
*/
1273-
private def macroDependencies(tree: Tree)(implicit ctx: Context) = {
1274+
private def macroDependencies(tree: Tree)(implicit ctx: Context) =
12741275
new TreeAccumulator[Set[Symbol]] {
12751276
private[this] var level = -1
1276-
override def apply(syms: Set[Symbol], tree: tpd.Tree)(implicit ctx: Context): Set[Symbol] = {
1277+
override def apply(syms: Set[Symbol], tree: tpd.Tree)(implicit ctx: Context): Set[Symbol] =
12771278
if (level != -1) foldOver(syms, tree)
12781279
else tree match {
12791280
case tree: RefTree if level == -1 && tree.symbol.isDefinedInCurrentRun && !tree.symbol.isLocal =>
@@ -1289,8 +1290,6 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
12891290
case _ =>
12901291
foldOver(syms, tree)
12911292
}
1292-
}
12931293
}.apply(Set.empty, tree)
1294-
}
12951294
}
12961295

compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ trait QuotesAndSplices {
216216
super.transform(tree)
217217
case tdef: TypeDef if tdef.symbol.hasAnnotation(defn.InternalQuoted_patternBindHoleAnnot) =>
218218
transformTypeBindingTypeDef(tdef, typePatBuf)
219-
case tree @ AppliedTypeTree(tpt, args) =>
219+
case tree @ AppliedTypeTree(tpt, args) =>
220220
val args1: List[Tree] = args.zipWithConserve(tpt.tpe.typeParams.map(_.paramVariance)) { (arg, v) =>
221221
arg.tpe match {
222222
case _: TypeBounds => transform(arg)

0 commit comments

Comments
 (0)