diff --git a/benchmark/PerformanceOfSemanticDBGenerationUsingTastyQuery.csv b/benchmark/PerformanceOfSemanticDBGenerationUsingTastyQuery.csv new file mode 100644 index 0000000000..4d2c8a1367 --- /dev/null +++ b/benchmark/PerformanceOfSemanticDBGenerationUsingTastyQuery.csv @@ -0,0 +1,19 @@ +Metric,File,Trial 1,Trial 2,Trial 3,Trial 4,Trial 5,Trial 6,Trial 7,Trial 8,Trial 9,Trial 10,Mean,Error Margin (95% Confidence),Standard Deviation,Confidence Interval (95%) +Elapsed Time Creating Ctx (millisecond),VariousFeatures.scala,89,85,84,80,89,92,81,84,85,83,85.2,2.21,3.57,"[82.99, 87.41]" +Elapsed Time Creating Ctx (millisecond),LargeClass.scala,103,90,91,96,94,97,94,98,91,91,94.5,2.40,3.88,"[92.1, 96.9]" +Elapsed Time Creating Ctx (millisecond),SimpleClass.scala,88,84,83,83,83,84,106,91,88,93,88.3,4.22,6.81,"[84.08, 92.52]" +Elapsed Time Symbol List (millisecond),VariousFeatures.scala,453,434,423,415,462,443,444,484,472,492,452.2,14.93,24.09,"[437.27, 467.13]" +Elapsed Time Symbol List (millisecond),LargeClass.scala,452,457,450,414,441,497,449,430,437,428,445.5,13.13,21.19,"[432.37, 458.63]" +Elapsed Time Symbol List (millisecond),SimpleClass.scala,417,412,407,398,425,421,429,446,447,431,423.3,9.30,15.00,"[414., 432.6]" +Elapsed Time Creating TastyExtractSemanticDB (millisecond),VariousFeatures.scala,544,521,508,496,552,536,526,569,560,577,538.9,15.55,25.08,"[523.35, 554.45]" +Elapsed Time Creating TastyExtractSemanticDB (millisecond),LargeClass.scala,557,549,543,511,537,595,544,530,530,520,541.6,13.64,22.01,"[527.96, 555.24]" +Elapsed Time Creating TastyExtractSemanticDB (millisecond),SimpleClass.scala,506,497,491,482,509,507,537,538,536,525,512.8,11.88,19.17,"[500.92, 524.68]" +Elapsed Time writeSemanticDB (millisecond),VariousFeatures.scala,189,183,169,171,178,179,172,175,175,175,176.6,3.51,5.66,"[173.09, 180.11]" +Elapsed Time writeSemanticDB (millisecond),LargeClass.scala,319,316,337,339,328,325,333,336,345,329,330.7,5.34,8.61,"[325.36, 336.04]" +Elapsed Time writeSemanticDB (millisecond),SimpleClass.scala,102,105,99,103,108,121,108,107,101,106,106,3.58,5.78,"[102.42, 109.58]" +New Time (millisecond),VariousFeatures.scala,744,715,687,675,742,728,708,754,744,762,725.9,17.04,27.49,"[708.86, 742.94]" +New Time (millisecond),LargeClass.scala,888,878,889,863,875,932,889,876,888,862,884,11.58,18.69,"[872.42, 895.58]" +New Time (millisecond),SimpleClass.scala,618,612,599,595,626,636,657,656,646,644,628.9,13.22,21.33,"[615.68, 642.12]" +Reference Time (millisecond),VariousFeatures.scala,89,93,80,81,78,102,91,91,92,88,88.5,4.23,6.83,"[84.27, 92.73]" +Reference Time (millisecond),SimpleClass.scala,86,90,92,82,93,84,84,97,81,90,87.9,3.10,5.01,"[84.8, 91.]" +Reference Time (millisecond),LargeClass.scala,167,165,163,166,168,181,167,169,161,173,168,3.30,5.33,"[164.7, 171.3]" \ No newline at end of file diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 6a8a88a429..c31d683131 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -506,5 +506,7 @@ private sealed trait YSettings: // Deprecated: Scheduled for removal @deprecated(message = "Scheduled for removal.", since = "3.5.0") val YoutputOnlyTasty: Setting[Boolean] = BooleanSetting(ForkSetting, "Youtput-only-tasty", "Used to only generate the TASTy file without the classfiles", deprecation = Deprecation.removed()) + val YproduceSemanticdbUsingTasty: Setting[Boolean] = BooleanSetting(ForkSetting, "Ysdb-using-tasty", "Produce the SemanticDB using Tasty") + end YSettings diff --git a/compiler/src/dotty/tools/dotc/sbt/LazyTastyQueryClasspath.scala b/compiler/src/dotty/tools/dotc/sbt/LazyTastyQueryClasspath.scala new file mode 100644 index 0000000000..bbc6c822bd --- /dev/null +++ b/compiler/src/dotty/tools/dotc/sbt/LazyTastyQueryClasspath.scala @@ -0,0 +1,137 @@ +/* +Adapted from: +https://github.com/scalacenter/tasty-query/pull/371 +https://github.com/scalacenter/scala-debug-adapter/blob/main/modules/decoder/src/main/scala/ch/epfl/scala/debugadapter/internal/stacktrace/CustomClasspath.scala + */ + +package dotty.tools.dotc +package sbt + +import tastyquery.Classpaths as tqcp +import tastyquery.Classpaths.{Classpath as TQClasspath, ClasspathEntry as TQClasspathEntry, + PackageData as TQPackageData, ClassData as TQClassData} +import tastyquery.Contexts as tqctxs +import tastyquery.Contexts.{Context as TQContext, ctx as tqctx} + +import dotty.tools.io.ClassPath +import dotty.tools.dotc.core.Contexts.* +import dotty.tools.dotc.ScalacCommand +import dotty.tools.io.AbstractFile +import dotty.tools.dotc.classpath.PackageEntry +import dotty.tools.dotc.Compiler +import dotty.tools.dotc.classpath.AggregateClassPath +import dotty.tools.io.FileZipArchive + +object LazyTastyQueryClasspath: + class DotcEntry(debugName: String, cp: ClassPath) extends TQClasspathEntry: + override def toString(): String = debugName + + def replaceSuffix(cls: AbstractFile, oldSuffix: String, newSuffix: String): Option[AbstractFile] = + val dir = cls match + case cls: FileZipArchive#Entry => cls.parent + case cls: AbstractFile => cls.container + val name = cls.name.stripSuffix(oldSuffix) + newSuffix + Option(dir.lookupName(name, directory = false)) + + lazy val _packages: List[DotcPackageData] = + def loadClasses(pkg: PackageEntry): List[DotcClassData] = + cp.classes(pkg.name).toList.map(cls => + val binary = cls.binary + val suffix = binary.flatMap(_.name.split('.').lastOption) + val (classRaw, tastyRaw) = suffix match + case Some("class") => + (binary, binary.flatMap(replaceSuffix(_, ".class", ".tasty"))) + case Some("tasty") => + (binary.flatMap(replaceSuffix(_, ".tasty", ".class")), binary) + case _ => + (None, None) + + DotcClassData(s"$debugName:${pkg.name}.${cls.name}", cls.name, classRaw, tastyRaw) + ) + + def loadPackage(pkg: PackageEntry): DotcPackageData = + val name = pkg.name + DotcPackageData(s"$debugName:$name", name, () => loadClasses(pkg)) + def loadSubPackages(name: String): List[DotcPackageData] = + cp.packages(name).toList.flatMap(pkg => loadPackage(pkg) :: loadSubPackages(pkg.name)) + loadSubPackages("") + + override def listAllPackages(): List[DotcPackageData] = _packages + end DotcEntry + + class DotcPackageData(val debugName: String, override val dotSeparatedName: String, fetchClasses: () => List[DotcClassData]) extends TQPackageData: + override def toString(): String = debugName + + private lazy val _classes: List[DotcClassData] = + fetchClasses() + + private lazy val _byName: Map[String, DotcClassData] = _classes.map(cls => cls.binaryName -> cls).toMap + + override def listAllClassDatas(): List[DotcClassData] = _classes + + override def getClassDataByBinaryName(binaryName: String): Option[DotcClassData] = _byName.get(binaryName) + end DotcPackageData + + + def patchBytes(bytes: Array[Byte]): IArray[Byte] = + bytes(4) = (28 | 0x80).toByte // major version + bytes(5) = (5 | 0x80).toByte // minor version + bytes(6) = (0 | 0x80).toByte // experimental + IArray.unsafeFromArray(bytes) + + class DotcClassData(val debugName: String, override val binaryName: String, cls: Option[AbstractFile], tsty: Option[AbstractFile]) extends TQClassData: + override def toString(): String = debugName + + private lazy val _tastyFileBytesPatched: IArray[Byte] = patchBytes(tsty.get.toByteArray) + + override def readClassFileBytes(): IArray[Byte] = + IArray.unsafeFromArray(cls.get.toByteArray) + + override def hasClassFile: Boolean = cls.exists(_.exists) + + override def readTastyFileBytes(): IArray[Byte] = + _tastyFileBytesPatched + + override def hasTastyFile: Boolean = tsty.exists(_.exists) + end DotcClassData + + class InMemoryEntry(debugName: String, packages: List[InMemoryPackageData]) extends TQClasspathEntry: + override def toString(): String = debugName + + override def listAllPackages(): List[InMemoryPackageData] = packages + end InMemoryEntry + + class InMemoryPackageData(val debugName: String, override val dotSeparatedName: String, fetchClasses: () => List[InMemoryTasty]) extends TQPackageData: + override def toString(): String = debugName + + private lazy val _classes: List[InMemoryTasty] = fetchClasses() + + private lazy val _byName: Map[String, InMemoryTasty] = _classes.map(cls => cls.binaryName -> cls).toMap + + override def listAllClassDatas(): List[InMemoryTasty] = _classes + + override def getClassDataByBinaryName(binaryName: String): Option[InMemoryTasty] = _byName.get(binaryName) + end InMemoryPackageData + + class InMemoryTasty(val debugName: String, override val binaryName: String, val tsty: () => Array[Byte]) extends TQClassData: + override def toString(): String = debugName + + lazy val _tastyFileBytesPatched: IArray[Byte] = patchBytes(tsty().clone()) + + override def readClassFileBytes(): IArray[Byte] = IArray.empty + + override def hasClassFile: Boolean = false + + override def hasTastyFile: Boolean = true + + override def readTastyFileBytes(): IArray[Byte] = _tastyFileBytesPatched + end InMemoryTasty + + + def makeClasspath(using Context): TQClasspath = + def flattenClasspath(cp: ClassPath): List[ClassPath] = cp match + case ag: AggregateClassPath => ag.aggregates.flatMap(flattenClasspath).toList + case _ => List(cp) + flattenClasspath(ctx.base.platform.classPath).map(cp => DotcEntry(cp.asClassPathString, cp)) + +end LazyTastyQueryClasspath \ No newline at end of file diff --git a/compiler/src/dotty/tools/dotc/sbt/tastyquery/TastyQueryExtensions.scala b/compiler/src/dotty/tools/dotc/sbt/tastyquery/TastyQueryExtensions.scala new file mode 100644 index 0000000000..2d77919cef --- /dev/null +++ b/compiler/src/dotty/tools/dotc/sbt/tastyquery/TastyQueryExtensions.scala @@ -0,0 +1,201 @@ +package dotty.tools.dotc + +import tastyquery.Contexts.* +import tastyquery.Symbols.* +import tastyquery.Types.* +import tastyquery.Names.* +import tastyquery.Modifiers.* +import tastyquery.Trees.* + +import scala.annotation.tailrec +import tastyquery.Names +import dotty.tools.dotc.core.SourceLanguage +import dotty.tools.dotc.core.StdNames.str + +extension (name: TermName) def isPackageObjectName: Boolean = name match + case SimpleName(name) => name == "package" || name.endsWith("package$") + case _ => false + +extension (name: TypeName) def isPackageObjectClassName: Boolean = name match + case ObjectClassTypeName(underlying) => underlying.toTermName.isPackageObjectName + case _ => false + +extension (sym: dotty.tools.dotc.semanticdb.Scala3.TastyFakeSymbol){ + def SDBFakeSymName (using builder: SDBSymbolNameBuilder)(using Context): String = + builder.symbolName(sym) +} +object Extensions: + extension (name: Name)(using Context) + def toTermName: TermName = name match + case name: TypeName => name.toTermName + case name: TermName => name + end toTermName + + def toTypeName: TypeName = name match + case name: TypeName => name + case name: TermName => name.toTypeName + end toTypeName + + end extension + + extension (sym: Symbol)(using Context) + def SDBname (using builder: SDBSymbolNameBuilder): String = + builder.symbolName(sym) + + /** Is this symbol the root class or its companion object? */ + def isRoot: Boolean = + (sym.owner == null) && sym.name.toTermName == Names.nme.RootName || sym.name == Names.nme.UserLandRootPackageName + + /** Is this symbol the empty package class or its companion object? */ + def isEmptyPackage: Boolean = + val owner = sym.owner + sym.name.toTermName == Names.nme.EmptyPackageName && owner != null && owner.isRoot + end isEmptyPackage + + /** Is this symbol the empty package class or its companion object? */ + def isEffectiveRoot: Boolean = sym.isRoot || sym.isEmptyPackage + + def isConstructor: Boolean = + sym.name == nme.Constructor + end isConstructor + def isPrimary: Boolean = + sym.owner match + case owner: ClassSymbol => owner.tree.get.rhs.constr.symbol == sym + case _ => false + def isTopLevel: Boolean = + val owner = sym.owner + owner != null && owner.isPackage + + /** Is this symbol directly owner by a term symbol, i.e., is it local to a block? */ + def isLocalToBlock: Boolean = + val owner = sym.owner + owner != null && owner.isTerm + + /** Is symbol directly or indirectly owned by a term symbol? */ + @tailrec final def isLocal: Boolean = { + val owner = sym.owner + if (owner == null) false + else if (isLocalToBlock) true + else if (owner.isPackage) false + else owner.isLocal + } + + private inline def predicateAs[T <: Symbol](inline p: T => Boolean): Boolean = (sym: @unchecked) match + case sym: T => p(sym) + case _ => false + end predicateAs + + // `ClassSymbol` predicates + def isTrait: Boolean = + predicateAs[ClassSymbol](_.isTrait) + end isTrait + + def isAbstractClass: Boolean = + predicateAs[ClassSymbol](_.isAbstractClass) + end isAbstractClass + + private inline def hasOpenLevel(inline level: OpenLevel): Boolean = + predicateAs[ClassSymbol](_.openLevel == level) + end hasOpenLevel + + def isFinal: Boolean = sym match + case sym: ClassSymbol => sym.openLevel == OpenLevel.Final + case sym: TermOrTypeSymbol => sym.isFinalMember + case _ => false + end isFinal + + def isSealed: Boolean = + hasOpenLevel(OpenLevel.Sealed) + end isSealed + + def isPackageClass: Boolean = + sym.isPackage + end isPackageClass + + // `TermSymbol` predicates + + def isAbstractOverride: Boolean = + predicateAs[TermSymbol](_.isAbstractOverride) + end isAbstractOverride + + def isAbstractMember: Boolean = + predicateAs[TermSymbol](_.isAbstractMember) + end isAbstractMember + + def isCovariant: Boolean = + predicateAs[ClassTypeParamSymbol](_.variance == Variance.Covariant) + end isCovariant + def isContravariant: Boolean = + predicateAs[ClassTypeParamSymbol](_.variance == Variance.Contravariant) + end isContravariant + + def isEnum: Boolean = + predicateAs[ClassSymbol](_.isEnum) + end isEnum + + def isGivenOrUsing: Boolean = + predicateAs[TermSymbol](_.isGivenOrUsing) + end isGivenOrUsing + + def isJavaDefined: Boolean = + predicateAs[TermOrTypeSymbol](_.sourceLanguage == SourceLanguage.Java) + end isJavaDefined + + def isImplicit: Boolean = + predicateAs[TermSymbol](_.isImplicit) + end isImplicit + + private inline def hasKind(kind: TermSymbolKind): Boolean = + predicateAs[TermSymbol](_.kind == kind) + end hasKind + + def isLazyVal: Boolean = + hasKind(TermSymbolKind.LazyVal) + end isLazyVal + + def isMacro: Boolean = + predicateAs[TermSymbol](_.isMacro) + end isMacro + def isStableMember: Boolean = + predicateAs[TermSymbol](_.isStableMember) + end isStableMember + def isInline: Boolean = + predicateAs[TermSymbol](_.isInline) + end isInline + + def isMethod: Boolean = + predicateAs[TermSymbol](_.isMethod) + end isMethod + + def isVar: Boolean = + predicateAs[TermSymbol](_.kind == TermSymbolKind.Var) + end isVar + + def isModuleVal: Boolean = + predicateAs[TermSymbol](_.isModuleVal) + end isModuleVal + + + def isParamWithDefault: Boolean = + predicateAs[TermSymbol](_.isParamWithDefault) + end isParamWithDefault + + def isParamAccessor: Boolean = + predicateAs[TermSymbol](_.isParamAccessor) + end isParamAccessor + def isGlobal: Boolean = + sym.isPackage || ((sym.isInstanceOf[TermOrTypeSymbol] && sym.asInstanceOf[TermOrTypeSymbol].isParam) || (sym.owner!= null && (sym.owner.nn.isClass || sym.owner.isPackage))) + && (sym.owner!= null && sym.owner.nn.isGlobal) + end isGlobal + end extension + + extension (sym: TermOrTypeSymbol) + def isParam: Boolean = + sym.owner.isTerm && sym.owner.asTerm.isTerm + && sym.owner.asTerm.paramSymss.exists { p => + p match + case Left(termParams) => termParams.contains(sym) + case Right(typeParams) => typeParams.contains(sym) + } + +end Extensions \ No newline at end of file diff --git a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala index 05dff8ffad..25d619838a 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala @@ -78,7 +78,9 @@ class ExtractSemanticDB private (phaseMode: ExtractSemanticDB.PhaseMode) extends } private def extractSemanticDB(sourceRoot: String, writeSemanticdbText: Boolean)(using Context): Boolean = + monitor(phaseName) { + val unit = ctx.compilationUnit val outputDir = ExtractSemanticDB.semanticdbPath( @@ -86,40 +88,39 @@ class ExtractSemanticDB private (phaseMode: ExtractSemanticDB.PhaseMode) extends ExtractSemanticDB.semanticdbOutDir, sourceRoot ) + ExtractSemanticDB.savedUnit = Some(unit) + ExtractSemanticDB.savedOutputDir = Some(outputDir) val extractor = ExtractSemanticDB.Extractor() extractor.extract(unit.tpdTree) - ExtractSemanticDB.write( - unit.source, - extractor.occurrences.toList, - extractor.symbolInfos.toList, - extractor.synthetics.toList, - outputDir, - sourceRoot, - writeSemanticdbText - ) + ExtractSemanticDB.write(unit.source,extractor.occurrences.toList,extractor.symbolInfos.toList,extractor.synthetics.toList,outputDir,sourceRoot,writeSemanticdbText) } override def runOn(units: List[CompilationUnit])(using ctx: Context): List[CompilationUnit] = { val sourceRoot = ctx.settings.sourceroot.value val appendDiagnostics = phaseMode == ExtractSemanticDB.PhaseMode.AppendDiagnostics val unitContexts = units.map(ctx.fresh.setCompilationUnit(_).withRootImports) - if (appendDiagnostics) - val warnings = ctx.reporter.allWarnings.groupBy(w => w.pos.source) - val buf = mutable.ListBuffer.empty[(Path, Seq[Diagnostic])] - val units0 = - for unitCtx <- unitContexts if computeDiagnostics(sourceRoot, warnings, buf += _)(using unitCtx) - yield unitCtx.compilationUnit - cancellable { - buf.toList.asJava.parallelStream().forEach { case (out, warnings) => - ExtractSemanticDB.appendDiagnostics(warnings, out) + ExtractSemanticDB.unitContexts = Some(unitContexts) + if (!ctx.settings.YproduceSemanticdbUsingTasty.value){ + if (appendDiagnostics) + val warnings = ctx.reporter.allWarnings.groupBy(w => w.pos.source) + val buf = mutable.ListBuffer.empty[(Path, Seq[Diagnostic])] + val units0 = + for unitCtx <- unitContexts if computeDiagnostics(sourceRoot, warnings, buf += _)(using unitCtx) + yield unitCtx.compilationUnit + cancellable { + buf.toList.asJava.parallelStream().forEach { case (out, warnings) => + ExtractSemanticDB.appendDiagnostics(warnings, out) + } } - } - units0 - else - val writeSemanticdbText = ctx.settings.semanticdbText.value - for unitCtx <- unitContexts if extractSemanticDB(sourceRoot, writeSemanticdbText)(using unitCtx) - yield unitCtx.compilationUnit + units0 + else + val writeSemanticdbText = ctx.settings.semanticdbText.value + val result = for unitCtx <- unitContexts if extractSemanticDB(sourceRoot, writeSemanticdbText)(using unitCtx) + yield unitCtx.compilationUnit + result } + else for unitCtx <- unitContexts yield unitCtx.compilationUnit +} def run(using Context): Unit = unsupported("run") end ExtractSemanticDB @@ -131,7 +132,9 @@ object ExtractSemanticDB: val phaseNamePrefix: String = "extractSemanticDB" val description: String = "extract info into .semanticdb files" - + var savedUnit: Option[dotty.tools.dotc.CompilationUnit] = None + var savedOutputDir: Option[java.nio.file.Path] = None + var unitContexts: Option[List[dotty.tools.dotc.core.Contexts.Context]] = None enum PhaseMode: case ExtractSemanticInfo case AppendDiagnostics @@ -150,12 +153,13 @@ object ExtractSemanticDB: ctx.settings.outputDir.value /** Output directory for SemanticDB files */ - private def semanticdbOutDir(using Context): Path = + def semanticdbOutDir(using Context): Path = + semanticdbTarget.getOrElse(outputDirectory.jpath) private def absolutePath(path: Path): Path = path.toAbsolutePath.normalize - private def write( + def write( source: SourceFile, occurrences: List[SymbolOccurrence], symbolInfos: List[SymbolInformation], @@ -206,7 +210,7 @@ object ExtractSemanticDB: private def relPath(source: SourceFile, sourceRoot: String) = SourceFile.relativePath(source, sourceRoot) - private def semanticdbPath(source: SourceFile, base: Path, sourceRoot: String): Path = + def semanticdbPath(source: SourceFile, base: Path, sourceRoot: String): Path = absolutePath(base) .resolve("META-INF") .resolve("semanticdb") @@ -437,7 +441,7 @@ object ExtractSemanticDB: synth.tryFindSynthetic(tree).foreach(synthetics.addOne) traverseChildren(tree) - case tree: TypeTree => + case tree: TypeTree => //this is where the Int in the Example(x: Int) is registered tree.typeOpt match // Any types could be appear inside of `TypeTree`, but // types that precent in source other than TypeRef are traversable and contain Ident tree nodes @@ -527,8 +531,7 @@ object ExtractSemanticDB: private def registerUse(sym: Symbol, span: Span, treeSource: SourceFile)(using Context): Unit = registerUse(sym.symbolName, span, treeSource) - private def registerUse(symbol: String, span: Span, treeSource: SourceFile)(using Context): Unit = - registerOccurrence(symbol, span, SymbolOccurrence.Role.REFERENCE, treeSource) + 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], treeSource: SourceFile)(using Context) = val sname = sym.symbolName diff --git a/compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala b/compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala index f49b000897..811e12c92c 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala @@ -60,6 +60,36 @@ object Scala3: // println(name.mangledString) nameInSource == name.mangledString + import dotty.tools.dotc.SDBSymbolNameBuilder + import dotty.tools.dotc.Extensions.SDBname + import dotty.tools.dotc.SDBFakeSymName + sealed trait TastyFakeSymbol { + var sname: Option[String] = None + } + + case class TastyWildcardTypeSymbol(owner: tastyquery.Symbols.Symbol, bounds: tastyquery.Types.TypeBounds) extends TastyFakeSymbol + case class TastyTermParamRefSymbol(owner: tastyquery.Symbols.Symbol, name: tastyquery.Names.Name, tp: tastyquery.Types.Type) extends TastyFakeSymbol + case class TastyTypeParamRefSymbol(owner: tastyquery.Symbols.Symbol, name: tastyquery.Names.Name, tp: tastyquery.Types.TypeBounds) extends TastyFakeSymbol + case class TastyRefinementSymbol(owner: tastyquery.Symbols.Symbol, name: tastyquery.Names.Name, tp: tastyquery.Types.Type) extends TastyFakeSymbol + extension (sym: TastySemanticSymbol) + def name: tastyquery.Names.Name = sym match + case s: tastyquery.Symbols.Symbol => s.name + case s: TastyWildcardTypeSymbol => tastyquery.Names.SimpleName("_") + case s: TastyTermParamRefSymbol => s.name + case s: TastyTypeParamRefSymbol => s.name + case s: TastyRefinementSymbol => s.name + + def symbolName(using tastyquery.Contexts.Context, SDBSymbolNameBuilder): String = + sym match + case s: tastyquery.Symbols.Symbol => s.SDBname + case s: TastyFakeSymbol => + s.sname.getOrElse { + val sname = s.SDBFakeSymName + s.sname = Some(sname) + sname + } + type TastySemanticSymbol = tastyquery.Symbols.Symbol | TastyFakeSymbol + sealed trait FakeSymbol { private[Scala3] var sname: Option[String] = None } @@ -70,7 +100,6 @@ object Scala3: * - SymbolInformation with signature TypeSignature of given type bound. */ case class WildcardTypeSymbol(owner: Symbol, bounds: TypeBounds) extends FakeSymbol - case class TermParamRefSymbol(owner: Symbol, name: Name, tp: Type) extends FakeSymbol case class TypeParamRefSymbol(owner: Symbol, name: Name, tp: TypeBounds) extends FakeSymbol case class RefinementSymbol(owner: Symbol, name: Name, tp: Type) extends FakeSymbol diff --git a/compiler/src/dotty/tools/dotc/semanticdb/TastyExtractSemanticDB.scala b/compiler/src/dotty/tools/dotc/semanticdb/TastyExtractSemanticDB.scala new file mode 100644 index 0000000000..d2e35bbd6c --- /dev/null +++ b/compiler/src/dotty/tools/dotc/semanticdb/TastyExtractSemanticDB.scala @@ -0,0 +1,501 @@ +package dotty.tools.dotc + +import dotty.tools.dotc.sbt.* +import tastyquery.Names as tqn +import tastyquery.Classpaths.* +import tastyquery.Symbols.* +import tastyquery.Names.* +import tastyquery.Symbols.* +import core.* +import Contexts.* +import tastyquery.Contexts.Context +import tastyquery.Trees.* +import tastyquery.Symbols.* + +import tastyquery.Classpaths.* +import scala.collection.mutable.{Map, ArrayBuffer} +import dotty.tools.dotc.semanticdb.ExtractSemanticDB + + +import dotty.tools.dotc.Extensions.* +import dotty.tools.dotc.config.Settings.* +import dotty.tools.dotc.semanticdb.Range.* +import dotty.tools.dotc.config.Settings.Setting.value +import dotty.tools.dotc.semanticdb.SymbolInformation +import dotty.tools.dotc.semanticdb.SymbolInformation.Kind.PACKAGE_OBJECT.isPackageObject +import dotty.tools.dotc.semanticdb.Scala3.SymbolKind +import tastyquery.Types.NoPrefix +import tastyquery.Types.* +import tastyquery.Annotations +import dotty.tools.dotc.core.Annotations.Annotation +import dotty.tools.dotc.semanticdb.SymbolInformation.Kind.* +import dotty.tools.dotc.semanticdb.PrivateThisAccess +import dotty.tools.dotc.semanticdb.Access +import dotty.tools.dotc.semanticdb.PrivateAccess +import dotty.tools.dotc.semanticdb.ProtectedThisAccess +import dotty.tools.dotc.semanticdb.AccessMessage.SealedValue.ProtectedAccess +import dotty.tools.dotc.semanticdb.AccessMessage.SealedValue.ProtectedWithinAccess +import dotty.tools.dotc.semanticdb.PrivateWithinAccess +import dotty.tools.dotc.semanticdb.PublicAccess +import tastyquery.Modifiers.TermSymbolKind +import tastyquery.Modifiers.Visibility +import tastyquery.Modifiers.Variance +import dotty.tools.dotc.SDBtype.toSemanticSig +import dotty.tools.dotc.semanticdb.LinkMode +import scala.collection.mutable.ListBuffer +import dotty.tools.dotc.semanticdb.Scala3.symbolName +import dotty.tools.dotc.SDBtype.toSemanticType +import dotty.tools.dotc.SymbolScopeOps.sscopeOpt +import dotty.tools.dotc.semanticdb.Scala3.StringOps +import tastyquery.SourcePosition +import dotty.tools.dotc.semanticdb.SymbolOccurrence +import scala.collection.mutable + import dotty.tools.dotc.SymbolScopeOps.sscopeOpt +import dotty.tools.dotc.ast.Trees.NamedDefTree +import tastyquery.Traversers.TreeTraverser +import dotty.tools.dotc.semanticdb.Scala3.name +import dotty.tools.dotc.semanticdb.Synthetic +import dotty.tools.dotc.semanticdb.SemanticSymbolBuilder +import dotty.tools.dotc.semanticdb.Scala3.TastyFakeSymbol + + + + +import dotty.tools.dotc.SDBSymbolNameBuilder +import dotty.tools.dotc.core.StdNames.str + +extension (sym : Symbol){ + + def symbolProps(symkinds: Set[SymbolKind])(using Context): Int = + + var props = 0 + if sym.isTerm && sym.asTerm.isPrimary then + props |= SymbolInformation.Property.PRIMARY.value + if sym.isFinal then + props |= SymbolInformation.Property.FINAL.value + if sym.isSealed then + props |= SymbolInformation.Property.SEALED.value + if sym.isGivenOrUsing || sym.isImplicit then + props |= SymbolInformation.Property.IMPLICIT.value + if sym.isLazyVal then + props |= SymbolInformation.Property.LAZY.value + if sym.isCovariant then + props |= SymbolInformation.Property.COVARIANT.value + if sym.isContravariant then + props |= SymbolInformation.Property.CONTRAVARIANT.value + if symkinds.exists(_.isVal) then + props |= SymbolInformation.Property.VAL.value + if symkinds.exists(_.isVar) then + props |= SymbolInformation.Property.VAR.value + props + + def symbolAccess(kind: SymbolInformation.Kind )(using Context, SDBSymbolNameBuilder): Access = { + kind match + case LOCAL => Access.Empty + case PARAMETER => Access.Empty + case SELF_PARAMETER => Access.Empty + case TYPE_PARAMETER => Access.Empty + case PACKAGE => Access.Empty + case PACKAGE_OBJECT => Access.Empty + case _ => + sym.asInstanceOf[TermOrTypeSymbol].visibility match + case Visibility.PrivateThis => PrivateThisAccess() + case tastyquery.Modifiers.Visibility.Private => dotty.tools.dotc.semanticdb.PrivateAccess() + case Visibility.ProtectedThis => dotty.tools.dotc.semanticdb.ProtectedThisAccess() + case tastyquery.Modifiers.Visibility.Protected => dotty.tools.dotc.semanticdb.ProtectedAccess() + case Visibility.ScopedProtected(scope) => scope match + case x: ClassSymbol => + val ssym = x.SDBname + x.visibility match + case Visibility.ProtectedThis => dotty.tools.dotc.semanticdb.ProtectedWithinAccess(ssym) + case Visibility.ScopedProtected(scope) => dotty.tools.dotc.semanticdb.ProtectedWithinAccess(ssym) + case _ => dotty.tools.dotc.semanticdb.PrivateWithinAccess(ssym) + + case x: PackageSymbol => PublicAccess() + case Visibility.ScopedPrivate(scope) =>scope match + case x: ClassSymbol => + val ssym = x.SDBname + x.visibility match + case Visibility.ProtectedThis => dotty.tools.dotc.semanticdb.ProtectedWithinAccess(ssym) + case Visibility.ScopedProtected(scope) => dotty.tools.dotc.semanticdb.PrivateWithinAccess(ssym) + case _ => PrivateWithinAccess(ssym) + case _: PackageSymbol => PublicAccess() + + case Visibility.Public => PublicAccess() + } + + def symbolKind(symkinds: Set[SymbolKind])(using ctx: Context): SymbolInformation.Kind = { + + if sym.isType && sym.isInstanceOf[TypeParamSymbol] then + SymbolInformation.Kind.TYPE_PARAMETER + else if sym.isTerm && sym.asTerm.isParam then + SymbolInformation.Kind.PARAMETER + else if sym.isTerm && sym.isLocal then + SymbolInformation.Kind.LOCAL + else if sym.isMacro then + SymbolInformation.Kind.MACRO + else if sym.isConstructor then + SymbolInformation.Kind.CONSTRUCTOR + else if sym.isMethod || symkinds.exists(_.isVarOrVal) then + SymbolInformation.Kind.METHOD + else if sym.isClass && sym.asClass.name.isPackageObjectClassName then + SymbolInformation.Kind.PACKAGE_OBJECT + else if sym.isModuleVal then + SymbolInformation.Kind.OBJECT + else if sym.isPackage then + SymbolInformation.Kind.PACKAGE + else if sym.isTrait then + SymbolInformation.Kind.TRAIT + else if sym.isClass then + SymbolInformation.Kind.CLASS + else if sym.isType then + SymbolInformation.Kind.TYPE + else if sym.isParamAccessor then + SymbolInformation.Kind.FIELD + else + SymbolInformation.Kind.UNKNOWN_KIND + } + def overriddenSymbols(using Context, SDBSymbolNameBuilder): List[String] = + sym match + case x: TermOrTypeSymbol => x.allOverriddenSymbols.map(_.SDBname).toList + case x: PackageSymbol => List.empty + + def symbolAnnotations(using ctx: Context)(using SDBSymbolNameBuilder): List[dotty.tools.dotc.semanticdb.Annotation] = + val child = ctx.findTopLevelClass("scala.annotation.internal.Child") + val body = ctx.findTopLevelClass("scala.annotation.internal.Body") + + sym.annotations.collect{ + case annot + if annot.symbol != child + && annot.symbol != body + && false + => dotty.tools.dotc.semanticdb.Annotation(annot.tree.tpe.toSemanticType(sym.SDBname, Some(annot.symbol.asInstanceOf[TermSymbol]))) + + } + + def replaceUnitInMethodType(methodType: TypeOrMethodic, newResultType: Type)(using ctx: Context): TypeOrMethodic = { + val unitSym = ctx.defn.scalaPackage.findDecl(typeName("Unit")) + methodType match + case mt: MethodType => + val newResult = replaceUnitInMethodType(mt.resultType, newResultType) + + MethodType(mt.paramNames, mt.paramInfos, newResult) + MethodType(mt.paramNames)( + pt2 => mt.instantiateParamTypes(pt2.paramRefs), + pt2 => replaceUnitInMethodType(mt.instantiate(pt2.paramRefs), newResultType) + ) + case pt: PolyType => + PolyType(pt.paramNames)( + pt2 => pt.instantiateParamTypeBounds(pt2.paramRefs), + pt2 => replaceUnitInMethodType(pt.instantiate(pt2.paramRefs), newResultType) + ) + case t : TypeRef if t.optSymbol.contains(unitSym) => + newResultType + case _ => methodType + } + + def symbolInfo(symkinds: Set[SymbolKind])(using ctx: Context)(using SDBSymbolNameBuilder): SymbolInformation = { + val kind = sym.symbolKind(symkinds) + + sym match + case termSymbol: TermSymbol => { + + val kind = sym.symbolKind(symkinds) + val annotations = termSymbol.symbolAnnotations + val signature = if (kind == SymbolInformation.Kind.CONSTRUCTOR) then { + val nonTranformed = termSymbol.declaredType + val res = replaceUnitInMethodType(nonTranformed, termSymbol.owner.asClass.appliedRefInsideThis) + res.toSemanticSig(using LinkMode.SymlinkChildren)(sym.asInstanceOf[TermSymbol]) + } + else { + + termSymbol.declaredType.toSemanticSig(using LinkMode.SymlinkChildren)(sym.asInstanceOf[TermSymbol]) + } + + SymbolInformation( + symbol = sym.SDBname, + language = dotty.tools.dotc.semanticdb.Language.SCALA, + kind = kind, + properties = symbolProps(symkinds), + displayName = termSymbol.name.toString(), + access = termSymbol.symbolAccess(kind), + overriddenSymbols = termSymbol.overriddenSymbols, + annotations = termSymbol.symbolAnnotations, + signature = signature + ) + + } + + case typeSymbol : TypeMemberSymbol => { + val signature = typeSymbol.declaredBounds.high.toSemanticSig(using LinkMode.SymlinkChildren)(typeSymbol) + SymbolInformation( + symbol = sym.SDBname, + language = dotty.tools.dotc.semanticdb.Language.SCALA, + kind = kind, + properties = symbolProps(symkinds), + displayName = sym.name.toString(), + overriddenSymbols = sym.overriddenSymbols, + signature = signature + ) + } + + case classSymbol: ClassSymbol => { + + val stparams = classSymbol.typeParams.sscopeOpt(using LinkMode.SymlinkChildren) + val sparents = classSymbol.parents.map(_.toSemanticType(sym.SDBname, None)) + val sself = classSymbol.appliedRefInsideThis.toSemanticType(sym.SDBname, None) + val typeParams = classSymbol.typeParams.toSet + val declsSet = classSymbol.declarations.toSet + val decls = (typeParams ++ declsSet).toList.sscopeOpt(using LinkMode.SymlinkChildren) + val signature = semanticdb.ClassSignature(stparams, sparents, sself, decls) + + SymbolInformation( + symbol = sym.SDBname, + language = dotty.tools.dotc.semanticdb.Language.SCALA, + kind = kind, + properties = symbolProps(symkinds), + displayName = sym.name.toString(), + overriddenSymbols = sym.overriddenSymbols, + signature = signature + ) + } + case _ => { + SymbolInformation( + symbol = sym.SDBname, + language = dotty.tools.dotc.semanticdb.Language.SCALA, + kind = kind, + properties = symbolProps(symkinds), + displayName = sym.name.toString(), + overriddenSymbols = sym.overriddenSymbols + ) + }} +} + + +class CustomTreeTraverser(sourceFilePath: String)(using ctx: Context)(using SDBSymbolNameBuilder) extends TreeTraverser: + val sdbStringBuilder = new SDBSymbolNameBuilder() + val extractor = TastyPositionExtractor(sourceFilePath) + + private def registerSymbol(sym: Symbol, symkinds: Set[SymbolKind])(using Context, SDBSymbolNameBuilder): Unit = + val sname = sym.SDBname + val isLocal = sname.isLocal + if !isLocal || !localNames.contains(sname) then + if isLocal then + localNames += sname + symbolInfos += sym.symbolInfo(symkinds) + + + private def registerSymbolSimple(sym: Symbol)(using Context, SDBSymbolNameBuilder): Unit = { + registerSymbol(sym, Set.empty) + } + + private def registerDefinition(sym: Symbol, span: SourcePosition, symkinds: Set[SymbolKind], extractor: TastyPositionExtractor)(using Context, SDBSymbolNameBuilder) = + val sname = sym.SDBname + registerSymbol(sym, symkinds) + + private def registerOccurrence(symbol: Symbol, range: Option[dotty.tools.dotc.semanticdb.Range], role: SymbolOccurrence.Role)(using Context, SDBSymbolNameBuilder): Unit = + val occ = SymbolOccurrence(range, symbol.SDBname, role) + if !generated.contains(occ) && occ.symbol.nonEmpty && !range.isEmpty then + occurrences += occ + generated += occ + + private def registerOccurrence(symbol: Symbol, span: SourcePosition, role: SymbolOccurrence.Role)(using Context, SDBSymbolNameBuilder): Unit = + val range = if span.isUnknown then None else + val result = extractor.extract(symbol.name.toString(), span, symbol) + Some(result) + registerOccurrence(symbol, range, role) + + private def registerOccurrence(symbol: Symbol, otherSymbol: Symbol, otherSymbolSpan: SourcePosition, role: SymbolOccurrence.Role)(using Context, SDBSymbolNameBuilder): Unit = + val range = if otherSymbolSpan.isUnknown then None else + val result = extractor.extract(otherSymbol.name.toString(), otherSymbolSpan, otherSymbol) + Some(result) + + registerOccurrence(symbol, range, role) + + private def registerOccurrence(symbol: Symbol, symbolName: String, span: SourcePosition, role: SymbolOccurrence.Role)(using Context, SDBSymbolNameBuilder): Unit = + val range = if span.isUnknown then None else + val result = extractor.extract(symbolName, span, symbol) + Some(result) + + val occ = SymbolOccurrence(range, symbolName, role) + if !generated.contains(occ) && occ.symbol.nonEmpty && !range.isEmpty then + occurrences += occ + generated += occ + + val synthetics = new ListBuffer[Synthetic]() + val symbolInfos = new ListBuffer[SymbolInformation]() + val occurrences = new ListBuffer[SymbolOccurrence]() + val localNames = new mutable.HashSet[String]() + private val generated = new mutable.HashSet[SymbolOccurrence] + override def traverse(tree: Tree): Unit = + + val pos = tree.pos + tree match + case namedTree: (DefTree) => + namedTree match + case defDef: DefDef => + defDef.paramLists.foreach{namedTree => + namedTree match + case Left(listValDef) => + listValDef.foreach(namedTree => + + registerSymbolSimple(namedTree.symbol)(using ctx, sdbStringBuilder) + if (!defDef.symbol.isConstructor){ + if !namedTree.pos.isZeroExtent then + registerOccurrence(namedTree.symbol, namedTree.pos, dotty.tools.dotc.semanticdb.SymbolOccurrence.Role.DEFINITION) + } + super.traverse(namedTree) + ) + case Right(listTypeParam) => + listTypeParam.foreach(namedTree => + + + if (!defDef.symbol.isConstructor){ + registerSymbolSimple(namedTree.symbol)(using ctx, sdbStringBuilder) + if !namedTree.pos.isZeroExtent then + registerOccurrence(namedTree.symbol, namedTree.pos, dotty.tools.dotc.semanticdb.SymbolOccurrence.Role.DEFINITION) + } + super.traverse(namedTree) + ) + } + traverse(defDef.resultTpt) + defDef.rhs match + case None => + case Some(value) => traverse(value) + registerDefinition(namedTree.symbol, pos, symbolKinds(namedTree), extractor) + if (defDef.symbol.isConstructor) then + registerOccurrence(namedTree.symbol, pos, dotty.tools.dotc.semanticdb.SymbolOccurrence.Role.DEFINITION) + else if !defDef.pos.isZeroExtent then + defDef.rhs match + case None => registerOccurrence(namedTree.symbol, pos, dotty.tools.dotc.semanticdb.SymbolOccurrence.Role.DEFINITION) + case Some(value) => + if value.pos.startColumn != defDef.pos.startColumn then + registerOccurrence(namedTree.symbol, pos, dotty.tools.dotc.semanticdb.SymbolOccurrence.Role.DEFINITION) + + case _ => + registerDefinition(namedTree.symbol, pos, symbolKinds(namedTree), extractor) + if !pos.isZeroExtent then + registerOccurrence(namedTree.symbol, pos, dotty.tools.dotc.semanticdb.SymbolOccurrence.Role.DEFINITION) + super.traverse(tree) + + + case typeIdent: TypeIdent => + typeIdent.toType match + case typeRef: TypeRef => + val sym = typeRef.optSymbol.get + val owner = sym.owner + val ownerOwner = sym.owner.owner + sym.owner match + case termSymbol : TermSymbol => + termSymbol.owner match + case classSymbol : ClassSymbol if termSymbol.isConstructor => + val newName = classSymbol.SDBname + sym.name.toString.unescapeUnicode + registerOccurrence(classSymbol, newName, pos, dotty.tools.dotc.semanticdb.SymbolOccurrence.Role.REFERENCE) + case _ => + case _ => + registerOccurrence(sym, pos, dotty.tools.dotc.semanticdb.SymbolOccurrence.Role.REFERENCE) + case _ => + + super.traverse(tree) + + case assign : Assign => + assign.lhs match + case select : Select => + val setterName = select.symbol.name.toTermName match + case simpleName : SimpleName => simpleName.append(str.SETTER_SUFFIX) + case _ => select.symbol.name.toTermName + + val found = select.symbol.owner match + case classSymbol: ClassSymbol => + classSymbol.declarations.find(_.name == setterName).getOrElse(select.symbol) + case _ => select.symbol + + registerOccurrence(found, select.symbol, select.pos, dotty.tools.dotc.semanticdb.SymbolOccurrence.Role.REFERENCE) + super.traverse(assign.rhs) + case _ => super.traverse(tree) + + + case ident: Ident=> + registerOccurrence(ident.symbol, ident.pos, dotty.tools.dotc.semanticdb.SymbolOccurrence.Role.REFERENCE) + super.traverse(tree) + + case select : Select => + registerOccurrence(select.symbol, select.pos, dotty.tools.dotc.semanticdb.SymbolOccurrence.Role.REFERENCE) + super.traverse(tree) + + case apply: Apply => + apply.fun match + case ident: Ident => + ident.symbol match + case termSymbol: TermSymbol => + registerOccurrence(termSymbol, ident.pos, dotty.tools.dotc.semanticdb.SymbolOccurrence.Role.REFERENCE) + case _ => + super.traverse(tree) + case _ => super.traverse(tree) + case _ => + super.traverse(tree) + + private def symbolKinds(tree: Tree)(using Context): Set[SymbolKind] = + val symkinds = scala.collection.mutable.HashSet.empty[SymbolKind] + tree match + case tree: ValDef => + + if !tree.symbol.isParam then + tree.symbol.kind match + case TermSymbolKind.Val => symkinds += SymbolKind.Val + case TermSymbolKind.LazyVal => symkinds += SymbolKind.Val + case TermSymbolKind.Var => symkinds += SymbolKind.Var + case _ => + if tree.rhs.isEmpty && !(tree.symbol.isParamAccessor || tree.symbol.isCaseClassAccessor|| tree.symbol.isParam) then + symkinds += SymbolKind.Abstract + case tree: DefDef => + if tree.rhs.isEmpty then + symkinds += SymbolKind.Abstract + case tree: Bind if (!tree.symbol.isType) => + symkinds += SymbolKind.Val + case tree: Bind if (tree.symbol.isType) => + symkinds += SymbolKind.TypeVal + case _ => + + symkinds.toSet + +class TastyExtractSemanticDB(entry: ClasspathEntry, cp: Classpath, ctx: dotty.tools.dotc.core.Contexts.Context) { + val ctx3 = tastyquery.Contexts.Context.initialize(cp) + val symbolList = ctx3.findSymbolsByClasspathEntry(entry).toList + val originFileList = symbolList.flatMap { x => + x.tree.map(tree => (tree.pos.sourceFile, x)) + }.groupMap(_._1)(_._2).toList + + def writeSemanticDB(unitContexts :List[Contexts.Context]): Unit = { + val sourceRoot = ctx.settings.sourceroot.value(using ctx) + for ((dottyCtx, i) <- unitContexts.zipWithIndex) do { + val unit = dottyCtx.compilationUnit + val outputDir = + ExtractSemanticDB.semanticdbPath( + unit.source, + ExtractSemanticDB.semanticdbOutDir(using dottyCtx), + sourceRoot + ) + val sdbStringBuilder = new SDBSymbolNameBuilder() + val TreeTraverser = new CustomTreeTraverser(unit.source.toString)(using ctx3)(using sdbStringBuilder) + + val found = originFileList.filter( (sourceFile, _) => + sourceFile.name == unit.source.file.name).head._2 + found.map(x=> x.tree match + case Some(tree) => + TreeTraverser.traverse(tree) + case None => ) + val definitionList = TreeTraverser.symbolInfos.toList + val occurrences = TreeTraverser.occurrences.toList + semanticdb.ExtractSemanticDB.write( + unit.source, + occurrences, + definitionList, + List.empty[dotty.tools.dotc.semanticdb.Synthetic], + outputDir, + sourceRoot, + false + ) + } + } +} \ No newline at end of file diff --git a/compiler/src/dotty/tools/dotc/semanticdb/TastyPositionExtractor.scala b/compiler/src/dotty/tools/dotc/semanticdb/TastyPositionExtractor.scala new file mode 100644 index 0000000000..9a879707e9 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/semanticdb/TastyPositionExtractor.scala @@ -0,0 +1,179 @@ +package dotty.tools.dotc +import tastyquery.SourcePosition +import tastyquery.Symbols.* +import scala.io.Source +import java.nio.file.{Paths, Path} +import tastyquery.Symbols +import tastyquery.Trees.ClassDef +import tastyquery.Trees.TypeMember +import tastyquery.Trees.TypeParam +import tastyquery.Trees.ValDef +import tastyquery.Trees.DefDef +import tastyquery.Trees.Bind +import tastyquery.Trees.TypeTreeBind +import tastyquery.Trees.Ident +import tastyquery.Trees.Select +import tastyquery.Trees.SelectOuter +import tastyquery.Trees.This +import tastyquery.Trees.Super +import tastyquery.Trees.Apply +import tastyquery.Trees.TypeApply +import tastyquery.Trees.New +import tastyquery.Trees.Typed +import tastyquery.Trees.Assign +import tastyquery.Trees.NamedArg +import tastyquery.Trees.Block +import tastyquery.Trees.If +import tastyquery.Trees.InlineIf +import tastyquery.Trees.Lambda +import tastyquery.Trees.Match +import tastyquery.Trees.InlineMatch +import tastyquery.Trees.SeqLiteral +import tastyquery.Trees.While +import tastyquery.Trees.Throw +import tastyquery.Trees.Try +import tastyquery.Trees.Literal +import tastyquery.Trees.Return +import tastyquery.Trees.Inlined +import tastyquery.Trees.Quote +import tastyquery.Trees.Splice +import tastyquery.Trees.SplicePattern +import tastyquery.Trees.Template +import scala.io.BufferedSource + +def extractInLine(name: String, line: String, span: SourcePosition, source: BufferedSource): dotty.tools.dotc.semanticdb.Range = + source.close() + val foundStartColumn = + if span.startLine == span.endLine then + line.lastIndexOf(name, span.endColumn) + else + line.lastIndexOf(name) + val foundEndColumn = foundStartColumn + name.size + if foundStartColumn < 0 then { + new dotty.tools.dotc.semanticdb.Range(span.startLine,span.startColumn,span.startLine, span.startColumn) + } + else + new dotty.tools.dotc.semanticdb.Range(span.startLine,foundStartColumn,span.startLine, foundEndColumn) + +class TastyPositionExtractor(sourceFilePath: String): + + def extract(name: String, span: SourcePosition, sym: Symbol): dotty.tools.dotc.semanticdb.Range = + if span.isZeroExtent then { + new dotty.tools.dotc.semanticdb.Range(span.startLine,span.startColumn,span.endLine, span.endColumn) + } + else { + val source = Source.fromFile(sourceFilePath) + source.getLines.zipWithIndex.collectFirst { case (line, idx) if idx == span.startLine => line } match + + case None => + source.close() + new dotty.tools.dotc.semanticdb.Range(span.startLine,span.startColumn,span.endLine, span.endColumn) + + case Some(line) => + sym.tree match + case None => + extractInLine(name, line, span, source) + case Some(tree) => + tree match + case classDef : ClassDef => + classDef.rhs match + case template : Template => + template.body match + case head :: next => + if head.pos.startLine == span.startLine then + val searchingEndColumn = head.pos.startColumn + val cutString = line.substring(0, searchingEndColumn).nn + extractInLine(name, cutString, span, source) + else + extractInLine(name, line, span, source) + case Nil => + extractInLine(name, line, span, source) + + case defDef : DefDef => + if span== defDef.pos then + defDef.paramLists match + case head :: next => + head match + case Left(listValdDef) => + listValdDef match + case head :: next => + if head.pos.endLine == span.endLine then + val searchingEndColumn = head.pos.startColumn + val cutString = line.substring(0, searchingEndColumn).nn + extractInLine(name, cutString, span, source) + else + extractInLine(name, line, span, source) + case Nil => + extractInLine(name, line, span, source) + case Right(listTypeParam) => + listTypeParam match + case head :: next => + if head.pos.startLine == span.startLine then + val searchingEndColumn = listTypeParam.head.pos.startColumn + val cutString = line.substring(0, searchingEndColumn).nn + extractInLine(name, cutString, span, source) + else + extractInLine(name, line, span, source) + case Nil => + extractInLine(name, line, span, source) + + case Nil => + defDef.rhs match + case None => + extractInLine(name, line, span, source) + case Some(tree2) => + if tree2.pos.startLine != span.startLine then + extractInLine(name, line, span, source) + else + val searchingEndColumn = tree2.pos.startColumn + val cutString = line.substring(0, searchingEndColumn).nn + extractInLine(name, cutString, span, source) + else + extractInLine(name, line, span, source) + + case valDef : ValDef => + val span2 = valDef.pos + + if span == span2 then + val tptPos = valDef.tpt.pos + if tptPos.isUnknown then + valDef.rhs match + case None => + println("noRHS") + extractInLine(name, line, span, source) + + case Some(tree) => + if span== span2 then + val searchingEndColumn = tree.pos.startColumn + val cutString = line.substring(0, searchingEndColumn).nn + extractInLine(name, cutString, span, source) + else + extractInLine(name, line, span, source) + else + if (!tptPos.isZeroExtent && tptPos.endLine == span.startLine) then + val searchingEndColumn = tptPos.startColumn + val cutString = line.substring(0, searchingEndColumn).nn + extractInLine(name, cutString, span, source) + else + extractInLine(name, line, span, source) + else + extractInLine(name, line, span, source) + + + case bind : Bind => + val span2 = bind.pos + if span == span2 then + val pos3 = bind.body.pos + if (!pos3.isZeroExtent && pos3.endLine == span.endLine) then + val searchingEndColumn = pos3.startColumn + val cutString = line.substring(0, searchingEndColumn).nn + extractInLine(name, cutString, span, source) + else + extractInLine(name, line, span, source) + else + extractInLine(name, line, span, source) + + case _ => + extractInLine(name, line, span, source) + + } \ No newline at end of file diff --git a/compiler/src/dotty/tools/dotc/semanticdb/TastySemanticSymbolBuilder.scala b/compiler/src/dotty/tools/dotc/semanticdb/TastySemanticSymbolBuilder.scala new file mode 100644 index 0000000000..2051ca6ed5 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/semanticdb/TastySemanticSymbolBuilder.scala @@ -0,0 +1,144 @@ + +package dotty.tools.dotc +import tastyquery.Contexts.* +import tastyquery.Symbols.* +import tastyquery.Types.* +import tastyquery.Names.* +import tastyquery.Modifiers.* +import tastyquery.Trees.* + +import scala.annotation.tailrec +import tastyquery.Symbols.* + +import scala.collection.mutable +import _root_.dotty.tools.dotc.semanticdb.Scala3.* +import _root_.dotty.tools.dotc.semanticdb.Scala3.StringOps +import _root_.dotty.tools.dotc.symbolKind +import dotty.tools.dotc.Extensions.* +import tastyquery.SourcePosition + + +class SDBSymbolNameBuilder: + var nextLocalIdx: Int = 0 + val locals = mutable.HashMap[Symbol, Int]() + val symsAtOffset = new mutable.HashMap[SourcePosition, mutable.Set[Symbol]] + + def symbolName(sym: Symbol)(using Context): String = + + val b = StringBuilder(20) + addSymName(b, sym) + b.toString + + def symbolName(sym: TastyFakeSymbol)(using Context): String = + sym match + case sym: TastyWildcardTypeSymbol=> + val b = StringBuilder(20) + addSymName(b, sym.owner) + b.append('['); addName(b, sym.name); b.append(']') + b.toString + case sym: TastyTermParamRefSymbol=> + val b = StringBuilder(20) + addSymName(b, sym.owner) + b.append('('); addName(b, sym.name); b.append(')') + b.toString + + case sym: TastyTypeParamRefSymbol=> + val b = StringBuilder(20) + addSymName(b, sym.owner) + b.append('['); addName(b, sym.name); b.append(']') + b.toString + case sym: TastyRefinementSymbol=> + val b = StringBuilder(20) + addLocalSymName(b) + b.toString + + + def addName(b: StringBuilder, name: Name): Unit = + val str = name.toString.unescapeUnicode + if str.isJavaIdent then b append str + else b append '`' append str append '`' + + private def addLocalSymName(b: StringBuilder): Unit = + val idx = nextLocalIdx + nextLocalIdx += 1 + b.append(Symbols.LocalPrefix).append(idx) + + def addSymName(b: StringBuilder, sym: Symbol)(using Context):Unit = { + + def addOwner(owner: Symbol): Unit = { + + if !owner.isRoot then addSymName(b, owner) + } + + def addDescriptor(sym: Symbol)(using Context): Unit = { + + if sym.isClass && sym.asClass.isModuleClass then + addDescriptor(sym.asClass.moduleValue.get) + else if sym.isRoot then b.append("_root_/") + else if sym.isEmptyPackage then b.append("_empty_/") + else if sym.isInstanceOf[TermSymbol] && sym.asInstanceOf[TermSymbol].isParam then + b.append('('); addName(b, sym.name); b.append(')') + else if sym.isInstanceOf[TypeParamSymbol] then { + b.append('[') + addName(b, sym.name) + b.append(']') + } + else + addName(b, sym.name) + if sym.isPackage then + b.append('/') + else if sym.isType then b.append('#') + else if (sym.isMethod || sym.isVar) + && (!sym.isStableMember || sym.isConstructor) then + b.append('('); + addOverloadIdx(sym); + b.append(").") + else b.append('.') + } + + def addOverloadIdx(initSym: Symbol): Unit = + sym match + case termSymbol: TermSymbol => + sym.owner match + case owner: ClassSymbol => + + val decls = owner.declarations.filter(x=> x.name == initSym.name) + val alts = decls.filter( x => x.isMethod || (x.asInstanceOf[TermSymbol].kind == TermSymbolKind.Var)).partition(x => !x.isSynthetic).toList.flatten + + alts match + case head :: next => + val idx = next.indexWhere(x => x.isTerm && x.asInstanceOf[TermSymbol].signature == termSymbol.signature) + if (idx >= 0){ + b.append('+').append(idx + 1) + } + case _ => + case _ => + case _ => + + def computeLocalIdx(sym: Symbol)(using Context): Int = + + val startPos = sym.tree match + case None => None + case Some(value) => if value.pos.isUnknown then None else Some(value.pos)//if value.pos.exists then Some(value.pos.span.start) else + locals get sym match + case Some(idx) => idx + case None => + (for { + pos <- startPos + syms <- symsAtOffset.get(pos) + found <- syms.find(_.name == sym.name) + } yield found) match + case Some(other) => computeLocalIdx(other) + case None => + val idx = nextLocalIdx + nextLocalIdx += 1 + locals(sym) = idx + symsAtOffset.get(startPos.get).foreach(_ += sym) + idx + + if !sym.isGlobal then + b.append("local").append(computeLocalIdx(sym)) + else if sym.owner != null then + addOwner(sym.owner); + addDescriptor(sym); + } diff --git a/compiler/src/dotty/tools/dotc/semanticdb/TastyTypeOps.scala b/compiler/src/dotty/tools/dotc/semanticdb/TastyTypeOps.scala new file mode 100644 index 0000000000..09c7b811b7 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/semanticdb/TastyTypeOps.scala @@ -0,0 +1,286 @@ +package dotty.tools.dotc + +import tastyquery.Contexts.Context +import tastyquery.Types.* +import scala.collection.mutable +import tastyquery.Names.* +import tastyquery.Symbols.TermSymbol +import tastyquery.Symbols.ClassTypeParamSymbol +import tastyquery.Symbols.LocalTypeParamSymbol +import tastyquery.Symbols.TypeMemberSymbol +import tastyquery.Symbols.ClassSymbol +import tastyquery.Symbols.PackageSymbol +import dotty.tools.dotc.semanticdb.Scala3.SemanticSymbol +import dotty.tools.dotc.SDBSymbolNameBuilder +import tastyquery.Constants.* +import tastyquery.Annotations.Annotation +import dotty.tools.dotc.core.SymDenotations.NoDenotation.matches +import dotty.tools.dotc.core.Symbols.TypeSymbol + +import dotty.tools.dotc.semanticdb.Scala3.* +import dotty.tools.dotc.semanticdb.LinkMode +import dotty.tools.dotc.semanticdb.Scala3.TastyFakeSymbol +import dotty.tools.dotc.SymbolScopeOps.sscopeOpt +import tastyquery.Modifiers.Variance +import dotty.tools.dotc.SymbolScopeOps.sscope +import dotty.tools.dotc.core.TypeComparer.andType +import tastyquery.Symbols.TermOrTypeSymbol +import dotty.tools.dotc.Extensions.* + +object SDBtype: + + private val paramRefSymtab = mutable.Map[(LambdaType, Name), TastySemanticSymbol]() + private val refinementSymtab = mutable.Map[(RefinedType, Name), tastyquery.Symbols.TermOrTypeSymbol]() + val fakeSymbols = mutable.Set[TastyFakeSymbol]() + + extension (const: Constant) + def toSemanticConstTasty(using Context): semanticdb.Constant = const.tag match { + case UnitTag => semanticdb.UnitConstant() + case BooleanTag => semanticdb.BooleanConstant(const.booleanValue) + case ByteTag => semanticdb.ByteConstant(const.byteValue) + case ShortTag => semanticdb.ShortConstant(const.shortValue) + case CharTag => semanticdb.CharConstant(const.charValue) + case IntTag => semanticdb.IntConstant(const.intValue) + case LongTag => semanticdb.LongConstant(const.longValue) + case FloatTag => semanticdb.FloatConstant(const.floatValue) + case DoubleTag => semanticdb.DoubleConstant(const.doubleValue) + case StringTag => semanticdb.StringConstant(const.stringValue) + case NullTag => semanticdb.NullConstant() + case _ => throw new Error(s"Constant ${const} can't be converted to Semanticdb Constant.") + } + private def registerFakeSymbol(sym: TastyFakeSymbol)(using Context): Unit = + fakeSymbols.add(sym) + + extension (tpe: TermType) + def toSemanticSig(using LinkMode, Context, SDBSymbolNameBuilder)(sym: tastyquery.Symbols.TermOrTypeSymbol): semanticdb.Signature = { + def loop(tpe: TermType): semanticdb.Signature = tpe match{ + + case mp: MethodicType => + def flatten( + t: TermType, + paramss: List[List[TastySemanticSymbol]], + tparams: List[TastySemanticSymbol] + ): (TermType, List[List[TastySemanticSymbol]], List[TastySemanticSymbol]) = t match { + case mt: MethodType => + val syms: List[TastySemanticSymbol] = mt.paramNames.zip(mt.paramInfos).map { + (name, info) => + paramRefSymtab.get(mt, name).getOrElse{ + registerFakeSymbol(TastyTermParamRefSymbol(sym, name, info)) + TastyTermParamRefSymbol(sym, name, info) + } + } + flatten(mt.resultType, paramss :+ syms, tparams) + + case pt: PolyType => + val syms: List[TastySemanticSymbol] = pt.paramNames.zip(pt.paramInfos).map { + (name, info) => + paramRefSymtab.get(pt, name).getOrElse{ + if sym.isConstructor then + registerFakeSymbol(TastyTypeParamRefSymbol(sym.owner, name, info)) + TastyTypeParamRefSymbol(sym.owner, name, info) + else + registerFakeSymbol(TastyTypeParamRefSymbol(sym, name, info)) + TastyTypeParamRefSymbol(sym, name, info) + } + + } + flatten(pt.resultType, paramss, tparams ++ syms) + case other => + (other, paramss, tparams) + } + val (resType, paramss, tparams) = flatten(mp, Nil, Nil) + val sparamss = paramss.map(x => {x.sscope}) + val stparams = tparams.sscopeOpt + + val toReturn = semanticdb.MethodSignature( + stparams, + sparamss, + resType.toSemanticType(sym.SDBname, Some(sym))) + toReturn + //as equivalent of ExprType do not have a MethodType, used to catch a ExprType + case _ if sym.isMethod => + semanticdb.ValueSignature(semanticdb.ByNameType(toSemanticType(sym.SDBname, Some(sym)))) + + case other => semanticdb.ValueSignature(toSemanticType(sym.SDBname, Some(sym))) + } + loop(tpe) + } + + def toSemanticType(using Context, SDBSymbolNameBuilder)(sym: String, symSymbol : Option[TermOrTypeSymbol]): semanticdb.Type = + val ctx = summon[Context] + import semanticdb.ConstantOps.* + def loop(tpe: TermType): semanticdb.Type = tpe match { + case typeRef: TypeRef => + val spre = if tpe.hasTrivialPrefix then semanticdb.Type.Empty else { + typeRef.prefix match + case NoPrefix => semanticdb.Type.Empty + case pre: PackageRef => semanticdb.Type.Empty + case pre: Type => loop(pre) + } + val ssym = typeRef.optSymbol match + case None => "Error no Symbol" + case Some(value) => + value.SDBname + semanticdb.TypeRef(spre, ssym, Seq.empty) + + case termRef: TermRef => + val spre = if tpe.hasTrivialPrefix then semanticdb.Type.Empty else { + termRef.prefix match + case NoPrefix => semanticdb.Type.Empty + case pre:PackageRef => loop(pre) + case pre: Type => loop(pre) + } + val ssym = termRef.optSymbol match + case None => "Error no Symbol" + case Some(value) => + value.SDBname + semanticdb.SingleType(spre, ssym) + + case thisType: ThisType => + semanticdb.ThisType(sym) + + case tref: TermParamRef => + semanticdb.SingleType(semanticdb.Type.Empty, sym) + + case tref: TypeParamRef => + semanticdb.TypeRef(semanticdb.Type.Empty, sym, Seq.empty) + + case superType: SuperType => + val spre = loop(superType.thistpe) + val ssym = sym + semanticdb.SuperType(spre, ssym) + + case constantType: ConstantType if constantType.value.tag == core.Constants.ClazzTag => + semanticdb.ConstantType(constantType.value.toSemanticConstTasty) + + case constantType: ConstantType => + semanticdb.ConstantType(constantType.value.toSemanticConstTasty) + + case matchType: MatchType => + val scases = matchType.cases.map{ + caseType => + caseType match { + case caseType: MatchTypeCase => + val skey = loop(caseType.pattern) + val sbody = loop(caseType.result) + semanticdb.MatchType.CaseType(skey, sbody) + }} + + val sscrutinee = loop(matchType.scrutinee) + val sbound = loop(matchType.bound) + semanticdb.MatchType(sscrutinee, scases) + + case rec: RecType => + loop(rec.parent) + case repeated: RepeatedType => + val stpe = loop(repeated.elemType) + semanticdb.RepeatedType(stpe) + case app : AppliedType => + val andSym = ctx.defn.scalaPackage.findDecl(typeName("&")) + val barSym = ctx.defn.scalaPackage.findDecl(typeName("|")) + app.tycon match + case tycon: TypeRef if tycon.optSymbol.contains(barSym) => + loop(OrType(app.args.head.highIfWildcard, app.args.tail.head.highIfWildcard)) + case tycon: TypeRef if tycon.optSymbol.contains(andSym) => + loop(AndType(app.args.head.highIfWildcard, app.args.tail.head.highIfWildcard)) + case _ => { + val targs = app.args.map {arg => + arg match + case arg: WildcardTypeArg => arg.bounds match + case bounds: AbstractTypeBounds => + symSymbol match + case None => + val sarg = loop(bounds.high) + (None, sarg) + case Some(value) => + + val wildcardSym = TastyWildcardTypeSymbol(value, bounds) + val ssym = wildcardSym.SDBFakeSymName + (Some(wildcardSym), semanticdb.TypeRef(semanticdb.Type.Empty, ssym, Seq.empty)) + case TypeAlias(alias) => + val sarg = loop(alias) + (None, sarg) + case arg: Type => + val sarg = loop(arg) + (None, sarg) + } + + val wildcardSyms = targs.flatMap(_._1) + val sargs = targs.map(_._2) + val applied = loop(app.tycon) match + case ref @ semanticdb.TypeRef(_, _, targs) => + ref.copy(typeArguments = targs ++ sargs) + case _ => + semanticdb.Type.Empty + if (wildcardSyms.isEmpty) applied + else semanticdb.ExistentialType( + applied, + wildcardSyms.sscopeOpt(using LinkMode.HardlinkChildren) + )} + + case and: AndType => + def flatten(child: Type): List[Type] = child match + case andType: AndType=> flatten(andType.first) ++ flatten(andType.second) + case other => List(other) + val stpes = flatten(and).map(loop) + semanticdb.IntersectionType(stpes) + + case or: OrType => + def flatten(child: Type): List[Type] = child match + case orType: OrType => flatten(orType.first) ++ flatten(orType.second) + case other => List(other) + val intermediate = flatten(or) + val stpes = flatten(or).map(loop) + semanticdb.UnionType(stpes) + + case lambda: TypeLambda => + val parameters = Some(semanticdb.Scope(Seq(""))) + val resType = loop(lambda.resultType) + semanticdb.LambdaType( + parameters, + resType) + + case _ => + semanticdb.Type.Empty + } + loop(tpe) + + + + + private def hasTrivialPrefix(using Context): Boolean = + def checkTrivialPrefix(pre: Prefix, sym: tastyquery.Symbols.Symbol)(using Context): Boolean = + pre match + case NoPrefix => false + case pre : PackageRef => pre.symbol == sym.owner + case pre : Type => + sym.owner match + case owner: ClassSymbol => pre.isSameType(owner.thisType) + case _ => false + + tpe match { + case typeRef : TypeRef => + typeRef.optSymbol match + case None => false + case Some(value) => checkTrivialPrefix(typeRef.prefix, value) + case _ => false + } + + +object SymbolScopeOps: + import dotty.tools.dotc.semanticdb.Scala3.{_, given} + extension (syms: List[TastySemanticSymbol]) + def sscope(using linkMode: LinkMode)(using Context, SDBSymbolNameBuilder): semanticdb.Scope = + linkMode match + case LinkMode.SymlinkChildren => + semanticdb.Scope(symlinks = syms.map( + x => { + x.symbolName + } + + )) + case LinkMode.HardlinkChildren => + semanticdb.Scope(Seq("Hardlink not implemented")) + + def sscopeOpt(using LinkMode, Context, SDBSymbolNameBuilder): Option[semanticdb.Scope] = + if syms.nonEmpty then Some(syms.sscope) else None diff --git a/compiler/src/dotty/tools/dotc/transform/Pickler.scala b/compiler/src/dotty/tools/dotc/transform/Pickler.scala index c8c071064a..3cbd7e0c86 100644 --- a/compiler/src/dotty/tools/dotc/transform/Pickler.scala +++ b/compiler/src/dotty/tools/dotc/transform/Pickler.scala @@ -25,6 +25,7 @@ import scala.annotation.constructorOnly import scala.concurrent.Promise import dotty.tools.dotc.transform.Pickler.writeSigFilesAsync + import scala.util.chaining.given import dotty.tools.io.FileWriters.{EagerReporter, BufferingReporter} import dotty.tools.dotc.sbt.interfaces.IncrementalCallback @@ -418,6 +419,49 @@ class Pickler extends Phase { .resolve("best-effort") Files.createDirectories(outpath) BestEffortTastyWriter.write(outpath.nn, result) + + import dotty.tools.dotc.sbt.* + import dotty.tools.dotc.sbt.LazyTastyQueryClasspath.* + import tastyquery.Names as tqn + import tastyquery.Classpaths.* + import tastyquery.Classpaths.* + import tastyquery.Symbols.* + import tastyquery.Names.* + import tastyquery.Symbols.{ClassSymbol, TermOrTypeSymbol} + + if ctx.settings.YproduceSemanticdbUsingTasty.value then + val sourceroot = ctx.settings.sourceroot.value + val entryDebugString = sourceroot + val packagePrefixesAndData = result.flatMap( + _.pickled.toList.map( + (cls, tsty) => { + val internalName = + if (cls.is(Module)) cls.binaryClassName.stripSuffix(str.MODULE_SUFFIX).nn + else cls.binaryClassName + + val fullyQualifiedName = internalName + val path = fullyQualifiedName.split('.') + val binaryName = path.last + val packagePrefix = path.dropRight(1).mkString(".") + val output = (packagePrefix, InMemoryTasty(fullyQualifiedName, binaryName, tsty)) + output + } + )) + val packageData = packagePrefixesAndData + .groupBy(_._1) + .map( + (pkg, data) => { + val classes = data.map(_._2) + InMemoryPackageData(s"${entryDebugString}:${pkg}", pkg, () => classes.toList) + }) + .toList + + val unitContexts = semanticdb.ExtractSemanticDB.unitContexts.get + val entry = InMemoryEntry(entryDebugString, packageData) + val cp = entry :: makeClasspath(using ctx) + val sdbExtractor = new TastyExtractSemanticDB(entry, cp, ctx) + sdbExtractor.writeSemanticDB(unitContexts) + result } @@ -503,4 +547,4 @@ class Pickler extends Phase { actual.length == expect.length && actual.lazyZip(expect).forall(matches) } -} +} \ No newline at end of file diff --git a/compiler/test/dotty/tools/dotc/semanticdb/SemanticdbTests.scala b/compiler/test/dotty/tools/dotc/semanticdb/SemanticdbTests.scala index 4db047d095..705ed8dc2c 100644 --- a/compiler/test/dotty/tools/dotc/semanticdb/SemanticdbTests.scala +++ b/compiler/test/dotty/tools/dotc/semanticdb/SemanticdbTests.scala @@ -189,4 +189,4 @@ object SemanticdbTests: sb.toString end printTextDocument -end SemanticdbTests +end SemanticdbTests \ No newline at end of file diff --git a/compiler/test/dotty/tools/dotc/semanticdb/TastySemanticdbTests.scala b/compiler/test/dotty/tools/dotc/semanticdb/TastySemanticdbTests.scala new file mode 100644 index 0000000000..7c2dabb455 --- /dev/null +++ b/compiler/test/dotty/tools/dotc/semanticdb/TastySemanticdbTests.scala @@ -0,0 +1,144 @@ +package dotty.tools.dotc.semanticdb + +import scala.language.unsafeNulls + +import java.net.URLClassLoader +import java.util.regex.Pattern +import java.io.File +import java.nio.file._ +import java.nio.charset.StandardCharsets +import java.util.stream.Collectors +import java.util.Comparator +import scala.util.control.NonFatal +import scala.collection.mutable +import scala.jdk.CollectionConverters._ + +import javax.tools.ToolProvider + +import org.junit.Assert._ +import org.junit.Test +import org.junit.experimental.categories.Category + +import dotty.BootstrappedOnlyTests +import dotty.tools.dotc.Main +import dotty.tools.dotc.semanticdb.Scala3.given +import dotty.tools.dotc.util.SourceFile + + +@Category(Array(classOf[BootstrappedOnlyTests])) +class TastySemanticdbTests: + val javaFile = FileSystems.getDefault.getPathMatcher("glob:**.java") + val scalaFile = FileSystems.getDefault.getPathMatcher("glob:**.scala") + val expectFile = FileSystems.getDefault.getPathMatcher("glob:**.expect.scala") + val rootSrc = Paths.get(System.getProperty("dotty.tools.dotc.semanticdb.test")) + val expectSrc = rootSrc.resolve("expect") + val javaRoot = rootSrc.resolve("javacp") + val metacExpectFile = rootSrc.resolve("metac.expect") + + @Category(Array(classOf[dotty.SlowTests])) + @Test def expectTestsTasty: Unit = + println("TASTY Running test...") + if (!scala.util.Properties.isWin) runExpectTest(updateExpectFiles = false) + + def runExpectTest(updateExpectFiles: Boolean): Unit = + + println("RUNNING ALL TESTS") + val target = generateSemanticdb() + val errors = mutable.ArrayBuffer.empty[Path] + val metacSb: StringBuilder = StringBuilder(5000) + def collectErrorOrUpdate(expectPath: Path, obtained: String, fileName: String) = + if updateExpectFiles then + Files.write(expectPath, obtained.getBytes(StandardCharsets.UTF_8)) + println("updated: " + expectPath) + else + val expected = new String(Files.readAllBytes(expectPath), StandardCharsets.UTF_8) + val expectName = expectPath.getFileName + val relExpect = rootSrc.relativize(expectPath) + if expected.trim != obtained.trim then + println("INCORRECT PATH IS:") + println(fileName) + Files.write(expectPath.resolveSibling("" + expectName + ".out"), obtained.getBytes(StandardCharsets.UTF_8)) + errors += expectPath + + for source <- inputFiles().sorted do + val filename = source.getFileName.toString + val relpath = expectSrc.relativize(source) + val semanticdbPath = target + .resolve("META-INF") + .resolve("semanticdb") + .resolve(relpath) + .resolveSibling(filename + ".semanticdb") + val expectPath = source.resolveSibling(filename.replace(".scala", ".expect.scala")) + val doc = Tools.loadTextDocument(source, relpath, semanticdbPath) + Tools.metac(doc, rootSrc.relativize(source))(using metacSb) + val obtained = trimTrailingWhitespace(SemanticdbTests.printTextDocument(doc)) + collectErrorOrUpdate(expectPath, obtained, filename) + /* + Decided to not check metacExpectFile here as the file just regroups the SemanticDB info of all files in the test folder which have some that do not pass with the Tasty - Query version. + Prefered to do this rather than include in the metacExpectFile only files produced using Tasty-Query. + This enables to not alter SemanticDBTests.scala and keep update the updateExpect of it. + */ + for expect <- errors do + def red(msg: String) = Console.RED + msg + Console.RESET + def blue(msg: String) = Console.BLUE + msg + Console.RESET + 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 'scala3-compiler-bootstrapped/Test/runMain dotty.tools.dotc.semanticdb.updateExpect'""".stripMargin) + Files.walk(target).sorted(Comparator.reverseOrder).forEach(Files.delete) + if errors.nonEmpty then + fail(s"${errors.size} errors in expect test.") + + def trimTrailingWhitespace(s: String): String = + Pattern.compile(" +$", Pattern.MULTILINE).matcher(s).replaceAll("") + + def inputFiles(): List[Path] = + val ls = Files.walk(expectSrc) + val files = + try ls.filter(p => scalaFile.matches(p) && !expectFile.matches(p)).collect(Collectors.toList).asScala + finally ls.close() + require(files.nonEmpty, s"No input files! $expectSrc") + + val filteredFiles = files.toList.filter { file => + file.getFileName.toString.startsWith("TastyQuery")} + println(filteredFiles.toList) + filteredFiles + + def javaFiles(): List[Path] = + val ls = Files.walk(javaRoot) + val files = + try ls.filter(p => javaFile.matches(p)).collect(Collectors.toList).asScala + finally ls.close() + require(files.nonEmpty, s"No input files! $expectSrc") + files.toList + + def generateSemanticdb(): Path = + val target = Files.createTempDirectory("semanticdb") + val javaArgs = Array("-d", target.toString) ++ javaFiles().map(_.toString) + val javac = ToolProvider.getSystemJavaCompiler + val exitJava = javac.run(null, null, null, javaArgs*) + assert(exitJava == 0, "java compiler has errors") + println(s"source root is : ${expectSrc.toString}") + val args = Array( + "-Ysdb-using-tasty", + "-Xsemanticdb", + "-d", target.toString, + "-feature", + "-deprecation", + "-sourceroot", expectSrc.toString, + "-classpath", target.toString, + "-Xignore-scala2-macros", + "-usejavacp", + "-Wunused:all" + ) ++ inputFiles().map(_.toString) + println("ARGS") + println(args.toList) + + val exit = Main.process(args) + assertFalse(s"dotc errors: ${exit.errorCount}", exit.hasErrors) + target + +end TastySemanticdbTests \ No newline at end of file diff --git a/docs/_spec/Gemfile b/docs/_spec/Gemfile index dcb5701fd8..708513e056 100644 --- a/docs/_spec/Gemfile +++ b/docs/_spec/Gemfile @@ -2,7 +2,7 @@ source "https://rubygems.org" ruby "~> 2.7" -gem "jekyll", "3.6.3" +gem "jekyll", "4.4.1" gem "webrick" gem "rouge" # gem 's3_website' diff --git a/docs/_spec/Gemfile.lock b/docs/_spec/Gemfile.lock index 38a790c676..a577ad3c25 100644 --- a/docs/_spec/Gemfile.lock +++ b/docs/_spec/Gemfile.lock @@ -1,46 +1,76 @@ GEM remote: https://rubygems.org/ specs: - addressable (2.8.1) - public_suffix (>= 2.0.2, < 6.0) + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) + base64 (0.2.0) colorator (1.1.0) - ffi (1.15.5) + concurrent-ruby (1.3.5) + csv (3.3.2) + em-websocket (0.5.3) + eventmachine (>= 0.12.9) + http_parser.rb (~> 0) + eventmachine (1.2.7) + ffi (1.17.1) + ffi (1.17.1-x86_64-linux-gnu) forwardable-extended (2.6.0) - jekyll (3.6.3) + google-protobuf (3.25.6) + google-protobuf (3.25.6-x86_64-linux) + http_parser.rb (0.8.0) + i18n (1.14.7) + concurrent-ruby (~> 1.0) + jekyll (4.4.1) addressable (~> 2.4) + base64 (~> 0.2) colorator (~> 1.0) - jekyll-sass-converter (~> 1.0) - jekyll-watch (~> 1.1) - kramdown (~> 1.14) + csv (~> 3.0) + em-websocket (~> 0.5) + i18n (~> 1.0) + jekyll-sass-converter (>= 2.0, < 4.0) + jekyll-watch (~> 2.0) + json (~> 2.6) + kramdown (~> 2.3, >= 2.3.1) + kramdown-parser-gfm (~> 1.0) liquid (~> 4.0) - mercenary (~> 0.3.3) + mercenary (~> 0.3, >= 0.3.6) pathutil (~> 0.9) - rouge (>= 1.7, < 3) + rouge (>= 3.0, < 5.0) safe_yaml (~> 1.0) - jekyll-sass-converter (1.5.2) - sass (~> 3.4) - jekyll-watch (1.5.1) + terminal-table (>= 1.8, < 4.0) + webrick (~> 1.7) + jekyll-sass-converter (3.0.0) + sass-embedded (~> 1.54) + jekyll-watch (2.2.1) listen (~> 3.0) - kramdown (1.17.0) - liquid (4.0.3) - listen (3.7.1) + json (2.9.1) + kramdown (2.5.1) + rexml (>= 3.3.9) + kramdown-parser-gfm (1.1.0) + kramdown (~> 2.0) + liquid (4.0.4) + listen (3.9.0) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) - mercenary (0.3.6) + mercenary (0.4.0) pathutil (0.16.2) forwardable-extended (~> 2.6) - public_suffix (5.0.0) + public_suffix (5.1.1) + rake (13.2.1) rb-fsevent (0.11.2) - rb-inotify (0.10.1) + rb-inotify (0.11.1) ffi (~> 1.0) redcarpet (3.6.0) - rouge (2.2.1) + rexml (3.4.0) + rouge (4.5.1) safe_yaml (1.0.5) - sass (3.7.4) - sass-listen (~> 4.0.0) - sass-listen (4.0.0) - rb-fsevent (~> 0.9, >= 0.9.4) - rb-inotify (~> 0.9, >= 0.9.7) + sass-embedded (1.63.6) + google-protobuf (~> 3.23) + rake (>= 13.0.0) + sass-embedded (1.63.6-x86_64-linux-gnu) + google-protobuf (~> 3.23) + terminal-table (3.0.2) + unicode-display_width (>= 1.1.1, < 3) + unicode-display_width (2.6.0) webrick (1.9.1) PLATFORMS @@ -48,7 +78,7 @@ PLATFORMS x86_64-linux DEPENDENCIES - jekyll (= 3.6.3) + jekyll (= 4.4.1) redcarpet (= 3.6.0) rouge webrick diff --git a/project/Build.scala b/project/Build.scala index a7be508ce1..03d20d7845 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -767,6 +767,7 @@ object Build { "org.jline" % "jline-terminal" % "3.27.1", "org.jline" % "jline-terminal-jni" % "3.27.1", // needed for Windows ("io.get-coursier" %% "coursier" % "2.0.16" % Test).cross(CrossVersion.for3Use2_13), + "ch.epfl.scala" %% "tasty-query" % "0.0.0+1226-275ea2d1+20241221-0226-SNAPSHOT", ), // For convenience, change the baseDirectory when running the compiler @@ -2715,4 +2716,4 @@ object ScaladocConfigs { .remove[SiteRoot] .remove[ApiSubdirectory] } -} +} \ No newline at end of file diff --git a/tasty/src/dotty/tools/tasty/TastyVersion.scala b/tasty/src/dotty/tools/tasty/TastyVersion.scala index b6474f7c79..d5bb714d21 100644 --- a/tasty/src/dotty/tools/tasty/TastyVersion.scala +++ b/tasty/src/dotty/tools/tasty/TastyVersion.scala @@ -27,7 +27,6 @@ case class TastyVersion private(major: Int, minor: Int, experimental: Int) { object TastyVersion { - @sharable private val cache: java.util.concurrent.ConcurrentHashMap[TastyVersion, TastyVersion] = new java.util.concurrent.ConcurrentHashMap() diff --git a/tests/pos/HelloWorld2.scala b/tests/pos/HelloWorld2.scala new file mode 100644 index 0000000000..78d5cd9e2f --- /dev/null +++ b/tests/pos/HelloWorld2.scala @@ -0,0 +1,3 @@ +class SimpleClass{ + def foo = 2 +} diff --git a/tests/pos/HelloWorld2.scala.semanticdb b/tests/pos/HelloWorld2.scala.semanticdb new file mode 100644 index 0000000000..64fe06e484 Binary files /dev/null and b/tests/pos/HelloWorld2.scala.semanticdb differ diff --git a/tests/pos/HelloWorld3.scala b/tests/pos/HelloWorld3.scala new file mode 100644 index 0000000000..bf686be679 --- /dev/null +++ b/tests/pos/HelloWorld3.scala @@ -0,0 +1,6 @@ +class HelloWorld3{ + def power(x:Int, y:Int) = x^y + def complexFormula(param1: Int, param2: Double, param3: Float) = + val intermidiate = {param3 * (param1 + param3)/param2}.toInt + intermidiate ^ intermidiate +} diff --git a/tests/pos/LargeClass.scala b/tests/pos/LargeClass.scala new file mode 100644 index 0000000000..8d7064fb9f --- /dev/null +++ b/tests/pos/LargeClass.scala @@ -0,0 +1,202 @@ +class LargeClass { + def fun1(x: Int, y: Int): Int = x * y + def fun2(x: Int, y: Int): Int = x * y + def fun3(x: Int, y: Int): Int = x * y + def fun4(x: Int, y: Int): Int = x * y + def fun5(x: Int, y: Int): Int = x * y + def fun6(x: Int, y: Int): Int = x * y + def fun7(x: Int, y: Int): Int = x * y + def fun8(x: Int, y: Int): Int = x * y + def fun9(x: Int, y: Int): Int = x * y + def fun10(x: Int, y: Int): Int = x * y + def fun11(x: Int, y: Int): Int = x * y + def fun12(x: Int, y: Int): Int = x * y + def fun13(x: Int, y: Int): Int = x * y + def fun14(x: Int, y: Int): Int = x * y + def fun15(x: Int, y: Int): Int = x * y + def fun16(x: Int, y: Int): Int = x * y + def fun17(x: Int, y: Int): Int = x * y + def fun18(x: Int, y: Int): Int = x * y + def fun19(x: Int, y: Int): Int = x * y + def fun20(x: Int, y: Int): Int = x * y + def fun21(x: Int, y: Int): Int = x * y + def fun22(x: Int, y: Int): Int = x * y + def fun23(x: Int, y: Int): Int = x * y + def fun24(x: Int, y: Int): Int = x * y + def fun25(x: Int, y: Int): Int = x * y + def fun26(x: Int, y: Int): Int = x * y + def fun27(x: Int, y: Int): Int = x * y + def fun28(x: Int, y: Int): Int = x * y + def fun29(x: Int, y: Int): Int = x * y + def fun30(x: Int, y: Int): Int = x * y + def fun31(x: Int, y: Int): Int = x * y + def fun32(x: Int, y: Int): Int = x * y + def fun33(x: Int, y: Int): Int = x * y + def fun34(x: Int, y: Int): Int = x * y + def fun35(x: Int, y: Int): Int = x * y + def fun36(x: Int, y: Int): Int = x * y + def fun37(x: Int, y: Int): Int = x * y + def fun38(x: Int, y: Int): Int = x * y + def fun39(x: Int, y: Int): Int = x * y + def fun40(x: Int, y: Int): Int = x * y + def fun41(x: Int, y: Int): Int = x * y + def fun42(x: Int, y: Int): Int = x * y + def fun43(x: Int, y: Int): Int = x * y + def fun44(x: Int, y: Int): Int = x * y + def fun45(x: Int, y: Int): Int = x * y + def fun46(x: Int, y: Int): Int = x * y + def fun47(x: Int, y: Int): Int = x * y + def fun48(x: Int, y: Int): Int = x * y + def fun49(x: Int, y: Int): Int = x * y + def fun50(x: Int, y: Int): Int = x * y + def fun51(x: Int, y: Int): Int = x * y + def fun52(x: Int, y: Int): Int = x * y + def fun53(x: Int, y: Int): Int = x * y + def fun54(x: Int, y: Int): Int = x * y + def fun55(x: Int, y: Int): Int = x * y + def fun56(x: Int, y: Int): Int = x * y + def fun57(x: Int, y: Int): Int = x * y + def fun58(x: Int, y: Int): Int = x * y + def fun59(x: Int, y: Int): Int = x * y + def fun60(x: Int, y: Int): Int = x * y + def fun61(x: Int, y: Int): Int = x * y + def fun62(x: Int, y: Int): Int = x * y + def fun63(x: Int, y: Int): Int = x * y + def fun64(x: Int, y: Int): Int = x * y + def fun65(x: Int, y: Int): Int = x * y + def fun66(x: Int, y: Int): Int = x * y + def fun67(x: Int, y: Int): Int = x * y + def fun68(x: Int, y: Int): Int = x * y + def fun69(x: Int, y: Int): Int = x * y + def fun70(x: Int, y: Int): Int = x * y + def fun71(x: Int, y: Int): Int = x * y + def fun72(x: Int, y: Int): Int = x * y + def fun73(x: Int, y: Int): Int = x * y + def fun74(x: Int, y: Int): Int = x * y + def fun75(x: Int, y: Int): Int = x * y + def fun76(x: Int, y: Int): Int = x * y + def fun77(x: Int, y: Int): Int = x * y + def fun78(x: Int, y: Int): Int = x * y + def fun79(x: Int, y: Int): Int = x * y + def fun80(x: Int, y: Int): Int = x * y + def fun81(x: Int, y: Int): Int = x * y + def fun82(x: Int, y: Int): Int = x * y + def fun83(x: Int, y: Int): Int = x * y + def fun84(x: Int, y: Int): Int = x * y + def fun85(x: Int, y: Int): Int = x * y + def fun86(x: Int, y: Int): Int = x * y + def fun87(x: Int, y: Int): Int = x * y + def fun88(x: Int, y: Int): Int = x * y + def fun89(x: Int, y: Int): Int = x * y + def fun90(x: Int, y: Int): Int = x * y + def fun91(x: Int, y: Int): Int = x * y + def fun92(x: Int, y: Int): Int = x * y + def fun93(x: Int, y: Int): Int = x * y + def fun94(x: Int, y: Int): Int = x * y + def fun95(x: Int, y: Int): Int = x * y + def fun96(x: Int, y: Int): Int = x * y + def fun97(x: Int, y: Int): Int = x * y + def fun98(x: Int, y: Int): Int = x * y + def fun99(x: Int, y: Int): Int = x * y + def fun100(x: Int, y: Int): Int = x * y + def fun101(x: Int, y: Int): Int = x * y + def fun102(x: Int, y: Int): Int = x * y + def fun103(x: Int, y: Int): Int = x * y + def fun104(x: Int, y: Int): Int = x * y + def fun105(x: Int, y: Int): Int = x * y + def fun106(x: Int, y: Int): Int = x * y + def fun107(x: Int, y: Int): Int = x * y + def fun108(x: Int, y: Int): Int = x * y + def fun109(x: Int, y: Int): Int = x * y + def fun110(x: Int, y: Int): Int = x * y + def fun111(x: Int, y: Int): Int = x * y + def fun112(x: Int, y: Int): Int = x * y + def fun113(x: Int, y: Int): Int = x * y + def fun114(x: Int, y: Int): Int = x * y + def fun115(x: Int, y: Int): Int = x * y + def fun116(x: Int, y: Int): Int = x * y + def fun117(x: Int, y: Int): Int = x * y + def fun118(x: Int, y: Int): Int = x * y + def fun119(x: Int, y: Int): Int = x * y + def fun120(x: Int, y: Int): Int = x * y + def fun121(x: Int, y: Int): Int = x * y + def fun122(x: Int, y: Int): Int = x * y + def fun123(x: Int, y: Int): Int = x * y + def fun124(x: Int, y: Int): Int = x * y + def fun125(x: Int, y: Int): Int = x * y + def fun126(x: Int, y: Int): Int = x * y + def fun127(x: Int, y: Int): Int = x * y + def fun128(x: Int, y: Int): Int = x * y + def fun129(x: Int, y: Int): Int = x * y + def fun130(x: Int, y: Int): Int = x * y + def fun131(x: Int, y: Int): Int = x * y + def fun132(x: Int, y: Int): Int = x * y + def fun133(x: Int, y: Int): Int = x * y + def fun134(x: Int, y: Int): Int = x * y + def fun135(x: Int, y: Int): Int = x * y + def fun136(x: Int, y: Int): Int = x * y + def fun137(x: Int, y: Int): Int = x * y + def fun138(x: Int, y: Int): Int = x * y + def fun139(x: Int, y: Int): Int = x * y + def fun140(x: Int, y: Int): Int = x * y + def fun141(x: Int, y: Int): Int = x * y + def fun142(x: Int, y: Int): Int = x * y + def fun143(x: Int, y: Int): Int = x * y + def fun144(x: Int, y: Int): Int = x * y + def fun145(x: Int, y: Int): Int = x * y + def fun146(x: Int, y: Int): Int = x * y + def fun147(x: Int, y: Int): Int = x * y + def fun148(x: Int, y: Int): Int = x * y + def fun149(x: Int, y: Int): Int = x * y + def fun150(x: Int, y: Int): Int = x * y + def fun151(x: Int, y: Int): Int = x * y + def fun152(x: Int, y: Int): Int = x * y + def fun153(x: Int, y: Int): Int = x * y + def fun154(x: Int, y: Int): Int = x * y + def fun155(x: Int, y: Int): Int = x * y + def fun156(x: Int, y: Int): Int = x * y + def fun157(x: Int, y: Int): Int = x * y + def fun158(x: Int, y: Int): Int = x * y + def fun159(x: Int, y: Int): Int = x * y + def fun160(x: Int, y: Int): Int = x * y + def fun161(x: Int, y: Int): Int = x * y + def fun162(x: Int, y: Int): Int = x * y + def fun163(x: Int, y: Int): Int = x * y + def fun164(x: Int, y: Int): Int = x * y + def fun165(x: Int, y: Int): Int = x * y + def fun166(x: Int, y: Int): Int = x * y + def fun167(x: Int, y: Int): Int = x * y + def fun168(x: Int, y: Int): Int = x * y + def fun169(x: Int, y: Int): Int = x * y + def fun170(x: Int, y: Int): Int = x * y + def fun171(x: Int, y: Int): Int = x * y + def fun172(x: Int, y: Int): Int = x * y + def fun173(x: Int, y: Int): Int = x * y + def fun174(x: Int, y: Int): Int = x * y + def fun175(x: Int, y: Int): Int = x * y + def fun176(x: Int, y: Int): Int = x * y + def fun177(x: Int, y: Int): Int = x * y + def fun178(x: Int, y: Int): Int = x * y + def fun179(x: Int, y: Int): Int = x * y + def fun180(x: Int, y: Int): Int = x * y + def fun181(x: Int, y: Int): Int = x * y + def fun182(x: Int, y: Int): Int = x * y + def fun183(x: Int, y: Int): Int = x * y + def fun184(x: Int, y: Int): Int = x * y + def fun185(x: Int, y: Int): Int = x * y + def fun186(x: Int, y: Int): Int = x * y + def fun187(x: Int, y: Int): Int = x * y + def fun188(x: Int, y: Int): Int = x * y + def fun189(x: Int, y: Int): Int = x * y + def fun190(x: Int, y: Int): Int = x * y + def fun191(x: Int, y: Int): Int = x * y + def fun192(x: Int, y: Int): Int = x * y + def fun193(x: Int, y: Int): Int = x * y + def fun194(x: Int, y: Int): Int = x * y + def fun195(x: Int, y: Int): Int = x * y + def fun196(x: Int, y: Int): Int = x * y + def fun197(x: Int, y: Int): Int = x * y + def fun198(x: Int, y: Int): Int = x * y + def fun199(x: Int, y: Int): Int = x * y + def fun200(x: Int, y: Int): Int = x * y +} \ No newline at end of file diff --git a/tests/pos/SimpleClass.scala b/tests/pos/SimpleClass.scala new file mode 100644 index 0000000000..7b25b5d805 --- /dev/null +++ b/tests/pos/SimpleClass.scala @@ -0,0 +1 @@ +class SimpleClass{} \ No newline at end of file diff --git a/tests/pos/SimpleClass.scala.semanticdb b/tests/pos/SimpleClass.scala.semanticdb new file mode 100644 index 0000000000..993de9bd67 Binary files /dev/null and b/tests/pos/SimpleClass.scala.semanticdb differ diff --git a/tests/pos/VariousFeatures.scala b/tests/pos/VariousFeatures.scala new file mode 100644 index 0000000000..99891636d1 --- /dev/null +++ b/tests/pos/VariousFeatures.scala @@ -0,0 +1,31 @@ +class VariousFeatures(param1: Double | String, param2: Int){ + val x : String & Int = ??? + def usingClassParams = param1 match + case param1: Double => + param1.toInt + param2 + case _ => + val /*** Some comments*/ someLocalVal = 3 + val otherLocalVal = 4 + if param2 > 10 then + (someLocalVal * otherLocalVal).toDouble + else + None + def modfiyString(inputString: String): String = + param1 match + case string: String => string.concat(inputString) + case double: Double => inputString.charAt(double.toInt).toString + + val modified = modfiyString("Hello") + + def incompleteFormula(param1: Int, param2: Double, param3: Float) = + if {param3 % (param1 + param3)/param2}.toInt == 3 then + ??? + else + param1 ^ param1 +} + +//another comment +class VariousFeatures2{ + val y = "Hello World" + def printHelloWorld = print(y) +} diff --git a/tests/semanticdb/expect/TastyQueryByNameMethod.expect.scala b/tests/semanticdb/expect/TastyQueryByNameMethod.expect.scala new file mode 100644 index 0000000000..9810c4d5d7 --- /dev/null +++ b/tests/semanticdb/expect/TastyQueryByNameMethod.expect.scala @@ -0,0 +1,4 @@ +class ByNameMethod/*<-_empty_::ByNameMethod#*/{ + def x/*<-_empty_::ByNameMethod#x().*/ = 2 + //def y = List(2) +} diff --git a/tests/semanticdb/expect/TastyQueryByNameMethod.scala b/tests/semanticdb/expect/TastyQueryByNameMethod.scala new file mode 100644 index 0000000000..e017c34084 --- /dev/null +++ b/tests/semanticdb/expect/TastyQueryByNameMethod.scala @@ -0,0 +1,4 @@ +class ByNameMethod{ + def x = 2 + //def y = List(2) +} diff --git a/tests/semanticdb/expect/TastyQueryClassDifficultNames.expect.scala b/tests/semanticdb/expect/TastyQueryClassDifficultNames.expect.scala new file mode 100644 index 0000000000..c291fb68ef --- /dev/null +++ b/tests/semanticdb/expect/TastyQueryClassDifficultNames.expect.scala @@ -0,0 +1,9 @@ + +class TastyQueryClassDifficultNames/*<-_empty_::TastyQueryClassDifficultNames#*/{ + class t/*<-_empty_::TastyQueryClassDifficultNames#t#*/(t/*<-_empty_::TastyQueryClassDifficultNames#t#t.*/: Double/*->scala::Double#*/){val tt/*<-_empty_::TastyQueryClassDifficultNames#t#tt.*/ = t/*->_empty_::TastyQueryClassDifficultNames#t#t.*/ + + } + class c/*<-_empty_::TastyQueryClassDifficultNames#c#*/ (c/*<-_empty_::TastyQueryClassDifficultNames#c#c.*/: Any/*->scala::Any#*/){class c/*<-_empty_::TastyQueryClassDifficultNames#c#c#*/(c/*<-_empty_::TastyQueryClassDifficultNames#c#c#c.*/ : Any/*->scala::Any#*/){class c/*<-_empty_::TastyQueryClassDifficultNames#c#c#c#*/{}}} + //there is an issue remaining if we have (t: Int) + +} diff --git a/tests/semanticdb/expect/TastyQueryClassDifficultNames.scala b/tests/semanticdb/expect/TastyQueryClassDifficultNames.scala new file mode 100644 index 0000000000..54aa48e699 --- /dev/null +++ b/tests/semanticdb/expect/TastyQueryClassDifficultNames.scala @@ -0,0 +1,9 @@ + +class TastyQueryClassDifficultNames{ + class t(t: Double){val tt = t + + } + class c (c: Any){class c(c : Any){class c{}}} + //there is an issue remaining if we have (t: Int) + +} diff --git a/tests/semanticdb/expect/TastyQueryMatching.expect.scala b/tests/semanticdb/expect/TastyQueryMatching.expect.scala new file mode 100644 index 0000000000..a4173f4a63 --- /dev/null +++ b/tests/semanticdb/expect/TastyQueryMatching.expect.scala @@ -0,0 +1,13 @@ +class TastyQueryMatching/*<-_empty_::TastyQueryMatching#*/{ + def matchingOr/*<-_empty_::TastyQueryMatching#matchingOr().*/(x/*<-_empty_::TastyQueryMatching#matchingOr().(x)*/ : Int/*->scala::Int#*/ |/*->scala::`|`#*/ String/*->scala::Predef.String#*/ |/*->scala::`|`#*/ Double/*->scala::Double#*/) = + x/*->_empty_::TastyQueryMatching#matchingOr().(x)*/ match + case s/*<-local0*/: String/*->scala::Predef.String#*/ => s/*->local0*/.concat/*->java::lang::String#concat().*/(s/*->local0*/) + case number/*<-local1*/: Int/*->scala::Int#*/ => (number/*->local1*/ */*->scala::Int#`*`(+3).*/ number/*->local1*/) + case double/*<-local2*/: Double/*->scala::Double#*/ => print/*->scala::Predef.print().*/("") + + def matchingDefault/*<-_empty_::TastyQueryMatching#matchingDefault().*/(x/*<-_empty_::TastyQueryMatching#matchingDefault().(x)*/: Boolean/*->scala::Boolean#*/ |/*->scala::`|`#*/ Unit/*->scala::Unit#*/) = + x/*->_empty_::TastyQueryMatching#matchingDefault().(x)*/ match + case _: Unit/*->scala::Unit#*/ => + case _ => + +} diff --git a/tests/semanticdb/expect/TastyQueryMatching.scala b/tests/semanticdb/expect/TastyQueryMatching.scala new file mode 100644 index 0000000000..d4ac8094e0 --- /dev/null +++ b/tests/semanticdb/expect/TastyQueryMatching.scala @@ -0,0 +1,13 @@ +class TastyQueryMatching{ + def matchingOr(x : Int | String | Double) = + x match + case s: String => s.concat(s) + case number: Int => (number * number) + case double: Double => print("") + + def matchingDefault(x: Boolean | Unit) = + x match + case _: Unit => + case _ => + +} diff --git a/tests/semanticdb/expect/TastyQueryMethodComplexFormula.expect.scala b/tests/semanticdb/expect/TastyQueryMethodComplexFormula.expect.scala new file mode 100644 index 0000000000..02b5ff08dd --- /dev/null +++ b/tests/semanticdb/expect/TastyQueryMethodComplexFormula.expect.scala @@ -0,0 +1,3 @@ +class TastyQueryMethodComplexFormula/*<-_empty_::TastyQueryMethodComplexFormula#*/{ + def complexFormula/*<-_empty_::TastyQueryMethodComplexFormula#complexFormula().*/(param1/*<-_empty_::TastyQueryMethodComplexFormula#complexFormula().(param1)*/:Int/*->scala::Int#*/, param2/*<-_empty_::TastyQueryMethodComplexFormula#complexFormula().(param2)*/:Int/*->scala::Int#*/) = (param1/*->_empty_::TastyQueryMethodComplexFormula#complexFormula().(param1)*/*/*->scala::Int#`*`(+3).*/param2/*->_empty_::TastyQueryMethodComplexFormula#complexFormula().(param2)*/)//*->scala::Int#`::`(+3).*/param2/*->_empty_::TastyQueryMethodComplexFormula#complexFormula().(param2)*/ +} diff --git a/tests/semanticdb/expect/TastyQueryMethodComplexFormula.scala b/tests/semanticdb/expect/TastyQueryMethodComplexFormula.scala new file mode 100644 index 0000000000..b2f090e974 --- /dev/null +++ b/tests/semanticdb/expect/TastyQueryMethodComplexFormula.scala @@ -0,0 +1,3 @@ +class TastyQueryMethodComplexFormula{ + def complexFormula(param1:Int, param2:Int) = (param1*param2)/param2 +} diff --git a/tests/semanticdb/expect/TastyQueryMethodDifficultNames.expect.scala b/tests/semanticdb/expect/TastyQueryMethodDifficultNames.expect.scala new file mode 100644 index 0000000000..c37f4cac2b --- /dev/null +++ b/tests/semanticdb/expect/TastyQueryMethodDifficultNames.expect.scala @@ -0,0 +1,6 @@ + +class MethodWithDifficultName/*<-_empty_::MethodWithDifficultName#*/{ + //putting as many e to confuse + def e/*<-_empty_::MethodWithDifficultName#e().*/(e/*<-_empty_::MethodWithDifficultName#e().(e)*/: Boolean/*->scala::Boolean#*/) = {val e/*<-local0*/: Boolean/*->scala::Boolean#*/ = "e" ==/*->scala::Any#`==`().*/ "e" &&/*->scala::Boolean#`&&`().*/ true ==/*->scala::Boolean#`==`().*/ false} + def methodDifficultName/*<-_empty_::MethodWithDifficultName#methodDifficultName().*/(z/*<-_empty_::MethodWithDifficultName#methodDifficultName().(z)*/: Int/*->scala::Int#*/, y/*<-_empty_::MethodWithDifficultName#methodDifficultName().(y)*/: String/*->scala::Predef.String#*/) = {val methodDifficultName/*<-local1*/ = 3} +} diff --git a/tests/semanticdb/expect/TastyQueryMethodDifficultNames.scala b/tests/semanticdb/expect/TastyQueryMethodDifficultNames.scala new file mode 100644 index 0000000000..b4bcf60130 --- /dev/null +++ b/tests/semanticdb/expect/TastyQueryMethodDifficultNames.scala @@ -0,0 +1,6 @@ + +class MethodWithDifficultName{ + //putting as many e to confuse + def e(e: Boolean) = {val e: Boolean = "e" == "e" && true == false} + def methodDifficultName(z: Int, y: String) = {val methodDifficultName = 3} +} diff --git a/tests/semanticdb/expect/TastyQueryMethodWithParam.expect.scala b/tests/semanticdb/expect/TastyQueryMethodWithParam.expect.scala new file mode 100644 index 0000000000..4cd2d1ffdc --- /dev/null +++ b/tests/semanticdb/expect/TastyQueryMethodWithParam.expect.scala @@ -0,0 +1,3 @@ +class MethodWithParam/*<-_empty_::MethodWithParam#*/{ + def methodWithTemParam/*<-_empty_::MethodWithParam#methodWithTemParam().*/(z/*<-_empty_::MethodWithParam#methodWithTemParam().(z)*/: Int/*->scala::Int#*/, y/*<-_empty_::MethodWithParam#methodWithTemParam().(y)*/: String/*->scala::Predef.String#*/) = "Hello" +} diff --git a/tests/semanticdb/expect/TastyQueryMethodWithParam.scala b/tests/semanticdb/expect/TastyQueryMethodWithParam.scala new file mode 100644 index 0000000000..39ea9951b9 --- /dev/null +++ b/tests/semanticdb/expect/TastyQueryMethodWithParam.scala @@ -0,0 +1,3 @@ +class MethodWithParam{ + def methodWithTemParam(z: Int, y: String) = "Hello" +} diff --git a/tests/semanticdb/expect/TastyQueryMethodWithParamMultiply.expect.scala b/tests/semanticdb/expect/TastyQueryMethodWithParamMultiply.expect.scala new file mode 100644 index 0000000000..2dba8b22fc --- /dev/null +++ b/tests/semanticdb/expect/TastyQueryMethodWithParamMultiply.expect.scala @@ -0,0 +1,9 @@ +class MethodWithParamMultiply/*<-_empty_::MethodWithParamMultiply#*/{ + def addition/*<-_empty_::MethodWithParamMultiply#addition().*/(z/*<-_empty_::MethodWithParamMultiply#addition().(z)*/: Int/*->scala::Int#*/, y/*<-_empty_::MethodWithParamMultiply#addition().(y)*/: Int/*->scala::Int#*/) = z/*->_empty_::MethodWithParamMultiply#addition().(z)*/+/*->scala::Int#`+`(+4).*/y/*->_empty_::MethodWithParamMultiply#addition().(y)*/ + def multiplication/*<-_empty_::MethodWithParamMultiply#multiplication().*/(x/*<-_empty_::MethodWithParamMultiply#multiplication().(x)*/:Int/*->scala::Int#*/, y/*<-_empty_::MethodWithParamMultiply#multiplication().(y)*/: Int/*->scala::Int#*/) = x/*->_empty_::MethodWithParamMultiply#multiplication().(x)*/*/*->scala::Int#`*`(+3).*/y/*->_empty_::MethodWithParamMultiply#multiplication().(y)*/ + def division/*<-_empty_::MethodWithParamMultiply#division().*/(x/*<-_empty_::MethodWithParamMultiply#division().(x)*/:Int/*->scala::Int#*/, y/*<-_empty_::MethodWithParamMultiply#division().(y)*/:Int/*->scala::Int#*/) = x/*->_empty_::MethodWithParamMultiply#division().(x)*///*->scala::Int#`::`(+3).*/y/*->_empty_::MethodWithParamMultiply#division().(y)*/ + def power/*<-_empty_::MethodWithParamMultiply#power().*/(x/*<-_empty_::MethodWithParamMultiply#power().(x)*/:Int/*->scala::Int#*/, y/*<-_empty_::MethodWithParamMultiply#power().(y)*/:Int/*->scala::Int#*/) = x/*->_empty_::MethodWithParamMultiply#power().(x)*/^/*->scala::Int#`^`(+3).*/y/*->_empty_::MethodWithParamMultiply#power().(y)*/ + def complexFormula/*<-_empty_::MethodWithParamMultiply#complexFormula().*/(param1/*<-_empty_::MethodWithParamMultiply#complexFormula().(param1)*/: Int/*->scala::Int#*/, param2/*<-_empty_::MethodWithParamMultiply#complexFormula().(param2)*/: Double/*->scala::Double#*/, param3/*<-_empty_::MethodWithParamMultiply#complexFormula().(param3)*/: Float/*->scala::Float#*/) = + val intermidiate/*<-local0*/ = {param3/*->_empty_::MethodWithParamMultiply#complexFormula().(param3)*/ */*->scala::Float#`*`(+5).*/ (param1/*->_empty_::MethodWithParamMultiply#complexFormula().(param1)*/ +/*->scala::Int#`+`(+6).*/ param3/*->_empty_::MethodWithParamMultiply#complexFormula().(param3)*/)//*->scala::Float#`::`(+6).*/param2/*->_empty_::MethodWithParamMultiply#complexFormula().(param2)*/}.toInt/*->scala::Double#toInt().*/ + intermidiate/*->local0*/ ^/*->scala::Int#`^`(+3).*/ intermidiate/*->local0*/ +} diff --git a/tests/semanticdb/expect/TastyQueryMethodWithParams.expect.scala b/tests/semanticdb/expect/TastyQueryMethodWithParams.expect.scala new file mode 100644 index 0000000000..1998791c48 --- /dev/null +++ b/tests/semanticdb/expect/TastyQueryMethodWithParams.expect.scala @@ -0,0 +1,9 @@ +class MethodWithParamMultiply/*<-_empty_::MethodWithParamMultiply#*/{ + def addition/*<-_empty_::MethodWithParamMultiply#addition().*/(z/*<-_empty_::MethodWithParamMultiply#addition().(z)*/: Int/*->scala::Int#*/, y/*<-_empty_::MethodWithParamMultiply#addition().(y)*/: Int/*->scala::Int#*/) = z/*->_empty_::MethodWithParamMultiply#addition().(z)*/+/*->scala::Int#`+`(+4).*/y/*->_empty_::MethodWithParamMultiply#addition().(y)*/ + def multiplication/*<-_empty_::MethodWithParamMultiply#multiplication().*/(x/*<-_empty_::MethodWithParamMultiply#multiplication().(x)*/:Int/*->scala::Int#*/, y/*<-_empty_::MethodWithParamMultiply#multiplication().(y)*/: Int/*->scala::Int#*/) = x/*->_empty_::MethodWithParamMultiply#multiplication().(x)*/*/*->scala::Int#`*`(+3).*/y/*->_empty_::MethodWithParamMultiply#multiplication().(y)*/ + def division/*<-_empty_::MethodWithParamMultiply#division().*/(x/*<-_empty_::MethodWithParamMultiply#division().(x)*/:Int/*->scala::Int#*/, y/*<-_empty_::MethodWithParamMultiply#division().(y)*/:Int/*->scala::Int#*/) = x/*->_empty_::MethodWithParamMultiply#division().(x)*///*->scala::Int#`::`(+3).*/y/*->_empty_::MethodWithParamMultiply#division().(y)*/ + def power/*<-_empty_::MethodWithParamMultiply#power().*/(x/*<-_empty_::MethodWithParamMultiply#power().(x)*/:Int/*->scala::Int#*/, y/*<-_empty_::MethodWithParamMultiply#power().(y)*/:Int/*->scala::Int#*/) = x/*->_empty_::MethodWithParamMultiply#power().(x)*/^/*->scala::Int#`^`(+3).*/y/*->_empty_::MethodWithParamMultiply#power().(y)*/ + def complexFormula/*<-_empty_::MethodWithParamMultiply#complexFormula().*/(param1/*<-_empty_::MethodWithParamMultiply#complexFormula().(param1)*/: Int/*->scala::Int#*/, param2/*<-_empty_::MethodWithParamMultiply#complexFormula().(param2)*/: Double/*->scala::Double#*/, param3/*<-_empty_::MethodWithParamMultiply#complexFormula().(param3)*/: Float/*->scala::Float#*/) = + val intermidiate/*<-local0*/ = {param3/*->_empty_::MethodWithParamMultiply#complexFormula().(param3)*/ */*->scala::Float#`*`(+5).*/ (param1/*->_empty_::MethodWithParamMultiply#complexFormula().(param1)*/ +/*->scala::Int#`+`(+6).*/ param3/*->_empty_::MethodWithParamMultiply#complexFormula().(param3)*/)//*->scala::Float#`::`(+6).*/param2/*->_empty_::MethodWithParamMultiply#complexFormula().(param2)*/}.toInt/*->scala::Double#toInt().*/ + intermidiate/*->local0*/ ^/*->scala::Int#`^`(+3).*/ intermidiate/*->local0*/ +} \ No newline at end of file diff --git a/tests/semanticdb/expect/TastyQueryMethodWithParams.scala b/tests/semanticdb/expect/TastyQueryMethodWithParams.scala new file mode 100644 index 0000000000..380553164c --- /dev/null +++ b/tests/semanticdb/expect/TastyQueryMethodWithParams.scala @@ -0,0 +1,9 @@ +class MethodWithParamMultiply{ + def addition(z: Int, y: Int) = z+y + def multiplication(x:Int, y: Int) = x*y + def division(x:Int, y:Int) = x/y + def power(x:Int, y:Int) = x^y + def complexFormula(param1: Int, param2: Double, param3: Float) = + val intermidiate = {param3 * (param1 + param3)/param2}.toInt + intermidiate ^ intermidiate +} \ No newline at end of file diff --git a/tests/semanticdb/expect/TastyQueryMethodWithParams2.expect.scala b/tests/semanticdb/expect/TastyQueryMethodWithParams2.expect.scala new file mode 100644 index 0000000000..cbc29525df --- /dev/null +++ b/tests/semanticdb/expect/TastyQueryMethodWithParams2.expect.scala @@ -0,0 +1,4 @@ +class MethodWithParamMultiply2/*<-_empty_::MethodWithParamMultiply2#*/{ + def complexFormula/*<-_empty_::MethodWithParamMultiply2#complexFormula().*/() = + val intermidiate/*<-local0*/ = 1 +} \ No newline at end of file diff --git a/tests/semanticdb/expect/TastyQueryMethodWithParams2.scala b/tests/semanticdb/expect/TastyQueryMethodWithParams2.scala new file mode 100644 index 0000000000..50a8c1c331 --- /dev/null +++ b/tests/semanticdb/expect/TastyQueryMethodWithParams2.scala @@ -0,0 +1,4 @@ +class MethodWithParamMultiply2{ + def complexFormula() = + val intermidiate = 1 +} \ No newline at end of file diff --git a/tests/semanticdb/expect/TastyQuerySimpleClass.expect.scala b/tests/semanticdb/expect/TastyQuerySimpleClass.expect.scala new file mode 100644 index 0000000000..6a38f33cd1 --- /dev/null +++ b/tests/semanticdb/expect/TastyQuerySimpleClass.expect.scala @@ -0,0 +1 @@ +class SimpleClass/*<-_empty_::SimpleClass#*/{} \ No newline at end of file diff --git a/tests/semanticdb/expect/TastyQuerySimpleClass.scala b/tests/semanticdb/expect/TastyQuerySimpleClass.scala new file mode 100644 index 0000000000..7b25b5d805 --- /dev/null +++ b/tests/semanticdb/expect/TastyQuerySimpleClass.scala @@ -0,0 +1 @@ +class SimpleClass{} \ No newline at end of file diff --git a/tests/semanticdb/expect/TastyQuerySimpleClassWithParams.expect.scala b/tests/semanticdb/expect/TastyQuerySimpleClassWithParams.expect.scala new file mode 100644 index 0000000000..c9d0a50586 --- /dev/null +++ b/tests/semanticdb/expect/TastyQuerySimpleClassWithParams.expect.scala @@ -0,0 +1,3 @@ +class SimpleClassWithParams/*<-_empty_::SimpleClassWithParams#*/(x/*<-_empty_::SimpleClassWithParams#x.*/:String/*->scala::Predef.String#*/){ + val y/*<-_empty_::SimpleClassWithParams#y.*/ = x/*->_empty_::SimpleClassWithParams#x.*/ +} \ No newline at end of file diff --git a/tests/semanticdb/expect/TastyQuerySimpleClassWithTypeParams.expect.scala b/tests/semanticdb/expect/TastyQuerySimpleClassWithTypeParams.expect.scala new file mode 100644 index 0000000000..cfc33afbb7 --- /dev/null +++ b/tests/semanticdb/expect/TastyQuerySimpleClassWithTypeParams.expect.scala @@ -0,0 +1 @@ +class SimpleClassWithTypeParams/*<-_empty_::SimpleClassWithTypeParams#*/[X/*<-_empty_::SimpleClassWithTypeParams#[X]*/]{} \ No newline at end of file diff --git a/tests/semanticdb/expect/TastyQuerySimpleMethod.expect.scala b/tests/semanticdb/expect/TastyQuerySimpleMethod.expect.scala new file mode 100644 index 0000000000..ff4ad83428 --- /dev/null +++ b/tests/semanticdb/expect/TastyQuerySimpleMethod.expect.scala @@ -0,0 +1,3 @@ +class TastyQuerySimpleMethod/*<-_empty_::TastyQuerySimpleMethod#*/{ + def simpleMethod/*<-_empty_::TastyQuerySimpleMethod#simpleMethod().*/(x/*<-_empty_::TastyQuerySimpleMethod#simpleMethod().(x)*/: Int/*->scala::Int#*/) = x/*->_empty_::TastyQuerySimpleMethod#simpleMethod().(x)*/ +} \ No newline at end of file diff --git a/tests/semanticdb/expect/TastyQuerySimpleMethod.scala b/tests/semanticdb/expect/TastyQuerySimpleMethod.scala new file mode 100644 index 0000000000..740242f509 --- /dev/null +++ b/tests/semanticdb/expect/TastyQuerySimpleMethod.scala @@ -0,0 +1,3 @@ +class TastyQuerySimpleMethod{ + def simpleMethod(x: Int) = x +} \ No newline at end of file diff --git a/tests/semanticdb/expect/TastyQueryValDifficultNames.expect.scala b/tests/semanticdb/expect/TastyQueryValDifficultNames.expect.scala new file mode 100644 index 0000000000..f9ce9ec870 --- /dev/null +++ b/tests/semanticdb/expect/TastyQueryValDifficultNames.expect.scala @@ -0,0 +1,6 @@ + +class TastyQueryValDifficultNames/*<-_empty_::TastyQueryValDifficultNames#*/{ + val g/*<-_empty_::TastyQueryValDifficultNames#g.*/: String/*->scala::Predef.String#*/ = g/*->_empty_::TastyQueryValDifficultNames#g.*/ + val i/*<-_empty_::TastyQueryValDifficultNames#i.*/: String/*->scala::Predef.String#*/ = i/*->_empty_::TastyQueryValDifficultNames#i.*/ match { case i/*<-local0*/: String/*->scala::Predef.String#*/ => i/*->local0*/ +/*->java::lang::String#`+`().*/ "i"; case _ => i/*->_empty_::TastyQueryValDifficultNames#i.*/ } + val a/*<-_empty_::TastyQueryValDifficultNames#a.*/ = " a "; val aa/*<-_empty_::TastyQueryValDifficultNames#aa.*/ = "a"; val isEqualTrimmed/*<-_empty_::TastyQueryValDifficultNames#isEqualTrimmed.*/ = a/*->_empty_::TastyQueryValDifficultNames#a.*/.trim/*->java::lang::String#trim().*/ ==/*->scala::Any#`==`().*/ aa/*->_empty_::TastyQueryValDifficultNames#aa.*/ +} diff --git a/tests/semanticdb/expect/TastyQueryValDifficultNames.scala b/tests/semanticdb/expect/TastyQueryValDifficultNames.scala new file mode 100644 index 0000000000..5c8ffd8072 --- /dev/null +++ b/tests/semanticdb/expect/TastyQueryValDifficultNames.scala @@ -0,0 +1,6 @@ + +class TastyQueryValDifficultNames{ + val g: String = g + val i: String = i match { case i: String => i + "i"; case _ => i } + val a = " a "; val aa = "a"; val isEqualTrimmed = a.trim == aa +} diff --git a/tests/semanticdb/expect/TastyQueryVar.expect.scala b/tests/semanticdb/expect/TastyQueryVar.expect.scala new file mode 100644 index 0000000000..e3153bab6a --- /dev/null +++ b/tests/semanticdb/expect/TastyQueryVar.expect.scala @@ -0,0 +1,10 @@ +class TastyQueryVar/*<-_empty_::TastyQueryVar#*/{ + var x/*<-_empty_::TastyQueryVar#x().*/ = 2 + x/*->_empty_::TastyQueryVar#`x_=`().*/ = 3 + + def foo/*<-_empty_::TastyQueryVar#foo().*/ = + var z/*<-local0*/ = 2 + z/*->local0*/ = 3 + var p/*<-_empty_::TastyQueryVar#p().*/ = foo/*->_empty_::TastyQueryVar#foo().*/ + p/*->_empty_::TastyQueryVar#`p_=`().*/ = {val x/*<-local1*/ = true} +} diff --git a/tests/semanticdb/expect/TastyQueryVar.scala b/tests/semanticdb/expect/TastyQueryVar.scala new file mode 100644 index 0000000000..cf829de269 --- /dev/null +++ b/tests/semanticdb/expect/TastyQueryVar.scala @@ -0,0 +1,10 @@ +class TastyQueryVar{ + var x = 2 + x = 3 + + def foo = + var x = 2 + x = 3 + var p = foo + p = {val x = true} +} diff --git a/tests/semanticdb/expect/TastyQueryVariousFeatures.expect.scala b/tests/semanticdb/expect/TastyQueryVariousFeatures.expect.scala new file mode 100644 index 0000000000..71f89c5062 --- /dev/null +++ b/tests/semanticdb/expect/TastyQueryVariousFeatures.expect.scala @@ -0,0 +1,31 @@ +class VariousFeatures/*<-_empty_::VariousFeatures#*/(param1/*<-_empty_::VariousFeatures#param1.*/: Double/*->scala::Double#*/ |/*->scala::`|`#*/ String/*->scala::Predef.String#*/, param2/*<-_empty_::VariousFeatures#param2.*/: Int/*->scala::Int#*/){ + val x/*<-_empty_::VariousFeatures#x.*/ : String/*->scala::Predef.String#*/ &/*->scala::`&`#*/ Int/*->scala::Int#*/ = ???/*->scala::Predef.`???`().*/ + def usingClassParams/*<-_empty_::VariousFeatures#usingClassParams().*/ = param1/*->_empty_::VariousFeatures#param1.*/ match + case param1/*<-local0*/: Double/*->scala::Double#*/ => + param1/*->local0*/.toInt/*->scala::Double#toInt().*/ +/*->scala::Int#`+`(+4).*/ param2/*->_empty_::VariousFeatures#param2.*/ + case _ => + val /*** Some comments*/ someLocalVal/*<-local1*/ = 3 + val otherLocalVal/*<-local2*/ = 4 + if param2/*->_empty_::VariousFeatures#param2.*/ >/*->scala::Int#`>`(+3).*/ 10 then + (someLocalVal/*->local1*/ */*->scala::Int#`*`(+3).*/ otherLocalVal/*->local2*/).toDouble/*->scala::Int#toDouble().*/ + else + None/*->scala::None.*/ + def modfiyString/*<-_empty_::VariousFeatures#modfiyString().*/(inputString/*<-_empty_::VariousFeatures#modfiyString().(inputString)*/: String/*->scala::Predef.String#*/): String/*->scala::Predef.String#*/ = + param1/*->_empty_::VariousFeatures#param1.*/ match + case string/*<-local3*/: String/*->scala::Predef.String#*/ => string/*->local3*/.concat/*->java::lang::String#concat().*/(inputString/*->_empty_::VariousFeatures#modfiyString().(inputString)*/) + case double/*<-local4*/: Double/*->scala::Double#*/ => inputString/*->_empty_::VariousFeatures#modfiyString().(inputString)*/.charAt/*->java::lang::String#charAt().*/(double/*->local4*/.toInt/*->scala::Double#toInt().*/).toString/*->scala::Any#toString().*/ + + val modified/*<-_empty_::VariousFeatures#modified.*/ = modfiyString/*->_empty_::VariousFeatures#modfiyString().*/("Hello") + + def incompleteFormula/*<-_empty_::VariousFeatures#incompleteFormula().*/(param1/*<-_empty_::VariousFeatures#incompleteFormula().(param1)*/: Int/*->scala::Int#*/, param2/*<-_empty_::VariousFeatures#incompleteFormula().(param2)*/: Double/*->scala::Double#*/, param3/*<-_empty_::VariousFeatures#incompleteFormula().(param3)*/: Float/*->scala::Float#*/) = + if {param3/*->_empty_::VariousFeatures#incompleteFormula().(param3)*/ %/*->scala::Float#`%`(+5).*/ (param1/*->_empty_::VariousFeatures#incompleteFormula().(param1)*/ +/*->scala::Int#`+`(+6).*/ param3/*->_empty_::VariousFeatures#incompleteFormula().(param3)*/)//*->scala::Float#`::`(+6).*/param2/*->_empty_::VariousFeatures#incompleteFormula().(param2)*/}.toInt/*->scala::Double#toInt().*/ ==/*->scala::Int#`==`(+3).*/ 3 then + ???/*->scala::Predef.`???`().*/ + else + param1/*->_empty_::VariousFeatures#incompleteFormula().(param1)*/ ^/*->scala::Int#`^`(+3).*/ param1/*->_empty_::VariousFeatures#incompleteFormula().(param1)*/ +} + +//another comment +class VariousFeatures2/*<-_empty_::VariousFeatures2#*/{ + val y/*<-_empty_::VariousFeatures2#y.*/ = "Hello World" + def printHelloWorld/*<-_empty_::VariousFeatures2#printHelloWorld().*/ = print/*->scala::Predef.print().*/(y/*->_empty_::VariousFeatures2#y.*/) +} diff --git a/tests/semanticdb/expect/TastyQueryVariousFeatures.scala b/tests/semanticdb/expect/TastyQueryVariousFeatures.scala new file mode 100644 index 0000000000..99891636d1 --- /dev/null +++ b/tests/semanticdb/expect/TastyQueryVariousFeatures.scala @@ -0,0 +1,31 @@ +class VariousFeatures(param1: Double | String, param2: Int){ + val x : String & Int = ??? + def usingClassParams = param1 match + case param1: Double => + param1.toInt + param2 + case _ => + val /*** Some comments*/ someLocalVal = 3 + val otherLocalVal = 4 + if param2 > 10 then + (someLocalVal * otherLocalVal).toDouble + else + None + def modfiyString(inputString: String): String = + param1 match + case string: String => string.concat(inputString) + case double: Double => inputString.charAt(double.toInt).toString + + val modified = modfiyString("Hello") + + def incompleteFormula(param1: Int, param2: Double, param3: Float) = + if {param3 % (param1 + param3)/param2}.toInt == 3 then + ??? + else + param1 ^ param1 +} + +//another comment +class VariousFeatures2{ + val y = "Hello World" + def printHelloWorld = print(y) +} diff --git a/tests/semanticdb/expect/example-dir/FileInDir.expect.scala b/tests/semanticdb/expect/example-dir/FileInDir.expect.scala index 73b1c9164b..75b2a9bc88 100644 --- a/tests/semanticdb/expect/example-dir/FileInDir.expect.scala +++ b/tests/semanticdb/expect/example-dir/FileInDir.expect.scala @@ -1,3 +1,2 @@ package example - -class FileInDir/*<-example::FileInDir#*/ +class FileInDir/*<-example::FileInDir#*/ \ No newline at end of file diff --git a/tests/semanticdb/expect/example-dir/FileInDir.scala b/tests/semanticdb/expect/example-dir/FileInDir.scala index b661c7ed47..83cd8899a8 100644 --- a/tests/semanticdb/expect/example-dir/FileInDir.scala +++ b/tests/semanticdb/expect/example-dir/FileInDir.scala @@ -1,3 +1,2 @@ package example - -class FileInDir +class FileInDir \ No newline at end of file diff --git a/tests/semanticdb/expect/tastyQuerySimpleClassWithTypeParams.expect.scala b/tests/semanticdb/expect/tastyQuerySimpleClassWithTypeParams.expect.scala new file mode 100644 index 0000000000..cfc33afbb7 --- /dev/null +++ b/tests/semanticdb/expect/tastyQuerySimpleClassWithTypeParams.expect.scala @@ -0,0 +1 @@ +class SimpleClassWithTypeParams/*<-_empty_::SimpleClassWithTypeParams#*/[X/*<-_empty_::SimpleClassWithTypeParams#[X]*/]{} \ No newline at end of file diff --git a/tests/semanticdb/expect/tastyQuerySimpleClassWithTypeParams.scala b/tests/semanticdb/expect/tastyQuerySimpleClassWithTypeParams.scala new file mode 100644 index 0000000000..9e061876db --- /dev/null +++ b/tests/semanticdb/expect/tastyQuerySimpleClassWithTypeParams.scala @@ -0,0 +1 @@ +class SimpleClassWithTypeParams[X]{} \ No newline at end of file diff --git a/tests/semanticdb/metac.expect b/tests/semanticdb/metac.expect index 2622189903..cb49533ce1 100644 --- a/tests/semanticdb/metac.expect +++ b/tests/semanticdb/metac.expect @@ -3872,6 +3872,596 @@ Occurrences: [7:9..7:10): i <- example/TargetName.m1().(i) [7:12..7:18): String -> scala/Predef.String# +expect/TastyQueryByNameMethod.scala +----------------------------------- + +Summary: +Schema => SemanticDB v4 +Uri => TastyQueryByNameMethod.scala +Text => empty +Language => Scala +Symbols => 3 entries +Occurrences => 3 entries + +Symbols: +_empty_/ByNameMethod# => class ByNameMethod extends Object { self: ByNameMethod => +2 decls } +_empty_/ByNameMethod#``(). => primary ctor (): ByNameMethod +_empty_/ByNameMethod#x(). => method x => Int + +Occurrences: +[0:6..0:18): ByNameMethod <- _empty_/ByNameMethod# +[1:4..1:4): <- _empty_/ByNameMethod#``(). +[1:8..1:9): x <- _empty_/ByNameMethod#x(). + +expect/TastyQueryClassDifficultNames.scala +------------------------------------------ + +Summary: +Schema => SemanticDB v4 +Uri => TastyQueryClassDifficultNames.scala +Text => empty +Language => Scala +Symbols => 17 entries +Occurrences => 18 entries +Diagnostics => 2 entries + +Symbols: +_empty_/TastyQueryClassDifficultNames# => class TastyQueryClassDifficultNames extends Object { self: TastyQueryClassDifficultNames => +7 decls } +_empty_/TastyQueryClassDifficultNames#``(). => primary ctor (): TastyQueryClassDifficultNames +_empty_/TastyQueryClassDifficultNames#c# => class c extends Object { self: c => +3 decls } +_empty_/TastyQueryClassDifficultNames#c#``(). => primary ctor (param c: Any): c +_empty_/TastyQueryClassDifficultNames#c#``().(c) => param c: Any +_empty_/TastyQueryClassDifficultNames#c#c# => class c extends Object { self: c => +3 decls } +_empty_/TastyQueryClassDifficultNames#c#c#``(). => primary ctor (param c: Any): c +_empty_/TastyQueryClassDifficultNames#c#c#``().(c) => param c: Any +_empty_/TastyQueryClassDifficultNames#c#c#c# => class c extends Object { self: c => +1 decls } +_empty_/TastyQueryClassDifficultNames#c#c#c#``(). => primary ctor (): c +_empty_/TastyQueryClassDifficultNames#c#c#c. => private[this] val method c Any +_empty_/TastyQueryClassDifficultNames#c#c. => private[this] val method c Any +_empty_/TastyQueryClassDifficultNames#t# => class t extends Object { self: t => +3 decls } +_empty_/TastyQueryClassDifficultNames#t#``(). => primary ctor (param t: Double): t +_empty_/TastyQueryClassDifficultNames#t#``().(t) => param t: Double +_empty_/TastyQueryClassDifficultNames#t#t. => private[this] val method t Double +_empty_/TastyQueryClassDifficultNames#t#tt. => val method tt Double + +Occurrences: +[1:6..1:35): TastyQueryClassDifficultNames <- _empty_/TastyQueryClassDifficultNames# +[2:4..2:4): <- _empty_/TastyQueryClassDifficultNames#``(). +[2:10..2:11): t <- _empty_/TastyQueryClassDifficultNames#t# +[2:11..2:11): <- _empty_/TastyQueryClassDifficultNames#t#``(). +[2:12..2:13): t <- _empty_/TastyQueryClassDifficultNames#t#t. +[2:15..2:21): Double -> scala/Double# +[2:27..2:29): tt <- _empty_/TastyQueryClassDifficultNames#t#tt. +[2:32..2:33): t -> _empty_/TastyQueryClassDifficultNames#t#t. +[5:10..5:11): c <- _empty_/TastyQueryClassDifficultNames#c# +[5:11..5:11): <- _empty_/TastyQueryClassDifficultNames#c#``(). +[5:13..5:14): c <- _empty_/TastyQueryClassDifficultNames#c#c. +[5:16..5:19): Any -> scala/Any# +[5:27..5:28): c <- _empty_/TastyQueryClassDifficultNames#c#c# +[5:28..5:28): <- _empty_/TastyQueryClassDifficultNames#c#c#``(). +[5:29..5:30): c <- _empty_/TastyQueryClassDifficultNames#c#c#c. +[5:33..5:36): Any -> scala/Any# +[5:38..5:38): <- _empty_/TastyQueryClassDifficultNames#c#c#c#``(). +[5:44..5:45): c <- _empty_/TastyQueryClassDifficultNames#c#c#c# + +Diagnostics: +[5:13..5:14): [warning] unused explicit parameter +[5:29..5:30): [warning] unused explicit parameter + +expect/TastyQueryMatching.scala +------------------------------- + +Summary: +Schema => SemanticDB v4 +Uri => TastyQueryMatching.scala +Text => empty +Language => Scala +Symbols => 9 entries +Occurrences => 30 entries + +Symbols: +_empty_/TastyQueryMatching# => class TastyQueryMatching extends Object { self: TastyQueryMatching => +3 decls } +_empty_/TastyQueryMatching#``(). => primary ctor (): TastyQueryMatching +_empty_/TastyQueryMatching#matchingDefault(). => method matchingDefault (param x: Boolean | Unit): Unit +_empty_/TastyQueryMatching#matchingDefault().(x) => param x: Boolean | Unit +_empty_/TastyQueryMatching#matchingOr(). => method matchingOr (param x: Int | String | Double): String | Int | Unit +_empty_/TastyQueryMatching#matchingOr().(x) => param x: Int | String | Double +local0 => val local s: String +local1 => val local number: Int +local2 => val local double: Double + +Occurrences: +[0:6..0:24): TastyQueryMatching <- _empty_/TastyQueryMatching# +[1:4..1:4): <- _empty_/TastyQueryMatching#``(). +[1:8..1:18): matchingOr <- _empty_/TastyQueryMatching#matchingOr(). +[1:19..1:20): x <- _empty_/TastyQueryMatching#matchingOr().(x) +[1:23..1:26): Int -> scala/Int# +[1:27..1:28): | -> scala/`|`# +[1:29..1:35): String -> scala/Predef.String# +[1:36..1:37): | -> scala/`|`# +[1:38..1:44): Double -> scala/Double# +[2:8..2:9): x -> _empty_/TastyQueryMatching#matchingOr().(x) +[3:17..3:18): s <- local0 +[3:20..3:26): String -> scala/Predef.String# +[3:30..3:31): s -> local0 +[3:32..3:38): concat -> java/lang/String#concat(). +[3:39..3:40): s -> local0 +[4:17..4:23): number <- local1 +[4:25..4:28): Int -> scala/Int# +[4:33..4:39): number -> local1 +[4:40..4:41): * -> scala/Int#`*`(+3). +[4:42..4:48): number -> local1 +[5:17..5:23): double <- local2 +[5:25..5:31): Double -> scala/Double# +[5:35..5:40): print -> scala/Predef.print(). +[7:8..7:23): matchingDefault <- _empty_/TastyQueryMatching#matchingDefault(). +[7:24..7:25): x <- _empty_/TastyQueryMatching#matchingDefault().(x) +[7:27..7:34): Boolean -> scala/Boolean# +[7:35..7:36): | -> scala/`|`# +[7:37..7:41): Unit -> scala/Unit# +[8:8..8:9): x -> _empty_/TastyQueryMatching#matchingDefault().(x) +[9:20..9:24): Unit -> scala/Unit# + +expect/TastyQueryMethodComplexFormula.scala +------------------------------------------- + +Summary: +Schema => SemanticDB v4 +Uri => TastyQueryMethodComplexFormula.scala +Text => empty +Language => Scala +Symbols => 5 entries +Occurrences => 12 entries + +Symbols: +_empty_/TastyQueryMethodComplexFormula# => class TastyQueryMethodComplexFormula extends Object { self: TastyQueryMethodComplexFormula => +2 decls } +_empty_/TastyQueryMethodComplexFormula#``(). => primary ctor (): TastyQueryMethodComplexFormula +_empty_/TastyQueryMethodComplexFormula#complexFormula(). => method complexFormula (param param1: Int, param param2: Int): Int +_empty_/TastyQueryMethodComplexFormula#complexFormula().(param1) => param param1: Int +_empty_/TastyQueryMethodComplexFormula#complexFormula().(param2) => param param2: Int + +Occurrences: +[0:6..0:36): TastyQueryMethodComplexFormula <- _empty_/TastyQueryMethodComplexFormula# +[1:8..1:8): <- _empty_/TastyQueryMethodComplexFormula#``(). +[1:12..1:26): complexFormula <- _empty_/TastyQueryMethodComplexFormula#complexFormula(). +[1:27..1:33): param1 <- _empty_/TastyQueryMethodComplexFormula#complexFormula().(param1) +[1:34..1:37): Int -> scala/Int# +[1:39..1:45): param2 <- _empty_/TastyQueryMethodComplexFormula#complexFormula().(param2) +[1:46..1:49): Int -> scala/Int# +[1:54..1:60): param1 -> _empty_/TastyQueryMethodComplexFormula#complexFormula().(param1) +[1:60..1:61): * -> scala/Int#`*`(+3). +[1:61..1:67): param2 -> _empty_/TastyQueryMethodComplexFormula#complexFormula().(param2) +[1:68..1:69): / -> scala/Int#`/`(+3). +[1:69..1:75): param2 -> _empty_/TastyQueryMethodComplexFormula#complexFormula().(param2) + +expect/TastyQueryMethodDifficultNames.scala +------------------------------------------- + +Summary: +Schema => SemanticDB v4 +Uri => TastyQueryMethodDifficultNames.scala +Text => empty +Language => Scala +Symbols => 9 entries +Occurrences => 16 entries +Diagnostics => 2 entries + +Symbols: +_empty_/MethodWithDifficultName# => class MethodWithDifficultName extends Object { self: MethodWithDifficultName => +3 decls } +_empty_/MethodWithDifficultName#``(). => primary ctor (): MethodWithDifficultName +_empty_/MethodWithDifficultName#e(). => method e (val local e: Boolean): Unit +_empty_/MethodWithDifficultName#e().(e) => param e: Boolean +_empty_/MethodWithDifficultName#methodDifficultName(). => method methodDifficultName (param z: Int, param y: String): Unit +_empty_/MethodWithDifficultName#methodDifficultName().(y) => param y: String +_empty_/MethodWithDifficultName#methodDifficultName().(z) => param z: Int +local0 => val local e: Boolean +local1 => val local methodDifficultName: Int + +Occurrences: +[1:6..1:29): MethodWithDifficultName <- _empty_/MethodWithDifficultName# +[3:4..3:4): <- _empty_/MethodWithDifficultName#``(). +[3:8..3:9): e <- _empty_/MethodWithDifficultName#e(). +[3:10..3:11): e <- _empty_/MethodWithDifficultName#e().(e) +[3:13..3:20): Boolean -> scala/Boolean# +[3:29..3:30): e <- local0 +[3:32..3:39): Boolean -> scala/Boolean# +[3:46..3:48): == -> scala/Any#`==`(). +[3:53..3:55): && -> scala/Boolean#`&&`(). +[3:61..3:63): == -> scala/Boolean#`==`(). +[4:8..4:27): methodDifficultName <- _empty_/MethodWithDifficultName#methodDifficultName(). +[4:28..4:29): z <- _empty_/MethodWithDifficultName#methodDifficultName().(z) +[4:31..4:34): Int -> scala/Int# +[4:36..4:37): y <- _empty_/MethodWithDifficultName#methodDifficultName().(y) +[4:39..4:45): String -> scala/Predef.String# +[4:54..4:73): methodDifficultName <- local1 + +Diagnostics: +[3:29..3:30): [warning] unused local definition +[4:54..4:73): [warning] unused local definition + +expect/TastyQueryMethodWithParam.scala +-------------------------------------- + +Summary: +Schema => SemanticDB v4 +Uri => TastyQueryMethodWithParam.scala +Text => empty +Language => Scala +Symbols => 5 entries +Occurrences => 7 entries + +Symbols: +_empty_/MethodWithParam# => class MethodWithParam extends Object { self: MethodWithParam => +2 decls } +_empty_/MethodWithParam#``(). => primary ctor (): MethodWithParam +_empty_/MethodWithParam#methodWithTemParam(). => method methodWithTemParam (param z: Int, param y: String): String +_empty_/MethodWithParam#methodWithTemParam().(y) => param y: String +_empty_/MethodWithParam#methodWithTemParam().(z) => param z: Int + +Occurrences: +[0:6..0:21): MethodWithParam <- _empty_/MethodWithParam# +[1:4..1:4): <- _empty_/MethodWithParam#``(). +[1:8..1:26): methodWithTemParam <- _empty_/MethodWithParam#methodWithTemParam(). +[1:27..1:28): z <- _empty_/MethodWithParam#methodWithTemParam().(z) +[1:30..1:33): Int -> scala/Int# +[1:35..1:36): y <- _empty_/MethodWithParam#methodWithTemParam().(y) +[1:38..1:44): String -> scala/Predef.String# + +expect/TastyQueryMethodWithParams.scala +--------------------------------------- + +Summary: +Schema => SemanticDB v4 +Uri => TastyQueryMethodWithParams.scala +Text => empty +Language => Scala +Symbols => 19 entries +Occurrences => 53 entries + +Symbols: +_empty_/MethodWithParamMultiply# => class MethodWithParamMultiply extends Object { self: MethodWithParamMultiply => +6 decls } +_empty_/MethodWithParamMultiply#``(). => primary ctor (): MethodWithParamMultiply +_empty_/MethodWithParamMultiply#addition(). => method addition (param z: Int, param y: Int): Int +_empty_/MethodWithParamMultiply#addition().(y) => param y: Int +_empty_/MethodWithParamMultiply#addition().(z) => param z: Int +_empty_/MethodWithParamMultiply#complexFormula(). => method complexFormula (param param1: Int, param param2: Double, param param3: Float): Int +_empty_/MethodWithParamMultiply#complexFormula().(param1) => param param1: Int +_empty_/MethodWithParamMultiply#complexFormula().(param2) => param param2: Double +_empty_/MethodWithParamMultiply#complexFormula().(param3) => param param3: Float +_empty_/MethodWithParamMultiply#division(). => method division (param x: Int, param y: Int): Int +_empty_/MethodWithParamMultiply#division().(x) => param x: Int +_empty_/MethodWithParamMultiply#division().(y) => param y: Int +_empty_/MethodWithParamMultiply#multiplication(). => method multiplication (param x: Int, param y: Int): Int +_empty_/MethodWithParamMultiply#multiplication().(x) => param x: Int +_empty_/MethodWithParamMultiply#multiplication().(y) => param y: Int +_empty_/MethodWithParamMultiply#power(). => method power (param x: Int, param y: Int): Int +_empty_/MethodWithParamMultiply#power().(x) => param x: Int +_empty_/MethodWithParamMultiply#power().(y) => param y: Int +local0 => val local intermidiate: Int + +Occurrences: +[0:6..0:29): MethodWithParamMultiply <- _empty_/MethodWithParamMultiply# +[1:4..1:4): <- _empty_/MethodWithParamMultiply#``(). +[1:8..1:16): addition <- _empty_/MethodWithParamMultiply#addition(). +[1:17..1:18): z <- _empty_/MethodWithParamMultiply#addition().(z) +[1:20..1:23): Int -> scala/Int# +[1:25..1:26): y <- _empty_/MethodWithParamMultiply#addition().(y) +[1:28..1:31): Int -> scala/Int# +[1:35..1:36): z -> _empty_/MethodWithParamMultiply#addition().(z) +[1:36..1:37): + -> scala/Int#`+`(+4). +[1:37..1:38): y -> _empty_/MethodWithParamMultiply#addition().(y) +[2:8..2:22): multiplication <- _empty_/MethodWithParamMultiply#multiplication(). +[2:23..2:24): x <- _empty_/MethodWithParamMultiply#multiplication().(x) +[2:25..2:28): Int -> scala/Int# +[2:30..2:31): y <- _empty_/MethodWithParamMultiply#multiplication().(y) +[2:33..2:36): Int -> scala/Int# +[2:40..2:41): x -> _empty_/MethodWithParamMultiply#multiplication().(x) +[2:41..2:42): * -> scala/Int#`*`(+3). +[2:42..2:43): y -> _empty_/MethodWithParamMultiply#multiplication().(y) +[3:8..3:16): division <- _empty_/MethodWithParamMultiply#division(). +[3:17..3:18): x <- _empty_/MethodWithParamMultiply#division().(x) +[3:19..3:22): Int -> scala/Int# +[3:24..3:25): y <- _empty_/MethodWithParamMultiply#division().(y) +[3:26..3:29): Int -> scala/Int# +[3:33..3:34): x -> _empty_/MethodWithParamMultiply#division().(x) +[3:34..3:35): / -> scala/Int#`/`(+3). +[3:35..3:36): y -> _empty_/MethodWithParamMultiply#division().(y) +[4:8..4:13): power <- _empty_/MethodWithParamMultiply#power(). +[4:14..4:15): x <- _empty_/MethodWithParamMultiply#power().(x) +[4:16..4:19): Int -> scala/Int# +[4:21..4:22): y <- _empty_/MethodWithParamMultiply#power().(y) +[4:23..4:26): Int -> scala/Int# +[4:30..4:31): x -> _empty_/MethodWithParamMultiply#power().(x) +[4:31..4:32): ^ -> scala/Int#`^`(+3). +[4:32..4:33): y -> _empty_/MethodWithParamMultiply#power().(y) +[5:8..5:22): complexFormula <- _empty_/MethodWithParamMultiply#complexFormula(). +[5:23..5:29): param1 <- _empty_/MethodWithParamMultiply#complexFormula().(param1) +[5:31..5:34): Int -> scala/Int# +[5:36..5:42): param2 <- _empty_/MethodWithParamMultiply#complexFormula().(param2) +[5:44..5:50): Double -> scala/Double# +[5:52..5:58): param3 <- _empty_/MethodWithParamMultiply#complexFormula().(param3) +[5:60..5:65): Float -> scala/Float# +[6:12..6:24): intermidiate <- local0 +[6:28..6:34): param3 -> _empty_/MethodWithParamMultiply#complexFormula().(param3) +[6:35..6:36): * -> scala/Float#`*`(+5). +[6:38..6:44): param1 -> _empty_/MethodWithParamMultiply#complexFormula().(param1) +[6:45..6:46): + -> scala/Int#`+`(+6). +[6:47..6:53): param3 -> _empty_/MethodWithParamMultiply#complexFormula().(param3) +[6:54..6:55): / -> scala/Float#`/`(+6). +[6:55..6:61): param2 -> _empty_/MethodWithParamMultiply#complexFormula().(param2) +[6:63..6:68): toInt -> scala/Double#toInt(). +[7:8..7:20): intermidiate -> local0 +[7:21..7:22): ^ -> scala/Int#`^`(+3). +[7:23..7:35): intermidiate -> local0 + +expect/TastyQueryMethodWithParams2.scala +---------------------------------------- + +Summary: +Schema => SemanticDB v4 +Uri => TastyQueryMethodWithParams2.scala +Text => empty +Language => Scala +Symbols => 4 entries +Occurrences => 4 entries +Diagnostics => 1 entries + +Symbols: +_empty_/MethodWithParamMultiply2# => class MethodWithParamMultiply2 extends Object { self: MethodWithParamMultiply2 => +2 decls } +_empty_/MethodWithParamMultiply2#``(). => primary ctor (): MethodWithParamMultiply2 +_empty_/MethodWithParamMultiply2#complexFormula(). => method complexFormula (): Unit +local0 => val local intermidiate: Int + +Occurrences: +[0:6..0:30): MethodWithParamMultiply2 <- _empty_/MethodWithParamMultiply2# +[1:4..1:4): <- _empty_/MethodWithParamMultiply2#``(). +[1:8..1:22): complexFormula <- _empty_/MethodWithParamMultiply2#complexFormula(). +[2:12..2:24): intermidiate <- local0 + +Diagnostics: +[2:12..2:24): [warning] unused local definition + +expect/TastyQuerySimpleClass.scala +---------------------------------- + +Summary: +Schema => SemanticDB v4 +Uri => TastyQuerySimpleClass.scala +Text => empty +Language => Scala +Symbols => 2 entries +Occurrences => 2 entries + +Symbols: +_empty_/SimpleClass# => class SimpleClass extends Object { self: SimpleClass => +1 decls } +_empty_/SimpleClass#``(). => primary ctor (): SimpleClass + +Occurrences: +[0:0..0:0): <- _empty_/SimpleClass#``(). +[0:6..0:17): SimpleClass <- _empty_/SimpleClass# + +expect/TastyQuerySimpleMethod.scala +----------------------------------- + +Summary: +Schema => SemanticDB v4 +Uri => TastyQuerySimpleMethod.scala +Text => empty +Language => Scala +Symbols => 4 entries +Occurrences => 6 entries + +Symbols: +_empty_/TastyQuerySimpleMethod# => class TastyQuerySimpleMethod extends Object { self: TastyQuerySimpleMethod => +2 decls } +_empty_/TastyQuerySimpleMethod#``(). => primary ctor (): TastyQuerySimpleMethod +_empty_/TastyQuerySimpleMethod#simpleMethod(). => method simpleMethod (param x: Int): Int +_empty_/TastyQuerySimpleMethod#simpleMethod().(x) => param x: Int + +Occurrences: +[0:6..0:28): TastyQuerySimpleMethod <- _empty_/TastyQuerySimpleMethod# +[1:4..1:4): <- _empty_/TastyQuerySimpleMethod#``(). +[1:8..1:20): simpleMethod <- _empty_/TastyQuerySimpleMethod#simpleMethod(). +[1:21..1:22): x <- _empty_/TastyQuerySimpleMethod#simpleMethod().(x) +[1:24..1:27): Int -> scala/Int# +[1:31..1:32): x -> _empty_/TastyQuerySimpleMethod#simpleMethod().(x) + +expect/TastyQueryValDifficultNames.scala +---------------------------------------- + +Summary: +Schema => SemanticDB v4 +Uri => TastyQueryValDifficultNames.scala +Text => empty +Language => Scala +Symbols => 8 entries +Occurrences => 20 entries + +Symbols: +_empty_/TastyQueryValDifficultNames# => class TastyQueryValDifficultNames extends Object { self: TastyQueryValDifficultNames => +6 decls } +_empty_/TastyQueryValDifficultNames#``(). => primary ctor (): TastyQueryValDifficultNames +_empty_/TastyQueryValDifficultNames#a. => val method a String +_empty_/TastyQueryValDifficultNames#aa. => val method aa String +_empty_/TastyQueryValDifficultNames#g. => val method g String +_empty_/TastyQueryValDifficultNames#i. => val method i String +_empty_/TastyQueryValDifficultNames#isEqualTrimmed. => val method isEqualTrimmed Boolean +local0 => val local i: String + +Occurrences: +[1:6..1:33): TastyQueryValDifficultNames <- _empty_/TastyQueryValDifficultNames# +[2:4..2:4): <- _empty_/TastyQueryValDifficultNames#``(). +[2:8..2:9): g <- _empty_/TastyQueryValDifficultNames#g. +[2:11..2:17): String -> scala/Predef.String# +[2:20..2:21): g -> _empty_/TastyQueryValDifficultNames#g. +[3:8..3:9): i <- _empty_/TastyQueryValDifficultNames#i. +[3:11..3:17): String -> scala/Predef.String# +[3:20..3:21): i -> _empty_/TastyQueryValDifficultNames#i. +[3:35..3:36): i <- local0 +[3:38..3:44): String -> scala/Predef.String# +[3:48..3:49): i -> local0 +[3:50..3:51): + -> java/lang/String#`+`(). +[3:67..3:68): i -> _empty_/TastyQueryValDifficultNames#i. +[4:8..4:9): a <- _empty_/TastyQueryValDifficultNames#a. +[4:23..4:25): aa <- _empty_/TastyQueryValDifficultNames#aa. +[4:38..4:52): isEqualTrimmed <- _empty_/TastyQueryValDifficultNames#isEqualTrimmed. +[4:55..4:56): a -> _empty_/TastyQueryValDifficultNames#a. +[4:57..4:61): trim -> java/lang/String#trim(). +[4:62..4:64): == -> scala/Any#`==`(). +[4:65..4:67): aa -> _empty_/TastyQueryValDifficultNames#aa. + +expect/TastyQueryVar.scala +-------------------------- + +Summary: +Schema => SemanticDB v4 +Uri => TastyQueryVar.scala +Text => empty +Language => Scala +Symbols => 11 entries +Occurrences => 11 entries +Diagnostics => 1 entries + +Symbols: +_empty_/TastyQueryVar# => class TastyQueryVar extends Object { self: TastyQueryVar => +6 decls } +_empty_/TastyQueryVar#``(). => primary ctor (): TastyQueryVar +_empty_/TastyQueryVar#`p_=`(). => var method p_= (param x$1: Unit): Unit +_empty_/TastyQueryVar#`p_=`().(x$1) => param x$1: Unit +_empty_/TastyQueryVar#`x_=`(). => var method x_= (param x$1: Int): Unit +_empty_/TastyQueryVar#`x_=`().(x$1) => param x$1: Int +_empty_/TastyQueryVar#foo(). => method foo => Unit +_empty_/TastyQueryVar#p(). => var method p Unit +_empty_/TastyQueryVar#x(). => var method x Int +local0 => var local z: Int +local1 => val local x: Boolean + +Occurrences: +[0:6..0:19): TastyQueryVar <- _empty_/TastyQueryVar# +[1:4..1:4): <- _empty_/TastyQueryVar#``(). +[1:8..1:9): x <- _empty_/TastyQueryVar#x(). +[2:4..2:5): x -> _empty_/TastyQueryVar#`x_=`(). +[4:8..4:11): foo <- _empty_/TastyQueryVar#foo(). +[5:12..5:13): z <- local0 +[6:8..6:9): z -> local0 +[7:8..7:9): p <- _empty_/TastyQueryVar#p(). +[7:12..7:15): foo -> _empty_/TastyQueryVar#foo(). +[8:4..8:5): p -> _empty_/TastyQueryVar#`p_=`(). +[8:13..8:14): x <- local1 + +Diagnostics: +[8:13..8:14): [warning] unused local definition + +expect/TastyQueryVariousFeatures.scala +-------------------------------------- + +Summary: +Schema => SemanticDB v4 +Uri => TastyQueryVariousFeatures.scala +Text => empty +Language => Scala +Symbols => 24 entries +Occurrences => 75 entries + +Symbols: +_empty_/VariousFeatures# => class VariousFeatures extends Object { self: VariousFeatures => +8 decls } +_empty_/VariousFeatures#``(). => primary ctor (param param1: Double | String, param param2: Int): VariousFeatures +_empty_/VariousFeatures#``().(param1) => param param1: Double | String +_empty_/VariousFeatures#``().(param2) => param param2: Int +_empty_/VariousFeatures#incompleteFormula(). => method incompleteFormula (param param1: Int, param param2: Double, param param3: Float): Int +_empty_/VariousFeatures#incompleteFormula().(param1) => param param1: Int +_empty_/VariousFeatures#incompleteFormula().(param2) => param param2: Double +_empty_/VariousFeatures#incompleteFormula().(param3) => param param3: Float +_empty_/VariousFeatures#modfiyString(). => method modfiyString (param inputString: String): String +_empty_/VariousFeatures#modfiyString().(inputString) => param inputString: String +_empty_/VariousFeatures#modified. => val method modified String +_empty_/VariousFeatures#param1. => private[this] val method param1 Double | String +_empty_/VariousFeatures#param2. => private[this] val method param2 Int +_empty_/VariousFeatures#usingClassParams(). => method usingClassParams => Int | Double | None +_empty_/VariousFeatures#x. => val method x String & Int +_empty_/VariousFeatures2# => class VariousFeatures2 extends Object { self: VariousFeatures2 => +3 decls } +_empty_/VariousFeatures2#``(). => primary ctor (): VariousFeatures2 +_empty_/VariousFeatures2#printHelloWorld(). => method printHelloWorld => Unit +_empty_/VariousFeatures2#y. => val method y String +local0 => val local param1: Double +local1 => val local someLocalVal: Int +local2 => val local otherLocalVal: Int +local3 => val local string: String +local4 => val local double: Double + +Occurrences: +[0:6..0:21): VariousFeatures <- _empty_/VariousFeatures# +[0:21..0:21): <- _empty_/VariousFeatures#``(). +[0:22..0:28): param1 <- _empty_/VariousFeatures#param1. +[0:30..0:36): Double -> scala/Double# +[0:37..0:38): | -> scala/`|`# +[0:39..0:45): String -> scala/Predef.String# +[0:47..0:53): param2 <- _empty_/VariousFeatures#param2. +[0:55..0:58): Int -> scala/Int# +[1:8..1:9): x <- _empty_/VariousFeatures#x. +[1:12..1:18): String -> scala/Predef.String# +[1:19..1:20): & -> scala/`&`# +[1:21..1:24): Int -> scala/Int# +[1:27..1:30): ??? -> scala/Predef.`???`(). +[2:8..2:24): usingClassParams <- _empty_/VariousFeatures#usingClassParams(). +[2:27..2:33): param1 -> _empty_/VariousFeatures#param1. +[3:13..3:19): param1 <- local0 +[3:21..3:27): Double -> scala/Double# +[4:12..4:18): param1 -> local0 +[4:19..4:24): toInt -> scala/Double#toInt(). +[4:25..4:26): + -> scala/Int#`+`(+4). +[4:27..4:33): param2 -> _empty_/VariousFeatures#param2. +[6:37..6:49): someLocalVal <- local1 +[7:16..7:29): otherLocalVal <- local2 +[8:15..8:21): param2 -> _empty_/VariousFeatures#param2. +[8:22..8:23): > -> scala/Int#`>`(+3). +[9:17..9:29): someLocalVal -> local1 +[9:30..9:31): * -> scala/Int#`*`(+3). +[9:32..9:45): otherLocalVal -> local2 +[9:47..9:55): toDouble -> scala/Int#toDouble(). +[11:16..11:20): None -> scala/None. +[12:8..12:20): modfiyString <- _empty_/VariousFeatures#modfiyString(). +[12:21..12:32): inputString <- _empty_/VariousFeatures#modfiyString().(inputString) +[12:34..12:40): String -> scala/Predef.String# +[12:43..12:49): String -> scala/Predef.String# +[13:8..13:14): param1 -> _empty_/VariousFeatures#param1. +[14:17..14:23): string <- local3 +[14:25..14:31): String -> scala/Predef.String# +[14:35..14:41): string -> local3 +[14:42..14:48): concat -> java/lang/String#concat(). +[14:49..14:60): inputString -> _empty_/VariousFeatures#modfiyString().(inputString) +[15:17..15:23): double <- local4 +[15:25..15:31): Double -> scala/Double# +[15:35..15:46): inputString -> _empty_/VariousFeatures#modfiyString().(inputString) +[15:47..15:53): charAt -> java/lang/String#charAt(). +[15:54..15:60): double -> local4 +[15:61..15:66): toInt -> scala/Double#toInt(). +[15:68..15:76): toString -> scala/Any#toString(). +[17:8..17:16): modified <- _empty_/VariousFeatures#modified. +[17:19..17:31): modfiyString -> _empty_/VariousFeatures#modfiyString(). +[19:8..19:25): incompleteFormula <- _empty_/VariousFeatures#incompleteFormula(). +[19:26..19:32): param1 <- _empty_/VariousFeatures#incompleteFormula().(param1) +[19:34..19:37): Int -> scala/Int# +[19:39..19:45): param2 <- _empty_/VariousFeatures#incompleteFormula().(param2) +[19:47..19:53): Double -> scala/Double# +[19:55..19:61): param3 <- _empty_/VariousFeatures#incompleteFormula().(param3) +[19:63..19:68): Float -> scala/Float# +[20:12..20:18): param3 -> _empty_/VariousFeatures#incompleteFormula().(param3) +[20:19..20:20): % -> scala/Float#`%`(+5). +[20:22..20:28): param1 -> _empty_/VariousFeatures#incompleteFormula().(param1) +[20:29..20:30): + -> scala/Int#`+`(+6). +[20:31..20:37): param3 -> _empty_/VariousFeatures#incompleteFormula().(param3) +[20:38..20:39): / -> scala/Float#`/`(+6). +[20:39..20:45): param2 -> _empty_/VariousFeatures#incompleteFormula().(param2) +[20:47..20:52): toInt -> scala/Double#toInt(). +[20:53..20:55): == -> scala/Int#`==`(+3). +[21:12..21:15): ??? -> scala/Predef.`???`(). +[23:12..23:18): param1 -> _empty_/VariousFeatures#incompleteFormula().(param1) +[23:19..23:20): ^ -> scala/Int#`^`(+3). +[23:21..23:27): param1 -> _empty_/VariousFeatures#incompleteFormula().(param1) +[27:6..27:22): VariousFeatures2 <- _empty_/VariousFeatures2# +[28:4..28:4): <- _empty_/VariousFeatures2#``(). +[28:8..28:9): y <- _empty_/VariousFeatures2#y. +[29:8..29:23): printHelloWorld <- _empty_/VariousFeatures2#printHelloWorld(). +[29:26..29:31): print -> scala/Predef.print(). +[29:32..29:33): y -> _empty_/VariousFeatures2#y. + expect/Traits.scala ------------------- @@ -4319,8 +4909,8 @@ example/FileInDir#``(). => primary ctor (): FileInDir Occurrences: [0:8..0:15): example <- example/ -[2:0..2:0): <- example/FileInDir#``(). -[2:6..2:15): FileInDir <- example/FileInDir# +[1:0..1:0): <- example/FileInDir#``(). +[1:6..1:15): FileInDir <- example/FileInDir# expect/exports-example-Codec.scala ---------------------------------- @@ -5629,6 +6219,27 @@ Synthetics: [12:2..12:12):List.apply => *[Nothing] [13:2..13:14):List.`apply` => *[Nothing] +expect/tastyQuerySimpleClassWithTypeParams.scala +------------------------------------------------ + +Summary: +Schema => SemanticDB v4 +Uri => tastyQuerySimpleClassWithTypeParams.scala +Text => empty +Language => Scala +Symbols => 3 entries +Occurrences => 3 entries + +Symbols: +_empty_/SimpleClassWithTypeParams# => class SimpleClassWithTypeParams [typeparam X ] extends Object { self: SimpleClassWithTypeParams[X] => +2 decls } +_empty_/SimpleClassWithTypeParams#[X] => typeparam X +_empty_/SimpleClassWithTypeParams#``(). => primary ctor [typeparam X ](): SimpleClassWithTypeParams[X] + +Occurrences: +[0:6..0:31): SimpleClassWithTypeParams <- _empty_/SimpleClassWithTypeParams# +[0:31..0:31): <- _empty_/SimpleClassWithTypeParams#``(). +[0:32..0:33): X <- _empty_/SimpleClassWithTypeParams#[X] + expect/toplevel.scala ---------------------