Skip to content

Commit

Permalink
use new infer expected type for singleton complations
Browse files Browse the repository at this point in the history
  • Loading branch information
kasiaMarek committed Aug 23, 2024
1 parent d490d13 commit d4d6cec
Show file tree
Hide file tree
Showing 2 changed files with 2 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import dotty.tools.dotc.core.Contexts.Context
import dotty.tools.dotc.core.Flags
import dotty.tools.dotc.core.StdNames
import dotty.tools.dotc.core.Symbols
import dotty.tools.dotc.core.Symbols.defn
import dotty.tools.dotc.core.Types.*
import dotty.tools.dotc.core.Types.Type
import dotty.tools.dotc.interactive.Interactive
Expand Down Expand Up @@ -61,7 +62,7 @@ class InferExpectedType(
object InterCompletionType:
def inferType(path: List[Tree])(using Context): Option[Type] =
path match
case (lit: Literal) :: Select(Literal(_), _) :: Apply(Select(Literal(_), _), List(Literal(Constant(null)))) :: rest => inferType(rest, lit.span)
case (lit: Literal) :: Select(Literal(_), _) :: Apply(Select(Literal(_), _), List(s: Select)) :: rest if s.symbol == defn.Predef_undefined => inferType(rest, lit.span)
case ident :: rest => inferType(rest, ident.span)
case _ => None

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,13 @@ import dotty.tools.pc.completions.CompletionValue.SingletonValue
import dotty.tools.dotc.ast.tpd.*
import dotty.tools.dotc.core.Constants.Constant
import dotty.tools.dotc.core.Contexts.Context
import dotty.tools.dotc.core.Flags
import dotty.tools.dotc.core.StdNames
import dotty.tools.dotc.core.Symbols
import dotty.tools.dotc.core.Types.AndType
import dotty.tools.dotc.core.Types.AppliedType
import dotty.tools.dotc.core.Types.ConstantType
import dotty.tools.dotc.core.Types.OrType
import dotty.tools.dotc.core.Types.TermRef
import dotty.tools.dotc.core.Types.Type
import dotty.tools.dotc.core.Types.TypeRef
import dotty.tools.dotc.util.Spans.Span
import dotty.tools.dotc.core.Symbols.defn

object SingletonCompletions:
def contribute(
Expand Down Expand Up @@ -55,79 +50,3 @@ object SingletonCompletions:
collectSingletons(tpe1).intersect(collectSingletons(tpe2))
case _ => Nil

object InterCompletionType:
def inferType(path: List[Tree])(using Context): Option[Type] =
path match
case (lit: Literal) :: Select(Literal(_), _) :: Apply(Select(Literal(_), _), List(s: Select)) :: rest if s.symbol == defn.Predef_undefined =>
inferType(rest, lit.span)
case ident :: rest => inferType(rest, ident.span)
case _ => None

def inferType(path: List[Tree], span: Span)(using Context): Option[Type] =
path match
case Apply(head, List(p : Select)) :: rest if p.name == StdNames.nme.??? && p.qualifier.symbol.name == StdNames.nme.Predef && p.span.isSynthetic =>
inferType(rest, span)
case Block(_, expr) :: rest if expr.span.contains(span) =>
inferType(rest, span)
case If(cond, _, _) :: rest if !cond.span.contains(span) =>
inferType(rest, span)
case Typed(expr, tpt) :: _ if expr.span.contains(span) && !tpt.tpe.isErroneous => Some(tpt.tpe)
case Block(_, expr) :: rest if expr.span.contains(span) =>
inferType(rest, span)
case Bind(_, body) :: rest if body.span.contains(span) => inferType(rest, span)
case Alternative(_) :: rest => inferType(rest, span)
case Try(block, _, _) :: rest if block.span.contains(span) => inferType(rest, span)
case CaseDef(_, _, body) :: Try(_, cases, _) :: rest if body.span.contains(span) && cases.exists(_.span.contains(span)) => inferType(rest, span)
case If(cond, _, _) :: rest if !cond.span.contains(span) => inferType(rest, span)
case CaseDef(_, _, body) :: Match(_, cases) :: rest if body.span.contains(span) && cases.exists(_.span.contains(span)) =>
inferType(rest, span)
case NamedArg(_, arg) :: rest if arg.span.contains(span) => inferType(rest, span)
// x match
// case @@
case CaseDef(pat, _, _) :: Match(sel, cases) :: rest if pat.span.contains(span) && cases.exists(_.span.contains(span)) && !sel.tpe.isErroneous =>
sel.tpe match
case tpe: TermRef => Some(tpe.symbol.info).filterNot(_.isErroneous)
case tpe => Some(tpe)
// List(@@)
case SeqLiteral(_, tpe) :: _ if !tpe.tpe.isErroneous =>
Some(tpe.tpe)
// val _: T = @@
// def _: T = @@
case (defn: ValOrDefDef) :: rest if !defn.tpt.tpe.isErroneous => Some(defn.tpt.tpe)
// f(@@)
case (app: Apply) :: rest =>
val param =
for {
ind <- app.args.zipWithIndex.collectFirst {
case (arg, id) if arg.span.contains(span) => id
}
params <- app.symbol.paramSymss.find(!_.exists(_.isTypeParam))
param <- params.get(ind)
} yield param.info
param match
// def f[T](a: T): T = ???
// f[Int](@@)
// val _: Int = f(@@)
case Some(t : TypeRef) if t.symbol.is(Flags.TypeParam) =>
for {
(typeParams, args) <-
app match
case Apply(TypeApply(fun, args), _) =>
val typeParams = fun.symbol.paramSymss.headOption.filter(_.forall(_.isTypeParam))
typeParams.map((_, args.map(_.tpe)))
// val f: (j: "a") => Int
// f(@@)
case Apply(Select(v, StdNames.nme.apply), _) =>
v.symbol.info match
case AppliedType(des, args) =>
Some((des.typeSymbol.typeParams, args))
case _ => None
case _ => None
ind = typeParams.indexOf(t.symbol)
tpe <- args.get(ind)
if !tpe.isErroneous
} yield tpe
case Some(tpe) => Some(tpe)
case _ => None
case _ => None

0 comments on commit d4d6cec

Please sign in to comment.