Home | History | Annotate | Download | only in options
      1 // Copyright 2014 The Bazel Authors. All rights reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //    http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 package com.google.devtools.common.options;
     15 
     16 import java.util.Objects;
     17 
     18 /**
     19  * The position of an option in the interpretation order. Options are interpreted using a
     20  * last-option-wins system for single valued options, and are listed in that order for
     21  * multiple-valued options.
     22  *
     23  * <p>The position of the option is in category order, and within the priority category in index
     24  * order.
     25  */
     26 public class OptionPriority implements Comparable<OptionPriority> {
     27   private final PriorityCategory priorityCategory;
     28   private final int index;
     29   private final boolean locked;
     30 
     31   private OptionPriority(PriorityCategory priorityCategory, int index, boolean locked) {
     32     this.priorityCategory = priorityCategory;
     33     this.index = index;
     34     this.locked = locked;
     35   }
     36 
     37   /** Get the first OptionPriority for that category. */
     38   static OptionPriority lowestOptionPriorityAtCategory(PriorityCategory category) {
     39     return new OptionPriority(category, 0, false);
     40   }
     41 
     42   /**
     43    * Get the priority for the option following this one. In normal, incremental option parsing, the
     44    * returned priority would compareTo as after the current one. Does not increment locked
     45    * priorities.
     46    */
     47   static OptionPriority nextOptionPriority(OptionPriority priority) {
     48     if (priority.locked) {
     49       return priority;
     50     }
     51     return new OptionPriority(priority.priorityCategory, priority.index + 1, false);
     52   }
     53 
     54   /**
     55    * Return a priority for this option that will avoid priority increases by calls to
     56    * nextOptionPriority.
     57    *
     58    * <p>Some options are expanded in-place, and need to be all parsed at the priority of the
     59    * original option. In this case, parsing one of these after another should not cause the option
     60    * to be considered as higher priority than the ones before it (this would cause overlap between
     61    * the expansion of --expansion_flag and a option following it in the same list of options).
     62    */
     63   public static OptionPriority getLockedPriority(OptionPriority priority) {
     64     return new OptionPriority(priority.priorityCategory, priority.index, true);
     65   }
     66 
     67   public PriorityCategory getPriorityCategory() {
     68     return priorityCategory;
     69   }
     70 
     71   @Override
     72   public int compareTo(OptionPriority o) {
     73     if (priorityCategory.equals(o.priorityCategory)) {
     74       return index - o.index;
     75     }
     76     return priorityCategory.ordinal() - o.priorityCategory.ordinal();
     77   }
     78 
     79   @Override
     80   public boolean equals(Object o) {
     81     if (o instanceof OptionPriority) {
     82       OptionPriority other = (OptionPriority) o;
     83       return other.priorityCategory.equals(priorityCategory) && other.index == index;
     84     }
     85     return false;
     86   }
     87 
     88   @Override
     89   public int hashCode() {
     90     return Objects.hash(priorityCategory, index);
     91   }
     92 
     93   @Override
     94   public String toString() {
     95     return String.format("OptionPriority(%s,%s)", priorityCategory, index);
     96   }
     97 
     98   /**
     99    * The priority of option values, in order of increasing priority.
    100    *
    101    * <p>In general, new values for options can only override values with a lower or equal priority.
    102    * Option values provided in annotations in an options class are implicitly at the priority {@code
    103    * DEFAULT}.
    104    *
    105    * <p>The ordering of the priorities is the source-code order. This is consistent with the
    106    * automatically generated {@code compareTo} method as specified by the Java Language
    107    * Specification. DO NOT change the source-code order of these values, or you will break code that
    108    * relies on the ordering.
    109    */
    110   public enum PriorityCategory {
    111 
    112     /**
    113      * The priority of values specified in the {@link Option} annotation. This should never be
    114      * specified in calls to {@link OptionsParser#parse}.
    115      */
    116     DEFAULT,
    117 
    118     /**
    119      * Overrides default options at runtime, while still allowing the values to be overridden
    120      * manually.
    121      */
    122     COMPUTED_DEFAULT,
    123 
    124     /** For options coming from a configuration file or rc file. */
    125     RC_FILE,
    126 
    127     /** For options coming from the command line. */
    128     COMMAND_LINE,
    129 
    130     /** For options coming from invocation policy. */
    131     INVOCATION_POLICY,
    132 
    133     /**
    134      * This priority can be used to unconditionally override any user-provided options. This should
    135      * be used rarely and with caution!
    136      */
    137     SOFTWARE_REQUIREMENT
    138   }
    139 }
    140