static StringBuilder AppendGenericTypeNameFromSignature (StringBuilder typeBuilder, string value, ref int index)
		{
			var array   = GetArraySuffix (value, ref index);
			var builtin = GetBuiltinName (value, ref index);
			if (builtin != null) {
				return typeBuilder.Append (builtin).Append (array);
			}
			switch (value [index]) {
			case 'L':
				index++;
				int depth   = 0;
				while (index < value.Length) {
					var c   = value [index++];
					if (depth == 0 && c == ';')
						break;

					if (c == '<') {
						depth++;
						typeBuilder.Append ("<");
						AppendGenericTypeNameFromSignature (typeBuilder, value, ref index);
					} else if (c == '>') {
						typeBuilder.Append (">");
						depth--;
					} else if (depth > 0) {
						index--;
						typeBuilder.Append (", ");
						AppendGenericTypeNameFromSignature (typeBuilder, value, ref index);
					} else if (c == '/' || c == '$') {
						typeBuilder.Append ('.');
					} else {
						typeBuilder.Append (c);
					}
				}
				return typeBuilder.Append (array);
			case 'T':
				index++;
				typeBuilder.Append (Signature.ExtractIdentifier (value, ref index));
				index++;    // consume ';'
				return typeBuilder.Append(array);
			case '*':
				index++;
				return typeBuilder.Append ("?");
			case '+':
				index++;
				typeBuilder.Append ("? extends ");
				return AppendGenericTypeNameFromSignature (typeBuilder, value, ref index);
			case '-':
				index++;
				typeBuilder.Append ("? super ");
				return AppendGenericTypeNameFromSignature (typeBuilder, value, ref index);
			}
			typeBuilder.Append ("/* should not be reached */").Append (value.Substring (index));
			index = value.Length;
			return typeBuilder;
		}
		string SignatureToJavaTypeName (string value)
		{
			if (string.IsNullOrEmpty (value))
				return string.Empty;
			int index   = 0;
			var array   = GetArraySuffix (value, ref index);
			var builtin = GetBuiltinName (value, ref index);
			if (builtin != null)
				return builtin + array;
			if (value [index] == 'L') {
				index++;
				var type    = new StringBuilder ();
				int depth   = 0;
				int e       = index;
				while (e < value.Length) {
					var c = value [e++];
					if (depth == 0 && c == ';')
						break;

					if (c == '<') {
						depth++;
					} else if (c == '>') {
						depth--;
					} else if (depth > 0) {
						;
					} else if (c == '/' || c == '$') {
						type.Append ('.');
					} else {
						type.Append (c);
					}
				}
				return type.Append (array).ToString ();
			}
			if (value [index] == 'T') {
				index++;
				var tp  = Signature.ExtractIdentifier (value, ref index);
				if (signature != null)
					return SignatureToJavaTypeName (signature.TypeParameters [tp].ClassBound) + array;
			}
			return value;
		}