Skip to content
This repository has been archived by the owner on Feb 12, 2023. It is now read-only.

Refactor DownWalker to include none-Apex DependencyHolders #98

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 53 additions & 41 deletions apexlink/src/main/scala/com/nawforce/apexlink/deps/DownWalker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import com.nawforce.apexlink.api.Org
import com.nawforce.apexlink.org.OrgImpl
import com.nawforce.apexlink.types.apex.{ApexClassDeclaration, ApexDeclaration}
import com.nawforce.apexlink.types.core.DependencyHolder
import com.nawforce.pkgforce.names.{Name, TypeIdentifier}
import com.nawforce.pkgforce.names.TypeIdentifier
import com.nawforce.pkgforce.parsers.{CLASS_NATURE, INTERFACE_NATURE}

import scala.collection.mutable
Expand All @@ -37,9 +37,6 @@ case class NodeData(
/** Downstream dependency walker. Collects information on the dependencies of a type. */
class DownWalker(org: Org, apexOnly: Boolean) {

private val packagesByNamespace =
org.getPackages().map(pkg => (Name(pkg.getNamespaces(false).head), pkg)).toMap

private val transitiveCollector = new TransitiveCollector(org, apexOnly)

/* Collect information on dependencies of the passed identifiers. The walk depth can be limited but the result will
Expand Down Expand Up @@ -97,44 +94,59 @@ class DownWalker(org: Org, apexOnly: Boolean) {
private def createNode(id: TypeIdentifier, ignoring: Array[TypeIdentifier]): Option[NodeData] = {
org
.asInstanceOf[OrgImpl]
.findTypeIdentifier(id)
.filter(td => !apexOnly || td.isInstanceOf[ApexDeclaration])
.collect { case td: DependencyHolder => td }
.map(td => {
val pkg = td.moduleDeclaration.map(_.pkg)
val typeId = pkg.map(pkg => TypeIdentifier(pkg.namespace, td.typeName))
.findTypeIdentifier(id) match {
case Some(td: ApexDeclaration) => Some(createApexNode(td, ignoring))
case Some(td: DependencyHolder) if !apexOnly =>
// Treat non-apex as a pseudo-leaf by not collecting further
Some(
NodeData(
id,
td.nature.value,
transitiveCollector.count(id, ignoring),
Array.empty,
Array.empty,
Array.empty
)
)
case _ => None
}
}

val inherits =
td.dependencies()
.flatMap({
case dt: ApexClassDeclaration => Some(dt.nature, dt.outerTypeId.asTypeIdentifier)
case _ => None
})
.filterNot(d => typeId.contains(d._2))
.filterNot(d => ignoring.contains(d._2))
.toSet
val extending = inherits.filter(id => id._1 == CLASS_NATURE).map(_._2)
val implementing = inherits.filter(id => id._1 == INTERFACE_NATURE).map(_._2)
val output = extending ++ implementing
private def createApexNode(td: ApexDeclaration, ignoring: Array[TypeIdentifier]): NodeData = {
val pkg = td.moduleDeclaration.map(_.pkg)
val id = td.typeId.asTypeIdentifier

val all =
pkg
.flatMap(pkg => {
Option(pkg.getDependencies(id, outerInheritanceOnly = false, apexOnly))
})
.getOrElse(Array[TypeIdentifier]())
val uses = all
.filterNot(output.contains)
.filterNot(id => typeId.contains(id))
.filterNot(id => ignoring.contains(id))
NodeData(
id,
td.nature.value,
transitiveCollector.count(id, ignoring),
extending.toArray,
implementing.toArray,
uses
)
})
val inherits = {
td.dependencies()
.flatMap({
case dt: ApexClassDeclaration => Some(dt.nature, dt.outerTypeId.asTypeIdentifier)
case _ => None
})
.filterNot(d => id == d._2)
.filterNot(d => ignoring.contains(d._2))
.toSet
}
val extending = inherits.filter(id => id._1 == CLASS_NATURE).map(_._2)
val implementing = inherits.filter(id => id._1 == INTERFACE_NATURE).map(_._2)
val output = extending ++ implementing

val all =
pkg
.flatMap(pkg => {
Option(pkg.getDependencies(id, outerInheritanceOnly = false, apexOnly))
})
.getOrElse(Array[TypeIdentifier]())
val uses = all
.filterNot(output.contains)
.filterNot(_ == id)
.filterNot(ignoring.contains)
NodeData(
id,
td.nature.value,
transitiveCollector.count(id, ignoring),
extending.toArray,
implementing.toArray,
uses
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,13 @@ trait ApexFieldLike extends FieldDeclaration with IdLocatable {
}

/** Apex defined types core features, be they full or summary style */
trait ApexDeclaration extends DependentType with IdLocatable {
trait ApexDeclaration extends DependentType with DependencyHolder with IdLocatable {
val sourceHash: Int
val module: Module

/** Override to resolve conflict, TypeDeclaration & DependencyHolder both default false */
override val inTest: Boolean = false

def summary: TypeSummary
}

Expand All @@ -133,15 +136,12 @@ trait ApexFullDeclaration extends ApexDeclaration {
trait ApexTriggerDeclaration extends ApexDeclaration

/** Apex defined classes, interfaces, enum of either full or summary type */
trait ApexClassDeclaration extends ApexDeclaration with DependencyHolder {
trait ApexClassDeclaration extends ApexDeclaration {
val localFields: ArraySeq[ApexFieldLike]
val localMethods: ArraySeq[ApexMethodLike]

override def nestedTypes: ArraySeq[ApexClassDeclaration]

/** Override to resolve conflict, TypeDeclaration & DependencyHolder both default false */
override val inTest: Boolean = false

/** Override to handle request to flush the type to passed cache if dirty */
def flush(pc: ParsedCache, context: PackageContext): Unit

Expand Down