diff --git a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala index aa1d7b102fb5..d282695c07fa 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala @@ -16,7 +16,6 @@ import NameOps._ import util.Spans.Span import util.{SourceFile, SourcePosition} import transform.SymUtils._ -import SymbolInformation.{Kind => k} import scala.jdk.CollectionConverters._ import scala.collection.mutable @@ -46,12 +45,13 @@ class ExtractSemanticDB extends Phase: val unit = ctx.compilationUnit val extractor = Extractor() extractor.extract(unit.tpdTree) - ExtractSemanticDB.write(unit.source, extractor.occurrences.toList, extractor.symbolInfos.toList) + ExtractSemanticDB.write(unit.source, extractor.occurrences.toList, extractor.symbolInfos.toList, extractor.synthetics.toList) /** Extractor of symbol occurrences from trees */ class Extractor extends TreeTraverser: given s.SemanticSymbolBuilder = s.SemanticSymbolBuilder() - val converter = s.TypeOps() + val synth = SyntheticsExtractor() + given converter: s.TypeOps = s.TypeOps() /** The bodies of synthetic locals */ private val localBodies = mutable.HashMap[Symbol, Tree]() @@ -62,6 +62,8 @@ class ExtractSemanticDB extends Phase: /** The extracted symbol infos */ val symbolInfos = new mutable.ListBuffer[SymbolInformation]() + val synthetics = new mutable.ListBuffer[s.Synthetic]() + /** A cache of localN names */ val localNames = new mutable.HashSet[String]() @@ -158,11 +160,13 @@ class ExtractSemanticDB extends Phase: tree match case tree: DefDef => tree.paramss.foreach(_.foreach(param => registerSymbolSimple(param.symbol))) - case tree: ValDef if tree.symbol.is(Given) => traverse(tree.tpt) + case tree: ValDef if tree.symbol.is(Given) => + traverse(tree.tpt) case _ => if !tree.symbol.isGlobal then localBodies(tree.symbol) = tree.rhs // ignore rhs + case PatternValDef(pat, rhs) => traverse(rhs) PatternValDef.collectPats(pat).foreach(traverse) @@ -179,6 +183,10 @@ class ExtractSemanticDB extends Phase: registerUseGuarded(None, privateWithin, spanOfSymbol(privateWithin, tree.span, tree.source), tree.source) else if !excludeSymbol(tree.symbol) then registerSymbol(tree.symbol, symbolKinds(tree)) + case tree: Template if tree.symbol.owner.is(Invisible) => + // do nothing + // exclude the symbols and synthetics generated by @main annotation + // (main class generated by @main has `Invisible` flag, see `MainProxies.scala`). case tree: Template => val ctorSym = tree.constr.symbol for parent <- tree.parentsOrDerived if parent.span.hasLength do @@ -197,6 +205,7 @@ class ExtractSemanticDB extends Phase: case tree: Apply => @tu lazy val genParamSymbol: Name => String = tree.fun.symbol.funParamSymbol traverse(tree.fun) + synth.tryFindSynthetic(tree).foreach(synthetics.addOne) for arg <- tree.args do arg match case tree @ NamedArg(name, arg) => @@ -292,12 +301,6 @@ class ExtractSemanticDB extends Phase: end PatternValDef - 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)) - private def registerSymbol(sym: Symbol, symkinds: Set[SymbolKind])(using Context): Unit = val sname = sym.symbolName @@ -338,24 +341,6 @@ class ExtractSemanticDB extends Phase: if !sym.is(Package) then registerSymbol(sym, symkinds) - private def namePresentInSource(sym: Symbol, span: Span, source:SourceFile)(using Context): Boolean = - if !span.exists then false - else - val content = source.content() - val (start, end) = - if content.lift(span.end - 1).exists(_ == '`') then - (span.start + 1, span.end - 1) - else (span.start, span.end) - val nameInSource = content.slice(start, end).mkString - // for secondary constructors `this` - if sym.isConstructor && nameInSource == nme.THISkw.toString then - true - else - val target = - if sym.isPackageObject then sym.owner - else sym - nameInSource == target.name.stripModuleClassSuffix.lastPart.toString - 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) @@ -466,7 +451,12 @@ object ExtractSemanticDB: val name: String = "extractSemanticDB" - def write(source: SourceFile, occurrences: List[SymbolOccurrence], symbolInfos: List[SymbolInformation])(using Context): Unit = + def write( + source: SourceFile, + occurrences: List[SymbolOccurrence], + symbolInfos: List[SymbolInformation], + synthetics: List[Synthetic], + )(using Context): Unit = def absolutePath(path: Path): Path = path.toAbsolutePath.normalize val semanticdbTarget = val semanticdbTargetSetting = ctx.settings.semanticdbTarget.value @@ -488,7 +478,8 @@ object ExtractSemanticDB: text = "", md5 = internal.MD5.compute(String(source.content)), symbols = symbolInfos, - occurrences = occurrences + occurrences = occurrences, + synthetics = synthetics, ) val docs = TextDocuments(List(doc)) val out = Files.newOutputStream(outpath) diff --git a/compiler/src/dotty/tools/dotc/semanticdb/PPrint.scala b/compiler/src/dotty/tools/dotc/semanticdb/PPrint.scala index edc9ad79518b..2f1e2b760f1c 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/PPrint.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/PPrint.scala @@ -5,8 +5,8 @@ import dotty.tools.dotc.{semanticdb => s} import scala.collection.mutable import dotty.tools.dotc.semanticdb.Scala3.{_, given} import SymbolInformation.Kind._ - -class SymbolInfomationPrinter (symtab: PrinterSymtab): +import dotty.tools.dotc.util.SourceFile +class SymbolInformationPrinter (symtab: PrinterSymtab): val notes = InfoNotes() val infoPrinter = InfoPrinter(notes) @@ -28,8 +28,9 @@ class SymbolInfomationPrinter (symtab: PrinterSymtab): val displayName = if sym.isGlobal then sym.desc.value else sym SymbolInformation(symbol = sym, displayName = displayName) } + end InfoNotes - class InfoPrinter(notes: InfoNotes) { + class InfoPrinter(notes: InfoNotes): private enum SymbolStyle: case Reference, Definition def pprint(info: SymbolInformation): String = @@ -81,7 +82,7 @@ class SymbolInfomationPrinter (symtab: PrinterSymtab): private def pprintDef(info: SymbolInformation) = notes.enter(info) pprint(info.symbol, SymbolStyle.Definition) - private def pprintRef(sym: String): String = pprint(sym, SymbolStyle.Reference) + def pprintRef(sym: String): String = pprint(sym, SymbolStyle.Reference) private def pprintDef(sym: String): String = pprint(sym, SymbolStyle.Definition) private def pprint(sym: String, style: SymbolStyle): String = val info = notes.visit(sym) @@ -137,7 +138,7 @@ class SymbolInfomationPrinter (symtab: PrinterSymtab): case _ => "" - private def pprint(tpe: Type): String = { + protected def pprint(tpe: Type): String = { def prefix(tpe: Type): String = tpe match case TypeRef(pre, sym, args) => val preStr = pre match { @@ -204,7 +205,7 @@ class SymbolInfomationPrinter (symtab: PrinterSymtab): case tpe => s"@${pprint(tpe)}" } - private def pprint(const: Constant): String = const match { + protected def pprint(const: Constant): String = const match { case Constant.Empty => "" case UnitConstant() => @@ -245,7 +246,6 @@ class SymbolInfomationPrinter (symtab: PrinterSymtab): s"private[${ssym}] " case ProtectedWithinAccess(ssym) => s"protected[${ssym}] " - extension (scope: Scope) private def infos: List[SymbolInformation] = if (scope.symlinks.nonEmpty) @@ -258,8 +258,8 @@ class SymbolInfomationPrinter (symtab: PrinterSymtab): case Some(s) => s.infos case None => Nil } - } -end SymbolInfomationPrinter + end InfoPrinter +end SymbolInformationPrinter extension (info: SymbolInformation) def prefixBeforeTpe: String = { @@ -280,3 +280,110 @@ object PrinterSymtab: new PrinterSymtab { override def info(symbol: String): Option[SymbolInformation] = map.get(symbol) } + +def processRange(sb: StringBuilder, range: Range): Unit = + sb.append('[') + .append(range.startLine).append(':').append(range.startCharacter) + .append("..") + .append(range.endLine).append(':').append(range.endCharacter) + .append("):") + + + +class SyntheticPrinter(symtab: PrinterSymtab, source: SourceFile) extends SymbolInformationPrinter(symtab): + + def pprint(synth: Synthetic): String = + val sb = new StringBuilder() + val notes = InfoNotes() + val treePrinter = TreePrinter(source, synth.range, notes) + + synth.range match + case Some(range) => + processRange(sb, range) + sb.append(source.substring(range)) + case None => + sb.append("[):") + sb.append(" => ") + sb.append(treePrinter.pprint(synth.tree)) + sb.toString + + extension (source: SourceFile) + private def substring(range: Option[s.Range]): String = + range match + case Some(range) => source.substring(range) + case None => "" + private def substring(range: s.Range): String = + /** get the line length of a given line */ + def lineLength(line: Int): Int = + val isLastLine = source.lineToOffsetOpt(line).nonEmpty && source.lineToOffsetOpt(line + 1).isEmpty + if isLastLine then source.content.length - source.lineToOffset(line) - 1 + else source.lineToOffset(line + 1) - source.lineToOffset(line) - 1 // -1 for newline char + + val start = source.lineToOffset(range.startLine) + + math.min(range.startCharacter, lineLength(range.startLine)) + val end = source.lineToOffset(range.endLine) + + math.min(range.endCharacter, lineLength(range.endLine)) + new String(source.content, start, end - start) + + + // def pprint(tree: s.Tree, range: Option[Range]): String = + class TreePrinter(source: SourceFile, originalRange: Option[Range], notes: InfoNotes) extends InfoPrinter(notes): + def pprint(tree: Tree): String = + val sb = new StringBuilder() + processTree(tree)(using sb) + sb.toString + + + private def rep[T](xs: Seq[T], seq: String)(f: T => Unit)(using sb: StringBuilder): Unit = + xs.zipWithIndex.foreach { (x, i) => + if i != 0 then sb.append(seq) + f(x) + } + + private def processTree(tree: Tree)(using sb: StringBuilder): Unit = + tree match { + case tree: ApplyTree => + processTree(tree.function) + sb.append("(") + rep(tree.arguments, ", ")(processTree) + sb.append(")") + case tree: FunctionTree => + sb.append("{") + sb.append("(") + rep(tree.parameters, ", ")(processTree) + sb.append(") =>") + processTree(tree.body) + sb.append("}") + case tree: IdTree => + sb.append(pprintRef(tree.symbol)) + case tree: LiteralTree => + sb.append(pprint(tree.constant)) + case tree: MacroExpansionTree => + sb.append("(`macro-expandee` : `") + sb.append(pprint(tree.tpe)) + sb.append(")") + case tree: OriginalTree => + if (tree.range == originalRange && originalRange.nonEmpty) then + sb.append("*") + else + sb.append("orig(") + sb.append(source.substring(tree.range)) + sb.append(")") + case tree: SelectTree => + processTree(tree.qualifier) + sb.append(".") + tree.id match + case Some(tree) => processTree(tree) + case None => () + case tree: TypeApplyTree => + processTree(tree.function) + sb.append("[") + rep(tree.typeArguments, ", ")((t) => sb.append(pprint(t))) + sb.append("]") + + case _ => + sb.append("") + } + + +end SyntheticPrinter diff --git a/compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala b/compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala index 504b49904a76..c8d418f236c7 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala @@ -10,6 +10,10 @@ import core.Flags._ import core.NameKinds import core.StdNames.nme import SymbolInformation.{Kind => k} +import dotty.tools.dotc.util.SourceFile +import dotty.tools.dotc.util.Spans.Span +import dotty.tools.dotc.ast.tpd +import dotty.tools.dotc.{semanticdb => s} import java.lang.Character.{isJavaIdentifierPart, isJavaIdentifierStart} @@ -26,6 +30,30 @@ object Scala3: private val WILDCARDTypeName = nme.WILDCARD.toTypeName + 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)) + + def namePresentInSource(sym: Symbol, span: Span, source:SourceFile)(using Context): Boolean = + if !span.exists then false + else + val content = source.content() + val (start, end) = + if content.lift(span.end - 1).exists(_ == '`') then + (span.start + 1, span.end - 1) + else (span.start, span.end) + val nameInSource = content.slice(start, end).mkString + // for secondary constructors `this` + if sym.isConstructor && nameInSource == nme.THISkw.toString then + true + else + val target = + if sym.isPackageObject then sym.owner + else sym + nameInSource == target.name.stripModuleClassSuffix.lastPart.toString + sealed trait FakeSymbol { private[Scala3] var sname: Option[String] = None } @@ -423,9 +451,7 @@ object Scala3: def hasLength = range.endLine > range.startLine || range.endCharacter > range.startCharacter end RangeOps - /** Sort symbol occurrences by their start position. */ - given OccurrenceOrdering: Ordering[SymbolOccurrence] = (x, y) => - x.range -> y.range match + private def compareRange(x: Option[Range], y: Option[Range]): Int = x -> y match case None -> _ | _ -> None => 0 case Some(a) -> Some(b) => val byLine = Integer.compare(a.startLine, b.startLine) @@ -433,10 +459,14 @@ object Scala3: byLine else // byCharacter Integer.compare(a.startCharacter, b.startCharacter) - end OccurrenceOrdering + + /** Sort symbol occurrences by their start position. */ + given Ordering[SymbolOccurrence] = (x, y) => compareRange(x.range, y.range) given Ordering[SymbolInformation] = Ordering.by[SymbolInformation, String](_.symbol)(IdentifierOrdering()) + given Ordering[Synthetic] = (x, y) => compareRange(x.range, y.range) + /** * A comparator for identifier like "Predef" or "Function10". * diff --git a/compiler/src/dotty/tools/dotc/semanticdb/SyntheticsExtractor.scala b/compiler/src/dotty/tools/dotc/semanticdb/SyntheticsExtractor.scala new file mode 100644 index 000000000000..c6d87c67a578 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/semanticdb/SyntheticsExtractor.scala @@ -0,0 +1,98 @@ +package dotty.tools.dotc.semanticdb + +import dotty.tools.dotc.ast.tpd._ +import dotty.tools.dotc.core.Contexts._ +import dotty.tools.dotc.core.Flags._ +import dotty.tools.dotc.core.StdNames.nme +import dotty.tools.dotc.{semanticdb => s} + +import scala.collection.mutable + +class SyntheticsExtractor: + import Scala3.{_, given} + + def tryFindSynthetic(tree: Tree)(using Context, SemanticSymbolBuilder, TypeOps): Option[s.Synthetic] = + extension (synth: s.Synthetic) + def toOpt: Some[s.Synthetic] = Some(synth) + + if tree.span.isSynthetic then + tree match + case tree: Apply if isForSynthetic(tree) => + None // not yet supported (for synthetics) + case tree: Apply + if tree.args.nonEmpty && + tree.args.forall(arg => + arg.symbol.isOneOf(GivenOrImplicit) && + arg.span.isSynthetic + ) => + s.Synthetic( + range(tree.span, tree.source), + s.ApplyTree( + tree.fun.toSemanticOriginal, + tree.args.map(_.toSemanticTree) + ) + ).toOpt + + case tree: Apply if tree.fun.symbol.is(Implicit) => + val pos = range(tree.span, tree.source) + s.Synthetic( + pos, + s.ApplyTree( + tree.fun.toSemanticTree, + arguments = List( + s.OriginalTree(pos) + ) + ) + ).toOpt + + case _ => None + else None + + private given TreeOps: AnyRef with + extension (tree: Tree) + def toSemanticTree(using Context, SemanticSymbolBuilder, TypeOps): s.Tree = + tree match + case tree: Apply => + s.ApplyTree( + tree.fun.toSemanticQualifierTree, + tree.args.map(_.toSemanticTree) + ) + case tree: TypeApply => + s.TypeApplyTree( + tree.fun.toSemanticQualifierTree, + tree.args.map { targ => + targ.tpe.toSemanticType(targ.symbol)(using LinkMode.SymlinkChildren) + } + ) + case tree: Ident => tree.toSemanticId + case tree: Select => tree.toSemanticId + case _ => s.Tree.defaultInstance + + def toSemanticQualifierTree(using Context, SemanticSymbolBuilder): s.Tree = tree match + case sel @ Select(qual, _) if sel.symbol.owner != qual.symbol => + s.SelectTree(qual.toSemanticId, Some(sel.toSemanticId)) + case fun => fun.toSemanticId + + def toSemanticId(using Context, SemanticSymbolBuilder) = + s.IdTree(tree.symbol.symbolName) + + def toSemanticOriginal(using Context) = + s.OriginalTree(range(tree.span, tree.source)) + end TreeOps + + + private def isForSynthetic(tree: Tree): Boolean = + def isForComprehensionSyntheticName(select: Select): Boolean = + select.span.toSynthetic == select.qualifier.span.toSynthetic && ( + select.name == nme.map || + select.name == nme.flatMap || + select.name == nme.withFilter || + select.name == nme.foreach + ) + tree match + case Apply(fun, _) => isForSynthetic(fun) + case TypeApply(fun, _) => isForSynthetic(fun) + case select: Select => isForComprehensionSyntheticName(select) + case _ => false + +end SyntheticsExtractor diff --git a/compiler/src/dotty/tools/dotc/semanticdb/Tools.scala b/compiler/src/dotty/tools/dotc/semanticdb/Tools.scala index ec427523195e..54b57f7c6a2f 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/Tools.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/Tools.scala @@ -53,9 +53,10 @@ object Tools: def metac(doc: TextDocument, realPath: Path)(using sb: StringBuilder): StringBuilder = val symtab = PrinterSymtab.fromTextDocument(doc) - val symPrinter = SymbolInfomationPrinter(symtab) + val symPrinter = SymbolInformationPrinter(symtab) val realURI = realPath.toString - given SourceFile = SourceFile.virtual(doc.uri, doc.text) + given sourceFile: SourceFile = SourceFile.virtual(doc.uri, doc.text) + val synthPrinter = SyntheticPrinter(symtab, sourceFile) sb.append(realURI).nl sb.append("-" * realURI.length).nl sb.nl @@ -66,6 +67,8 @@ object Tools: sb.append("Language => ").append(languageString(doc.language)).nl sb.append("Symbols => ").append(doc.symbols.length).append(" entries").nl sb.append("Occurrences => ").append(doc.occurrences.length).append(" entries").nl + if doc.synthetics.nonEmpty then + sb.append("Synthetics => ").append(doc.synthetics.length).append(" entries").nl sb.nl sb.append("Symbols:").nl doc.symbols.sorted.foreach(s => processSymbol(s, symPrinter)) @@ -73,6 +76,11 @@ object Tools: sb.append("Occurrences:").nl doc.occurrences.sorted.foreach(processOccurrence) sb.nl + if doc.synthetics.nonEmpty then + sb.append("Synthetics:").nl + doc.synthetics.sorted.foreach(s => processSynth(s, synthPrinter)) + sb.nl + sb end metac private def schemaString(schema: Schema) = @@ -92,17 +100,16 @@ object Tools: case UNKNOWN_LANGUAGE | Unrecognized(_) => "unknown" end languageString - private def processSymbol(info: SymbolInformation, printer: SymbolInfomationPrinter)(using sb: StringBuilder): Unit = + private def processSymbol(info: SymbolInformation, printer: SymbolInformationPrinter)(using sb: StringBuilder): Unit = sb.append(printer.pprintSymbolInformation(info)).nl + private def processSynth(synth: Synthetic, printer: SyntheticPrinter)(using sb: StringBuilder): Unit = + sb.append(printer.pprint(synth)).nl + private def processOccurrence(occ: SymbolOccurrence)(using sb: StringBuilder, sourceFile: SourceFile): Unit = occ.range match case Some(range) => - sb.append('[') - .append(range.startLine).append(':').append(range.startCharacter) - .append("..") - .append(range.endLine).append(':').append(range.endCharacter) - .append("):") + processRange(sb, range) if range.endLine == range.startLine && range.startCharacter != range.endCharacter && !(occ.symbol.isConstructor && occ.role.isDefinition) then diff --git a/compiler/src/dotty/tools/dotc/semanticdb/TypeOps.scala b/compiler/src/dotty/tools/dotc/semanticdb/TypeOps.scala index b71327b4c28a..963a153388a3 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/TypeOps.scala @@ -215,7 +215,7 @@ class TypeOps: } loop(tpe) - private def toSemanticType(sym: Symbol)(using LinkMode, SemanticSymbolBuilder, Context): s.Type = + def toSemanticType(sym: Symbol)(using LinkMode, SemanticSymbolBuilder, Context): s.Type = import ConstantOps._ def loop(tpe: Type): s.Type = tpe match { case t if t.isFromJavaObject => @@ -409,6 +409,9 @@ class TypeOps: case _: MatchType => s.Type.Empty + case tvar: TypeVar => + loop(tvar.stripped) + case _ => s.Type.Empty } diff --git a/tests/semanticdb/expect/Synthetic.expect.scala b/tests/semanticdb/expect/Synthetic.expect.scala index 271d3013c0ae..b6b14fe6de81 100644 --- a/tests/semanticdb/expect/Synthetic.expect.scala +++ b/tests/semanticdb/expect/Synthetic.expect.scala @@ -47,4 +47,15 @@ class Synthetic/*<-example::Synthetic#*/ { if a/*->local8*/ scala::Int#`<`(+3).*/ b/*->local9*/ } yield a/*->local8*/ + object Contexts/*<-example::Synthetic#Contexts.*/ { + def foo/*<-example::Synthetic#Contexts.foo().*/(x/*<-example::Synthetic#Contexts.foo().(x)*/: Int/*->scala::Int#*/)(using Int/*->scala::Int#*/) = ???/*->scala::Predef.`???`().*/ + def m1/*<-example::Synthetic#Contexts.m1().*/(using Int/*->scala::Int#*/) = foo/*->example::Synthetic#Contexts.foo().*/(0) + def m2/*<-example::Synthetic#Contexts.m2().*/(using x/*<-example::Synthetic#Contexts.m2().(x)*/: Int/*->scala::Int#*/) = foo/*->example::Synthetic#Contexts.foo().*/(0) + def m3/*<-example::Synthetic#Contexts.m3().*/ = + given x/*<-local10*/: Int/*->scala::Int#*/ = 1 + foo/*->example::Synthetic#Contexts.foo().*/(x/*->local10*/) + def m4/*<-example::Synthetic#Contexts.m4().*/ = + given Int/*->scala::Int#*/ = 1 + foo/*->example::Synthetic#Contexts.foo().*/(0) + } } diff --git a/tests/semanticdb/expect/Synthetic.scala b/tests/semanticdb/expect/Synthetic.scala index 484e07098877..10d13e936468 100644 --- a/tests/semanticdb/expect/Synthetic.scala +++ b/tests/semanticdb/expect/Synthetic.scala @@ -47,4 +47,15 @@ class Synthetic { if a < b } yield a + object Contexts { + def foo(x: Int)(using Int) = ??? + def m1(using Int) = foo(0) + def m2(using x: Int) = foo(0) + def m3 = + given x: Int = 1 + foo(x) + def m4 = + given Int = 1 + foo(0) + } } diff --git a/tests/semanticdb/expect/toplevel.expect.scala b/tests/semanticdb/expect/toplevel.expect.scala index 67164c326def..6348125a2afd 100644 --- a/tests/semanticdb/expect/toplevel.expect.scala +++ b/tests/semanticdb/expect/toplevel.expect.scala @@ -4,4 +4,5 @@ def combine/*<-_empty_::toplevel$package.combine(+1).*/(x/*<-_empty_::toplevel$p def combine/*<-_empty_::toplevel$package.combine(+2).*/ = 0 def foo/*<-_empty_::toplevel$package.foo().*/ = "foo" @main/*->scala::main#*/ def MyProgram/*<-_empty_::toplevel$package.MyProgram().*/(times/*<-_empty_::toplevel$package.MyProgram().(times)*/: Int/*->scala::Int#*/): Unit/*->scala::Unit#*/ = (1 to/*->scala::runtime::RichInt#to().*/ times/*->_empty_::toplevel$package.MyProgram().(times)*/) foreach/*->scala::collection::immutable::Range#foreach().*/ (_ => println/*->scala::Predef.println(+1).*/("hello")) +@main/*->scala::main#*/ def readInts/*<-_empty_::toplevel$package.readInts().*/(ints/*<-_empty_::toplevel$package.readInts().(ints)*/: Int/*->scala::Int#*/*): Unit/*->scala::Unit#*/ = println/*->scala::Predef.println(+1).*/(ints/*->_empty_::toplevel$package.readInts().(ints)*/.mkString/*->scala::collection::IterableOnceOps#mkString(+1).*/(",")) def fooRef/*<-_empty_::toplevel$package.fooRef().*/ = toplevel$package.foo/*->_empty_::toplevel$package.foo().*/ diff --git a/tests/semanticdb/expect/toplevel.scala b/tests/semanticdb/expect/toplevel.scala index e6af17e14953..c4340efcf212 100644 --- a/tests/semanticdb/expect/toplevel.scala +++ b/tests/semanticdb/expect/toplevel.scala @@ -4,4 +4,5 @@ def combine(x: Int, y: Int, z: Int) = x + y + z def combine = 0 def foo = "foo" @main def MyProgram(times: Int): Unit = (1 to times) foreach (_ => println("hello")) +@main def readInts(ints: Int*): Unit = println(ints.mkString(",")) def fooRef = toplevel$package.foo diff --git a/tests/semanticdb/metac.expect b/tests/semanticdb/metac.expect index d66bf1dc17dd..1c95e06cae7c 100644 --- a/tests/semanticdb/metac.expect +++ b/tests/semanticdb/metac.expect @@ -50,6 +50,7 @@ Text => empty Language => Scala Symbols => 48 entries Occurrences => 105 entries +Synthetics => 3 entries Symbols: advanced/C# => class C [typeparam T ] extends Object { self: C[T] => +3 decls } @@ -208,6 +209,11 @@ Occurrences: [48:37..48:38): x -> advanced/HKClass#foo().(x) [48:39..48:47): toString -> scala/Tuple2#toString(). +Synthetics: +[26:12..26:16):s.s1 => reflectiveSelectable(*) +[28:12..28:16):s.s2 => reflectiveSelectable(*) +[30:12..30:16):s.s3 => reflectiveSelectable(*) + expect/Annotations.scala ------------------------ @@ -1228,6 +1234,7 @@ Text => empty Language => Scala Symbols => 26 entries Occurrences => 50 entries +Synthetics => 1 entries Symbols: ext/Extension$package. => final package object ext extends Object { self: ext.type => +6 decls } @@ -1309,6 +1316,9 @@ Occurrences: [17:48..17:49): F -> ext/Functor#[F] [17:50..17:51): U -> ext/Functor#map().[U] +Synthetics: +[14:46..14:61):summon[Read[T]] => *(x$2) + expect/ForComprehension.scala ----------------------------- @@ -1505,6 +1515,7 @@ Text => empty Language => Scala Symbols => 23 entries Occurrences => 48 entries +Synthetics => 6 entries Symbols: example/ImplicitConversion# => class ImplicitConversion extends Object { self: ImplicitConversion => +9 decls } @@ -1581,6 +1592,16 @@ Occurrences: [34:56..34:57): + -> java/lang/String#`+`(). [34:58..34:63): other -> example/ImplicitConversion.newAny2stringadd#`+`().(other) +Synthetics: +[15:2..15:9):message => augmentString(*) +[17:2..17:7):tuple => newAny2stringadd[Tuple2[Int, Int]](*) +[20:15..20:22):message => string2Number(*) +[24:2..26:16):s"""Hello + |$message + |$number""" => augmentString(*) +[28:15..28:19):char => char2int(*) +[29:16..29:20):char => char2long(*) + expect/Imports.scala -------------------- @@ -1685,6 +1706,7 @@ Text => empty Language => Scala Symbols => 45 entries Occurrences => 61 entries +Synthetics => 3 entries Symbols: givens/InventedNames$package. => final package object givens extends Object { self: givens.type => +24 decls } @@ -1796,6 +1818,11 @@ Occurrences: [41:8..41:17): given_Z_T -> givens/InventedNames$package.given_Z_T(). [41:18..41:24): String -> scala/Predef.String# +Synthetics: +[24:0..24:0): => *(x$1) +[34:8..34:20):given_Double => *(intValue) +[40:8..40:15):given_Y => *(given_X) + expect/Issue1749.scala ---------------------- @@ -1806,6 +1833,7 @@ Text => empty Language => Scala Symbols => 7 entries Occurrences => 22 entries +Synthetics => 3 entries Symbols: example/Issue1749# => class Issue1749 extends Object { self: Issue1749 => +3 decls } @@ -1840,6 +1868,11 @@ Occurrences: [13:49..13:55): String -> scala/Predef.String# [14:2..14:5): map -> example/Issue1854#map. +Synthetics: +[8:2..8:10):(x1, x1) => orderingToOrdered[Tuple2[Int, Int]](*) +[8:2..8:10):(x1, x1) => *(Tuple2(Int, Int)) +[8:10..8:10): => *(Int, Int) + expect/Local.scala ------------------ @@ -1992,6 +2025,7 @@ Text => empty Language => Scala Symbols => 3 entries Occurrences => 80 entries +Synthetics => 1 entries Symbols: example/MethodUsages# => class MethodUsages extends Object { self: MethodUsages => +2 decls } @@ -2080,6 +2114,9 @@ Occurrences: [34:4..34:7): m20 -> example/Methods#m20(+2). [34:8..34:9): m -> example/Methods#m17.m(). +Synthetics: +[13:2..13:26):m.m7(m, new m.List[Int]) => *(Int) + expect/Methods.scala -------------------- @@ -2654,6 +2691,7 @@ Text => empty Language => Scala Symbols => 68 entries Occurrences => 110 entries +Synthetics => 1 entries Symbols: example/C# => class C extends Object { self: C => +3 decls } @@ -2837,6 +2875,9 @@ Occurrences: [32:49..32:56): pickOne -> example/SpecialRefinement#pickOne(). [32:57..32:59): as -> example/PickOneRefinement_1#run().(as) +Synthetics: +[15:23..15:34):elems.toMap => *(refl[Tuple2[String, Any]]) + expect/RightAssociativeExtension.scala -------------------------------------- @@ -2922,11 +2963,22 @@ Schema => SemanticDB v4 Uri => Synthetic.scala Text => empty Language => Scala -Symbols => 40 entries -Occurrences => 112 entries +Symbols => 52 entries +Occurrences => 133 entries +Synthetics => 21 entries Symbols: -example/Synthetic# => class Synthetic extends Object { self: Synthetic => +21 decls } +example/Synthetic# => class Synthetic extends Object { self: Synthetic => +23 decls } +example/Synthetic#Contexts. => final object Contexts extends Object { self: Contexts.type => +6 decls } +example/Synthetic#Contexts.foo(). => method foo (param x: Int)(implicit given param x$2: Int): Nothing +example/Synthetic#Contexts.foo().(x$2) => implicit given param x$2: Int +example/Synthetic#Contexts.foo().(x) => param x: Int +example/Synthetic#Contexts.m1(). => method m1 (implicit given param x$1: Int): Nothing +example/Synthetic#Contexts.m1().(x$1) => implicit given param x$1: Int +example/Synthetic#Contexts.m2(). => method m2 (implicit given param x: Int): Nothing +example/Synthetic#Contexts.m2().(x) => implicit given param x: Int +example/Synthetic#Contexts.m3(). => method m3 => Nothing +example/Synthetic#Contexts.m4(). => method m4 => Nothing example/Synthetic#F# => class F extends Object { self: F => +1 decls } example/Synthetic#F#``(). => primary ctor (): F example/Synthetic#J# => class J [typeparam T ] extends Object { self: J[T] => +4 decls } @@ -2966,6 +3018,8 @@ local6 => param a: Int local7 => param b: Int local8 => param a: Int local9 => param b: Int +local10 => final implicit lazy val given local x: Int +local11 => final implicit lazy val given local given_Int: Int Occurrences: [0:8..0:15): example <- example/ @@ -3080,6 +3134,50 @@ Occurrences: [46:9..46:10): < -> scala/Int#`<`(+3). [46:11..46:12): b -> local9 [47:10..47:11): a -> local8 +[49:9..49:17): Contexts <- example/Synthetic#Contexts. +[50:8..50:11): foo <- example/Synthetic#Contexts.foo(). +[50:12..50:13): x <- example/Synthetic#Contexts.foo().(x) +[50:15..50:18): Int -> scala/Int# +[50:26..50:29): Int -> scala/Int# +[50:33..50:36): ??? -> scala/Predef.`???`(). +[51:8..51:10): m1 <- example/Synthetic#Contexts.m1(). +[51:17..51:20): Int -> scala/Int# +[51:24..51:27): foo -> example/Synthetic#Contexts.foo(). +[52:8..52:10): m2 <- example/Synthetic#Contexts.m2(). +[52:17..52:18): x <- example/Synthetic#Contexts.m2().(x) +[52:20..52:23): Int -> scala/Int# +[52:27..52:30): foo -> example/Synthetic#Contexts.foo(). +[53:8..53:10): m3 <- example/Synthetic#Contexts.m3(). +[54:12..54:13): x <- local10 +[54:15..54:18): Int -> scala/Int# +[55:6..55:9): foo -> example/Synthetic#Contexts.foo(). +[55:10..55:11): x -> local10 +[56:8..56:10): m4 <- example/Synthetic#Contexts.m4(). +[57:12..57:15): Int -> scala/Int# +[58:6..58:9): foo -> example/Synthetic#Contexts.foo(). + +Synthetics: +[6:2..6:18):Array.empty[Int] => intArrayOps(*) +[7:2..7:8):"fooo" => augmentString(*) +[10:13..10:24):"name:(.*)" => augmentString(*) +[13:8..13:28):2 #:: LazyList.empty => toDeferrer[Int](*) +[13:14..13:28):LazyList.empty => toDeferrer[Nothing](*) +[17:18..17:38):2 #:: LazyList.empty => toDeferrer[Int](*) +[17:24..17:38):LazyList.empty => toDeferrer[Nothing](*) +[19:12..19:13):1 => intWrapper(*) +[19:26..19:27):0 => intWrapper(*) +[19:46..19:47):x => ArrowAssoc[Int](*) +[20:12..20:13):1 => intWrapper(*) +[20:26..20:27):0 => intWrapper(*) +[21:12..21:13):1 => intWrapper(*) +[21:26..21:27):0 => intWrapper(*) +[32:35..32:49):Array.empty[T] => *(evidence$1) +[36:22..36:27):new F => orderingToOrdered[F](*) +[36:22..36:27):new F => *(ordering) +[51:24..51:30):foo(0) => *(x$1) +[52:27..52:33):foo(0) => *(x) +[55:6..55:12):foo(x) => *(x) +[58:6..58:12):foo(0) => *(given_Int) expect/Traits.scala ------------------- @@ -4510,15 +4608,14 @@ Schema => SemanticDB v4 Uri => toplevel.scala Text => empty Language => Scala -Symbols => 19 entries -Occurrences => 34 entries +Symbols => 18 entries +Occurrences => 42 entries +Synthetics => 1 entries Symbols: _empty_/MyProgram# => final class MyProgram extends Object { self: MyProgram => +2 decls } -_empty_/MyProgram#``(). => primary ctor (): MyProgram -_empty_/MyProgram#main(). => static method main (param args: Array[String]): Unit -_empty_/MyProgram#main().(args) => param args: Array[String] -_empty_/toplevel$package. => final package object _empty_ extends Object { self: _empty_.type => +8 decls } +_empty_/readInts# => final class readInts extends Object { self: readInts => +2 decls } +_empty_/toplevel$package. => final package object _empty_ extends Object { self: _empty_.type => +9 decls } _empty_/toplevel$package.MyProgram(). => method MyProgram (param times: Int): Unit _empty_/toplevel$package.MyProgram().(times) => param times: Int _empty_/toplevel$package.a. => val inline method a "" @@ -4532,7 +4629,8 @@ _empty_/toplevel$package.combine(+1).(z) => param z: Int _empty_/toplevel$package.combine(+2). => method combine => Int _empty_/toplevel$package.foo(). => method foo => String _empty_/toplevel$package.fooRef(). => method fooRef => String -local0 => val local error: ParseError +_empty_/toplevel$package.readInts(). => method readInts (param ints: Int*): Unit +_empty_/toplevel$package.readInts().(ints) => param ints: Int* Occurrences: [0:11..0:12): a <- _empty_/toplevel$package.a. @@ -4567,6 +4665,17 @@ Occurrences: [5:46..5:51): times -> _empty_/toplevel$package.MyProgram().(times) [5:53..5:60): foreach -> scala/collection/immutable/Range#foreach(). [5:67..5:74): println -> scala/Predef.println(+1). -[6:4..6:10): fooRef <- _empty_/toplevel$package.fooRef(). -[6:30..6:33): foo -> _empty_/toplevel$package.foo(). +[6:1..6:5): main -> scala/main# +[6:10..6:18): readInts <- _empty_/toplevel$package.readInts(). +[6:19..6:23): ints <- _empty_/toplevel$package.readInts().(ints) +[6:25..6:28): Int -> scala/Int# +[6:32..6:36): Unit -> scala/Unit# +[6:39..6:46): println -> scala/Predef.println(+1). +[6:47..6:51): ints -> _empty_/toplevel$package.readInts().(ints) +[6:52..6:60): mkString -> scala/collection/IterableOnceOps#mkString(+1). +[7:4..7:10): fooRef <- _empty_/toplevel$package.fooRef(). +[7:30..7:33): foo -> _empty_/toplevel$package.foo(). + +Synthetics: +[5:41..5:42):1 => intWrapper(*)