use of com.google.errorprone.annotations.Var in project java-common-lib by sosy-lab.
the class OptionAnnotationProcessor method processOptions.
/**
* Checks constraints for {@link Options} annotations. This contains:
*
* <ul>
* <li>Only classes are allowed to be annotated.
* <li>Non-private constructors without a Configuration parameter produce a warning (maybe
* injection was forgotten?).
* <li>{@link Options} is irrelevant without at least one {link Option}.
* </ul>
*/
private void processOptions(Element elem) {
if (elem.getKind() != ElementKind.CLASS) {
message(ERROR, elem, Options.class, "@Options annotation can only be used on classes.");
return;
}
TypeElement element = (TypeElement) elem;
// Private classes and constructors are ignored, these are often used for tests.
if (!element.getModifiers().contains(Modifier.PRIVATE)) {
List<ExecutableElement> constructors = constructorsIn(element.getEnclosedElements());
for (ExecutableElement constructor : constructors) {
if (constructor.getModifiers().contains(Modifier.PRIVATE)) {
continue;
}
if (constructor.getParameters().isEmpty() && constructors.size() == 1) {
// but I do not know how to detect them.
continue;
}
boolean foundConfigurationParameter = constructor.getParameters().stream().anyMatch((param) -> param.asType().toString().equals(Configuration.class.getName()));
if (!foundConfigurationParameter && warningsEnabled(constructor)) {
message(WARNING, constructor, "Constructor does not receive Configuration instance" + " and may not be able to inject configuration options of this class.");
}
}
}
// check if there is any @Option inside or in its super classes (for recursive inject)
@Var boolean foundOption = false;
@Var TypeElement currentClass = element;
do {
if (hasChildWithAnnotation(currentClass, Option.class)) {
foundOption = true;
break;
}
currentClass = (TypeElement) ((DeclaredType) currentClass.getSuperclass()).asElement();
} while (currentClass.getSuperclass().getKind() != TypeKind.NONE);
if (!foundOption && warningsEnabled(element)) {
message(WARNING, element, Options.class, "@Options annotation on class without @Option fields or methods is useless.");
}
}
use of com.google.errorprone.annotations.Var in project java-common-lib by sosy-lab.
the class OptionAnnotationProcessor method getRawTypeName.
/**
* Given a TypeMirror representing some type, this method produces a String representation of the
* raw type. It also eliminates primitive types by boxing them.
*/
private String getRawTypeName(TypeMirror t) {
@Var TypeMirror type = typeUtils().erasure(t);
if (type.getKind().isPrimitive()) {
type = typeUtils().boxedClass((PrimitiveType) type).asType();
}
@Var String typeName = type.toString();
// Unfortunately, there is an Eclipse bug in the erasure() method called above:
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=340635
// We have to get the raw type ourselves:
int i = typeName.indexOf('<');
if (i > 0) {
typeName = typeName.substring(0, i);
}
return typeName;
}
use of com.google.errorprone.annotations.Var in project java-common-lib by sosy-lab.
the class Parser method parse.
/**
* Parse a configuration file given as a {@link BufferedReader} with the format as defined above.
*
* <p>The reader is left open after this method returns. This method may additionally access more
* files from the file system if they are included.
*
* @param r The reader to read the file from.
* @param basePath If #include filenames are relative, resolve them as sibling of basePath. Source
* must not contain #include if absent.
* @param source A string to use as source of the file in error messages (this should usually be a
* filename or something similar).
* @throws IOException If an I/O error occurs.
* @throws InvalidConfigurationException If the configuration file has an invalid format.
*/
@SuppressFBWarnings(value = "SBSC_USE_STRINGBUFFER_CONCATENATION", justification = "performance irrelevant compared to I/O, String much more convenient")
private void parse(BufferedReader r, Optional<Path> basePath, String source) throws IOException, InvalidConfigurationException {
checkNotNull(basePath);
checkNotNull(source);
@Var String line;
@Var int lineno = 0;
@Var String currentPrefix = "";
@Var String currentOptionName = null;
@Var String currentValue = null;
Map<String, String> definedOptions = new HashMap<>();
while ((line = r.readLine()) != null) {
lineno++;
line = line.trim();
String fullLine = line;
assert (currentValue == null) == (currentOptionName == null);
if (currentValue != null) {
// we are in the continuation of a key = value pair
currentValue += line;
// no continue here, we need to run the code at the end of the loop body
} else if (line.isEmpty() || line.equals("#") || line.startsWith("# ") || line.startsWith("//")) {
// empty or comment
continue;
} else if (line.startsWith("#")) {
if (!line.startsWith("#include")) {
throw new InvalidConfigurationFileException("Illegal parser directive", lineno, source, fullLine);
}
line = line.substring("#include".length()).trim();
if (line.isEmpty()) {
throw new InvalidConfigurationFileException("Include without filename", lineno, source, fullLine);
}
checkArgument(basePath.isPresent(), "File %s contains #include directive, but base path not given.", source);
// parse included file (content will be in fields of this class)
parse0(basePath.get().resolveSibling(Paths.get(line)));
continue;
} else if (line.startsWith("[") && line.endsWith("]")) {
// category
line = line.substring(1, line.length() - 1);
line = line.trim();
if (line.isEmpty()) {
// this is allowed, it clears the prefix
currentPrefix = "";
} else if (!OPTION_NAME.matcher(line).matches()) {
throw new InvalidConfigurationFileException("Invalid category \"" + line + "\"", lineno, source, fullLine);
} else {
currentPrefix = line + ".";
}
continue;
} else if (line.length() < 3) {
throw new InvalidConfigurationFileException("Illegal content", lineno, source, fullLine);
} else {
// normal key=value line
String[] bits = line.split("=", 2);
if (bits.length != 2) {
throw new InvalidConfigurationFileException("Missing key-value separator", lineno, source, fullLine);
}
currentOptionName = bits[0].trim();
if (!OPTION_NAME.matcher(currentOptionName).matches()) {
throw new InvalidConfigurationFileException("Invalid option \"" + currentOptionName + "\"", lineno, source, fullLine);
}
if (definedOptions.containsKey(currentPrefix + currentOptionName)) {
throw new InvalidConfigurationFileException("Duplicate option \"" + currentPrefix + currentOptionName + "\"", lineno, source, fullLine);
}
currentValue = bits[1].trim();
}
assert (currentValue != null) && (currentOptionName != null);
if (currentValue.endsWith("\\")) {
// continuation
currentValue = currentValue.substring(0, currentValue.length() - 1);
} else {
definedOptions.put(currentPrefix + currentOptionName, currentValue);
currentValue = null;
currentOptionName = null;
}
}
assert (currentValue == null) == (currentOptionName == null);
if (currentValue != null) {
definedOptions.put(currentPrefix + currentOptionName, currentValue);
}
// now overwrite included options with local ones
options.putAll(definedOptions);
Path thisSource = Paths.get(source);
for (String name : definedOptions.keySet()) {
sources.put(name, thisSource);
}
}
use of com.google.errorprone.annotations.Var in project java-common-lib by sosy-lab.
the class RationalTest method testInstantiationBigDecimal.
@Test
public void testInstantiationBigDecimal() {
@Var BigDecimal a = BigDecimal.valueOf(1, 3);
assertThat(Rational.ofBigDecimal(a)).isEqualTo(Rational.of("1/1000"));
a = BigDecimal.valueOf(1, -4);
assertThat(Rational.ofBigDecimal(a)).isEqualTo(Rational.of("10000"));
}
use of com.google.errorprone.annotations.Var in project java-common-lib by sosy-lab.
the class TimeSpan method multiply.
/**
* Create a new time span that is the current one multiplied by a non-negative integral factor.
* The unit of the returned time span is the same as the current one if possible, otherwise the
* closest unit that still allows to the result. Note that this can loose precision.
*/
@CheckReturnValue
public TimeSpan multiply(int factor) {
checkArgument(factor >= 0, "Cannot multiply TimeSpan with negative value %s", factor);
@Var TimeUnit dest = unit;
while (true) {
try {
return new TimeSpan(LongMath.checkedMultiply(getChecked(dest), factor), dest);
} catch (ArithmeticException e) {
// Overflow is expected to be very rare, thus handle exception case instead of checking.
// Try again with next unit.
dest = ALL_UNITS.higher(dest);
if (dest == null) {
// overflow from multiplication
throw e;
}
}
}
}
Aggregations