mirror of
https://github.com/jlengrand/error-prone-support.git
synced 2026-03-10 08:11:25 +00:00
Not sure
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
package tech.picnic.errorprone.openai;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
// XXX: Use this class, or drop it.
|
||||
final class AggregatingIssueExtractor implements IssueExtractor {
|
||||
private final ImmutableSet<IssueExtractor> delegates;
|
||||
|
||||
AggregatingIssueExtractor(ImmutableSet<IssueExtractor> delegates) {
|
||||
this.delegates = delegates;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Issue> extract(String str) {
|
||||
return delegates.stream().flatMap(delegate -> delegate.extract(str));
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package tech.picnic.errorprone.openai;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
@@ -11,11 +12,13 @@ import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.regex.Pattern;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import tech.picnic.errorprone.openai.MavenLogParser.JavacAndCheckstyleLogLineAnalyzer;
|
||||
import tech.picnic.errorprone.openai.MavenLogParser.LogLineAnalyzer;
|
||||
|
||||
// XXX: Consider using https://picocli.info/quick-guide.html. Can also be used for an interactive
|
||||
// CLI.
|
||||
// XXX: Introduce README.
|
||||
// XXX: Consider creating a binary executable using GraalVM.
|
||||
// XXX: Add support for sending a suitable subset of the code to OpenAI, so as (a) to better deal
|
||||
// with the token limit and (b) potentially reduce cost.
|
||||
public final class AiPatcher {
|
||||
private static final Pattern FILE_LOCATION_MARKER =
|
||||
Pattern.compile("^(.*?\\.java):\\[(\\d+)(?:,(\\d+))?\\] ");
|
||||
@@ -91,17 +94,20 @@ public final class AiPatcher {
|
||||
|
||||
// XXX: Clean this up.
|
||||
private static void extractPathAndMessage(String logLine, BiConsumer<Path, String> sink) {
|
||||
LogLineAnalyzer analyzer =
|
||||
new JavacAndCheckstyleLogLineAnalyzer(
|
||||
new PathFinder(FileSystems.getDefault(), Path.of("")));
|
||||
IssueExtractor analyzer =
|
||||
new AggregatingIssueExtractor(
|
||||
ImmutableSet.of(new JavacIssueExtractor(), new CheckstyleIssueExtractor()));
|
||||
|
||||
analyzer
|
||||
.analyze(logLine)
|
||||
.extract(logLine)
|
||||
.findFirst()
|
||||
.ifPresent(
|
||||
issue ->
|
||||
sink.accept(
|
||||
issue.file(),
|
||||
// XXX: Fix.
|
||||
new PathFinder(FileSystems.getDefault(), Path.of(""))
|
||||
.findPath(issue.file())
|
||||
.orElseThrow(),
|
||||
issue.column().isEmpty()
|
||||
? String.format("- Line %s: %s", issue.line(), issue.message())
|
||||
: String.format(
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package tech.picnic.errorprone.openai;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
// [ERROR] src/main/java/tech/picnic/errorprone/refaster/plugin/RefasterRuleCompiler.java:[13,1]
|
||||
// (annotation) AnnotationUseStyle: Annotation style must be 'COMPACT_NO_ARRAY'.
|
||||
// [ERROR] src/main/java/tech/picnic/errorprone/refaster/plugin/RefasterRuleCompiler.java:[14,15]
|
||||
// (annotation) AnnotationUseStyle: Annotation array values cannot contain trailing comma.
|
||||
// [ERROR] src/main/java/tech/picnic/errorprone/refaster/plugin/RefasterRuleCompiler.java:[16]
|
||||
// (regexp) RegexpMultiline: Avoid blank lines at the start of a block.
|
||||
|
||||
final class CheckstyleIssueExtractor implements IssueExtractor {
|
||||
private static final Pattern LOG_LINE_FORMAT =
|
||||
Pattern.compile(
|
||||
"^(?<file>.+?\\.java):\\[(?<line>\\d+)(?:,(?<column>\\d+))?\\] \\(.+?\\) .+: (?<message>.+)$",
|
||||
Pattern.DOTALL);
|
||||
|
||||
private final IssueExtractor delegate = new RegexIssueExtractor(LOG_LINE_FORMAT);
|
||||
|
||||
@Override
|
||||
public Stream<Issue> extract(String str) {
|
||||
return delegate.extract(str);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package tech.picnic.errorprone.openai;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
// XXX: Use or drop.
|
||||
final class FileEditSuggester {
|
||||
private final OpenAi openAi;
|
||||
|
||||
FileEditSuggester(OpenAi openAi) {
|
||||
this.openAi = openAi;
|
||||
}
|
||||
|
||||
ImmutableList<EditSuggestion> suggestEdits(String fileContent) {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
record EditSuggestion(String replacement, String unifiedPatch) {}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package tech.picnic.errorprone.openai;
|
||||
|
||||
import java.util.OptionalInt;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
// XXX: Document
|
||||
interface IssueExtractor {
|
||||
Stream<Issue> extract(String str);
|
||||
|
||||
// XXX: Make `Path` a `String` and do path lookup post collection? (This would simplify things,
|
||||
// but may close off some future possibilities.)
|
||||
// ^ Not really. Where it matters we can double-resolve.
|
||||
// XXX: ^ Also simplifies testing.
|
||||
// XXX: Or move to separate file?
|
||||
record Issue(String message, String file, int line, OptionalInt column) {
|
||||
|
||||
Issue withMessage(String message) {
|
||||
return new Issue(message, file, line, column);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package tech.picnic.errorprone.openai;
|
||||
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
// [WARNING]
|
||||
// /home/sschroevers/workspace/picnic/error-prone-support/openai-coder/src/main/java/tech/picnic/errorprone/openai/AiPatcher.java:[30,22] no comment
|
||||
// [WARNING]
|
||||
// /home/sschroevers/workspace/picnic/error-prone-support/openai-coder/src/main/java/tech/picnic/errorprone/openai/AiPatcher.java:[22,32] [UnusedVariable] The field 'FILE_LOCATION_MARKER' is never read.
|
||||
// (see https://errorprone.info/bugpattern/UnusedVariable)
|
||||
// Did you mean to remove this line or 'static {
|
||||
// Pattern.compile("^(.*?\\.java):\\[(\\d+)(?:,(\\d+))?\\] "); }'?
|
||||
|
||||
// XXX: Create another `LogLineAnalyzer` for Error Prone test compiler output.
|
||||
// XXX: Also replace "Did you mean to remove" with "Remove"?
|
||||
final class JavacIssueExtractor implements IssueExtractor {
|
||||
private static final Pattern LOG_LINE_FORMAT =
|
||||
Pattern.compile(
|
||||
"^(?<file>.+?\\.java):\\[(?<line>\\d+)(?:,(?<column>\\d+))?\\] (?<message>.+)$",
|
||||
Pattern.DOTALL);
|
||||
private static final Pattern ERROR_PRONE_DOCUMENTATION_REFERENCE =
|
||||
Pattern.compile("^\\s*\\(see .+\\)\\s+$");
|
||||
|
||||
private final IssueExtractor delegate = new RegexIssueExtractor(LOG_LINE_FORMAT);
|
||||
|
||||
@Override
|
||||
public Stream<Issue> extract(String str) {
|
||||
return delegate
|
||||
.extract(str)
|
||||
.map(issue -> issue.withMessage(removeErrorProneDocumentationReference(issue.message())));
|
||||
}
|
||||
|
||||
private static String removeErrorProneDocumentationReference(String message) {
|
||||
return message
|
||||
.lines()
|
||||
.filter(line -> !ERROR_PRONE_DOCUMENTATION_REFERENCE.matcher(line).matches())
|
||||
.collect(joining(""));
|
||||
}
|
||||
|
||||
// // XXX: drop the `(see` line.
|
||||
// @Override
|
||||
// public Stream<Issue> extract(String str) {
|
||||
// Matcher matcher = FILE_LOCATION_MARKER.matcher(str);
|
||||
// if (!matcher.find()) {
|
||||
// return Stream.empty();
|
||||
// }
|
||||
//
|
||||
// return pathFinder
|
||||
// .findPath(matcher.group("file"))
|
||||
// .map(
|
||||
// p ->
|
||||
// new Issue(
|
||||
// str.substring(matcher.end()),
|
||||
// p,
|
||||
// Integer.parseInt(matcher.group("line")),
|
||||
// matcher.group("column") == null
|
||||
// ? OptionalInt.empty()
|
||||
// : OptionalInt.of(Integer.parseInt(matcher.group("column")))))
|
||||
// .stream();
|
||||
// }
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package tech.picnic.errorprone.openai;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.nio.file.Path;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
final class MavenLogParser {
|
||||
private final ImmutableSet<LogLineAnalyzer> logLineAnalyzers;
|
||||
|
||||
// XXX: Use.
|
||||
MavenLogParser(ImmutableSet<LogLineAnalyzer> logLineAnalyzers) {
|
||||
this.logLineAnalyzers = logLineAnalyzers;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
// XXX: Create a second `LogLineAnalyzer` for Error Prone test compiler output.
|
||||
|
||||
// XXX: Review class name.
|
||||
// XXX: Provide additional implementations.
|
||||
static final class JavacAndCheckstyleLogLineAnalyzer implements LogLineAnalyzer {
|
||||
private static final Pattern FILE_LOCATION_MARKER =
|
||||
Pattern.compile("^(.*?\\.java):\\[(\\d+)(?:,(\\d+))?\\] ");
|
||||
|
||||
private final PathFinder pathFinder;
|
||||
|
||||
JavacAndCheckstyleLogLineAnalyzer(PathFinder pathFinder) {
|
||||
this.pathFinder = pathFinder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Issue> analyze(String logLine) {
|
||||
Matcher matcher = FILE_LOCATION_MARKER.matcher(logLine);
|
||||
if (!matcher.find()) {
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
return pathFinder
|
||||
.findPath(matcher.group(1))
|
||||
.map(
|
||||
p ->
|
||||
new Issue(
|
||||
logLine.substring(matcher.end()),
|
||||
p,
|
||||
Integer.parseInt(matcher.group(2)),
|
||||
matcher.group(3) == null
|
||||
? OptionalInt.empty()
|
||||
: OptionalInt.of(Integer.parseInt(matcher.group(3)))))
|
||||
.stream();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Move to separate file.
|
||||
interface LogLineAnalyzer {
|
||||
Stream<Issue> analyze(String line);
|
||||
}
|
||||
|
||||
// XXX: Make `Path` a `String` and do path lookup post collection? (This would simplify things,
|
||||
// but may close off some future possibilities.)
|
||||
// ^ Not really. Where it matters we can double-resolve.
|
||||
// XXX: Move to separate file, or inside `LogLineAnalyzer`.
|
||||
record Issue(String message, Path file, int line, OptionalInt column) {}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package tech.picnic.errorprone.openai;
|
||||
|
||||
import java.util.OptionalInt;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
// XXX: Document contract
|
||||
final class RegexIssueExtractor implements IssueExtractor {
|
||||
private final Pattern pattern;
|
||||
|
||||
RegexIssueExtractor(Pattern pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Issue> extract(String str) {
|
||||
return Stream.of(pattern.matcher(str))
|
||||
.filter(Matcher::matches)
|
||||
.map(
|
||||
matcher ->
|
||||
new IssueExtractor.Issue(
|
||||
matcher.group("message"),
|
||||
matcher.group("file"),
|
||||
Integer.parseInt(matcher.group("line")),
|
||||
matcher.group("column") == null
|
||||
? OptionalInt.empty()
|
||||
: OptionalInt.of(Integer.parseInt(matcher.group("column")))));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user