Checkpoint

This commit is contained in:
Stephan Schroevers
2023-04-19 22:54:50 +02:00
parent 34024296a6
commit 9221f7f212
4 changed files with 118 additions and 4 deletions

View File

@@ -3,6 +3,10 @@ package tech.picnic.errorprone.openai;
import static com.google.common.base.Preconditions.checkState;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.theokanning.openai.completion.chat.ChatCompletionRequest;
import com.theokanning.openai.completion.chat.ChatCompletionResult;
import com.theokanning.openai.completion.chat.ChatMessage;
import com.theokanning.openai.edit.EditRequest;
import com.theokanning.openai.service.OpenAiService;
import java.time.Duration;
@@ -42,13 +46,30 @@ public class OpenAi implements AutoCloseable {
.model("code-davinci-edit-001")
.instruction(instruction)
.temperature(0.0)
.n(1)
.build())
.getChoices()
.get(0)
.getText();
}
// XXX: Improve error handling, including checking the finish reason.
String requestChatCompletion(String instruction) {
return openAiService
.createChatCompletion(
ChatCompletionRequest.builder()
.messages(
ImmutableList.of(
new ChatMessage("system", "You are an expert Java developer"),
new ChatMessage("user", instruction)))
.model("gpt-3.5-turbo")
.temperature(0.0)
.build())
.getChoices()
.get(0)
.getMessage()
.getContent();
}
@Override
public void close() {
openAiService.shutdownExecutor();

View File

@@ -14,9 +14,12 @@ import java.util.stream.Stream;
* Compiler message format</a>
*/
// XXX: Can path be relative? If so, that'd clash with `CheckStyleIssueExtractor`.
// ^ I think we should allow this, and then introduce a way to _chain_ extractors using short
// circuiting.
// XXX: Also replace "Did you mean to remove" with "Remove"?
// XXX: Also replace "Did you mean '" with "Instead use '"?
// XXX: Concat "Did you mean" message to the preceding line?
// XXX: More generally join lines by `. ` (inserting dot if necessary)?
// ^ For debuggability it could make sense to keep the original message, and _separately_ generate
// the OpenAI prompt.
final class PlexusCompilerIssueExtractor implements IssueExtractor<String> {
@@ -24,7 +27,7 @@ final class PlexusCompilerIssueExtractor implements IssueExtractor<String> {
// https://github.com/codehaus-plexus/plexus-compiler/blob/a5775b2258349b7c0d7c7759f162c80672328a0e/plexus-compiler-api/src/main/java/org/codehaus/plexus/compiler/CompilerMessage.java#L271-L296.
private static final Pattern LOG_LINE_FORMAT =
Pattern.compile(
"^(?<file>/.+?\\.java):\\[(?<line>\\d+)(?:,(?<column>\\d+))?\\] (?<message>.+)$",
"^(?<file>/.+?\\.java):(?:\\[(?<line>\\d+)(?:,(?<column>\\d+))?\\])? (?<message>.+)$",
Pattern.DOTALL);
private static final Pattern ERROR_PRONE_DOCUMENTATION_REFERENCE =
Pattern.compile("^\\s*\\(see .+\\)\\s*$");

View File

@@ -0,0 +1,72 @@
package tech.picnic.errorprone.openai;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.params.provider.Arguments.arguments;
import static tech.picnic.errorprone.openai.OpenAi.OPENAI_TOKEN_VARIABLE;
import java.util.stream.Stream;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
// XXX: Drop this code.
@TestInstance(Lifecycle.PER_CLASS)
@EnabledIfSystemProperty(named = OPENAI_TOKEN_VARIABLE, matches = ".*")
final class PlayGroundTest {
private final OpenAi openAi = OpenAi.create();
@AfterAll
void tearDown() {
openAi.close();
}
@Test
@Disabled
void test() {
String input =
"""
I would like to generate Refaster rules that match a Java expression A and transform it into an equivalent Java expression B.
This is an example of a Refaster rule that unwraps `Comparator#comparing` arguments to `Comparator#thenComparing`:
import static java.util.Comparator.comparing;
import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
import java.util.Comparator;
import java.util.function.Function;
/** Don't explicitly create {@link Comparator}s unnecessarily. */
final class ThenComparing<S, T extends Comparable<? super T>> {
@BeforeTemplate
Comparator<S> before(Comparator<S> cmp, Function<? super S, ? extends T> function) {
return cmp.thenComparing(comparing(function));
}
@AfterTemplate
Comparator<S> after(Comparator<S> cmp, Function<? super S, ? extends T> function) {
return cmp.thenComparing(function);
}
}
###
Write a Refaster rule that transforms `mono.blockOptional().map(function)` into `mono.map(function).blockOptional()`.
Requirements:
- Just write the new code. Don't explain yourself.
- If the rule requires type parameters, declare those on the class.
- Add all relevant imports.
"""
.stripTrailing();
// XXX: ^ That trailing whitespace removal is crucial!!
assertThat(openAi.requestChatCompletion(input)).isEqualTo("XXX");
}
}

View File

@@ -14,8 +14,6 @@ import tech.picnic.errorprone.openai.IssueExtractor.Issue;
final class PlexusCompilerIssueExtractorTest {
private final IssueExtractor<String> issueExtractor = new PlexusCompilerIssueExtractor();
// XXX: Add column absent test case.
// XXX: Add line absent test case (and update the code to cover this case; see the Plexus code).
private static Stream<Arguments> extractTestCases() {
/* { input, expected } */
return Stream.of(
@@ -36,6 +34,26 @@ final class PlexusCompilerIssueExtractorTest {
OptionalInt.of(30),
OptionalInt.of(22),
"no comment"))),
arguments(
"""
/absolute/path/to/MyClass2.java:[123] error message without column specification
""",
ImmutableSet.of(
new Issue(
"/absolute/path/to/MyClass2.java",
OptionalInt.of(123),
OptionalInt.empty(),
"error message without column specification"))),
arguments(
"""
/absolute/path/to/MyClass3.java: error message without location specification
""",
ImmutableSet.of(
new Issue(
"/absolute/path/to/MyClass3.java",
OptionalInt.empty(),
OptionalInt.empty(),
"error message without location specification"))),
arguments(
"""
/absolute/path/to/another/Class.java:[10,17] cannot find symbol