|  | 
|  | 1 | +package io.bazel.rulesscala.scalac.reporter; | 
|  | 2 | + | 
|  | 3 | +import io.bazel.rules_scala.diagnostics.Diagnostics; | 
|  | 4 | +import java.io.IOException; | 
|  | 5 | +import java.nio.file.Files; | 
|  | 6 | +import java.nio.file.Path; | 
|  | 7 | +import java.nio.file.StandardOpenOption; | 
|  | 8 | +import java.util.*; | 
|  | 9 | +import scala.reflect.internal.util.Position; | 
|  | 10 | +import scala.reflect.internal.util.RangePosition; | 
|  | 11 | +import scala.tools.nsc.Settings; | 
|  | 12 | +import scala.tools.nsc.reporters.ConsoleReporter; | 
|  | 13 | + | 
|  | 14 | +public class ProtoReporter extends ConsoleReporter { | 
|  | 15 | + | 
|  | 16 | +  private final Map<String, List<Diagnostics.Diagnostic>> builder; | 
|  | 17 | + | 
|  | 18 | +  public ProtoReporter(Settings settings) { | 
|  | 19 | +    super(settings); | 
|  | 20 | +    builder = new LinkedHashMap<>(); | 
|  | 21 | +  } | 
|  | 22 | + | 
|  | 23 | +  @Override | 
|  | 24 | +  public void reset() { | 
|  | 25 | +    super.reset(); | 
|  | 26 | +  } | 
|  | 27 | + | 
|  | 28 | +  public void writeTo(Path path) throws IOException { | 
|  | 29 | +    Diagnostics.TargetDiagnostics.Builder targetDiagnostics = | 
|  | 30 | +        Diagnostics.TargetDiagnostics.newBuilder(); | 
|  | 31 | +    for (Map.Entry<String, List<Diagnostics.Diagnostic>> entry : builder.entrySet()) { | 
|  | 32 | +      targetDiagnostics.addDiagnostics( | 
|  | 33 | +          Diagnostics.FileDiagnostics.newBuilder() | 
|  | 34 | +              .setPath(entry.getKey()) | 
|  | 35 | +              .addAllDiagnostics(entry.getValue())); | 
|  | 36 | +    } | 
|  | 37 | +    Files.write( | 
|  | 38 | +        path, | 
|  | 39 | +        targetDiagnostics.build().toByteArray(), | 
|  | 40 | +        StandardOpenOption.CREATE, | 
|  | 41 | +        StandardOpenOption.APPEND); | 
|  | 42 | +  } | 
|  | 43 | + | 
|  | 44 | +  @Override | 
|  | 45 | +  public void info0(Position pos, String msg, Severity severity, boolean force) { | 
|  | 46 | +    doReport(pos, msg, severity); | 
|  | 47 | +  } | 
|  | 48 | + | 
|  | 49 | +  @Override | 
|  | 50 | +  public void doReport(Position pos, String msg, Severity severity) { | 
|  | 51 | +    super.doReport(pos, msg, severity); | 
|  | 52 | + | 
|  | 53 | +    Diagnostics.Diagnostic diagnostic = | 
|  | 54 | +        Diagnostics.Diagnostic.newBuilder() | 
|  | 55 | +            .setRange(positionToRange(pos)) | 
|  | 56 | +            .setSeverity(convertSeverity(severity)) | 
|  | 57 | +            .setMessage(msg) | 
|  | 58 | +            .build(); | 
|  | 59 | +    // TODO: Handle generated files | 
|  | 60 | +    String uri = "workspace-root://" + pos.source().file().path(); | 
|  | 61 | +    List<Diagnostics.Diagnostic> diagnostics = builder.computeIfAbsent(uri, key -> new ArrayList()); | 
|  | 62 | +    diagnostics.add(diagnostic); | 
|  | 63 | +  } | 
|  | 64 | + | 
|  | 65 | +  private Diagnostics.Severity convertSeverity(Object severity) { | 
|  | 66 | +    String stringified = severity.toString().toLowerCase(); | 
|  | 67 | +    if ("error".equals(stringified)) { | 
|  | 68 | +      return Diagnostics.Severity.ERROR; | 
|  | 69 | +    } else if ("warning".equals(stringified)) { | 
|  | 70 | +      return Diagnostics.Severity.WARNING; | 
|  | 71 | +    } else if ("info".equals(stringified)) { | 
|  | 72 | +      return Diagnostics.Severity.INFORMATION; | 
|  | 73 | +    } | 
|  | 74 | +    throw new RuntimeException("Unknown severity: " + stringified); | 
|  | 75 | +  } | 
|  | 76 | + | 
|  | 77 | +  private Diagnostics.Range positionToRange(Position pos) { | 
|  | 78 | +    if (pos instanceof RangePosition) { | 
|  | 79 | +      RangePosition rangePos = (RangePosition) pos; | 
|  | 80 | +      int startLine = pos.source().offsetToLine(rangePos.start()); | 
|  | 81 | +      int endLine = pos.source().offsetToLine(rangePos.end()); | 
|  | 82 | +      return Diagnostics.Range.newBuilder() | 
|  | 83 | +          .setStart( | 
|  | 84 | +              Diagnostics.Position.newBuilder() | 
|  | 85 | +                  .setLine(startLine) | 
|  | 86 | +                  .setCharacter(rangePos.start() - pos.source().lineToOffset(startLine))) | 
|  | 87 | +          .setEnd( | 
|  | 88 | +              Diagnostics.Position.newBuilder() | 
|  | 89 | +                  .setLine(endLine) | 
|  | 90 | +                  .setCharacter(rangePos.end() - pos.source().lineToOffset(endLine)) | 
|  | 91 | +                  .build()) | 
|  | 92 | +          .build(); | 
|  | 93 | +    } | 
|  | 94 | +    return Diagnostics.Range.newBuilder() | 
|  | 95 | +        .setStart( | 
|  | 96 | +            Diagnostics.Position.newBuilder() | 
|  | 97 | +                .setLine(pos.line() - 1) | 
|  | 98 | +                .setCharacter(pos.column() - 1)) | 
|  | 99 | +        .setEnd(Diagnostics.Position.newBuilder().setLine(pos.line())) | 
|  | 100 | +        .build(); | 
|  | 101 | +  } | 
|  | 102 | +} | 
0 commit comments