Search in sources :

Example 1 with APIOptionGroup

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);
    }
}
Also used : APIOptionGroup(com.oracle.svm.core.option.APIOptionGroup)

Example 2 with APIOptionGroup

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 */
    }
}
Also used : ArrayList(java.util.ArrayList) Field(java.lang.reflect.Field) Function(java.util.function.Function) APIOptionGroup(com.oracle.svm.core.option.APIOptionGroup) HostedOptionKey(com.oracle.svm.core.option.HostedOptionKey) APIOption(com.oracle.svm.core.option.APIOption) ReflectionUtilError(com.oracle.svm.util.ReflectionUtil.ReflectionUtilError)

Aggregations

APIOptionGroup (com.oracle.svm.core.option.APIOptionGroup)2 APIOption (com.oracle.svm.core.option.APIOption)1 HostedOptionKey (com.oracle.svm.core.option.HostedOptionKey)1 ReflectionUtilError (com.oracle.svm.util.ReflectionUtil.ReflectionUtilError)1 Field (java.lang.reflect.Field)1 ArrayList (java.util.ArrayList)1 Function (java.util.function.Function)1