Skip to content
Open
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 @@ -179,7 +179,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
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import java.util.zip.*
import scala.collection.*
import scala.io.Codec

import dotty.tools.dotc.sbt.interfaces.ProgressCallback
import dotty.tools.io.AbstractFile

import ast.{Trees, tpd}
Expand All @@ -30,6 +31,9 @@ class InteractiveDriver(val settings: List[String]) extends Driver {

override def sourcesRequired: Boolean = false

private var myProgressCallback: ProgressCallback = new ProgressCallback:
override def isCancelled(): Boolean = Thread.interrupted()

private val myInitCtx: Context = {
val rootCtx = initCtx.fresh.addMode(Mode.ReadPositions).addMode(Mode.Interactive)
rootCtx.setSetting(rootCtx.settings.YretainTrees, true)
Expand Down Expand Up @@ -151,7 +155,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 +173,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
16 changes: 4 additions & 12 deletions presentation-compiler/src/main/dotty/tools/pc/CachingDriver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ import scala.compiletime.uninitialized
*/
class CachingDriver(override val settings: List[String]) extends InteractiveDriver(settings):

@volatile private var lastCompiledURI: URI = uninitialized
private var lastCompiledURI: URI = uninitialized
private var previousDiags = List.empty[Diagnostic]

private def alreadyCompiled(uri: URI, content: Array[Char]): Boolean =
compilationUnits.get(uri) match
Expand All @@ -40,17 +41,8 @@ class CachingDriver(override val settings: List[String]) extends InteractiveDriv
case _ => false

override def run(uri: URI, source: SourceFile): List[Diagnostic] =
val diags =
if alreadyCompiled(uri, source.content) then Nil
else super.run(uri, source)
if !alreadyCompiled(uri, source.content) then previousDiags = 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)
lastCompiledURI = uri
diags
previousDiags

end CachingDriver
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package dotty.tools.pc

import dotty.tools.dotc.core.Contexts.Context
import dotty.tools.dotc.interactive.InteractiveDriver
import dotty.tools.dotc.interfaces.Diagnostic as DiagnosticInterfaces
import dotty.tools.dotc.reporting.ErrorMessageID
import dotty.tools.dotc.reporting.Diagnostic
import dotty.tools.dotc.reporting.CodeAction
import dotty.tools.dotc.rewrites.Rewrites.ActionPatch
import dotty.tools.pc.utils.InteractiveEnrichments.toLsp

import org.eclipse.lsp4j

import scala.jdk.CollectionConverters.*
import scala.meta.pc.VirtualFileParams

class DiagnosticProvider(driver: InteractiveDriver, params: VirtualFileParams):

def diagnostics(): List[lsp4j.Diagnostic] =
if params.shouldReturnDiagnostics then
val diags = driver.run(params.uri().nn, params.text().nn)
given Context = driver.currentCtx
diags.flatMap(toLsp)
else Nil

private def toLsp(diag: Diagnostic)(using Context): Option[lsp4j.Diagnostic] =
Option.when(diag.pos.exists):
val lspDiag = lsp4j.Diagnostic(
diag.pos.toLsp,
diag.msg.message,
toDiagnosticSeverity(diag.level),
"presentation compiler",
)
lspDiag.setCode(diag.msg.errorId.errorNumber)

val actions = diag.msg.actions.map(toLspScalaAction).asJava

lspDiag.setData(actions)
if diag.msg.errorId == ErrorMessageID.UnusedSymbolID then
lspDiag.setTags(List(lsp4j.DiagnosticTag.Unnecessary).asJava)

lspDiag

private def toLspScalaAction(action: CodeAction): lsp4j.CodeAction =
val lspAction = lsp4j.CodeAction(action.title)
lspAction.setKind(lsp4j.CodeActionKind.QuickFix)
lspAction.setIsPreferred(true)
val edits = action.patches.groupBy(_.srcPos.source.path)
.map((path, actions) => path -> (actions.map(toLspTextEdit).asJava))
.asJava

val workspaceEdit = lsp4j.WorkspaceEdit(edits)
lspAction.setEdit(workspaceEdit)
lspAction

private def toLspTextEdit(actionPatch: ActionPatch): lsp4j.TextEdit =
val startPos = lsp4j.Position(actionPatch.srcPos.startLine, actionPatch.srcPos.startColumn)
val endPos = lsp4j.Position(actionPatch.srcPos.endLine, actionPatch.srcPos.endColumn)
val range = lsp4j.Range(startPos, endPos)
lsp4j.TextEdit(range, actionPatch.replacement)

private def toDiagnosticSeverity(severity: Int): lsp4j.DiagnosticSeverity =
severity match
case DiagnosticInterfaces.ERROR => lsp4j.DiagnosticSeverity.Error
case DiagnosticInterfaces.WARNING => lsp4j.DiagnosticSeverity.Warning
case DiagnosticInterfaces.INFO => lsp4j.DiagnosticSeverity.Information
case _ => lsp4j.DiagnosticSeverity.Information
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import dotty.tools.dotc.util.Spans.Span
import org.eclipse.lsp4j.InlayHint
import org.eclipse.lsp4j.InlayHintKind
import org.eclipse.{lsp4j as l}
import scala.meta.internal.pc.InlayHintOrigin

class PcInlayHintsProvider(
driver: InteractiveDriver,
Expand Down Expand Up @@ -80,7 +81,7 @@ class PcInlayHintsProvider(
)
case _ => inlayHints
}

tree match
case ImplicitConversion(symbol, range) =>
val adjusted = adjustPos(range)
Expand All @@ -89,11 +90,13 @@ class PcInlayHintsProvider(
adjusted.startPos.toLsp,
labelPart(symbol, symbol.decodedName) :: LabelPart("(") :: Nil,
InlayHintKind.Parameter,
InlayHintOrigin.ImplicitConversion
)
.add(
adjusted.endPos.toLsp,
LabelPart(")") :: Nil,
InlayHintKind.Parameter,
InlayHintOrigin.ImplicitConversion
)
case ImplicitParameters(trees, pos) =>
firstPassHints.add(
Expand All @@ -104,12 +107,14 @@ class PcInlayHintsProvider(
case None => LabelPart(label)
),
InlayHintKind.Parameter,
InlayHintOrigin.ImplicitParameters
)
case ValueOf(label, pos) =>
firstPassHints.add(
adjustPos(pos).toLsp,
LabelPart("(") :: LabelPart(label) :: List(LabelPart(")")),
InlayHintKind.Parameter,
InlayHintOrigin.ImplicitParameters
)
case TypeParameters(tpes, pos, sel)
if !syntheticTupleApply(sel) =>
Expand All @@ -118,20 +123,19 @@ class PcInlayHintsProvider(
adjustPos(pos).endPos.toLsp,
label,
InlayHintKind.Type,
InlayHintOrigin.TypeParameters
)
case InferredType(tpe, pos, defTree)
if !isErrorTpe(tpe) =>
val adjustedPos = adjustPos(pos).endPos
if firstPassHints.containsDef(adjustedPos.start) then firstPassHints
else
firstPassHints
.add(
adjustedPos.toLsp,
LabelPart(": ") :: toLabelParts(tpe, pos),
InlayHintKind.Type,
)
.addDefinition(adjustedPos.start)
case Parameters(isInfixFun, args) =>
firstPassHints
.add(
adjustedPos.toLsp,
LabelPart(": ") :: toLabelParts(tpe, pos),
InlayHintKind.Type,
InlayHintOrigin.InferredType
)
case Parameters(isInfixFun, args) =>
def isNamedParam(pos: SourcePosition): Boolean =
val start = text.indexWhere(!_.isWhitespace, pos.start)
val end = text.lastIndexWhere(!_.isWhitespace, pos.end - 1)
Expand Down Expand Up @@ -167,6 +171,7 @@ class PcInlayHintsProvider(
hintPos.startPos.toLsp,
List(LabelPart(labelStr)),
InlayHintKind.Parameter,
if params.byNameParameters then InlayHintOrigin.ByNameParameters else InlayHintOrigin.NamedParameters
)
else ih
}
Expand Down Expand Up @@ -515,7 +520,7 @@ object XRayModeHint:
case Some(sel: Select) if sel.isForComprehensionMethod => false
case Some(par) if par.sourcePos.exists && par.sourcePos.line == tree.sourcePos.line => true
case _ => false

tree match
/*
anotherTree
Expand All @@ -530,7 +535,7 @@ object XRayModeHint:
.select
*/
case select @ Select(innerTree, _)
if innerTree.sourcePos.exists && !isParentOnSameLine && !isParentApply &&
if innerTree.sourcePos.exists && !isParentOnSameLine && !isParentApply &&
isEndOfLine(tree.sourcePos) =>
Some((select.tpe.widen.deepDealiasAndSimplify, tree.sourcePos))
case _ => None
Expand Down
Loading