Skip to content

Compiler cancellation with new compiler job queue #23191

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/Contexts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ object Contexts {
val local = incCallback
local != null && local.enabled || forceRun

/** The Zinc compile progress callback implementation if we are run from Zinc, null otherwise */
/** The Zinc compile progress callback implementation if we are run from Zinc or used by presentation compiler, null otherwise */
def progressCallback: ProgressCallback | Null = store(progressCallbackLoc)

/** Run `op` if there exists a Zinc progress callback */
Expand Down
13 changes: 10 additions & 3 deletions compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,16 @@ import Denotations.staticRef
import classpath.*
import reporting.*
import util.*
import sbt.interfaces.ProgressCallback

/** A Driver subclass designed to be used from IDEs */
class InteractiveDriver(val settings: List[String]) extends Driver {
import tpd.*

override def sourcesRequired: Boolean = false

private var myProgressCallback: ProgressCallback | Null = null

private val myInitCtx: Context = {
val rootCtx = initCtx.fresh.addMode(Mode.ReadPositions).addMode(Mode.Interactive)
rootCtx.setSetting(rootCtx.settings.YretainTrees, true)
Expand Down Expand Up @@ -141,6 +144,11 @@ class InteractiveDriver(val settings: List[String]) extends Driver {
(fromSource ++ fromClassPath).distinct
}

def runWithProgressCallback(uri: URI, sourceCode: String, progressCallback: ProgressCallback | Null = null) =
myProgressCallback = progressCallback
run(uri, sourceCode)
myProgressCallback = null

def run(uri: URI, sourceCode: String): List[Diagnostic] = run(uri, SourceFile.virtual(uri, sourceCode))

def run(uri: URI, source: SourceFile): List[Diagnostic] = {
Expand All @@ -151,7 +159,7 @@ class InteractiveDriver(val settings: List[String]) extends Driver {
val reporter =
new StoreReporter(null) with UniqueMessagePositions with HideNonSensicalMessages

val run = compiler.newRun(using myInitCtx.fresh.setReporter(reporter))
val run = compiler.newRun(using myInitCtx.fresh.setReporter(reporter).setProgressCallback(myProgressCallback))
myCtx = run.runContext.withRootImports

given Context = myCtx
Expand All @@ -169,8 +177,7 @@ class InteractiveDriver(val settings: List[String]) extends Driver {
myCtx = myCtx.fresh.setPhase(myInitCtx.base.typerPhase)

reporter.removeBufferedMessages
}
catch {
} catch {
case ex: FatalError =>
myCtx = previousCtx
close(uri)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,9 @@ class CachingDriver(override val settings: List[String]) extends InteractiveDriv
override def run(uri: URI, source: SourceFile): List[Diagnostic] =
val diags =
if alreadyCompiled(uri, source.content) then Nil
else super.run(uri, source)
lastCompiledURI = uri
diags

override def run(uri: URI, sourceCode: String): List[Diagnostic] =
val diags =
if alreadyCompiled(uri, sourceCode.toCharArray().nn) then Nil
else super.run(uri, sourceCode)
else
val res = super.run(uri, source)
res
lastCompiledURI = uri
diags

Expand Down
65 changes: 65 additions & 0 deletions presentation-compiler/src/main/dotty/tools/pc/DriverAccess.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package dotty.tools.pc


import scala.meta.pc.PresentationCompilerConfig

import dotty.tools.dotc.interactive.InteractiveDriver
import scala.meta.pc.CancelToken
import scala.meta.pc.VirtualFileParams
import java.util.concurrent.CompletableFuture
import scala.meta.internal.metals.EmptyCancelToken
import java.net.URI
import scala.meta.pc.OffsetParams

case class CompilationInputs(
uri: URI,
code: String,
cancelToken: CancelToken = EmptyCancelToken,
cleanDriver: Boolean = false
):
def show: String =
s"""|uri: $uri
|code: $code
|cancelToken: $cancelToken
|cleanDriver: $cleanDriver
|""".stripMargin

object CompilationInputs:
def empty: CompilationInputs = CompilationInputs(new URI(""), "", EmptyCancelToken, false)
def fromParams(params: VirtualFileParams | OffsetParams, cleanDriver: Boolean = false): CompilationInputs =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def fromParams(params: VirtualFileParams | OffsetParams, cleanDriver: Boolean = false): CompilationInputs =
def fromParams(params: VirtualFileParams, cleanDriver: Boolean = false): CompilationInputs =

OffsetParams <: VirtualFileParams

CompilationInputs(params.uri().nn, params.text().nn, params.token().nn, cleanDriver)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is already a printed in XtensionVirtualFileParams for VirtualFileParams. It has the benefit of printing also where the cursor / range selection was.


class DriverAccess(
config: PresentationCompilerConfig,
driverSettings: List[String],
reportContext: PcReportContext
):

private val taskQueue = TaskQueue(driverSettings, reportContext)
private val worker = Worker(taskQueue, config, reportContext)

def lookup[T](f: InteractiveDriver => T): CompletableFuture[T] =
enqueueTask(taskQueue.LookupTask(f))

def enqueueCancellable[T](inputs: CompilationInputs)
(f: CancelToken ?=> InteractiveDriver => T): CompletableFuture[T] =

given token: CancelToken = inputs.cancelToken
val task = taskQueue.CompilationTask(token, inputs)(f)

enqueueTask(task)

end enqueueCancellable

private def enqueueTask[T](task: taskQueue.Task[T]): CompletableFuture[T] =
taskQueue.enqueue(task)
worker.scheduleProcessing()
task.future

def shutdown(): Unit =
worker.shutdown()
taskQueue.shutdown()

def restart() =
taskQueue.shutdown()

Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,21 @@ class PcDefinitionProvider(
val uri = params.uri().nn
val text = params.text().nn
val filePath = Paths.get(uri)
driver.run(
uri,
SourceFile.virtual(filePath.toString, text)
)

val unit = driver.compilationUnits(uri)
val newCtx = driver.currentCtx.fresh.setCompilationUnit(unit)

val pos = driver.sourcePosition(params)
val path =
Interactive.pathTo(driver.openedTrees(uri), pos)(using driver.currentCtx)
val path = Interactive.pathTo(unit.tpdTree, pos.span)(using newCtx)

given localCtx: Context = Interactive.contextOfPath(path)(using newCtx)
val indexedContext = IndexedContext(pos)(using localCtx)

given ctx: Context = driver.localContext(params)
val indexedContext = IndexedContext(pos)(using ctx)
val result =
if findTypeDef then findTypeDefinitions(path, pos, indexedContext, uri)
else findDefinitions(path, pos, indexedContext, uri)

if result.locations().nn.isEmpty() then fallbackToUntyped(pos, uri)(using ctx)
if result.locations().nn.isEmpty() then fallbackToUntyped(pos, uri)
else result
end definitions

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,18 @@ class PcInlayHintsProvider(
val filePath = Paths.get(uri).nn
val sourceText = params.text().nn
val text = sourceText.toCharArray().nn
val source =
SourceFile.virtual(filePath.toString, sourceText)
driver.run(uri, source)
given InlayHintsParams = params

given InlayHintsParams = params
given InferredType.Text = InferredType.Text(text)
given ctx: Context = driver.currentCtx
val unit = driver.currentCtx.run.nn.units.head

val unit = driver.compilationUnits(uri)
val pos = driver.sourcePosition(params)

def provide(): List[InlayHint] =
val deepFolder = DeepFolder[InlayHints](collectDecorations)
Interactive
.pathTo(driver.openedTrees(uri), pos)(using driver.currentCtx)
.pathTo(unit.tpdTree, pos.span)
.headOption
.getOrElse(unit.tpdTree)
.enclosedChildren(pos.span)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package dotty.tools.pc

import scala.meta.internal.metals.ReportContext
import scala.meta.internal.metals.Reporter
import scala.meta.internal.metals.EmptyReportContext

class PcReportContext(underlying: ReportContext, pcDetails: Map[String, String]) extends ReportContext:
override def incognito: Reporter = underlying.incognito
override def unsanitized: Reporter = underlying.unsanitized
override def bloop: Reporter = underlying.bloop
def additionalData: String = pcDetails.mkString("\n")

object PcReportContext:
def empty: PcReportContext = PcReportContext(EmptyReportContext, Map.empty)

This file was deleted.

This file was deleted.

Loading
Loading