From 86bd57dae37b9433feb43428b7f9e900907b6c9f Mon Sep 17 00:00:00 2001 From: bishabosha Date: Wed, 13 May 2020 11:52:36 +0200 Subject: [PATCH 01/11] fix #8954 use tree source, look inside byname arguments --- .../dotc/semanticdb/ExtractSemanticDB.scala | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala index 9fb93842423f..1e40e4c3b3a4 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala @@ -114,8 +114,10 @@ class ExtractSemanticDB extends Phase: override def traverse(tree: Tree)(using Context): Unit = - inline def traverseCtorParamTpt(ctorSym: Symbol, tpt: Tree): Unit = - val tptSym = tpt.symbol + def traverseCtorParamTpt(ctorSym: Symbol, tpt: Tree)(using Context): Unit = + val tptSym = tpt match + case ByNameTypeTree(tpt) => tpt.symbol + case tpt => tpt.symbol if tptSym.owner == ctorSym val found = matchingMemberType(tptSym, ctorSym.owner) if tpt.span.hasLength @@ -131,7 +133,7 @@ class ExtractSemanticDB extends Phase: && tree.pid.span.hasLength tree.pid match case tree @ Select(qual, name) => - registerDefinition(tree.symbol, adjustSpanToName(tree.span, qual.span, name), Set.empty) + registerDefinition(tree.symbol, adjustSpanToName(tree.span, qual.span, name, tree.source), Set.empty) traverse(qual) case tree => registerDefinition(tree.symbol, tree.span, Set.empty) tree.stats.foreach(traverse) @@ -206,7 +208,7 @@ class ExtractSemanticDB extends Phase: val lhs = tree.lhs.symbol val setter = lhs.matchingSetter.orElse(lhs) tree.lhs match - case tree @ Select(qual, name) => registerUse(setter, adjustSpanToName(tree.span, qual.span, name)) + case tree @ Select(qual, name) => registerUse(setter, adjustSpanToName(tree.span, qual.span, name, tree.source)) case tree => registerUse(setter, tree.span) traverseChildren(tree.lhs) traverse(tree.rhs) @@ -217,7 +219,7 @@ class ExtractSemanticDB extends Phase: case tree: Select => val qualSpan = tree.qualifier.span val sym = tree.symbol.adjustIfCtorTyparam - registerUseGuarded(tree.qualifier.symbol.ifExists, sym, adjustSpanToName(tree.span, qualSpan, tree.name)) + registerUseGuarded(tree.qualifier.symbol.ifExists, sym, adjustSpanToName(tree.span, qualSpan, tree.name, tree.source)) if qualSpan.exists && qualSpan.hasLength then traverse(tree.qualifier) case tree: Import => @@ -502,7 +504,7 @@ class ExtractSemanticDB extends Phase: }).toMap end findGetters - private def adjustSpanToName(span: Span, qualSpan: Span, name: Name)(using Context) = + private def adjustSpanToName(span: Span, qualSpan: Span, name: Name, source: SourceFile) = val end = span.end val limit = qualSpan.end val start = @@ -559,8 +561,8 @@ class ExtractSemanticDB extends Phase: case _ => symkinds.toSet - private inline def ctorParams( - vparamss: List[List[ValDef]], body: List[Tree])(traverseTpt: => Tree => Unit)(using Context): Unit = + private def ctorParams( + vparamss: List[List[ValDef]], body: List[Tree])(traverseTpt: Tree => Unit)(using Context): Unit = @tu lazy val getters = findGetters(vparamss.flatMap(_.map(_.name)).toSet, body) for vparams <- vparamss From 0a369f4793c96640e7b38e27a4ebd9a25f6ff409 Mon Sep 17 00:00:00 2001 From: bishabosha Date: Wed, 13 May 2020 15:17:03 +0200 Subject: [PATCH 02/11] add regression tests --- compiler/test/dotty/tools/dotc/CompilationTests.scala | 1 + tests/pos-custom-args/semanticdb/ctorByName.scala | 3 +++ .../semanticdb/macro-pos/example_1.scala | 5 +++++ .../semanticdb/macro-pos/example_2.scala | 10 ++++++++++ .../semanticdb/macro-pos/example_3.scala | 5 +++++ 5 files changed, 24 insertions(+) create mode 100644 tests/pos-custom-args/semanticdb/ctorByName.scala create mode 100644 tests/pos-custom-args/semanticdb/macro-pos/example_1.scala create mode 100644 tests/pos-custom-args/semanticdb/macro-pos/example_2.scala create mode 100644 tests/pos-custom-args/semanticdb/macro-pos/example_3.scala diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index d18ee5be5d41..ae3316c35d2e 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -49,6 +49,7 @@ class CompilationTests extends ParallelTesting { compileFilesInDir("tests/new", defaultOptions), compileFilesInDir("tests/pos-scala2", scala2CompatMode), compileFilesInDir("tests/pos-custom-args/erased", defaultOptions.and("-Yerased-terms")), + compileFilesInDir("tests/pos-custom-args/semanticdb", defaultOptions.and("-Ysemanticdb")), compileFilesInDir("tests/pos", defaultOptions), compileFilesInDir("tests/pos-deep-subtype", allowDeepSubtypes), compileFile( diff --git a/tests/pos-custom-args/semanticdb/ctorByName.scala b/tests/pos-custom-args/semanticdb/ctorByName.scala new file mode 100644 index 000000000000..e76e55c60e1b --- /dev/null +++ b/tests/pos-custom-args/semanticdb/ctorByName.scala @@ -0,0 +1,3 @@ +object Macro { + class StringContextOps(sc: => StringContext) +} diff --git a/tests/pos-custom-args/semanticdb/macro-pos/example_1.scala b/tests/pos-custom-args/semanticdb/macro-pos/example_1.scala new file mode 100644 index 000000000000..340cd14c1d49 --- /dev/null +++ b/tests/pos-custom-args/semanticdb/macro-pos/example_1.scala @@ -0,0 +1,5 @@ +import quoted._ + +object CodeImpl { + def codeExpr(using qctx: QuoteContext): Expr[String] = '{""} +} diff --git a/tests/pos-custom-args/semanticdb/macro-pos/example_2.scala b/tests/pos-custom-args/semanticdb/macro-pos/example_2.scala new file mode 100644 index 000000000000..2273d60a54d4 --- /dev/null +++ b/tests/pos-custom-args/semanticdb/macro-pos/example_2.scala @@ -0,0 +1,10 @@ +import quoted._ + +object TestImpl { + transparent inline def fun (inline arg: String): String = + /* + Pad out the file + Lorem ipsum dolor sit amet consectetur adipiscing elit tincidunt id augue, facilisi dignissim nibh litora lectus quam senectus fringilla molestie sollicitudin, nunc ullamcorper auctor turpis integer netus fermentum mattis magna. Nullam potenti diam tellus bibendum odio tristique felis, pharetra posuere at imperdiet suspendisse aenean, eu lobortis sapien eleifend aptent sociosqu. + */ + ${ CodeImpl.codeExpr } +} diff --git a/tests/pos-custom-args/semanticdb/macro-pos/example_3.scala b/tests/pos-custom-args/semanticdb/macro-pos/example_3.scala new file mode 100644 index 000000000000..2c2223b59860 --- /dev/null +++ b/tests/pos-custom-args/semanticdb/macro-pos/example_3.scala @@ -0,0 +1,5 @@ +object Test { + + def test = TestImpl.fun("") + +} From 51ce9bbf1a1bd03e980c7d2092d5d91e2405c324 Mon Sep 17 00:00:00 2001 From: bishabosha Date: Thu, 14 May 2020 11:23:48 +0200 Subject: [PATCH 03/11] traverse annots once per definition symbol --- .../dotc/semanticdb/ExtractSemanticDB.scala | 27 ++++++++++++------ .../tools/vulpix/TestConfiguration.scala | 1 + .../semanticdb/recursiveAnnotResolve.scala | 28 +++++++++++++++++++ 3 files changed, 47 insertions(+), 9 deletions(-) create mode 100644 tests/pos-custom-args/semanticdb/recursiveAnnotResolve.scala diff --git a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala index 1e40e4c3b3a4..40b7b146aa99 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala @@ -72,6 +72,8 @@ class ExtractSemanticDB extends Phase: /** The symbol occurrences generated so far, as a set */ private val generated = new mutable.HashSet[SymbolOccurrence] + private val anotatedSymbols = new mutable.HashSet[Symbol] + /** Definitions of this symbol should be excluded from semanticdb */ private def excludeDef(sym: Symbol)(using Context): Boolean = !sym.exists @@ -104,13 +106,15 @@ class ExtractSemanticDB extends Phase: || sym == defn.Any_typeCast || qualifier.exists(excludeQual) - private def traverseAnnotsOf(sym: Symbol)(using Context): Unit = - for annot <- sym.annotations do - if annot.tree.span.exists - && annot.tree.span.hasLength - annot.tree match - case tree: Typed => () // hack for inline code - case tree => traverse(tree) + private def traverseAnnotsOfDefinition(sym: Symbol)(using Context): Unit = + if (!anotatedSymbols.contains(sym)) then + anotatedSymbols += sym + for annot <- sym.annotations do + if annot.tree.span.exists + && annot.tree.span.hasLength + annot.tree match + case tree: Typed => () // hack for inline code + case tree => traverse(tree) override def traverse(tree: Tree)(using Context): Unit = @@ -125,7 +129,11 @@ class ExtractSemanticDB extends Phase: else traverse(tpt) - traverseAnnotsOf(tree.symbol) + tree match + case tree: DefTree if tree.symbol.exists => + traverseAnnotsOfDefinition(tree.symbol) + case _ => + () tree match case tree: PackageDef => @@ -182,6 +190,7 @@ class ExtractSemanticDB extends Phase: case tree: Template => val ctorSym = tree.constr.symbol if !excludeDef(ctorSym) + traverseAnnotsOfDefinition(ctorSym) registerDefinition(ctorSym, tree.constr.span, Set.empty) ctorParams(tree.constr.vparamss, tree.body)(traverseCtorParamTpt(ctorSym, _)) for parent <- tree.parentsOrDerived if parent.span.hasLength do @@ -568,8 +577,8 @@ class ExtractSemanticDB extends Phase: vparams <- vparamss vparam <- vparams do - traverseAnnotsOf(vparam.symbol) if !excludeSymbol(vparam.symbol) + traverseAnnotsOfDefinition(vparam.symbol) val symkinds = getters.get(vparam.name).fold(SymbolKind.emptySet)(getter => if getter.mods.is(Mutable) then SymbolKind.VarSet else SymbolKind.ValSet) diff --git a/compiler/test/dotty/tools/vulpix/TestConfiguration.scala b/compiler/test/dotty/tools/vulpix/TestConfiguration.scala index bb04e418a59b..948d184afb0a 100644 --- a/compiler/test/dotty/tools/vulpix/TestConfiguration.scala +++ b/compiler/test/dotty/tools/vulpix/TestConfiguration.scala @@ -16,6 +16,7 @@ object TestConfiguration { "-Yno-deep-subtypes", "-Yno-double-bindings", "-Yforce-sbt-phases", + // "-Ysemanticdb", "-Xverify-signatures" ) diff --git a/tests/pos-custom-args/semanticdb/recursiveAnnotResolve.scala b/tests/pos-custom-args/semanticdb/recursiveAnnotResolve.scala new file mode 100644 index 000000000000..ed7c1e7a3a5b --- /dev/null +++ b/tests/pos-custom-args/semanticdb/recursiveAnnotResolve.scala @@ -0,0 +1,28 @@ +trait Reporter: + def report(m: String): Unit + +class Dummy extends Reporter: + def report(m: String) = () + + object ABug { + sealed trait Nat { + inline def ++ : Succ[this.type] = Succ(this) + + transparent inline def +(inline that: Nat): Nat = + inline this match { + case Zero => that + case Succ(p) => p + that.++ + } + } + + case object Zero extends Nat + case class Succ[N <: Nat](p: N) extends Nat + + transparent inline def toIntg(inline n: Nat): Int = + inline n match { + case Zero => 0 + case Succ(p) => toIntg(p) + 1 + } + + val j31 = toIntg(Zero.++.++.++ + Zero.++) + } From 1c67d793baa1aae903feca1af107800053d0fd6f Mon Sep 17 00:00:00 2001 From: bishabosha Date: Thu, 14 May 2020 12:26:08 +0200 Subject: [PATCH 04/11] fix literal type in ctor, move tests --- .../dotc/semanticdb/ExtractSemanticDB.scala | 33 +- .../semanticdb/ctorByName.scala | 3 - .../semanticdb/recursiveAnnotResolve.scala | 28 - tests/semanticdb/expect/Classes.expect.scala | 2 + tests/semanticdb/expect/Classes.scala | 2 + tests/semanticdb/expect/Enums.expect.scala | 4 +- tests/semanticdb/expect/Enums.scala | 4 +- .../semanticdb/expect/recursion.expect.scala | 25 + tests/semanticdb/expect/recursion.scala | 25 + .../expect/semanticdb-Types.expect.scala | 7 + .../semanticdb/expect/semanticdb-Types.scala | 7 + tests/semanticdb/metac.expect | 563 +++++++++++------- 12 files changed, 431 insertions(+), 272 deletions(-) delete mode 100644 tests/pos-custom-args/semanticdb/ctorByName.scala delete mode 100644 tests/pos-custom-args/semanticdb/recursiveAnnotResolve.scala create mode 100644 tests/semanticdb/expect/recursion.expect.scala create mode 100644 tests/semanticdb/expect/recursion.scala diff --git a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala index 40b7b146aa99..f7df4f39af7d 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala @@ -72,8 +72,6 @@ class ExtractSemanticDB extends Phase: /** The symbol occurrences generated so far, as a set */ private val generated = new mutable.HashSet[SymbolOccurrence] - private val anotatedSymbols = new mutable.HashSet[Symbol] - /** Definitions of this symbol should be excluded from semanticdb */ private def excludeDef(sym: Symbol)(using Context): Boolean = !sym.exists @@ -107,28 +105,15 @@ class ExtractSemanticDB extends Phase: || qualifier.exists(excludeQual) private def traverseAnnotsOfDefinition(sym: Symbol)(using Context): Unit = - if (!anotatedSymbols.contains(sym)) then - anotatedSymbols += sym - for annot <- sym.annotations do - if annot.tree.span.exists - && annot.tree.span.hasLength - annot.tree match - case tree: Typed => () // hack for inline code - case tree => traverse(tree) + for annot <- sym.annotations do + if annot.tree.span.exists + && annot.tree.span.hasLength + annot.tree match + case tree: Typed => () // hack for inline code + case tree => traverse(tree) override def traverse(tree: Tree)(using Context): Unit = - def traverseCtorParamTpt(ctorSym: Symbol, tpt: Tree)(using Context): Unit = - val tptSym = tpt match - case ByNameTypeTree(tpt) => tpt.symbol - case tpt => tpt.symbol - if tptSym.owner == ctorSym - val found = matchingMemberType(tptSym, ctorSym.owner) - if tpt.span.hasLength - registerUseGuarded(None, found, tpt.span) - else - traverse(tpt) - tree match case tree: DefTree if tree.symbol.exists => traverseAnnotsOfDefinition(tree.symbol) @@ -192,7 +177,7 @@ class ExtractSemanticDB extends Phase: if !excludeDef(ctorSym) traverseAnnotsOfDefinition(ctorSym) registerDefinition(ctorSym, tree.constr.span, Set.empty) - ctorParams(tree.constr.vparamss, tree.body)(traverseCtorParamTpt(ctorSym, _)) + ctorParams(tree.constr.vparamss, tree.body) for parent <- tree.parentsOrDerived if parent.span.hasLength do traverse(parent) val selfSpan = tree.self.span @@ -571,7 +556,7 @@ class ExtractSemanticDB extends Phase: symkinds.toSet private def ctorParams( - vparamss: List[List[ValDef]], body: List[Tree])(traverseTpt: Tree => Unit)(using Context): Unit = + vparamss: List[List[ValDef]], body: List[Tree])(using Context): Unit = @tu lazy val getters = findGetters(vparamss.flatMap(_.map(_.name)).toSet, body) for vparams <- vparamss @@ -583,7 +568,7 @@ class ExtractSemanticDB extends Phase: getters.get(vparam.name).fold(SymbolKind.emptySet)(getter => if getter.mods.is(Mutable) then SymbolKind.VarSet else SymbolKind.ValSet) registerSymbol(vparam.symbol, symbolName(vparam.symbol), symkinds) - traverseTpt(vparam.tpt) + traverse(vparam.tpt) object ExtractSemanticDB: import java.nio.file.Path diff --git a/tests/pos-custom-args/semanticdb/ctorByName.scala b/tests/pos-custom-args/semanticdb/ctorByName.scala deleted file mode 100644 index e76e55c60e1b..000000000000 --- a/tests/pos-custom-args/semanticdb/ctorByName.scala +++ /dev/null @@ -1,3 +0,0 @@ -object Macro { - class StringContextOps(sc: => StringContext) -} diff --git a/tests/pos-custom-args/semanticdb/recursiveAnnotResolve.scala b/tests/pos-custom-args/semanticdb/recursiveAnnotResolve.scala deleted file mode 100644 index ed7c1e7a3a5b..000000000000 --- a/tests/pos-custom-args/semanticdb/recursiveAnnotResolve.scala +++ /dev/null @@ -1,28 +0,0 @@ -trait Reporter: - def report(m: String): Unit - -class Dummy extends Reporter: - def report(m: String) = () - - object ABug { - sealed trait Nat { - inline def ++ : Succ[this.type] = Succ(this) - - transparent inline def +(inline that: Nat): Nat = - inline this match { - case Zero => that - case Succ(p) => p + that.++ - } - } - - case object Zero extends Nat - case class Succ[N <: Nat](p: N) extends Nat - - transparent inline def toIntg(inline n: Nat): Int = - inline n match { - case Zero => 0 - case Succ(p) => toIntg(p) + 1 - } - - val j31 = toIntg(Zero.++.++.++ + Zero.++) - } diff --git a/tests/semanticdb/expect/Classes.expect.scala b/tests/semanticdb/expect/Classes.expect.scala index c7418107c372..34022c5ba6a2 100644 --- a/tests/semanticdb/expect/Classes.expect.scala +++ b/tests/semanticdb/expect/Classes.expect.scala @@ -22,6 +22,8 @@ class C8/*<-classes::C8#*/(private[this] val x/*<-classes::C8#x.*/: Int/*->scala class C9/*<-classes::C9#*/(private[this] var x/*<-classes::C9#x().*/: Int/*->scala::Int#*/) +class C10/*<-classes::C10#*/(s/*<-classes::C10#s.*/: => String/*->scala::Predef.String#*/) + object N/*<-classes::N.*/ { val anonClass/*<-classes::N.anonClass.*/ = new C7/*->classes::C7#*/(42) { val local/*<-local1*/ = ???/*->scala::Predef.`???`().*/ diff --git a/tests/semanticdb/expect/Classes.scala b/tests/semanticdb/expect/Classes.scala index a1cfbbd9aee1..5d1d5efc4f4c 100644 --- a/tests/semanticdb/expect/Classes.scala +++ b/tests/semanticdb/expect/Classes.scala @@ -22,6 +22,8 @@ class C8(private[this] val x: Int) class C9(private[this] var x: Int) +class C10(s: => String) + object N { val anonClass = new C7(42) { val local = ??? diff --git a/tests/semanticdb/expect/Enums.expect.scala b/tests/semanticdb/expect/Enums.expect.scala index 6b7665bce7f8..34a4a406425d 100644 --- a/tests/semanticdb/expect/Enums.expect.scala +++ b/tests/semanticdb/expect/Enums.expect.scala @@ -16,8 +16,8 @@ object Enums/*<-_empty_::Enums.*/: suit/*->_empty_::Enums.Suits.isRed().(suit)*/ ==/*->scala::Any#`==`().*/ Hearts/*->_empty_::Enums.Suits.Hearts.*/ ||/*->scala::Boolean#`||`().*/ suit/*->_empty_::Enums.Suits.isRed().(suit)*/ ==/*->scala::Any#`==`().*/ Diamonds/*->_empty_::Enums.Suits.Diamonds.*/ def (suit: /*<-_empty_::Enums.Suits.isBlack().*//*<-_empty_::Enums.Suits.isBlack().(suit)*/Suits/*->_empty_::Enums.Suits#*/).isBlack: Boolean/*->scala::Boolean#*/ = suit/*->_empty_::Enums.Suits.isBlack().(suit)*/ match - case Spades/*->_empty_::Enums.Suits.Spades.*/ | Diamonds/*->_empty_::Enums.Suits.Diamonds.*/ => true - case _ => false + case Spades/*->_empty_::Enums.Suits.Spades.*/ | Clubs/*->_empty_::Enums.Suits.Clubs.*/ => true + case _ => false enum WeekDays/*<-_empty_::Enums.WeekDays#*/: case Monday/*<-_empty_::Enums.WeekDays.Monday.*/ diff --git a/tests/semanticdb/expect/Enums.scala b/tests/semanticdb/expect/Enums.scala index b93bc164c7bf..d32b8823c98f 100644 --- a/tests/semanticdb/expect/Enums.scala +++ b/tests/semanticdb/expect/Enums.scala @@ -16,8 +16,8 @@ object Enums: suit == Hearts || suit == Diamonds def (suit: Suits).isBlack: Boolean = suit match - case Spades | Diamonds => true - case _ => false + case Spades | Clubs => true + case _ => false enum WeekDays: case Monday diff --git a/tests/semanticdb/expect/recursion.expect.scala b/tests/semanticdb/expect/recursion.expect.scala new file mode 100644 index 000000000000..a576eca7a443 --- /dev/null +++ b/tests/semanticdb/expect/recursion.expect.scala @@ -0,0 +1,25 @@ +// semanticdb traversal of annotations of Nat caused an infinite loop +package recursion + +object Nats/*<-recursion::Nats.*/ { + sealed trait Nat/*<-recursion::Nats.Nat#*/ { + inline def ++/*<-recursion::Nats.Nat#`++`().*/ : Succ/*->recursion::Nats.Succ#*/[this.type] = Succ/*->recursion::Nats.Succ.*//*->recursion::Nats.Succ.apply().*/(this) + + transparent inline def +/*<-recursion::Nats.Nat#`+`().*/(inline that/*<-recursion::Nats.Nat#`+`().(that)*/: Nat/*->recursion::Nats.Nat#*/): Nat/*->recursion::Nats.Nat#*/ = + inline this match { + case Zero/*->recursion::Nats.Zero.*/ => that/*->recursion::Nats.Nat#`+`().(that)*/ + case Succ/*->recursion::Nats.Succ.*//*->recursion::Nats.Succ.unapply().*//*->local0*/(p/*<-local1*/) => p/*->local1*/ +/*->recursion::Nats.Nat#`+`().*/ that/*->recursion::Nats.Nat#`+`().(that)*/.++/*->recursion::Nats.Nat#`++`().*/ + } + } + + case object Zero/*<-recursion::Nats.Zero.*/ extends Nat/*->recursion::Nats.Nat#*/ + case class Succ/*<-recursion::Nats.Succ#*/[N/*<-recursion::Nats.Succ#[N]*/ <: Nat](p/*<-recursion::Nats.Succ#p.*/: N/*->recursion::Nats.Succ#[N]*/) extends Nat/*->recursion::Nats.Nat#*/ + + transparent inline def toIntg/*<-recursion::Nats.toIntg().*/(inline n/*<-recursion::Nats.toIntg().(n)*/: Nat/*->recursion::Nats.Nat#*/): Int/*->scala::Int#*/ = + inline n/*->recursion::Nats.toIntg().(n)*/ match { + case Zero/*->recursion::Nats.Zero.*/ => 0 + case Succ/*->recursion::Nats.Succ.*//*->recursion::Nats.Succ.unapply().*//*->local2*/(p/*<-local3*/) => toIntg/*->recursion::Nats.toIntg().*/(p/*->local3*/) +/*->scala::Int#`+`(+4).*/ 1 + } + + val j31/*<-recursion::Nats.j31.*/ = toIntg/*->recursion::Nats.toIntg().*/(Zero/*->recursion::Nats.Zero.*/.++.++.++/*<-local4*//*->recursion::Nats.Zero.*//*->recursion::Nats.Nat#`++`().*/ + /*<-local5*//*->recursion::Nats.Nat#`++`().*/Zer/*<-local6*//*->recursion::Nats.Nat#`++`().*//*->recursion::Nats.Nat#`+`().*/o/*->recursion::Nats.Zero.*/.++/*->recursion::Nats.Nat#`++`().*/) +} diff --git a/tests/semanticdb/expect/recursion.scala b/tests/semanticdb/expect/recursion.scala new file mode 100644 index 000000000000..4c0b54dd5083 --- /dev/null +++ b/tests/semanticdb/expect/recursion.scala @@ -0,0 +1,25 @@ +// semanticdb traversal of annotations of Nat caused an infinite loop +package recursion + +object Nats { + sealed trait Nat { + inline def ++ : Succ[this.type] = Succ(this) + + transparent inline def +(inline that: Nat): Nat = + inline this match { + case Zero => that + case Succ(p) => p + that.++ + } + } + + case object Zero extends Nat + case class Succ[N <: Nat](p: N) extends Nat + + transparent inline def toIntg(inline n: Nat): Int = + inline n match { + case Zero => 0 + case Succ(p) => toIntg(p) + 1 + } + + val j31 = toIntg(Zero.++.++.++ + Zero.++) +} diff --git a/tests/semanticdb/expect/semanticdb-Types.expect.scala b/tests/semanticdb/expect/semanticdb-Types.expect.scala index 3da1549f3b4b..cffc325c8410 100644 --- a/tests/semanticdb/expect/semanticdb-Types.expect.scala +++ b/tests/semanticdb/expect/semanticdb-Types.expect.scala @@ -23,6 +23,13 @@ class T/*<-types::T#*/ { val x/*<-types::T#x.*/ = new X/*->types::T#X#*/ } +case class Foo/*<-types::Foo#*/(s/*<-types::Foo#s.*/: "abc") + +object Foo/*<-types::Foo.*/ { + val x/*<-types::Foo.x.*/: "abc" @deprecated/*->scala::deprecated#*/ = "abc" + val y/*<-types::Foo.y.*/: "abc" = x/*->types::Foo.x.*/ +} + object Test/*<-types::Test.*/ { class M/*<-types::Test.M#*/ { def m/*<-types::Test.M#m().*/: Int/*->scala::Int#*/ = ???/*->scala::Predef.`???`().*/ diff --git a/tests/semanticdb/expect/semanticdb-Types.scala b/tests/semanticdb/expect/semanticdb-Types.scala index b6f5495c9675..0ce6bdc625e1 100644 --- a/tests/semanticdb/expect/semanticdb-Types.scala +++ b/tests/semanticdb/expect/semanticdb-Types.scala @@ -23,6 +23,13 @@ class T { val x = new X } +case class Foo(s: "abc") + +object Foo { + val x: "abc" @deprecated = "abc" + val y: "abc" = x +} + object Test { class M { def m: Int = ??? diff --git a/tests/semanticdb/metac.expect b/tests/semanticdb/metac.expect index 7f9903b3e3d7..e08a34444fac 100644 --- a/tests/semanticdb/metac.expect +++ b/tests/semanticdb/metac.expect @@ -339,8 +339,8 @@ Schema => SemanticDB v4 Uri => Classes.scala Text => empty Language => Scala -Symbols => 75 entries -Occurrences => 58 entries +Symbols => 79 entries +Occurrences => 62 entries Symbols: classes/C1# => final class C1 @@ -404,6 +404,10 @@ classes/C9# => class C9 classes/C9#``(). => primary ctor classes/C9#``().(x) => param x classes/C9#x(). => var method x +classes/C10# => class C10 +classes/C10#``(). => primary ctor +classes/C10#``().(s) => param s +classes/C10#s. => val method s classes/M. => final object M classes/M.C5# => class C5 classes/M.C5#``(). => primary ctor @@ -464,20 +468,24 @@ Occurrences: [22:8..22:34): <- classes/C9#``(). [22:27..22:28): x <- classes/C9#x(). [22:30..22:33): Int -> scala/Int# -[24:7..24:8): N <- classes/N. -[25:6..25:15): anonClass <- classes/N.anonClass. -[25:22..25:24): C7 -> classes/C7# -[25:24..25:24): -> classes/C7#``(). -[26:8..26:13): local <- local1 -[26:16..26:19): ??? -> scala/Predef.`???`(). -[28:6..28:13): anonFun <- classes/N.anonFun. -[28:16..28:20): List -> scala/package.List. -[28:20..28:20): -> scala/collection/IterableFactory#apply(). -[28:24..28:27): map -> scala/collection/immutable/List#map(). -[28:30..28:31): i <- local2 -[29:8..29:13): local <- local3 -[30:4..30:9): local -> local3 -[30:10..30:11): + -> scala/Int#`+`(+4). +[24:6..24:9): C10 <- classes/C10# +[24:9..24:23): <- classes/C10#``(). +[24:10..24:11): s <- classes/C10#s. +[24:16..24:22): String -> scala/Predef.String# +[26:7..26:8): N <- classes/N. +[27:6..27:15): anonClass <- classes/N.anonClass. +[27:22..27:24): C7 -> classes/C7# +[27:24..27:24): -> classes/C7#``(). +[28:8..28:13): local <- local1 +[28:16..28:19): ??? -> scala/Predef.`???`(). +[30:6..30:13): anonFun <- classes/N.anonFun. +[30:16..30:20): List -> scala/package.List. +[30:20..30:20): -> scala/collection/IterableFactory#apply(). +[30:24..30:27): map -> scala/collection/immutable/List#map(). +[30:30..30:31): i <- local2 +[31:8..31:13): local <- local3 +[32:4..32:9): local -> local3 +[32:10..32:11): + -> scala/Int#`+`(+4). expect/Empty.scala ------------------ @@ -739,7 +747,7 @@ Occurrences: [17:31..17:38): Boolean -> scala/Boolean# [17:41..17:45): suit -> _empty_/Enums.Suits.isBlack().(suit) [18:11..18:17): Spades -> _empty_/Enums.Suits.Spades. -[18:20..18:28): Diamonds -> _empty_/Enums.Suits.Diamonds. +[18:20..18:25): Clubs -> _empty_/Enums.Suits.Clubs. [21:7..21:15): WeekDays <- _empty_/Enums.WeekDays# [22:4..22:4): <- _empty_/Enums.WeekDays#``(). [22:9..22:15): Monday <- _empty_/Enums.WeekDays.Monday. @@ -2899,6 +2907,112 @@ Occurrences: [5:4..5:9): local -> local0 [5:10..5:11): + -> scala/Int#`+`(+4). +expect/recursion.scala +---------------------- + +Summary: +Schema => SemanticDB v4 +Uri => recursion.scala +Text => empty +Language => Scala +Symbols => 35 entries +Occurrences => 56 entries + +Symbols: +local0 => case val method N$1 +local1 => val local p +local2 => case val method N$2 +local3 => val local p +local4 => val local Nat_this +local5 => val local Nat_this +local6 => val local Nat_this +recursion/Nats. => final object Nats +recursion/Nats.Nat# => sealed trait Nat +recursion/Nats.Nat#`++`(). => macro ++ +recursion/Nats.Nat#`+`(). => macro + +recursion/Nats.Nat#`+`().(that) => param that +recursion/Nats.Nat#``(). => primary ctor +recursion/Nats.Succ# => case class Succ +recursion/Nats.Succ#[N] => typeparam N +recursion/Nats.Succ#_1(). => method _1 +recursion/Nats.Succ#``(). => primary ctor +recursion/Nats.Succ#``().(p) => val param p +recursion/Nats.Succ#copy$default$1(). => method copy$default$1 +recursion/Nats.Succ#copy$default$1().[N] => typeparam N +recursion/Nats.Succ#copy(). => method copy +recursion/Nats.Succ#copy().(p) => param p +recursion/Nats.Succ#copy().[N] => typeparam N +recursion/Nats.Succ#p. => val method p +recursion/Nats.Succ. => final object Succ +recursion/Nats.Succ.apply(). => method apply +recursion/Nats.Succ.apply().(p) => param p +recursion/Nats.Succ.apply().[N] => typeparam N +recursion/Nats.Succ.unapply(). => method unapply +recursion/Nats.Succ.unapply().(x$1) => param x$1 +recursion/Nats.Succ.unapply().[N] => typeparam N +recursion/Nats.Zero. => final case object Zero +recursion/Nats.j31. => val method j31 +recursion/Nats.toIntg(). => macro toIntg +recursion/Nats.toIntg().(n) => param n + +Occurrences: +[1:8..1:17): recursion <- recursion/ +[3:7..3:11): Nats <- recursion/Nats. +[4:15..4:18): Nat <- recursion/Nats.Nat# +[5:4..5:4): <- recursion/Nats.Nat#``(). +[5:15..5:17): ++ <- recursion/Nats.Nat#`++`(). +[5:20..5:24): Succ -> recursion/Nats.Succ# +[5:38..5:42): Succ -> recursion/Nats.Succ. +[5:42..5:42): -> recursion/Nats.Succ.apply(). +[7:27..7:28): + <- recursion/Nats.Nat#`+`(). +[7:36..7:40): that <- recursion/Nats.Nat#`+`().(that) +[7:42..7:45): Nat -> recursion/Nats.Nat# +[7:48..7:51): Nat -> recursion/Nats.Nat# +[9:13..9:17): Zero -> recursion/Nats.Zero. +[9:24..9:28): that -> recursion/Nats.Nat#`+`().(that) +[10:13..10:17): Succ -> recursion/Nats.Succ. +[10:17..10:17): -> recursion/Nats.Succ.unapply(). +[10:17..10:17): -> local0 +[10:18..10:19): p <- local1 +[10:24..10:25): p -> local1 +[10:26..10:27): + -> recursion/Nats.Nat#`+`(). +[10:28..10:32): that -> recursion/Nats.Nat#`+`().(that) +[10:33..10:35): ++ -> recursion/Nats.Nat#`++`(). +[14:14..14:18): Zero <- recursion/Nats.Zero. +[14:27..14:30): Nat -> recursion/Nats.Nat# +[15:13..15:17): Succ <- recursion/Nats.Succ# +[15:17..15:33): <- recursion/Nats.Succ#``(). +[15:18..15:19): N <- recursion/Nats.Succ#[N] +[15:28..15:29): p <- recursion/Nats.Succ#p. +[15:31..15:32): N -> recursion/Nats.Succ#[N] +[15:42..15:45): Nat -> recursion/Nats.Nat# +[17:25..17:31): toIntg <- recursion/Nats.toIntg(). +[17:39..17:40): n <- recursion/Nats.toIntg().(n) +[17:42..17:45): Nat -> recursion/Nats.Nat# +[17:48..17:51): Int -> scala/Int# +[18:11..18:12): n -> recursion/Nats.toIntg().(n) +[19:11..19:15): Zero -> recursion/Nats.Zero. +[20:11..20:15): Succ -> recursion/Nats.Succ. +[20:15..20:15): -> recursion/Nats.Succ.unapply(). +[20:15..20:15): -> local2 +[20:16..20:17): p <- local3 +[20:22..20:28): toIntg -> recursion/Nats.toIntg(). +[20:29..20:30): p -> local3 +[20:32..20:33): + -> scala/Int#`+`(+4). +[23:6..23:9): j31 <- recursion/Nats.j31. +[23:12..23:18): toIntg -> recursion/Nats.toIntg(). +[23:19..23:23): Zero -> recursion/Nats.Zero. +[23:24..23:32): ++.++.++ <- local4 +[23:24..23:24): -> recursion/Nats.Zero. +[23:24..23:26): ++ -> recursion/Nats.Nat#`++`(). +[23:27..23:35): ++.++ + <- local5 +[23:27..23:29): ++ -> recursion/Nats.Nat#`++`(). +[23:30..23:38): ++ + Zer <- local6 +[23:30..23:32): ++ -> recursion/Nats.Nat#`++`(). +[23:33..23:34): + -> recursion/Nats.Nat#`+`(). +[23:35..23:39): Zero -> recursion/Nats.Zero. +[23:40..23:42): ++ -> recursion/Nats.Nat#`++`(). + expect/semanticdb-Definitions.scala ----------------------------------- @@ -3088,8 +3202,8 @@ Schema => SemanticDB v4 Uri => semanticdb-Types.scala Text => empty Language => Scala -Symbols => 125 entries -Occurrences => 242 entries +Symbols => 140 entries +Occurrences => 250 entries Symbols: local0 => abstract method k @@ -3105,6 +3219,21 @@ types/B# => class B types/B#``(). => primary ctor types/C# => class C types/C#``(). => primary ctor +types/Foo# => case class Foo +types/Foo#_1(). => method _1 +types/Foo#``(). => primary ctor +types/Foo#``().(s) => val param s +types/Foo#copy$default$1(). => method copy$default$1 +types/Foo#copy(). => method copy +types/Foo#copy().(s) => param s +types/Foo#s. => val method s +types/Foo. => final object Foo +types/Foo.apply(). => method apply +types/Foo.apply().(s) => param s +types/Foo.unapply(). => method unapply +types/Foo.unapply().(x$1) => param x$1 +types/Foo.x. => val method x +types/Foo.y. => val method y types/P# => class P types/P#C# => class C types/P#C#``(). => primary ctor @@ -3266,201 +3395,209 @@ Occurrences: [22:6..22:7): x <- types/T#x. [22:14..22:15): X -> types/T#X# [22:15..22:15): -> types/T#X#``(). -[25:7..25:11): Test <- types/Test. -[26:8..26:9): M <- types/Test.M# -[27:4..27:4): <- types/Test.M#``(). -[27:8..27:9): m <- types/Test.M#m(). -[27:11..27:14): Int -> scala/Int# -[27:17..27:20): ??? -> scala/Predef.`???`(). -[30:8..30:9): N <- types/Test.N# -[31:4..31:4): <- types/Test.N#``(). -[31:8..31:9): n <- types/Test.N#n(). -[31:11..31:14): Int -> scala/Int# -[31:17..31:20): ??? -> scala/Predef.`???`(). -[34:8..34:9): C <- types/Test.C# -[34:18..34:18): <- types/Test.C#``(). -[34:18..34:19): M -> types/Test.M# -[34:19..34:19): -> types/Test.M#``(). -[35:8..35:9): p <- types/Test.C#p. -[35:16..35:17): P -> types/P# -[35:17..35:17): -> types/P#``(). -[36:8..36:9): x <- types/Test.C#x. -[36:12..36:13): p -> types/Test.C#p. -[36:14..36:15): x -> types/P#x. -[38:8..38:16): typeRef1 <- types/Test.C#typeRef1. -[38:18..38:19): C -> types/Test.C# -[38:22..38:25): ??? -> scala/Predef.`???`(). -[39:8..39:16): typeRef2 <- types/Test.C#typeRef2. -[39:18..39:19): p -> types/Test.C#p. -[39:20..39:21): C -> types/P#C# -[39:24..39:27): ??? -> scala/Predef.`???`(). -[40:8..40:16): typeRef3 <- types/Test.C#typeRef3. -[40:18..40:19): T -> types/T# -[40:20..40:21): C -> types/T#C# -[40:24..40:27): ??? -> scala/Predef.`???`(). -[41:8..41:16): typeRef4 <- types/Test.C#typeRef4. -[41:18..41:22): List -> scala/package.List# -[41:23..41:26): Int -> scala/Int# -[41:30..41:33): ??? -> scala/Predef.`???`(). -[43:8..43:19): singleType1 <- types/Test.C#singleType1. -[43:21..43:22): x -> types/Test.C#x. -[43:30..43:33): ??? -> scala/Predef.`???`(). -[44:8..44:19): singleType2 <- types/Test.C#singleType2. -[44:21..44:22): p -> types/Test.C#p. -[44:23..44:24): x -> types/P#x. -[44:32..44:35): ??? -> scala/Predef.`???`(). -[45:8..45:14): Either <- types/Test.C#Either. -[45:17..45:22): scala -> scala/ -[45:23..45:27): util -> scala/util/ -[45:28..45:34): Either -> scala/util/Either. -[47:8..47:17): thisType1 <- types/Test.C#thisType1. -[47:31..47:34): ??? -> scala/Predef.`???`(). -[48:8..48:17): thisType2 <- types/Test.C#thisType2. -[48:33..48:36): ??? -> scala/Predef.`???`(). -[50:8..50:18): superType1 <- types/Test.C#superType1. -[50:27..50:28): m -> types/Test.M#m(). -[51:8..51:18): superType2 <- types/Test.C#superType2. -[51:30..51:31): m -> types/Test.M#m(). -[52:8..52:18): superType3 <- types/Test.C#superType3. -[52:32..52:33): m -> types/Test.M#m(). -[54:8..54:21): compoundType1 <- types/Test.C#compoundType1. -[54:29..54:30): k <- local0 -[54:32..54:35): Int -> scala/Int# -[54:40..54:43): ??? -> scala/Predef.`???`(). -[55:8..55:21): compoundType2 <- types/Test.C#compoundType2. -[55:23..55:24): M -> types/Test.M# -[55:30..55:31): N -> types/Test.N# -[55:34..55:37): ??? -> scala/Predef.`???`(). -[56:8..56:21): compoundType3 <- types/Test.C#compoundType3. -[56:23..56:24): M -> types/Test.M# -[56:30..56:31): N -> types/Test.N# -[56:38..56:39): k <- local1 -[56:41..56:44): Int -> scala/Int# -[56:49..56:52): ??? -> scala/Predef.`???`(). -[57:8..57:21): compoundType4 <- types/Test.C#compoundType4. -[57:34..57:35): k <- local3 -[57:37..57:40): Int -> scala/Int# -[57:43..57:46): ??? -> scala/Predef.`???`(). -[58:8..58:21): compoundType5 <- types/Test.C#compoundType5. -[58:28..58:29): M -> types/Test.M# -[58:29..58:29): -> types/Test.M#``(). -[58:35..58:36): N -> types/Test.N# -[59:8..59:21): compoundType6 <- types/Test.C#compoundType6. -[59:28..59:29): M -> types/Test.M# -[59:29..59:29): -> types/Test.M#``(). -[59:35..59:36): N -> types/Test.N# -[59:43..59:44): k <- local6 -[59:46..59:49): Int -> scala/Int# -[59:52..59:55): ??? -> scala/Predef.`???`(). -[61:8..61:16): annType1 <- types/Test.C#annType1. -[61:18..61:19): T -> types/T# -[61:31..61:34): ??? -> scala/Predef.`???`(). -[62:8..62:16): annType2 <- types/Test.C#annType2. -[62:18..62:19): T -> types/T# -[62:21..62:25): ann1 -> types/ann1# -[62:27..62:31): ann2 -> types/ann2# +[25:11..25:14): Foo <- types/Foo# +[25:14..25:24): <- types/Foo#``(). +[25:15..25:16): s <- types/Foo#s. +[27:7..27:10): Foo <- types/Foo. +[28:6..28:7): x <- types/Foo.x. +[28:16..28:26): deprecated -> scala/deprecated# +[29:6..29:7): y <- types/Foo.y. +[29:17..29:18): x -> types/Foo.x. +[32:7..32:11): Test <- types/Test. +[33:8..33:9): M <- types/Test.M# +[34:4..34:4): <- types/Test.M#``(). +[34:8..34:9): m <- types/Test.M#m(). +[34:11..34:14): Int -> scala/Int# +[34:17..34:20): ??? -> scala/Predef.`???`(). +[37:8..37:9): N <- types/Test.N# +[38:4..38:4): <- types/Test.N#``(). +[38:8..38:9): n <- types/Test.N#n(). +[38:11..38:14): Int -> scala/Int# +[38:17..38:20): ??? -> scala/Predef.`???`(). +[41:8..41:9): C <- types/Test.C# +[41:18..41:18): <- types/Test.C#``(). +[41:18..41:19): M -> types/Test.M# +[41:19..41:19): -> types/Test.M#``(). +[42:8..42:9): p <- types/Test.C#p. +[42:16..42:17): P -> types/P# +[42:17..42:17): -> types/P#``(). +[43:8..43:9): x <- types/Test.C#x. +[43:12..43:13): p -> types/Test.C#p. +[43:14..43:15): x -> types/P#x. +[45:8..45:16): typeRef1 <- types/Test.C#typeRef1. +[45:18..45:19): C -> types/Test.C# +[45:22..45:25): ??? -> scala/Predef.`???`(). +[46:8..46:16): typeRef2 <- types/Test.C#typeRef2. +[46:18..46:19): p -> types/Test.C#p. +[46:20..46:21): C -> types/P#C# +[46:24..46:27): ??? -> scala/Predef.`???`(). +[47:8..47:16): typeRef3 <- types/Test.C#typeRef3. +[47:18..47:19): T -> types/T# +[47:20..47:21): C -> types/T#C# +[47:24..47:27): ??? -> scala/Predef.`???`(). +[48:8..48:16): typeRef4 <- types/Test.C#typeRef4. +[48:18..48:22): List -> scala/package.List# +[48:23..48:26): Int -> scala/Int# +[48:30..48:33): ??? -> scala/Predef.`???`(). +[50:8..50:19): singleType1 <- types/Test.C#singleType1. +[50:21..50:22): x -> types/Test.C#x. +[50:30..50:33): ??? -> scala/Predef.`???`(). +[51:8..51:19): singleType2 <- types/Test.C#singleType2. +[51:21..51:22): p -> types/Test.C#p. +[51:23..51:24): x -> types/P#x. +[51:32..51:35): ??? -> scala/Predef.`???`(). +[52:8..52:14): Either <- types/Test.C#Either. +[52:17..52:22): scala -> scala/ +[52:23..52:27): util -> scala/util/ +[52:28..52:34): Either -> scala/util/Either. +[54:8..54:17): thisType1 <- types/Test.C#thisType1. +[54:31..54:34): ??? -> scala/Predef.`???`(). +[55:8..55:17): thisType2 <- types/Test.C#thisType2. +[55:33..55:36): ??? -> scala/Predef.`???`(). +[57:8..57:18): superType1 <- types/Test.C#superType1. +[57:27..57:28): m -> types/Test.M#m(). +[58:8..58:18): superType2 <- types/Test.C#superType2. +[58:30..58:31): m -> types/Test.M#m(). +[59:8..59:18): superType3 <- types/Test.C#superType3. +[59:32..59:33): m -> types/Test.M#m(). +[61:8..61:21): compoundType1 <- types/Test.C#compoundType1. +[61:29..61:30): k <- local0 +[61:32..61:35): Int -> scala/Int# +[61:40..61:43): ??? -> scala/Predef.`???`(). +[62:8..62:21): compoundType2 <- types/Test.C#compoundType2. +[62:23..62:24): M -> types/Test.M# +[62:30..62:31): N -> types/Test.N# [62:34..62:37): ??? -> scala/Predef.`???`(). -[64:8..64:24): existentialType2 <- types/Test.C#existentialType2. -[64:26..64:30): List -> scala/package.List# -[64:36..64:39): ??? -> scala/Predef.`???`(). -[65:8..65:24): existentialType3 <- types/Test.C#existentialType3. -[65:27..65:32): Class -> java/lang/Class# -[65:33..65:40): forName -> java/lang/Class#forName(). -[66:8..66:24): existentialType4 <- types/Test.C#existentialType4. -[66:27..66:32): Class -> java/lang/Class# -[66:33..66:40): forName -> java/lang/Class#forName(). -[68:8..68:19): typeLambda1 <- types/Test.C#typeLambda1(). -[68:20..68:21): M <- types/Test.C#typeLambda1().[M] -[68:28..68:31): ??? -> scala/Predef.`???`(). -[69:4..69:15): typeLambda1 -> types/Test.C#typeLambda1(). -[69:24..69:25): L <- local7 -[69:26..69:27): T <- local8 -[69:31..69:35): List -> scala/package.List# -[69:36..69:37): T -> local8 -[71:11..71:25): ClassInfoType1 <- types/Test.C#ClassInfoType1. -[72:10..72:24): ClassInfoType2 <- types/Test.C#ClassInfoType2# -[72:33..72:33): <- types/Test.C#ClassInfoType2#``(). -[72:33..72:34): B -> types/B# -[72:34..72:34): -> types/B#``(). -[72:41..72:42): x <- types/Test.C#ClassInfoType2#x(). -[73:10..73:24): ClassInfoType3 <- types/Test.C#ClassInfoType3# -[73:24..73:27): <- types/Test.C#ClassInfoType3#``(). -[73:25..73:26): T <- types/Test.C#ClassInfoType3#[T] -[75:11..75:21): MethodType <- types/Test.C#MethodType. -[76:10..76:12): x1 <- types/Test.C#MethodType.x1(). -[76:14..76:17): Int -> scala/Int# -[76:20..76:23): ??? -> scala/Predef.`???`(). -[77:10..77:12): x2 <- types/Test.C#MethodType.x2(). -[77:14..77:17): Int -> scala/Int# -[77:20..77:23): ??? -> scala/Predef.`???`(). -[78:10..78:12): m3 <- types/Test.C#MethodType.m3(). -[78:14..78:17): Int -> scala/Int# -[78:20..78:23): ??? -> scala/Predef.`???`(). -[79:10..79:12): m4 <- types/Test.C#MethodType.m4(). -[79:16..79:19): Int -> scala/Int# -[79:22..79:25): ??? -> scala/Predef.`???`(). -[80:10..80:12): m5 <- types/Test.C#MethodType.m5(). -[80:13..80:14): x <- types/Test.C#MethodType.m5().(x) -[80:16..80:19): Int -> scala/Int# -[80:22..80:25): Int -> scala/Int# -[80:28..80:31): ??? -> scala/Predef.`???`(). -[81:10..81:12): m6 <- types/Test.C#MethodType.m6(). -[81:13..81:14): T <- types/Test.C#MethodType.m6().[T] -[81:16..81:17): x <- types/Test.C#MethodType.m6().(x) -[81:19..81:20): T -> types/Test.C#MethodType.m6().[T] -[81:23..81:24): T -> types/Test.C#MethodType.m6().[T] -[81:27..81:30): ??? -> scala/Predef.`???`(). -[84:11..84:21): ByNameType <- types/Test.C#ByNameType. -[85:10..85:12): m1 <- types/Test.C#ByNameType.m1(). -[85:13..85:14): x <- types/Test.C#ByNameType.m1().(x) -[85:19..85:22): Int -> scala/Int# -[85:25..85:28): Int -> scala/Int# -[85:31..85:34): ??? -> scala/Predef.`???`(). -[88:15..88:27): RepeatedType <- types/Test.C#RepeatedType# -[88:27..88:39): <- types/Test.C#RepeatedType#``(). -[88:28..88:29): s <- types/Test.C#RepeatedType#s. -[88:31..88:37): String -> scala/Predef.String# -[89:10..89:12): m1 <- types/Test.C#RepeatedType#m1(). -[89:13..89:14): x <- types/Test.C#RepeatedType#m1().(x) -[89:16..89:19): Int -> scala/Int# -[89:23..89:26): Int -> scala/Int# -[89:29..89:30): s -> types/Test.C#RepeatedType#s. -[89:31..89:37): length -> scala/collection/SeqOps#length(). -[92:11..92:19): TypeType <- types/Test.C#TypeType. -[93:11..93:13): T1 <- types/Test.C#TypeType.T1# -[94:10..94:12): m2 <- types/Test.C#TypeType.m2(). -[94:13..94:15): T2 <- types/Test.C#TypeType.m2().[T2] -[94:19..94:20): C -> types/Test.C# -[94:24..94:25): C -> types/Test.C# -[94:29..94:32): ??? -> scala/Predef.`???`(). -[95:10..95:12): m3 <- types/Test.C#TypeType.m3(). -[95:13..95:15): M3 <- types/Test.C#TypeType.m3().[M3] -[95:22..95:25): ??? -> scala/Predef.`???`(). -[96:11..96:13): T4 <- types/Test.C#TypeType.T4# -[96:16..96:17): C -> types/Test.C# -[97:11..97:13): T5 <- types/Test.C#TypeType.T5# -[97:14..97:15): U <- types/Test.C#TypeType.T5#[U] -[97:19..97:20): U -> types/Test.C#TypeType.T5#[U] -[101:9..101:16): Literal <- types/Test.Literal. -[102:14..102:17): int <- types/Test.Literal.int. -[103:14..103:18): long <- types/Test.Literal.long. -[104:14..104:19): float <- types/Test.Literal.float. -[105:14..105:20): double <- types/Test.Literal.double. -[106:14..106:17): nil <- types/Test.Literal.nil. -[107:14..107:18): char <- types/Test.Literal.char. -[108:14..108:20): string <- types/Test.Literal.string. -[109:14..109:18): bool <- types/Test.Literal.bool. -[110:14..110:18): unit <- types/Test.Literal.unit. -[111:14..111:22): javaEnum <- types/Test.Literal.javaEnum. -[111:25..111:29): java -> java/ -[111:30..111:33): nio -> java/nio/ -[111:34..111:38): file -> java/nio/file/ -[111:39..111:49): LinkOption -> java/nio/file/LinkOption# -[111:50..111:64): NOFOLLOW_LINKS -> java/nio/file/LinkOption#NOFOLLOW_LINKS. -[112:14..112:21): clazzOf <- types/Test.Literal.clazzOf. -[112:24..112:31): classOf -> scala/Predef.classOf(). -[112:32..112:38): Option -> scala/Option# -[112:39..112:42): Int -> scala/Int# +[63:8..63:21): compoundType3 <- types/Test.C#compoundType3. +[63:23..63:24): M -> types/Test.M# +[63:30..63:31): N -> types/Test.N# +[63:38..63:39): k <- local1 +[63:41..63:44): Int -> scala/Int# +[63:49..63:52): ??? -> scala/Predef.`???`(). +[64:8..64:21): compoundType4 <- types/Test.C#compoundType4. +[64:34..64:35): k <- local3 +[64:37..64:40): Int -> scala/Int# +[64:43..64:46): ??? -> scala/Predef.`???`(). +[65:8..65:21): compoundType5 <- types/Test.C#compoundType5. +[65:28..65:29): M -> types/Test.M# +[65:29..65:29): -> types/Test.M#``(). +[65:35..65:36): N -> types/Test.N# +[66:8..66:21): compoundType6 <- types/Test.C#compoundType6. +[66:28..66:29): M -> types/Test.M# +[66:29..66:29): -> types/Test.M#``(). +[66:35..66:36): N -> types/Test.N# +[66:43..66:44): k <- local6 +[66:46..66:49): Int -> scala/Int# +[66:52..66:55): ??? -> scala/Predef.`???`(). +[68:8..68:16): annType1 <- types/Test.C#annType1. +[68:18..68:19): T -> types/T# +[68:31..68:34): ??? -> scala/Predef.`???`(). +[69:8..69:16): annType2 <- types/Test.C#annType2. +[69:18..69:19): T -> types/T# +[69:21..69:25): ann1 -> types/ann1# +[69:27..69:31): ann2 -> types/ann2# +[69:34..69:37): ??? -> scala/Predef.`???`(). +[71:8..71:24): existentialType2 <- types/Test.C#existentialType2. +[71:26..71:30): List -> scala/package.List# +[71:36..71:39): ??? -> scala/Predef.`???`(). +[72:8..72:24): existentialType3 <- types/Test.C#existentialType3. +[72:27..72:32): Class -> java/lang/Class# +[72:33..72:40): forName -> java/lang/Class#forName(). +[73:8..73:24): existentialType4 <- types/Test.C#existentialType4. +[73:27..73:32): Class -> java/lang/Class# +[73:33..73:40): forName -> java/lang/Class#forName(). +[75:8..75:19): typeLambda1 <- types/Test.C#typeLambda1(). +[75:20..75:21): M <- types/Test.C#typeLambda1().[M] +[75:28..75:31): ??? -> scala/Predef.`???`(). +[76:4..76:15): typeLambda1 -> types/Test.C#typeLambda1(). +[76:24..76:25): L <- local7 +[76:26..76:27): T <- local8 +[76:31..76:35): List -> scala/package.List# +[76:36..76:37): T -> local8 +[78:11..78:25): ClassInfoType1 <- types/Test.C#ClassInfoType1. +[79:10..79:24): ClassInfoType2 <- types/Test.C#ClassInfoType2# +[79:33..79:33): <- types/Test.C#ClassInfoType2#``(). +[79:33..79:34): B -> types/B# +[79:34..79:34): -> types/B#``(). +[79:41..79:42): x <- types/Test.C#ClassInfoType2#x(). +[80:10..80:24): ClassInfoType3 <- types/Test.C#ClassInfoType3# +[80:24..80:27): <- types/Test.C#ClassInfoType3#``(). +[80:25..80:26): T <- types/Test.C#ClassInfoType3#[T] +[82:11..82:21): MethodType <- types/Test.C#MethodType. +[83:10..83:12): x1 <- types/Test.C#MethodType.x1(). +[83:14..83:17): Int -> scala/Int# +[83:20..83:23): ??? -> scala/Predef.`???`(). +[84:10..84:12): x2 <- types/Test.C#MethodType.x2(). +[84:14..84:17): Int -> scala/Int# +[84:20..84:23): ??? -> scala/Predef.`???`(). +[85:10..85:12): m3 <- types/Test.C#MethodType.m3(). +[85:14..85:17): Int -> scala/Int# +[85:20..85:23): ??? -> scala/Predef.`???`(). +[86:10..86:12): m4 <- types/Test.C#MethodType.m4(). +[86:16..86:19): Int -> scala/Int# +[86:22..86:25): ??? -> scala/Predef.`???`(). +[87:10..87:12): m5 <- types/Test.C#MethodType.m5(). +[87:13..87:14): x <- types/Test.C#MethodType.m5().(x) +[87:16..87:19): Int -> scala/Int# +[87:22..87:25): Int -> scala/Int# +[87:28..87:31): ??? -> scala/Predef.`???`(). +[88:10..88:12): m6 <- types/Test.C#MethodType.m6(). +[88:13..88:14): T <- types/Test.C#MethodType.m6().[T] +[88:16..88:17): x <- types/Test.C#MethodType.m6().(x) +[88:19..88:20): T -> types/Test.C#MethodType.m6().[T] +[88:23..88:24): T -> types/Test.C#MethodType.m6().[T] +[88:27..88:30): ??? -> scala/Predef.`???`(). +[91:11..91:21): ByNameType <- types/Test.C#ByNameType. +[92:10..92:12): m1 <- types/Test.C#ByNameType.m1(). +[92:13..92:14): x <- types/Test.C#ByNameType.m1().(x) +[92:19..92:22): Int -> scala/Int# +[92:25..92:28): Int -> scala/Int# +[92:31..92:34): ??? -> scala/Predef.`???`(). +[95:15..95:27): RepeatedType <- types/Test.C#RepeatedType# +[95:27..95:39): <- types/Test.C#RepeatedType#``(). +[95:28..95:29): s <- types/Test.C#RepeatedType#s. +[95:31..95:37): String -> scala/Predef.String# +[96:10..96:12): m1 <- types/Test.C#RepeatedType#m1(). +[96:13..96:14): x <- types/Test.C#RepeatedType#m1().(x) +[96:16..96:19): Int -> scala/Int# +[96:23..96:26): Int -> scala/Int# +[96:29..96:30): s -> types/Test.C#RepeatedType#s. +[96:31..96:37): length -> scala/collection/SeqOps#length(). +[99:11..99:19): TypeType <- types/Test.C#TypeType. +[100:11..100:13): T1 <- types/Test.C#TypeType.T1# +[101:10..101:12): m2 <- types/Test.C#TypeType.m2(). +[101:13..101:15): T2 <- types/Test.C#TypeType.m2().[T2] +[101:19..101:20): C -> types/Test.C# +[101:24..101:25): C -> types/Test.C# +[101:29..101:32): ??? -> scala/Predef.`???`(). +[102:10..102:12): m3 <- types/Test.C#TypeType.m3(). +[102:13..102:15): M3 <- types/Test.C#TypeType.m3().[M3] +[102:22..102:25): ??? -> scala/Predef.`???`(). +[103:11..103:13): T4 <- types/Test.C#TypeType.T4# +[103:16..103:17): C -> types/Test.C# +[104:11..104:13): T5 <- types/Test.C#TypeType.T5# +[104:14..104:15): U <- types/Test.C#TypeType.T5#[U] +[104:19..104:20): U -> types/Test.C#TypeType.T5#[U] +[108:9..108:16): Literal <- types/Test.Literal. +[109:14..109:17): int <- types/Test.Literal.int. +[110:14..110:18): long <- types/Test.Literal.long. +[111:14..111:19): float <- types/Test.Literal.float. +[112:14..112:20): double <- types/Test.Literal.double. +[113:14..113:17): nil <- types/Test.Literal.nil. +[114:14..114:18): char <- types/Test.Literal.char. +[115:14..115:20): string <- types/Test.Literal.string. +[116:14..116:18): bool <- types/Test.Literal.bool. +[117:14..117:18): unit <- types/Test.Literal.unit. +[118:14..118:22): javaEnum <- types/Test.Literal.javaEnum. +[118:25..118:29): java -> java/ +[118:30..118:33): nio -> java/nio/ +[118:34..118:38): file -> java/nio/file/ +[118:39..118:49): LinkOption -> java/nio/file/LinkOption# +[118:50..118:64): NOFOLLOW_LINKS -> java/nio/file/LinkOption#NOFOLLOW_LINKS. +[119:14..119:21): clazzOf <- types/Test.Literal.clazzOf. +[119:24..119:31): classOf -> scala/Predef.classOf(). +[119:32..119:38): Option -> scala/Option# +[119:39..119:42): Int -> scala/Int# expect/semanticdb-extract.scala ------------------------------- From 996b81b0d8851083301e2a0472a678891d534b57 Mon Sep 17 00:00:00 2001 From: bishabosha Date: Thu, 14 May 2020 12:43:46 +0200 Subject: [PATCH 05/11] resolve vars in overloads --- .../dotc/semanticdb/ExtractSemanticDB.scala | 2 +- .../expect/MethodUsages.expect.scala | 6 +++++ tests/semanticdb/expect/MethodUsages.scala | 6 +++++ tests/semanticdb/metac.expect | 26 +++++++++++++++++-- 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala index f7df4f39af7d..37dfd84d59b7 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala @@ -298,7 +298,7 @@ class ExtractSemanticDB extends Phase: else decls0 end decls - val alts = decls.filter(_.is(Method)).toList.reverse + val alts = decls.filter(_.isOneOf(Method | Mutable)).toList.reverse alts match case notSym :: rest if sym != notSym => val idx = rest.indexOf(sym).ensuring(_ >= 0) diff --git a/tests/semanticdb/expect/MethodUsages.expect.scala b/tests/semanticdb/expect/MethodUsages.expect.scala index ab1397975510..14c78431af72 100644 --- a/tests/semanticdb/expect/MethodUsages.expect.scala +++ b/tests/semanticdb/expect/MethodUsages.expect.scala @@ -30,3 +30,9 @@ class MethodUsages/*<-example::MethodUsages#*/ { m/*->example::MethodUsages#m.*/.m18/*->example::Methods#m18().*/(1) m/*->example::MethodUsages#m.*/.m18/*->example::Methods#m18(+1).*/("") } + +object MethodUsages/*<-example::MethodUsages.*/ { + var x/*<-example::MethodUsages.x().*/: Int/*->scala::Int#*/ = 1 + def x/*<-example::MethodUsages.x(+1).*/(n/*<-example::MethodUsages.x(+1).(n)*/: String/*->scala::Predef.String#*/): Int/*->scala::Int#*/ = /*->scala::Predef.augmentString().*/n/*->example::MethodUsages.x(+1).(n)*/.toInt/*->scala::collection::StringOps#toInt().*/ + def foo/*<-example::MethodUsages.foo().*/: Int/*->scala::Int#*/ = x/*->example::MethodUsages.x().*/ +/*->scala::Int#`+`(+4).*/ x/*->example::MethodUsages.x(+1).*/("22") +} diff --git a/tests/semanticdb/expect/MethodUsages.scala b/tests/semanticdb/expect/MethodUsages.scala index b5982e8563a5..355f2334b1b5 100644 --- a/tests/semanticdb/expect/MethodUsages.scala +++ b/tests/semanticdb/expect/MethodUsages.scala @@ -30,3 +30,9 @@ class MethodUsages { m.m18(1) m.m18("") } + +object MethodUsages { + var x: Int = 1 + def x(n: String): Int = n.toInt + def foo: Int = x + x("22") +} diff --git a/tests/semanticdb/metac.expect b/tests/semanticdb/metac.expect index e08a34444fac..f842de7c840a 100644 --- a/tests/semanticdb/metac.expect +++ b/tests/semanticdb/metac.expect @@ -1616,13 +1616,20 @@ Schema => SemanticDB v4 Uri => MethodUsages.scala Text => empty Language => Scala -Symbols => 3 entries -Occurrences => 76 entries +Symbols => 10 entries +Occurrences => 91 entries Symbols: example/MethodUsages# => class MethodUsages example/MethodUsages#``(). => primary ctor example/MethodUsages#m. => val method m +example/MethodUsages. => final object MethodUsages +example/MethodUsages.`x_=`(). => var method x_= +example/MethodUsages.`x_=`().(x$1) => param x$1 +example/MethodUsages.foo(). => method foo +example/MethodUsages.x(). => var method x +example/MethodUsages.x(+1). => method x +example/MethodUsages.x(+1).(n) => param n Occurrences: [0:8..0:15): example <- example/ @@ -1701,6 +1708,21 @@ Occurrences: [29:4..29:7): m18 -> example/Methods#m18(). [30:2..30:3): m -> example/MethodUsages#m. [30:4..30:7): m18 -> example/Methods#m18(+1). +[33:7..33:19): MethodUsages <- example/MethodUsages. +[34:6..34:7): x <- example/MethodUsages.x(). +[34:9..34:12): Int -> scala/Int# +[35:6..35:7): x <- example/MethodUsages.x(+1). +[35:8..35:9): n <- example/MethodUsages.x(+1).(n) +[35:11..35:17): String -> scala/Predef.String# +[35:20..35:23): Int -> scala/Int# +[35:26..35:26): -> scala/Predef.augmentString(). +[35:26..35:27): n -> example/MethodUsages.x(+1).(n) +[35:28..35:33): toInt -> scala/collection/StringOps#toInt(). +[36:6..36:9): foo <- example/MethodUsages.foo(). +[36:11..36:14): Int -> scala/Int# +[36:17..36:18): x -> example/MethodUsages.x(). +[36:19..36:20): + -> scala/Int#`+`(+4). +[36:21..36:22): x -> example/MethodUsages.x(+1). expect/Methods.scala -------------------- From 5f5fa14c494fd8af71caa9143f60cbecb2542ab8 Mon Sep 17 00:00:00 2001 From: bishabosha Date: Thu, 14 May 2020 15:53:51 +0200 Subject: [PATCH 06/11] fix #8970 support scala 2 macros in semanticdb --- .../dotc/semanticdb/ExtractSemanticDB.scala | 15 ++- .../dotc/semanticdb/SemanticdbTests.scala | 2 + tests/semanticdb/expect/Classes.expect.scala | 21 +++ tests/semanticdb/expect/Classes.scala | 21 +++ tests/semanticdb/metac.expect | 123 +++++++++++++++--- 5 files changed, 160 insertions(+), 22 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala index 37dfd84d59b7..9cc05b35e1d4 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala @@ -64,7 +64,7 @@ class ExtractSemanticDB extends Phase: val occurrences = new mutable.ListBuffer[SymbolOccurrence]() /** The extracted symbol infos */ - val symbolInfos = new mutable.HashSet[SymbolInformation]() + val symbolInfos = new mutable.ListBuffer[SymbolInformation]() /** A cache of localN names */ val localNames = new mutable.HashSet[String]() @@ -299,11 +299,14 @@ class ExtractSemanticDB extends Phase: decls0 end decls val alts = decls.filter(_.isOneOf(Method | Mutable)).toList.reverse - alts match - case notSym :: rest if sym != notSym => - val idx = rest.indexOf(sym).ensuring(_ >= 0) - b.append('+').append(idx + 1) - case _ => + def find(filter: Symbol => Boolean) = alts match + case notSym :: rest if !filter(notSym) => + val idx = rest.indexWhere(filter).ensuring(_ >= 0) + b.append('+').append(idx + 1) + case _ => + end find + val sig = sym.signature + find(_.signature == sig) def addDescriptor(sym: Symbol): Unit = if sym.is(ModuleClass) then diff --git a/compiler/test/dotty/tools/dotc/semanticdb/SemanticdbTests.scala b/compiler/test/dotty/tools/dotc/semanticdb/SemanticdbTests.scala index 3baf9145cde5..53aa4df47623 100644 --- a/compiler/test/dotty/tools/dotc/semanticdb/SemanticdbTests.scala +++ b/compiler/test/dotty/tools/dotc/semanticdb/SemanticdbTests.scala @@ -73,6 +73,8 @@ class SemanticdbTests: println(s"""[${red("error")}] check file ${blue(expect.toString)} does not match generated. |If you meant to make a change, replace the expect file by: | mv ${expect.resolveSibling("" + expect.getFileName + ".out")} $expect + |inspect with: + | diff $expect ${expect.resolveSibling("" + expect.getFileName + ".out")} |Or else update all expect files with | sbt 'dotty-compiler-bootstrapped/test:runMain dotty.tools.dotc.semanticdb.updateExpect'""".stripMargin) Files.walk(target).sorted(Comparator.reverseOrder).forEach(Files.delete) diff --git a/tests/semanticdb/expect/Classes.expect.scala b/tests/semanticdb/expect/Classes.expect.scala index 34022c5ba6a2..70bc27506c5d 100644 --- a/tests/semanticdb/expect/Classes.expect.scala +++ b/tests/semanticdb/expect/Classes.expect.scala @@ -24,6 +24,27 @@ class C9/*<-classes::C9#*/(private[this] var x/*<-classes::C9#x().*/: Int/*->sca class C10/*<-classes::C10#*/(s/*<-classes::C10#s.*/: => String/*->scala::Predef.String#*/) +class C11/*<-classes::C11#*/ { + def foo/*<-classes::C11#foo().*/: Int/*->scala::Int#*/ = macro ???/*->scala::Predef.`???`().*/ + inline def foo/*<-classes::C11#foo().*/: Int/*->scala::Int#*/ = ???/*->scala::Predef.`???`().*/ +} + +class C12/*<-classes::C12#*/ { + + class Context/*<-classes::C12#Context#*/: // Dummy scala.reflect.macros.Context + type Expr/*<-classes::C12#Context#Expr#*/[T/*<-classes::C12#Context#Expr#[T]*/] + + def foo1/*<-classes::C12#foo1().*/(x/*<-classes::C12#foo1().(x)*/: Int/*->scala::Int#*/): Int/*->scala::Int#*/ = macro foo1Impl/*->classes::C12#foo1Impl().*/ + def foo1/*<-classes::C12#foo1().*/(x/*<-classes::C12#foo1().(x)*/: Int/*->scala::Int#*/): Int/*->scala::Int#*/ = ???/*->scala::Predef.`???`().*/ + + def foo2/*<-classes::C12#foo2().*/(x/*<-classes::C12#foo2().(x)*/: Int/*->scala::Int#*/, y/*<-classes::C12#foo2().(y)*/: String/*->scala::Predef.String#*/): Int/*->scala::Int#*/ = macro foo2Impl/*->classes::C12#foo2Impl().*/ + def foo2/*<-classes::C12#foo2().*/(x/*<-classes::C12#foo2().(x)*/: Int/*->scala::Int#*/, y/*<-classes::C12#foo2().(y)*/: String/*->scala::Predef.String#*/): Int/*->scala::Int#*/ = ???/*->scala::Predef.`???`().*/ + + def foo1Impl/*<-classes::C12#foo1Impl().*/(context/*<-classes::C12#foo1Impl().(context)*/: Context/*->classes::C12#Context#*/)(x/*<-classes::C12#foo1Impl().(x)*/: context/*->classes::C12#foo1Impl().(context)*/.Expr/*->classes::C12#Context#Expr#*/[Int/*->scala::Int#*/]): context/*->classes::C12#foo1Impl().(context)*/.Expr/*->classes::C12#Context#Expr#*/[Int/*->scala::Int#*/] = ???/*->scala::Predef.`???`().*/ + def foo2Impl/*<-classes::C12#foo2Impl().*/(context/*<-classes::C12#foo2Impl().(context)*/: Context/*->classes::C12#Context#*/)(x/*<-classes::C12#foo2Impl().(x)*/: context/*->classes::C12#foo2Impl().(context)*/.Expr/*->classes::C12#Context#Expr#*/[Int/*->scala::Int#*/], y/*<-classes::C12#foo2Impl().(y)*/: context/*->classes::C12#foo2Impl().(context)*/.Expr/*->classes::C12#Context#Expr#*/[String/*->scala::Predef.String#*/]): context/*->classes::C12#foo2Impl().(context)*/.Expr/*->classes::C12#Context#Expr#*/[Int/*->scala::Int#*/] = ???/*->scala::Predef.`???`().*/ + +} + object N/*<-classes::N.*/ { val anonClass/*<-classes::N.anonClass.*/ = new C7/*->classes::C7#*/(42) { val local/*<-local1*/ = ???/*->scala::Predef.`???`().*/ diff --git a/tests/semanticdb/expect/Classes.scala b/tests/semanticdb/expect/Classes.scala index 5d1d5efc4f4c..510c853c0fda 100644 --- a/tests/semanticdb/expect/Classes.scala +++ b/tests/semanticdb/expect/Classes.scala @@ -24,6 +24,27 @@ class C9(private[this] var x: Int) class C10(s: => String) +class C11 { + def foo: Int = macro ??? + inline def foo: Int = ??? +} + +class C12 { + + class Context: // Dummy scala.reflect.macros.Context + type Expr[T] + + def foo1(x: Int): Int = macro foo1Impl + def foo1(x: Int): Int = ??? + + def foo2(x: Int, y: String): Int = macro foo2Impl + def foo2(x: Int, y: String): Int = ??? + + def foo1Impl(context: Context)(x: context.Expr[Int]): context.Expr[Int] = ??? + def foo2Impl(context: Context)(x: context.Expr[Int], y: context.Expr[String]): context.Expr[Int] = ??? + +} + object N { val anonClass = new C7(42) { val local = ??? diff --git a/tests/semanticdb/metac.expect b/tests/semanticdb/metac.expect index f842de7c840a..2626b6b04dcf 100644 --- a/tests/semanticdb/metac.expect +++ b/tests/semanticdb/metac.expect @@ -339,8 +339,8 @@ Schema => SemanticDB v4 Uri => Classes.scala Text => empty Language => Scala -Symbols => 79 entries -Occurrences => 62 entries +Symbols => 106 entries +Occurrences => 126 entries Symbols: classes/C1# => final class C1 @@ -408,6 +408,33 @@ classes/C10# => class C10 classes/C10#``(). => primary ctor classes/C10#``().(s) => param s classes/C10#s. => val method s +classes/C11# => class C11 +classes/C11#``(). => primary ctor +classes/C11#foo(). => macro foo +classes/C11#foo(). => macro foo +classes/C12# => class C12 +classes/C12#Context# => class Context +classes/C12#Context#Expr# => type Expr +classes/C12#Context#Expr#[T] => typeparam T +classes/C12#Context#``(). => primary ctor +classes/C12#``(). => primary ctor +classes/C12#foo1(). => macro foo1 +classes/C12#foo1(). => method foo1 +classes/C12#foo1().(x) => param x +classes/C12#foo1().(x) => param x +classes/C12#foo1Impl(). => method foo1Impl +classes/C12#foo1Impl().(context) => param context +classes/C12#foo1Impl().(x) => param x +classes/C12#foo2(). => macro foo2 +classes/C12#foo2(). => method foo2 +classes/C12#foo2().(x) => param x +classes/C12#foo2().(x) => param x +classes/C12#foo2().(y) => param y +classes/C12#foo2().(y) => param y +classes/C12#foo2Impl(). => method foo2Impl +classes/C12#foo2Impl().(context) => param context +classes/C12#foo2Impl().(x) => param x +classes/C12#foo2Impl().(y) => param y classes/M. => final object M classes/M.C5# => class C5 classes/M.C5#``(). => primary ctor @@ -472,20 +499,84 @@ Occurrences: [24:9..24:23): <- classes/C10#``(). [24:10..24:11): s <- classes/C10#s. [24:16..24:22): String -> scala/Predef.String# -[26:7..26:8): N <- classes/N. -[27:6..27:15): anonClass <- classes/N.anonClass. -[27:22..27:24): C7 -> classes/C7# -[27:24..27:24): -> classes/C7#``(). -[28:8..28:13): local <- local1 -[28:16..28:19): ??? -> scala/Predef.`???`(). -[30:6..30:13): anonFun <- classes/N.anonFun. -[30:16..30:20): List -> scala/package.List. -[30:20..30:20): -> scala/collection/IterableFactory#apply(). -[30:24..30:27): map -> scala/collection/immutable/List#map(). -[30:30..30:31): i <- local2 -[31:8..31:13): local <- local3 -[32:4..32:9): local -> local3 -[32:10..32:11): + -> scala/Int#`+`(+4). +[26:6..26:9): C11 <- classes/C11# +[27:2..27:2): <- classes/C11#``(). +[27:6..27:9): foo <- classes/C11#foo(). +[27:11..27:14): Int -> scala/Int# +[27:23..27:26): ??? -> scala/Predef.`???`(). +[28:13..28:16): foo <- classes/C11#foo(). +[28:18..28:21): Int -> scala/Int# +[28:24..28:27): ??? -> scala/Predef.`???`(). +[31:6..31:9): C12 <- classes/C12# +[33:2..33:2): <- classes/C12#``(). +[33:8..33:15): Context <- classes/C12#Context# +[34:4..34:4): <- classes/C12#Context#``(). +[34:9..34:13): Expr <- classes/C12#Context#Expr# +[34:14..34:15): T <- classes/C12#Context#Expr#[T] +[36:6..36:10): foo1 <- classes/C12#foo1(). +[36:11..36:12): x <- classes/C12#foo1().(x) +[36:14..36:17): Int -> scala/Int# +[36:20..36:23): Int -> scala/Int# +[36:32..36:40): foo1Impl -> classes/C12#foo1Impl(). +[37:6..37:10): foo1 <- classes/C12#foo1(). +[37:11..37:12): x <- classes/C12#foo1().(x) +[37:14..37:17): Int -> scala/Int# +[37:20..37:23): Int -> scala/Int# +[37:26..37:29): ??? -> scala/Predef.`???`(). +[39:6..39:10): foo2 <- classes/C12#foo2(). +[39:11..39:12): x <- classes/C12#foo2().(x) +[39:14..39:17): Int -> scala/Int# +[39:19..39:20): y <- classes/C12#foo2().(y) +[39:22..39:28): String -> scala/Predef.String# +[39:31..39:34): Int -> scala/Int# +[39:43..39:51): foo2Impl -> classes/C12#foo2Impl(). +[40:6..40:10): foo2 <- classes/C12#foo2(). +[40:11..40:12): x <- classes/C12#foo2().(x) +[40:14..40:17): Int -> scala/Int# +[40:19..40:20): y <- classes/C12#foo2().(y) +[40:22..40:28): String -> scala/Predef.String# +[40:31..40:34): Int -> scala/Int# +[40:37..40:40): ??? -> scala/Predef.`???`(). +[42:6..42:14): foo1Impl <- classes/C12#foo1Impl(). +[42:15..42:22): context <- classes/C12#foo1Impl().(context) +[42:24..42:31): Context -> classes/C12#Context# +[42:33..42:34): x <- classes/C12#foo1Impl().(x) +[42:36..42:43): context -> classes/C12#foo1Impl().(context) +[42:44..42:48): Expr -> classes/C12#Context#Expr# +[42:49..42:52): Int -> scala/Int# +[42:56..42:63): context -> classes/C12#foo1Impl().(context) +[42:64..42:68): Expr -> classes/C12#Context#Expr# +[42:69..42:72): Int -> scala/Int# +[42:76..42:79): ??? -> scala/Predef.`???`(). +[43:6..43:14): foo2Impl <- classes/C12#foo2Impl(). +[43:15..43:22): context <- classes/C12#foo2Impl().(context) +[43:24..43:31): Context -> classes/C12#Context# +[43:33..43:34): x <- classes/C12#foo2Impl().(x) +[43:36..43:43): context -> classes/C12#foo2Impl().(context) +[43:44..43:48): Expr -> classes/C12#Context#Expr# +[43:49..43:52): Int -> scala/Int# +[43:55..43:56): y <- classes/C12#foo2Impl().(y) +[43:58..43:65): context -> classes/C12#foo2Impl().(context) +[43:66..43:70): Expr -> classes/C12#Context#Expr# +[43:71..43:77): String -> scala/Predef.String# +[43:81..43:88): context -> classes/C12#foo2Impl().(context) +[43:89..43:93): Expr -> classes/C12#Context#Expr# +[43:94..43:97): Int -> scala/Int# +[43:101..43:104): ??? -> scala/Predef.`???`(). +[47:7..47:8): N <- classes/N. +[48:6..48:15): anonClass <- classes/N.anonClass. +[48:22..48:24): C7 -> classes/C7# +[48:24..48:24): -> classes/C7#``(). +[49:8..49:13): local <- local1 +[49:16..49:19): ??? -> scala/Predef.`???`(). +[51:6..51:13): anonFun <- classes/N.anonFun. +[51:16..51:20): List -> scala/package.List. +[51:20..51:20): -> scala/collection/IterableFactory#apply(). +[51:24..51:27): map -> scala/collection/immutable/List#map(). +[51:30..51:31): i <- local2 +[52:8..52:13): local <- local3 +[53:4..53:9): local -> local3 +[53:10..53:11): + -> scala/Int#`+`(+4). expect/Empty.scala ------------------ From 45571b210b7646631f02fab672cd5cf2be261073 Mon Sep 17 00:00:00 2001 From: bishabosha Date: Thu, 14 May 2020 16:36:24 +0200 Subject: [PATCH 07/11] support inlined local defs --- .../tools/dotc/semanticdb/ExtractSemanticDB.scala | 6 ++++-- .../semanticdb/inline-unapply/App_2.scala | 12 ++++++++++++ .../semanticdb/inline-unapply/Macro_1.scala | 8 ++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 tests/pos-custom-args/semanticdb/inline-unapply/App_2.scala create mode 100644 tests/pos-custom-args/semanticdb/inline-unapply/Macro_1.scala diff --git a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala index 9cc05b35e1d4..519fddf0449b 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala @@ -334,14 +334,16 @@ class ExtractSemanticDB extends Phase: * the same starting position have the same index. */ def localIdx(sym: Symbol)(using Context): Int = + def startPos(sym: Symbol) = + if sym.span.exists then sym.span.start else -1 def computeLocalIdx(): Int = - symsAtOffset(sym.span.start).find(_.name == sym.name) match + symsAtOffset(startPos(sym)).find(_.name == sym.name) match case Some(other) => localIdx(other) case None => val idx = nextLocalIdx nextLocalIdx += 1 locals(sym) = idx - symsAtOffset(sym.span.start) += sym + symsAtOffset(startPos(sym)) += sym idx locals.getOrElseUpdate(sym, computeLocalIdx()) diff --git a/tests/pos-custom-args/semanticdb/inline-unapply/App_2.scala b/tests/pos-custom-args/semanticdb/inline-unapply/App_2.scala new file mode 100644 index 000000000000..3d0d6b665128 --- /dev/null +++ b/tests/pos-custom-args/semanticdb/inline-unapply/App_2.scala @@ -0,0 +1,12 @@ + +object Test { + def main(args: Array[String]): Unit = { + 0 match + case Succ(n) => ??? + case _ => + + 2 match + case Succ(n) => assert(n == 1) + } + +} diff --git a/tests/pos-custom-args/semanticdb/inline-unapply/Macro_1.scala b/tests/pos-custom-args/semanticdb/inline-unapply/Macro_1.scala new file mode 100644 index 000000000000..2d49b71383e3 --- /dev/null +++ b/tests/pos-custom-args/semanticdb/inline-unapply/Macro_1.scala @@ -0,0 +1,8 @@ +import scala.quoted._ + +object Succ: + + inline def unapply(n: Int): Option[Int] = ${ impl('n) } + + private def impl(n: Expr[Int])(using QuoteContext): Expr[Option[Int]] = + '{ if $n == 0 then None else Some($n - 1)} From 3c167a76d12dce7485bc00f3d0518453f077b37f Mon Sep 17 00:00:00 2001 From: bishabosha Date: Thu, 14 May 2020 17:31:06 +0200 Subject: [PATCH 08/11] compile codebase tests with semanticdb --- compiler/test/dotty/tools/dotc/CompilationTests.scala | 6 +++--- compiler/test/dotty/tools/vulpix/TestConfiguration.scala | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index ae3316c35d2e..825f2a3d3698 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -202,9 +202,9 @@ class CompilationTests extends ParallelTesting { ).checkCompile() } - /** The purpose of this test is two-fold, being able to compile dotty + /** The purpose of this test is three-fold, being able to compile dotty * bootstrapped, and making sure that TASTY can link against a compiled - * version of Dotty + * version of Dotty, and compiling the compiler using the SemanticDB generation */ @Test def tastyBootstrap: Unit = { implicit val testGroup: TestGroup = TestGroup("tastyBootstrap/tests") @@ -228,7 +228,7 @@ class CompilationTests extends ParallelTesting { Properties.compilerInterface, Properties.scalaLibrary, Properties.scalaAsm, Properties.dottyInterfaces, Properties.jlineTerminal, Properties.jlineReader, ).mkString(File.pathSeparator), - Array("-Ycheck-reentrant", "-Yemit-tasty-in-class", "-language:postfixOps") + Array("-Ycheck-reentrant", "-Yemit-tasty-in-class", "-language:postfixOps", "-Ysemanticdb") ) val libraryDirs = List(Paths.get("library/src"), Paths.get("library/src-bootstrapped")) diff --git a/compiler/test/dotty/tools/vulpix/TestConfiguration.scala b/compiler/test/dotty/tools/vulpix/TestConfiguration.scala index 948d184afb0a..01775432ca12 100644 --- a/compiler/test/dotty/tools/vulpix/TestConfiguration.scala +++ b/compiler/test/dotty/tools/vulpix/TestConfiguration.scala @@ -16,7 +16,7 @@ object TestConfiguration { "-Yno-deep-subtypes", "-Yno-double-bindings", "-Yforce-sbt-phases", - // "-Ysemanticdb", + "-Ysemanticdb", "-Xverify-signatures" ) From 5f43d09fcf4d5198f2df1da389a2eaec2788669d Mon Sep 17 00:00:00 2001 From: bishabosha Date: Fri, 15 May 2020 16:45:52 +0200 Subject: [PATCH 09/11] pass Tree in context, source->treeSource --- .../dotc/semanticdb/ExtractSemanticDB.scala | 96 ++++++++++--------- .../expect/MethodUsages.expect.scala | 10 +- tests/semanticdb/expect/MethodUsages.scala | 10 +- tests/semanticdb/expect/Methods.expect.scala | 3 + tests/semanticdb/expect/Methods.scala | 3 + tests/semanticdb/metac.expect | 56 ++++++----- 6 files changed, 94 insertions(+), 84 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala index 519fddf0449b..28b1edc58a01 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala @@ -125,20 +125,20 @@ class ExtractSemanticDB extends Phase: if !excludeDef(tree.pid.symbol) && tree.pid.span.hasLength tree.pid match - case tree @ Select(qual, name) => - registerDefinition(tree.symbol, adjustSpanToName(tree.span, qual.span, name, tree.source), Set.empty) - traverse(qual) - case tree => registerDefinition(tree.symbol, tree.span, Set.empty) + case tree: Select => + registerDefinition(tree.symbol, selectSpan(tree), Set.empty, tree.source) + traverse(tree.qualifier) + case tree => registerDefinition(tree.symbol, tree.span, Set.empty, tree.source) tree.stats.foreach(traverse) case tree: NamedDefTree => if tree.symbol.isAllOf(ModuleValCreationFlags) return if !excludeDef(tree.symbol) && tree.span.hasLength - registerDefinition(tree.symbol, tree.adjustedNameSpan, symbolKinds(tree)) + registerDefinition(tree.symbol, tree.adjustedNameSpan, symbolKinds(tree), tree.source) val privateWithin = tree.symbol.privateWithin if privateWithin.exists - registerUseGuarded(None, privateWithin, spanOfSymbol(privateWithin, tree.span)) + registerUseGuarded(None, privateWithin, spanOfSymbol(privateWithin, tree.span, tree.source), tree.source) else if !excludeSymbol(tree.symbol) registerSymbol(tree.symbol, symbolName(tree.symbol), symbolKinds(tree)) tree match @@ -176,7 +176,7 @@ class ExtractSemanticDB extends Phase: val ctorSym = tree.constr.symbol if !excludeDef(ctorSym) traverseAnnotsOfDefinition(ctorSym) - registerDefinition(ctorSym, tree.constr.span, Set.empty) + registerDefinition(ctorSym, tree.constr.span, Set.empty, tree.source) ctorParams(tree.constr.vparamss, tree.body) for parent <- tree.parentsOrDerived if parent.span.hasLength do traverse(parent) @@ -192,9 +192,9 @@ class ExtractSemanticDB extends Phase: traverse(tree.fun) for arg <- tree.args do arg match - case arg @ NamedArg(name, value) => - registerUse(genParamSymbol(name), arg.span.startPos.withEnd(arg.span.start + name.toString.length)) - traverse(localBodies.get(value.symbol).getOrElse(value)) + case tree @ NamedArg(name, arg) => + registerUse(genParamSymbol(name), tree.span.startPos.withEnd(tree.span.start + name.toString.length), tree.source) + traverse(localBodies.get(arg.symbol).getOrElse(arg)) case _ => traverse(arg) case tree: Assign => val qualSym = condOpt(tree.lhs) { case Select(qual, _) if qual.symbol.exists => qual.symbol } @@ -202,29 +202,30 @@ class ExtractSemanticDB extends Phase: val lhs = tree.lhs.symbol val setter = lhs.matchingSetter.orElse(lhs) tree.lhs match - case tree @ Select(qual, name) => registerUse(setter, adjustSpanToName(tree.span, qual.span, name, tree.source)) - case tree => registerUse(setter, tree.span) + case tree: Select => registerUse(setter, selectSpan(tree), tree.source) + case tree => registerUse(setter, tree.span, tree.source) traverseChildren(tree.lhs) traverse(tree.rhs) case tree: Ident => if tree.name != nme.WILDCARD then val sym = tree.symbol.adjustIfCtorTyparam - registerUseGuarded(None, sym, tree.span) + registerUseGuarded(None, sym, tree.span, tree.source) case tree: Select => - val qualSpan = tree.qualifier.span + val qual = tree.qualifier + val qualSpan = qual.span val sym = tree.symbol.adjustIfCtorTyparam - registerUseGuarded(tree.qualifier.symbol.ifExists, sym, adjustSpanToName(tree.span, qualSpan, tree.name, tree.source)) + registerUseGuarded(qual.symbol.ifExists, sym, selectSpan(tree), tree.source) if qualSpan.exists && qualSpan.hasLength then - traverse(tree.qualifier) + traverse(qual) case tree: Import => if tree.span.exists && tree.span.hasLength then for sel <- tree.selectors do val imported = sel.imported.name if imported != nme.WILDCARD then for alt <- tree.expr.tpe.member(imported).alternatives do - registerUseGuarded(None, alt.symbol, sel.imported.span) + registerUseGuarded(None, alt.symbol, sel.imported.span, tree.source) if (alt.symbol.companionClass.exists) - registerUseGuarded(None, alt.symbol.companionClass, sel.imported.span) + registerUseGuarded(None, alt.symbol.companionClass, sel.imported.span, tree.source) traverseChildren(tree) case tree: Inlined => traverse(tree.call) @@ -334,18 +335,23 @@ class ExtractSemanticDB extends Phase: * the same starting position have the same index. */ def localIdx(sym: Symbol)(using Context): Int = - def startPos(sym: Symbol) = - if sym.span.exists then sym.span.start else -1 - def computeLocalIdx(): Int = - symsAtOffset(startPos(sym)).find(_.name == sym.name) match - case Some(other) => localIdx(other) + val startPos = + assert(sym.span.exists, s"$sym should have a span") + sym.span.start + @tailrec + def computeLocalIdx(sym: Symbol): Int = locals get sym match + case Some(idx) => idx + case None => symsAtOffset(startPos).find(_.name == sym.name) match + case Some(other) => computeLocalIdx(other) case None => val idx = nextLocalIdx nextLocalIdx += 1 locals(sym) = idx - symsAtOffset(startPos(sym)) += sym + symsAtOffset(startPos) += sym idx - locals.getOrElseUpdate(sym, computeLocalIdx()) + end computeLocalIdx + computeLocalIdx(sym) + end localIdx if sym.exists then if sym.isGlobal then @@ -361,10 +367,8 @@ class ExtractSemanticDB extends Phase: addSymName(b, sym) b.toString - inline private def source(using Context) = ctx.compilationUnit.source - - private def range(span: Span)(using Context): Option[Range] = - def lineCol(offset: Int) = (source.offsetToLine(offset), source.column(offset)) + private def range(span: Span, treeSource: SourceFile)(using Context): Option[Range] = + def lineCol(offset: Int) = (treeSource.offsetToLine(offset), treeSource.column(offset)) val (startLine, startCol) = lineCol(span.start) val (endLine, endCol) = lineCol(span.end) Some(Range(startLine, startCol, endLine, endCol)) @@ -456,30 +460,30 @@ class ExtractSemanticDB extends Phase: private def registerSymbolSimple(sym: Symbol)(using Context): Unit = registerSymbol(sym, symbolName(sym), Set.empty) - private def registerOccurrence(symbol: String, span: Span, role: SymbolOccurrence.Role)(using Context): Unit = - val occ = SymbolOccurrence(symbol, range(span), role) + private def registerOccurrence(symbol: String, span: Span, role: SymbolOccurrence.Role, treeSource: SourceFile)(using Context): Unit = + val occ = SymbolOccurrence(symbol, range(span, treeSource), role) if !generated.contains(occ) && occ.symbol.nonEmpty then occurrences += occ generated += occ - private def registerUseGuarded(qualSym: Option[Symbol], sym: Symbol, span: Span)(using Context) = + private def registerUseGuarded(qualSym: Option[Symbol], sym: Symbol, span: Span, treeSource: SourceFile)(using Context) = if !excludeUse(qualSym, sym) then - registerUse(sym, span) + registerUse(sym, span, treeSource) - private def registerUse(sym: Symbol, span: Span)(using Context): Unit = - registerUse(symbolName(sym), span) + private def registerUse(sym: Symbol, span: Span, treeSource: SourceFile)(using Context): Unit = + registerUse(symbolName(sym), span, treeSource) - private def registerUse(symbol: String, span: Span)(using Context): Unit = - registerOccurrence(symbol, span, SymbolOccurrence.Role.REFERENCE) + private def registerUse(symbol: String, span: Span, treeSource: SourceFile)(using Context): Unit = + registerOccurrence(symbol, span, SymbolOccurrence.Role.REFERENCE, treeSource) - private def registerDefinition(sym: Symbol, span: Span, symkinds: Set[SymbolKind])(using Context) = + private def registerDefinition(sym: Symbol, span: Span, symkinds: Set[SymbolKind], treeSource: SourceFile)(using Context) = val symbol = symbolName(sym) - registerOccurrence(symbol, span, SymbolOccurrence.Role.DEFINITION) + registerOccurrence(symbol, span, SymbolOccurrence.Role.DEFINITION, treeSource) if !sym.is(Package) registerSymbol(sym, symbol, symkinds) - private def spanOfSymbol(sym: Symbol, span: Span)(using Context): Span = - val contents = if source.exists then source.content() else Array.empty[Char] + private def spanOfSymbol(sym: Symbol, span: Span, treeSource: SourceFile)(using Context): Span = + val contents = if treeSource.exists then treeSource.content() else Array.empty[Char] val idx = contents.indexOfSlice(sym.name.show, span.start) val start = if idx >= 0 then idx else span.start Span(start, start + sym.name.show.length, start) @@ -503,13 +507,13 @@ class ExtractSemanticDB extends Phase: }).toMap end findGetters - private def adjustSpanToName(span: Span, qualSpan: Span, name: Name, source: SourceFile) = - val end = span.end - val limit = qualSpan.end + private def selectSpan(tree: Select) = + val end = tree.span.end + val limit = tree.qualifier.span.end val start = if limit < end then - val len = name.toString.length - if source.content()(end - 1) == '`' then end - len - 2 else end - len + val len = tree.name.toString.length + if tree.source.content()(end - 1) == '`' then end - len - 2 else end - len else limit Span(start max limit, end) diff --git a/tests/semanticdb/expect/MethodUsages.expect.scala b/tests/semanticdb/expect/MethodUsages.expect.scala index 14c78431af72..d202e21ec851 100644 --- a/tests/semanticdb/expect/MethodUsages.expect.scala +++ b/tests/semanticdb/expect/MethodUsages.expect.scala @@ -29,10 +29,8 @@ class MethodUsages/*<-example::MethodUsages#*/ { m/*->example::MethodUsages#m.*/.m18/*->example::Methods#m18.*/.m/*->example::Methods#m17.m().*/() m/*->example::MethodUsages#m.*/.m18/*->example::Methods#m18().*/(1) m/*->example::MethodUsages#m.*/.m18/*->example::Methods#m18(+1).*/("") -} - -object MethodUsages/*<-example::MethodUsages.*/ { - var x/*<-example::MethodUsages.x().*/: Int/*->scala::Int#*/ = 1 - def x/*<-example::MethodUsages.x(+1).*/(n/*<-example::MethodUsages.x(+1).(n)*/: String/*->scala::Predef.String#*/): Int/*->scala::Int#*/ = /*->scala::Predef.augmentString().*/n/*->example::MethodUsages.x(+1).(n)*/.toInt/*->scala::collection::StringOps#toInt().*/ - def foo/*<-example::MethodUsages.foo().*/: Int/*->scala::Int#*/ = x/*->example::MethodUsages.x().*/ +/*->scala::Int#`+`(+4).*/ x/*->example::MethodUsages.x(+1).*/("22") + m/*->example::MethodUsages#m.*/.m19/*->example::Methods#m19().*/(1,2)(3) + m/*->example::MethodUsages#m.*/.m20/*->example::Methods#m20().*/(1) + m/*->example::MethodUsages#m.*/.m20/*->example::Methods#m20(+1).*/("") + m/*->example::MethodUsages#m.*/.m20/*->example::Methods#m20(+2).*/.m/*->example::Methods#m17.m().*/() } diff --git a/tests/semanticdb/expect/MethodUsages.scala b/tests/semanticdb/expect/MethodUsages.scala index 355f2334b1b5..af5cd6df791d 100644 --- a/tests/semanticdb/expect/MethodUsages.scala +++ b/tests/semanticdb/expect/MethodUsages.scala @@ -29,10 +29,8 @@ class MethodUsages { m.m18.m() m.m18(1) m.m18("") -} - -object MethodUsages { - var x: Int = 1 - def x(n: String): Int = n.toInt - def foo: Int = x + x("22") + m.m19(1,2)(3) + m.m20(1) + m.m20("") + m.m20.m() } diff --git a/tests/semanticdb/expect/Methods.expect.scala b/tests/semanticdb/expect/Methods.expect.scala index 58990ecb1401..56198e4320f4 100644 --- a/tests/semanticdb/expect/Methods.expect.scala +++ b/tests/semanticdb/expect/Methods.expect.scala @@ -34,4 +34,7 @@ class Methods/*<-example::Methods#*/[T/*<-example::Methods#[T]*/] { def m18/*<-example::Methods#m18().*/(a/*<-example::Methods#m18().(a)*/: Int/*->scala::Int#*/) = ???/*->scala::Predef.`???`().*/ def m18/*<-example::Methods#m18(+1).*/(b/*<-example::Methods#m18(+1).(b)*/: String/*->scala::Predef.String#*/) = ???/*->scala::Predef.`???`().*/ def m19/*<-example::Methods#m19().*/(x/*<-example::Methods#m19().(x)*//*<-example::Methods#m19$default$3().(x)*/: Int/*->scala::Int#*/, y/*<-example::Methods#m19().(y)*//*<-example::Methods#m19$default$3().(y)*/: Int/*->scala::Int#*/ = 2)(z/*<-example::Methods#m19().(z)*/: Int/*->scala::Int#*/ = 3) = ???/*->scala::Predef.`???`().*/ + def m20/*<-example::Methods#m20().*/(a/*<-example::Methods#m20().(a)*/: Int/*->scala::Int#*/) = ???/*->scala::Predef.`???`().*/ + def m20/*<-example::Methods#m20(+1).*/(b/*<-example::Methods#m20(+1).(b)*/: String/*->scala::Predef.String#*/) = ???/*->scala::Predef.`???`().*/ + var m20/*<-example::Methods#m20(+2).*/ = m17/*->example::Methods#m17.*/ } diff --git a/tests/semanticdb/expect/Methods.scala b/tests/semanticdb/expect/Methods.scala index 0327a3c32279..d588d3df2e55 100644 --- a/tests/semanticdb/expect/Methods.scala +++ b/tests/semanticdb/expect/Methods.scala @@ -34,4 +34,7 @@ class Methods[T] { def m18(a: Int) = ??? def m18(b: String) = ??? def m19(x: Int, y: Int = 2)(z: Int = 3) = ??? + def m20(a: Int) = ??? + def m20(b: String) = ??? + var m20 = m17 } diff --git a/tests/semanticdb/metac.expect b/tests/semanticdb/metac.expect index 2626b6b04dcf..bb57f73c4f32 100644 --- a/tests/semanticdb/metac.expect +++ b/tests/semanticdb/metac.expect @@ -1707,20 +1707,13 @@ Schema => SemanticDB v4 Uri => MethodUsages.scala Text => empty Language => Scala -Symbols => 10 entries -Occurrences => 91 entries +Symbols => 3 entries +Occurrences => 85 entries Symbols: example/MethodUsages# => class MethodUsages example/MethodUsages#``(). => primary ctor example/MethodUsages#m. => val method m -example/MethodUsages. => final object MethodUsages -example/MethodUsages.`x_=`(). => var method x_= -example/MethodUsages.`x_=`().(x$1) => param x$1 -example/MethodUsages.foo(). => method foo -example/MethodUsages.x(). => var method x -example/MethodUsages.x(+1). => method x -example/MethodUsages.x(+1).(n) => param n Occurrences: [0:8..0:15): example <- example/ @@ -1799,21 +1792,15 @@ Occurrences: [29:4..29:7): m18 -> example/Methods#m18(). [30:2..30:3): m -> example/MethodUsages#m. [30:4..30:7): m18 -> example/Methods#m18(+1). -[33:7..33:19): MethodUsages <- example/MethodUsages. -[34:6..34:7): x <- example/MethodUsages.x(). -[34:9..34:12): Int -> scala/Int# -[35:6..35:7): x <- example/MethodUsages.x(+1). -[35:8..35:9): n <- example/MethodUsages.x(+1).(n) -[35:11..35:17): String -> scala/Predef.String# -[35:20..35:23): Int -> scala/Int# -[35:26..35:26): -> scala/Predef.augmentString(). -[35:26..35:27): n -> example/MethodUsages.x(+1).(n) -[35:28..35:33): toInt -> scala/collection/StringOps#toInt(). -[36:6..36:9): foo <- example/MethodUsages.foo(). -[36:11..36:14): Int -> scala/Int# -[36:17..36:18): x -> example/MethodUsages.x(). -[36:19..36:20): + -> scala/Int#`+`(+4). -[36:21..36:22): x -> example/MethodUsages.x(+1). +[31:2..31:3): m -> example/MethodUsages#m. +[31:4..31:7): m19 -> example/Methods#m19(). +[32:2..32:3): m -> example/MethodUsages#m. +[32:4..32:7): m20 -> example/Methods#m20(). +[33:2..33:3): m -> example/MethodUsages#m. +[33:4..33:7): m20 -> example/Methods#m20(+1). +[34:2..34:3): m -> example/MethodUsages#m. +[34:4..34:7): m20 -> example/Methods#m20(+2). +[34:8..34:9): m -> example/Methods#m17.m(). expect/Methods.scala -------------------- @@ -1823,8 +1810,8 @@ Schema => SemanticDB v4 Uri => Methods.scala Text => empty Language => Scala -Symbols => 70 entries -Occurrences => 139 entries +Symbols => 77 entries +Occurrences => 149 entries Symbols: example/Methods# => class Methods @@ -1838,6 +1825,8 @@ example/Methods#``(). => primary ctor example/Methods#`m8().`(). => method m8(). example/Methods#`m9().`# => class m9(). example/Methods#`m9().`#``(). => primary ctor +example/Methods#`m20_=`(). => var method m20_= +example/Methods#`m20_=`().(x$1) => param x$1 example/Methods#m1(). => method m1 example/Methods#m2(). => method m2 example/Methods#m3(). => method m3 @@ -1896,6 +1885,11 @@ example/Methods#m19(). => method m19 example/Methods#m19().(x) => param x example/Methods#m19().(y) => param y example/Methods#m19().(z) => param z +example/Methods#m20(). => method m20 +example/Methods#m20().(a) => param a +example/Methods#m20(+1). => method m20 +example/Methods#m20(+1).(b) => param b +example/Methods#m20(+2). => var method m20 local0 => abstract val method x Occurrences: @@ -2038,6 +2032,16 @@ Occurrences: [35:30..35:31): z <- example/Methods#m19().(z) [35:33..35:36): Int -> scala/Int# [35:44..35:47): ??? -> scala/Predef.`???`(). +[36:6..36:9): m20 <- example/Methods#m20(). +[36:10..36:11): a <- example/Methods#m20().(a) +[36:13..36:16): Int -> scala/Int# +[36:20..36:23): ??? -> scala/Predef.`???`(). +[37:6..37:9): m20 <- example/Methods#m20(+1). +[37:10..37:11): b <- example/Methods#m20(+1).(b) +[37:13..37:19): String -> scala/Predef.String# +[37:23..37:26): ??? -> scala/Predef.`???`(). +[38:6..38:9): m20 <- example/Methods#m20(+2). +[38:12..38:15): m17 -> example/Methods#m17. expect/NamedApplyBlock.scala ---------------------------- From 8ac0e641e9d002b7b4043dbb9007145b9667f390 Mon Sep 17 00:00:00 2001 From: bishabosha Date: Tue, 19 May 2020 12:37:54 +0200 Subject: [PATCH 10/11] enable ReadPositions when Ysemanticdb is set --- compiler/src/dotty/tools/dotc/Compiler.scala | 7 ++++++- tests/neg/mixin-forwarder-clash2.check | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/Compiler.scala b/compiler/src/dotty/tools/dotc/Compiler.scala index a8bb0b72c10d..d7b7fa47ba08 100644 --- a/compiler/src/dotty/tools/dotc/Compiler.scala +++ b/compiler/src/dotty/tools/dotc/Compiler.scala @@ -146,6 +146,11 @@ class Compiler { def newRun(implicit ctx: Context): Run = { reset() - new Run(this, ctx) + val rctx = + if ctx.settings.Ysemanticdb.value + ctx.addMode(Mode.ReadPositions) + else + ctx + new Run(this, rctx) } } diff --git a/tests/neg/mixin-forwarder-clash2.check b/tests/neg/mixin-forwarder-clash2.check index 9c3b23847e1f..ee0318142d43 100644 --- a/tests/neg/mixin-forwarder-clash2.check +++ b/tests/neg/mixin-forwarder-clash2.check @@ -3,6 +3,6 @@ 1 |class Bar2 extends Bar1 with Two[Foo] // error | ^ | Name clash between inherited members: - | def concat(suffix: Int): X in trait One and - | def concat: [Dummy](suffix: Int): Y in trait Two + | def concat(suffix: Int): X in trait One at line 4 and + | def concat: [Dummy](suffix: Int): Y in trait Two at line 8 | have the same type after erasure. From bd906c40b735186a7e28853c896d6284d5f54d72 Mon Sep 17 00:00:00 2001 From: bishabosha Date: Tue, 19 May 2020 17:08:30 +0200 Subject: [PATCH 11/11] test throw and inlined defs --- .../dotc/semanticdb/ExtractSemanticDB.scala | 16 +++-- .../expect/inlineconsume.expect.scala | 6 ++ tests/semanticdb/expect/inlineconsume.scala | 6 ++ .../semanticdb/expect/inlinedefs.expect.scala | 19 ++++++ tests/semanticdb/expect/inlinedefs.scala | 19 ++++++ tests/semanticdb/metac.expect | 61 +++++++++++++++++++ 6 files changed, 122 insertions(+), 5 deletions(-) create mode 100644 tests/semanticdb/expect/inlineconsume.expect.scala create mode 100644 tests/semanticdb/expect/inlineconsume.scala create mode 100644 tests/semanticdb/expect/inlinedefs.expect.scala create mode 100644 tests/semanticdb/expect/inlinedefs.scala diff --git a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala index 28b1edc58a01..30a437e9b800 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala @@ -81,27 +81,33 @@ class ExtractSemanticDB extends Phase: || excludeDefOrUse(sym) private def excludeDefOrUse(sym: Symbol)(using Context): Boolean = - sym.name.is(NameKinds.DefaultGetterName) + !sym.exists + || sym.name.is(NameKinds.DefaultGetterName) || sym.isConstructor && (sym.owner.is(ModuleClass) || !sym.isGlobal) || excludeSymbol(sym) private def excludeSymbol(sym: Symbol)(using Context): Boolean = - sym.name.isWildcard + !sym.exists + || sym.name.isWildcard || excludeQual(sym) private def excludeQual(sym: Symbol)(using Context): Boolean = - sym.isAnonymousFunction + !sym.exists + || sym.isAnonymousFunction || sym.isAnonymousModuleVal || sym.name.isEmptyNumbered private def excludeChildren(sym: Symbol)(using Context): Boolean = - sym.isAllOf(HigherKinded | Param) + !sym.exists + || sym.isAllOf(HigherKinded | Param) /** Uses of this symbol where the reference has given span should be excluded from semanticdb */ private def excludeUse(qualifier: Option[Symbol], sym: Symbol)(using Context): Boolean = - excludeDefOrUse(sym) + !sym.exists + || excludeDefOrUse(sym) || sym.isConstructor && sym.owner.isAnnotation || sym == defn.Any_typeCast + || sym.owner == defn.OpsPackageClass || qualifier.exists(excludeQual) private def traverseAnnotsOfDefinition(sym: Symbol)(using Context): Unit = diff --git a/tests/semanticdb/expect/inlineconsume.expect.scala b/tests/semanticdb/expect/inlineconsume.expect.scala new file mode 100644 index 000000000000..8ffe432064d4 --- /dev/null +++ b/tests/semanticdb/expect/inlineconsume.expect.scala @@ -0,0 +1,6 @@ +package inlineconsume + +import inlinedefs.FakePredef/*->inlinedefs::FakePredef.*/.assert/*->inlinedefs::FakePredef.assert().*/ + +class Foo/*<-inlineconsume::Foo#*/: + def test/*<-inlineconsume::Foo#test().*/ = assert/*->inlinedefs::FakePredef.assert().*/(3 >/*->scala::Int#`>`(+3).*/ 2) diff --git a/tests/semanticdb/expect/inlineconsume.scala b/tests/semanticdb/expect/inlineconsume.scala new file mode 100644 index 000000000000..db7130c50515 --- /dev/null +++ b/tests/semanticdb/expect/inlineconsume.scala @@ -0,0 +1,6 @@ +package inlineconsume + +import inlinedefs.FakePredef.assert + +class Foo: + def test = assert(3 > 2) diff --git a/tests/semanticdb/expect/inlinedefs.expect.scala b/tests/semanticdb/expect/inlinedefs.expect.scala new file mode 100644 index 000000000000..c00563e8af07 --- /dev/null +++ b/tests/semanticdb/expect/inlinedefs.expect.scala @@ -0,0 +1,19 @@ +package inlinedefs + +object FakePredef/*<-inlinedefs::FakePredef.*/: + + def assertFail/*<-inlinedefs::FakePredef.assertFail().*/(): Nothing/*->scala::Nothing#*/ = throw new java.lang.AssertionError/*->java::lang::AssertionError#*//*->java::lang::AssertionError#``(+2).*/("assertion failed") + + /** Super long padded documentation + * Lorem ipsum dolor sit amet, consectetur adipiscing elit, + * sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + * Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris + * nisi ut aliquip ex ea commodo consequat. + * Duis aute irure dolor in reprehenderit in voluptate velit esse cillum + * dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, + * sunt in culpa qui officia deserunt mollit anim id est laborum. + */ + transparent inline final def assert/*<-inlinedefs::FakePredef.assert().*/(inline assertion/*<-inlinedefs::FakePredef.assert().(assertion)*/: Boolean/*->scala::Boolean#*/): Unit/*->scala::Unit#*/ = { + if (!assertion/*->inlinedefs::FakePredef.assert().(assertion)*//*->scala::Boolean#`unary_!`().*/) + assertFail/*->inlinedefs::FakePredef.assertFail().*/() + } diff --git a/tests/semanticdb/expect/inlinedefs.scala b/tests/semanticdb/expect/inlinedefs.scala new file mode 100644 index 000000000000..abb7039b1964 --- /dev/null +++ b/tests/semanticdb/expect/inlinedefs.scala @@ -0,0 +1,19 @@ +package inlinedefs + +object FakePredef: + + def assertFail(): Nothing = throw new java.lang.AssertionError("assertion failed") + + /** Super long padded documentation + * Lorem ipsum dolor sit amet, consectetur adipiscing elit, + * sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + * Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris + * nisi ut aliquip ex ea commodo consequat. + * Duis aute irure dolor in reprehenderit in voluptate velit esse cillum + * dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, + * sunt in culpa qui officia deserunt mollit anim id est laborum. + */ + transparent inline final def assert(inline assertion: Boolean): Unit = { + if (!assertion) + assertFail() + } diff --git a/tests/semanticdb/metac.expect b/tests/semanticdb/metac.expect index bb57f73c4f32..09ac1176b4af 100644 --- a/tests/semanticdb/metac.expect +++ b/tests/semanticdb/metac.expect @@ -2999,6 +2999,67 @@ Occurrences: [2:0..2:0): <- example/FilenameWithSpaces#``(). [2:6..2:24): FilenameWithSpaces <- example/FilenameWithSpaces# +expect/inlineconsume.scala +-------------------------- + +Summary: +Schema => SemanticDB v4 +Uri => inlineconsume.scala +Text => empty +Language => Scala +Symbols => 3 entries +Occurrences => 9 entries + +Symbols: +inlineconsume/Foo# => class Foo +inlineconsume/Foo#``(). => primary ctor +inlineconsume/Foo#test(). => method test + +Occurrences: +[0:8..0:21): inlineconsume <- inlineconsume/ +[2:7..2:17): inlinedefs -> inlinedefs/ +[2:18..2:28): FakePredef -> inlinedefs/FakePredef. +[2:29..2:35): assert -> inlinedefs/FakePredef.assert(). +[4:6..4:9): Foo <- inlineconsume/Foo# +[5:2..5:2): <- inlineconsume/Foo#``(). +[5:6..5:10): test <- inlineconsume/Foo#test(). +[5:13..5:19): assert -> inlinedefs/FakePredef.assert(). +[5:22..5:23): > -> scala/Int#`>`(+3). + +expect/inlinedefs.scala +----------------------- + +Summary: +Schema => SemanticDB v4 +Uri => inlinedefs.scala +Text => empty +Language => Scala +Symbols => 4 entries +Occurrences => 15 entries + +Symbols: +inlinedefs/FakePredef. => final object FakePredef +inlinedefs/FakePredef.assert(). => final macro assert +inlinedefs/FakePredef.assert().(assertion) => param assertion +inlinedefs/FakePredef.assertFail(). => method assertFail + +Occurrences: +[0:8..0:18): inlinedefs <- inlinedefs/ +[2:7..2:17): FakePredef <- inlinedefs/FakePredef. +[4:6..4:16): assertFail <- inlinedefs/FakePredef.assertFail(). +[4:20..4:27): Nothing -> scala/Nothing# +[4:40..4:44): java -> java/ +[4:45..4:49): lang -> java/lang/ +[4:50..4:64): AssertionError -> java/lang/AssertionError# +[4:64..4:64): -> java/lang/AssertionError#``(+2). +[15:31..15:37): assert <- inlinedefs/FakePredef.assert(). +[15:45..15:54): assertion <- inlinedefs/FakePredef.assert().(assertion) +[15:56..15:63): Boolean -> scala/Boolean# +[15:66..15:70): Unit -> scala/Unit# +[16:9..16:18): assertion -> inlinedefs/FakePredef.assert().(assertion) +[16:18..16:18): -> scala/Boolean#`unary_!`(). +[17:6..17:16): assertFail -> inlinedefs/FakePredef.assertFail(). + expect/local-file.scala -----------------------