// Copyright 2014 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.devtools.common.options;

import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.devtools.common.options.OptionsParser.OptionDescription;
import com.google.devtools.common.options.OptionsParser.OptionValueDescription;
import com.google.devtools.common.options.OptionsParser.UnparsedOptionValueDescription;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * The implementation of the options parser. This is intentionally package
 * private for full flexibility. Use {@link OptionsParser} or {@link Options}
 * if you're a consumer.
 */
class OptionsParserImpl {

  /**
   * A bunch of default converters in case the user doesn't specify a
   * different one in the field annotation.
   */
  static final Map<Class<?>, Converter<?>> DEFAULT_CONVERTERS = Maps.newHashMap();

  static {
    DEFAULT_CONVERTERS.put(String.class, new Converter<String>() {
      @Override
      public String convert(String input) {
        return input;
      }
      @Override
      public String getTypeDescription() {
        return "a string";
      }});
    DEFAULT_CONVERTERS.put(int.class, new Converter<Integer>() {
      @Override
      public Integer convert(String input) throws OptionsParsingException {
        try {
          return Integer.decode(input);
        } catch (NumberFormatException e) {
          throw new OptionsParsingException("'" + input + "' is not an int");
        }
      }
      @Override
      public String getTypeDescription() {
        return "an integer";
      }});
    DEFAULT_CONVERTERS.put(double.class, new Converter<Double>() {
      @Override
      public Double convert(String input) throws OptionsParsingException {
        try {
          return Double.parseDouble(input);
        } catch (NumberFormatException e) {
          throw new OptionsParsingException("'" + input + "' is not a double");
        }
      }
      @Override
      public String getTypeDescription() {
        return "a double";
      }});
    DEFAULT_CONVERTERS.put(boolean.class, new Converters.BooleanConverter());
    DEFAULT_CONVERTERS.put(TriState.class, new Converter<TriState>() {
      @Override
      public TriState convert(String input) throws OptionsParsingException {
        if (input == null) {
          return TriState.AUTO;
        }
        input = input.toLowerCase();
        if (input.equals("auto")) {
          return TriState.AUTO;
        }
        if (input.equals("true") || input.equals("1") || input.equals("yes") ||
            input.equals("t") || input.equals("y")) {
          return TriState.YES;
        }
        if (input.equals("false") || input.equals("0") || input.equals("no") ||
            input.equals("f") || input.equals("n")) {
          return TriState.NO;
        }
        throw new OptionsParsingException("'" + input + "' is not a boolean");
      }
      @Override
      public String getTypeDescription() {
        return "a tri-state (auto, yes, no)";
      }});
    DEFAULT_CONVERTERS.put(Void.class, new Converter<Void>() {
      @Override
      public Void convert(String input) throws OptionsParsingException {
        if (input == null) {
          return null;  // expected input, return is unused so null is fine.
        }
        throw new OptionsParsingException("'" + input + "' unexpected");
      }
      @Override
      public String getTypeDescription() {
        return "";
      }});
    DEFAULT_CONVERTERS.put(long.class, new Converter<Long>() {
      @Override
      public Long convert(String input) throws OptionsParsingException {
        try {
          return Long.decode(input);
        } catch (NumberFormatException e) {
          throw new OptionsParsingException("'" + input + "' is not a long");
        }
      }
      @Override
      public String getTypeDescription() {
        return "a long integer";
      }});
  }

  /**
   * For every value, this class keeps track of its priority, its free-form source
   * description, whether it was set as an implicit dependency, and the value.
   */
  private static final class ParsedOptionEntry {
    private final Object value;
    private final OptionPriority priority;
    private final String source;
    private final String implicitDependant;
    private final String expandedFrom;
    private final boolean allowMultiple;

    ParsedOptionEntry(Object value,
        OptionPriority priority, String source, String implicitDependant, String expandedFrom,
        boolean allowMultiple) {
      this.value = value;
      this.priority = priority;
      this.source = source;
      this.implicitDependant = implicitDependant;
      this.expandedFrom = expandedFrom;
      this.allowMultiple = allowMultiple;
    }

    // Need to suppress unchecked warnings, because the "multiple occurrence"
    // options use unchecked ListMultimaps due to limitations of Java generics.
    @SuppressWarnings({"unchecked", "rawtypes"})
    Object getValue() {
      if (allowMultiple) {
        // Sort the results by option priority and return them in a new list.
        // The generic type of the list is not known at runtime, so we can't
        // use it here. It was already checked in the constructor, so this is
        // type-safe.
        List result = Lists.newArrayList();
        ListMultimap realValue = (ListMultimap) value;
        for (OptionPriority priority : OptionPriority.values()) {
          // If there is no mapping for this key, this check avoids object creation (because
          // ListMultimap has to return a new object on get) and also an unnecessary addAll call.
          if (realValue.containsKey(priority)) {
            result.addAll(realValue.get(priority));
          }
        }
        return result;
      }
      return value;
    }

    // Need to suppress unchecked warnings, because the "multiple occurrence"
    // options use unchecked ListMultimaps due to limitations of Java generics.
    @SuppressWarnings({"unchecked", "rawtypes"})
    void addValue(OptionPriority addedPriority, Object addedValue) {
      Preconditions.checkState(allowMultiple);
      ListMultimap optionValueList = (ListMultimap) value;
      if (addedValue instanceof List<?>) {
        for (Object element : (List<?>) addedValue) {
          optionValueList.put(addedPriority, element);
        }
      } else {
        optionValueList.put(addedPriority, addedValue);
      }
    }

    OptionValueDescription asOptionValueDescription(String fieldName) {
      return new OptionValueDescription(fieldName, getValue(), priority,
          source, implicitDependant, expandedFrom);
    }
  }

  private final OptionsData optionsData;

  /**
   * We store the results of parsing the arguments in here. It'll look like
   * <pre>
   *   Field("--host") -> "www.google.com"
   *   Field("--port") -> 80
   * </pre>
   * This map is modified by repeated calls to
   * {@link #parse(OptionPriority,Function,List)}.
   */
  private final Map<Field, ParsedOptionEntry> parsedValues = Maps.newHashMap();

  /**
   * We store the pre-parsed, explicit options for each priority in here.
   * We use partially preparsed options, which can be different from the original
   * representation, e.g. "--nofoo" becomes "--foo=0".
   */
  private final List<UnparsedOptionValueDescription> unparsedValues = Lists.newArrayList();

  /**
   * Unparsed values for use with the canonicalize command are stored separately from
   * unparsedValues so that invocation policy can modify the values for canonicalization (e.g.
   * override user-specified values with default values) without corrupting the data used to
   * represent the user's original invocation for {@link #asListOfExplicitOptions()} and
   * {@link #asListOfUnparsedOptions()}. A LinkedHashMultimap is used so that canonicalization
   * happens in the correct order and multiple values can be stored for flags that allow multiple
   * values.
   */
  private final Multimap<Field, UnparsedOptionValueDescription> canonicalizeValues
      = LinkedHashMultimap.create();

  private final List<String> warnings = Lists.newArrayList();

  private boolean allowSingleDashLongOptions = false;
  
  private ArgsPreProcessor argsPreProcessor =
      new ArgsPreProcessor() {
        @Override
        public List<String> preProcess(List<String> args) throws OptionsParsingException {
          return args;
        }
      };
  
  /**
   * Create a new parser object
   */
  OptionsParserImpl(OptionsData optionsData) {
    this.optionsData = optionsData;
  }

  /**
   * Indicates whether or not the parser will allow long options with a
   * single-dash, instead of the usual double-dash, too, eg. -example instead of just --example.
   */
  void setAllowSingleDashLongOptions(boolean allowSingleDashLongOptions) {
    this.allowSingleDashLongOptions = allowSingleDashLongOptions;
  }
  
  /** Sets the ArgsPreProcessor for manipulations of the options before parsing. */
  void setArgsPreProcessor(ArgsPreProcessor preProcessor) {
    this.argsPreProcessor = Preconditions.checkNotNull(preProcessor);
  }

  /**
   * The implementation of {@link OptionsBase#asMap}.
   */
  static Map<String, Object> optionsAsMap(OptionsBase optionsInstance) {
    Map<String, Object> map = Maps.newHashMap();
    for (Field field : OptionsParser.getAllAnnotatedFields(optionsInstance.getClass())) {
      try {
        String name = field.getAnnotation(Option.class).name();
        Object value = field.get(optionsInstance);
        map.put(name, value);
      } catch (IllegalAccessException e) {
        throw new IllegalStateException(e); // unreachable
      }
    }
    return map;
  }

  List<Field> getAnnotatedFieldsFor(Class<? extends OptionsBase> clazz) {
    return optionsData.getFieldsForClass(clazz);
  }

  /**
   * Implements {@link OptionsParser#asListOfUnparsedOptions()}.
   */
  List<UnparsedOptionValueDescription> asListOfUnparsedOptions() {
    List<UnparsedOptionValueDescription> result = Lists.newArrayList(unparsedValues);
    // It is vital that this sort is stable so that options on the same priority are not reordered.
    Collections.sort(result, new Comparator<UnparsedOptionValueDescription>() {
      @Override
      public int compare(UnparsedOptionValueDescription o1,
          UnparsedOptionValueDescription o2) {
        return o1.getPriority().compareTo(o2.getPriority());
      }
    });
    return result;
  }

  /**
   * Implements {@link OptionsParser#asListOfExplicitOptions()}.
   */
  List<UnparsedOptionValueDescription> asListOfExplicitOptions() {
    List<UnparsedOptionValueDescription> result = Lists.newArrayList(Iterables.filter(
      unparsedValues,
      new Predicate<UnparsedOptionValueDescription>() {
        @Override
        public boolean apply(UnparsedOptionValueDescription input) {
          return input.isExplicit();
        }
    }));
    // It is vital that this sort is stable so that options on the same priority are not reordered.
    Collections.sort(result, new Comparator<UnparsedOptionValueDescription>() {
      @Override
      public int compare(UnparsedOptionValueDescription o1,
          UnparsedOptionValueDescription o2) {
        return o1.getPriority().compareTo(o2.getPriority());
      }
    });
    return result;
  }

  /**
   * Implements {@link OptionsParser#canonicalize}.
   */
  List<String> asCanonicalizedList() {

    List<UnparsedOptionValueDescription> processed = Lists.newArrayList(
        canonicalizeValues.values());
    // Sort implicit requirement options to the end, keeping their existing order, and sort the
    // other options alphabetically.
    Collections.sort(processed, new Comparator<UnparsedOptionValueDescription>() {
      @Override
      public int compare(UnparsedOptionValueDescription o1, UnparsedOptionValueDescription o2) {
        if (o1.isImplicitRequirement()) {
          return o2.isImplicitRequirement() ? 0 : 1;
        }
        if (o2.isImplicitRequirement()) {
          return -1;
        }
        return o1.getName().compareTo(o2.getName());
      }
    });

    List<String> result = Lists.newArrayList();
    for (UnparsedOptionValueDescription value : processed) {

      // Ignore expansion options.
      if (value.isExpansion()) {
        continue;
      }

      result.add("--" + value.getName() + "=" + value.getUnparsedValue());
    }
    return result;
  }

  /**
   * Implements {@link OptionsParser#asListOfEffectiveOptions()}.
   */
  List<OptionValueDescription> asListOfEffectiveOptions() {
    List<OptionValueDescription> result = Lists.newArrayList();
    for (Map.Entry<String,Field> mapEntry : optionsData.getAllNamedFields()) {
      String fieldName = mapEntry.getKey();
      Field field = mapEntry.getValue();
      ParsedOptionEntry entry = parsedValues.get(field);
      if (entry == null) {
        Object value = optionsData.getDefaultValue(field);
        result.add(new OptionValueDescription(fieldName, value, OptionPriority.DEFAULT,
            null, null, null));
      } else {
        result.add(entry.asOptionValueDescription(fieldName));
      }
    }
    return result;
  }

  Collection<Class<?  extends OptionsBase>> getOptionsClasses() {
    return optionsData.getOptionsClasses();
  }

  private void maybeAddDeprecationWarning(Field field) {
    Option option = field.getAnnotation(Option.class);
    // Continue to support the old behavior for @Deprecated options.
    String warning = option.deprecationWarning();
    if (!warning.isEmpty() || (field.getAnnotation(Deprecated.class) != null)) {
      addDeprecationWarning(option.name(), warning);
    }
  }

  private void addDeprecationWarning(String optionName, String warning) {
    warnings.add("Option '" + optionName + "' is deprecated"
        + (warning.isEmpty() ? "" : ": " + warning));
  }

  // Warnings should not end with a '.' because the internal reporter adds one automatically.
  private void setValue(Field field, String name, Object value,
      OptionPriority priority, String source, String implicitDependant, String expandedFrom) {
    ParsedOptionEntry entry = parsedValues.get(field);
    if (entry != null) {
      // Override existing option if the new value has higher or equal priority.
      if (priority.compareTo(entry.priority) >= 0) {
        // Output warnings:
        if ((implicitDependant != null) && (entry.implicitDependant != null)) {
          if (!implicitDependant.equals(entry.implicitDependant)) {
            warnings.add("Option '" + name + "' is implicitly defined by both option '" +
                entry.implicitDependant + "' and option '" + implicitDependant + "'");
          }
        } else if ((implicitDependant != null) && priority.equals(entry.priority)) {
          warnings.add("Option '" + name + "' is implicitly defined by option '" +
              implicitDependant + "'; the implicitly set value overrides the previous one");
        } else if (entry.implicitDependant != null) {
          warnings.add("A new value for option '" + name + "' overrides a previous " +
              "implicit setting of that option by option '" + entry.implicitDependant + "'");
        } else if ((priority == entry.priority) &&
            ((entry.expandedFrom == null) && (expandedFrom != null))) {
          // Create a warning if an expansion option overrides an explicit option:
          warnings.add("The option '" + expandedFrom + "' was expanded and now overrides a "
              + "previous explicitly specified option '" + name + "'");
        }

        // Record the new value:
        parsedValues.put(field,
            new ParsedOptionEntry(value, priority, source, implicitDependant, expandedFrom, false));
      }
    } else {
      parsedValues.put(field,
          new ParsedOptionEntry(value, priority, source, implicitDependant, expandedFrom, false));
      maybeAddDeprecationWarning(field);
    }
  }

  private void addListValue(Field field, Object value, OptionPriority priority, String source,
      String implicitDependant, String expandedFrom) {
    ParsedOptionEntry entry = parsedValues.get(field);
    if (entry == null) {
      entry = new ParsedOptionEntry(ArrayListMultimap.create(), priority, source,
          implicitDependant, expandedFrom, true);
      parsedValues.put(field, entry);
      maybeAddDeprecationWarning(field);
    }
    entry.addValue(priority, value);
  }

  void clearValue(String optionName, Map<String, OptionValueDescription> clearedValues)
      throws OptionsParsingException {
    Field field = optionsData.getFieldFromName(optionName);
    if (field == null) {
      throw new IllegalArgumentException("No such option '" + optionName + "'");
    }
    Option option = field.getAnnotation(Option.class);
    clearValue(field, option, clearedValues);
  }

  private void clearValue(
      Field field, Option option, Map<String, OptionValueDescription> clearedValues)
      throws OptionsParsingException {

    ParsedOptionEntry removed = parsedValues.remove(field);
    if (removed != null) {
      clearedValues.put(option.name(), removed.asOptionValueDescription(option.name()));
    }

    canonicalizeValues.removeAll(field);

    // Recurse to remove any implicit or expansion flags that this flag may have added when
    // originally parsed.
    for (String[] args : new String[][] {option.implicitRequirements(), option.expansion()}) {
      Iterator<String> argsIterator = Iterators.forArray(args);
      while (argsIterator.hasNext()) {
        String arg = argsIterator.next();
        ParseOptionResult parseOptionResult = parseOption(arg, argsIterator);
        clearValue(parseOptionResult.field, parseOptionResult.option, clearedValues);
      }
    }
  }

  OptionValueDescription getOptionValueDescription(String name) {
    Field field = optionsData.getFieldFromName(name);
    if (field == null) {
      throw new IllegalArgumentException("No such option '" + name + "'");
    }
    ParsedOptionEntry entry = parsedValues.get(field);
    if (entry == null) {
      return null;
    }
    return entry.asOptionValueDescription(name);
  }

  OptionDescription getOptionDescription(String name) {
    Field field = optionsData.getFieldFromName(name);
    if (field == null) {
      return null;
    }

    Option optionAnnotation = field.getAnnotation(Option.class);
    return new OptionDescription(
        name,
        optionsData.getDefaultValue(field),
        optionsData.getConverter(field),
        optionAnnotation.allowMultiple());
  }

  boolean containsExplicitOption(String name) {
    Field field = optionsData.getFieldFromName(name);
    if (field == null) {
      throw new IllegalArgumentException("No such option '" + name + "'");
    }
    return parsedValues.get(field) != null;
  }

  /**
   * Parses the args, and returns what it doesn't parse. May be called multiple
   * times, and may be called recursively. In each call, there may be no
   * duplicates, but separate calls may contain intersecting sets of options; in
   * that case, the arg seen last takes precedence.
   */
  List<String> parse(OptionPriority priority, Function<? super String, String> sourceFunction,
      List<String> args) throws OptionsParsingException {
    return parse(priority, sourceFunction, null, null, args);
  }

  /**
   * Parses the args, and returns what it doesn't parse. May be called multiple
   * times, and may be called recursively. Calls may contain intersecting sets
   * of options; in that case, the arg seen last takes precedence.
   *
   * <p>The method uses the invariant that if an option has neither an implicit
   * dependent nor an expanded from value, then it must have been explicitly
   * set.
   */
  private List<String> parse(
      OptionPriority priority,
      Function<? super String, String> sourceFunction,
      String implicitDependent,
      String expandedFrom,
      List<String> args) throws OptionsParsingException {

    List<String> unparsedArgs = Lists.newArrayList();
    LinkedHashMap<String,List<String>> implicitRequirements = Maps.newLinkedHashMap();

    Iterator<String> argsIterator = argsPreProcessor.preProcess(args).iterator();
    while (argsIterator.hasNext()) {
      String arg = argsIterator.next();

      if (!arg.startsWith("-")) {
        unparsedArgs.add(arg);
        continue;  // not an option arg
      }

      if (arg.equals("--")) {  // "--" means all remaining args aren't options
        Iterators.addAll(unparsedArgs, argsIterator);
        break;
      }

      ParseOptionResult optionParseResult = parseOption(arg, argsIterator);
      Field field = optionParseResult.field;
      Option option = optionParseResult.option;
      String value = optionParseResult.value;

      final String originalName = option.name();

      if (option.wrapperOption()) {
        if (value.startsWith("-")) {

          List<String> unparsed = parse(
              priority,
              Functions.constant("Unwrapped from wrapper option --" + originalName),
              null, // implicitDependent
              null, // expandedFrom
              ImmutableList.of(value));

          if (!unparsed.isEmpty()) {
            throw new OptionsParsingException("Unparsed options remain after unwrapping " +
              arg + ": " + Joiner.on(' ').join(unparsed));
          }

          // Don't process implicitRequirements or expansions for wrapper options. In particular,
          // don't record this option in unparsedValues, so that only the wrapped option shows
          // up in canonicalized options.
          continue;

        } else {
          throw new OptionsParsingException("Invalid --" + originalName + " value format. "
              + "You may have meant --" + originalName + "=--" + value);
        }
      }

      if (implicitDependent == null) {
        // Log explicit options and expanded options in the order they are parsed (can be sorted
        // later). Also remember whether they were expanded or not. This information is needed to
        // correctly canonicalize flags.
        UnparsedOptionValueDescription unparsedOptionValueDescription =
            new UnparsedOptionValueDescription(
                originalName,
                field,
                value,
                priority,
                sourceFunction.apply(originalName),
                expandedFrom == null);
        unparsedValues.add(unparsedOptionValueDescription);
        if (option.allowMultiple()) {
          canonicalizeValues.put(field, unparsedOptionValueDescription);
        } else {
          canonicalizeValues.replaceValues(field, ImmutableList.of(unparsedOptionValueDescription));
        }
      }

      // Handle expansion options.
      if (option.expansion().length > 0) {
        Function<Object, String> expansionSourceFunction = Functions.<String>constant(
            "expanded from option --" + originalName + " from " +
            sourceFunction.apply(originalName));
        maybeAddDeprecationWarning(field);
        List<String> unparsed = parse(priority, expansionSourceFunction, null, originalName,
            ImmutableList.copyOf(option.expansion()));
        if (!unparsed.isEmpty()) {
          // Throw an assertion, because this indicates an error in the code that specified the
          // expansion for the current option.
          throw new AssertionError("Unparsed options remain after parsing expansion of " +
            arg + ": " + Joiner.on(' ').join(unparsed));
        }
      } else {
        Converter<?> converter = optionsData.getConverter(field);
        Object convertedValue;
        try {
          convertedValue = converter.convert(value);
        } catch (OptionsParsingException e) {
          // The converter doesn't know the option name, so we supply it here by
          // re-throwing:
          throw new OptionsParsingException("While parsing option " + arg
                                            + ": " + e.getMessage(), e);
        }

        // ...but allow duplicates of single-use options across separate calls to
        // parse(); latest wins:
        if (!option.allowMultiple()) {
          setValue(field, originalName, convertedValue,
              priority, sourceFunction.apply(originalName), implicitDependent, expandedFrom);
        } else {
          // But if it's a multiple-use option, then just accumulate the
          // values, in the order in which they were seen.
          // Note: The type of the list member is not known; Java introspection
          // only makes it available in String form via the signature string
          // for the field declaration.
          addListValue(field, convertedValue, priority, sourceFunction.apply(originalName),
              implicitDependent, expandedFrom);
        }
      }

      // Collect any implicit requirements.
      if (option.implicitRequirements().length > 0) {
        implicitRequirements.put(option.name(), Arrays.asList(option.implicitRequirements()));
      }
    }

    // Now parse any implicit requirements that were collected.
    // TODO(bazel-team): this should happen when the option is encountered.
    if (!implicitRequirements.isEmpty()) {
      for (Map.Entry<String,List<String>> entry : implicitRequirements.entrySet()) {
        Function<Object, String> requirementSourceFunction = Functions.<String>constant(
            "implicit requirement of option --" + entry.getKey() + " from " +
            sourceFunction.apply(entry.getKey()));

        List<String> unparsed = parse(priority, requirementSourceFunction, entry.getKey(), null,
            entry.getValue());
        if (!unparsed.isEmpty()) {
          // Throw an assertion, because this indicates an error in the code that specified in the
          // implicit requirements for the option(s).
          throw new AssertionError("Unparsed options remain after parsing implicit options: "
              + Joiner.on(' ').join(unparsed));
        }
      }
    }

    return unparsedArgs;
  }

  private static final class ParseOptionResult {
    final Field field;
    final Option option;
    final String value;

    ParseOptionResult(Field field, Option option, String value) {
      this.field = field;
      this.option = option;
      this.value = value;
    }
  }

  private ParseOptionResult parseOption(String arg, Iterator<String> nextArgs)
      throws OptionsParsingException {

    String value = null;
    Field field;
    boolean booleanValue = true;

    if (arg.length() == 2) { // -l  (may be nullary or unary)
      field = optionsData.getFieldForAbbrev(arg.charAt(1));
      booleanValue = true;

    } else if (arg.length() == 3 && arg.charAt(2) == '-') { // -l-  (boolean)
      field = optionsData.getFieldForAbbrev(arg.charAt(1));
      booleanValue = false;

    } else if (allowSingleDashLongOptions // -long_option
        || arg.startsWith("--")) { // or --long_option

      int equalsAt = arg.indexOf('=');
      int nameStartsAt = arg.startsWith("--") ? 2 : 1;
      String name =
          equalsAt == -1 ? arg.substring(nameStartsAt) : arg.substring(nameStartsAt, equalsAt);
      if (name.trim().isEmpty()) {
        throw new OptionsParsingException("Invalid options syntax: " + arg, arg);
      }
      value = equalsAt == -1 ? null : arg.substring(equalsAt + 1);
      field = optionsData.getFieldFromName(name);

      // look for a "no"-prefixed option name: "no<optionname>";
      // (Undocumented: we also allow --no_foo.  We're generous like that.)
      if (field == null && name.startsWith("no")) {
        name = name.substring(name.startsWith("no_") ? 3 : 2);
        field = optionsData.getFieldFromName(name);
        booleanValue = false;
        if (field != null) {
          // TODO(bazel-team): Add tests for these cases.
          if (!OptionsParserImpl.isBooleanField(field)) {
            throw new OptionsParsingException(
                "Illegal use of 'no' prefix on non-boolean option: " + arg, arg);
          }
          if (value != null) {
            throw new OptionsParsingException(
                "Unexpected value after boolean option: " + arg, arg);
          }
          // "no<optionname>" signifies a boolean option w/ false value
          value = "0";
        }
      }
    } else {
      throw new OptionsParsingException("Invalid options syntax: " + arg, arg);
    }

    if (field == null) {
      throw new OptionsParsingException("Unrecognized option: " + arg, arg);
    }

    Option option = field.getAnnotation(Option.class);

    if (value == null) {
      // Special-case boolean to supply value based on presence of "no" prefix.
      if (OptionsParserImpl.isBooleanField(field)) {
        value = booleanValue ? "1" : "0";
      } else if (field.getType().equals(Void.class) && !option.wrapperOption()) {
        // This is expected, Void type options have no args (unless they're wrapper options).
      } else if (nextArgs.hasNext()) {
        value = nextArgs.next();  // "--flag value" form
      } else {
        throw new OptionsParsingException("Expected value after " + arg);
      }
    }

    return new ParseOptionResult(field, option, value);
  }

  /**
   * Gets the result of parsing the options.
   */
  <O extends OptionsBase> O getParsedOptions(Class<O> optionsClass) {
    // Create the instance:
    O optionsInstance;
    try {
      Constructor<O> constructor = optionsData.getConstructor(optionsClass);
      if (constructor == null) {
        return null;
      }
      optionsInstance = constructor.newInstance(new Object[0]);
    } catch (Exception e) {
      throw new IllegalStateException(e);
    }

    // Set the fields
    for (Field field : optionsData.getFieldsForClass(optionsClass)) {
      Object value;
      ParsedOptionEntry entry = parsedValues.get(field);
      if (entry == null) {
        value = optionsData.getDefaultValue(field);
      } else {
        value = entry.getValue();
      }
      try {
        field.set(optionsInstance, value);
      } catch (IllegalAccessException e) {
        throw new IllegalStateException(e);
      }
    }
    return optionsInstance;
  }

  List<String> getWarnings() {
    return ImmutableList.copyOf(warnings);
  }

  static String getDefaultOptionString(Field optionField) {
    Option annotation = optionField.getAnnotation(Option.class);
    return annotation.defaultValue();
  }

  static boolean isBooleanField(Field field) {
    return field.getType().equals(boolean.class)
        || field.getType().equals(TriState.class)
        || findConverter(field) instanceof BoolOrEnumConverter;
  }

  static boolean isVoidField(Field field) {
    return field.getType().equals(Void.class);
  }

  static boolean isSpecialNullDefault(String defaultValueString, Field optionField) {
    return defaultValueString.equals("null") && !optionField.getType().isPrimitive();
  }

  static Converter<?> findConverter(Field optionField) {
    Option annotation = optionField.getAnnotation(Option.class);
    if (annotation.converter() == Converter.class) {
      Type type;
      if (annotation.allowMultiple()) {
        // The OptionParserImpl already checked that the type is List<T> for some T;
        // here we extract the type T.
        type = ((ParameterizedType) optionField.getGenericType()).getActualTypeArguments()[0];
      } else {
        type = optionField.getType();
      }
      Converter<?> converter = DEFAULT_CONVERTERS.get(type);
      if (converter == null) {
        throw new AssertionError("No converter found for "
            + type + "; possible fix: add "
            + "converter=... to @Option annotation for "
            + optionField.getName());
      }
      return converter;
    }
    try {
      Class<?> converter = annotation.converter();
      Constructor<?> constructor = converter.getConstructor(new Class<?>[0]);
      return (Converter<?>) constructor.newInstance(new Object[0]);
    } catch (Exception e) {
      throw new AssertionError(e);
    }
  }
}
