/******************************************************************************* * Copyright (c) 2006 IBM Corporation. * 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: * IBM Corporation - initial API and implementation *******************************************************************************/ package com.ibm.wala.types.generics; import java.util.ArrayList; import java.util.Iterator; import com.ibm.wala.types.TypeReference; import com.ibm.wala.util.debug.Assertions; /** * UNDER CONSTRUCTION. * * <verbatim> TypeSignature: FieldTypeSignature BaseType (code for a primitive) * * FieldTypeSignature: ClassTypeSignature ArrayTypeSignature TypeVariableSignature * * TypeVariableSignature: T identifier ; * * </verbatim> * * @author sjfink * */ public abstract class TypeSignature extends Signature { TypeSignature(String s) { super(s); } public static TypeSignature make(String s) throws IllegalArgumentException { if (s == null) { throw new IllegalArgumentException("s is null"); } if (s.length() == 0) { throw new IllegalArgumentException("illegal empty string s"); } assert (s.length() > 0); switch (s.charAt(0)) { case TypeReference.VoidTypeCode: Assertions.UNREACHABLE(); return null; case TypeReference.BooleanTypeCode: return BaseType.BOOLEAN; case TypeReference.ByteTypeCode: return BaseType.BYTE; case TypeReference.ShortTypeCode: return BaseType.SHORT; case TypeReference.IntTypeCode: return BaseType.INT; case TypeReference.LongTypeCode: return BaseType.LONG; case TypeReference.FloatTypeCode: return BaseType.FLOAT; case TypeReference.DoubleTypeCode: return BaseType.DOUBLE; case TypeReference.CharTypeCode: return BaseType.CHAR; case 'L': return ClassTypeSignature.makeClassTypeSig(s); case 'T': return TypeVariableSignature.make(s); case TypeReference.ArrayTypeCode: return ArrayTypeSignature.make(s); default: throw new IllegalArgumentException("malformed TypeSignature string:" + s); } } public abstract boolean isTypeVariable(); public abstract boolean isClassTypeSignature(); public abstract boolean isArrayTypeSignature(); public abstract boolean isBaseType(); /** * @param typeSigs TypeSignature* * @return tokenize it */ static String[] parseForTypeSignatures(String typeSigs) throws IllegalArgumentException { ArrayList<String> sigs = new ArrayList<String>(10); if (typeSigs.length() < 2) { // TODO: check this? throw new IllegalArgumentException("illegal string of TypeSignature " + typeSigs); } int i = 1; while (true) { switch (typeSigs.charAt(i++)) { case TypeReference.VoidTypeCode: sigs.add(TypeReference.VoidName.toString()); continue; case TypeReference.BooleanTypeCode: sigs.add(TypeReference.BooleanName.toString()); continue; case TypeReference.ByteTypeCode: sigs.add(TypeReference.ByteName.toString()); continue; case TypeReference.ShortTypeCode: sigs.add(TypeReference.ShortName.toString()); continue; case TypeReference.IntTypeCode: sigs.add(TypeReference.IntName.toString()); continue; case TypeReference.LongTypeCode: sigs.add(TypeReference.LongName.toString()); continue; case TypeReference.FloatTypeCode: sigs.add(TypeReference.FloatName.toString()); continue; case TypeReference.DoubleTypeCode: sigs.add(TypeReference.DoubleName.toString()); continue; case TypeReference.CharTypeCode: sigs.add(TypeReference.CharName.toString()); continue; case TypeReference.ClassTypeCode: { int off = i - 1; int depth = 0; while (typeSigs.charAt(i++) != ';' || depth > 0) { if (typeSigs.charAt(i - 1) == '<') { depth++; } if (typeSigs.charAt(i - 1) == '>') { depth--; } } sigs.add(typeSigs.substring(off, i)); continue; } case TypeReference.ArrayTypeCode: { switch (typeSigs.charAt(i)) { case TypeReference.BooleanTypeCode: case TypeReference.ByteTypeCode: case TypeReference.IntTypeCode: sigs.add(typeSigs.substring(i - 1, i + 1)); break; case 'T': case TypeReference.ClassTypeCode: int off = i - 1; i++; int depth = 0; while (typeSigs.charAt(i++) != ';' || depth > 0) { if (typeSigs.charAt(i - 1) == '<') { depth++; } if (typeSigs.charAt(i - 1) == '>') { depth--; } } sigs.add(typeSigs.substring(off, i)); break; default: Assertions.UNREACHABLE("BANG " + typeSigs.charAt(i)); } continue; } case (byte) 'T': { // type variable int off = i - 1; while (typeSigs.charAt(i++) != ';') ; sigs.add(typeSigs.substring(off, i)); continue; } case (byte) ')': // end of parameter list int size = sigs.size(); if (size == 0) { return null; } Iterator<String> it = sigs.iterator(); String[] result = new String[size]; for (int j = 0; j < size; j++) { result[j] = it.next(); } return result; default: assert false : "bad type signature list " + typeSigs; } } } }