Skip to content

Commit f8cb1ae

Browse files
committed
Diagram tweaks #1
- relaxed the restrictions on nodes - nodes can be classes, traits and objects, both stand-alone and companion objects -- all are added to the diagram, but usually companion objects are filtered out as they don't have any superclasses - changed the rules for default diagram creation: - classes and traits (and AnyRef) get inheritance diagrams - packages and objects get content diagrams (can be overridden by @contentDiagram [hideDiagram] and @inheritanceDiagram [hideDiagram]) - tweaked the model to register subclasses of Any - hardcoded the scala package diagram to show all relations - enabled @contentDiagram showInheritedNodes by default and changed the setting to hideInheritedNodes (and added a test for this) - better node selection (can select nodes that don't have a corresponding trait) - fixed the docsite link in member selection, which was broken since the first commit :))
1 parent f8057d2 commit f8cb1ae

11 files changed

+223
-84
lines changed

src/compiler/scala/tools/nsc/doc/html/page/Template.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
144144
<li class="hideall out"><span>Hide All</span></li>
145145
<li class="showall in"><span>Show all</span></li>
146146
</ol>
147-
<a href="docs.scala-lang.org/overviews/scaladoc/usage.html#members" target="_blank">Learn more about member selection</a>
147+
<a href="http://docs.scala-lang.org/overviews/scaladoc/usage.html#members" target="_blank">Learn more about member selection</a>
148148
</div>
149149
}
150150
{

src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,6 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
4545
memberSym.isOmittablePrefix || (closestPackage(memberSym) == closestPackage(templateSym))
4646
}
4747

48-
private lazy val noSubclassCache = Set[Symbol](AnyClass, AnyRefClass, ObjectClass)
49-
5048
def makeModel: Option[Universe] = {
5149
val universe = new Universe { thisUniverse =>
5250
thisFactory.universe = thisUniverse
@@ -270,7 +268,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
270268
def parentTypes =
271269
if (sym.isPackage || sym == AnyClass) List() else {
272270
val tps = sym.tpe.parents map { _.asSeenFrom(sym.thisType, sym) }
273-
makeParentTypes(RefinedType(tps, EmptyScope), inTpl)
271+
makeParentTypes(RefinedType(tps, EmptyScope), Some(this), inTpl)
274272
}
275273

276274
protected def linearizationFromSymbol(symbol: Symbol): List[(TemplateEntity, TypeEntity)] = {
@@ -290,7 +288,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
290288

291289
/* Subclass cache */
292290
private lazy val subClassesCache = (
293-
if (noSubclassCache(sym)) null
291+
if (sym == AnyRefClass) null
294292
else mutable.ListBuffer[DocTemplateEntity]()
295293
)
296294
def registerSubClass(sc: DocTemplateEntity): Unit = {
@@ -796,10 +794,15 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
796794
}
797795

798796
/** Get the types of the parents of the current class, ignoring the refinements */
799-
def makeParentTypes(aType: Type, inTpl: => TemplateImpl): List[(TemplateEntity, TypeEntity)] = aType match {
797+
def makeParentTypes(aType: Type, tpl: Option[DocTemplateImpl], inTpl: TemplateImpl): List[(TemplateEntity, TypeEntity)] = aType match {
800798
case RefinedType(parents, defs) =>
801-
val ignoreParents = Set[Symbol](AnyClass, ObjectClass)
802-
val filtParents = parents filterNot (x => ignoreParents(x.typeSymbol))
799+
val ignoreParents = Set[Symbol](AnyRefClass, ObjectClass)
800+
val filtParents =
801+
// we don't want to expose too many links to AnyRef, that will just be redundant information
802+
if (tpl.isDefined && (!tpl.get.isObject && parents.length < 2))
803+
parents
804+
else
805+
parents.filterNot((p: Type) => ignoreParents(p.typeSymbol))
803806
filtParents.map(parent => {
804807
val templateEntity = makeTemplate(parent.typeSymbol)
805808
val typeEntity = makeType(parent, inTpl)

src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ trait ModelFactoryImplicitSupport {
9191
* default Scala imports (Predef._ for example) and the companion object of the current class, if one exists. In the
9292
* future we might want to extend this to more complex scopes.
9393
*/
94-
def makeImplicitConversions(sym: Symbol, inTpl: => DocTemplateImpl): List[ImplicitConversionImpl] =
94+
def makeImplicitConversions(sym: Symbol, inTpl: DocTemplateImpl): List[ImplicitConversionImpl] =
9595
// Nothing and Null are somewhat special -- they can be transformed by any implicit conversion available in scope.
9696
// But we don't want that, so we'll simply refuse to find implicit conversions on for Nothing and Null
9797
if (!(sym.isClass || sym.isTrait || sym == AnyRefClass) || sym == NothingClass || sym == NullClass) Nil
@@ -148,7 +148,7 @@ trait ModelFactoryImplicitSupport {
148148
* - we also need to transform implicit parameters in the view's signature into constraints, such that Numeric[T4]
149149
* appears as a constraint
150150
*/
151-
def makeImplicitConversion(sym: Symbol, result: SearchResult, constrs: List[TypeConstraint], context: Context, inTpl: => DocTemplateImpl): List[ImplicitConversionImpl] =
151+
def makeImplicitConversion(sym: Symbol, result: SearchResult, constrs: List[TypeConstraint], context: Context, inTpl: DocTemplateImpl): List[ImplicitConversionImpl] =
152152
if (result.tree == EmptyTree) Nil
153153
else {
154154
// `result` will contain the type of the view (= implicit conversion method)
@@ -206,7 +206,7 @@ trait ModelFactoryImplicitSupport {
206206
}
207207
}
208208

209-
def makeImplicitConstraints(types: List[Type], sym: Symbol, context: Context, inTpl: => DocTemplateImpl): List[Constraint] =
209+
def makeImplicitConstraints(types: List[Type], sym: Symbol, context: Context, inTpl: DocTemplateImpl): List[Constraint] =
210210
types.flatMap((tpe:Type) => {
211211
// TODO: Before creating constraints, map typeVarToOriginOrWildcard on the implicitTypes
212212
val implType = typeVarToOriginOrWildcard(tpe)
@@ -282,7 +282,7 @@ trait ModelFactoryImplicitSupport {
282282
}
283283
})
284284

285-
def makeSubstitutionConstraints(subst: TreeTypeSubstituter, inTpl: => DocTemplateImpl): List[Constraint] =
285+
def makeSubstitutionConstraints(subst: TreeTypeSubstituter, inTpl: DocTemplateImpl): List[Constraint] =
286286
(subst.from zip subst.to) map {
287287
case (from, to) =>
288288
new EqualTypeParamConstraint {
@@ -292,7 +292,7 @@ trait ModelFactoryImplicitSupport {
292292
}
293293
}
294294

295-
def makeBoundedConstraints(tparams: List[Symbol], constrs: List[TypeConstraint], inTpl: => DocTemplateImpl): List[Constraint] =
295+
def makeBoundedConstraints(tparams: List[Symbol], constrs: List[TypeConstraint], inTpl: DocTemplateImpl): List[Constraint] =
296296
(tparams zip constrs) flatMap {
297297
case (tparam, constr) => {
298298
uniteConstraints(constr) match {
@@ -341,7 +341,7 @@ trait ModelFactoryImplicitSupport {
341341
val convSym: Symbol,
342342
val toType: Type,
343343
val constrs: List[Constraint],
344-
inTpl: => DocTemplateImpl)
344+
inTpl: DocTemplateImpl)
345345
extends ImplicitConversion {
346346

347347
def source: DocTemplateEntity = inTpl
@@ -365,7 +365,7 @@ trait ModelFactoryImplicitSupport {
365365
case _ => error("Scaladoc implicits: Could not create template for: " + toType + " of type " + toType.getClass); None
366366
}
367367

368-
def targetTypeComponents: List[(TemplateEntity, TypeEntity)] = makeParentTypes(toType, inTpl)
368+
def targetTypeComponents: List[(TemplateEntity, TypeEntity)] = makeParentTypes(toType, None, inTpl)
369369

370370
def convertorMethod: Either[MemberEntity, String] = {
371371
var convertor: MemberEntity = null

src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
3030

3131
protected val commentCache = mutable.HashMap.empty[(global.Symbol, TemplateImpl), Comment]
3232

33-
def addCommentBody(sym: global.Symbol, inTpl: => TemplateImpl, docStr: String, docPos: global.Position): global.Symbol = {
33+
def addCommentBody(sym: global.Symbol, inTpl: TemplateImpl, docStr: String, docPos: global.Position): global.Symbol = {
3434
commentCache += (sym, inTpl) -> parse(docStr, docStr, docPos)
3535
sym
3636
}
3737

38-
def comment(sym: global.Symbol, inTpl: => DocTemplateImpl): Option[Comment] = {
38+
def comment(sym: global.Symbol, inTpl: DocTemplateImpl): Option[Comment] = {
3939
val key = (sym, inTpl)
4040
if (commentCache isDefinedAt key)
4141
Some(commentCache(key))
@@ -50,7 +50,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
5050
* cases we have to give some `inTpl` comments (parent class for example)
5151
* to the comment of the symbol.
5252
* This function manages some of those cases : Param accessor and Primary constructor */
53-
def defineComment(sym: global.Symbol, inTpl: => DocTemplateImpl):Option[Comment] = {
53+
def defineComment(sym: global.Symbol, inTpl: DocTemplateImpl):Option[Comment] = {
5454

5555
//param accessor case
5656
// We just need the @param argument, we put it into the body

src/compiler/scala/tools/nsc/doc/model/diagram/Diagram.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ case class NormalNode(tpe: TypeEntity, tpl: Option[TemplateEntity]) extends Node
109109
case class ImplicitNode(tpe: TypeEntity, tpl: Option[TemplateEntity]) extends Node { override def isImplicitNode = true }
110110

111111
/** An outside node is shown in packages when a class from a different package makes it to the package diagram due to
112-
* its relation to a class in the package (and @contentDiagram showInheritedNodes annotation) */
112+
* its relation to a class in the template (see @contentDiagram hideInheritedNodes annotation) */
113113
case class OutsideNode(tpe: TypeEntity, tpl: Option[TemplateEntity]) extends Node { override def isOutsideNode = true }
114114

115115

src/compiler/scala/tools/nsc/doc/model/diagram/DiagramDirectiveParser.scala

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import html.page.diagram.DiagramStats
1919
trait DiagramDirectiveParser {
2020
this: ModelFactory with DiagramFactory with CommentFactory with TreeFactory =>
2121

22+
import this.global.definitions.AnyRefClass
23+
2224
///// DIAGRAM FILTERS //////////////////////////////////////////////////////////////////////////////////////////////
2325

2426
/**
@@ -48,16 +50,22 @@ trait DiagramDirectiveParser {
4850
/** Hide subclasses (for type hierarchy diagrams) */
4951
def hideSubclasses: Boolean
5052
/** Show related classes from other objects/traits/packages (for content diagrams) */
51-
def showInheritedNodes: Boolean
53+
def hideInheritedNodes: Boolean
5254
/** Hide a node from the diagram */
53-
def hideNode(clazz: TemplateEntity): Boolean
55+
def hideNode(clazz: Node): Boolean
5456
/** Hide an edge from the diagram */
55-
def hideEdge(clazz1: TemplateEntity, clazz2: TemplateEntity): Boolean
57+
def hideEdge(clazz1: Node, clazz2: Node): Boolean
5658
}
5759

5860
/** Main entry point into this trait: generate the filter for inheritance diagrams */
5961
def makeInheritanceDiagramFilter(template: DocTemplateImpl): DiagramFilter = {
60-
val defaultFilter = if (template.isClass || template.isTrait) FullDiagram else NoDiagramAtAll
62+
63+
val defaultFilter =
64+
if (template.isClass || template.isTrait || template.sym == AnyRefClass)
65+
FullDiagram
66+
else
67+
NoDiagramAtAll
68+
6169
if (template.comment.isDefined)
6270
makeDiagramFilter(template, template.comment.get.inheritDiagram, defaultFilter, true)
6371
else
@@ -83,9 +91,9 @@ trait DiagramDirectiveParser {
8391
val hideOutgoingImplicits: Boolean = false
8492
val hideSuperclasses: Boolean = false
8593
val hideSubclasses: Boolean = false
86-
val showInheritedNodes: Boolean = false
87-
def hideNode(clazz: TemplateEntity): Boolean = false
88-
def hideEdge(clazz1: TemplateEntity, clazz2: TemplateEntity): Boolean = false
94+
val hideInheritedNodes: Boolean = false
95+
def hideNode(clazz: Node): Boolean = false
96+
def hideEdge(clazz1: Node, clazz2: Node): Boolean = false
8997
}
9098

9199
/** Hide the diagram completely, no need for special filtering */
@@ -95,9 +103,9 @@ trait DiagramDirectiveParser {
95103
val hideOutgoingImplicits: Boolean = true
96104
val hideSuperclasses: Boolean = true
97105
val hideSubclasses: Boolean = true
98-
val showInheritedNodes: Boolean = false
99-
def hideNode(clazz: TemplateEntity): Boolean = true
100-
def hideEdge(clazz1: TemplateEntity, clazz2: TemplateEntity): Boolean = true
106+
val hideInheritedNodes: Boolean = true
107+
def hideNode(clazz: Node): Boolean = true
108+
def hideEdge(clazz1: Node, clazz2: Node): Boolean = true
101109
}
102110

103111
/** The AnnotationDiagramFilter trait directs the diagram engine according to an annotation
@@ -107,12 +115,18 @@ trait DiagramDirectiveParser {
107115
hideOutgoingImplicits: Boolean,
108116
hideSuperclasses: Boolean,
109117
hideSubclasses: Boolean,
110-
showInheritedNodes: Boolean,
118+
hideInheritedNodes: Boolean,
111119
hideNodesFilter: List[Pattern],
112120
hideEdgesFilter: List[(Pattern, Pattern)]) extends DiagramFilter {
113121

114-
def hideNode(clazz: TemplateEntity): Boolean = {
115-
val qualifiedName = clazz.qualifiedName
122+
private[this] def getName(n: Node): String =
123+
if (n.tpl.isDefined)
124+
n.tpl.get.qualifiedName
125+
else
126+
n.name
127+
128+
def hideNode(clazz: Node): Boolean = {
129+
val qualifiedName = getName(clazz)
116130
for (hideFilter <- hideNodesFilter)
117131
if (hideFilter.matcher(qualifiedName).matches) {
118132
// println(hideFilter + ".matcher(" + qualifiedName + ").matches = " + hideFilter.matcher(qualifiedName).matches)
@@ -121,9 +135,9 @@ trait DiagramDirectiveParser {
121135
false
122136
}
123137

124-
def hideEdge(clazz1: TemplateEntity, clazz2: TemplateEntity): Boolean = {
125-
val clazz1Name = clazz1.qualifiedName
126-
val clazz2Name = clazz2.qualifiedName
138+
def hideEdge(clazz1: Node, clazz2: Node): Boolean = {
139+
val clazz1Name = getName(clazz1)
140+
val clazz2Name = getName(clazz2)
127141
for ((clazz1Filter, clazz2Filter) <- hideEdgesFilter) {
128142
if (clazz1Filter.matcher(clazz1Name).matches &&
129143
clazz2Filter.matcher(clazz2Name).matches) {
@@ -162,7 +176,7 @@ trait DiagramDirectiveParser {
162176
var hideOutgoingImplicits0: Boolean = false
163177
var hideSuperclasses0: Boolean = false
164178
var hideSubclasses0: Boolean = false
165-
var showInheritedNodes0: Boolean = false
179+
var hideInheritedNodes0: Boolean = false
166180
var hideNodesFilter0: List[Pattern] = Nil
167181
var hideEdgesFilter0: List[(Pattern, Pattern)] = Nil
168182

@@ -190,8 +204,8 @@ trait DiagramDirectiveParser {
190204
hideSuperclasses0 = true
191205
case "hideSubclasses" if isInheritanceDiagram =>
192206
hideSubclasses0 = true
193-
case "showInheritedNodes" if !isInheritanceDiagram =>
194-
showInheritedNodes0 = true
207+
case "hideInheritedNodes" if !isInheritanceDiagram =>
208+
hideInheritedNodes0 = true
195209
case HideNodesRegex(last) =>
196210
val matcher = NodeSpecPattern.matcher(entry)
197211
while (matcher.find()) {
@@ -225,7 +239,7 @@ trait DiagramDirectiveParser {
225239
(hideOutgoingImplicits0 == false) &&
226240
(hideSuperclasses0 == false) &&
227241
(hideSubclasses0 == false) &&
228-
(showInheritedNodes0 == false) &&
242+
(hideInheritedNodes0 == false) &&
229243
(hideDiagram0 == false))
230244
FullDiagram
231245
else
@@ -235,7 +249,7 @@ trait DiagramDirectiveParser {
235249
hideOutgoingImplicits = hideOutgoingImplicits0,
236250
hideSuperclasses = hideSuperclasses0,
237251
hideSubclasses = hideSubclasses0,
238-
showInheritedNodes = showInheritedNodes0,
252+
hideInheritedNodes = hideInheritedNodes0,
239253
hideNodesFilter = hideNodesFilter0,
240254
hideEdgesFilter = hideEdgesFilter0)
241255

0 commit comments

Comments
 (0)