Copyright (c) 2000, 2016 IBM Corporation and others. This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which accompanies this distribution, and is available at https://www.eclipse.org/legal/epl-2.0/ SPDX-License-Identifier: EPL-2.0 Contributors: IBM Corporation - initial API and implementation
/******************************************************************************* * Copyright (c) 2000, 2016 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/
package org.eclipse.jdt.internal.corext.template.java; import java.util.Arrays; import org.eclipse.jdt.core.CompletionProposal; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.Signature;
Utilities for Signature operations.
See Also:
  • Signature
Since:3.1
/** * Utilities for Signature operations. * * @see Signature * @since 3.1 */
public final class SignatureUtil {
The signature of the null type. This type does not really exist in the type system. It represents the bound of type variables that have no lower bound, for example the parameter type to the add method of an instance of java.util.List<? extends Number>.

The only possible value that has that type is null.

The representation of the null type is the signature of a type variable named null ("Tnull;"), which will only work if no such variable gets declared in the same context.

/** * The signature of the null type. This type does not really exist in the * type system. It represents the bound of type variables that have no lower * bound, for example the parameter type to the <code>add</code> method of * an instance of <code>java.util.List&lt;? extends Number&gt;</code>. * <p> * The only possible value that has that type is <code>null</code>. * </p> * <p> * The representation of the null type is the signature of a type variable * named <code>null</code> ({@value}), which will only work if no such * variable gets declared in the same context. */
private static final String NULL_TYPE_SIGNATURE= "Tnull;"; //$NON-NLS-1$ private static final char[] NULL_TYPE_SIGNATURE_ARRAY= NULL_TYPE_SIGNATURE.toCharArray();
The signature of java.lang.Object ("Ljava.lang.Object;").
/** * The signature of <code>java.lang.Object</code> ({@value}). */
private static final String OBJECT_SIGNATURE= "Ljava.lang.Object;"; //$NON-NLS-1$ private static final char[] OBJECT_SIGNATURE_ARRAY= OBJECT_SIGNATURE.toCharArray(); private SignatureUtil() { // do not instantiate }
Returns true if signature is the signature of the java.lang.Object type.
Params:
  • signature – the signature
Returns:true if signature is the signature of the java.lang.Object type, false otherwise
/** * Returns <code>true</code> if <code>signature</code> is the * signature of the <code>java.lang.Object</code> type. * * @param signature the signature * @return <code>true</code> if <code>signature</code> is the * signature of the <code>java.lang.Object</code> type, * <code>false</code> otherwise */
public static boolean isJavaLangObject(String signature) { return OBJECT_SIGNATURE.equals(signature); }
Returns the upper bound of a type signature. Returns the signature of java.lang.Object if signature is a lower bound (? super T); returns the signature of the type T of an upper bound (? extends T) or signature itself if it is not a bound signature.
Params:
  • signature – the signature
Returns:the upper bound signature of signature
/** * Returns the upper bound of a type signature. Returns the signature of <code>java.lang.Object</code> if * <code>signature</code> is a lower bound (<code>? super T</code>); returns * the signature of the type <code>T</code> of an upper bound (<code>? extends T</code>) * or <code>signature</code> itself if it is not a bound signature. * * @param signature the signature * @return the upper bound signature of <code>signature</code> */
public static String getUpperBound(String signature) { return String.valueOf(getUpperBound(signature.toCharArray())); }
Returns the upper bound of a type signature. Returns the signature of java.lang.Object if signature is a lower bound (? super T); returns the signature of the type T of an upper bound (? extends T) or signature itself if it is not a bound signature.
Params:
  • signature – the signature
Returns:the upper bound signature of signature
/** * Returns the upper bound of a type signature. Returns the signature of <code>java.lang.Object</code> if * <code>signature</code> is a lower bound (<code>? super T</code>); returns * the signature of the type <code>T</code> of an upper bound (<code>? extends T</code>) * or <code>signature</code> itself if it is not a bound signature. * * @param signature the signature * @return the upper bound signature of <code>signature</code> */
public static char[] getUpperBound(char[] signature) { if (signature.length < 1) return signature; if (signature[0] == Signature.C_STAR) return OBJECT_SIGNATURE_ARRAY; int superIndex= indexOf(signature, Signature.C_SUPER); if (superIndex == 0) return OBJECT_SIGNATURE_ARRAY; if (superIndex != -1) { char afterSuper= signature[superIndex + 1]; if (afterSuper == Signature.C_STAR) { char[] type= new char[signature.length - 1]; System.arraycopy(signature, 0, type, 0, superIndex); type[superIndex]= Signature.C_STAR; System.arraycopy(signature, superIndex + 2, type, superIndex + 1, signature.length - superIndex - 2); return getUpperBound(type); } if (afterSuper == Signature.C_EXTENDS) { int typeEnd= typeEnd(signature, superIndex + 1); char[] type= new char[signature.length - (typeEnd - superIndex - 1)]; System.arraycopy(signature, 0, type, 0, superIndex); type[superIndex]= Signature.C_STAR; System.arraycopy(signature, typeEnd, type, superIndex + 1, signature.length - typeEnd); return getUpperBound(type); } } if (signature[0] == Signature.C_EXTENDS) { char[] type= new char[signature.length - 1]; System.arraycopy(signature, 1, type, 0, signature.length - 1); return type; } return signature; }
Returns the lower bound of a type signature. Returns the null type signature if signature is a wildcard or upper bound (? extends T); returns the signature of the type T of a lower bound (? super T) or signature itself if it is not a bound signature.
Params:
  • signature – the signature
Returns:the lower bound signature of signature
/** * Returns the lower bound of a type signature. Returns the null type * signature if <code>signature</code> is a wildcard or upper bound (<code>? extends T</code>); * returns the signature of the type <code>T</code> of a lower bound (<code>? super T</code>) * or <code>signature</code> itself if it is not a bound signature. * * @param signature the signature * @return the lower bound signature of <code>signature</code> */
public static String getLowerBound(String signature) { return String.valueOf(getLowerBound(signature.toCharArray())); }
Returns the lower bound of a type signature. Returns the null type signature if signature is a wildcard or upper bound (? extends T); returns the signature of the type T of a lower bound (? super T) or signature itself if it is not a bound signature.
Params:
  • signature – the signature
Returns:the lower bound signature of signature
/** * Returns the lower bound of a type signature. Returns the null type * signature if <code>signature</code> is a wildcard or upper bound (<code>? extends T</code>); * returns the signature of the type <code>T</code> of a lower bound (<code>? super T</code>) * or <code>signature</code> itself if it is not a bound signature. * * @param signature the signature * @return the lower bound signature of <code>signature</code> */
public static char[] getLowerBound(char[] signature) { if (signature.length < 1) return signature; if (signature.length == 1 && signature[0] == Signature.C_STAR) return signature; int superIndex= indexOf(signature, Signature.C_EXTENDS); if (superIndex == 0) return NULL_TYPE_SIGNATURE_ARRAY; if (superIndex != -1) { char afterSuper= signature[superIndex + 1]; if (afterSuper == Signature.C_STAR || afterSuper == Signature.C_EXTENDS) // impossible captured type return NULL_TYPE_SIGNATURE_ARRAY; } char[][] typeArguments= Signature.getTypeArguments(signature); for (int i= 0; i < typeArguments.length; i++) if (Arrays.equals(typeArguments[i], NULL_TYPE_SIGNATURE_ARRAY)) return NULL_TYPE_SIGNATURE_ARRAY; if (signature[0] == Signature.C_SUPER) { char[] type= new char[signature.length - 1]; System.arraycopy(signature, 1, type, 0, signature.length - 1); return type; } return signature; } private static int indexOf(char[] signature, char ch) { for (int i= 0; i < signature.length; i++) { if (signature[i] == ch) return i; } return -1; }
Returns the fully qualified type name of the given signature, with any type parameters and arrays erased.
Params:
  • signature – the signature
Throws:
Returns:the fully qualified type name of the signature
/** * Returns the fully qualified type name of the given signature, with any * type parameters and arrays erased. * * @param signature the signature * @return the fully qualified type name of the signature * @throws IllegalArgumentException if the signature is syntactically incorrect */
public static String stripSignatureToFQN(String signature) throws IllegalArgumentException { signature= Signature.getTypeErasure(signature); signature= Signature.getElementType(signature); return Signature.toString(signature); }
Returns the qualified signature corresponding to signature.
Params:
  • signature – the signature to qualify
  • context – the type inside which an unqualified type will be resolved to find the qualifier, or null if no context is available
Returns:the qualified signature
/** * Returns the qualified signature corresponding to * <code>signature</code>. * * @param signature the signature to qualify * @param context the type inside which an unqualified type will be * resolved to find the qualifier, or <code>null</code> if no * context is available * @return the qualified signature */
public static String qualifySignature(final String signature, final IType context) { if (context == null) return signature; String qualifier= Signature.getSignatureQualifier(signature); if (qualifier.length() > 0) return signature; String elementType= Signature.getElementType(signature); String erasure= Signature.getTypeErasure(elementType); String simpleName= Signature.getSignatureSimpleName(erasure); String genericSimpleName= Signature.getSignatureSimpleName(elementType); int dim= Signature.getArrayCount(signature); try { String[][] strings= context.resolveType(simpleName); if (strings != null && strings.length > 0) qualifier= strings[0][0]; } catch (JavaModelException e) { // ignore - not found } if (qualifier.length() == 0) return signature; String qualifiedType= Signature.toQualifiedName(new String[] {qualifier, genericSimpleName}); String qualifiedSignature= Signature.createTypeSignature(qualifiedType, true); String newSignature= Signature.createArraySignature(qualifiedSignature, dim); return newSignature; }
Takes a method signature [< typeVariableName : formalTypeDecl >] ( paramTypeSig1* ) retTypeSig and returns it with any parameter signatures filtered through getLowerBound and the return type filtered through getUpperBound. Any preceding formal type variable declarations are removed.

TODO this is a temporary workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=83600

Params:
  • signature – the method signature to convert
Returns:the signature with no bounded types
/** * Takes a method signature * <code>[&lt; typeVariableName : formalTypeDecl &gt;] ( paramTypeSig1* ) retTypeSig</code> * and returns it with any parameter signatures filtered through * <code>getLowerBound</code> and the return type filtered through * <code>getUpperBound</code>. Any preceding formal type variable * declarations are removed. * <p> * TODO this is a temporary workaround for * https://bugs.eclipse.org/bugs/show_bug.cgi?id=83600 * </p> * * @param signature the method signature to convert * @return the signature with no bounded types */
public static char[] unboundedSignature(char[] signature) { if (signature == null || signature.length < 2) return signature; final boolean BUG_83600= true; // XXX the signatures from CompletionRequestor contain a superfluous '+' // before type parameters to parameter types if (BUG_83600) { signature= fix83600(signature); } StringBuilder res= new StringBuilder("("); //$NON-NLS-1$ char[][] parameters= Signature.getParameterTypes(signature); for (int i= 0; i < parameters.length; i++) { char[] param= parameters[i]; res.append(getLowerBound(param)); } res.append(')'); res.append(getUpperBound(Signature.getReturnType(signature))); return res.toString().toCharArray(); }
TODO this is a temporary workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=83600 and https://bugs.eclipse.org/bugs/show_bug.cgi?id=85293
Params:
  • signature – the method signature to convert
Returns:the fixed signature
/** * TODO this is a temporary workaround for * https://bugs.eclipse.org/bugs/show_bug.cgi?id=83600 and * https://bugs.eclipse.org/bugs/show_bug.cgi?id=85293 * * @param signature the method signature to convert * @return the fixed signature */
public static char[] fix83600(char[] signature) { if (signature == null || signature.length < 2) return signature; return Signature.removeCapture(signature); } private static int typeEnd(char[] signature, int pos) { int depth= 0; while (pos < signature.length) { switch (signature[pos]) { case Signature.C_GENERIC_START: depth++; break; case Signature.C_GENERIC_END: if (depth == 0) return pos; depth--; break; case Signature.C_SEMICOLON: if (depth == 0) return pos + 1; break; } pos++; } return pos + 1; } public static String getQualifiedTypeName(CompletionProposal proposal) { return String.valueOf(Signature.toCharArray(Signature .getTypeErasure(proposal.getSignature()))); } public static String getSimpleTypeName(CompletionProposal proposal) { return Signature.getSimpleName(getQualifiedTypeName(proposal)); } }