@@ -106,31 +106,43 @@ object Signatures {
106106
107107 private def extractParamTypess (resultType : Type )(using Context ): List [List [Type ]] =
108108 resultType match {
109+ // Reference to a type which is not a type class
109110 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.
121115 case AppliedType (TypeRef (_, cls), (appliedType @ AppliedType (tycon, args)) :: Nil )
122116 if (cls == ctx.definitions.OptionClass || cls == ctx.definitions.SomeClass ) =>
123117 tycon match
124118 case TypeRef (_, cls) if cls == ctx.definitions.SeqClass => List (List (appliedType))
125119 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
128123 case MethodTpe (_, _, resultType) =>
129124 extractParamTypess(resultType.widenDealias)
130125 case _ =>
131126 Nil
132127 }
133128
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+
134146 def toSignature (denot : SingleDenotation )(using Context ): Option [Signature ] = {
135147 val symbol = denot.symbol
136148 val docComment = ParsedComment .docOf(symbol)
@@ -216,11 +228,6 @@ object Signatures {
216228 }
217229 }
218230
219- object underscoreMembersFilter extends NameFilter {
220- def apply (pre : Type , name : Name )(using Context ): Boolean = name.startsWith(" _" )
221- def isStable = true
222- }
223-
224231 /**
225232 * The number of parameters that are applied in `tree`.
226233 *
0 commit comments