@@ -106,31 +106,43 @@ object Signatures {
106
106
107
107
private def extractParamTypess (resultType : Type )(using Context ): List [List [Type ]] =
108
108
resultType match {
109
+ // Reference to a type which is not a type class
109
110
case ref : TypeRef if ! ref.symbol.isPrimitiveValueClass =>
110
- if (
111
- ref.symbol.asClass.baseClasses.contains(ctx.definitions.ProductClass ) &&
112
- ! ref.symbol.is(Flags .CaseClass )
113
- ) || ref.symbol.isStaticOwner then
114
- val productAccessors = ref.memberDenots(
115
- underscoreMembersFilter,
116
- (name, buf) => buf += ref.member(name).asSingleDenotation
117
- )
118
- List (productAccessors.map(_.info.finalResultType).toList)
119
- else
120
- ref.symbol.primaryConstructor.paramInfo.paramInfoss
111
+ getExtractorMembers(ref)
112
+ // Option or Some applied type. There is special syntax for multiple returned arguments:
113
+ // Option[TupleN] and Option[Seq],
114
+ // We are not intrested in them, instead we extract proper type parameters from the Option type parameter.
121
115
case AppliedType (TypeRef (_, cls), (appliedType @ AppliedType (tycon, args)) :: Nil )
122
116
if (cls == ctx.definitions.OptionClass || cls == ctx.definitions.SomeClass ) =>
123
117
tycon match
124
118
case TypeRef (_, cls) if cls == ctx.definitions.SeqClass => List (List (appliedType))
125
119
case _ => List (args)
126
- case AppliedType (_, args) =>
127
- List (args)
120
+ // Applied type extractor. We must extract from applied type to retain type parameters
121
+ case appliedType : AppliedType => getExtractorMembers(appliedType)
122
+ // This is necessary to extract proper result type as unapply can return other methods eg. apply
128
123
case MethodTpe (_, _, resultType) =>
129
124
extractParamTypess(resultType.widenDealias)
130
125
case _ =>
131
126
Nil
132
127
}
133
128
129
+ // Returns extractors from given type. In case if there are no extractor methods it fallbacks to get method
130
+ private def getExtractorMembers (resultType : Type )(using Context ): List [List [Type ]] =
131
+ val productAccessors = resultType.memberDenots(
132
+ underscoreMembersFilter,
133
+ (name, buf) => buf += resultType.member(name).asSingleDenotation
134
+ )
135
+ val availableExtractors = if productAccessors.isEmpty then
136
+ List (resultType.member(core.Names .termName(" get" )))
137
+ else
138
+ productAccessors
139
+ List (availableExtractors.map(_.info.finalResultType.stripAnnots).toList)
140
+
141
+ object underscoreMembersFilter extends NameFilter {
142
+ def apply (pre : Type , name : Name )(using Context ): Boolean = name.startsWith(" _" )
143
+ def isStable = true
144
+ }
145
+
134
146
def toSignature (denot : SingleDenotation )(using Context ): Option [Signature ] = {
135
147
val symbol = denot.symbol
136
148
val docComment = ParsedComment .docOf(symbol)
@@ -216,11 +228,6 @@ object Signatures {
216
228
}
217
229
}
218
230
219
- object underscoreMembersFilter extends NameFilter {
220
- def apply (pre : Type , name : Name )(using Context ): Boolean = name.startsWith(" _" )
221
- def isStable = true
222
- }
223
-
224
231
/**
225
232
* The number of parameters that are applied in `tree`.
226
233
*
0 commit comments