Error in errors

- Parse error format produced by my intel laptop now.
- Fix some off-by-one errors in error reporting.
This commit is contained in:
Jozufozu 2023-11-26 16:16:33 -08:00
parent c5f2361e6b
commit 08d9f789dc
3 changed files with 108 additions and 23 deletions

View file

@ -61,7 +61,7 @@ public class Compilation {
}
GL20.glDeleteShader(handle);
return ShaderResult.failure(new FailedCompilation(shaderName, files, generatedSource.toString(), infoLog));
return ShaderResult.failure(new FailedCompilation(shaderName, files, generatedSource.toString(), source, infoLog));
}
public void enableExtension(String ext) {
@ -80,7 +80,7 @@ public class Compilation {
private void appendHeader(SourceComponent component, String source) {
if (component instanceof SourceFile file) {
int fileID = files.size();
int fileID = files.size() + 1;
files.add(file);

View file

@ -1,6 +1,8 @@
package com.jozufozu.flywheel.backend.compile.core;
import java.util.List;
import java.util.Locale;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@ -13,6 +15,7 @@ import com.jozufozu.flywheel.glsl.SourceFile;
import com.jozufozu.flywheel.glsl.SourceLines;
import com.jozufozu.flywheel.glsl.error.ConsoleColors;
import com.jozufozu.flywheel.glsl.error.ErrorBuilder;
import com.jozufozu.flywheel.glsl.error.ErrorLevel;
import com.jozufozu.flywheel.glsl.span.Span;
import com.jozufozu.flywheel.lib.util.StringUtil;
@ -20,16 +23,20 @@ import net.minecraft.resources.ResourceLocation;
public class FailedCompilation {
public static final ResourceLocation GENERATED_SOURCE_NAME = Flywheel.rl("generated_source");
private static final Pattern ERROR_LINE = Pattern.compile("(\\d+)\\((\\d+)\\) : (.*)");
private static final Pattern PATTERN_ONE = Pattern.compile("(\\d+)\\((\\d+)\\) : (.*)");
private static final Pattern PATTERN_TWO = Pattern.compile("(\\w+): (\\d+):(\\d+):(?: '(.+?)' :)?(.*)");
private final List<SourceFile> files;
private final SourceLines generatedSource;
private final String errorLog;
private final String shaderName;
// Unused, but handy for debugging.
private final String completeSource;
public FailedCompilation(String shaderName, List<SourceFile> files, String generatedSource, String errorLog) {
public FailedCompilation(String shaderName, List<SourceFile> files, String generatedSource, String completeSource, String errorLog) {
this.shaderName = shaderName;
this.files = files;
this.generatedSource = new SourceLines(GENERATED_SOURCE_NAME, generatedSource);
this.completeSource = completeSource;
this.errorLog = errorLog;
}
@ -45,26 +52,60 @@ public class FailedCompilation {
@NotNull
private Stream<ErrorBuilder> errorStream() {
return errorLog.lines()
.map(this::interpretErrorLine);
.mapMulti(this::interpretLine);
}
private ErrorBuilder interpretErrorLine(String s) {
Matcher matcher = ERROR_LINE.matcher(s);
if (matcher.find()) {
int fileId = Integer.parseInt(matcher.group(1));
int lineNo = Integer.parseInt(matcher.group(2));
var msg = StringUtil.trimPrefix(matcher.group(3), "error")
.stripLeading();
if (fileId == 0) {
return interpretGeneratedError(lineNo, msg);
} else {
return interpretSourceError(fileId, lineNo, msg);
}
private void interpretLine(String s, Consumer<ErrorBuilder> out) {
if (s.isEmpty()) {
return;
}
Matcher matcher;
matcher = PATTERN_ONE.matcher(s);
if (matcher.find()) {
out.accept(interpretPattern1(matcher));
return;
}
matcher = PATTERN_TWO.matcher(s);
if (matcher.find()) {
out.accept(interpretPattern2(matcher));
return;
}
out.accept(ErrorBuilder.create()
.error(s));
}
private ErrorBuilder interpretPattern1(Matcher matcher) {
int fileId = Integer.parseInt(matcher.group(1));
int lineNo = Integer.parseInt(matcher.group(2));
var msg = StringUtil.trimPrefix(matcher.group(3), "error")
.stripLeading();
if (fileId == 0) {
return interpretGeneratedError(ErrorLevel.ERROR, lineNo, msg);
} else {
return interpretSourceError(fileId, lineNo, msg);
}
}
private ErrorBuilder interpretPattern2(Matcher matcher) {
var errorLevel = parseErrorLevel(matcher.group(1));
int fileId = Integer.parseInt(matcher.group(2));
int lineNo = Integer.parseInt(matcher.group(3)) - 1;
String span = matcher.group(4);
var msg = matcher.group(5).trim();
if (fileId == 0) {
return interpretGeneratedError(errorLevel, lineNo, msg);
} else {
return interpretWithSpan(errorLevel, fileId, lineNo, span, msg);
}
return ErrorBuilder.create()
.error(s);
}
private ErrorBuilder interpretSourceError(int fileId, int lineNo, String msg) {
@ -77,11 +118,36 @@ public class FailedCompilation {
.pointAt(span, 1);
}
private ErrorBuilder interpretGeneratedError(int lineNo, String msg) {
private ErrorBuilder interpretWithSpan(ErrorLevel errorLevel, int fileId, int lineNo, String span, String msg) {
var sourceFile = files.get(fileId - 1);
Span errorSpan;
if (span != null) {
errorSpan = sourceFile.getLineSpanMatching(lineNo, span);
} else {
errorSpan = sourceFile.getLineSpanNoWhitespace(lineNo);
}
return ErrorBuilder.create()
.error(msg)
.header(errorLevel, msg)
.pointAtFile(sourceFile)
.pointAt(errorSpan, 1);
}
private ErrorBuilder interpretGeneratedError(ErrorLevel errorLevel, int lineNo, String msg) {
return ErrorBuilder.create()
.header(errorLevel, msg)
.pointAtFile("[in generated source]")
.pointAtLine(generatedSource, lineNo, 1)
.note("This generally indicates a bug in Flywheel, not your shader code.");
}
@NotNull
private static ErrorLevel parseErrorLevel(String level) {
return switch (level.toLowerCase(Locale.ROOT)) {
case "error" -> ErrorLevel.ERROR;
case "warning", "warn" -> ErrorLevel.WARN;
default -> ErrorLevel.NOTE;
};
}
}

View file

@ -8,6 +8,7 @@ import java.util.Optional;
import java.util.Set;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@ -144,6 +145,24 @@ public class SourceFile implements SourceComponent {
return new StringSpan(source, begin, end);
}
public Span getLineSpanMatching(int line, @Nullable String match) {
if (match == null) {
return getLineSpanNoWhitespace(line);
}
var spanBegin = source.lineString(line)
.indexOf(match);
if (spanBegin == -1) {
return getLineSpanNoWhitespace(line);
}
int begin = source.lineStartIndex(line) + spanBegin;
int end = begin + match.length();
return new StringSpan(source, begin, end);
}
/**
* Search this file and recursively search all imports to find a struct definition matching the given name.
*