use of com.oracle.svm.core.option.APIOptionGroup in project graal by oracle.
the class APIOptionFeature method printGroupOption.
private static void printGroupOption(Consumer<String> println, String groupName, List<OptionInfo> options) {
APIOptionGroup group = options.get(0).group;
assert group != null;
StringBuilder sb = new StringBuilder();
sb.append(startLowerCase(group.helpText()));
if (!group.helpText().endsWith(".")) {
sb.append(".");
}
sb.append(" Allowed options for <value>:");
SubstrateOptionsParser.printOption(println, groupName + "<value>", sb.toString(), 4, 22, 66);
for (OptionInfo groupEntry : options) {
assert groupEntry.group == group;
sb.setLength(0);
boolean first = true;
boolean isDefault = false;
for (String variant : groupEntry.variants) {
if (variant.equals(groupEntry.defaultValue)) {
isDefault = true;
}
if (first) {
first = false;
} else {
sb.append(" | ");
}
sb.append("'").append(variant).append("'");
}
sb.append(": ").append(groupEntry.helpText);
if (isDefault) {
sb.append(" (default)");
}
SubstrateOptionsParser.printOption(println, "", sb.toString(), 4, 22, 66);
}
}
use of com.oracle.svm.core.option.APIOptionGroup in project graal by oracle.
the class APIOptionFeature method extractOption.
private static void extractOption(String optionPrefix, OptionDescriptor optionDescriptor, SortedMap<String, OptionInfo> apiOptions, Map<String, GroupInfo> groupInfos, Map<Class<? extends APIOptionGroup>, APIOptionGroup> groupInstances) {
try {
Field optionField = optionDescriptor.getDeclaringClass().getDeclaredField(optionDescriptor.getFieldName());
APIOption[] apiAnnotations = optionField.getAnnotationsByType(APIOption.class);
for (APIOption apiAnnotation : apiAnnotations) {
String builderOption = optionPrefix;
if (apiAnnotation.name().length <= 0) {
VMError.shouldNotReachHere(String.format("APIOption for %s does not provide a name entry", optionDescriptor.getLocation()));
}
String apiOptionName = APIOption.Utils.optionName(apiAnnotation.name()[0]);
String rawOptionName = optionDescriptor.getName();
APIOptionGroup group = null;
String defaultValue = null;
boolean booleanOption = false;
Class<?> optionValueType = optionDescriptor.getOptionValueType();
if (optionValueType.isArray()) {
VMError.guarantee(optionDescriptor.getOptionKey() instanceof HostedOptionKey, "Only HostedOptionKeys are allowed to have array type key values.");
optionValueType = optionValueType.getComponentType();
}
boolean hasFixedValue = apiAnnotation.fixedValue().length > 0;
if (optionValueType.equals(Boolean.class)) {
if (!apiAnnotation.group().equals(APIOption.NullGroup.class)) {
try {
Class<? extends APIOptionGroup> groupClass = apiAnnotation.group();
APIOptionGroup g = group = groupInstances.computeIfAbsent(groupClass, ReflectionUtil::newInstance);
String groupName = APIOption.Utils.groupName(group);
GroupInfo groupInfo = groupInfos.computeIfAbsent(groupName, (n) -> new GroupInfo(g));
if (group.helpText() == null || group.helpText().isEmpty()) {
VMError.shouldNotReachHere(String.format("APIOptionGroup %s(%s) needs to provide help text", groupClass.getName(), group.name()));
}
String groupMember = apiAnnotation.name()[0];
groupInfo.supportedValues.add(groupMember);
apiOptionName = groupName + groupMember;
Boolean isEnabled = (Boolean) optionDescriptor.getOptionKey().getDefaultValue();
if (isEnabled) {
groupInfo.defaultValues.add(groupMember);
/* Use OptionInfo.defaultValue to remember group default value */
defaultValue = groupMember;
}
} catch (ReflectionUtilError ex) {
throw VMError.shouldNotReachHere("Class specified as group for @APIOption " + apiOptionName + " cannot be loaded or instantiated: " + apiAnnotation.group().getTypeName(), ex.getCause());
}
}
if (apiAnnotation.kind().equals(APIOptionKind.Paths)) {
VMError.shouldNotReachHere(String.format("Boolean APIOption %s(%s) cannot use APIOptionKind.Paths", apiOptionName, rawOptionName));
}
if (apiAnnotation.defaultValue().length > 0) {
VMError.shouldNotReachHere(String.format("Boolean APIOption %s(%s) cannot use APIOption.defaultValue", apiOptionName, rawOptionName));
}
if (hasFixedValue) {
VMError.shouldNotReachHere(String.format("Boolean APIOption %s(%s) cannot use APIOption.fixedValue", apiOptionName, rawOptionName));
}
builderOption += apiAnnotation.kind().equals(APIOptionKind.Negated) ? "-" : "+";
builderOption += rawOptionName;
booleanOption = true;
} else {
if (!apiAnnotation.group().equals(APIOption.NullGroup.class)) {
VMError.shouldNotReachHere(String.format("Using @APIOption.group not supported for non-boolean APIOption %s(%s)", apiOptionName, rawOptionName));
}
if (apiAnnotation.kind().equals(APIOptionKind.Negated)) {
VMError.shouldNotReachHere(String.format("Non-boolean APIOption %s(%s) cannot use APIOptionKind.Negated", apiOptionName, rawOptionName));
}
if (apiAnnotation.defaultValue().length > 1) {
VMError.shouldNotReachHere(String.format("APIOption %s(%s) cannot have more than one APIOption.defaultValue", apiOptionName, rawOptionName));
}
if (apiAnnotation.fixedValue().length > 1) {
VMError.shouldNotReachHere(String.format("APIOption %s(%s) cannot have more than one APIOption.fixedValue", apiOptionName, rawOptionName));
}
if (hasFixedValue && apiAnnotation.defaultValue().length > 0) {
VMError.shouldNotReachHere(String.format("APIOption %s(%s) APIOption.defaultValue and APIOption.fixedValue cannot be combined", apiOptionName, rawOptionName));
}
if (apiAnnotation.defaultValue().length > 0) {
defaultValue = apiAnnotation.defaultValue()[0];
}
if (hasFixedValue) {
defaultValue = apiAnnotation.fixedValue()[0];
}
builderOption += rawOptionName;
builderOption += "=";
}
String helpText = optionDescriptor.getHelp();
if (!apiAnnotation.customHelp().isEmpty()) {
helpText = apiAnnotation.customHelp();
}
if (helpText == null || helpText.isEmpty()) {
VMError.shouldNotReachHere(String.format("APIOption %s(%s) needs to provide help text", apiOptionName, rawOptionName));
}
if (group == null) {
/* Regular help text needs to start with lower-case letter */
helpText = startLowerCase(helpText);
}
List<Function<Object, Object>> valueTransformers = new ArrayList<>(apiAnnotation.valueTransformer().length);
for (Class<? extends Function<Object, Object>> transformerClass : apiAnnotation.valueTransformer()) {
try {
valueTransformers.add(ReflectionUtil.newInstance(transformerClass));
} catch (ReflectionUtilError ex) {
throw VMError.shouldNotReachHere("Class specified as valueTransformer for @APIOption " + apiOptionName + " cannot be loaded or instantiated: " + transformerClass.getTypeName(), ex.getCause());
}
}
if (apiAnnotation.valueSeparator().length == 0) {
throw VMError.shouldNotReachHere(String.format("APIOption %s(%s) does not specify any valueSeparator", apiOptionName, rawOptionName));
}
for (char valueSeparator : apiAnnotation.valueSeparator()) {
if (valueSeparator == APIOption.WHITESPACE_SEPARATOR) {
String msgTail = " cannot use APIOption.WHITESPACE_SEPARATOR as value separator";
if (booleanOption) {
throw VMError.shouldNotReachHere(String.format("Boolean APIOption %s(%s)" + msgTail, apiOptionName, rawOptionName));
}
if (hasFixedValue) {
VMError.shouldNotReachHere(String.format("APIOption %s(%s) with fixed value" + msgTail, apiOptionName, rawOptionName));
}
if (defaultValue != null) {
VMError.shouldNotReachHere(String.format("APIOption %s(%s) with default value" + msgTail, apiOptionName, rawOptionName));
}
}
}
boolean defaultFinal = booleanOption || hasFixedValue;
apiOptions.put(apiOptionName, new APIOptionHandler.OptionInfo(apiAnnotation.name(), apiAnnotation.valueSeparator(), builderOption, defaultValue, helpText, apiAnnotation.kind().equals(APIOptionKind.Paths), defaultFinal, apiAnnotation.deprecated(), valueTransformers, group, apiAnnotation.extra()));
}
} catch (NoSuchFieldException e) {
/* Does not qualify as APIOption */
}
}
Aggregations