add a util DiagnosticSink

This commit is contained in:
bQUARKz 2026-02-26 18:23:40 +00:00
parent 296fe06f07
commit 176a3f7587
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
2 changed files with 131 additions and 1 deletions

View File

@ -1,4 +1,92 @@
package p.studio.compiler.source.diagnostics;
public class DiagnosticSink {
import p.studio.compiler.source.Span;
import p.studio.utilities.structures.ReadOnlyCollection;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class DiagnosticSink extends ReadOnlyCollection<Diagnostic> {
private int errorCount = 0;
private int warningCount = 0;
protected DiagnosticSink() {
super(new ArrayList<>());
}
public static DiagnosticSink empty() {
return new DiagnosticSink();
}
public DiagnosticSink report(final Diagnostic diagnostic) {
Objects.requireNonNull(diagnostic);
if (diagnostic.getSeverity().isError()) {
errorCount++;
} else {
warningCount++;
}
collection.add(diagnostic);
return this;
}
public DiagnosticSink report(
final Severity severity,
final String code,
final String message,
final Span span) {
return report(severity, code, message, span, List.of());
}
public DiagnosticSink report(
final Severity severity,
final String code,
final String message,
final Span span,
final List<RelatedSpan> related) {
return report(new Diagnostic(
Objects.requireNonNull(severity),
Objects.requireNonNull(code),
Objects.requireNonNull(message),
Objects.requireNonNull(span),
List.copyOf(Objects.requireNonNull(related))));
}
public DiagnosticSink error(
final String code,
final String message,
final Span span) {
return report(Severity.Error, code, message, span);
}
public DiagnosticSink warning(
final String code,
final String message,
final Span span) {
return report(Severity.Warning, code, message, span);
}
public DiagnosticSink merge(final DiagnosticSink diagnostics) {
Objects.requireNonNull(diagnostics);
for (final Diagnostic diagnostic : diagnostics) {
report(diagnostic);
}
return this;
}
public boolean hasErrors() {
return errorCount > 0;
}
public boolean hasWarnings() {
return warningCount > 0;
}
public int errorCount() {
return errorCount;
}
public int warningCount() {
return warningCount;
}
}

View File

@ -0,0 +1,42 @@
package p.studio.compiler.source.diagnostics;
import org.junit.jupiter.api.Test;
import p.studio.compiler.source.Span;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
class DiagnosticSinkTest {
@Test
void shouldReportAndCountDiagnostics() {
final var sink = DiagnosticSink.empty();
sink.error("E001", "Unknown symbol", Span.none());
sink.warning("W001", "Unused declaration", Span.none());
assertEquals(2, sink.size());
assertTrue(sink.hasErrors());
assertTrue(sink.hasWarnings());
assertEquals(1, sink.errorCount());
assertEquals(1, sink.warningCount());
}
@Test
void shouldMergeDiagnostics() {
final var a = DiagnosticSink.empty()
.warning("W010", "Unused import", Span.none());
final var b = DiagnosticSink.empty()
.error("E999", "Invalid type", Span.none());
a.merge(b);
assertEquals(2, a.size());
assertTrue(a.hasErrors());
assertTrue(a.hasWarnings());
assertEquals(1, a.errorCount());
assertEquals(1, a.warningCount());
assertEquals(1, b.errorCount());
assertEquals(0, b.warningCount());
}
}