-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add unsafe RawPresentationCompiler implementation #24133
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
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package dotty.tools.pc | ||
|
||
import org.eclipse.lsp4j | ||
import org.eclipse.lsp4j.DiagnosticSeverity | ||
import dotty.tools.dotc.interactive.InteractiveDriver | ||
import dotty.tools.dotc.interfaces.Diagnostic as DiagnosticInterfaces | ||
import dotty.tools.dotc.reporting.Diagnostic | ||
import dotty.tools.pc.utils.InteractiveEnrichments.toLsp | ||
|
||
import scala.meta.pc.VirtualFileParams | ||
import ch.epfl.scala.bsp4j | ||
import dotty.tools.dotc.reporting.CodeAction | ||
import dotty.tools.dotc.rewrites.Rewrites.ActionPatch | ||
import scala.jdk.CollectionConverters.* | ||
import dotty.tools.dotc.core.Contexts.Context | ||
import dotty.tools.dotc.reporting.ErrorMessageID | ||
import org.eclipse.lsp4j.DiagnosticTag | ||
|
||
class DiagnosticProvider(driver: InteractiveDriver, params: VirtualFileParams): | ||
|
||
def diagnostics(): List[lsp4j.Diagnostic] = | ||
val diags = driver.run(params.uri().nn, params.text().nn) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should check if diagnotics are expected via params.shouldReturnDiagnostics() I added it recently, will be available in the new metals There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you tell me the scenario in which you don't want to return diags ? LSP always sends request after keypress in following order: It will be compiled by completion or inlay hints anyway so it doesn't matter, and getting diagnostics is a free operation in terms of computations. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was thinking of cases where people would want to switch between the two modes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I see it, it would be very easy to control this on lsp level though but yeah. We can add it for simplicity. |
||
given Context = driver.currentCtx | ||
diags.flatMap(toLsp) | ||
|
||
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 scalaDiagnostic = new bsp4j.ScalaDiagnostic() | ||
|
||
val actions = diag.msg.actions.map(toBspScalaAction).asJava | ||
scalaDiagnostic.setActions(actions) | ||
// lspDiag.setRelatedInformation(???) Currently not emitted by the compiler | ||
lspDiag.setData(scalaDiagnostic) | ||
if diag.msg.errorId == ErrorMessageID.UnusedSymbolID then | ||
lspDiag.setTags(List(DiagnosticTag.Unnecessary).asJava) | ||
|
||
lspDiag | ||
|
||
private def toBspScalaAction(action: CodeAction): bsp4j.ScalaAction = | ||
val bspAction = bsp4j.ScalaAction(action.title) | ||
action.description.foreach(bspAction.setDescription) | ||
val workspaceEdit = bsp4j.ScalaWorkspaceEdit(action.patches.map(toBspTextEdit).asJava) | ||
bspAction.setEdit(workspaceEdit) | ||
bspAction | ||
|
||
private def toBspTextEdit(actionPatch: ActionPatch): bsp4j.ScalaTextEdit = | ||
val startPos = bsp4j.Position(actionPatch.srcPos.startLine, actionPatch.srcPos.startColumn) | ||
val endPos = bsp4j.Position(actionPatch.srcPos.endLine, actionPatch.srcPos.endColumn) | ||
val range = bsp4j.Range(startPos, endPos) | ||
bsp4j.ScalaTextEdit(range, actionPatch.replacement) | ||
|
||
|
||
private def toDiagnosticSeverity(severity: Int): DiagnosticSeverity = | ||
severity match | ||
case DiagnosticInterfaces.ERROR => DiagnosticSeverity.Error | ||
case DiagnosticInterfaces.WARNING => DiagnosticSeverity.Warning | ||
case DiagnosticInterfaces.INFO => DiagnosticSeverity.Information | ||
case _ => DiagnosticSeverity.Information |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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, | ||
|
@@ -80,7 +81,7 @@ class PcInlayHintsProvider( | |
) | ||
case _ => inlayHints | ||
} | ||
|
||
tree match | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TLDR: I think that it's fine to patch only the necessary changes for now, but this should probably be refactored (similarly as Scala 2 code) soon-ish. The refactor in the Scala 2 PC was meant to allow for more than one "case" to be executed here. This isn't a problem yet, since scalameta/metals#7815 hasn't been ported yet. Though one could make an argument that this problem appeared before and was "hacked" my merging implementations for two inlay hint types.
I think that a similar refactor should be done here as well, though it maybe shouldn't be part of this PR. |
||
case ImplicitConversion(symbol, range) => | ||
val adjusted = adjustPos(range) | ||
|
@@ -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( | ||
|
@@ -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) => | ||
|
@@ -118,19 +123,18 @@ 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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It was removed out of sudden in Scala 2 presentation compiler, I believe it is no longer necessary as we're deduplicating inlay hints during There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it wasn't actually doing anything anymore |
||
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) | ||
|
@@ -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 | ||
} | ||
|
@@ -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 | ||
|
@@ -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 | ||
|
Uh oh!
There was an error while loading. Please reload this page.