/* BSD 2-Clause License - see OPAL/LICENSE for details. */ package org.opalj package ai package util import scala.language.reflectiveCalls import scala.xml.Node import scala.xml.NodeSeq import org.opalj.io.process import org.opalj.br._ import org.opalj.collection.mutable.IntArrayStack /** * Several utility methods to facilitate the development of the abstract interpreter/ * new domains for the abstract interpreter, by creating various kinds of dumps of * the state of the interpreter. * * ==Thread Safety== * This object is thread-safe. * * @author Michael Eichberg */ object XHTML { def styles: String = process(this.getClass.getResourceAsStream("default.css"))( scala.io.Source.fromInputStream(_).mkString ) def jquery: String = process(this.getClass.getResourceAsStream("jquery-3.6.1.min.js"))( scala.io.Source.fromInputStream(_).mkString ) def colResizable: String = process(this.getClass.getResourceAsStream("colResizable-1.6.min.js"))( scala.io.Source.fromInputStream(_).mkString ) def createXHTML( htmlTitle: Option[String] = None, body: NodeSeq ): Node = { val theTitle = htmlTitle.map(t => Seq({ t })).getOrElse(Seq.empty[Node]) // HTML 5 XML serialization (XHTML 5) { theTitle } { body } } def caption(classFile: Option[ClassFile], method: Option[Method]): String = { val typeName = classFile.map(_.thisType.toJava).getOrElse("") val methodName = method.map(m => m.signatureToJava(false)).getOrElse("< method >") s"$typeName{ $methodName }" } def htmlify(s: String): Node = { scala.xml.Unparsed( s.replace("<", "<").replace(">", ">").replace("\n", "
"). replace("\t", "  ") ) } def valueToString(value: AnyRef)(implicit ids: Option[AnyRef => Int]): String = { if (value != null) value.toString + ids.map("@"+_.apply(value)).getOrElse("") else "null@" } def throwableToXHTML(throwable: Throwable): scala.xml.Node = { val node = if (throwable.getStackTrace == null || throwable.getStackTrace.size == 0) {
{ throwable.getClass.getSimpleName+" "+throwable.getMessage }
} else { val stackElements = for { stackElement <- throwable.getStackTrace } yield { { stackElement.getClassName } { stackElement.getMethodName } { stackElement.getLineNumber } } val summary = throwable.getClass.getSimpleName+" "+throwable.getMessage
{ summary } { stackElements }
} if (throwable.getCause ne null) { val causedBy = throwableToXHTML(throwable.getCause)
{ node }

caused by:

{ causedBy }
} else { node } } def instructionsToXHTML( title: String, instructions: { def mkString(sep: String): String } ): Node = {

{ title }: { instructions.mkString(", ") }

} def evaluatedInstructionsToXHTML(evaluatedPCs: IntArrayStack) = { val header = "Evaluated instructions: "+evaluatedPCs.count(_ >= 0)+"
" val footer = "" val subroutineStart = "
Subroutine
" val subroutineEnd = "
" var openSubroutines = 0 val asStrings = evaluatedPCs.reverse.map { case SUBROUTINE_START => openSubroutines += 1 subroutineStart case SUBROUTINE_END => openSubroutines -= 1 subroutineEnd case instruction => instruction.toString+" " } header+"Evaluation Order:
"+ asStrings.mkString("") + ( if (openSubroutines > 0) { var missingSubroutineEnds = subroutineEnd openSubroutines -= 1 while (openSubroutines > 0) { missingSubroutineEnds += subroutineEnd openSubroutines -= 1 } missingSubroutineEnds } else "" ) + footer+"
" } }