Skip to content

Commit

Permalink
Centralise validate exception logging in TypeDeclaration
Browse files Browse the repository at this point in the history
  • Loading branch information
nawforce committed Dec 10, 2024
1 parent fdaaef3 commit 25d198e
Show file tree
Hide file tree
Showing 13 changed files with 40 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ trait ModuleRefresh {
val holders = existingLabels.getTypeDependencyHolders
newLabels.setTypeDependencyHolders(holders)
replaceType(newLabels.typeName, Some(newLabels))
newLabels.validate()
newLabels.safeValidate()
Seq((newLabels.typeId, holders.toSet))
}

Expand Down Expand Up @@ -84,7 +84,7 @@ trait ModuleRefresh {

// Update and validate
replaceType(newType.typeName, Some(newType))
newType.validate()
newType.safeValidate()
(typeId, holders.toSet)
})
} else {
Expand Down Expand Up @@ -153,7 +153,7 @@ trait ModuleRefresh {
// Hack: we don't need to revalidate here but MetadataValidator wipes out all
// diagnostics so if we don't validate we can save to cache without important diagnostics,
// especially the Missing ones which will break invalidation handling.
getDependentType(doc.controllingTypeName(namespace)).foreach(_.validate())
getDependentType(doc.controllingTypeName(namespace)).foreach(_.safeValidate())
None
case _ => Some(createSupportedTypes(doc, source))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ trait PackageAPI extends Package {
td.paths.foreach(path => org.issues.pop(path))
td.preReValidate()
})
collectedTypes.foreach(_.validate())
collectedTypes.foreach(_.safeValidate())
}

/* Collect all classes in a super class hierarchy that have an abstract ancestor */
Expand Down
19 changes: 6 additions & 13 deletions jvm/src/main/scala/com/nawforce/apexlink/org/StreamDeployer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ class StreamDeployer(
consumeSObjects(bufferedIterator)
consumeClasses(bufferedIterator)
consumeTriggers(bufferedIterator)
components.validate()
pages.validate()
components.safeValidate()
pages.safeValidate()
}

// Run plugins over loaded types DependentTypes
Expand Down Expand Up @@ -113,7 +113,7 @@ class StreamDeployer(
})

// Run custom validation to setup dependencies
sobjects.foreach(_.validate())
sobjects.foreach(_.safeValidate())
}

/** Consume Apex class events, this is a bit more involved as we try and load first via cache and
Expand Down Expand Up @@ -162,14 +162,7 @@ class StreamDeployer(
)

// Validate the classes, this must be last due to mutual dependence
decls.foreach { decl =>
try {
decl.validate()
} catch {
case ex: Throwable =>
module.log(decl.paths.head, "Validation failed", ex)
}
}
decls.foreach { _.safeValidate() }
}
}

Expand Down Expand Up @@ -281,7 +274,7 @@ class StreamDeployer(
localAccum.entrySet.forEach(kv => {
types.put(kv.getKey, kv.getValue)
})
localAccum.values().asScala.foreach(_.validate())
localAccum.values().asScala.foreach(_.safeValidate())
}
ArraySeq.from(failedDocuments.asScala.toSeq)
}
Expand All @@ -301,7 +294,7 @@ class StreamDeployer(
.create(module, doc.path, data)
.map(td => {
types.put(td)
td.validate()
td.safeValidate()
})
}
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ abstract class FullDeclaration(
}
}

override def validate(): Unit = {
override protected def validate(): Unit = {
LoggerOps.debugTime(s"Validated ${location.path}") {
// Validate inside a parsing context as LazyBlock may call parser
CST.sourceContext.withValue(Some(source)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ class SummaryDeclaration(
// Nothing to do here
}

override def validate(): Unit = {
override protected def validate(): Unit = {
propagateOuterDependencies(new TypeCache())
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ final case class TriggerDeclaration(
private var depends: Option[SkinnySet[Dependent]] = None
private val objectTypeName = TypeName(objectNameId.name, Nil, Some(TypeNames.Schema))

override def validate(): Unit = {
override protected def validate(): Unit = {
LoggerOps.debugTime(s"Validated ${location.path}") {
val context = new TypeVerifyContext(None, this, None, enablePlugins = true)
val tdOpt = context.getTypeAndAddDependency(objectTypeName, this)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class BasicTypeDeclaration(
override def constructors: ArraySeq[ConstructorDeclaration] =
ConstructorDeclaration.emptyConstructorDeclarations

override def validate(): Unit = {}
override protected def validate(): Unit = {}
}

class InnerBasicTypeDeclaration(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@ import com.nawforce.apexlink.types.synthetic.{
CustomFieldDeclaration,
LocatableCustomFieldDeclaration
}
import com.nawforce.pkgforce.diagnostics.{ERROR_CATEGORY, Issue}
import com.nawforce.pkgforce.modifiers._
import com.nawforce.pkgforce.names.{Name, Names, TypeName}
import com.nawforce.pkgforce.parsers.{CLASS_NATURE, INTERFACE_NATURE, Nature}
import com.nawforce.pkgforce.path.{PathLike, UnsafeLocatable}
import com.nawforce.pkgforce.path.{Location, PathLike, PathLocation, UnsafeLocatable}

import java.io.{PrintWriter, StringWriter}
import scala.collection.immutable.ArraySeq
import scala.collection.mutable

Expand Down Expand Up @@ -425,7 +427,22 @@ trait TypeDeclaration extends AbstractTypeDeclaration with Dependent with PreReV
.flatMap(typeName => TypeResolver(typeName, this).toOption)
.getOrElse(this)

def validate(): Unit
def safeValidate(): Unit = {
try {
validate()
} catch {
case ex: Throwable =>
val writer = new StringWriter
writer.append("Validation failed")
writer.append(": ")
ex.printStackTrace(new PrintWriter(writer))
OrgInfo.log(
Issue(ERROR_CATEGORY, PathLocation(paths.head, Location.empty), writer.toString)
)
}
}

protected def validate(): Unit

override def findNestedType(name: Name): Option[TypeDeclaration] = {
nestedTypes.find(_.name == name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ final case class Component(
override def dependencies(): Iterable[Dependent] =
depends.getOrElse(Array[Dependent]())

override def validate(): Unit = {
override protected def validate(): Unit = {
super.validate()
vfContainer.foreach(vf => {
depends = Some(vf.validate())
Expand Down Expand Up @@ -122,8 +122,8 @@ final case class ComponentDeclaration(
// Propagate dependencies to nested
nestedComponents.foreach(_.addTypeDependencyHolder(typeId))

override def validate(): Unit = {
components.foreach(_.validate())
override protected def validate(): Unit = {
components.foreach(_.safeValidate())
propagateOuterDependencies(new TypeCache())
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ final case class PageDeclaration(
new PageDeclaration(sourceInfo, module, newPages)
}

override def validate(): Unit = {
override protected def validate(): Unit = {
// We may create multiple Pages for each .page file to handle namespaces
// We only want to validate one of them to avoid duplicate diagnostics
val uniquePages = pages.map(page => (page.location.path, page)).toMap.values
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ class PlatformTypeDeclaration(val native: Any, val outer: Option[PlatformTypeDec
.map(c => new PlatformConstructor(c, this))
}

override def validate(): Unit = {
override protected def validate(): Unit = {
// Not required
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ final case class GhostSObjectDeclaration(module: OPM.Module, _typeName: TypeName
TypeResolver(superClass.get, this).toOption
}

override def validate(): Unit = {
override protected def validate(): Unit = {
// Not required
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ final case class SObjectDeclaration(
override lazy val superClassDeclaration: Option[TypeDeclaration] =
TypeResolver(superClass.get, this).toOption

override def validate(): Unit = {
override protected def validate(): Unit = {
// Check field types, can be ignored for Feed, Share & History synthetic SObjects
if (isSynthetic) return

Expand Down

0 comments on commit 25d198e

Please sign in to comment.