mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-23 01:21:42 +00:00
CoroutineYieldInLoopDetector
This checks for while loops where coroutines are in scope but without calling a blocking method on at least one of those coroutines:
```
drivetrain.run(theCoroutine -> {
while (drivetrain.getDistance() < 10) { // ERROR: "Missing call to `theCoroutine.yield()` inside loop"
drivetrain.setSpeed(1);
}
});
```
Note that, because we assume most looping constructs in commands will use while loops, we don't check for-loops, for-each loops, or do-while loops.
This check can be disabled with `@SuppressWarnings("CoroutineYieldInLoop")`
CodeAfterCoroutineParkDetector
Essentially acts like the Java compiler's check for code after a while (true) loop, but for coroutine.park():
```
drivetrain.run(theCoroutine -> {
drivetrain.setSpeed(1.0);
theCoroutine.park();
drivetrain.setSpeed(0.0); // ERROR: "Unreachable statement: `theCoroutine.park()` will never exit"
});
```
This check can be disabled with `@SuppressWarnings("CodeAfterCoroutinePark")`
IncorrectCoroutineUseDetector
Checks for usage of captured (outer) coroutine parameters and assignments to fields.
```
drivetrain.run(outer -> {
outer.await(arm.run(inner -> {
outer.yield(); // ERROR: "Coroutine `outer` may not be in scope. Consider using `inner`"
}))
});
```
This check can be disabled with `@SuppressWarnings("CoroutineMayNotBeInScope")`
```
private Coroutine coroutineField;
drivetrain.run(co -> coroutineField = co); // ERROR: "Captured coroutines may not be stored in fields"
```
This check can be disabled with `@SuppressWarnings("CoroutineCapture")`
49 lines
1.6 KiB
Java
49 lines
1.6 KiB
Java
// Copyright (c) FIRST and other WPILib contributors.
|
|
// Open Source Software; you can modify and/or share it under the terms of
|
|
// the WPILib BSD license file in the root directory of this project.
|
|
|
|
package org.wpilib.javacplugin;
|
|
|
|
import java.io.IOException;
|
|
import java.util.List;
|
|
import javax.tools.Diagnostic;
|
|
import javax.tools.JavaFileObject;
|
|
|
|
public final class CompileTestUtils {
|
|
public static final int kJavaVersion = 17;
|
|
public static final List<Object> kJavaVersionOptions =
|
|
List.of("-source", kJavaVersion, "-target", kJavaVersion);
|
|
|
|
private CompileTestUtils() {
|
|
// Utility class
|
|
}
|
|
|
|
/**
|
|
* Gets the source code for a given compiler error.
|
|
*
|
|
* @param diagnostic The diagnostic to get the source for.
|
|
* @return The source code for the given diagnostic.
|
|
*/
|
|
public static String getErrorSource(Diagnostic<? extends JavaFileObject> diagnostic) {
|
|
try (var reader = diagnostic.getSource().openReader(true)) {
|
|
int sourceLength = (int) (diagnostic.getEndPosition() - diagnostic.getStartPosition() + 1);
|
|
char[] buf = new char[sourceLength];
|
|
long skipCnt = reader.skip(diagnostic.getStartPosition());
|
|
if (skipCnt != diagnostic.getStartPosition()) {
|
|
// Didn't skip to the expected position; bail
|
|
return "<unknown source>";
|
|
}
|
|
|
|
int readCnt = reader.read(buf);
|
|
if (readCnt != sourceLength) {
|
|
// Didn't read the expected length of text; bail
|
|
return "<unknown source>";
|
|
}
|
|
|
|
return new String(buf);
|
|
} catch (IOException e) {
|
|
return "<unknown source>";
|
|
}
|
|
}
|
|
}
|