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
fix: handle backticked names in inffered-type #3791
Changes from all commits
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 |
---|---|---|
|
@@ -17,13 +17,16 @@ import scala.meta.tokens.{Token as T} | |
import dotty.tools.dotc.ast.Trees.* | ||
import dotty.tools.dotc.ast.untpd | ||
import dotty.tools.dotc.core.Contexts.* | ||
import dotty.tools.dotc.core.NameOps.* | ||
import dotty.tools.dotc.core.Names.* | ||
import dotty.tools.dotc.core.Symbols.* | ||
import dotty.tools.dotc.core.Types.* | ||
import dotty.tools.dotc.interactive.Interactive | ||
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.util.Spans.Span | ||
import org.eclipse.lsp4j.TextEdit | ||
|
||
/** | ||
|
@@ -121,9 +124,10 @@ final class InferredTypeProvider( | |
*/ | ||
case Some(vl @ ValDef(sym, tpt, _)) => | ||
val isParam = path.tail.headOption.exists(_.symbol.isAnonymousFunction) | ||
def baseEdit(withParens: Boolean) = | ||
def baseEdit(withParens: Boolean): TextEdit = | ||
val endPos = findNamePos(params.text, vl).endPos | ||
new TextEdit( | ||
vl.namePos.endPos.toLSP, | ||
endPos.toLSP, | ||
": " + printType(tpt.tpe) + { | ||
if withParens then ")" else "" | ||
} | ||
|
@@ -134,7 +138,7 @@ final class InferredTypeProvider( | |
toCheckFor: Char, | ||
blockStartPos: SourcePosition | ||
) = | ||
val text = params.text.toString() | ||
val text = params.text | ||
val isParensFunction: Boolean = text(applyEndingPos) == toCheckFor | ||
|
||
val alreadyHasParens = | ||
|
@@ -251,4 +255,41 @@ final class InferredTypeProvider( | |
end match | ||
end inferredTypeEdits | ||
|
||
private def findNamePos(text: String, tree: untpd.NamedDefTree)(using | ||
Context | ||
): SourcePosition = | ||
val realName = tree.name.stripModuleClassSuffix.toString.toList | ||
|
||
// `NamedDefTree.namePos` is incorrect for bacticked names | ||
@tailrec | ||
def lookup( | ||
idx: Int, | ||
start: Option[(Int, List[Char])], | ||
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. [note] 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. Maybe forge this note into code? case class Lookup(position: Int, tralingName: List[Char]) |
||
withBacktick: Boolean | ||
): Option[SourcePosition] = | ||
start match | ||
case Some((start, nextMatch :: left)) => | ||
if text.charAt(idx) == nextMatch then | ||
lookup(idx + 1, Some((start, left)), withBacktick) | ||
else lookup(idx + 1, None, withBacktick = false) | ||
case Some((start, Nil)) => | ||
val end = if withBacktick then idx + 1 else idx | ||
val pos = tree.source.atSpan(Span(start, end, start)) | ||
Some(pos) | ||
case None if idx < text.length => | ||
val ch = text.charAt(idx) | ||
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. Should we guard 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.
|
||
if ch == realName.head then | ||
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. Maybe it's too cautious, but can we use 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. Is it possible to get zero length name? 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 don't think it's possible, we could add a require with a proper message just in case 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. added a check for that |
||
lookup(idx + 1, Some((idx, realName.tail)), withBacktick) | ||
else if ch == '`' then lookup(idx + 1, None, withBacktick = true) | ||
else lookup(idx + 1, None, withBacktick = false) | ||
case _ => | ||
None | ||
|
||
val macthedByText = | ||
if realName.nonEmpty then lookup(tree.sourcePos.start, None, false) | ||
else None | ||
|
||
macthedByText.getOrElse(tree.namePos) | ||
end findNamePos | ||
|
||
end InferredTypeProvider |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could it be
@tailrec
?