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 9f029041a4
commit 24aa5b1795
3 changed files with 108 additions and 23 deletions

View File

@ -61,7 +61,7 @@ public class Compilation {
} }
GL20.glDeleteShader(handle); 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) { public void enableExtension(String ext) {
@ -80,7 +80,7 @@ public class Compilation {
private void appendHeader(SourceComponent component, String source) { private void appendHeader(SourceComponent component, String source) {
if (component instanceof SourceFile file) { if (component instanceof SourceFile file) {
int fileID = files.size(); int fileID = files.size() + 1;
files.add(file); files.add(file);

View File

@ -1,6 +1,8 @@
package com.jozufozu.flywheel.backend.compile.core; package com.jozufozu.flywheel.backend.compile.core;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.function.Consumer;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; 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.SourceLines;
import com.jozufozu.flywheel.glsl.error.ConsoleColors; import com.jozufozu.flywheel.glsl.error.ConsoleColors;
import com.jozufozu.flywheel.glsl.error.ErrorBuilder; 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.glsl.span.Span;
import com.jozufozu.flywheel.lib.util.StringUtil; import com.jozufozu.flywheel.lib.util.StringUtil;
@ -20,16 +23,20 @@ import net.minecraft.resources.ResourceLocation;
public class FailedCompilation { public class FailedCompilation {
public static final ResourceLocation GENERATED_SOURCE_NAME = Flywheel.rl("generated_source"); 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 List<SourceFile> files;
private final SourceLines generatedSource; private final SourceLines generatedSource;
private final String errorLog; private final String errorLog;
private final String shaderName; 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.shaderName = shaderName;
this.files = files; this.files = files;
this.generatedSource = new SourceLines(GENERATED_SOURCE_NAME, generatedSource); this.generatedSource = new SourceLines(GENERATED_SOURCE_NAME, generatedSource);
this.completeSource = completeSource;
this.errorLog = errorLog; this.errorLog = errorLog;
} }
@ -45,26 +52,60 @@ public class FailedCompilation {
@NotNull @NotNull
private Stream<ErrorBuilder> errorStream() { private Stream<ErrorBuilder> errorStream() {
return errorLog.lines() return errorLog.lines()
.map(this::interpretErrorLine); .mapMulti(this::interpretLine);
} }
private ErrorBuilder interpretErrorLine(String s) { private void interpretLine(String s, Consumer<ErrorBuilder> out) {
Matcher matcher = ERROR_LINE.matcher(s); if (s.isEmpty()) {
return;
}
Matcher matcher;
matcher = PATTERN_ONE.matcher(s);
if (matcher.find()) { 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 fileId = Integer.parseInt(matcher.group(1));
int lineNo = Integer.parseInt(matcher.group(2)); int lineNo = Integer.parseInt(matcher.group(2));
var msg = StringUtil.trimPrefix(matcher.group(3), "error") var msg = StringUtil.trimPrefix(matcher.group(3), "error")
.stripLeading(); .stripLeading();
if (fileId == 0) { if (fileId == 0) {
return interpretGeneratedError(lineNo, msg); return interpretGeneratedError(ErrorLevel.ERROR, lineNo, msg);
} else { } else {
return interpretSourceError(fileId, lineNo, msg); return interpretSourceError(fileId, lineNo, msg);
} }
} }
return ErrorBuilder.create()
.error(s); 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);
}
} }
private ErrorBuilder interpretSourceError(int fileId, int lineNo, String msg) { private ErrorBuilder interpretSourceError(int fileId, int lineNo, String msg) {
@ -77,11 +118,36 @@ public class FailedCompilation {
.pointAt(span, 1); .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() 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]") .pointAtFile("[in generated source]")
.pointAtLine(generatedSource, lineNo, 1) .pointAtLine(generatedSource, lineNo, 1)
.note("This generally indicates a bug in Flywheel, not your shader code."); .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 java.util.Set;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
@ -144,6 +145,24 @@ public class SourceFile implements SourceComponent {
return new StringSpan(source, begin, end); 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. * Search this file and recursively search all imports to find a struct definition matching the given name.
* *