// Copyright 2017 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.processor;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.common.options.Converter;
import com.google.devtools.common.options.Converters;
import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionDefinition;
import com.google.devtools.common.options.OptionDocumentationCategory;
import com.google.devtools.common.options.OptionEffectTag;
import com.google.devtools.common.options.OptionMetadataTag;
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.OptionsParsingException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.ExecutableType;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.Diagnostic;

/**
 * Annotation processor for {@link Option}.
 *
 * <p>Checks the following invariants about {@link Option}-annotated fields ("options"):
 *
 * <ul>
 *   <li>The {@link OptionsParser} only accepts options in {@link OptionsBase}-inheriting classes
 *   <li>All options must be declared publicly and be neither static nor final.
 *   <li>All options that must be used on the command line must have sensible names without
 *       whitespace or other confusing characters, such as equal signs.
 *   <li>The type of the option must match the converter that will convert the unparsed string value
 *       into the option type. For options that do not specify a converter, check that there is a
 *       valid match in the {@link Converters#DEFAULT_CONVERTERS} list.
 *   <li>Options must list valid combinations of tags and documentation categories.
 *   <li>Expansion options and options with implicit requirements cannot expand in more than one
 *       way, how multiple expansions would interact is not defined and should not be necessary.
 *   <li>Multiple options must not declare default value (see {@link
 *       #MULTIPLE_OPTIONS_DEFAULT_VALUE_EXCEPTIONS} for exceptions).
 * </ul>
 *
 * <p>These properties can be relied upon at runtime without additional checks.
 */
@SupportedAnnotationTypes({"com.google.devtools.common.options.Option"})
public final class OptionProcessor extends AbstractProcessor {

  private Types typeUtils;
  private Elements elementUtils;
  private Messager messager;
  private ImmutableMap<TypeMirror, Converter<?>> defaultConverters;
  private ImmutableMap<Class<?>, PrimitiveType> primitiveTypeMap;

  @Override
  public SourceVersion getSupportedSourceVersion() {
    return SourceVersion.latestSupported();
  }

  @Override
  public synchronized void init(ProcessingEnvironment processingEnv) {
    super.init(processingEnv);
    typeUtils = processingEnv.getTypeUtils();
    elementUtils = processingEnv.getElementUtils();
    messager = processingEnv.getMessager();

    // Because of the discrepancies between the java.lang and javax.lang type models, we can't
    // directly use the get() method for the default converter map. Instead, we'll convert it once,
    // to be more usable, and with the boxed type return values of convert() as the keys.
    ImmutableMap.Builder<TypeMirror, Converter<?>> converterMapBuilder =
        new ImmutableMap.Builder<>();

    // Create a link from the primitive Classes to their primitive types. This intentionally
    // only contains the types in the DEFAULT_CONVERTERS map.
    ImmutableMap.Builder<Class<?>, PrimitiveType> builder = new ImmutableMap.Builder<>();
    builder.put(int.class, typeUtils.getPrimitiveType(TypeKind.INT));
    builder.put(double.class, typeUtils.getPrimitiveType(TypeKind.DOUBLE));
    builder.put(boolean.class, typeUtils.getPrimitiveType(TypeKind.BOOLEAN));
    builder.put(long.class, typeUtils.getPrimitiveType(TypeKind.LONG));
    primitiveTypeMap = builder.build();

    for (Map.Entry<Class<?>, Converter<?>> entry : Converters.DEFAULT_CONVERTERS.entrySet()) {
      Class<?> converterClass = entry.getKey();
      String typeName = converterClass.getCanonicalName();
      TypeElement typeElement = elementUtils.getTypeElement(typeName);
      // Check that we can get a type mirror, either through the type element or the primitive type.
      if (typeElement != null) {
        converterMapBuilder.put(typeElement.asType(), entry.getValue());
      } else {
        if (!primitiveTypeMap.containsKey(converterClass)) {
          messager.printMessage(
              Diagnostic.Kind.ERROR,
              String.format("Can't get a TypeElement for Type %s", typeName));
          continue;
        }
        // Add the primitive types to the map, both in primitive TypeMirror form, and the boxed
        // classes, such as java.lang.Integer, because primitives must be boxed in collections,
        // such as allowMultiple options, which have type List<singleOptionType>.
        PrimitiveType primitiveType = primitiveTypeMap.get(converterClass);
        converterMapBuilder.put(primitiveType, entry.getValue());
        converterMapBuilder.put(typeUtils.boxedClass(primitiveType).asType(), entry.getValue());
      }
    }
    defaultConverters = converterMapBuilder.build();
  }

  /** Check that the Option variables only occur in OptionBase-inheriting classes. */
  private void checkInOptionBase(VariableElement optionField) throws OptionProcessorException {
    if (optionField.getEnclosingElement().getKind() != ElementKind.CLASS) {
      throw new OptionProcessorException(optionField, "The field should belong to a class.");
    }
    TypeMirror thisOptionClass = optionField.getEnclosingElement().asType();
    TypeMirror optionsBase =
        elementUtils.getTypeElement("com.google.devtools.common.options.OptionsBase").asType();
    if (!typeUtils.isAssignable(thisOptionClass, optionsBase)) {
      throw new OptionProcessorException(
          optionField,
          "@Option annotated fields can only be in classes that inherit from OptionsBase.");
    }
  }

  /**
   * Checks that the Option variables is public and neither final nor static.
   *
   * <p>Private or protected fields would prevent the options parser from having full access to the
   * fields it's expected to read, and {@link OptionsBase} equality would not work as intended.
   *
   * <p>Static or final fields would cause issue with correct value assigning at the end of parsing.
   */
  private static void checkModifiers(VariableElement optionField) throws OptionProcessorException {
    if (!optionField.getModifiers().contains(Modifier.PUBLIC)) {
      throw new OptionProcessorException(optionField, "@Option annotated fields should be public.");
    }
    if (optionField.getModifiers().contains(Modifier.STATIC)) {
      throw new OptionProcessorException(
          optionField, "@Option annotated fields should not be static.");
    }
    if (optionField.getModifiers().contains(Modifier.FINAL)) {
      throw new OptionProcessorException(
          optionField, "@Option annotated fields should not be final.");
    }
  }

  private ImmutableList<TypeMirror> getAcceptedConverterReturnTypes(VariableElement optionField)
      throws OptionProcessorException {
    TypeMirror optionType = optionField.asType();
    Option annotation = optionField.getAnnotation(Option.class);
    TypeMirror listType = elementUtils.getTypeElement(List.class.getCanonicalName()).asType();
    // Options that accumulate multiple mentions in an arglist must have type List<T>, where each
    // individual mention has type T. Identify type T to use it for checking the converter's return
    // type.
    if (annotation.allowMultiple()) {
      // Check that the option type is in fact a list.
      if (optionType.getKind() != TypeKind.DECLARED) {
        throw new OptionProcessorException(
            optionField,
            "Option that allows multiple occurrences must be of type %s, but is of type %s",
            listType,
            optionType);
      }
      DeclaredType optionDeclaredType = (DeclaredType) optionType;
      if (!typeUtils.isAssignable(typeUtils.erasure(optionDeclaredType), listType)) {
        throw new OptionProcessorException(
            optionField,
            "Option that allows multiple occurrences must be assignable to type %s, but is of type"
                + " %s",
            listType,
            optionType);
      }

      // Check that there is only one generic parameter, and store it as the singular option type.
      List<? extends TypeMirror> genericParameters = optionDeclaredType.getTypeArguments();
      if (genericParameters.size() != 1) {
        throw new OptionProcessorException(
            optionField,
            "Option that allows multiple occurrences must be of type %s, "
                + "where E is the type of an individual command-line mention of this option, "
                + "but is of type %s",
            listType,
            optionType);
      }

      // For repeated options, we also accept cases where each option itself contains a list, which
      // are then concatenated into the final single list type. For this reason, we will accept both
      // converters that return the type of a single option, and List<singleOption>, which,
      // incidentally, is the original optionType.
      // Example: --foo=a,b,c --foo=d,e,f could have a final value of type List<Char>,
      //       value {a,b,c,e,d,f}, instead of requiring a final value of type List<List<Char>>
      //       value {{a,b,c},{d,e,f}}
      TypeMirror singularOptionType = genericParameters.get(0);

      return ImmutableList.of(singularOptionType, optionType);
    } else {
      return ImmutableList.of(optionField.asType());
    }
  }

  private void checkForDefaultConverter(
      VariableElement optionField,
      List<TypeMirror> acceptedConverterReturnTypes,
      String defaultValue)
      throws OptionProcessorException {
    for (TypeMirror acceptedConverterReturnType : acceptedConverterReturnTypes) {
      Converter<?> converterInstance = defaultConverters.get(acceptedConverterReturnType);
      if (converterInstance == null) {
        // This return type isn't a match, move on to the next one in case.
        continue;
      }
      TypeElement converter =
          elementUtils.getTypeElement(converterInstance.getClass().getCanonicalName());
      try {
        // For the default converters, it so happens we have access to the convert methods
        // at compile time, since we already have the OptionsParser source. Take advantage of
        // this to test that the provided defaultValue is valid.
        converterInstance.convert(defaultValue);
      } catch (OptionsParsingException e) {
        throw new OptionProcessorException(
            optionField,
            /* throwable = */ e,
            "Option lists a default value (%s) that is not parsable by the option's converter "
                + "(s)",
            defaultValue,
            converter);
      }
      return; // This one passes the test.
    }

    // We didn't find a default converter.
    throw new OptionProcessorException(
        optionField,
        "Cannot find valid converter for option of type %s",
        acceptedConverterReturnTypes.get(0));
  }

  private void checkProvidedConverter(
      VariableElement optionField,
      ImmutableList<TypeMirror> acceptedConverterReturnTypes,
      TypeElement converterElement)
      throws OptionProcessorException {
    if (converterElement.getModifiers().contains(Modifier.ABSTRACT)) {
      throw new OptionProcessorException(
          optionField, "The converter type %s must be a concrete type", converterElement.asType());
    }

    DeclaredType converterType = (DeclaredType) converterElement.asType();

    // Unfortunately, for provided classes, we do not have access to the compiled convert
    // method at this time, and cannot check that the default value is parseable. We will
    // instead check that T of Converter<T> matches the option's type, but this is all we can
    // do.
    List<ExecutableElement> methodList =
        elementUtils.getAllMembers(converterElement).stream()
            .filter(element -> element.getKind() == ElementKind.METHOD)
            .map(methodElement -> (ExecutableElement) methodElement)
            .filter(methodElement -> methodElement.getSimpleName().contentEquals("convert"))
            .filter(
                methodElement ->
                    methodElement.getParameters().size() == 1
                        && typeUtils.isSameType(
                            methodElement.getParameters().get(0).asType(),
                            elementUtils.getTypeElement(String.class.getCanonicalName()).asType()))
            .collect(Collectors.toList());
    // Check that there is just the one method
    if (methodList.size() != 1) {
      throw new OptionProcessorException(
          optionField,
          "Converter %s has methods 'convert(String)': %s",
          converterElement,
          methodList.stream().map(Object::toString).collect(Collectors.joining(", ")));
    }

    ExecutableType convertMethodType =
        (ExecutableType) typeUtils.asMemberOf(converterType, methodList.get(0));
    TypeMirror convertMethodResultType = convertMethodType.getReturnType();
    // Check that the converter's return type is in the accepted list.
    for (TypeMirror acceptedConverterReturnType : acceptedConverterReturnTypes) {
      if (typeUtils.isAssignable(convertMethodResultType, acceptedConverterReturnType)) {
        return; // This one passes the test.
      }
    }
    throw new OptionProcessorException(
        optionField,
        "Type of field (%s) must be assignable from the converter's return type (%s)",
        acceptedConverterReturnTypes.get(0),
        convertMethodResultType);
  }

  private void checkConverter(VariableElement optionField) throws OptionProcessorException {
    TypeMirror optionType = optionField.asType();
    Option annotation = optionField.getAnnotation(Option.class);
    ImmutableList<TypeMirror> acceptedConverterReturnTypes =
        getAcceptedConverterReturnTypes(optionField);

    // For simple, static expansions, don't accept non-Void types.
    if (annotation.expansion().length != 0
        && !typeUtils.isSameType(
            optionType, elementUtils.getTypeElement(Void.class.getCanonicalName()).asType())) {
      throw new OptionProcessorException(
          optionField,
          "Option is an expansion flag with a static expansion, but does not have Void type.");
    }

    // Obtain the converter for this option.
    AnnotationMirror optionMirror =
        ProcessorUtils.getAnnotation(elementUtils, typeUtils, optionField, Option.class);
    TypeElement defaultConverterElement =
        elementUtils.getTypeElement(Converter.class.getCanonicalName());
    TypeElement converterElement =
        ProcessorUtils.getClassTypeFromAnnotationField(elementUtils, optionMirror, "converter");
    if (converterElement == null) {
      throw new OptionProcessorException(optionField, "Null converter found.");
    }

    if (typeUtils.isSameType(converterElement.asType(), defaultConverterElement.asType())) {
      // Find a matching converter in the default converter list, and check that it successfully
      // parses the default value for this option.
      checkForDefaultConverter(
          optionField, acceptedConverterReturnTypes, annotation.defaultValue());
    } else {
      // Check that the provided converter has an accepted return type.
      checkProvidedConverter(optionField, acceptedConverterReturnTypes, converterElement);
    }
  }

  /**
   * Check that the option lists at least one effect, and that no nonsensical combinations are
   * listed, such as having a known effect listed with UNKNOWN.
   */
  private static void checkEffectTagRationality(VariableElement optionField)
      throws OptionProcessorException {
    Option annotation = optionField.getAnnotation(Option.class);
    OptionEffectTag[] effectTags = annotation.effectTags();
    // Check that there is at least one OptionEffectTag listed.
    if (effectTags.length < 1) {
      throw new OptionProcessorException(
          optionField,
          "Option does not list at least one OptionEffectTag. If the option has no effect, "
              + "please be explicit and add NO_OP. Otherwise, add a tag representing its effect.");
    } else if (effectTags.length > 1) {
      // If there are more than 1 tag, make sure that NO_OP and UNKNOWN is not one of them.
      // These don't make sense if other effects are listed.
      ImmutableList<OptionEffectTag> tags = ImmutableList.copyOf(effectTags);
      if (tags.contains(OptionEffectTag.UNKNOWN)) {
        throw new OptionProcessorException(
            optionField,
            "Option includes UNKNOWN with other, known, effects. Please remove UNKNOWN from "
                + "the list.");
      }
      if (tags.contains(OptionEffectTag.NO_OP)) {
        throw new OptionProcessorException(
            optionField,
            "Option includes NO_OP with other effects. This doesn't make much sense. Please "
                + "remove NO_OP or the actual effects from the list, whichever is correct.");
      }
    }
  }

  /**
   * Check that if the metadata tags listed by an option require the option to be unknown by the
   * average user, the same option will be omitted from documentation.
   */
  private static void checkMetadataTagAndCategoryRationality(VariableElement optionField)
      throws OptionProcessorException {
    Option annotation = optionField.getAnnotation(Option.class);
    OptionMetadataTag[] metadataTags = annotation.metadataTags();
    OptionDocumentationCategory category = annotation.documentationCategory();

    for (OptionMetadataTag tag : metadataTags) {
      if (tag == OptionMetadataTag.HIDDEN || tag == OptionMetadataTag.INTERNAL) {
        if (category != OptionDocumentationCategory.UNDOCUMENTED) {
          throw new OptionProcessorException(
              optionField,
              "Option has metadata tag %s but does not have category UNDOCUMENTED. Please fix.",
              tag);
        }
      }
    }
  }

  /** These categories used to indicate whether a flag was documented, but no longer. */
  private static final ImmutableList<String> DEPRECATED_CATEGORIES =
      ImmutableList.of("undocumented", "hidden", "internal");

  private static void checkOldCategoriesAreNotUsed(VariableElement optionField)
      throws OptionProcessorException {
    Option annotation = optionField.getAnnotation(Option.class);
    if (DEPRECATED_CATEGORIES.contains(annotation.category())) {
      throw new OptionProcessorException(
          optionField,
          "Documentation level is no longer read from the option category. Category \""
              + annotation.category()
              + "\" is disallowed, see OptionMetadataTags for the relevant tags.");
    }
  }

  private static void checkOptionName(VariableElement optionField) throws OptionProcessorException {
    Option annotation = optionField.getAnnotation(Option.class);
    String optionName = annotation.name();
    if (optionName.isEmpty()) {
      throw new OptionProcessorException(optionField, "Option must have an actual name.");
    }

    // Specifically for non-internal options, which are flags intended to be used on the command
    // line, check that there are no weird characters or whitespace.
    if (!ImmutableList.copyOf(annotation.metadataTags()).contains(OptionMetadataTag.INTERNAL)) {
      if (!Pattern.matches("([\\w:-])*", optionName)) {
        // Ideally, this would be just \w, but - and : are needed for legacy options. We can lie in
        // the error though, no harm in encouraging good behavior.
        throw new OptionProcessorException(
            optionField,
            "Options that are used on the command line as flags must have names made from word "
                + "characters only.");
      }
    }
  }

  /**
   * Some flags expand to other flags, either in place, or with "implicit requirements" that get
   * added on top of the flag's value. Don't let these flags do too many crazy things, dealing with
   * this is enough.
   */
  private void checkExpansionOptions(VariableElement optionField) throws OptionProcessorException {
    Option annotation = optionField.getAnnotation(Option.class);
    boolean isExpansion = annotation.expansion().length > 0;
    boolean hasImplicitRequirements = annotation.implicitRequirements().length > 0;

    if (isExpansion && hasImplicitRequirements) {
      throw new OptionProcessorException(
          optionField,
          "Can't set an option to be both an expansion option and have implicit requirements.");
    }

    if (isExpansion || hasImplicitRequirements) {
      if (annotation.allowMultiple()) {
        throw new OptionProcessorException(
            optionField,
            "Can't set an option to accumulate multiple values and let it expand to other flags.");
      }
    }
  }

  private static boolean hasSpecialNullDefaultValue(Option annotation) {
    return OptionDefinition.SPECIAL_NULL_DEFAULT_VALUE.equals(annotation.defaultValue());
  }

  /**
   * Options that are allowed to have default values.
   *
   * <p>DO NOT ADD new (especially production) options here - the long-term goal is to prohibit
   * multiple options to have default values.
   */
  private static final ImmutableList<String> MULTIPLE_OPTIONS_DEFAULT_VALUE_EXCEPTIONS =
      ImmutableList.of(
          // Multiple options used in OptionDefinitionTest
          "non_empty_string_multiple_option",
          "empty_string_multiple_option",
          // Production multiple options that still have default value.
          // Mostly due to backward compatibility reasons.
          "runs_per_test",
          "flaky_test_attempts",
          "worker_max_instances");

  private static boolean isMultipleOptionDefaultValueException(Option annotation) {
    return MULTIPLE_OPTIONS_DEFAULT_VALUE_EXCEPTIONS.contains(annotation.name());
  }

  private static void checkNoDefaultValueForMultipleOption(VariableElement optionField)
      throws OptionProcessorException {
    Option annotation = optionField.getAnnotation(Option.class);

    if (annotation.allowMultiple()
        && !hasSpecialNullDefaultValue(annotation)
        && !isMultipleOptionDefaultValueException(annotation)) {
      String message =
          String.format(
              "Default values for multiple options are not allowed - use \"%s\" special value",
              "null");
      throw new OptionProcessorException(optionField, message);
    }
  }

  @Override
  public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    for (Element annotatedElement : roundEnv.getElementsAnnotatedWith(Option.class)) {
      try {
        // Only fields are annotated with Option, this should already be checked by the
        // @Target(ElementType.FIELD) annotation.
        VariableElement optionField = (VariableElement) annotatedElement;

        checkModifiers(optionField);
        checkInOptionBase(optionField);
        checkOptionName(optionField);
        checkOldCategoriesAreNotUsed(optionField);
        checkExpansionOptions(optionField);
        checkConverter(optionField);
        checkEffectTagRationality(optionField);
        checkMetadataTagAndCategoryRationality(optionField);
        checkNoDefaultValueForMultipleOption(optionField);
      } catch (OptionProcessorException e) {
        error(e.getElementInError(), e.getMessage());
      }
    }
    return false;
  }

  /**
   * Prints an error message & fails the compilation.
   *
   * @param e The element which has caused the error. Can be null
   * @param msg The error message
   */
  public void error(Element e, String msg) {
    messager.printMessage(Diagnostic.Kind.ERROR, msg, e);
  }
}
