/******************************************************************************* * Copyright (c) 2015, 2016 Google, Inc and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Stefan Xenos (Google) - Initial implementation *******************************************************************************/ package org.eclipse.jdt.internal.core.nd.java.model; import org.eclipse.jdt.internal.compiler.codegen.AnnotationTargetTypeConstants; import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation; import org.eclipse.jdt.internal.compiler.env.IBinaryTypeAnnotation; public class TypeAnnotationBuilder implements ITypeAnnotationBuilder { TypeAnnotationBuilder parent; int kind; int index; int length; int target; int targetParameter; int targetParameter2; private TypeAnnotationBuilder(TypeAnnotationBuilder parent, int kind, int index, int length, int nextTarget, int nextTargetParameter, int nextTargetParameter2) { super(); this.parent = parent; this.kind = kind; this.index = index; this.length = length; this.target = nextTarget; this.targetParameter = nextTargetParameter; this.targetParameter2 = nextTargetParameter2; } public static TypeAnnotationBuilder create() { return new TypeAnnotationBuilder(null, 0, 0, 0, -1, -1, -1); } private TypeAnnotationBuilder walk(int nextKind, int nextIndex) { return new TypeAnnotationBuilder(this, nextKind, nextIndex, this.length+1, this.target, this.targetParameter, this.targetParameter2); } private TypeAnnotationBuilder toTarget(int newTarget) { return new TypeAnnotationBuilder(this.parent, this.kind, this.index, this.length, newTarget, this.targetParameter, this.targetParameter2); } private TypeAnnotationBuilder toTarget(int newTarget, int parameter) { return new TypeAnnotationBuilder(this.parent, this.kind, this.index, this.length, newTarget, parameter, this.targetParameter2); } private TypeAnnotationBuilder toTarget2(int parameter) { return new TypeAnnotationBuilder(this.parent, this.kind, this.index, this.length, this.target, this.targetParameter, parameter); } @Override public ITypeAnnotationBuilder toField() { return toTarget(AnnotationTargetTypeConstants.FIELD); } @Override public ITypeAnnotationBuilder toMethodReturn() { return toTarget(AnnotationTargetTypeConstants.METHOD_RETURN); } @Override public ITypeAnnotationBuilder toReceiver() { return toTarget(AnnotationTargetTypeConstants.METHOD_RECEIVER); } @Override public ITypeAnnotationBuilder toTypeParameter(boolean isClassTypeParameter, int rank) { int targetType = isClassTypeParameter ? AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER : AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER; return toTarget(targetType, rank); } @Override public ITypeAnnotationBuilder toTypeParameterBounds(boolean isClassTypeParameter, int parameterRank) { int targetType = isClassTypeParameter ? AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER_BOUND : AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER_BOUND; return toTarget(targetType, parameterRank); } @Override public ITypeAnnotationBuilder toTypeBound(short boundIndex) { return toTarget2(boundIndex); } @Override public ITypeAnnotationBuilder toSupertype(short superTypeIndex) { return toTarget(AnnotationTargetTypeConstants.CLASS_EXTENDS, superTypeIndex); } @Override public ITypeAnnotationBuilder toMethodParameter(short parameterIndex) { return toTarget(AnnotationTargetTypeConstants.METHOD_FORMAL_PARAMETER, parameterIndex); } @Override public ITypeAnnotationBuilder toThrows(int rank) { return toTarget(AnnotationTargetTypeConstants.THROWS, rank); } @Override public ITypeAnnotationBuilder toTypeArgument(int rank) { return walk(AnnotationTargetTypeConstants.TYPE_ARGUMENT, rank); } @Override public ITypeAnnotationBuilder toWildcardBound() { return walk(AnnotationTargetTypeConstants.WILDCARD_BOUND, 0); } @Override public ITypeAnnotationBuilder toNextArrayDimension() { return walk(AnnotationTargetTypeConstants.NEXT_ARRAY_DIMENSION, 0); } @Override public ITypeAnnotationBuilder toNextNestedType() { return walk(AnnotationTargetTypeConstants.NEXT_NESTED_TYPE, 0); } @Override public IBinaryTypeAnnotation build(IBinaryAnnotation annotation) { return new IndexBinaryTypeAnnotation(this.target, this.targetParameter, this.targetParameter2, getTypePath(), annotation); } private int[] getTypePath() { if (this.length == 0) { return IBinaryTypeAnnotation.NO_TYPE_PATH; } int[] result = new int[this.length * 2]; TypeAnnotationBuilder next = this; while (next != null && next.length > 0) { int writeIdx = (next.length - 1) * 2; result[writeIdx] = next.kind; result[writeIdx + 1] = next.index; next = next.parent; } return result; } }