Skip to content

Commit

Permalink
Merge pull request #381 from gabro/denotation-ops
Browse files Browse the repository at this point in the history
Add resultType extension method on Symbol
  • Loading branch information
olafurpg authored Sep 28, 2017
2 parents 6b8cccd + d5e40bd commit d511c19
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 28 deletions.
4 changes: 3 additions & 1 deletion project/Mima.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ object Mima {
val ignoredABIProblems: Seq[ProblemFilter] = {
// After v0.5, start running mima checks in CI and document breaking changes here.
// See https://github.com/typesafehub/migration-manager/wiki/sbt-plugin#basic-usage
Seq()
Seq(
ProblemFilters.exclude[Problem]("scalafix.internal.*")
)
}
}
2 changes: 1 addition & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ addSbtPlugin(
"com.eed3si9n" % "sbt-assembly" % "0.14.5" exclude ("org.apache.maven", "maven-plugin-api"))
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.18")
addSbtPlugin("ch.epfl.scala" % "sbt-scalajs-bundler" % "0.7.0")
addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "0.1.14")
addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "0.1.15")

libraryDependencies += "org.scala-sbt" % "scripted-plugin" % sbtVersion.value
Original file line number Diff line number Diff line change
Expand Up @@ -66,37 +66,12 @@ case class ExplicitResultTypes(
case _: Defn.Var => MemberKind.Var
}

private val denotDialect =
dialects.Scala212.copy(allowMethodTypes = true, allowTypeLambdas = true)

def parseDenotationInfo(symbol: Symbol, denot: Denotation): Option[Type] = {
def getDeclType(tpe: Type): Type = tpe match {
case Type.Method(_, tpe) if denot.isDef => tpe
case Type.Lambda(_, tpe) if denot.isDef => getDeclType(tpe)
case Type.Method((Term.Param(_, _, Some(tpe), _) :: Nil) :: Nil, _)
if denot.isVar =>
// Workaround for https://github.com/scalameta/scalameta/issues/1100
tpe
case x =>
x
}
val signature =
if (denot.isVal || denot.isDef | denot.isVar) denot.signature
else {
throw new UnsupportedOperationException(
s"Can't parse type for denotation $denot, denot.info=${denot.signature}")
}
val input = Input.Denotation(signature, symbol)
(denotDialect, input).parse[Type].toOption.map(getDeclType)
}

override def fix(ctx: RuleCtx): Patch = {
def defnType(defn: Defn): Option[(Type, Patch)] =
for {
name <- defnName(defn)
symbol <- name.symbol
denot <- symbol.denotation
typ <- parseDenotationInfo(symbol, denot)
typ <- symbol.resultType
} yield TypeSyntax.prettify(typ, ctx, config.unsafeShortenNames)
import scala.meta._
def fix(defn: Defn, body: Term): Patch = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package scalafix.internal.util

import scala.meta._

object DenotationOps {
val defaultDialect =
dialects.Scala212.copy(allowMethodTypes = true, allowTypeLambdas = true)

def resultType(
symbol: Symbol,
denot: Denotation,
dialect: Dialect): Option[Type] = {
def getDeclType(tpe: Type): Type = tpe match {
case Type.Method(_, tpe) if denot.isDef => tpe
case Type.Lambda(_, tpe) if denot.isDef => getDeclType(tpe)
case Type.Method((Term.Param(_, _, Some(tpe), _) :: Nil) :: Nil, _)
if denot.isVar =>
// Workaround for https://github.com/scalameta/scalameta/issues/1100
tpe
case x =>
x
}
val signature =
if (denot.isVal || denot.isDef | denot.isVar) denot.signature
else {
throw new UnsupportedOperationException(
s"Can't parse type for denotation $denot, denot.info=${denot.signature}")
}
val input = Input.Denotation(signature, symbol)
(dialect, input).parse[Type].toOption.map(getDeclType)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import scala.meta.semanticdb.Symbol
import scala.compat.Platform.EOL
import scala.meta.internal.scalafix.ScalafixScalametaHacks
import scalafix.internal.util.SymbolOps
import scalafix.internal.util.DenotationOps
import scalafix.util.SymbolMatcher
import scalafix.util.TreeOps

Expand All @@ -30,6 +31,9 @@ package object syntax {
@deprecated("Renamed to denotation", "0.5.0")
def denotOpt: Option[Denotation] = denotation
def denotation: Option[Denotation] = index.denotation(symbol)
def resultType: Option[Type] =
denotation.flatMap(denot =>
DenotationOps.resultType(symbol, denot, DenotationOps.defaultDialect))
}
implicit class XtensionSymbol(symbol: Symbol) {
def normalized: Symbol = SymbolOps.normalize(symbol)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package test

object DenotationOpsTest {
def m(x: Int, y: String): List[String] = List(y)
var x = true
val y = m(42, "hey")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package scalafix.tests

import scala.meta._
import scala.meta.contrib._
import scalafix.syntax._
import scalafix.internal.util.DenotationOps

class DenotationOpsTest extends BaseSemanticTest("DenotationOpsTest") {

test("resultType") {
val source = docs.input.parse[Source].get
source.collect {
case t @ Pat.Var(Name("x")) =>
for {
symbol <- t.symbol
resultType <- symbol.resultType
} yield assert(resultType isEqual t"Boolean")

case t @ Pat.Var(Name("y")) =>
for {
symbol <- t.symbol
resultType <- symbol.resultType
} yield assert(resultType isEqual t"List[String]")

case t: Defn.Def if t.name.value == "m" =>
for {
symbol <- t.symbol
resultType <- symbol.resultType
} yield assert(resultType isEqual t"List[String]")
}
}

}

0 comments on commit d511c19

Please sign in to comment.