From f7c3ce29262a99274ba7a106ad664cba313a43ec Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 18 Jan 2018 14:05:40 +1000 Subject: [PATCH] Add -p option to suppress private members --- .../scala/tools/jardiff/AsmTextifyRenderer.scala | 16 +++++++++++++--- .../main/scala/scala/tools/jardiff/JarDiff.scala | 4 ++-- .../main/scala/scala/tools/jardiff/Main.scala | 5 +++-- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/core/src/main/scala/scala/tools/jardiff/AsmTextifyRenderer.scala b/core/src/main/scala/scala/tools/jardiff/AsmTextifyRenderer.scala index a9b8a31..0787626 100644 --- a/core/src/main/scala/scala/tools/jardiff/AsmTextifyRenderer.scala +++ b/core/src/main/scala/scala/tools/jardiff/AsmTextifyRenderer.scala @@ -8,11 +8,11 @@ import java.io.PrintWriter import java.nio.file.{Files, Path} import scala.collection.JavaConverters._ -import scala.tools.asm.ClassReader -import scala.tools.asm.tree.ClassNode +import scala.tools.asm.{ClassReader, Opcodes} +import scala.tools.asm.tree.{ClassNode, FieldNode, InnerClassNode, MethodNode} import scala.tools.asm.util.TraceClassVisitor -class AsmTextifyRenderer(code: Boolean, raw: Boolean) extends FileRenderer { +class AsmTextifyRenderer(code: Boolean, raw: Boolean, privates: Boolean) extends FileRenderer { def outFileExtension: String = ".asm" override def render(in: Path, out: Path): Unit = { val classBytes = Files.readAllBytes(in) @@ -20,6 +20,11 @@ class AsmTextifyRenderer(code: Boolean, raw: Boolean) extends FileRenderer { val node = if (raw) rawNode else zapScalaClassAttrs(sortClassMembers(rawNode)) if (!code) node.methods.forEach(_.instructions.clear()) + if (!privates) { + node.methods.removeIf((m: MethodNode) => isPrivate(m.access)) + node.fields.removeIf((m: FieldNode) => isPrivate(m.access)) + node.innerClasses.removeIf((m: InnerClassNode) => isPrivate(m.access)) + } Files.createDirectories(out.getParent) val pw = new PrintWriter(Files.newBufferedWriter(out)) try { @@ -30,6 +35,11 @@ class AsmTextifyRenderer(code: Boolean, raw: Boolean) extends FileRenderer { } } + private def isPrivate(access: Int): Boolean = { + (access & Opcodes.ACC_PRIVATE) != 0 + + } + def sortClassMembers(node: ClassNode): node.type = { node.fields.sort(_.name compareTo _.name) node.methods.sort(_.name compareTo _.name) diff --git a/core/src/main/scala/scala/tools/jardiff/JarDiff.scala b/core/src/main/scala/scala/tools/jardiff/JarDiff.scala index f411f5f..63e0dab 100644 --- a/core/src/main/scala/scala/tools/jardiff/JarDiff.scala +++ b/core/src/main/scala/scala/tools/jardiff/JarDiff.scala @@ -108,10 +108,10 @@ object JarDiff { else List(path) } def apply(files: List[List[Path]], config: JarDiff.Config): JarDiff = { - val renderers = Map("class" -> List(new AsmTextifyRenderer(config.code, config.raw), new ScalapRenderer())).withDefault(_ => List(IdentityRenderer)) + val renderers = Map("class" -> List(new AsmTextifyRenderer(config.code, config.raw, config.privates), new ScalapRenderer())).withDefault(_ => List(IdentityRenderer)) new JarDiff(files, config, renderers) } - case class Config(gitRepo: Option[Path], code: Boolean, raw: Boolean, contextLines: Option[Int], diffOutputStream: OutputStream) + case class Config(gitRepo: Option[Path], code: Boolean, raw: Boolean, privates: Boolean, contextLines: Option[Int], diffOutputStream: OutputStream) } diff --git a/core/src/main/scala/scala/tools/jardiff/Main.scala b/core/src/main/scala/scala/tools/jardiff/Main.scala index 74c31c7..f7da210 100644 --- a/core/src/main/scala/scala/tools/jardiff/Main.scala +++ b/core/src/main/scala/scala/tools/jardiff/Main.scala @@ -30,11 +30,12 @@ object Main { Git.setArgName("dir") val NoCode = new cli.Option("c", "suppress-code", false, "Suppress method bodies") val Raw = new cli.Option("r", "raw", false, "Disable sorting and filtering of classfile contents") + val NoPrivates = new cli.Option("p", "suppress-privates", false, "Display only non-private members") val ContextLines = new cli.Option("U", "unified", true, "Number of context lines in diff") val Quiet = new cli.Option("q", "quiet", false, "Don't output diffs to standard out") ContextLines.setArgName("n") def apply(): Options = { - new cli.Options().addOption(Help).addOption(Git).addOption(ContextLines).addOption(NoCode).addOption(Raw).addOption(Quiet) + new cli.Options().addOption(Help).addOption(Git).addOption(ContextLines).addOption(NoCode).addOption(Raw).addOption(NoPrivates).addOption(Quiet) } } private implicit class RichCommandLine(val self: CommandLine) { @@ -69,7 +70,7 @@ object Main { } else { val gitRepo = if (line.has(Opts.Git)) Some(Paths.get(line.get(Opts.Git))) else None val diffOutputStream = if (line.has(Opts.Quiet)) NullOutputStream.INSTANCE else System.out - val config = JarDiff.Config(gitRepo, !line.has(Opts.NoCode), line.has(Opts.Raw), line.getOptInt(Opts.ContextLines), diffOutputStream) + val config = JarDiff.Config(gitRepo, !line.has(Opts.NoCode), line.has(Opts.Raw), !line.has(Opts.NoPrivates), line.getOptInt(Opts.ContextLines), diffOutputStream) val paths = trailingArgs.asScala.toList.map(JarDiff.expandClassPath) paths match { case Nil => ShowUsage(helpText)