-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathSelectionRanges.scala
More file actions
83 lines (65 loc) · 2.3 KB
/
Copy pathSelectionRanges.scala
File metadata and controls
83 lines (65 loc) · 2.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import java.io.File
import dotty.tools.dotc.interactive.InteractiveDriver
import dotty.tools.dotc.util.SourceFile
import dotty.tools.dotc.util.SourcePosition
import dotty.tools.dotc.util.Spans
import dotty.tools.dotc.core.Contexts.Context
import dotty.tools.dotc.interactive.Interactive
import coursierapi.Dependency
import coursierapi.Fetch
import scala.jdk.CollectionConverters._
import dotty.tools.dotc.ast.Trees.Tree
import dotty.tools.dotc.ast.Trees.Untyped
object SelectionRanges:
@main def createSelectionRanges: Unit =
val ourScalaCode = """|object Main:
| @main def hello: Unit =
| println("Hello world!")
|""".stripMargin
val fetch = Fetch.create()
fetch.addDependencies(
Dependency.of("org.scala-lang", "scala3-library_3", "3.1.0")
)
val extraLibraries = fetch
.fetch()
.asScala
.map(_.toPath())
.toSeq
val driver = new InteractiveDriver(
List(
"-color:never",
"-classpath",
extraLibraries.mkString(File.pathSeparator)
)
)
val filename = "Example.scala"
val uri = java.net.URI.create(s"file:///$filename")
val sourceFile = SourceFile.virtual(filename, ourScalaCode)
val diagnostics = driver.run(
uri,
sourceFile
)
assert(diagnostics.isEmpty)
// We won't actually use this, but if we wanted we could already
// get the entire tree here
val tree: Option[Tree[Untyped]] =
driver.currentCtx.run.units.headOption.map(_.untpdTree)
// 35 between H<<cursor>>ello
val pos: SourcePosition = new SourcePosition(sourceFile, Spans.Span(55))
given ctx: Context = driver.currentCtx
// Note that we actually have typed trees here, which we don't need for
// this feature.
val trees: List[dotty.tools.dotc.ast.tpd.Tree] =
Interactive.pathTo(driver.openedTrees(uri), pos)
val ranges = trees.map { tree =>
(tree.sourcePos.start, tree.sourcePos.end)
}.distinct
ranges.zipWithIndex
.foreach { case ((start, end), index) =>
val selection = ourScalaCode.slice(start, end)
pprint
.copy(colorLiteral = fansi.Color.Blue)
.pprintln(s"Selection Range: ${index + 1}")
pprint.pprintln(selection)
println()
}