From 2f870590ccc2a9d8a0dd594b62773f65dc25a4ec Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Thu, 20 May 2021 15:54:28 +0200 Subject: [PATCH 1/8] record end markers in trees and semanticdb --- .../src/dotty/tools/dotc/ast/Desugar.scala | 2 + compiler/src/dotty/tools/dotc/ast/Trees.scala | 39 ++++++- .../dotty/tools/dotc/parsing/Parsers.scala | 18 ++- .../dotc/semanticdb/ExtractSemanticDB.scala | 87 ++++++++------- .../semanticdb/expect/EndMarkers.expect.scala | 59 ++++++++++ tests/semanticdb/expect/EndMarkers.scala | 59 ++++++++++ .../expect/EndMarkers2.expect.scala | 7 ++ tests/semanticdb/expect/EndMarkers2.scala | 7 ++ tests/semanticdb/metac.expect | 104 ++++++++++++++++++ 9 files changed, 336 insertions(+), 46 deletions(-) create mode 100644 tests/semanticdb/expect/EndMarkers.expect.scala create mode 100644 tests/semanticdb/expect/EndMarkers.scala create mode 100644 tests/semanticdb/expect/EndMarkers2.expect.scala create mode 100644 tests/semanticdb/expect/EndMarkers2.scala diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 0bbe5ee7c7ac..5c244085f2f5 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -182,6 +182,7 @@ object desugar { tpt = TypeTree(defn.UnitType), rhs = setterRhs ).withMods((mods | Accessor) &~ (CaseAccessor | GivenOrImplicit | Lazy)) + .dropEndSpan Thicket(vdef1, setter) } else vdef1 @@ -874,6 +875,7 @@ object desugar { val modul = ValDef(moduleName, clsRef, New(clsRef, Nil)) .withMods(mods.toTermFlags & RetainedModuleValFlags | ModuleValCreationFlags) .withSpan(mdef.span.startPos) + .withEndSpan(copyFrom=mdef) val ValDef(selfName, selfTpt, _) = impl.self val selfMods = impl.self.mods if (!selfTpt.isEmpty) report.error(ObjectMayNotHaveSelfType(mdef), impl.self.srcPos) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index d1de1094524c..137864570330 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -327,9 +327,43 @@ object Trees { extension (mdef: untpd.DefTree) def mods: untpd.Modifiers = mdef.rawMods - abstract class NamedDefTree[-T >: Untyped](implicit @constructorOnly src: SourceFile) extends NameTree[T] with DefTree[T] { + /** PackageDef | NamedDefTree */ + sealed trait WithEndMarker: + self: Attachment.Container => + + import WithEndMarker.* + + final def endToken: SimpleName = endMarker.stripModuleClassSuffix.lastPart + + protected def endMarker: Name + + final def withEndSpan(span: Span): self.type = + self.withAttachment(EndMarker, span) + + final def withEndSpan(copyFrom: WithEndMarker): self.type = + copyFrom.endSpan.foreach(span => withEndSpan(span=span)) + this + + final def dropEndSpan: self.type = + self.removeAttachment(EndMarker) + this + + final def endSpan: Option[Span] = self.getAttachment(EndMarker) + + object WithEndMarker: + /** Property key for trees with an `end` marker */ + private val EndMarker: Property.StickyKey[Span] = Property.StickyKey() + + end WithEndMarker + + abstract class NamedDefTree[-T >: Untyped](implicit @constructorOnly src: SourceFile) + extends NameTree[T] with DefTree[T] with WithEndMarker { type ThisTree[-T >: Untyped] <: NamedDefTree[T] + protected def endMarker = + if name == nme.CONSTRUCTOR then nme.this_ + else name + /** The position of the name defined by this definition. * This is a point position if the definition is synthetic, or a range position * if the definition comes from source. @@ -857,9 +891,10 @@ object Trees { /** package pid { stats } */ case class PackageDef[-T >: Untyped] private[ast] (pid: RefTree[T], stats: List[Tree[T]])(implicit @constructorOnly src: SourceFile) - extends ProxyTree[T] { + extends ProxyTree[T] with WithEndMarker { type ThisTree[-T >: Untyped] = PackageDef[T] def forwardTo: RefTree[T] = pid + protected def endMarker: Name = pid.name } /** arg @annot */ diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 86144347f3fe..edae8cd92df4 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1283,8 +1283,8 @@ object Parsers { in.token == IDENTIFIER && in.name == nme.extension case PackageDef(pid: RefTree, _) => in.isIdent && in.name == pid.name - case PatDef(_, IdPattern(id, _) :: Nil, _, _) => - in.isIdent && in.name == id.name + case PatDef(_, IdPattern(id, _) :: Nil, _, _) => // TODO: it looks like this case is never reached + in.isIdent && in.name == id.name case stat: MemberDef if stat.mods.is(Given) => in.token == GIVEN case _: PatDef => in.token == VAL case _: If => in.token == IF @@ -1295,9 +1295,21 @@ object Parsers { case _: (ForYield | ForDo) => in.token == FOR case _ => false + def matchesWithUpdated(stat: Tree): Boolean = { + val didMatch = matches(stat) + if didMatch then + stat match + case stat: WithEndMarker => + val end = in.lastCharOffset + stat.withEndSpan(span=Span(end - stat.endToken.length, end)) + case _ => + () + didMatch + } + if in.token == END then val start = in.skipToken() - if stats.isEmpty || !matches(stats.last) then + if stats.isEmpty || !matchesWithUpdated(stats.last) then syntaxError("misaligned end marker", Span(start, in.lastCharOffset)) in.token = IDENTIFIER // Leaving it as the original token can confuse newline insertion in.nextToken() diff --git a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala index 89cf6f3df7d5..28a807163581 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala @@ -6,7 +6,7 @@ import core._ import Phases._ import ast.tpd._ import ast.untpd.given -import ast.Trees.mods +import ast.Trees.{mods, WithEndMarker} import Contexts._ import Symbols._ import Flags._ @@ -139,47 +139,46 @@ class ExtractSemanticDB extends Phase: case tree => registerDefinition(tree.symbol, tree.span, Set.empty, tree.source) tree.stats.foreach(traverse) case tree: NamedDefTree => - if tree.symbol.isAllOf(ModuleValCreationFlags) then - return - if !excludeDef(tree.symbol) - && tree.span.hasLength then - registerDefinition(tree.symbol, tree.nameSpan, symbolKinds(tree), tree.source) - val privateWithin = tree.symbol.privateWithin - if privateWithin.exists then - registerUseGuarded(None, privateWithin, spanOfSymbol(privateWithin, tree.span, tree.source), tree.source) - else if !excludeSymbol(tree.symbol) then - registerSymbol(tree.symbol, symbolName(tree.symbol), symbolKinds(tree)) - tree match - case tree: ValDef - if tree.symbol.isAllOf(EnumValue) => - tree.rhs match - case Block(TypeDef(_, template: Template) :: _, _) => // simple case with specialised extends clause - template.parents.filter(!_.span.isZeroExtent).foreach(traverse) - case _ => // calls $new - case tree: ValDef - if tree.symbol.isSelfSym => - if tree.tpt.span.hasLength then - traverse(tree.tpt) - case tree: DefDef - if tree.symbol.isConstructor => // ignore typeparams for secondary ctors - tree.trailingParamss.foreach(_.foreach(traverse)) - traverse(tree.rhs) - case tree: (DefDef | ValDef) - if tree.symbol.isSyntheticWithIdent => + if !tree.symbol.isAllOf(ModuleValCreationFlags) then + if !excludeDef(tree.symbol) + && tree.span.hasLength then + registerDefinition(tree.symbol, tree.nameSpan, symbolKinds(tree), tree.source) + val privateWithin = tree.symbol.privateWithin + if privateWithin.exists then + registerUseGuarded(None, privateWithin, spanOfSymbol(privateWithin, tree.span, tree.source), tree.source) + else if !excludeSymbol(tree.symbol) then + registerSymbol(tree.symbol, symbolName(tree.symbol), symbolKinds(tree)) tree match - case tree: DefDef => - tree.paramss.foreach(_.foreach(param => registerSymbolSimple(param.symbol))) - case tree: ValDef if tree.symbol.is(Given) => traverse(tree.tpt) - case _ => - if !tree.symbol.isGlobal then - localBodies(tree.symbol) = tree.rhs - // ignore rhs - case PatternValDef(pat, rhs) => - traverse(rhs) - PatternValDef.collectPats(pat).foreach(traverse) - case tree => - if !excludeChildren(tree.symbol) then - traverseChildren(tree) + case tree: ValDef + if tree.symbol.isAllOf(EnumValue) => + tree.rhs match + case Block(TypeDef(_, template: Template) :: _, _) => // simple case with specialised extends clause + template.parents.filter(!_.span.isZeroExtent).foreach(traverse) + case _ => // calls $new + case tree: ValDef + if tree.symbol.isSelfSym => + if tree.tpt.span.hasLength then + traverse(tree.tpt) + case tree: DefDef + if tree.symbol.isConstructor => // ignore typeparams for secondary ctors + tree.trailingParamss.foreach(_.foreach(traverse)) + traverse(tree.rhs) + case tree: (DefDef | ValDef) + if tree.symbol.isSyntheticWithIdent => + tree match + case tree: DefDef => + tree.paramss.foreach(_.foreach(param => registerSymbolSimple(param.symbol))) + case tree: ValDef if tree.symbol.is(Given) => traverse(tree.tpt) + case _ => + if !tree.symbol.isGlobal then + localBodies(tree.symbol) = tree.rhs + // ignore rhs + case PatternValDef(pat, rhs) => + traverse(rhs) + PatternValDef.collectPats(pat).foreach(traverse) + case tree => + if !excludeChildren(tree.symbol) then + traverseChildren(tree) case tree: Template => val ctorSym = tree.constr.symbol if !excludeDef(ctorSym) then @@ -240,6 +239,12 @@ class ExtractSemanticDB extends Phase: case _ => traverseChildren(tree) + tree match + case tree: WithEndMarker => + for endSpan <- tree.endSpan do + registerUseGuarded(None, tree.symbol, endSpan, tree.source) + case _ => + end traverse private def funParamSymbol(funSym: Symbol)(using Context): Name => String = diff --git a/tests/semanticdb/expect/EndMarkers.expect.scala b/tests/semanticdb/expect/EndMarkers.expect.scala new file mode 100644 index 000000000000..f60679a4bc99 --- /dev/null +++ b/tests/semanticdb/expect/EndMarkers.expect.scala @@ -0,0 +1,59 @@ +package endmarkers: + + class MultiCtor/*<-endmarkers::MultiCtor#*/(val i/*<-endmarkers::MultiCtor#i.*/: Int/*->scala::Int#*/): + def this()/*<-endmarkers::MultiCtor#``(+1).*/ = + this(23) + end this/*->endmarkers::MultiCtor#``(+1).*/ + end MultiCtor/*->endmarkers::MultiCtor#*/ + + /*<-endmarkers::EndMarkers$package.*/def topLevelMethod/*<-endmarkers::EndMarkers$package.topLevelMethod().*/: String/*->scala::Predef.String#*/ = + "hello" + end topLevelMethod/*->endmarkers::EndMarkers$package.topLevelMethod().*/ + + val topLevelVal/*<-endmarkers::EndMarkers$package.topLevelVal.*/: Int/*->scala::Int#*/ = + 23 + end topLevelVal/*->endmarkers::EndMarkers$package.topLevelVal.*/ + + var topLevelVar/*<-endmarkers::EndMarkers$package.topLevelVar().*/: String/*->scala::Predef.String#*/ = + "" + end topLevelVar/*->endmarkers::EndMarkers$package.topLevelVar().*/ + + class Container/*<-endmarkers::Container#*/: + + def foo/*<-endmarkers::Container#foo().*/ = + (/*->scala::Tuple3.apply().*/1,2,3) + end foo/*->endmarkers::Container#foo().*/ + + val bar/*<-endmarkers::Container#bar.*/ = + (/*->scala::Tuple3.apply().*/4,5,6) + end bar/*->endmarkers::Container#bar.*/ + + var baz/*<-endmarkers::Container#baz().*/ = + 15 + end baz/*->endmarkers::Container#baz().*/ + + end Container/*->endmarkers::Container#*/ + + def topLevelWithLocals/*<-endmarkers::EndMarkers$package.topLevelWithLocals().*/: Unit/*->scala::Unit#*/ = + + val localVal/*<-local0*/ = + 37 + end localVal/*->local0*/ + + var localVar/*<-local1*/ = + 43 + end localVar/*->local1*/ + + def localDef/*<-local2*/ = + 97 + end localDef/*->local2*/ + + end topLevelWithLocals/*->endmarkers::EndMarkers$package.topLevelWithLocals().*/ + + object TestObj/*<-endmarkers::TestObj.*/: + + def foo/*<-endmarkers::TestObj.foo().*/ = 23 + + end TestObj/*->endmarkers::TestObj.*/ + +end endmarkers diff --git a/tests/semanticdb/expect/EndMarkers.scala b/tests/semanticdb/expect/EndMarkers.scala new file mode 100644 index 000000000000..c7ae04898ebd --- /dev/null +++ b/tests/semanticdb/expect/EndMarkers.scala @@ -0,0 +1,59 @@ +package endmarkers: + + class MultiCtor(val i: Int): + def this() = + this(23) + end this + end MultiCtor + + def topLevelMethod: String = + "hello" + end topLevelMethod + + val topLevelVal: Int = + 23 + end topLevelVal + + var topLevelVar: String = + "" + end topLevelVar + + class Container: + + def foo = + (1,2,3) + end foo + + val bar = + (4,5,6) + end bar + + var baz = + 15 + end baz + + end Container + + def topLevelWithLocals: Unit = + + val localVal = + 37 + end localVal + + var localVar = + 43 + end localVar + + def localDef = + 97 + end localDef + + end topLevelWithLocals + + object TestObj: + + def foo = 23 + + end TestObj + +end endmarkers diff --git a/tests/semanticdb/expect/EndMarkers2.expect.scala b/tests/semanticdb/expect/EndMarkers2.expect.scala new file mode 100644 index 000000000000..c6d5d6937c30 --- /dev/null +++ b/tests/semanticdb/expect/EndMarkers2.expect.scala @@ -0,0 +1,7 @@ +package object endmark/*<-endmarkers2::package.*/ers2: + + type Foo/*<-endmarkers2::package.Foo#*/ = + Unit/*->scala::Unit#*/ + end Foo/*->endmarkers2::package.Foo#*/ + +end endmarkers2/*->endmarkers2::package.*/ diff --git a/tests/semanticdb/expect/EndMarkers2.scala b/tests/semanticdb/expect/EndMarkers2.scala new file mode 100644 index 000000000000..377696ca8a79 --- /dev/null +++ b/tests/semanticdb/expect/EndMarkers2.scala @@ -0,0 +1,7 @@ +package object endmarkers2: + + type Foo = + Unit + end Foo + +end endmarkers2 diff --git a/tests/semanticdb/metac.expect b/tests/semanticdb/metac.expect index 5c741a5acf74..7ad6be73fe13 100644 --- a/tests/semanticdb/metac.expect +++ b/tests/semanticdb/metac.expect @@ -658,6 +658,110 @@ Occurrences: [0:8..0:15): example <- example/ [2:7..2:18): EmptyObject <- example/EmptyObject. +expect/EndMarkers.scala +----------------------- + +Summary: +Schema => SemanticDB v4 +Uri => EndMarkers.scala +Text => empty +Language => Scala +Symbols => 24 entries +Occurrences => 43 entries + +Symbols: +endmarkers/Container# => class Container +endmarkers/Container#``(). => primary ctor +endmarkers/Container#`baz_=`(). => var method baz_= +endmarkers/Container#`baz_=`().(x$1) => param x$1 +endmarkers/Container#bar. => val method bar +endmarkers/Container#baz(). => var method baz +endmarkers/Container#foo(). => method foo +endmarkers/EndMarkers$package. => final package object endmarkers +endmarkers/EndMarkers$package.`topLevelVar_=`(). => var method topLevelVar_= +endmarkers/EndMarkers$package.`topLevelVar_=`().(x$1) => param x$1 +endmarkers/EndMarkers$package.topLevelMethod(). => method topLevelMethod +endmarkers/EndMarkers$package.topLevelVal. => val method topLevelVal +endmarkers/EndMarkers$package.topLevelVar(). => var method topLevelVar +endmarkers/EndMarkers$package.topLevelWithLocals(). => method topLevelWithLocals +endmarkers/MultiCtor# => class MultiCtor +endmarkers/MultiCtor#``(). => primary ctor +endmarkers/MultiCtor#``().(i) => val param i +endmarkers/MultiCtor#``(+1). => ctor +endmarkers/MultiCtor#i. => val method i +endmarkers/TestObj. => final object TestObj +endmarkers/TestObj.foo(). => method foo +local0 => val local localVal +local1 => var local localVar +local2 => local localDef + +Occurrences: +[0:8..0:18): endmarkers <- endmarkers/ +[2:8..2:17): MultiCtor <- endmarkers/MultiCtor# +[2:17..2:17): <- endmarkers/MultiCtor#``(). +[2:22..2:23): i <- endmarkers/MultiCtor#i. +[2:25..2:28): Int -> scala/Int# +[3:8..3:14): <- endmarkers/MultiCtor#``(+1). +[4:11..4:11): -> endmarkers/MultiCtor#``(). +[5:8..5:12): this -> endmarkers/MultiCtor#``(+1). +[6:6..6:15): MultiCtor -> endmarkers/MultiCtor# +[8:2..8:2): <- endmarkers/EndMarkers$package. +[8:6..8:20): topLevelMethod <- endmarkers/EndMarkers$package.topLevelMethod(). +[8:22..8:28): String -> scala/Predef.String# +[10:6..10:20): topLevelMethod -> endmarkers/EndMarkers$package.topLevelMethod(). +[12:6..12:17): topLevelVal <- endmarkers/EndMarkers$package.topLevelVal. +[12:19..12:22): Int -> scala/Int# +[14:6..14:17): topLevelVal -> endmarkers/EndMarkers$package.topLevelVal. +[16:6..16:17): topLevelVar <- endmarkers/EndMarkers$package.topLevelVar(). +[16:19..16:25): String -> scala/Predef.String# +[18:6..18:17): topLevelVar -> endmarkers/EndMarkers$package.topLevelVar(). +[20:8..20:17): Container <- endmarkers/Container# +[22:4..22:4): <- endmarkers/Container#``(). +[22:8..22:11): foo <- endmarkers/Container#foo(). +[23:7..23:7): -> scala/Tuple3.apply(). +[24:8..24:11): foo -> endmarkers/Container#foo(). +[26:8..26:11): bar <- endmarkers/Container#bar. +[27:7..27:7): -> scala/Tuple3.apply(). +[28:8..28:11): bar -> endmarkers/Container#bar. +[30:8..30:11): baz <- endmarkers/Container#baz(). +[32:8..32:11): baz -> endmarkers/Container#baz(). +[34:6..34:15): Container -> endmarkers/Container# +[36:6..36:24): topLevelWithLocals <- endmarkers/EndMarkers$package.topLevelWithLocals(). +[36:26..36:30): Unit -> scala/Unit# +[38:8..38:16): localVal <- local0 +[40:8..40:16): localVal -> local0 +[42:8..42:16): localVar <- local1 +[44:8..44:16): localVar -> local1 +[46:8..46:16): localDef <- local2 +[48:8..48:16): localDef -> local2 +[50:6..50:24): topLevelWithLocals -> endmarkers/EndMarkers$package.topLevelWithLocals(). +[52:9..52:16): TestObj <- endmarkers/TestObj. +[54:8..54:11): foo <- endmarkers/TestObj.foo(). +[56:6..56:13): TestObj -> endmarkers/TestObj. +[58:4..58:14): endmarkers -> endmarkers/ + +expect/EndMarkers2.scala +------------------------ + +Summary: +Schema => SemanticDB v4 +Uri => EndMarkers2.scala +Text => empty +Language => Scala +Symbols => 2 entries +Occurrences => 5 entries + +Symbols: +endmarkers2/package. => final package object endmarkers2 +endmarkers2/package.Foo# => type Foo + +Occurrences: +[0:15..0:22): endmark <- endmarkers2/package. +[2:7..2:10): Foo <- endmarkers2/package.Foo# +[3:4..3:8): Unit -> scala/Unit# +[4:6..4:9): Foo -> endmarkers2/package.Foo# +[6:4..6:15): endmarkers2 -> endmarkers2/package. + expect/EnumVal.scala -------------------- From 4ae44d683f0bb1b1fa61c741e9c1e3ec32cd6fe7 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Thu, 20 May 2021 19:54:12 +0200 Subject: [PATCH 2/8] use package name for pkg object namespan --- compiler/src/dotty/tools/dotc/ast/Trees.scala | 3 ++- tests/semanticdb/expect/EndMarkers2.expect.scala | 2 +- tests/semanticdb/expect/semanticdb-Flags.expect.scala | 4 ++-- tests/semanticdb/metac.expect | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 137864570330..464ad0967719 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -376,7 +376,8 @@ object Trees { val point = span.point if (rawMods.is(Synthetic) || span.isSynthetic || name.toTermName == nme.ERROR) Span(point) else { - val realName = name.stripModuleClassSuffix.lastPart + val srcName = if symbol.isPackageObject then symbol.owner.name else name + val realName = srcName.stripModuleClassSuffix.lastPart Span(point, point + realName.length, point) } } diff --git a/tests/semanticdb/expect/EndMarkers2.expect.scala b/tests/semanticdb/expect/EndMarkers2.expect.scala index c6d5d6937c30..61b8f8093a8e 100644 --- a/tests/semanticdb/expect/EndMarkers2.expect.scala +++ b/tests/semanticdb/expect/EndMarkers2.expect.scala @@ -1,4 +1,4 @@ -package object endmark/*<-endmarkers2::package.*/ers2: +package object endmarkers2/*<-endmarkers2::package.*/: type Foo/*<-endmarkers2::package.Foo#*/ = Unit/*->scala::Unit#*/ diff --git a/tests/semanticdb/expect/semanticdb-Flags.expect.scala b/tests/semanticdb/expect/semanticdb-Flags.expect.scala index fe920433e231..b64732665c25 100644 --- a/tests/semanticdb/expect/semanticdb-Flags.expect.scala +++ b/tests/semanticdb/expect/semanticdb-Flags.expect.scala @@ -2,8 +2,8 @@ package flags import scala.language/*->scala::language.*/.experimental/*->scala::language.experimental.*/.macros/*->scala::language.experimental.macros.*/ -package object p { - p/*<-flags::p::package.*/rivate lazy val x/*<-flags::p::package.x.*/ = 1 +package object p/*<-flags::p::package.*/ { + private lazy val x/*<-flags::p::package.x.*/ = 1 protected implicit var y/*<-flags::p::package.y().*/: Int/*->scala::Int#*/ = 2 def z/*<-flags::p::package.z().*/(pp/*<-flags::p::package.z().(pp)*/: Int/*->scala::Int#*/) = 3 def m/*<-flags::p::package.m().*/[TT/*<-flags::p::package.m().[TT]*/]: Int/*->scala::Int#*/ = macro ???/*->scala::Predef.`???`().*/ diff --git a/tests/semanticdb/metac.expect b/tests/semanticdb/metac.expect index 7ad6be73fe13..3b33445d1eff 100644 --- a/tests/semanticdb/metac.expect +++ b/tests/semanticdb/metac.expect @@ -756,7 +756,7 @@ endmarkers2/package. => final package object endmarkers2 endmarkers2/package.Foo# => type Foo Occurrences: -[0:15..0:22): endmark <- endmarkers2/package. +[0:15..0:26): endmarkers2 <- endmarkers2/package. [2:7..2:10): Foo <- endmarkers2/package.Foo# [3:4..3:8): Unit -> scala/Unit# [4:6..4:9): Foo -> endmarkers2/package.Foo# @@ -3833,7 +3833,7 @@ Occurrences: [2:13..2:21): language -> scala/language. [2:22..2:34): experimental -> scala/language.experimental. [2:35..2:41): macros -> scala/language.experimental.macros. -[4:15..5:3): <- flags/p/package. +[4:15..4:16): p <- flags/p/package. [5:2..5:3): p -> flags/p/ [5:19..5:20): x <- flags/p/package.x. [6:25..6:26): y <- flags/p/package.y(). From b0e8ac0a00d590d9ec7478007c1aace801971f7f Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Thu, 20 May 2021 20:44:50 +0200 Subject: [PATCH 3/8] resolve end name later --- .../src/dotty/tools/dotc/ast/Desugar.scala | 4 +-- compiler/src/dotty/tools/dotc/ast/Trees.scala | 34 ++++++++++++------- .../dotty/tools/dotc/parsing/Parsers.scala | 3 +- .../dotc/semanticdb/ExtractSemanticDB.scala | 3 +- 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 5c244085f2f5..80fab2246726 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -182,7 +182,7 @@ object desugar { tpt = TypeTree(defn.UnitType), rhs = setterRhs ).withMods((mods | Accessor) &~ (CaseAccessor | GivenOrImplicit | Lazy)) - .dropEndSpan + .dropEndIndex Thicket(vdef1, setter) } else vdef1 @@ -875,7 +875,7 @@ object desugar { val modul = ValDef(moduleName, clsRef, New(clsRef, Nil)) .withMods(mods.toTermFlags & RetainedModuleValFlags | ModuleValCreationFlags) .withSpan(mdef.span.startPos) - .withEndSpan(copyFrom=mdef) + .withEndIndex(copyFrom=mdef) val ValDef(selfName, selfTpt, _) = impl.self val selfMods = impl.self.mods if (!selfTpt.isEmpty) report.error(ObjectMayNotHaveSelfType(mdef), impl.self.srcPos) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 464ad0967719..ec669ada5f71 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -333,26 +333,31 @@ object Trees { import WithEndMarker.* - final def endToken: SimpleName = endMarker.stripModuleClassSuffix.lastPart + final def endSpan(using Context): Span = + self.getAttachment(EndIndex) match + case Some(end) => + val realName = endName.stripModuleClassSuffix.lastPart + Span(end - realName.length, end) + case none => NoSpan - protected def endMarker: Name + protected def endName(using Context): Name - final def withEndSpan(span: Span): self.type = - self.withAttachment(EndMarker, span) + final def withEndIndex(index: Int): self.type = + self.withAttachment(EndIndex, index) - final def withEndSpan(copyFrom: WithEndMarker): self.type = - copyFrom.endSpan.foreach(span => withEndSpan(span=span)) + final def withEndIndex(copyFrom: WithEndMarker): self.type = + copyFrom.endIndex.foreach(index => withEndIndex(index)) this - final def dropEndSpan: self.type = - self.removeAttachment(EndMarker) + final def dropEndIndex: self.type = + self.removeAttachment(EndIndex) this - final def endSpan: Option[Span] = self.getAttachment(EndMarker) + protected def endIndex: Option[Int] = self.getAttachment(EndIndex) object WithEndMarker: /** Property key for trees with an `end` marker */ - private val EndMarker: Property.StickyKey[Span] = Property.StickyKey() + private val EndIndex: Property.StickyKey[Int] = Property.StickyKey() end WithEndMarker @@ -360,8 +365,12 @@ object Trees { extends NameTree[T] with DefTree[T] with WithEndMarker { type ThisTree[-T >: Untyped] <: NamedDefTree[T] - protected def endMarker = + protected def endName(using Context) = if name == nme.CONSTRUCTOR then nme.this_ + else srcName + + protected def srcName(using Context): Name = + if symbol.isPackageObject then symbol.owner.name else name /** The position of the name defined by this definition. @@ -376,7 +385,6 @@ object Trees { val point = span.point if (rawMods.is(Synthetic) || span.isSynthetic || name.toTermName == nme.ERROR) Span(point) else { - val srcName = if symbol.isPackageObject then symbol.owner.name else name val realName = srcName.stripModuleClassSuffix.lastPart Span(point, point + realName.length, point) } @@ -895,7 +903,7 @@ object Trees { extends ProxyTree[T] with WithEndMarker { type ThisTree[-T >: Untyped] = PackageDef[T] def forwardTo: RefTree[T] = pid - protected def endMarker: Name = pid.name + protected def endName(using Context): Name = pid.name } /** arg @annot */ diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index edae8cd92df4..13bc11910260 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1300,8 +1300,7 @@ object Parsers { if didMatch then stat match case stat: WithEndMarker => - val end = in.lastCharOffset - stat.withEndSpan(span=Span(end - stat.endToken.length, end)) + stat.withEndIndex(index=in.lastCharOffset) case _ => () didMatch diff --git a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala index 28a807163581..b97e1f3f8484 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala @@ -241,7 +241,8 @@ class ExtractSemanticDB extends Phase: tree match case tree: WithEndMarker => - for endSpan <- tree.endSpan do + val endSpan = tree.endSpan + if endSpan.exists then registerUseGuarded(None, tree.symbol, endSpan, tree.source) case _ => From 88b39db0e09d62f4d646fdc5217b3560af0f2d01 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Tue, 25 May 2021 11:22:23 +0200 Subject: [PATCH 4/8] remove redundant case --- compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 13bc11910260..441ef71f22d0 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1283,8 +1283,6 @@ object Parsers { in.token == IDENTIFIER && in.name == nme.extension case PackageDef(pid: RefTree, _) => in.isIdent && in.name == pid.name - case PatDef(_, IdPattern(id, _) :: Nil, _, _) => // TODO: it looks like this case is never reached - in.isIdent && in.name == id.name case stat: MemberDef if stat.mods.is(Given) => in.token == GIVEN case _: PatDef => in.token == VAL case _: If => in.token == IF From 3ebfd4a8342a482669ba9dda398f1955e7b22f28 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Thu, 27 May 2021 12:30:29 +0200 Subject: [PATCH 5/8] refactor names --- compiler/src/dotty/tools/dotc/ast/Desugar.scala | 4 ++-- compiler/src/dotty/tools/dotc/ast/Trees.scala | 4 ++-- compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 80fab2246726..54ff9021a83c 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -182,7 +182,7 @@ object desugar { tpt = TypeTree(defn.UnitType), rhs = setterRhs ).withMods((mods | Accessor) &~ (CaseAccessor | GivenOrImplicit | Lazy)) - .dropEndIndex + .dropEndIndex() // the end marker should only appear on the getter definition Thicket(vdef1, setter) } else vdef1 @@ -875,7 +875,7 @@ object desugar { val modul = ValDef(moduleName, clsRef, New(clsRef, Nil)) .withMods(mods.toTermFlags & RetainedModuleValFlags | ModuleValCreationFlags) .withSpan(mdef.span.startPos) - .withEndIndex(copyFrom=mdef) + .withEndIndex(copyFrom = mdef) // copy over the end market position to the module val val ValDef(selfName, selfTpt, _) = impl.self val selfMods = impl.self.mods if (!selfTpt.isEmpty) report.error(ObjectMayNotHaveSelfType(mdef), impl.self.srcPos) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index ec669ada5f71..b259e405b78b 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -346,10 +346,10 @@ object Trees { self.withAttachment(EndIndex, index) final def withEndIndex(copyFrom: WithEndMarker): self.type = - copyFrom.endIndex.foreach(index => withEndIndex(index)) + copyFrom.endIndex.foreach(withEndIndex) this - final def dropEndIndex: self.type = + final def dropEndIndex(): self.type = self.removeAttachment(EndIndex) this diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 441ef71f22d0..887621468ab7 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1293,12 +1293,12 @@ object Parsers { case _: (ForYield | ForDo) => in.token == FOR case _ => false - def matchesWithUpdated(stat: Tree): Boolean = { + def matchesAndSetEnd(stat: Tree): Boolean = { val didMatch = matches(stat) if didMatch then stat match case stat: WithEndMarker => - stat.withEndIndex(index=in.lastCharOffset) + stat.withEndIndex(index = in.lastCharOffset) case _ => () didMatch @@ -1306,7 +1306,7 @@ object Parsers { if in.token == END then val start = in.skipToken() - if stats.isEmpty || !matchesWithUpdated(stats.last) then + if stats.isEmpty || !matchesAndSetEnd(stats.last) then syntaxError("misaligned end marker", Span(start, in.lastCharOffset)) in.token = IDENTIFIER // Leaving it as the original token can confuse newline insertion in.nextToken() From 65187a37b9585031bdde1f3bfbce849748c11cc2 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Tue, 1 Jun 2021 13:40:32 +0200 Subject: [PATCH 6/8] escape ctor in srcName --- compiler/src/dotty/tools/dotc/ast/Desugar.scala | 2 +- compiler/src/dotty/tools/dotc/ast/Trees.scala | 13 +++++-------- tests/semanticdb/expect/Annotations.expect.scala | 2 +- tests/semanticdb/expect/EndMarkers.expect.scala | 2 +- .../semanticdb/expect/semanticdb-Flags.expect.scala | 4 ++-- tests/semanticdb/metac.expect | 8 ++++---- 6 files changed, 14 insertions(+), 17 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 54ff9021a83c..5d953140ce78 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -875,7 +875,7 @@ object desugar { val modul = ValDef(moduleName, clsRef, New(clsRef, Nil)) .withMods(mods.toTermFlags & RetainedModuleValFlags | ModuleValCreationFlags) .withSpan(mdef.span.startPos) - .withEndIndex(copyFrom = mdef) // copy over the end market position to the module val + .withEndIndex(copyFrom = mdef) // copy over the end marker position to the module val val ValDef(selfName, selfTpt, _) = impl.self val selfMods = impl.self.mods if (!selfTpt.isEmpty) report.error(ObjectMayNotHaveSelfType(mdef), impl.self.srcPos) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index b259e405b78b..6a0146241788 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -336,11 +336,11 @@ object Trees { final def endSpan(using Context): Span = self.getAttachment(EndIndex) match case Some(end) => - val realName = endName.stripModuleClassSuffix.lastPart + val realName = srcName.stripModuleClassSuffix.lastPart Span(end - realName.length, end) case none => NoSpan - protected def endName(using Context): Name + protected def srcName(using Context): Name final def withEndIndex(index: Int): self.type = self.withAttachment(EndIndex, index) @@ -365,12 +365,9 @@ object Trees { extends NameTree[T] with DefTree[T] with WithEndMarker { type ThisTree[-T >: Untyped] <: NamedDefTree[T] - protected def endName(using Context) = - if name == nme.CONSTRUCTOR then nme.this_ - else srcName - protected def srcName(using Context): Name = - if symbol.isPackageObject then symbol.owner.name + if name == nme.CONSTRUCTOR then nme.this_ + else if symbol.isPackageObject then symbol.owner.name else name /** The position of the name defined by this definition. @@ -903,7 +900,7 @@ object Trees { extends ProxyTree[T] with WithEndMarker { type ThisTree[-T >: Untyped] = PackageDef[T] def forwardTo: RefTree[T] = pid - protected def endName(using Context): Name = pid.name + protected def srcName(using Context): Name = pid.name } /** arg @annot */ diff --git a/tests/semanticdb/expect/Annotations.expect.scala b/tests/semanticdb/expect/Annotations.expect.scala index fb89c0e94abc..14976ad8aa2f 100644 --- a/tests/semanticdb/expect/Annotations.expect.scala +++ b/tests/semanticdb/expect/Annotations.expect.scala @@ -21,7 +21,7 @@ class Annotations/*<-annot::Annotations#*/[@TypeParameterAnnotation/*->com::java class B/*<-annot::B#*/ @ConstructorAnnotation/*->com::javacp::annot::ConstructorAnnotation#*/()(x/*<-annot::B#x.*/: Int/*->scala::Int#*/) { @ConstructorAnnotation/*->com::javacp::annot::ConstructorAnnotation#*/ - def this()/*<-annot::B#``(+1).*/ = this(42) + def this/*<-annot::B#``(+1).*/() = this(42) } @ObjectAnnotation/*->com::javacp::annot::ObjectAnnotation#*/ diff --git a/tests/semanticdb/expect/EndMarkers.expect.scala b/tests/semanticdb/expect/EndMarkers.expect.scala index f60679a4bc99..d115bdf4c470 100644 --- a/tests/semanticdb/expect/EndMarkers.expect.scala +++ b/tests/semanticdb/expect/EndMarkers.expect.scala @@ -1,7 +1,7 @@ package endmarkers: class MultiCtor/*<-endmarkers::MultiCtor#*/(val i/*<-endmarkers::MultiCtor#i.*/: Int/*->scala::Int#*/): - def this()/*<-endmarkers::MultiCtor#``(+1).*/ = + def this/*<-endmarkers::MultiCtor#``(+1).*/() = this(23) end this/*->endmarkers::MultiCtor#``(+1).*/ end MultiCtor/*->endmarkers::MultiCtor#*/ diff --git a/tests/semanticdb/expect/semanticdb-Flags.expect.scala b/tests/semanticdb/expect/semanticdb-Flags.expect.scala index b64732665c25..7166a5da9859 100644 --- a/tests/semanticdb/expect/semanticdb-Flags.expect.scala +++ b/tests/semanticdb/expect/semanticdb-Flags.expect.scala @@ -8,8 +8,8 @@ package object p/*<-flags::p::package.*/ { def z/*<-flags::p::package.z().*/(pp/*<-flags::p::package.z().(pp)*/: Int/*->scala::Int#*/) = 3 def m/*<-flags::p::package.m().*/[TT/*<-flags::p::package.m().[TT]*/]: Int/*->scala::Int#*/ = macro ???/*->scala::Predef.`???`().*/ abstract class C/*<-flags::p::package.C#*/[+T/*<-flags::p::package.C#[T]*/, -U/*<-flags::p::package.C#[U]*/, V/*<-flags::p::package.C#[V]*/](x/*<-flags::p::package.C#x.*/: T/*->flags::p::package.C#[T]*/, y/*<-flags::p::package.C#y.*/: U/*->flags::p::package.C#[U]*/, z/*<-flags::p::package.C#z.*/: V/*->flags::p::package.C#[V]*/) { - def this()/*<-flags::p::package.C#``(+1).*/ = this(???/*->scala::Predef.`???`().*/, ???/*->scala::Predef.`???`().*/, ???/*->scala::Predef.`???`().*/) - def this(t/*<-flags::p::package.C#``(+2).*//*<-flags::p::package.C#``(+2).(t)*/: T/*->flags::p::package.C#[T]*/) = this(t/*->flags::p::package.C#``(+2).(t)*/, ???/*->scala::Predef.`???`().*/, ???/*->scala::Predef.`???`().*/) + def this/*<-flags::p::package.C#``(+1).*/() = this(???/*->scala::Predef.`???`().*/, ???/*->scala::Predef.`???`().*/, ???/*->scala::Predef.`???`().*/) + def this/*<-flags::p::package.C#``(+2).*/(t/*<-flags::p::package.C#``(+2).(t)*/: T/*->flags::p::package.C#[T]*/) = this(t/*->flags::p::package.C#``(+2).(t)*/, ???/*->scala::Predef.`???`().*/, ???/*->scala::Predef.`???`().*/) def w/*<-flags::p::package.C#w().*/: Int/*->scala::Int#*/ } type T1/*<-flags::p::package.T1#*/ = Int/*->scala::Int#*/ diff --git a/tests/semanticdb/metac.expect b/tests/semanticdb/metac.expect index 3b33445d1eff..da2b53db0f32 100644 --- a/tests/semanticdb/metac.expect +++ b/tests/semanticdb/metac.expect @@ -252,7 +252,7 @@ Occurrences: [21:33..21:34): x <- annot/B#x. [21:36..21:39): Int -> scala/Int# [22:3..22:24): ConstructorAnnotation -> com/javacp/annot/ConstructorAnnotation# -[23:6..23:12): <- annot/B#``(+1). +[23:6..23:10): <- annot/B#``(+1). [23:20..23:20): -> annot/B#``(). [26:1..26:17): ObjectAnnotation -> com/javacp/annot/ObjectAnnotation# [27:7..27:8): M <- annot/M. @@ -701,7 +701,7 @@ Occurrences: [2:17..2:17): <- endmarkers/MultiCtor#``(). [2:22..2:23): i <- endmarkers/MultiCtor#i. [2:25..2:28): Int -> scala/Int# -[3:8..3:14): <- endmarkers/MultiCtor#``(+1). +[3:8..3:12): <- endmarkers/MultiCtor#``(+1). [4:11..4:11): -> endmarkers/MultiCtor#``(). [5:8..5:12): this -> endmarkers/MultiCtor#``(+1). [6:6..6:15): MultiCtor -> endmarkers/MultiCtor# @@ -3856,12 +3856,12 @@ Occurrences: [9:39..9:40): U -> flags/p/package.C#[U] [9:42..9:43): z <- flags/p/package.C#z. [9:45..9:46): V -> flags/p/package.C#[V] -[10:8..10:14): <- flags/p/package.C#``(+1). +[10:8..10:12): <- flags/p/package.C#``(+1). [10:22..10:22): -> flags/p/package.C#``(). [10:22..10:25): ??? -> scala/Predef.`???`(). [10:27..10:30): ??? -> scala/Predef.`???`(). [10:32..10:35): ??? -> scala/Predef.`???`(). -[11:8..11:14): <- flags/p/package.C#``(+2). +[11:8..11:12): <- flags/p/package.C#``(+2). [11:13..11:14): t <- flags/p/package.C#``(+2).(t) [11:16..11:17): T -> flags/p/package.C#[T] [11:26..11:26): -> flags/p/package.C#``(). From f0aa7a96c2add4802032efcbb64a0baaa7b5cd3e Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Tue, 1 Jun 2021 14:32:27 +0200 Subject: [PATCH 7/8] modify spans of statements with end markers --- .../src/dotty/tools/dotc/ast/Desugar.scala | 4 +- compiler/src/dotty/tools/dotc/ast/Trees.scala | 49 +++++++++++-------- .../dotty/tools/dotc/parsing/Parsers.scala | 18 ++++--- .../dotc/semanticdb/ExtractSemanticDB.scala | 2 +- 4 files changed, 42 insertions(+), 31 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 5d953140ce78..e774022f26ab 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -182,7 +182,7 @@ object desugar { tpt = TypeTree(defn.UnitType), rhs = setterRhs ).withMods((mods | Accessor) &~ (CaseAccessor | GivenOrImplicit | Lazy)) - .dropEndIndex() // the end marker should only appear on the getter definition + .dropEndMarker() // the end marker should only appear on the getter definition Thicket(vdef1, setter) } else vdef1 @@ -875,7 +875,6 @@ object desugar { val modul = ValDef(moduleName, clsRef, New(clsRef, Nil)) .withMods(mods.toTermFlags & RetainedModuleValFlags | ModuleValCreationFlags) .withSpan(mdef.span.startPos) - .withEndIndex(copyFrom = mdef) // copy over the end marker position to the module val val ValDef(selfName, selfTpt, _) = impl.self val selfMods = impl.self.mods if (!selfTpt.isEmpty) report.error(ObjectMayNotHaveSelfType(mdef), impl.self.srcPos) @@ -885,6 +884,7 @@ object desugar { val clsTmpl = cpy.Template(impl)(self = clsSelf, body = impl.body) val cls = TypeDef(clsName, clsTmpl) .withMods(mods.toTypeFlags & RetainedModuleClassFlags | ModuleClassCreationFlags) + .withEndMarker(copyFrom = mdef) // copy over the end marker position to the module class def Thicket(modul, classDef(cls).withSpan(mdef.span)) } } diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 6a0146241788..25b67921fc44 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -327,42 +327,51 @@ object Trees { extension (mdef: untpd.DefTree) def mods: untpd.Modifiers = mdef.rawMods - /** PackageDef | NamedDefTree */ - sealed trait WithEndMarker: - self: Attachment.Container => + sealed trait WithEndMarker[-T >: Untyped]: + self: PackageDef[T] | NamedDefTree[T] => import WithEndMarker.* final def endSpan(using Context): Span = - self.getAttachment(EndIndex) match - case Some(end) => - val realName = srcName.stripModuleClassSuffix.lastPart - Span(end - realName.length, end) - case none => NoSpan + if hasEndMarker then + val realName = srcName.stripModuleClassSuffix.lastPart + span.withStart(span.end - realName.length) + else + NoSpan + /** The name in source code that represents this construct, + * and is the name that the user must write to create a valid + * end marker. + * e.g. a constructor definition is terminated in the source + * code by `end this`, so it's `srcName` should return `this`. + */ protected def srcName(using Context): Name - final def withEndIndex(index: Int): self.type = - self.withAttachment(EndIndex, index) + final def withEndMarker(): self.type = + self.withAttachment(HasEndMarker, ()) - final def withEndIndex(copyFrom: WithEndMarker): self.type = - copyFrom.endIndex.foreach(withEndIndex) - this + final def withEndMarker(copyFrom: WithEndMarker[?]): self.type = + if copyFrom.hasEndMarker then + this.withEndMarker() + else + this - final def dropEndIndex(): self.type = - self.removeAttachment(EndIndex) + final def dropEndMarker(): self.type = + self.removeAttachment(HasEndMarker) this - protected def endIndex: Option[Int] = self.getAttachment(EndIndex) + protected def hasEndMarker: Boolean = self.hasAttachment(HasEndMarker) object WithEndMarker: - /** Property key for trees with an `end` marker */ - private val EndIndex: Property.StickyKey[Int] = Property.StickyKey() + /** Property key that signals the tree was terminated + * with an `end` marker in the source code + */ + private val HasEndMarker: Property.StickyKey[Unit] = Property.StickyKey() end WithEndMarker abstract class NamedDefTree[-T >: Untyped](implicit @constructorOnly src: SourceFile) - extends NameTree[T] with DefTree[T] with WithEndMarker { + extends NameTree[T] with DefTree[T] with WithEndMarker[T] { type ThisTree[-T >: Untyped] <: NamedDefTree[T] protected def srcName(using Context): Name = @@ -897,7 +906,7 @@ object Trees { /** package pid { stats } */ case class PackageDef[-T >: Untyped] private[ast] (pid: RefTree[T], stats: List[Tree[T]])(implicit @constructorOnly src: SourceFile) - extends ProxyTree[T] with WithEndMarker { + extends ProxyTree[T] with WithEndMarker[T] { type ThisTree[-T >: Untyped] = PackageDef[T] def forwardTo: RefTree[T] = pid protected def srcName(using Context): Name = pid.name diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 887621468ab7..0f3ae09d1879 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1275,7 +1275,13 @@ object Parsers { def checkEndMarker[T <: Tree](stats: ListBuffer[T]): Unit = - def matches(stat: Tree): Boolean = stat match + def updateSpanOfLast(last: T): Unit = + last match + case last: WithEndMarker[t] => last.withEndMarker() + case _ => + last.span = last.span.withEnd(in.lastCharOffset) + + def matches(stat: T): Boolean = stat match case stat: MemberDef if !stat.name.isEmpty => if stat.name == nme.CONSTRUCTOR then in.token == THIS else in.isIdent && in.name == stat.name.toTermName @@ -1293,14 +1299,10 @@ object Parsers { case _: (ForYield | ForDo) => in.token == FOR case _ => false - def matchesAndSetEnd(stat: Tree): Boolean = { - val didMatch = matches(stat) + def matchesAndSetEnd(last: T): Boolean = { + val didMatch = matches(last) if didMatch then - stat match - case stat: WithEndMarker => - stat.withEndIndex(index = in.lastCharOffset) - case _ => - () + updateSpanOfLast(last) didMatch } diff --git a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala index b97e1f3f8484..b233488b9a8c 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala @@ -240,7 +240,7 @@ class ExtractSemanticDB extends Phase: traverseChildren(tree) tree match - case tree: WithEndMarker => + case tree: WithEndMarker[t] => val endSpan = tree.endSpan if endSpan.exists then registerUseGuarded(None, tree.symbol, endSpan, tree.source) From c327d79104b6101a3f3a9535fa7103bd5f009442 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Tue, 1 Jun 2021 15:50:43 +0200 Subject: [PATCH 8/8] exclude top level wrapper objects set the Synthetic flag on top level wrapper objects. fixes #11693, top level definition wrapper objects no longer appear as a definition occurrence in semanticdb, but are still recorded as a symbol --- .../src/dotty/tools/dotc/ast/Desugar.scala | 4 ++- .../expect/AnonymousGiven.expect.scala | 2 +- .../semanticdb/expect/EndMarkers.expect.scala | 2 +- .../semanticdb/expect/Extension.expect.scala | 2 +- .../expect/InventedNames.expect.scala | 2 +- .../RightAssociativeExtension.expect.scala | 2 +- .../expect/exports-package.expect.scala | 2 +- tests/semanticdb/expect/i9727.expect.scala | 2 +- tests/semanticdb/expect/toplevel.expect.scala | 3 +- tests/semanticdb/expect/toplevel.scala | 1 + tests/semanticdb/metac.expect | 30 ++++++++----------- 11 files changed, 26 insertions(+), 26 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index e774022f26ab..af7a3b235717 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -1301,7 +1301,9 @@ object desugar { if (nestedStats.isEmpty) pdef else { val name = packageObjectName(ctx.source) - val grouped = ModuleDef(name, Template(emptyConstructor, Nil, Nil, EmptyValDef, nestedStats)) + val grouped = + ModuleDef(name, Template(emptyConstructor, Nil, Nil, EmptyValDef, nestedStats)) + .withMods(Modifiers(Synthetic)) cpy.PackageDef(pdef)(pdef.pid, topStats :+ grouped) } } diff --git a/tests/semanticdb/expect/AnonymousGiven.expect.scala b/tests/semanticdb/expect/AnonymousGiven.expect.scala index 68800202b6c1..c28b9d5e770d 100644 --- a/tests/semanticdb/expect/AnonymousGiven.expect.scala +++ b/tests/semanticdb/expect/AnonymousGiven.expect.scala @@ -2,4 +2,4 @@ package angiven trait Foo/*<-angiven::Foo#*/ -/*<-angiven::AnonymousGiven$package.*/def bar/*<-angiven::AnonymousGiven$package.bar().*/(using Foo/*->angiven::Foo#*/) = 42 \ No newline at end of file +def bar/*<-angiven::AnonymousGiven$package.bar().*/(using Foo/*->angiven::Foo#*/) = 42 \ No newline at end of file diff --git a/tests/semanticdb/expect/EndMarkers.expect.scala b/tests/semanticdb/expect/EndMarkers.expect.scala index d115bdf4c470..76d43a91127c 100644 --- a/tests/semanticdb/expect/EndMarkers.expect.scala +++ b/tests/semanticdb/expect/EndMarkers.expect.scala @@ -6,7 +6,7 @@ package endmarkers: end this/*->endmarkers::MultiCtor#``(+1).*/ end MultiCtor/*->endmarkers::MultiCtor#*/ - /*<-endmarkers::EndMarkers$package.*/def topLevelMethod/*<-endmarkers::EndMarkers$package.topLevelMethod().*/: String/*->scala::Predef.String#*/ = + def topLevelMethod/*<-endmarkers::EndMarkers$package.topLevelMethod().*/: String/*->scala::Predef.String#*/ = "hello" end topLevelMethod/*->endmarkers::EndMarkers$package.topLevelMethod().*/ diff --git a/tests/semanticdb/expect/Extension.expect.scala b/tests/semanticdb/expect/Extension.expect.scala index d96dcd4c87c8..536886368502 100644 --- a/tests/semanticdb/expect/Extension.expect.scala +++ b/tests/semanticdb/expect/Extension.expect.scala @@ -1,6 +1,6 @@ package ext -/*<-ext::Extension$package.*/extension (s/*<-ext::Extension$package.foo().(s)*//*<-ext::Extension$package.`#*#`().(s)*/: String/*->scala::Predef.String#*/) +extension (s/*<-ext::Extension$package.foo().(s)*//*<-ext::Extension$package.`#*#`().(s)*/: String/*->scala::Predef.String#*/) def foo/*<-ext::Extension$package.foo().*/: Int/*->scala::Int#*/ = 42 def #*#/*<-ext::Extension$package.`#*#`().*/ (i/*<-ext::Extension$package.`#*#`().(i)*/: Int/*->scala::Int#*/): (String/*->scala::Predef.String#*/, Int/*->scala::Int#*/) = (/*->scala::Tuple2.apply().*/s/*->ext::Extension$package.`#*#`().(s)*/, i/*->ext::Extension$package.`#*#`().(i)*/) diff --git a/tests/semanticdb/expect/InventedNames.expect.scala b/tests/semanticdb/expect/InventedNames.expect.scala index 5ff2f20213bd..f1ac3a4ae0cb 100644 --- a/tests/semanticdb/expect/InventedNames.expect.scala +++ b/tests/semanticdb/expect/InventedNames.expect.scala @@ -11,7 +11,7 @@ trait Z/*<-givens::Z#*/[T/*<-givens::Z#[T]*/]: -/*<-givens::InventedNames$package.*/given intValue/*<-givens::InventedNames$package.intValue.*/: Int/*->scala::Int#*/ = 4 +given intValue/*<-givens::InventedNames$package.intValue.*/: Int/*->scala::Int#*/ = 4 given /*<-givens::InventedNames$package.given_String.*/String/*->scala::Predef.String#*/ = "str" given /*<-givens::InventedNames$package.given_Double().*/(using Int/*->scala::Int#*/): Double/*->scala::Double#*/ = 4.0 given /*<-givens::InventedNames$package.given_List_T().*/[T/*<-givens::InventedNames$package.given_List_T().[T]*/]: List/*->scala::package.List#*/[T/*->givens::InventedNames$package.given_List_T().[T]*/] = Nil/*->scala::package.Nil.*/ diff --git a/tests/semanticdb/expect/RightAssociativeExtension.expect.scala b/tests/semanticdb/expect/RightAssociativeExtension.expect.scala index 38f81d0154ef..c32fd1becfda 100644 --- a/tests/semanticdb/expect/RightAssociativeExtension.expect.scala +++ b/tests/semanticdb/expect/RightAssociativeExtension.expect.scala @@ -1,6 +1,6 @@ package ext -/*<-ext::RightAssociativeExtension$package.*/extension (s/*<-ext::RightAssociativeExtension$package.`:*:`().(s)*/: String/*->scala::Predef.String#*/) +extension (s/*<-ext::RightAssociativeExtension$package.`:*:`().(s)*/: String/*->scala::Predef.String#*/) def :*:/*<-ext::RightAssociativeExtension$package.`:*:`().*/ (i/*<-ext::RightAssociativeExtension$package.`:*:`().(i)*/: Int/*->scala::Int#*/): (String/*->scala::Predef.String#*/, Int/*->scala::Int#*/) = (/*->scala::Tuple2.apply().*/s/*->ext::RightAssociativeExtension$package.`:*:`().(s)*/, i/*->ext::RightAssociativeExtension$package.`:*:`().(i)*/) val b/*<-ext::RightAssociativeExtension$package.b.*/ = "foo" :*:/*->ext::RightAssociativeExtension$package.`:*:`().*/ 23 \ No newline at end of file diff --git a/tests/semanticdb/expect/exports-package.expect.scala b/tests/semanticdb/expect/exports-package.expect.scala index 79c0f5b16e53..512b68dcc842 100644 --- a/tests/semanticdb/expect/exports-package.expect.scala +++ b/tests/semanticdb/expect/exports-package.expect.scala @@ -1,3 +1,3 @@ package exports -/*<-exports::`exports-package$package`.*/export example.{Decoder/*<-exports::`exports-package$package`.Decoder#*/, Encoder/*<-exports::`exports-package$package`.Encoder#*/, Codec/*<-exports::`exports-package$package`.Codec#*/} +export example.{Decoder/*<-exports::`exports-package$package`.Decoder#*/, Encoder/*<-exports::`exports-package$package`.Encoder#*/, Codec/*<-exports::`exports-package$package`.Codec#*/} diff --git a/tests/semanticdb/expect/i9727.expect.scala b/tests/semanticdb/expect/i9727.expect.scala index 017da086d4b5..4cbe6761906f 100644 --- a/tests/semanticdb/expect/i9727.expect.scala +++ b/tests/semanticdb/expect/i9727.expect.scala @@ -1,5 +1,5 @@ package i9727 class Test/*<-i9727::Test#*/(a/*<-i9727::Test#a.*/: Int/*->scala::Int#*/) -/*<-i9727::i9727$package.*/val a/*<-i9727::i9727$package.a.*/ = new Test/*->i9727::Test#*/(1) +val a/*<-i9727::i9727$package.a.*/ = new Test/*->i9727::Test#*/(1) val b/*<-i9727::i9727$package.b.*/ = new Test/*->i9727::Test#*/(2) diff --git a/tests/semanticdb/expect/toplevel.expect.scala b/tests/semanticdb/expect/toplevel.expect.scala index a856d673e68c..dfb0cc5de508 100644 --- a/tests/semanticdb/expect/toplevel.expect.scala +++ b/tests/semanticdb/expect/toplevel.expect.scala @@ -1,6 +1,7 @@ -/*<-_empty_::toplevel$package.*/inline val a/*<-_empty_::toplevel$package.a.*/ = "" +inline val a/*<-_empty_::toplevel$package.a.*/ = "" extension (x/*<-_empty_::toplevel$package.combine().(x)*/: Int/*->scala::Int#*/) def combine/*<-_empty_::toplevel$package.combine().*/ (y/*<-_empty_::toplevel$package.combine().(y)*/: Int/*->scala::Int#*/) = x/*->_empty_::toplevel$package.combine().(x)*/ +/*->scala::Int#`+`(+4).*/ y/*->_empty_::toplevel$package.combine().(y)*/ def combine/*<-_empty_::toplevel$package.combine(+1).*/(x/*<-_empty_::toplevel$package.combine(+1).(x)*/: Int/*->scala::Int#*/, y/*<-_empty_::toplevel$package.combine(+1).(y)*/: Int/*->scala::Int#*/, z/*<-_empty_::toplevel$package.combine(+1).(z)*/: Int/*->scala::Int#*/) = x/*->_empty_::toplevel$package.combine(+1).(x)*/ +/*->scala::Int#`+`(+4).*/ y/*->_empty_::toplevel$package.combine(+1).(y)*/ +/*->scala::Int#`+`(+4).*/ z/*->_empty_::toplevel$package.combine(+1).(z)*/ def combine/*<-_empty_::toplevel$package.combine(+2).*/ = 0 def foo/*<-_empty_::toplevel$package.foo().*/ = "foo" /*<-_empty_::MyProgram#*//*->_empty_::toplevel$package.MyProgram().*//*->scala::util::CommandLineParser.parseArgument().*//*->_empty_::MyProgram#main().(args)*//*->scala::util::CommandLineParser.FromString.given_FromString_Int.*//*->scala::util::CommandLineParser.showError().*//*->local0*/@main/*->scala::main#*/ def MyProgram/*<-_empty_::toplevel$package.MyProgram().*/(times/*<-_empty_::toplevel$package.MyProgram().(times)*/: Int/*->scala::Int#*/): Unit/*->scala::Unit#*/ = (/*->scala::LowPriorityImplicits#intWrapper().*/1 to/*->scala::runtime::RichInt#to().*/ times/*->_empty_::toplevel$package.MyProgram().(times)*/) foreach/*->scala::collection::immutable::Range#foreach().*/ (_ => println/*->scala::Predef.println(+1).*/("hello")) +def fooRef/*<-_empty_::toplevel$package.fooRef().*/ = toplevel$package/*->_empty_::toplevel$package.*/.foo/*->_empty_::toplevel$package.foo().*/ diff --git a/tests/semanticdb/expect/toplevel.scala b/tests/semanticdb/expect/toplevel.scala index 5dae4ccadd5e..e6af17e14953 100644 --- a/tests/semanticdb/expect/toplevel.scala +++ b/tests/semanticdb/expect/toplevel.scala @@ -4,3 +4,4 @@ def combine(x: Int, y: Int, z: Int) = x + y + z def combine = 0 def foo = "foo" @main def MyProgram(times: Int): Unit = (1 to times) foreach (_ => println("hello")) +def fooRef = toplevel$package.foo diff --git a/tests/semanticdb/metac.expect b/tests/semanticdb/metac.expect index da2b53db0f32..00ed8c849766 100644 --- a/tests/semanticdb/metac.expect +++ b/tests/semanticdb/metac.expect @@ -338,7 +338,7 @@ Uri => AnonymousGiven.scala Text => empty Language => Scala Symbols => 5 entries -Occurrences => 6 entries +Occurrences => 5 entries Symbols: angiven/AnonymousGiven$package. => final package object angiven @@ -351,7 +351,6 @@ Occurrences: [0:8..0:15): angiven <- angiven/ [2:0..2:0): <- angiven/Foo#``(). [2:6..2:9): Foo <- angiven/Foo# -[4:0..4:0): <- angiven/AnonymousGiven$package. [4:4..4:7): bar <- angiven/AnonymousGiven$package.bar(). [4:14..4:17): Foo -> angiven/Foo# @@ -667,7 +666,7 @@ Uri => EndMarkers.scala Text => empty Language => Scala Symbols => 24 entries -Occurrences => 43 entries +Occurrences => 42 entries Symbols: endmarkers/Container# => class Container @@ -705,7 +704,6 @@ Occurrences: [4:11..4:11): -> endmarkers/MultiCtor#``(). [5:8..5:12): this -> endmarkers/MultiCtor#``(+1). [6:6..6:15): MultiCtor -> endmarkers/MultiCtor# -[8:2..8:2): <- endmarkers/EndMarkers$package. [8:6..8:20): topLevelMethod <- endmarkers/EndMarkers$package.topLevelMethod(). [8:22..8:28): String -> scala/Predef.String# [10:6..10:20): topLevelMethod -> endmarkers/EndMarkers$package.topLevelMethod(). @@ -1278,7 +1276,7 @@ Uri => Extension.scala Text => empty Language => Scala Symbols => 8 entries -Occurrences => 19 entries +Occurrences => 18 entries Symbols: ext/Extension$package. => final package object ext @@ -1292,7 +1290,6 @@ ext/Extension$package.foo().(s) => param s Occurrences: [0:8..0:11): ext <- ext/ -[2:0..2:0): <- ext/Extension$package. [2:11..2:12): s <- ext/Extension$package.foo().(s) [2:11..2:12): s <- ext/Extension$package.`#*#`().(s) [2:14..2:20): String -> scala/Predef.String# @@ -1747,7 +1744,7 @@ Uri => InventedNames.scala Text => empty Language => Scala Symbols => 45 entries -Occurrences => 73 entries +Occurrences => 72 entries Symbols: givens/InventedNames$package. => final package object givens @@ -1812,7 +1809,6 @@ Occurrences: [9:6..9:9): doZ <- givens/Z#doZ(). [9:11..9:15): List -> scala/package.List# [9:16..9:17): T -> givens/Z#[T] -[13:0..13:0): <- givens/InventedNames$package. [13:6..13:14): intValue <- givens/InventedNames$package.intValue. [13:16..13:19): Int -> scala/Int# [14:6..14:6): <- givens/InventedNames$package.given_String. @@ -2731,7 +2727,7 @@ Uri => RightAssociativeExtension.scala Text => empty Language => Scala Symbols => 5 entries -Occurrences => 14 entries +Occurrences => 13 entries Symbols: ext/RightAssociativeExtension$package. => final package object ext @@ -2742,7 +2738,6 @@ ext/RightAssociativeExtension$package.b. => val method b Occurrences: [0:8..0:11): ext <- ext/ -[2:0..2:0): <- ext/RightAssociativeExtension$package. [2:11..2:12): s <- ext/RightAssociativeExtension$package.`:*:`().(s) [2:14..2:20): String -> scala/Predef.String# [3:6..3:9): :*: <- ext/RightAssociativeExtension$package.`:*:`(). @@ -3471,7 +3466,7 @@ Uri => exports-package.scala Text => empty Language => Scala Symbols => 4 entries -Occurrences => 6 entries +Occurrences => 5 entries Symbols: exports/`exports-package$package`. => final package object exports @@ -3481,7 +3476,6 @@ exports/`exports-package$package`.Encoder# => final type Encoder Occurrences: [0:8..0:15): exports <- exports/ -[2:0..2:0): <- exports/`exports-package$package`. [2:7..2:14): example -> exports/example/ [2:16..2:23): Decoder <- exports/`exports-package$package`.Decoder# [2:25..2:32): Encoder <- exports/`exports-package$package`.Encoder# @@ -3516,7 +3510,7 @@ Uri => i9727.scala Text => empty Language => Scala Symbols => 7 entries -Occurrences => 12 entries +Occurrences => 11 entries Symbols: i9727/Test# => class Test @@ -3533,7 +3527,6 @@ Occurrences: [2:10..2:10): <- i9727/Test#``(). [2:11..2:12): a <- i9727/Test#a. [2:14..2:17): Int -> scala/Int# -[3:0..3:0): <- i9727/i9727$package. [3:4..3:5): a <- i9727/i9727$package.a. [3:12..3:16): Test -> i9727/Test# [3:16..3:16): -> i9727/Test#``(). @@ -4381,8 +4374,8 @@ Schema => SemanticDB v4 Uri => toplevel.scala Text => empty Language => Scala -Symbols => 18 entries -Occurrences => 42 entries +Symbols => 19 entries +Occurrences => 44 entries Symbols: _empty_/MyProgram# => final class MyProgram @@ -4402,10 +4395,10 @@ _empty_/toplevel$package.combine(+1).(y) => param y _empty_/toplevel$package.combine(+1).(z) => param z _empty_/toplevel$package.combine(+2). => method combine _empty_/toplevel$package.foo(). => method foo +_empty_/toplevel$package.fooRef(). => method fooRef local0 => val local error Occurrences: -[0:0..0:0): <- _empty_/toplevel$package. [0:11..0:12): a <- _empty_/toplevel$package.a. [1:11..1:12): x <- _empty_/toplevel$package.combine().(x) [1:14..1:17): Int -> scala/Int# @@ -4447,4 +4440,7 @@ Occurrences: [5:46..5:51): times -> _empty_/toplevel$package.MyProgram().(times) [5:53..5:60): foreach -> scala/collection/immutable/Range#foreach(). [5:67..5:74): println -> scala/Predef.println(+1). +[6:4..6:10): fooRef <- _empty_/toplevel$package.fooRef(). +[6:13..6:29): toplevel$package -> _empty_/toplevel$package. +[6:30..6:33): foo -> _empty_/toplevel$package.foo().