/*
 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.tools.javac.code;

import java.util.Iterator;

import com.sun.tools.javac.tree.JCTree.JCLambda;
import com.sun.tools.javac.util.*;

/** A type annotation position.
*
*  <p><b>This is NOT part of any supported API.
*  If you write code that depends on this, you do so at your own risk.
*  This code and its internal interfaces are subject to change or
*  deletion without notice.</b>
*/
// Code duplicated in com.sun.tools.classfile.TypeAnnotation.Position
public class TypeAnnotationPosition {

    public enum TypePathEntryKind {
        ARRAY(0),
        INNER_TYPE(1),
        WILDCARD(2),
        TYPE_ARGUMENT(3);

        public final int tag;

        private TypePathEntryKind(int tag) {
            this.tag = tag;
        }
    }

    public static class TypePathEntry {
        /** The fixed number of bytes per TypePathEntry. */
        public static final int bytesPerEntry = 2;

        public final TypePathEntryKind tag;
        public final int arg;

        public static final TypePathEntry ARRAY = new TypePathEntry(TypePathEntryKind.ARRAY);
        public static final TypePathEntry INNER_TYPE = new TypePathEntry(TypePathEntryKind.INNER_TYPE);
        public static final TypePathEntry WILDCARD = new TypePathEntry(TypePathEntryKind.WILDCARD);

        private TypePathEntry(TypePathEntryKind tag) {
            Assert.check(tag == TypePathEntryKind.ARRAY ||
                    tag == TypePathEntryKind.INNER_TYPE ||
                    tag == TypePathEntryKind.WILDCARD,
                    "Invalid TypePathEntryKind: " + tag);
            this.tag = tag;
            this.arg = 0;
        }

        public TypePathEntry(TypePathEntryKind tag, int arg) {
            Assert.check(tag == TypePathEntryKind.TYPE_ARGUMENT,
                    "Invalid TypePathEntryKind: " + tag);
            this.tag = tag;
            this.arg = arg;
        }

        public static TypePathEntry fromBinary(int tag, int arg) {
            Assert.check(arg == 0 || tag == TypePathEntryKind.TYPE_ARGUMENT.tag,
                    "Invalid TypePathEntry tag/arg: " + tag + "/" + arg);
            switch (tag) {
            case 0:
                return ARRAY;
            case 1:
                return INNER_TYPE;
            case 2:
                return WILDCARD;
            case 3:
                return new TypePathEntry(TypePathEntryKind.TYPE_ARGUMENT, arg);
            default:
                Assert.error("Invalid TypePathEntryKind tag: " + tag);
                return null;
            }
        }

        @Override
        public String toString() {
            return tag.toString() +
                    (tag == TypePathEntryKind.TYPE_ARGUMENT ? ("(" + arg + ")") : "");
        }

        @Override
        public boolean equals(Object other) {
            if (! (other instanceof TypePathEntry)) {
                return false;
            }
            TypePathEntry tpe = (TypePathEntry) other;
            return this.tag == tpe.tag && this.arg == tpe.arg;
        }

        @Override
        public int hashCode() {
            return this.tag.hashCode() * 17 + this.arg;
        }
    }

    public static final List<TypePathEntry> emptyPath = List.nil();

    // NOTE: All of these will be converted to final fields eventually.

    public final TargetType type;

    // For generic/array types.

    // This field is in the process of being made final.  Do not
    // introduce new mutations.
    public List<TypePathEntry> location;

    // Tree position.
    public final int pos;

    // For type casts, type tests, new, locals (as start_pc),
    // and method and constructor reference type arguments.
    public boolean isValidOffset = false;
    public int offset = -1;

    // For locals. arrays same length
    public int[] lvarOffset = null;
    public int[] lvarLength = null;
    public int[] lvarIndex = null;

    // For type parameter bound
    public final int bound_index;

    // For type parameter and method parameter
    public final int parameter_index;

    // For class extends, implements, and throws clauses
    public final int type_index;

    // For exception parameters, index into exception table.  In
    // com.sun.tools.javac.jvm.Gen.genCatch, we first use this to hold
    // the catch type index.  Then in
    // com.sun.tools.javac.jvm.Code.fillExceptionParameterPositions we
    // use that value to determine the exception table index.
    private int exception_index = Integer.MIN_VALUE;

    // If this type annotation is within a lambda expression,
    // store a pointer to the lambda expression tree in order
    // to allow a later translation to the right method.
    public final JCLambda onLambda;

    // NOTE: This constructor will eventually go away, and be replaced
    // by static builder methods.

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append('[');
        sb.append(type);

        switch (type) {
        // instanceof
        case INSTANCEOF:
        // new expression
        case NEW:
        // constructor/method reference receiver
        case CONSTRUCTOR_REFERENCE:
        case METHOD_REFERENCE:
            sb.append(", offset = ");
            sb.append(offset);
            break;
        // local variable
        case LOCAL_VARIABLE:
        // resource variable
        case RESOURCE_VARIABLE:
            if (lvarOffset == null) {
                sb.append(", lvarOffset is null!");
                break;
            }
            sb.append(", {");
            for (int i = 0; i < lvarOffset.length; ++i) {
                if (i != 0) sb.append("; ");
                sb.append("start_pc = ");
                sb.append(lvarOffset[i]);
                sb.append(", length = ");
                sb.append(lvarLength[i]);
                sb.append(", index = ");
                sb.append(lvarIndex[i]);
            }
            sb.append("}");
            break;
        // method receiver
        case METHOD_RECEIVER:
            // Do nothing
            break;
        // type parameter
        case CLASS_TYPE_PARAMETER:
        case METHOD_TYPE_PARAMETER:
            sb.append(", param_index = ");
            sb.append(parameter_index);
            break;
        // type parameter bound
        case CLASS_TYPE_PARAMETER_BOUND:
        case METHOD_TYPE_PARAMETER_BOUND:
            sb.append(", param_index = ");
            sb.append(parameter_index);
            sb.append(", bound_index = ");
            sb.append(bound_index);
            break;
        // class extends or implements clause
        case CLASS_EXTENDS:
            sb.append(", type_index = ");
            sb.append(type_index);
            break;
        // throws
        case THROWS:
            sb.append(", type_index = ");
            sb.append(type_index);
            break;
        // exception parameter
        case EXCEPTION_PARAMETER:
            sb.append(", exception_index = ");
            sb.append(exception_index);
            break;
        // method parameter
        case METHOD_FORMAL_PARAMETER:
            sb.append(", param_index = ");
            sb.append(parameter_index);
            break;
        // type cast
        case CAST:
        // method/constructor/reference type argument
        case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
        case METHOD_INVOCATION_TYPE_ARGUMENT:
        case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
        case METHOD_REFERENCE_TYPE_ARGUMENT:
            sb.append(", offset = ");
            sb.append(offset);
            sb.append(", type_index = ");
            sb.append(type_index);
            break;
        // We don't need to worry about these
        case METHOD_RETURN:
        case FIELD:
            break;
        default:
            Assert.error("Unknown target type: " + type);
        }

        // Append location data for generics/arrays.
        if (!location.isEmpty()) {
            sb.append(", location = (");
            sb.append(location);
            sb.append(")");
        }

        sb.append(", pos = ");
        sb.append(pos);

        if (onLambda != null) {
            sb.append(", onLambda hash = ");
            sb.append(onLambda.hashCode());
        }

        sb.append(']');
        return sb.toString();
    }

    /**
     * Indicates whether the target tree of the annotation has been optimized
     * away from classfile or not.
     * @return true if the target has not been optimized away
     */
    public boolean emitToClassfile() {
        return !type.isLocal() || isValidOffset;
    }


    public boolean matchesPos(int pos) {
        return this.pos == pos;
    }

    public void updatePosOffset(int to) {
        offset = to;
        lvarOffset = new int[]{to};
        isValidOffset = true;
    }

    public boolean hasExceptionIndex() {
        return exception_index >= 0;
    }

    public int getExceptionIndex() {
        Assert.check(exception_index >= 0, "exception_index does not contain a bytecode offset");
        return exception_index;
    }

    public void setExceptionIndex(final int exception_index) {
        Assert.check(hasCatchType(), "exception_index already contains a bytecode offset");
        Assert.check(exception_index >= 0, "Expected a valid bytecode offset");
        this.exception_index = exception_index;
    }

    public boolean hasCatchType() {
        return exception_index < 0 && exception_index != Integer.MIN_VALUE;
    }

    public int getCatchType() {
        Assert.check(hasCatchType(),
                     "exception_index does not contain valid catch info");
        return ((-this.exception_index) - 1) & 0xff ;
    }

    public int getStartPos() {
        Assert.check(hasCatchType(),
                     "exception_index does not contain valid catch info");
        return ((-this.exception_index) - 1) >> 8 ;
    }

    public void setCatchInfo(final int catchType, final int startPos) {
        Assert.check(this.exception_index < 0,
                     "exception_index already contains a bytecode index");
        Assert.check(catchType >= 0, "Expected a valid catch type");
        this.exception_index = -((catchType | startPos << 8) + 1);
    }

    /**
     * Decode the binary representation for a type path and set
     * the {@code location} field.
     *
     * @param list The bytecode representation of the type path.
     */
    public static List<TypePathEntry> getTypePathFromBinary(java.util.List<Integer> list) {
        ListBuffer<TypePathEntry> loc = new ListBuffer<>();
        Iterator<Integer> iter = list.iterator();
        while (iter.hasNext()) {
            Integer fst = iter.next();
            Assert.check(iter.hasNext(), "Could not decode type path: " + list);
            Integer snd = iter.next();
            loc = loc.append(TypePathEntry.fromBinary(fst, snd));
        }
        return loc.toList();
    }

    public static List<Integer> getBinaryFromTypePath(java.util.List<TypePathEntry> locs) {
        ListBuffer<Integer> loc = new ListBuffer<>();
        for (TypePathEntry tpe : locs) {
            loc = loc.append(tpe.tag.tag);
            loc = loc.append(tpe.arg);
        }
        return loc.toList();
    }

    // These methods are the new preferred way to create
    // TypeAnnotationPositions

    // Never make this a public constructor without creating a builder.
    private TypeAnnotationPosition(final TargetType ttype,
                                   final int pos,
                                   final int parameter_index,
                                   final JCLambda onLambda,
                                   final int type_index,
                                   final int bound_index,
                                   final List<TypePathEntry> location) {
        Assert.checkNonNull(location);
        this.type = ttype;
        this.pos = pos;
        this.parameter_index = parameter_index;
        this.onLambda = onLambda;
        this.type_index = type_index;
        this.bound_index = bound_index;
        this.location = location;
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a method return.
     *
     * @param location The type path.
     * @param onLambda The lambda for this parameter.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        methodReturn(final List<TypePathEntry> location,
                     final JCLambda onLambda,
                     final int pos) {
        return new TypeAnnotationPosition(TargetType.METHOD_RETURN, pos,
                                          Integer.MIN_VALUE, onLambda,
                                          Integer.MIN_VALUE, Integer.MIN_VALUE,
                                          location);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a method return.
     *
     * @param location The type path.
     */
    public static TypeAnnotationPosition
        methodReturn(final List<TypePathEntry> location) {
        return methodReturn(location, null, -1);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a method return.
     *
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition methodReturn(final int pos) {
        return methodReturn(emptyPath, null, pos);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a method receiver parameter.
     *
     * @param location The type path.
     * @param onLambda The lambda for this parameter.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        methodReceiver(final List<TypePathEntry> location,
                     final JCLambda onLambda,
                     final int pos) {
        return new TypeAnnotationPosition(TargetType.METHOD_RECEIVER, pos,
                                          Integer.MIN_VALUE, onLambda,
                                          Integer.MIN_VALUE, Integer.MIN_VALUE,
                                          location);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a method receiver parameter.
     *
     * @param location The type path.
     */
    public static TypeAnnotationPosition
        methodReceiver(final List<TypePathEntry> location) {
        return methodReceiver(location, null, -1);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a method receiver parameter.
     *
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition methodReceiver(final int pos) {
        return methodReceiver(emptyPath, null, pos);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a method formal parameter.
     *
     * @param location The type path.
     * @param onLambda The lambda for this parameter.
     * @param index The index of the parameter.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        methodParameter(final List<TypePathEntry> location,
                        final JCLambda onLambda,
                        final int parameter_index,
                        final int pos) {
        return new TypeAnnotationPosition(TargetType.METHOD_FORMAL_PARAMETER,
                                          pos, parameter_index, onLambda,
                                          Integer.MIN_VALUE, Integer.MIN_VALUE,
                                          location);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a method formal parameter.
     *
     * @param onLambda The lambda for this parameter.
     * @param index The index of the parameter.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        methodParameter(final JCLambda onLambda,
                        final int parameter_index,
                        final int pos) {
        return methodParameter(emptyPath, onLambda,
                               parameter_index, pos);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a method formal parameter.
     *
     * @param index The index of the parameter.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        methodParameter(final int parameter_index,
                        final int pos) {
        return methodParameter(null, parameter_index, pos);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a method formal parameter.
     *
     * @param location The type path.
     * @param index The index of the parameter.
     */
    public static TypeAnnotationPosition
        methodParameter(final List<TypePathEntry> location,
                        final int parameter_index) {
        return methodParameter(location, null, parameter_index, -1);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a method reference.
     *
     * @param location The type path.
     * @param onLambda The lambda for this method reference.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        methodRef(final List<TypePathEntry> location,
                  final JCLambda onLambda,
                  final int pos) {
        return new TypeAnnotationPosition(TargetType.METHOD_REFERENCE, pos,
                                          Integer.MIN_VALUE, onLambda,
                                          Integer.MIN_VALUE, Integer.MIN_VALUE,
                                          location);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a method reference.
     *
     * @param location The type path.
     * @param onLambda The lambda for this method reference.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        methodRef(final List<TypePathEntry> location) {
        return methodRef(location, null, -1);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a constructor reference.
     *
     * @param location The type path.
     * @param onLambda The lambda for this constructor reference.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        constructorRef(final List<TypePathEntry> location,
                       final JCLambda onLambda,
                       final int pos) {
        return new TypeAnnotationPosition(TargetType.CONSTRUCTOR_REFERENCE, pos,
                                          Integer.MIN_VALUE, onLambda,
                                          Integer.MIN_VALUE, Integer.MIN_VALUE,
                                          location);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a constructor reference.
     *
     * @param location The type path.
     * @param onLambda The lambda for this constructor reference.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        constructorRef(final List<TypePathEntry> location) {
        return constructorRef(location, null, -1);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a field.
     *
     * @param location The type path.
     * @param onLambda The lambda for this variable.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        field(final List<TypePathEntry> location,
              final JCLambda onLambda,
              final int pos) {
        return new TypeAnnotationPosition(TargetType.FIELD, pos,
                                          Integer.MIN_VALUE, onLambda,
                                          Integer.MIN_VALUE, Integer.MIN_VALUE,
                                          location);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a field.
     *
     * @param location The type path.
     */
    public static TypeAnnotationPosition
        field(final List<TypePathEntry> location) {
        return field(location, null, -1);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a field.
     *
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition field(final int pos) {
        return field(emptyPath, null, pos);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a local variable.
     *
     * @param location The type path.
     * @param onLambda The lambda for this variable.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        localVariable(final List<TypePathEntry> location,
                      final JCLambda onLambda,
                      final int pos) {
        return new TypeAnnotationPosition(TargetType.LOCAL_VARIABLE, pos,
                                          Integer.MIN_VALUE, onLambda,
                                          Integer.MIN_VALUE, Integer.MIN_VALUE,
                                          location);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a local variable.
     *
     * @param onLambda The lambda for this variable.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        localVariable(final JCLambda onLambda,
                      final int pos) {
        return localVariable(emptyPath, onLambda, pos);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a local variable.
     *
     * @param location The type path.
     */
    public static TypeAnnotationPosition
        localVariable(final List<TypePathEntry> location) {
        return localVariable(location, null, -1);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for an exception parameter.
     *
     * @param location The type path.
     * @param onLambda The lambda for this parameter.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        exceptionParameter(final List<TypePathEntry> location,
                           final JCLambda onLambda,
                           final int type_index,
                           final int pos) {
        return new TypeAnnotationPosition(TargetType.EXCEPTION_PARAMETER, pos,
                                          Integer.MIN_VALUE, onLambda,
                                          type_index, Integer.MIN_VALUE,
                                          location);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for an exception parameter.
     *
     * @param onLambda The lambda for this parameter.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        exceptionParameter(final JCLambda onLambda,
                           final int pos) {
        return exceptionParameter(emptyPath, onLambda, Integer.MIN_VALUE, pos);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for an exception parameter.
     *
     * @param location The type path.
     */
    public static TypeAnnotationPosition
        exceptionParameter(final List<TypePathEntry> location) {
        return exceptionParameter(location, null, Integer.MIN_VALUE, -1);
    }


    /**
     * Create a {@code TypeAnnotationPosition} for a resource variable.
     *
     * @param location The type path.
     * @param onLambda The lambda for this variable.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        resourceVariable(final List<TypePathEntry> location,
                         final JCLambda onLambda,
                         final int pos) {
        return new TypeAnnotationPosition(TargetType.RESOURCE_VARIABLE, pos,
                                          Integer.MIN_VALUE, onLambda,
                                          Integer.MIN_VALUE, Integer.MIN_VALUE,
                                          location);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a resource variable.
     *
     * @param onLambda The lambda for this variable.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        resourceVariable(final JCLambda onLambda,
                         final int pos) {
        return resourceVariable(emptyPath, onLambda, pos);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a resource variable.
     *
     * @param location The type path.
     * @param onLambda The lambda for this variable.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        resourceVariable(final List<TypePathEntry> location) {
        return resourceVariable(location, null, -1);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a new.
     *
     * @param location The type path.
     * @param onLambda The lambda for this variable.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        newObj(final List<TypePathEntry> location,
               final JCLambda onLambda,
               final int pos) {
        return new TypeAnnotationPosition(TargetType.NEW, pos,
                                          Integer.MIN_VALUE, onLambda,
                                          Integer.MIN_VALUE, Integer.MIN_VALUE,
                                          location);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a new.
     *
     * @param location The type path.
     * @param onLambda The lambda for this variable.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition newObj(final int pos) {
        return newObj(emptyPath, null, pos);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a new.
     *
     * @param location The type path.
     * @param onLambda The lambda for this variable.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        newObj(final List<TypePathEntry> location) {
        return newObj(location, null, -1);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a class extension.
     *
     * @param location The type path.
     * @param onLambda The lambda for this variable.
     * @param type_index The index of the interface.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        classExtends(final List<TypePathEntry> location,
                     final JCLambda onLambda,
                     final int type_index,
                     final int pos) {
        return new TypeAnnotationPosition(TargetType.CLASS_EXTENDS, pos,
                                          Integer.MIN_VALUE, onLambda,
                                          type_index, Integer.MIN_VALUE,
                                          location);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a class extension.
     *
     * @param location The type path.
     * @param onLambda The lambda for this variable.
     * @param type_index The index of the interface.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        classExtends(final List<TypePathEntry> location,
                     final JCLambda onLambda,
                     final int pos) {
        return classExtends(location, onLambda, -1, pos);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a class extension.
     *
     * @param location The type path.
     * @param type_index The index of the interface.
     */
    public static TypeAnnotationPosition
        classExtends(final List<TypePathEntry> location,
                     final int type_index) {
        return classExtends(location, null, type_index, -1);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a class extension.
     *
     * @param type_index The index of the interface.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition classExtends(final int type_index,
                                                      final int pos) {
        return classExtends(emptyPath, null, type_index, pos);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a class extension.
     *
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition classExtends(final int pos) {
        return classExtends(-1, pos);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for an instanceof.
     *
     * @param location The type path.
     * @param onLambda The lambda for this variable.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        instanceOf(final List<TypePathEntry> location,
                   final JCLambda onLambda,
                   final int pos) {
        return new TypeAnnotationPosition(TargetType.INSTANCEOF, pos,
                                          Integer.MIN_VALUE, onLambda,
                                          Integer.MIN_VALUE, Integer.MIN_VALUE,
                                          location);
    }
    /**
     * Create a {@code TypeAnnotationPosition} for an instanceof.
     *
     * @param location The type path.
     * @param onLambda The lambda for this variable.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        instanceOf(final List<TypePathEntry> location) {
        return instanceOf(location, null, -1);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a type cast.
     *
     * @param location The type path.
     * @param onLambda The lambda for this variable.
     * @param type_index The index into an intersection type.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        typeCast(final List<TypePathEntry> location,
                 final JCLambda onLambda,
                 final int type_index,
                 final int pos) {
        return new TypeAnnotationPosition(TargetType.CAST, pos,
                                          Integer.MIN_VALUE, onLambda,
                                          type_index, Integer.MIN_VALUE,
                                          location);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a type cast.
     *
     * @param location The type path.
     * @param onLambda The lambda for this variable.
     * @param type_index The index into an intersection type.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        typeCast(final List<TypePathEntry> location,
                 final int type_index) {
        return typeCast(location, null, type_index, -1);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a method
     * invocation type argument.
     *
     * @param location The type path.
     * @param onLambda The lambda for this variable.
     * @param type_index The index of the type argument.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        methodInvocationTypeArg(final List<TypePathEntry> location,
                                final JCLambda onLambda,
                                final int type_index,
                                final int pos) {
        return new TypeAnnotationPosition(TargetType.METHOD_INVOCATION_TYPE_ARGUMENT,
                                          pos, Integer.MIN_VALUE, onLambda,
                                          type_index, Integer.MIN_VALUE,
                                          location);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a method
     * invocation type argument.
     *
     * @param location The type path.
     * @param type_index The index of the type argument.
     */
    public static TypeAnnotationPosition
        methodInvocationTypeArg(final List<TypePathEntry> location,
                                final int type_index) {
        return methodInvocationTypeArg(location, null, type_index, -1);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a constructor
     * invocation type argument.
     *
     * @param location The type path.
     * @param onLambda The lambda for this variable.
     * @param type_index The index of the type argument.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        constructorInvocationTypeArg(final List<TypePathEntry> location,
                                     final JCLambda onLambda,
                                     final int type_index,
                                     final int pos) {
        return new TypeAnnotationPosition(TargetType.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT,
                                          pos, Integer.MIN_VALUE, onLambda,
                                          type_index, Integer.MIN_VALUE,
                                          location);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a constructor
     * invocation type argument.
     *
     * @param location The type path.
     * @param type_index The index of the type argument.
     */
    public static TypeAnnotationPosition
        constructorInvocationTypeArg(final List<TypePathEntry> location,
                                     final int type_index) {
        return constructorInvocationTypeArg(location, null, type_index, -1);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a type parameter.
     *
     * @param location The type path.
     * @param onLambda The lambda for this variable.
     * @param parameter_index The index of the type parameter.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        typeParameter(final List<TypePathEntry> location,
                      final JCLambda onLambda,
                      final int parameter_index,
                      final int pos) {
        return new TypeAnnotationPosition(TargetType.CLASS_TYPE_PARAMETER, pos,
                                          parameter_index, onLambda,
                                          Integer.MIN_VALUE, Integer.MIN_VALUE,
                                          location);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a type parameter.
     *
     * @param location The type path.
     * @param onLambda The lambda for this variable.
     * @param parameter_index The index of the type parameter.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        typeParameter(final List<TypePathEntry> location,
                      final int parameter_index) {
        return typeParameter(location, null, parameter_index, -1);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a method type parameter.
     *
     * @param location The type path.
     * @param onLambda The lambda for this variable.
     * @param parameter_index The index of the type parameter.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        methodTypeParameter(final List<TypePathEntry> location,
                            final JCLambda onLambda,
                            final int parameter_index,
                            final int pos) {
        return new TypeAnnotationPosition(TargetType.METHOD_TYPE_PARAMETER,
                                          pos, parameter_index, onLambda,
                                          Integer.MIN_VALUE, Integer.MIN_VALUE,
                                          location);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a method type parameter.
     *
     * @param location The type path.
     * @param parameter_index The index of the type parameter.
     */
    public static TypeAnnotationPosition
        methodTypeParameter(final List<TypePathEntry> location,
                            final int parameter_index) {
        return methodTypeParameter(location, null, parameter_index, -1);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a throws clause.
     *
     * @param location The type path.
     * @param onLambda The lambda for this variable.
     * @param type_index The index of the exception.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        methodThrows(final List<TypePathEntry> location,
                     final JCLambda onLambda,
                     final int type_index,
                     final int pos) {
        return new TypeAnnotationPosition(TargetType.THROWS, pos,
                                          Integer.MIN_VALUE, onLambda,
                                          type_index, Integer.MIN_VALUE,
                                          location);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a throws clause.
     *
     * @param location The type path.
     * @param type_index The index of the exception.
     */
    public static TypeAnnotationPosition
        methodThrows(final List<TypePathEntry> location,
                     final int type_index) {
        return methodThrows(location, null, type_index, -1);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a method reference
     * type argument.
     *
     * @param location The type path.
     * @param onLambda The lambda for this variable.
     * @param parameter_index The index of the type argument.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        methodRefTypeArg(final List<TypePathEntry> location,
                         final JCLambda onLambda,
                         final int type_index,
                         final int pos) {
        return new TypeAnnotationPosition(TargetType.METHOD_REFERENCE_TYPE_ARGUMENT,
                                          pos, Integer.MIN_VALUE, onLambda,
                                          type_index, Integer.MIN_VALUE,
                                          location);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a method reference
     * type argument.
     *
     * @param location The type path.
     * @param onLambda The lambda for this variable.
     * @param parameter_index The index of the type argument.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        methodRefTypeArg(final List<TypePathEntry> location,
                         final int type_index) {
        return methodRefTypeArg(location, null, type_index, -1);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a constructor reference
     * type argument.
     *
     * @param location The type path.
     * @param onLambda The lambda for this variable.
     * @param parameter_index The index of the type argument.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        constructorRefTypeArg(final List<TypePathEntry> location,
                              final JCLambda onLambda,
                              final int type_index,
                              final int pos) {
        return new TypeAnnotationPosition(TargetType.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT,
                                          pos, Integer.MIN_VALUE, onLambda,
                                          type_index, Integer.MIN_VALUE,
                                          location);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a constructor reference
     * type argument.
     *
     * @param location The type path.
     * @param parameter_index The index of the type argument.
     */
    public static TypeAnnotationPosition
        constructorRefTypeArg(final List<TypePathEntry> location,
                              final int type_index) {
        return constructorRefTypeArg(location, null, type_index, -1);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a type parameter bound.
     *
     * @param location The type path.
     * @param onLambda The lambda for this variable.
     * @param parameter_index The index of the type parameter.
     * @param bound_index The index of the type parameter bound.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        typeParameterBound(final List<TypePathEntry> location,
                           final JCLambda onLambda,
                           final int parameter_index,
                           final int bound_index,
                           final int pos) {
        return new TypeAnnotationPosition(TargetType.CLASS_TYPE_PARAMETER_BOUND,
                                          pos, parameter_index, onLambda,
                                          Integer.MIN_VALUE, bound_index,
                                          location);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a type parameter bound.
     *
     * @param location The type path.
     * @param parameter_index The index of the type parameter.
     * @param bound_index The index of the type parameter bound.
     */
    public static TypeAnnotationPosition
        typeParameterBound(final List<TypePathEntry> location,
                           final int parameter_index,
                           final int bound_index) {
        return typeParameterBound(location, null, parameter_index,
                                  bound_index, -1);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a method type
     * parameter bound.
     *
     * @param location The type path.
     * @param onLambda The lambda for this variable.
     * @param parameter_index The index of the type parameter.
     * @param bound_index The index of the type parameter bound.
     * @param pos The position from the associated tree node.
     */
    public static TypeAnnotationPosition
        methodTypeParameterBound(final List<TypePathEntry> location,
                                 final JCLambda onLambda,
                                 final int parameter_index,
                                 final int bound_index,
                                 final int pos) {
        return new TypeAnnotationPosition(TargetType.METHOD_TYPE_PARAMETER_BOUND,
                                          pos, parameter_index, onLambda,
                                          Integer.MIN_VALUE, bound_index,
                                          location);
    }

    /**
     * Create a {@code TypeAnnotationPosition} for a method type
     * parameter bound.
     *
     * @param location The type path.
     * @param parameter_index The index of the type parameter.
     * @param bound_index The index of the type parameter bound.
     */
    public static TypeAnnotationPosition
        methodTypeParameterBound(final List<TypePathEntry> location,
                                 final int parameter_index,
                                 final int bound_index) {
        return methodTypeParameterBound(location, null, parameter_index,
                                        bound_index, -1);
    }
}
