From a04b6d1c58c059a3cde5ff89e5257944be53c2b7 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 16 Sep 2019 21:22:51 +0200 Subject: [PATCH 1/8] Make indentation significant in old-style control syntax Indentation was significant only after new-style if-then, while-do, for-yield, for-do. This was prone to cause gotchas. We now treat indentation as significant also if the conditions or enumerators of these constructs use parens or braces. --- .../dotty/tools/dotc/parsing/Parsers.scala | 7 ++++-- tests/pos/indent4.scala | 24 +++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 tests/pos/indent4.scala diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index e10232327085..3e8b0729655c 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1636,8 +1636,10 @@ object Parsers { if (rewriteToOldSyntax()) revertToParens(t) in.nextToken() } - else if (rewriteToNewSyntax(t.span)) - dropParensOrBraces(t.span.start, s"${tokenString(altToken)}") + else + in.observeIndented() + if (rewriteToNewSyntax(t.span)) + dropParensOrBraces(t.span.start, s"${tokenString(altToken)}") t } else { @@ -2296,6 +2298,7 @@ object Parsers { dropParensOrBraces(start, if (in.token == YIELD || in.token == DO) "" else "do") } } + in.observeIndented() res } else { diff --git a/tests/pos/indent4.scala b/tests/pos/indent4.scala new file mode 100644 index 000000000000..50eef34ff3e7 --- /dev/null +++ b/tests/pos/indent4.scala @@ -0,0 +1,24 @@ +object testindent + + if (true) + val x = 1 + println(x) + + while (false) + val x = 1 + println(x) + + for (x <- List(1, 2, 3)) + val y = x + println(y) + + for { x <- List(1, 2, 3) } + val y = x + println(y) + + for { + x <- List(1, 2, 3) + } + val y = x + println(y) + From 05fb7060969d587a67175a664301d5ce5551e941 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 16 Sep 2019 22:14:28 +0200 Subject: [PATCH 2/8] Allow misindented continuation keywords Also: align indentation in some code --- compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala | 3 ++- compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 7 +++++-- .../dotty/tools/dotc/reporting/diagnostic/messages.scala | 3 ++- compiler/src/dotty/tools/dotc/transform/Mixin.scala | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala index 8b3a0b7a550f..55e2473bc405 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala @@ -2588,7 +2588,8 @@ class JSCodeGen()(implicit ctx: Context) { sym.info.paramNamess.flatten.zip(sym.info.paramInfoss.flatten) val wereRepeated = ctx.atPhase(ctx.elimRepeatedPhase) { - val list = for ((name, tpe) <- paramNamesAndTypes) + val list = + for ((name, tpe) <- paramNamesAndTypes) yield (name -> tpe.isRepeatedParam) list.toMap } diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 3e8b0729655c..b4f0400f7fc1 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1234,6 +1234,9 @@ object Parsers { case _ => op } + def observeIndentedUnlessFollowedBy(followers: BitSet): Unit = + if !followers.contains(in.token) then in.observeIndented() + /* ------------- TYPES ------------------------------------------------------ */ /** Same as [[typ]], but if this results in a wildcard it emits a syntax error and @@ -1637,7 +1640,7 @@ object Parsers { in.nextToken() } else - in.observeIndented() + observeIndentedUnlessFollowedBy(BitSet(THEN, DO)) if (rewriteToNewSyntax(t.span)) dropParensOrBraces(t.span.start, s"${tokenString(altToken)}") t @@ -2298,7 +2301,7 @@ object Parsers { dropParensOrBraces(start, if (in.token == YIELD || in.token == DO) "" else "do") } } - in.observeIndented() + observeIndentedUnlessFollowedBy(BitSet(YIELD, DO)) res } else { diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index bd3549012860..1e75b2106244 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -2174,7 +2174,8 @@ object messages { def symLocation(sym: Symbol) = { val lineDesc = if (sym.span.exists && sym.span != sym.owner.span) - s" at line ${sym.sourcePos.line + 1}" else "" + s" at line ${sym.sourcePos.line + 1}" + else "" i"in ${sym.owner}${lineDesc}" } val clashDescription = diff --git a/compiler/src/dotty/tools/dotc/transform/Mixin.scala b/compiler/src/dotty/tools/dotc/transform/Mixin.scala index 2dd7af23f804..96d92caf4ffc 100644 --- a/compiler/src/dotty/tools/dotc/transform/Mixin.scala +++ b/compiler/src/dotty/tools/dotc/transform/Mixin.scala @@ -254,7 +254,7 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase => def setters(mixin: ClassSymbol): List[Tree] = for (setter <- mixin.info.decls.filter(setr => setr.isSetter && !wasOneOf(setr, Deferred))) - yield transformFollowing(DefDef(mkForwarderSym(setter.asTerm), unitLiteral.withSpan(cls.span))) + yield transformFollowing(DefDef(mkForwarderSym(setter.asTerm), unitLiteral.withSpan(cls.span))) def mixinForwarders(mixin: ClassSymbol): List[Tree] = for (meth <- mixin.info.decls.toList if needsMixinForwarder(meth)) From f9ba2fd8e13e4f178edaf4cd1e2bc829c48a2002 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 17 Sep 2019 09:41:02 +0200 Subject: [PATCH 3/8] Introduce option to treat colon at eol as indentation start A `:` at the end of a line starting an indentation region is now allowed only if option `-Yindent-colon` is set. Rewriting to colons is also subject to that setting. --- .../dotty/tools/dotc/config/ScalaSettings.scala | 1 + .../src/dotty/tools/dotc/parsing/Parsers.scala | 1 + .../src/dotty/tools/dotc/parsing/Scanners.scala | 15 +++++++++------ .../src/dotty/tools/dotc/transform/Mixin.scala | 1 - 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 0aecf0920973..b0582dd855db 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -52,6 +52,7 @@ class ScalaSettings extends Settings.SettingGroup { val oldSyntax: Setting[Boolean] = BooleanSetting("-old-syntax", "Require `(...)` around conditions") val indent: Setting[Boolean] = BooleanSetting("-indent", "allow significant indentation") val noindent: Setting[Boolean] = BooleanSetting("-noindent", "require classical {...} syntax, indentation is not significant") + val YindentColons: Setting[Boolean] = BooleanSetting("-Yindent-colons", "allow colons at ends-of-lines to start indentation blocks") /** Decompiler settings */ val printTasty: Setting[Boolean] = BooleanSetting("-print-tasty", "Prints the raw tasty.") withAbbreviation "--print-tasty" diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index b4f0400f7fc1..a966f13f326d 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -717,6 +717,7 @@ object Parsers { */ def bracesToIndented[T](body: => T): T = { val colonRequired = possibleColonOffset == in.lastOffset + if colonRequired && !in.colonSyntax then return body val (startOpening, endOpening) = startingElimRegion(colonRequired) val isOutermost = in.currentRegion.isOutermost def allBraces(r: Region): Boolean = r match { diff --git a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala index 84ecf16878fa..73fae38b7248 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala @@ -152,12 +152,15 @@ object Scanners { val rewriteNoIndent = ctx.settings.noindent.value && rewrite val noindentSyntax = - ctx.settings.noindent.value || - ctx.settings.oldSyntax.value || - isScala2Mode + ctx.settings.noindent.value + || ctx.settings.oldSyntax.value + || isScala2Mode val indentSyntax = - (if (Config.defaultIndent) !noindentSyntax else ctx.settings.indent.value) || - rewriteNoIndent + (if (Config.defaultIndent) !noindentSyntax else ctx.settings.indent.value) + || rewriteNoIndent + val colonSyntax = + ctx.settings.YindentColons.value + || rewriteNoIndent if (rewrite) { val s = ctx.settings @@ -590,7 +593,7 @@ object Scanners { lookahead() val atEOL = isAfterLineEnd reset() - if (atEOL) token = COLONEOL + if colonSyntax && atEOL then token = COLONEOL case EOF | RBRACE => currentRegion match { case r: Indented if !r.isOutermost => diff --git a/compiler/src/dotty/tools/dotc/transform/Mixin.scala b/compiler/src/dotty/tools/dotc/transform/Mixin.scala index 96d92caf4ffc..6914f59fb1b6 100644 --- a/compiler/src/dotty/tools/dotc/transform/Mixin.scala +++ b/compiler/src/dotty/tools/dotc/transform/Mixin.scala @@ -263,7 +263,6 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase => transformFollowing(polyDefDef(mkForwarderSym(meth.asTerm, Bridge), forwarderRhsFn(meth))) } - cpy.Template(impl)( constr = if (cls.is(Trait)) cpy.DefDef(impl.constr)(vparamss = Nil :: Nil) From c2fc7da4ff6b7a51dceb6416cc996c3e17999e55 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 17 Sep 2019 10:16:28 +0200 Subject: [PATCH 4/8] Fix test file to be indent invariant --- tests/pos/Coder.scala | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/tests/pos/Coder.scala b/tests/pos/Coder.scala index 6eb1ad55ab95..8a36200ed9b1 100644 --- a/tests/pos/Coder.scala +++ b/tests/pos/Coder.scala @@ -15,14 +15,16 @@ class Coder(words: List[String]) { } /** Invert the mnemonics map to give a map from chars 'A' ... 'Z' to '2' ... '9' */ - private val charCode0: Map[Char, Char] = mnemonics withFilter { - case (digit, str) => true - case _ => false - } flatMap { x$1 => - x$1 match { - case (digit, str) => str map (ltr => ltr -> digit) + private val charCode0: Map[Char, Char] = mnemonics + .withFilter { + case (digit, str) => true + case _ => false + } + .flatMap { x$1 => + x$1 match { + case (digit, str) => str map (ltr => ltr -> digit) + } } - } private val charCode: Map[Char, Char] = for ((digit, str) <- mnemonics; ltr <- str) yield ltr -> digit @@ -42,12 +44,12 @@ class Coder(words: List[String]) { splitPoint <- 1 to number.length word <- wordsForNum(number take splitPoint) rest <- encode(number drop splitPoint) - } yield word :: rest + } + yield word :: rest }.toSet /** Maps a number to a list of all word phrases that can represent it */ def translate(number: String): Set[String] = encode(number) map (_ mkString " ") - } object Coder { From a612dbee84f5c05ad1997838f0cae802470dd996 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 17 Sep 2019 10:20:39 +0200 Subject: [PATCH 5/8] Fixes for setting-controlled colon-at-eol --- .../src/dotty/tools/dotc/parsing/Parsers.scala | 15 +++++---------- .../src/dotty/tools/dotc/parsing/Scanners.scala | 8 +++++--- .../src/dotty/tools/dotc/parsing/Tokens.scala | 4 ++++ .../dotty/tools/dotc/typer/QuotesAndSplices.scala | 2 +- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index a966f13f326d..68519b66fd39 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -717,7 +717,6 @@ object Parsers { */ def bracesToIndented[T](body: => T): T = { val colonRequired = possibleColonOffset == in.lastOffset - if colonRequired && !in.colonSyntax then return body val (startOpening, endOpening) = startingElimRegion(colonRequired) val isOutermost = in.currentRegion.isOutermost def allBraces(r: Region): Boolean = r match { @@ -736,7 +735,7 @@ object Parsers { } }) canRewrite &= (in.isAfterLineEnd || statCtdTokens.contains(in.token)) // test (5) - if (canRewrite) { + if (canRewrite && (!colonRequired || in.colonSyntax)) { val openingPatchStr = if (!colonRequired) "" else if (testChar(startOpening - 1, Chars.isOperatorPart(_))) " :" @@ -1219,7 +1218,7 @@ object Parsers { } def possibleTemplateStart(): Unit = { - in.observeIndented() + in.observeIndented(noIndentTemplateTokens, nme.derives) newLineOptWhenFollowedBy(LBRACE) } @@ -1235,9 +1234,6 @@ object Parsers { case _ => op } - def observeIndentedUnlessFollowedBy(followers: BitSet): Unit = - if !followers.contains(in.token) then in.observeIndented() - /* ------------- TYPES ------------------------------------------------------ */ /** Same as [[typ]], but if this results in a wildcard it emits a syntax error and @@ -1641,7 +1637,7 @@ object Parsers { in.nextToken() } else - observeIndentedUnlessFollowedBy(BitSet(THEN, DO)) + in.observeIndented(noIndentAfterConditionTokens) if (rewriteToNewSyntax(t.span)) dropParensOrBraces(t.span.start, s"${tokenString(altToken)}") t @@ -2302,7 +2298,7 @@ object Parsers { dropParensOrBraces(start, if (in.token == YIELD || in.token == DO) "" else "do") } } - observeIndentedUnlessFollowedBy(BitSet(YIELD, DO)) + in.observeIndented(noIndentAfterEnumeratorTokens) res } else { @@ -3547,11 +3543,10 @@ object Parsers { /** TemplateOpt = [Template] */ def templateOpt(constr: DefDef): Template = - possibleBracesStart() + possibleTemplateStart() if (in.token == EXTENDS || isIdent(nme.derives)) template(constr) else { - possibleTemplateStart() if (in.isNestedStart) template(constr) else Template(constr, Nil, Nil, EmptyValDef, Nil) } diff --git a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala index 73fae38b7248..1c0bde213d33 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala @@ -535,10 +535,11 @@ object Scanners { } } - def observeIndented(): Unit = + def observeIndented(unless: BitSet, unlessSoftKW: TermName = EmptyTermName): Unit = if (indentSyntax && isAfterLineEnd && token != INDENT) { val newLineInserted = token == NEWLINE || token == NEWLINES val nextOffset = if (newLineInserted) next.offset else offset + val nextToken = if (newLineInserted) next.token else token val nextWidth = indentWidth(nextOffset) val lastWidth = currentRegion match { case r: Indented => r.width @@ -546,12 +547,13 @@ object Scanners { case _ => nextWidth } - if (lastWidth < nextWidth) { + if lastWidth < nextWidth + && !unless.contains(nextToken) + && (unlessSoftKW.isEmpty || token != IDENTIFIER || name != unlessSoftKW) then currentRegion = Indented(nextWidth, Set(), COLONEOL, currentRegion) if (!newLineInserted) next.copyFrom(this) offset = nextOffset token = INDENT - } } /** - Join CASE + CLASS => CASECLASS, CASE + OBJECT => CASEOBJECT, SEMI + ELSE => ELSE, COLON + => COLONEOL diff --git a/compiler/src/dotty/tools/dotc/parsing/Tokens.scala b/compiler/src/dotty/tools/dotc/parsing/Tokens.scala index 0e83f37aef1e..8294b8d4254d 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Tokens.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Tokens.scala @@ -281,6 +281,10 @@ object Tokens extends TokensCommon { */ final val startParamOrGivenTypeTokens: BitSet = startParamTokens | BitSet(GIVEN, ERASED) + final val noIndentTemplateTokens = BitSet(EXTENDS) + final val noIndentAfterConditionTokens = BitSet(THEN, DO) + final val noIndentAfterEnumeratorTokens = BitSet(YIELD, DO) + final val scala3keywords = BitSet(ENUM, ERASED, GIVEN, IMPLIED) final val softModifierNames = Set(nme.inline, nme.opaque) diff --git a/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala b/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala index bab7932762a8..80f30874763f 100644 --- a/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala +++ b/compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala @@ -216,7 +216,7 @@ trait QuotesAndSplices { super.transform(tree) case tdef: TypeDef if tdef.symbol.hasAnnotation(defn.InternalQuoted_patternBindHoleAnnot) => transformTypeBindingTypeDef(tdef, typePatBuf) - case tree @ AppliedTypeTree(tpt, args) => + case tree @ AppliedTypeTree(tpt, args) => val args1: List[Tree] = args.zipWithConserve(tpt.tpe.typeParams.map(_.paramVariance)) { (arg, v) => arg.tpe match { case _: TypeBounds => transform(arg) From 785ddcca12bf0d627e3de90b2796d62ddd4eefca Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 17 Sep 2019 10:35:00 +0200 Subject: [PATCH 6/8] Rewrite compiler files back to old syntax Previous edits already used new syntax. Rewriting to old syntax was done automatically. --- compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 9 +++++---- compiler/src/dotty/tools/dotc/parsing/Scanners.scala | 7 ++++--- compiler/src/dotty/tools/dotc/typer/Applications.scala | 4 ++-- compiler/src/dotty/tools/dotc/typer/Inliner.scala | 9 ++++----- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 68519b66fd39..48f246f14cfe 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1636,10 +1636,11 @@ object Parsers { if (rewriteToOldSyntax()) revertToParens(t) in.nextToken() } - else + else { in.observeIndented(noIndentAfterConditionTokens) if (rewriteToNewSyntax(t.span)) dropParensOrBraces(t.span.start, s"${tokenString(altToken)}") + } t } else { @@ -3542,14 +3543,14 @@ object Parsers { /** TemplateOpt = [Template] */ - def templateOpt(constr: DefDef): Template = + def templateOpt(constr: DefDef): Template = { possibleTemplateStart() if (in.token == EXTENDS || isIdent(nme.derives)) template(constr) - else { + else if (in.isNestedStart) template(constr) else Template(constr, Nil, Nil, EmptyValDef, Nil) - } + } /** TemplateBody ::= [nl] `{' TemplateStatSeq `}' */ diff --git a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala index 1c0bde213d33..ede520f7b809 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala @@ -547,13 +547,14 @@ object Scanners { case _ => nextWidth } - if lastWidth < nextWidth + if (lastWidth < nextWidth && !unless.contains(nextToken) - && (unlessSoftKW.isEmpty || token != IDENTIFIER || name != unlessSoftKW) then + && (unlessSoftKW.isEmpty || token != IDENTIFIER || name != unlessSoftKW)) { currentRegion = Indented(nextWidth, Set(), COLONEOL, currentRegion) if (!newLineInserted) next.copyFrom(this) offset = nextOffset token = INDENT + } } /** - Join CASE + CLASS => CASECLASS, CASE + OBJECT => CASEOBJECT, SEMI + ELSE => ELSE, COLON + => COLONEOL @@ -595,7 +596,7 @@ object Scanners { lookahead() val atEOL = isAfterLineEnd reset() - if colonSyntax && atEOL then token = COLONEOL + if (colonSyntax && atEOL) token = COLONEOL case EOF | RBRACE => currentRegion match { case r: Indented if !r.isOutermost => diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index f92b15ee6fe5..70ed4b4143c4 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -890,8 +890,8 @@ trait Applications extends Compatibility { case err: ErrorType => cpy.Apply(tree)(fun1, proto.unforcedTypedArgs).withType(err) case TryDynamicCallType => typedDynamicApply(tree, pt) case _ => - if originalProto.isDropped then fun1 - else if fun1.symbol == defn.Compiletime_summonFrom then + if (originalProto.isDropped) fun1 + else if (fun1.symbol == defn.Compiletime_summonFrom) // Special handling of `summonFrom { ... }`. // We currently cannot use a macro for that since unlike other inline methods // summonFrom needs to expand lazily. For instance, in diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 96aea1c65745..0ff79a9ab558 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -1252,7 +1252,8 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { |""".stripMargin ctx.error(msg, inlinedFrom.sourcePos) EmptyTree - } else { + } + else { val evaluatedSplice = Splicer.splice(body, inlinedFrom.sourcePos, MacroClassLoader.fromContext)(ctx1) val inlinedNormailizer = new TreeMap { @@ -1270,10 +1271,10 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { /** Return the set of symbols that are refered at level -1 by the tree and defined in the current run. * This corresponds to the symbols that will need to be interpreted. */ - private def macroDependencies(tree: Tree)(implicit ctx: Context) = { + private def macroDependencies(tree: Tree)(implicit ctx: Context) = new TreeAccumulator[Set[Symbol]] { private[this] var level = -1 - override def apply(syms: Set[Symbol], tree: tpd.Tree)(implicit ctx: Context): Set[Symbol] = { + override def apply(syms: Set[Symbol], tree: tpd.Tree)(implicit ctx: Context): Set[Symbol] = if (level != -1) foldOver(syms, tree) else tree match { 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) { case _ => foldOver(syms, tree) } - } }.apply(Set.empty, tree) - } } From edd51adae7d645104b4064114b379223cd4ce41c Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 17 Sep 2019 11:13:01 +0200 Subject: [PATCH 7/8] Avoid colon-at-eol in tests Drop it since it is not longer supported without a special option --- .../dotty/tools/dotc/CompilationTests.scala | 3 +- tests/pos-special/indent-colons.scala | 118 ++++++++++++++++++ tests/pos/i7217.scala | 2 +- tests/pos/indent.scala | 19 +-- 4 files changed, 133 insertions(+), 9 deletions(-) create mode 100644 tests/pos-special/indent-colons.scala diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index c68eff6ea7be..bab516d8ca2a 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -56,7 +56,8 @@ class CompilationTests extends ParallelTesting { "tests/neg-custom-args/fatal-warnings/xfatalWarnings.scala", defaultOptions.and("-nowarn", "-Xfatal-warnings") ), - compileFile("tests/pos-special/typeclass-scaling.scala", defaultOptions.and("-Xmax-inlines", "40")) + compileFile("tests/pos-special/typeclass-scaling.scala", defaultOptions.and("-Xmax-inlines", "40")), + compileFile("tests/pos-special/indent-colons.scala", defaultOptions.and("-Yindent-colons")) ).checkCompile() } diff --git a/tests/pos-special/indent-colons.scala b/tests/pos-special/indent-colons.scala new file mode 100644 index 000000000000..ef9af5044174 --- /dev/null +++ b/tests/pos-special/indent-colons.scala @@ -0,0 +1,118 @@ +object Test + + locally: + var x = 0 + while x < 10 do x += 1 + val f = 10 + while + x += 1 + x < 10 + do () + + def f(x: Int): Int = + val y = + if x > 0 then + println("hello") + 22 + else + println("world") + 33 + val z = 22 + x + y + z + end f + + def g = "!" + + val xs = List(1, 2, 3) + + xs.map: + x => + val y = x * x + y * y + + xs.map: + x => + val y = x * x + y + y + + xs.map { x => + val y = x * x + if y >= 0 then + val z = y + y + println(z) + y + 1 + } + + println(f(2) + g) + + (new Test2).foo + (new Test3).foo + + var x = 1 + while + x += 1 + val y = x + println(y) + x < 10 + do () + +class Test2 + self => + def foo = 1 + + val x = + new Test2: + override def foo = 2 + end new + end x +end Test2 + +class Test3 + self => + def foo = 1 + +import collection.mutable.HashMap + +class Coder(words: List[String]) + + class Foo + println() + end Foo + + class Bar + + (2 -> "ABC", new ArrowAssoc('3') -> "DEF") + + private val mnemonics = Map( + '2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL", + '6' -> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ") + + ('1', "1") match + case (digit, str) => true + case _ => false + + ('1', "1") match + case (digit, str) => true + case _ => false + + try List(1, 2, 3) match + case x :: xs => println(x) + case Nil => println("Nil") + catch + case ex: java.io.IOException => println(ex) + case ex: Throwable => + throw ex + end try + + /** Invert the mnemonics map to give a map from chars 'A' ... 'Z' to '2' ... '9' */ + private val charCode0: Map[Char, Char] = + mnemonics + .withFilter: + case (digit, str) => true + case _ => false + .flatMap: + case (digit, str) => str map (ltr => ltr -> digit) +end Coder + +object Test22 + def foo: Int = 22 \ No newline at end of file diff --git a/tests/pos/i7217.scala b/tests/pos/i7217.scala index 1c2a92c731b7..0a177a1da88c 100644 --- a/tests/pos/i7217.scala +++ b/tests/pos/i7217.scala @@ -1,4 +1,4 @@ -class Foo(p1: String, p2: String): +class Foo(p1: String, p2: String) def this(p1: String) = this(p1, "blah") val x = { Foo("blah", "hah") } diff --git a/tests/pos/indent.scala b/tests/pos/indent.scala index ef9af5044174..e77f16b79134 100644 --- a/tests/pos/indent.scala +++ b/tests/pos/indent.scala @@ -1,6 +1,6 @@ object Test - locally: + locally { var x = 0 while x < 10 do x += 1 val f = 10 @@ -8,6 +8,7 @@ object Test x += 1 x < 10 do () + } def f(x: Int): Int = val y = @@ -25,15 +26,17 @@ object Test val xs = List(1, 2, 3) - xs.map: + xs.map { x => val y = x * x y * y + } - xs.map: + xs.map { x => val y = x * x y + y + } xs.map { x => val y = x * x @@ -61,9 +64,9 @@ class Test2 def foo = 1 val x = - new Test2: + new Test2 { override def foo = 2 - end new + } end x end Test2 @@ -107,11 +110,13 @@ class Coder(words: List[String]) /** Invert the mnemonics map to give a map from chars 'A' ... 'Z' to '2' ... '9' */ private val charCode0: Map[Char, Char] = mnemonics - .withFilter: + .withFilter { case (digit, str) => true case _ => false - .flatMap: + } + .flatMap { case (digit, str) => str map (ltr => ltr -> digit) + } end Coder object Test22 From 5331cafd22e21c0431d7ec6fabc6f9232f6b6e2a Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 17 Sep 2019 12:04:46 +0200 Subject: [PATCH 8/8] Fix more tests --- tests/neg/endmarkers.scala | 28 +++++++++++----------------- tests/neg/i4373b.scala | 2 +- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/tests/neg/endmarkers.scala b/tests/neg/endmarkers.scala index 40a2a731b2cf..3f6f41627f31 100644 --- a/tests/neg/endmarkers.scala +++ b/tests/neg/endmarkers.scala @@ -1,6 +1,6 @@ object Test - locally: + locally { var x = 0 while x < 10 do x += 1 end while // error: end of statement expected but while found // error: not found: end @@ -9,7 +9,8 @@ object Test x += 1 x < 10 do () - end while // error: misaligned end marker + end while // error: misaligned end marker // error: not found : end + } // error: ';' expected, but '}' found def f(x: Int): Int = val y = @@ -23,22 +24,12 @@ object Test val z = 22 x + y + z - end f // error: misaligned end marker + end f def g = "!" val xs = List(1, 2, 3) - xs.map: - x => - val y = x * x - y * y - - xs.map: - x => - val y = x * x - y + y - println(f(2) + g) (new Test2).foo @@ -57,10 +48,11 @@ class Test2 def foo = 1 object x - new Test2: + new Test2 { override def foo = 2 end new // error: end of statement expected but new found // error: not found: end - def bar = 2 // error: ';' expected, but unindent found + } // error: ';' expected, but '}' found + def bar = 2 end Test2 // error: misaligned end marker end Test2 @@ -102,9 +94,11 @@ class Coder(words: List[String]) /** Invert the mnemonics map to give a map from chars 'A' ... 'Z' to '2' ... '9' */ private val charCode0: Map[Char, Char] = mnemonics - .withFilter: + .withFilter { case (digit, str) => true case _ => false - .flatMap: + } + .flatMap { case (digit, str) => str map (ltr => ltr -> digit) + } end Coder // error: The start of this line does not match any of the previous indentation widths. \ No newline at end of file diff --git a/tests/neg/i4373b.scala b/tests/neg/i4373b.scala index a3d8f3850eff..297fcd76ff08 100644 --- a/tests/neg/i4373b.scala +++ b/tests/neg/i4373b.scala @@ -1,5 +1,5 @@ // ==> 05bef7805687ba94da37177f7568e3ba7da1f91c.scala <== class x0 { x1: // error - x0 | _ + x0 | _ // error // error \ No newline at end of file