Skip to content

Commit b95bb20

Browse files
committed
Check only stable qual for import prefix
1 parent afb4806 commit b95bb20

File tree

9 files changed

+3085
-1
lines changed

9 files changed

+3085
-1
lines changed

compiler/src/dotty/tools/dotc/transform/CheckUnused.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
7373
val target = res.dealias.typeSymbol
7474
resolveUsage(target, target.name, res.importPrefix.skipPackageObject) // case _: T =>
7575
case _ =>
76-
else if tree.qualifier.span.isSynthetic || name.exists(_ != tree.symbol.name) then
76+
else if tree.qualifier.span.isSynthetic && tree.qualifier.tpe.isStable || name.exists(_ != tree.symbol.name) then
7777
if !ignoreTree(tree) then
7878
resolveUsage(tree.symbol, name, tree.qualifier.tpe)
7979
else

tests/warn/i22629/BoilerplateResultMappers.scala

+1,709
Large diffs are not rendered by default.

tests/warn/i22629/KeyMapper.scala

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package neotypes
2+
package mappers
3+
4+
import model.exceptions.KeyMapperException
5+
6+
@annotation.implicitNotFound("${A} is not a valid type for keys")
7+
trait KeyMapper[A] { self =>
8+
9+
/** Encodes a value as a key.
10+
*
11+
* @param a
12+
* The value to encode.
13+
* @tparam A
14+
* The type of the value to encode.
15+
* @return
16+
* The key corresponding to that value.
17+
*/
18+
def encodeKey(a: A): String
19+
20+
/** Decodes a key as a value.
21+
*
22+
* @param key
23+
* The key to decode.
24+
* @tparam A
25+
* The type of the value to decode.
26+
* @return
27+
* The value corresponding to that key or an error.
28+
*/
29+
def decodeKey(key: String): Either[KeyMapperException, A]
30+
31+
/** Creates a new [[KeyMapper]] by providing transformation functions to and from A.
32+
*
33+
* @param f
34+
* The function to apply before the encoding.
35+
* @param g
36+
* The function to apply after the decoding.
37+
* @tparam B
38+
* The type of the new [[KeyMapper]]
39+
* @return
40+
* A new [[KeyMapper]] for values of type B.
41+
*/
42+
final def imap[B](f: B => A)(g: A => Either[KeyMapperException, B]): KeyMapper[B] = new KeyMapper[B] {
43+
override def encodeKey(b: B): String =
44+
self.encodeKey(f(b))
45+
46+
override def decodeKey(key: String): Either[KeyMapperException, B] =
47+
self.decodeKey(key).flatMap(g)
48+
}
49+
}
50+
51+
object KeyMapper {
52+
53+
/** Summons an implicit [[KeyMapper]] already in scope by result type.
54+
*
55+
* @param mapper
56+
* A [[KeyMapper]] in scope of the desired type.
57+
* @tparam A
58+
* The result type of the mapper.
59+
* @return
60+
* A [[KeyMapper]] for the given type currently in implicit scope.
61+
*/
62+
def apply[A](implicit mapper: KeyMapper[A]): KeyMapper[A] = mapper
63+
64+
implicit final val string: KeyMapper[String] = new KeyMapper[String] {
65+
override def encodeKey(key: String): String =
66+
key
67+
68+
override def decodeKey(key: String): Either[KeyMapperException, String] =
69+
Right(key)
70+
}
71+
}
+221
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
package neotypes
2+
package mappers
3+
4+
import model.query.QueryParam
5+
6+
import org.neo4j.driver.types.{IsoDuration => NeoDuration, Point => NeoPoint}
7+
8+
import java.time.{
9+
Duration => JDuration,
10+
LocalDate => JDate,
11+
LocalDateTime => JDateTime,
12+
LocalTime => JTime,
13+
Period => JPeriod,
14+
OffsetTime => JZTime,
15+
ZonedDateTime => JZDateTime
16+
}
17+
import java.util.UUID
18+
import scala.collection.immutable.ArraySeq
19+
import scala.jdk.CollectionConverters._
20+
21+
@annotation.implicitNotFound("Could not find the ParameterMapper for ${A}")
22+
sealed trait ParameterMapper[A] { self =>
23+
24+
/** Casts a Scala value of type A into a valid Neo4j parameter.
25+
*
26+
* @param scalaValue
27+
* The value to cast.
28+
* @tparam A
29+
* The type of the scalaValue.
30+
* @return
31+
* The same value casted as a valid Neo4j parameter.
32+
*/
33+
def toQueryParam(scalaValue: A): QueryParam
34+
35+
/** Creates a new [[ParameterMapper]] by applying a function to a Scala value of type B before casting it using this
36+
* mapper.
37+
*
38+
* @param f
39+
* The function to apply before the cast.
40+
* @tparam B
41+
* The input type of the supplied function.
42+
* @return
43+
* A new [[ParameterMapper]] for values of type B.
44+
*/
45+
final def contramap[B](f: B => A): ParameterMapper[B] = new ParameterMapper[B] {
46+
override def toQueryParam(scalaValue: B): QueryParam =
47+
self.toQueryParam(f(scalaValue))
48+
}
49+
}
50+
51+
object ParameterMapper {
52+
53+
/** Summons an implicit [[ParameterMapper]] already in scope by result type.
54+
*
55+
* @param mapper
56+
* A [[ParameterMapper]] in scope of the desired type.
57+
* @tparam A
58+
* The input type of the mapper.
59+
* @return
60+
* A [[ParameterMapper]] for the given type currently in implicit scope.
61+
*/
62+
def apply[A](implicit mapper: ParameterMapper[A]): ParameterMapper[A] = mapper
63+
64+
/** Constructs a [[ParameterMapper]] that always returns a constant value.
65+
*
66+
* @param v
67+
* The value to always return.
68+
* @tparam A
69+
* The type of the input value.
70+
* @return
71+
* A [[ParameterMapper]] that always returns the supplied value.
72+
*/
73+
def const[A](v: AnyRef): ParameterMapper[A] = new ParameterMapper[A] {
74+
override def toQueryParam(scalaValue: A): QueryParam = // warn unused explicit parameter
75+
QueryParam.tag[AnyRef](v)
76+
}
77+
78+
/** Constructs a [[ParameterMapper]] from a cast function.
79+
*
80+
* @param f
81+
* The cast function.
82+
* @tparam A
83+
* The input type of the cast function.
84+
* @return
85+
* a [[ParameterMapper]] that will cast its inputs using the provided function.
86+
*/
87+
private[neotypes] def fromCast[A](f: A => AnyRef): ParameterMapper[A] = new ParameterMapper[A] {
88+
override def toQueryParam(scalaValue: A): QueryParam =
89+
QueryParam.tag[AnyRef](f(scalaValue))
90+
}
91+
92+
/** Constructs a [[ParameterMapper]] that works like an identity function.
93+
*
94+
* Many values do not require any mapping to be used as parameters. For those cases, this private helper is useful to
95+
* reduce boilerplate.
96+
*
97+
* @tparam A
98+
* The type of the input value (must be a subtype of [[AnyRef]]).
99+
* @return
100+
* A [[ParameterMapper]] that always returns its input unchanged.
101+
*/
102+
private[neotypes] def identity[A <: AnyRef] = new ParameterMapper[A] {
103+
override def toQueryParam(scalaValue: A): QueryParam =
104+
QueryParam.tag[A](scalaValue)
105+
}
106+
107+
/** A QueryParam is already encoded so all we need to do is return the same value. This instance is useful to pass
108+
* heterogeneous Lists and Maps.
109+
*/
110+
implicit final val PassthroughParameterMapper: ParameterMapper[QueryParam] =
111+
new ParameterMapper[QueryParam] {
112+
override def toQueryParam(param: QueryParam): QueryParam =
113+
param
114+
}
115+
116+
implicit final val BooleanParameterMapper: ParameterMapper[Boolean] =
117+
ParameterMapper.fromCast(Boolean.box)
118+
119+
implicit final val ByteArrayParameterMapper: ParameterMapper[Array[Byte]] =
120+
ParameterMapper.identity
121+
122+
implicit final val ByteArraySeqParameterMapper: ParameterMapper[ArraySeq[Byte]] =
123+
ByteArrayParameterMapper.contramap(arr => arr.unsafeArray.asInstanceOf[Array[Byte]])
124+
125+
implicit final val DoubleParameterMapper: ParameterMapper[Double] =
126+
ParameterMapper.fromCast(Double.box)
127+
128+
implicit final val FloatParameterMapper: ParameterMapper[Float] =
129+
ParameterMapper.fromCast(Float.box)
130+
131+
implicit final val IntParameterMapper: ParameterMapper[Int] =
132+
ParameterMapper.fromCast(Int.box)
133+
134+
implicit final val LongParameterMapper: ParameterMapper[Long] =
135+
ParameterMapper.fromCast(Long.box)
136+
137+
implicit final val StringParameterMapper: ParameterMapper[String] =
138+
ParameterMapper.identity
139+
140+
implicit final val UUIDParameterMapper: ParameterMapper[UUID] =
141+
ParameterMapper[String].contramap(_.toString)
142+
143+
implicit final val NeoDurationParameterMapper: ParameterMapper[NeoDuration] =
144+
ParameterMapper.identity
145+
146+
implicit final val NeoPointParameterMapper: ParameterMapper[NeoPoint] =
147+
ParameterMapper.identity
148+
149+
implicit final val JDurationParameterMapper: ParameterMapper[JDuration] =
150+
ParameterMapper.identity
151+
152+
implicit final val JPeriodParameterMapper: ParameterMapper[JPeriod] =
153+
ParameterMapper.identity
154+
155+
implicit final val JDateParameterMapper: ParameterMapper[JDate] =
156+
ParameterMapper.identity
157+
158+
implicit final val JTimeParameterMapper: ParameterMapper[JTime] =
159+
ParameterMapper.identity
160+
161+
implicit final val JDateTimeParameterMapper: ParameterMapper[JDateTime] =
162+
ParameterMapper.identity
163+
164+
implicit final val JZTimeParameterMapper: ParameterMapper[JZTime] =
165+
ParameterMapper.identity
166+
167+
implicit final val JZDateTimeParameterMapper: ParameterMapper[JZDateTime] =
168+
ParameterMapper.identity
169+
170+
private final def iterableParameterMapperImpl[T](mapper: ParameterMapper[T]): ParameterMapper[Iterable[T]] =
171+
ParameterMapper.fromCast { col =>
172+
col.iterator.map(mapper.toQueryParam).asJava
173+
}
174+
175+
implicit final def iterableParameterMapper[T, C](implicit
176+
ev: C <:< Iterable[T],
177+
mapper: ParameterMapper[T]
178+
): ParameterMapper[C] =
179+
iterableParameterMapperImpl(mapper).contramap(ev)
180+
181+
implicit final def collectionParameterMapper[T, C[_]](implicit
182+
ev: C[T] <:< Iterable[T],
183+
mapper: ParameterMapper[T]
184+
): ParameterMapper[C[T]] =
185+
iterableParameterMapperImpl(mapper).contramap(ev)
186+
187+
private final def iterableMapParameterMapperImpl[K, V](
188+
keyMapper: KeyMapper[K],
189+
valueMapper: ParameterMapper[V]
190+
): ParameterMapper[Iterable[(K, V)]] =
191+
ParameterMapper.fromCast { col =>
192+
col
193+
.iterator
194+
.map { case (key, v) =>
195+
keyMapper.encodeKey(key) -> valueMapper.toQueryParam(v)
196+
}
197+
.toMap
198+
.asJava
199+
}
200+
201+
implicit final def mapParameterMapper[K, V, M[_, _]](implicit
202+
ev: M[K, V] <:< Iterable[(K, V)],
203+
keyMapper: KeyMapper[K],
204+
valueMapper: ParameterMapper[V]
205+
): ParameterMapper[M[K, V]] =
206+
iterableMapParameterMapperImpl(keyMapper, valueMapper).contramap(ev)
207+
208+
implicit final def optionAnyRefParameterMapper[T](implicit mapper: ParameterMapper[T]): ParameterMapper[Option[T]] =
209+
new ParameterMapper[Option[T]] {
210+
override def toQueryParam(optional: Option[T]): QueryParam =
211+
optional.fold(ifEmpty = QueryParam.NullValue)(mapper.toQueryParam)
212+
}
213+
214+
implicit final def tupleParameterMapper[A, B](implicit
215+
aMapper: ParameterMapper[A],
216+
bMapper: ParameterMapper[B]
217+
): ParameterMapper[(A, B)] =
218+
ParameterMapper[List[QueryParam]].contramap { case (a, b) =>
219+
aMapper.toQueryParam(a) :: bMapper.toQueryParam(b) :: Nil
220+
}
221+
}

0 commit comments

Comments
 (0)