Skip to content
This repository has been archived by the owner on Apr 7, 2018. It is now read-only.

Upgrade to Scalameta 3.0.0 #22

Merged
merged 2 commits into from
Feb 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,8 @@ sbtHostScalacOptions.in(Global) := {
// TODO(olafur) avoid getparent()
val sbthostPlugin = classDirectory.in(nsc, Compile).value.getParentFile / jarname
val sbthostPluginPath = sbthostPlugin.getAbsolutePath
val dummy = "-Jdummy=" + sbthostPlugin.lastModified
s"-Xplugin:$sbthostPluginPath" ::
"-Xplugin-require:semanticdb-sbt" ::
dummy ::
Nil
}

Expand All @@ -52,7 +50,8 @@ lazy val input = project
sbtPlugin := true,
compile.in(Compile) :=
compile.in(Compile).dependsOn(Keys.`package`.in(nsc, Compile)).value,
scalacOptions ++= sbtHostScalacOptions.value
scalacOptions ++= sbtHostScalacOptions.value,
scalacOptions += "-Jdummy=" + System.currentTimeMillis()
)

lazy val sbtTests = project
Expand Down Expand Up @@ -146,10 +145,12 @@ lazy val mergeSettings = Def.settings(
}
)

lazy val scalametaVersion = "2.0.0-M3"
// NOTE: Can't upgrade to 2.10.7, because sbt is using 2.10.6.
// (Well, it WAS using 2.10.6 until it was upgraded to 2.10.7 in 0.13.17).
lazy val scalametaVersion = "3.0.0"
lazy val scala210 = "2.10.6"
lazy val scala211 = "2.11.11"
lazy val scala212 = "2.12.3"
lazy val scala211 = "2.11.12"
lazy val scala212 = "2.12.4"

lazy val isScala210 = Seq(
scalaVersion := scala210,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ trait DatabaseOps
extends SymbolOps
with ConfigOps
with InputOps
with DenotationOps
with LanguageOps
with RangeOps
with SymbolInformationOps
with HijackReporterOps
with ReflectionToolkit {
val global: Global
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package scala.meta.internal.sbthost

trait LanguageOps { self: DatabaseOps =>
def isSbt = g.getClass.getName.contains("sbt.compiler.Eval")

lazy val language: String = {
// Select Sbt0137 dialect for scala sources extracted from sbt files
if (isSbt) "Sbt0137" else "Scala210"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package scala.meta.internal.sbthost

import scala.reflect.internal.{util => gu}
import scala.meta.internal.{semanticdb3 => s}

trait RangeOps { self: DatabaseOps =>
implicit class XtensionGPositionSRange(gpos: gu.Position) {
private def source: gu.BatchSourceFile = {
gpos.source.asInstanceOf[gu.BatchSourceFile]
}

private def line(offset: Int): Int = {
// NOTE(olafur): `source.offsetToLine(offset)` does not work as expected under
// SbtGlobal because Sbt does a lot of custom stuff for source files.
// Using line=0 and character=offset is a hack that works only for APIs like
// scala.meta.Position where we convert line/column pairs to offsets using
// lineToOffset(line) + column. This trick is incompatible with how LSP treats
// line/character ranges, where the semantics are different:
// > If the character value is greater than the line length it defaults
// > back to the line length.
// > - https://microsoft.github.io/language-server-protocol/specification#position
0

}

private def character(offset: Int): Int = {
// NOTE(olafur): see above why
// offset - source.lineToOffset(source.offsetToLine(offset))
// won't work as expected.
offset
}

def toMeta: Option[s.Range] = {
gpos match {
case p: gu.RangePosition =>
Some(s.Range(line(p.start), character(p.start), line(p.end), character(p.end)))
case p: gu.OffsetPosition =>
Some(s.Range(line(p.point), character(p.point), line(p.point), character(p.point)))
case _ =>
None
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,28 @@ import scala.tools.nsc.Phase
import scala.tools.nsc.io.VirtualFile
import scala.tools.nsc.plugins.PluginComponent
import scala.tools.nsc.reporters.StoreReporter
import org.langmeta.internal.semanticdb.{schema => s}
import scala.meta.internal.{semanticdb3 => s}

trait SbthostPipeline extends DatabaseOps { self: SbthostPlugin =>
object SbthostComponent extends PluginComponent {
private lazy val pathCount = mutable.Map.empty[Path, Int].withDefaultValue(0)
val global: SbthostPipeline.this.global.type = SbthostPipeline.this.global
// Select Sbt0137 dialect for scala sources extracted from sbt files
private val isSbt = g.getClass.getName.contains("sbt.compiler.Eval")
private val detectedDialect =
if (isSbt) "Sbt0137" else "Scala210"
override val runsAfter = List("typer")
override val runsRightAfter = Some("typer")
val phaseName = "semanticdb-sbt"
def getMessages(source: SourceFile): mutable.LinkedHashSet[s.Message] =
def getDiagnostics(source: SourceFile): mutable.LinkedHashSet[s.Diagnostic] =
g.reporter match {
case reporter: StoreReporter =>
reporter.infos.withFilter(_.pos.source == source).map { info =>
val range = Option(info.pos).collect {
case p: RangePosition => s.Position(p.start, p.end)
case p: OffsetPosition => s.Position(p.point, p.point)
}
val severity = info.severity.id match {
case 0 => s.Message.Severity.INFO
case 1 => s.Message.Severity.WARNING
case 2 => s.Message.Severity.ERROR
case els => s.Message.Severity.UNKNOWN
reporter.infos.withFilter(_.pos.source == source).flatMap { info =>
info.pos.toMeta.map { range =>
val severity = info.severity.id match {
case 0 => s.Diagnostic.Severity.INFORMATION
case 1 => s.Diagnostic.Severity.WARNING
case 2 => s.Diagnostic.Severity.ERROR
case els => s.Diagnostic.Severity.UNKNOWN_SEVERITY
}
s.Diagnostic(Some(range), severity, info.msg)
}
s.Message(range, severity, info.msg)
}
case els =>
mutable.LinkedHashSet.empty
Expand All @@ -53,8 +47,8 @@ trait SbthostPipeline extends DatabaseOps { self: SbthostPlugin =>
// even if they origin from the same source.
else ()
def apply(unit: g.CompilationUnit): Unit = {
val names = ListBuffer.newBuilder[s.ResolvedName]
val denots = mutable.Map.empty[String, s.ResolvedSymbol]
val symbols = mutable.Map.empty[String, s.SymbolInformation]
val occs = ListBuffer.newBuilder[s.SymbolOccurrence]
def isValidSymbol(symbol: g.Symbol) =
symbol.ne(null) && symbol != g.NoSymbol
def computeNames(): Unit = {
Expand Down Expand Up @@ -83,11 +77,15 @@ trait SbthostPipeline extends DatabaseOps { self: SbthostPlugin =>
isValidSymbol(tree.symbol.owner)) {
val symbol = tree.symbol.toSemantic
val symbolSyntax = symbol.syntax
val range = s.Position(tree.pos.point, tree.pos.point)
names += s.ResolvedName(Some(range), symbolSyntax, false)
if (!denots.contains(symbolSyntax)) {
val denot = tree.symbol.toDenotation
denots(symbolSyntax) = s.ResolvedSymbol(symbol.syntax, Some(denot))
tree.pos.focus.toMeta match {
case Some(range) =>
val role = s.SymbolOccurrence.Role.REFERENCE
occs += s.SymbolOccurrence(Some(range), symbolSyntax, role)
if (!symbols.contains(symbolSyntax)) {
symbols(symbolSyntax) = tree.symbol.toSymbolInformation
}
case _ =>
()
}
}
}
Expand All @@ -113,22 +111,23 @@ trait SbthostPipeline extends DatabaseOps { self: SbthostPlugin =>
n
}
val filename = config.relativePath(sourcePath)
val attributes = s.Document(
filename = filename.toString,
language = detectedDialect,
contents = unit.source.content.mkString,
names = names.result(),
symbols = denots.result().values.toSeq,
messages = getMessages(unit.source).toSeq
val document = s.TextDocument(
schema = s.Schema.SEMANTICDB3,
uri = filename.toString,
text = unit.source.content.mkString,
language = language,
symbols = symbols.result().values.toSeq,
occurrences = occs.result(),
diagnostics = getDiagnostics(unit.source).toSeq
)
val semanticdbOutFile = config.semanticdbPath(filename)
semanticdbOutFile.toFile.getParentFile.mkdirs()
// If this is not the first compilation unit for this .sbt file, append.
val options =
if (counter > 0 && isSbt) Array(StandardOpenOption.APPEND)
else Array(StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)
val db = s.Database(List(attributes))
Files.write(semanticdbOutFile.normalize(), db.toByteArray, options: _*)
val documents = s.TextDocuments(List(document))
Files.write(semanticdbOutFile.normalize(), documents.toByteArray, options: _*)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package scala.meta.internal.sbthost
import java.nio.file.Paths
import scala.meta.internal.sbthost
import scala.meta.internal.sbthost
import org.langmeta.internal.semanticdb.{schema => s}
import scala.tools.nsc.Global
import scala.tools.nsc.plugins.Plugin
import scala.tools.nsc.plugins.PluginComponent
Expand Down
Loading