diff --git a/build.gradle b/build.gradle index 947bb6f..509b0f4 100644 --- a/build.gradle +++ b/build.gradle @@ -138,8 +138,10 @@ tasks.withType(Test).configureEach { test { include '**/NullSpecTest$Minimal.class' - inputs.files("${rootDir}/tests/minimal") + + include '**/NullSpecTest$Regression.class' + inputs.files("${rootDir}/tests/regression") } tasks.register('jspecifySamplesTest', Test) { diff --git a/src/main/java/com/google/jspecify/nullness/ConformanceTypeInformationPresenter.java b/src/main/java/com/google/jspecify/nullness/ConformanceTypeInformationPresenter.java index 83d4da6..9bffb72 100644 --- a/src/main/java/com/google/jspecify/nullness/ConformanceTypeInformationPresenter.java +++ b/src/main/java/com/google/jspecify/nullness/ConformanceTypeInformationPresenter.java @@ -16,7 +16,6 @@ import com.sun.source.tree.AssignmentTree; import com.sun.source.tree.ClassTree; -import com.sun.source.tree.ExpressionTree; import com.sun.source.tree.MethodInvocationTree; import com.sun.source.tree.Tree; import java.util.List; @@ -85,9 +84,6 @@ protected void reportTreeType( String methodName = calledElem.getSimpleName().toString(); AnnotatedExecutableType calledType = (AnnotatedExecutableType) type; List params = calledType.getParameterTypes(); - MethodInvocationTree mit = (MethodInvocationTree) tree; - List args = mit.getArguments(); - assert params.size() == args.size(); for (int i = 0; i < params.size(); ++i) { String paramName = calledElem.getParameters().get(i).getSimpleName().toString(); diff --git a/src/test/java/tests/ConformanceTest.java b/src/test/java/tests/ConformanceTest.java index c7e2cb7..93bd890 100644 --- a/src/test/java/tests/ConformanceTest.java +++ b/src/test/java/tests/ConformanceTest.java @@ -29,7 +29,6 @@ import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Stream; @@ -142,8 +141,7 @@ private static ImmutableSet analyze( TestUtilities.getShouldEmitDebugInfo()); TypecheckResult result = new TypecheckExecutor().runTest(config); return result.getUnexpectedDiagnostics().stream() - .map(d -> DetailMessage.parse(d.getMessage(), testDirectory)) - .filter(Objects::nonNull) + .map(d -> DetailMessage.parse(d, testDirectory)) // Do not filter out messages without details. // .filter(DetailMessage::hasDetails) .map(DetailMessageReportedFact::new) @@ -182,7 +180,7 @@ static final class DetailMessageReportedFact extends ReportedFact { private final DetailMessage detailMessage; DetailMessageReportedFact(DetailMessage detailMessage) { - super(detailMessage.file, detailMessage.lineNumber); + super(detailMessage.getFile(), detailMessage.getLineNumber()); this.detailMessage = detailMessage; } diff --git a/src/test/java/tests/DetailMessage.java b/src/test/java/tests/DetailMessage.java index c7deeed..cf77b02 100644 --- a/src/test/java/tests/DetailMessage.java +++ b/src/test/java/tests/DetailMessage.java @@ -4,16 +4,13 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.collect.Iterables.getLast; import static java.lang.Integer.parseInt; -import static java.util.Arrays.stream; import static java.util.regex.Pattern.DOTALL; -import static java.util.stream.Collectors.joining; import com.google.common.base.Joiner; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.List; import java.util.Objects; import java.util.regex.Matcher; @@ -30,13 +27,6 @@ */ final class DetailMessage extends TestDiagnostic { - private static final Pattern MESSAGE_PATTERN = - Pattern.compile( - "(?\\S+):(?\\d+): (?" - + stream(DiagnosticKind.values()).map(k -> k.parseString).collect(joining("|")) - + "): (?.*)", - DOTALL); - /** Parser for the output for -Adetailedmsgtext. */ // Implemented here: org.checkerframework.framework.source.SourceChecker#detailedMsgTextPrefix private static final Pattern DETAIL_MESSAGE_PATTERN = @@ -49,12 +39,6 @@ final class DetailMessage extends TestDiagnostic { private static final Pattern OFFSETS_PATTERN = Pattern.compile("(\\( (?-?\\d+), (?-?\\d+) \\))?"); - /** The path to the source file containing the diagnostic. */ - final Path file; - - /** The line number (1-based) of the diagnostic in the {@link #file}. */ - final int lineNumber; - /** The message key for the user-visible text message that is emitted. */ final String messageKey; @@ -71,30 +55,29 @@ final class DetailMessage extends TestDiagnostic { final String readableMessage; /** - * Returns an object parsed from a diagnostic message, or {@code null} if the message doesn't - * match the expected format. + * Returns an object parsed from a diagnostic message. * * @param rootDirectory if not null, a root directory prefix to remove from the file part of the * message */ - static @Nullable DetailMessage parse(String input, @Nullable Path rootDirectory) { - Matcher messageMatcher = MESSAGE_PATTERN.matcher(input); - if (!messageMatcher.matches()) { - return null; - } - - Path file = Paths.get(messageMatcher.group("file")); - if (rootDirectory != null) { + static DetailMessage parse(TestDiagnostic input, @Nullable Path rootDirectory) { + Path file = input.getFile(); + if (rootDirectory != null && file.startsWith(rootDirectory)) { file = rootDirectory.relativize(file); } - int lineNumber = parseInt(messageMatcher.group("lineNumber")); - DiagnosticKind kind = DiagnosticKind.fromParseString(messageMatcher.group("kind")); - String message = messageMatcher.group("message"); - Matcher detailsMatcher = DETAIL_MESSAGE_PATTERN.matcher(message); + Matcher detailsMatcher = DETAIL_MESSAGE_PATTERN.matcher(input.getMessage()); if (!detailsMatcher.matches()) { // Return a message with no key or parts. - return new DetailMessage(file, lineNumber, kind, "", ImmutableList.of(), null, null, message); + return new DetailMessage( + file, + input.getLineNumber(), + input.getKind(), + "", + ImmutableList.of(), + null, + null, + input.getMessage()); } int messagePartCount = parseInt(detailsMatcher.group("messagePartCount")); @@ -112,8 +95,8 @@ final class DetailMessage extends TestDiagnostic { return new DetailMessage( file, - lineNumber, - kind, + input.getLineNumber(), + input.getKind(), detailsMatcher.group("messageKey"), messageArguments, intOrNull(offsetsMatcher.group("start")), @@ -127,16 +110,14 @@ private static Integer intOrNull(String input) { private DetailMessage( Path file, - int lineNumber, + long lineNumber, DiagnosticKind diagnosticKind, String messageKey, ImmutableList messageArguments, Integer offsetStart, Integer offsetEnd, String readableMessage) { - super(file.toString(), lineNumber, diagnosticKind, readableMessage, false, true); - this.file = file; - this.lineNumber = lineNumber; + super(file, lineNumber, diagnosticKind, readableMessage, false); this.messageKey = messageKey; this.messageArguments = messageArguments; this.offsetStart = offsetStart; @@ -144,11 +125,6 @@ private DetailMessage( this.readableMessage = readableMessage; } - /** The last part of the {@link #file}. */ - String getFileName() { - return file.getFileName().toString(); - } - /** * True if this was parsed from an actual {@code -Adetailedmsgtext} message; false if this was * some other diagnostic. @@ -183,7 +159,7 @@ public int hashCode() { @Override public String toString() { - return String.format("%s:%d: (%s) %s", file, lineNumber, messageKey, readableMessage); + return String.format("%s:%d:%s: (%s) %s", file, lineNumber, kind, messageKey, readableMessage); } /** String format for debugging use. */ @@ -191,6 +167,7 @@ String toDetailedString() { return toStringHelper(this) .add("file", file) .add("lineNumber", lineNumber) + .add("kind", kind) .add("messageKey", messageKey) .add("messageArguments", messageArguments) .add("offsetStart", offsetStart) diff --git a/src/test/java/tests/NullSpecTest.java b/src/test/java/tests/NullSpecTest.java index 500e6f4..f5ca17e 100644 --- a/src/test/java/tests/NullSpecTest.java +++ b/src/test/java/tests/NullSpecTest.java @@ -41,6 +41,18 @@ public static String[] getTestDirs() { } } + /** A small set of regression tests. */ + public static class Regression extends NullSpecTest { + public Regression(List testFiles) { + super(testFiles, false); + } + + @Parameters + public static String[] getTestDirs() { + return new String[] {"regression"}; + } + } + /** A test that ignores cases where there is limited nullness information. */ public static class Lenient extends NullSpecTest { public Lenient(List testFiles) { @@ -105,8 +117,8 @@ public TypecheckResult adjustTypecheckResult(TypecheckResult testResult) { for (ListIterator i = unexpected.listIterator(); i.hasNext(); ) { TestDiagnostic diagnostic = i.next(); - DetailMessage detailMessage = DetailMessage.parse(diagnostic.getMessage(), null); - if (detailMessage != null && detailMessage.hasDetails()) { + DetailMessage detailMessage = DetailMessage.parse(diagnostic, null); + if (detailMessage.hasDetails()) { // Replace diagnostics that can be parsed with DetailMessage diagnostics. i.set(detailMessage); } else if (diagnostic.getKind() != DiagnosticKind.Error) { @@ -145,8 +157,8 @@ private boolean corresponds(TestDiagnostic missing, TestDiagnostic unexpected) { */ private boolean corresponds(TestDiagnostic missing, DetailMessage unexpected) { // First, make sure the two diagnostics are on the same file and line. - if (!missing.getFilename().equals(unexpected.getFileName()) - || missing.getLineNumber() != unexpected.lineNumber) { + if (!missing.getFilename().equals(unexpected.getFilename()) + || missing.getLineNumber() != unexpected.getLineNumber()) { return false; }