From ed1ef0d1a81d1403d03252d323f06d087f1307ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Zyba=C5=82a?= Date: Mon, 16 Nov 2020 09:01:53 +0100 Subject: [PATCH 1/5] Add NameNormalizer --- .../dotty/dokka/tasty/ClassLikeSupport.scala | 23 ++++++++----------- .../dotty/dokka/tasty/NameNormalizer.scala | 14 +++++++++++ .../src/dotty/dokka/tasty/TastyParser.scala | 2 +- .../src/dotty/dokka/tasty/TypesSupport.scala | 2 +- 4 files changed, 25 insertions(+), 16 deletions(-) create mode 100644 scala3doc/src/dotty/dokka/tasty/NameNormalizer.scala diff --git a/scala3doc/src/dotty/dokka/tasty/ClassLikeSupport.scala b/scala3doc/src/dotty/dokka/tasty/ClassLikeSupport.scala index 6de72f1fb18d..1dde046b4674 100644 --- a/scala3doc/src/dotty/dokka/tasty/ClassLikeSupport.scala +++ b/scala3doc/src/dotty/dokka/tasty/ClassLikeSupport.scala @@ -30,7 +30,7 @@ trait ClassLikeSupport: object DClass: def apply[T >: DClass](classDef: ClassDef)( dri: DRI = classDef.symbol.dri, - name: String = classDef.name, + name: String = classDef.symbol.normalizedName, signatureOnly: Boolean = false, modifiers: Seq[Modifier] = classDef.symbol.getExtraModifiers(), ): DClass = @@ -109,7 +109,7 @@ trait ClassLikeSupport: private def parseMember(s: Tree): Option[Member] = processTreeOpt(s)(s match case dd: DefDef if !dd.symbol.isHiddenByVisibility && !dd.symbol.isSyntheticFunc && dd.symbol.isExtensionMethod => dd.symbol.extendedSymbol.map { extSym => - val target = ExtensionTarget(extSym.symbol.name, extSym.tpt.dokkaType.asSignature, extSym.tpt.symbol.dri) + val target = ExtensionTarget(extSym.symbol.normalizedName, extSym.tpt.dokkaType.asSignature, extSym.tpt.symbol.dri) parseMethod(dd.symbol, kind = Kind.Extension(target)) } // TODO check given methods? @@ -164,7 +164,7 @@ trait ClassLikeSupport: private def parseInheritedMember(s: Tree): Option[Member] = processTreeOpt(s)(s match case c: ClassDef if c.symbol.shouldDocumentClasslike && !c.symbol.isGiven => Some(parseClasslike(c, signatureOnly = true)) case other => parseMember(other) - ).map(_.withOrigin(Origin.InheritedFrom(s.symbol.owner.name, s.symbol.owner.dri))) + ).map(_.withOrigin(Origin.InheritedFrom(s.symbol.owner.normalizedName, s.symbol.owner.dri))) extension (c: ClassDef): def membersToDocument = c.body.filterNot(_.symbol.isHiddenByVisibility) @@ -197,7 +197,7 @@ trait ClassLikeSupport: }.toList def getParameterModifier(parameter: Symbol): String = - val fieldSymbol = c.symbol.field(parameter.name) + val fieldSymbol = c.symbol.field(parameter.normalizedName) if fieldSymbol.flags.is(Flags.Mutable) then "var " else if fieldSymbol.flags.is(Flags.ParamAccessor) && !c.symbol.flags.is(Flags.Case) && !fieldSymbol.flags.is(Flags.Private) then "val " else "" @@ -221,7 +221,6 @@ trait ClassLikeSupport: def parseObject(classDef: ClassDef, signatureOnly: Boolean = false)(using ctx: Context): DClass = DClass(classDef)( - name = classDef.name.stripSuffix("$"), // All objects are final so we do not need final modifer! modifiers = classDef.symbol.getExtraModifiers().filter(_ != Modifier.Final), signatureOnly = signatureOnly @@ -266,11 +265,7 @@ trait ClassLikeSupport: Kind.Implicit(Kind.Def, None) else kind - val name = methodKind match - case Kind.Constructor => "this" - case Kind.Given(_, _) => methodSymbol.name.stripPrefix("given_") - case Kind.Extension(_) => methodSymbol.name.stripPrefix("extension_") - case _ => methodSymbol.name + val name = method.symbol.normalizedName new DFunction( methodSymbol.dri, @@ -302,7 +297,7 @@ trait ClassLikeSupport: def parseArgument(argument: ValDef, prefix: Symbol => String, isExtendedSymbol: Boolean = false, isGrouped: Boolean = false): DParameter = new DParameter( argument.symbol.dri, - prefix(argument.symbol) + argument.symbol.name, + prefix(argument.symbol) + argument.symbol.normalizedName, argument.symbol.documentation.asJava, null, argument.tpt.dokkaType, @@ -320,7 +315,7 @@ trait ClassLikeSupport: else "" new DTypeParameter( - Invariance(TypeParameter(argument.symbol.dri, variancePrefix + argument.symbol.name, null)), + Invariance(TypeParameter(argument.symbol.dri, variancePrefix + argument.symbol.normalizedName, null)), argument.symbol.documentation.asJava, null, JList(argument.rhs.dokkaType), @@ -343,7 +338,7 @@ trait ClassLikeSupport: new DProperty( typeDef.symbol.dri, - typeDef.name, + typeDef.symbol.normalizedName, /*documentation =*/ typeDef.symbol.documentation.asJava, /*expectPresentInSet =*/ null, // unused /*sources =*/ JMap(), @@ -374,7 +369,7 @@ trait ClassLikeSupport: new DProperty( valDef.symbol.dri, - valDef.name, + valDef.symbol.normalizedName, /*documentation =*/ valDef.symbol.documentation.asJava, /*expectPresentInSet =*/ null, // unused /*sources =*/ JMap(), diff --git a/scala3doc/src/dotty/dokka/tasty/NameNormalizer.scala b/scala3doc/src/dotty/dokka/tasty/NameNormalizer.scala new file mode 100644 index 000000000000..43642e5c0a26 --- /dev/null +++ b/scala3doc/src/dotty/dokka/tasty/NameNormalizer.scala @@ -0,0 +1,14 @@ +package dotty.dokka.tasty + +import dotty.dokka._ + +trait NameNormalizer: + self: TastyParser => + import qctx.reflect._ + extension (s: Symbol) def normalizedName: String = { + val withoutGivenPrefix = if s.isGiven then s.name.stripPrefix("given_") else s.name + val withoutExtensionPrefix = if s.isExtensionMethod then withoutGivenPrefix.stripPrefix("extension_") else withoutGivenPrefix + val withoutObjectSuffix = if s.flags.is(Flags.Object) then withoutExtensionPrefix.stripSuffix("$") else withoutExtensionPrefix + val constructorNormalizedName = if s.isClassConstructor then "this" else withoutObjectSuffix + constructorNormalizedName + } diff --git a/scala3doc/src/dotty/dokka/tasty/TastyParser.scala b/scala3doc/src/dotty/dokka/tasty/TastyParser.scala index 67985b4626b9..4b97ae3d796c 100644 --- a/scala3doc/src/dotty/dokka/tasty/TastyParser.scala +++ b/scala3doc/src/dotty/dokka/tasty/TastyParser.scala @@ -157,7 +157,7 @@ trait DokkaBaseTastyInspector: /** Parses a single Tasty compilation unit. */ case class TastyParser(qctx: QuoteContext, inspector: DokkaBaseTastyInspector, config: DottyDokkaConfig) - extends ScaladocSupport with BasicSupport with TypesSupport with ClassLikeSupport with SyntheticsSupport with PackageSupport: + extends ScaladocSupport with BasicSupport with TypesSupport with ClassLikeSupport with SyntheticsSupport with PackageSupport with NameNormalizer: import qctx.reflect._ def sourceSet = inspector.sourceSet diff --git a/scala3doc/src/dotty/dokka/tasty/TypesSupport.scala b/scala3doc/src/dotty/dokka/tasty/TypesSupport.scala index ccdeb4f6bba9..140aab376625 100644 --- a/scala3doc/src/dotty/dokka/tasty/TypesSupport.scala +++ b/scala3doc/src/dotty/dokka/tasty/TypesSupport.scala @@ -61,7 +61,7 @@ trait TypesSupport: private def link(symbol: Symbol)(using cxt: Context): List[JProjection] = { val suffix = if symbol.isValDef then texts(".type") else Nil - (new TypeParameter(symbol.dri, symbol.name, null)) :: suffix + (new TypeParameter(symbol.dri, symbol.normalizedName, null)) :: suffix } private def commas(lists: List[List[JProjection]]) = lists match From 752cb1b3a040eed6528f2158d3be5a42c06f1be5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Zyba=C5=82a?= Date: Mon, 16 Nov 2020 11:31:40 +0100 Subject: [PATCH 2/5] Add extension information in extension function pages --- .../dokka/translators/ScalaContentBuilder.scala | 8 ++++++++ .../dotty/dokka/translators/ScalaPageCreator.scala | 12 ++++++++++-- .../dokka/translators/ScalaSignatureProvider.scala | 5 +++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/scala3doc/src/dotty/dokka/translators/ScalaContentBuilder.scala b/scala3doc/src/dotty/dokka/translators/ScalaContentBuilder.scala index e15296aa88a8..466da52762e6 100644 --- a/scala3doc/src/dotty/dokka/translators/ScalaContentBuilder.scala +++ b/scala3doc/src/dotty/dokka/translators/ScalaContentBuilder.scala @@ -248,6 +248,14 @@ class ScalaPageContentBuilder( def signature(d: Documentable) = addChildren(signatureProvider.signature(d).asScala.toList) + private def buildSignature(d: Documentable, s: Signature) = signatureProvider.asInstanceOf[ScalaSignatureProvider].signature(d, s) + + def signature(d: Documentable, s: Signature) = addChild(buildSignature(d, s)) + + def inlineSignature(d: Documentable, s: Signature) = addChildren( + buildSignature(d, s).getChildren.asScala.toSeq + ) + def defaultHeaders = List( contentForDRIs( dris = mainDRI, diff --git a/scala3doc/src/dotty/dokka/translators/ScalaPageCreator.scala b/scala3doc/src/dotty/dokka/translators/ScalaPageCreator.scala index 6f2fabeaf713..0965a5c18d44 100644 --- a/scala3doc/src/dotty/dokka/translators/ScalaPageCreator.scala +++ b/scala3doc/src/dotty/dokka/translators/ScalaPageCreator.scala @@ -317,12 +317,20 @@ class ScalaPageCreator( case _ => withNamedTags } + val withExtensionInformation = d.kind match { + case Kind.Extension(on) => + val sourceSets = d.getSourceSets.asScala.toSet + withCompanion.cell(sourceSets = sourceSets)(_.text("Extension")) + .cell(sourceSets = sourceSets)(_.text(s"This function is an extension on (${on.name}: ").inlineSignature(d, on.signature).text(")")) + case _ => withCompanion + } + d match - case null => withCompanion + case null => withExtensionInformation case m: Member => sourceLinks.pathTo(m).fold(withCompanion){ link => val sourceSets = m.getSourceSets.asScala.toSet - withCompanion.cell(sourceSets = sourceSets)(_.text("Source")) + withExtensionInformation.cell(sourceSets = sourceSets)(_.text("Source")) .cell(sourceSets = sourceSets)(_.resolvedLink("(source)", link)) } } diff --git a/scala3doc/src/dotty/dokka/translators/ScalaSignatureProvider.scala b/scala3doc/src/dotty/dokka/translators/ScalaSignatureProvider.scala index 35911cbd1e18..a090a823e79e 100644 --- a/scala3doc/src/dotty/dokka/translators/ScalaSignatureProvider.scala +++ b/scala3doc/src/dotty/dokka/translators/ScalaSignatureProvider.scala @@ -31,6 +31,11 @@ class ScalaSignatureProvider(contentConverter: CommentsToContentConverter, logge def driLink(text: String, dri: DRI): SignatureBuilder = ContentNodeBuilder(builder.driLink(text, dri)) } + def signature(d: Documentable, s: Signature) = signatureContent(d){ builder => + val res = ContentNodeBuilder(builder).signature(s) + res.asInstanceOf[ContentNodeBuilder].builder + } + override def signature(documentable: Documentable) = JList(signatureContent(documentable){ builder => val withAnnotations = ContentNodeBuilder(builder).annotationsBlock(documentable) From 424c093a1187feddd1f06081e001f639a88bc788 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Zyba=C5=82a?= Date: Mon, 16 Nov 2020 12:25:37 +0100 Subject: [PATCH 3/5] Extension method groupping fix. CRs from PR #10306 --- scala3doc/src/dotty/dokka/model/api/api.scala | 2 +- .../dotty/dokka/tasty/ClassLikeSupport.scala | 7 +++++- .../src/dotty/dokka/tasty/TastyParser.scala | 2 +- .../ImplicitMembersExtensionTransformer.scala | 23 ++++++++++++------- .../translators/ScalaSignatureProvider.scala | 4 ++-- 5 files changed, 25 insertions(+), 13 deletions(-) diff --git a/scala3doc/src/dotty/dokka/model/api/api.scala b/scala3doc/src/dotty/dokka/model/api/api.scala index 4ba85604945a..ba73d137953c 100644 --- a/scala3doc/src/dotty/dokka/model/api/api.scala +++ b/scala3doc/src/dotty/dokka/model/api/api.scala @@ -49,7 +49,7 @@ enum Modifier(val name: String, val prefix: Boolean): case Opaque extends Modifier("opaque", true) case Open extends Modifier("open", true) -case class ExtensionTarget(name: String, signature: Signature, dri: DRI) +case class ExtensionTarget(name: String, signature: Signature, dri: DRI, position: Long) case class ImplicitConversion(from: DRI, to: DRI) trait ImplicitConversionProvider { def conversion: Option[ImplicitConversion] } trait Classlike diff --git a/scala3doc/src/dotty/dokka/tasty/ClassLikeSupport.scala b/scala3doc/src/dotty/dokka/tasty/ClassLikeSupport.scala index 1dde046b4674..6907c79bdec4 100644 --- a/scala3doc/src/dotty/dokka/tasty/ClassLikeSupport.scala +++ b/scala3doc/src/dotty/dokka/tasty/ClassLikeSupport.scala @@ -109,7 +109,12 @@ trait ClassLikeSupport: private def parseMember(s: Tree): Option[Member] = processTreeOpt(s)(s match case dd: DefDef if !dd.symbol.isHiddenByVisibility && !dd.symbol.isSyntheticFunc && dd.symbol.isExtensionMethod => dd.symbol.extendedSymbol.map { extSym => - val target = ExtensionTarget(extSym.symbol.normalizedName, extSym.tpt.dokkaType.asSignature, extSym.tpt.symbol.dri) + val target = ExtensionTarget( + extSym.symbol.normalizedName, + extSym.tpt.dokkaType.asSignature, + extSym.tpt.symbol.dri, + extSym.symbol.pos.start + ) parseMethod(dd.symbol, kind = Kind.Extension(target)) } // TODO check given methods? diff --git a/scala3doc/src/dotty/dokka/tasty/TastyParser.scala b/scala3doc/src/dotty/dokka/tasty/TastyParser.scala index 4b97ae3d796c..f5fad4985a31 100644 --- a/scala3doc/src/dotty/dokka/tasty/TastyParser.scala +++ b/scala3doc/src/dotty/dokka/tasty/TastyParser.scala @@ -168,7 +168,7 @@ case class TastyParser(qctx: QuoteContext, inspector: DokkaBaseTastyInspector, c private def errorMsg[T](a: Any, m: => String, e: Throwable): Option[T] = val msg = try m catch case e: Throwable => a.toString - println(s"ERROR: tree is faling: msg") + println(s"ERROR: tree is faling: $msg") e.printStackTrace() throw e diff --git a/scala3doc/src/dotty/dokka/transformers/ImplicitMembersExtensionTransformer.scala b/scala3doc/src/dotty/dokka/transformers/ImplicitMembersExtensionTransformer.scala index cac96da63409..794ba463e5ad 100644 --- a/scala3doc/src/dotty/dokka/transformers/ImplicitMembersExtensionTransformer.scala +++ b/scala3doc/src/dotty/dokka/transformers/ImplicitMembersExtensionTransformer.scala @@ -14,18 +14,25 @@ import dotty.dokka.model.api._ class ImplicitMembersExtensionTransformer(ctx: DokkaContext) extends DocumentableTransformer: override def invoke(original: DModule, context: DokkaContext): DModule = val classlikeMap = original.driMap + val logger = context.getLogger - def expandMember(outerMembers: Seq[Member])(c: Member): Member = - val companion = c match - case classlike: DClass => ClasslikeExtension.getFrom(classlike).flatMap(_.companion).flatMap(classlikeMap.get) + def retrieveCompanion(m: Member) = m match { + case classlike: DClass => + val comp = ClasslikeExtension.getFrom(classlike).flatMap(_.companion) + comp.flatMap { dri => + val res = classlikeMap.get(dri) + if res.isEmpty then logger.warn(s"Companion for class ${classlike.name} exists but is missing in classlike map") + res + } case _ => None + } + + def expandMember(outerMembers: Seq[Member])(c: Member): Member = + val companion = retrieveCompanion(c) val allParents = c.parents.flatMap(p => classlikeMap.get(p.dri)) - val parentCompanions = allParents.flatMap { - case cls: DClasslike => ClasslikeExtension.getFrom(cls).flatMap(_.companion).flatMap(classlikeMap.get) - case _ => None - } + val parentCompanions = allParents.flatMap(retrieveCompanion) // TODO (#220): We can expand this on generic etc val implictSources = outerMembers ++ companion.toSeq ++ parentCompanions @@ -34,7 +41,7 @@ class ImplicitMembersExtensionTransformer(ctx: DokkaContext) extends Documentabl val MyDri = c.getDri def collectApplicableMembers(source: Member): Seq[Member] = source.allMembers.flatMap { - case m @ Member(_, _, _, Kind.Extension(ExtensionTarget(_, _, MyDri)), Origin.DefinedWithin) => + case m @ Member(_, _, _, Kind.Extension(ExtensionTarget(_, _, MyDri, _)), Origin.DefinedWithin) => Seq(m.withOrigin(Origin.ExtensionFrom(source.name, source.dri)).withKind(Kind.Def)) case m @ Member(_, _, _, conversionProvider: ImplicitConversionProvider, Origin.DefinedWithin) => conversionProvider.conversion match diff --git a/scala3doc/src/dotty/dokka/translators/ScalaSignatureProvider.scala b/scala3doc/src/dotty/dokka/translators/ScalaSignatureProvider.scala index a090a823e79e..dafac1e8690b 100644 --- a/scala3doc/src/dotty/dokka/translators/ScalaSignatureProvider.scala +++ b/scala3doc/src/dotty/dokka/translators/ScalaSignatureProvider.scala @@ -31,12 +31,12 @@ class ScalaSignatureProvider(contentConverter: CommentsToContentConverter, logge def driLink(text: String, dri: DRI): SignatureBuilder = ContentNodeBuilder(builder.driLink(text, dri)) } - def signature(d: Documentable, s: Signature) = signatureContent(d){ builder => + def signature(d: Member, s: Signature) = signatureContent(d){ builder => val res = ContentNodeBuilder(builder).signature(s) res.asInstanceOf[ContentNodeBuilder].builder } - override def signature(documentable: Documentable) = + override def signature(documentable: Member) = JList(signatureContent(documentable){ builder => val withAnnotations = ContentNodeBuilder(builder).annotationsBlock(documentable) val res = ScalaSignatureProvider.rawSignature(documentable, withAnnotations) From 02aedfabf4dc92b16b9072f637bc1a7d3b651857 Mon Sep 17 00:00:00 2001 From: Aleksander Boruch-Gruszecki Date: Mon, 23 Nov 2020 11:29:23 +0100 Subject: [PATCH 4/5] Fix indent, ws, style --- .../dotty/dokka/tasty/NameNormalizer.scala | 20 +++++++++---------- .../ImplicitMembersExtensionTransformer.scala | 16 +++++++-------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/scala3doc/src/dotty/dokka/tasty/NameNormalizer.scala b/scala3doc/src/dotty/dokka/tasty/NameNormalizer.scala index 43642e5c0a26..583cc9f32a32 100644 --- a/scala3doc/src/dotty/dokka/tasty/NameNormalizer.scala +++ b/scala3doc/src/dotty/dokka/tasty/NameNormalizer.scala @@ -2,13 +2,13 @@ package dotty.dokka.tasty import dotty.dokka._ -trait NameNormalizer: - self: TastyParser => - import qctx.reflect._ - extension (s: Symbol) def normalizedName: String = { - val withoutGivenPrefix = if s.isGiven then s.name.stripPrefix("given_") else s.name - val withoutExtensionPrefix = if s.isExtensionMethod then withoutGivenPrefix.stripPrefix("extension_") else withoutGivenPrefix - val withoutObjectSuffix = if s.flags.is(Flags.Object) then withoutExtensionPrefix.stripSuffix("$") else withoutExtensionPrefix - val constructorNormalizedName = if s.isClassConstructor then "this" else withoutObjectSuffix - constructorNormalizedName - } +trait NameNormalizer { self: TastyParser => + import qctx.reflect._ + extension (s: Symbol) def normalizedName: String = { + val withoutGivenPrefix = if s.isGiven then s.name.stripPrefix("given_") else s.name + val withoutExtensionPrefix = if s.isExtensionMethod then withoutGivenPrefix.stripPrefix("extension_") else withoutGivenPrefix + val withoutObjectSuffix = if s.flags.is(Flags.Object) then withoutExtensionPrefix.stripSuffix("$") else withoutExtensionPrefix + val constructorNormalizedName = if s.isClassConstructor then "this" else withoutObjectSuffix + constructorNormalizedName + } +} diff --git a/scala3doc/src/dotty/dokka/transformers/ImplicitMembersExtensionTransformer.scala b/scala3doc/src/dotty/dokka/transformers/ImplicitMembersExtensionTransformer.scala index 794ba463e5ad..d54791474999 100644 --- a/scala3doc/src/dotty/dokka/transformers/ImplicitMembersExtensionTransformer.scala +++ b/scala3doc/src/dotty/dokka/transformers/ImplicitMembersExtensionTransformer.scala @@ -17,14 +17,14 @@ class ImplicitMembersExtensionTransformer(ctx: DokkaContext) extends Documentabl val logger = context.getLogger def retrieveCompanion(m: Member) = m match { - case classlike: DClass => - val comp = ClasslikeExtension.getFrom(classlike).flatMap(_.companion) - comp.flatMap { dri => - val res = classlikeMap.get(dri) - if res.isEmpty then logger.warn(s"Companion for class ${classlike.name} exists but is missing in classlike map") - res - } - case _ => None + case classlike: DClass => + val comp = ClasslikeExtension.getFrom(classlike).flatMap(_.companion) + comp.flatMap { dri => + val res = classlikeMap.get(dri) + if res.isEmpty then logger.warn(s"Companion for class ${classlike.name} exists but is missing in classlike map") + res + } + case _ => None } def expandMember(outerMembers: Seq[Member])(c: Member): Member = From 01dcb5952a20cad3b7c1eceab49f39cb74a50f00 Mon Sep 17 00:00:00 2001 From: Aleksander Boruch-Gruszecki Date: Mon, 23 Nov 2020 11:38:00 +0100 Subject: [PATCH 5/5] Scala3doc: remove outdated extension name handling --- scala3doc/src/dotty/dokka/tasty/NameNormalizer.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scala3doc/src/dotty/dokka/tasty/NameNormalizer.scala b/scala3doc/src/dotty/dokka/tasty/NameNormalizer.scala index 583cc9f32a32..a5ffdf900910 100644 --- a/scala3doc/src/dotty/dokka/tasty/NameNormalizer.scala +++ b/scala3doc/src/dotty/dokka/tasty/NameNormalizer.scala @@ -6,8 +6,7 @@ trait NameNormalizer { self: TastyParser => import qctx.reflect._ extension (s: Symbol) def normalizedName: String = { val withoutGivenPrefix = if s.isGiven then s.name.stripPrefix("given_") else s.name - val withoutExtensionPrefix = if s.isExtensionMethod then withoutGivenPrefix.stripPrefix("extension_") else withoutGivenPrefix - val withoutObjectSuffix = if s.flags.is(Flags.Object) then withoutExtensionPrefix.stripSuffix("$") else withoutExtensionPrefix + val withoutObjectSuffix = if s.flags.is(Flags.Object) then withoutGivenPrefix.stripSuffix("$") else withoutGivenPrefix val constructorNormalizedName = if s.isClassConstructor then "this" else withoutObjectSuffix constructorNormalizedName }