// 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, /*conversionContext=*/ null);
      } 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() == 2
                        && typeUtils.isSameType(
                            methodElement.getParameters().get(0).asType(),
                            elementUtils.getTypeElement(String.class.getCanonicalName()).asType())
                        && typeUtils.isSameType(
                            methodElement.getParameters().get(1).asType(),
                            elementUtils.getTypeElement(Object.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 %d methods 'convert(String, Object)', expected 1: %s",
          converterElement,
          methodList.size(),
          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");

  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);
  }
}
