From 31e3f39c55d3377bcc81481ef077a94b164b207b Mon Sep 17 00:00:00 2001 From: Hubert Plociniczak Date: Wed, 1 Jun 2022 15:50:46 +0200 Subject: [PATCH] Suppress pointless warnings coming from SBT (#3499) This change introduces a custom LogManager for console that allows for excluding certain log messages. The primarily reason for introducing such LogManager/Appender is to stop issuing hundreds of pointless warnings coming from the analyzing compiler (wrapper around javac) for classes that are being generated by annotation processors. The output looks like this: ``` [info] Cannot install GraalVM MBean due to Failed to load org.graalvm.nativebridge.jni.JNIExceptionWrapperEntryPoints [info] compiling 129 Scala sources and 395 Java sources to /home/hubert/work/repos/enso/enso/engine/runtime/target/scala-2.13/classes ... [warn] Unexpected javac output: warning: File for type 'org.enso.interpreter.runtime.type.ConstantsGen' created in the last round will not be subject to annotation processing. [warn] 1 warning. [info] [Use -Dgraal.LogFile= to redirect Graal log output to a file.] [info] Cannot install GraalVM MBean due to Failed to load org.graalvm.nativebridge.jni.JNIExceptionWrapperEntryPoints [info] foojavac Filer [warn] Could not determine source for class org.enso.interpreter.node.expression.builtin.number.decimal.CeilMethodGen [warn] Could not determine source for class org.enso.interpreter.node.expression.builtin.resource.TakeNodeGen [warn] Could not determine source for class org.enso.interpreter.node.expression.builtin.error.ThrowErrorMethodGen [warn] Could not determine source for class org.enso.interpreter.node.expression.builtin.number.smallInteger.MultiplyMethodGen [warn] Could not determine source for class org.enso.interpreter.node.expression.builtin.warning.GetWarningsNodeGen [warn] Could not determine source for class org.enso.interpreter.node.expression.builtin.number.smallInteger.BitAndMethodGen [warn] Could not determine source for class org.enso.interpreter.node.expression.builtin.error.ErrorToTextNodeGen [warn] Could not determine source for class org.enso.interpreter.node.expression.builtin.warning.GetValueMethodGen [warn] Could not determine source for class org.enso.interpreter.runtime.callable.atom.AtomGen$MethodDispatchLibraryExports$Cached .... ``` The output now has over 500 of those and there will be more. Much more (generated by our and Truffle processors). There is no way to tell SBT that those are OK. One could potentially think of splitting compilation into 3 stages (Java processors, Java and Scala) but that will already complicate the non-trivial build definition and we may still end up with the initial problem. This is a fix to make it possible to get reasonable feedback from compilation without scrolling mutliple screens *every single time*. Also fixed a spurious warning in javac processor complaining about creating files in the last round. Related to https://www.pivotaltracker.com/story/show/182138198 --- build.sbt | 10 +++--- .../enso/interpreter/dsl/TypeProcessor.java | 17 ++++++++-- project/CustomLogManager.scala | 33 +++++++++++++++++++ 3 files changed, 52 insertions(+), 8 deletions(-) create mode 100644 project/CustomLogManager.scala diff --git a/build.sbt b/build.sbt index e6594e03e22..b42f122a314 100644 --- a/build.sbt +++ b/build.sbt @@ -5,11 +5,8 @@ import sbt.Keys.{libraryDependencies, scalacOptions} import sbt.addCompilerPlugin import sbt.complete.DefaultParsers._ import sbt.complete.Parser -import sbtcrossproject.CrossPlugin.autoImport.{crossProject, CrossType} -import src.main.scala.licenses.{ - DistributionDescription, - SBTDistributionComponent -} +import sbtcrossproject.CrossPlugin.autoImport.{CrossType, crossProject} +import src.main.scala.licenses.{DistributionDescription, SBTDistributionComponent} import java.io.File @@ -151,6 +148,7 @@ val packageBuilder = new DistributionPackage.Builder( ) Global / onChangedBuildSource := ReloadOnSourceChanges +Global / excludeLintKeys += logManager // ============================================================================ // === Compiler Options ======================================================= @@ -1186,6 +1184,8 @@ lazy val runtime = (project in file("engine/runtime")) .configs(Benchmark) .settings( frgaalJavaCompilerSetting, + Compile/logManager := + sbt.internal.util.CustomLogManager.excludeMsg("Could not determine source for class ", Level.Warn), version := ensoVersion, commands += WithDebugCommand.withDebug, cleanInstruments := FixInstrumentsGeneration.cleanInstruments.value, diff --git a/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/TypeProcessor.java b/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/TypeProcessor.java index 2aaef110cda..23581daa270 100644 --- a/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/TypeProcessor.java +++ b/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/TypeProcessor.java @@ -4,6 +4,7 @@ import javax.annotation.processing.*; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; +import javax.tools.Diagnostic; import javax.tools.JavaFileObject; import java.io.IOException; import java.io.PrintWriter; @@ -18,6 +19,7 @@ import org.openide.util.lookup.ServiceProvider; public class TypeProcessor extends BuiltinsMetadataProcessor { private final Map> builtinTypes = new HashMap<>(); + private JavaFileObject jfo = null; private class BuiltinTypeConstr { private String tpeName; @@ -50,6 +52,17 @@ public class TypeProcessor extends BuiltinsMetadataProcessor annotations, RoundEnvironment roundEnv) { + if (jfo == null) { + // Create generator for Java source file once(!) so that it can be used at the last + // round of processing. Otherwise, javac complains that the generated file won't be + // used in further processing. That's fine, we know it won't. + try { + jfo = processingEnv.getFiler().createSourceFile(ConstantsGenFullClassname); + } catch (IOException e) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage()); + return false; + } + } for (TypeElement annotation : annotations) { Set annotatedElements = roundEnv.getElementsAnnotatedWith(annotation); for (Element elt : annotatedElements) { @@ -85,9 +98,7 @@ public class TypeProcessor extends BuiltinsMetadataProcessor pastEntries) throws IOException { - JavaFileObject gen = processingEnv.getFiler().createSourceFile(ConstantsGenFullClassname); for (Filer f : builtinTypes.keySet()) { - System.out.println("foo" + f.toString()); for (Map.Entry entry : builtinTypes.get(f).entrySet()) { BuiltinTypeConstr constr = entry.getValue(); writer.append( @@ -104,7 +115,7 @@ public class TypeProcessor extends BuiltinsMetadataProcessor new CustomAppender(level, msgPrefix, ConsoleOut.systemOut)) + } + + /** + * Returns a custom ConsoleAppender that will skip log messages starting with a certain prefix. + * + * The only reason for such appender is to force SBT to keep quiet about certain kind of messages + * coming from the analyzing compiler (wrapper around java compiler) when it tries to match class files + * to source files. There is absolutely no way to tell SBT that that some sources are being generated from + * annotation processors and it will get them during the same compilation round. Nor can we easily + * suppress such warning. + * + * @param excludeLevel level of log message to exclude (together with prefix) + * @param prefix prefix of log message to exclude (together with log level) + * @param out object representing console output + */ + private final class CustomAppender(excludeLevel: sbt.Level.Value, prefix: String, out: ConsoleOut) + extends ConsoleAppender("out", Properties.from(out, Terminal.isAnsiSupported, Terminal.isAnsiSupported), noSuppressedMessage) { + override def appendLog(level: sbt.Level.Value, message: => String): Unit = { + if (excludeLevel != level || !message.startsWith(prefix)) { + super.appendLog(level, message) + } + } + } +}