static ITypeReference ParseTypeName(string typeName, ref int pos)
 {
     string reflectionTypeName = typeName;
     if (pos == typeName.Length)
         throw new ReflectionNameParseException(pos, "Unexpected end");
     ITypeReference result;
     if (reflectionTypeName[pos] == '`') {
         // type parameter reference
         pos++;
         if (pos == reflectionTypeName.Length)
             throw new ReflectionNameParseException(pos, "Unexpected end");
         if (reflectionTypeName[pos] == '`') {
             // method type parameter reference
             pos++;
             int index = ReflectionHelper.ReadTypeParameterCount(reflectionTypeName, ref pos);
             result = TypeParameterReference.Create(SymbolKind.Method, index);
         } else {
             // class type parameter reference
             int index = ReflectionHelper.ReadTypeParameterCount(reflectionTypeName, ref pos);
             result = TypeParameterReference.Create(SymbolKind.TypeDefinition, index);
         }
     } else {
         // not a type parameter reference: read the actual type name
         List<ITypeReference> typeArguments = new List<ITypeReference>();
         int typeParameterCount;
         string typeNameWithoutSuffix = ReadTypeName(typeName, ref pos, true, out typeParameterCount, typeArguments);
         result = new GetPotentiallyNestedClassTypeReference(typeNameWithoutSuffix, typeParameterCount);
         while (pos < typeName.Length && typeName[pos] == '.') {
             pos++;
             string nestedTypeName = ReadTypeName(typeName, ref pos, false, out typeParameterCount, typeArguments);
             result = new NestedTypeReference(result, nestedTypeName, typeParameterCount);
         }
         if (typeArguments.Count > 0) {
             result = new ParameterizedTypeReference(result, typeArguments);
         }
     }
     while (pos < typeName.Length) {
         switch (typeName[pos]) {
             case '[':
                 int dimensions = 1;
                 do {
                     pos++;
                     if (pos == typeName.Length)
                         throw new ReflectionNameParseException(pos, "Unexpected end");
                     if (typeName[pos] == ',')
                         dimensions++;
                 } while (typeName[pos] != ']');
                 result = new ArrayTypeReference(result, dimensions);
                 break;
             case '*':
                 result = new PointerTypeReference(result);
                 break;
             case '@':
                 result = new ByReferenceTypeReference(result);
                 break;
             default:
                 return result;
         }
         pos++;
     }
     return result;
 }
		static ITypeReference ParseReflectionName(string reflectionTypeName, ref int pos, IEntity entity)
		{
			if (pos == reflectionTypeName.Length)
				throw new ReflectionNameParseException(pos, "Unexpected end");
			if (reflectionTypeName[pos] == '`') {
				// type parameter reference
				pos++;
				if (pos == reflectionTypeName.Length)
					throw new ReflectionNameParseException(pos, "Unexpected end");
				if (reflectionTypeName[pos] == '`') {
					// method type parameter reference
					pos++;
					int index = ReadTypeParameterCount(reflectionTypeName, ref pos);
					IMethod method = entity as IMethod;
					if (method != null && index >= 0 && index < method.TypeParameters.Count)
						return method.TypeParameters[index];
					else
						return SharedTypes.UnknownType;
				} else {
					// class type parameter reference
					int index = ReadTypeParameterCount(reflectionTypeName, ref pos);
					ITypeDefinition c = (entity as ITypeDefinition) ?? (entity != null ? entity.DeclaringTypeDefinition : null);
					if (c != null && index >= 0 && index < c.TypeParameters.Count)
						return c.TypeParameters[index];
					else
						return SharedTypes.UnknownType;
				}
			}
			// not a type parameter reference: read the actual type name
			int tpc;
			string typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc);
			ITypeReference reference = new GetClassTypeReference(typeName, tpc);
			// read type suffixes
			while (pos < reflectionTypeName.Length) {
				switch (reflectionTypeName[pos++]) {
					case '+':
						typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc);
						reference = new NestedTypeReference(reference, typeName, tpc);
						break;
					case '*':
						reference = new PointerTypeReference(reference);
						break;
					case '&':
						reference = new ByReferenceTypeReference(reference);
						break;
					case '[':
						// this might be an array or a generic type
						if (pos == reflectionTypeName.Length)
							throw new ReflectionNameParseException(pos, "Unexpected end");
						if (reflectionTypeName[pos] == '[') {
							// it's a generic type
							List<ITypeReference> typeArguments = new List<ITypeReference>(tpc);
							pos++;
							typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos, entity));
							if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']')
								pos++;
							else
								throw new ReflectionNameParseException(pos, "Expected end of type argument");
							
							while (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') {
								pos++;
								if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == '[')
									pos++;
								else
									throw new ReflectionNameParseException(pos, "Expected another type argument");
								
								typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos, entity));
								
								if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']')
									pos++;
								else
									throw new ReflectionNameParseException(pos, "Expected end of type argument");
							}
							
							if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') {
								pos++;
								reference = new ParameterizedTypeReference(reference, typeArguments);
							} else {
								throw new ReflectionNameParseException(pos, "Expected end of generic type");
							}
						} else {
							// it's an array
							int dimensions = 1;
							while (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') {
								dimensions++;
								pos++;
							}
							if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') {
								pos++; // end of array
								reference = new ArrayTypeReference(reference, dimensions);
							} else {
								throw new ReflectionNameParseException(pos, "Invalid array modifier");
							}
						}
						break;
					case ',':
						// assembly qualified name, ignore everything up to the end/next ']'
						while (pos < reflectionTypeName.Length && reflectionTypeName[pos] != ']')
							pos++;
						break;
					default:
						pos--; // reset pos to the character we couldn't read
						if (reflectionTypeName[pos] == ']')
							return reference; // return from a nested generic
						else
							throw new ReflectionNameParseException(pos, "Unexpected character: '" + reflectionTypeName[pos] + "'");
				}
			}
			return reference;
		}
        bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
        {
            NestedTypeReference o = other as NestedTypeReference;

            return(o != null && declaringTypeRef == o.declaringTypeRef && name == o.name && additionalTypeParameterCount == o.additionalTypeParameterCount);
        }
		static ITypeReference ParseReflectionName(string reflectionTypeName, ref int pos)
		{
			if (pos == reflectionTypeName.Length)
				throw new ReflectionNameParseException(pos, "Unexpected end");
			ITypeReference reference;
			if (reflectionTypeName[pos] == '`') {
				// type parameter reference
				pos++;
				if (pos == reflectionTypeName.Length)
					throw new ReflectionNameParseException(pos, "Unexpected end");
				if (reflectionTypeName[pos] == '`') {
					// method type parameter reference
					pos++;
					int index = ReadTypeParameterCount(reflectionTypeName, ref pos);
					reference = TypeParameterReference.Create(SymbolKind.Method, index);
				} else {
					// class type parameter reference
					int index = ReadTypeParameterCount(reflectionTypeName, ref pos);
					reference = TypeParameterReference.Create(SymbolKind.TypeDefinition, index);
				}
			} else {
				// not a type parameter reference: read the actual type name
				int tpc;
				string typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc);
				string assemblyName = SkipAheadAndReadAssemblyName(reflectionTypeName, pos);
				reference = CreateGetClassTypeReference(assemblyName, typeName, tpc);
			}
			// read type suffixes
			while (pos < reflectionTypeName.Length) {
				switch (reflectionTypeName[pos++]) {
					case '+':
						int tpc;
						string typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc);
						reference = new NestedTypeReference(reference, typeName, tpc);
						break;
					case '*':
						reference = new PointerTypeReference(reference);
						break;
					case '&':
						reference = new ByReferenceTypeReference(reference);
						break;
					case '[':
						// this might be an array or a generic type
						if (pos == reflectionTypeName.Length)
							throw new ReflectionNameParseException(pos, "Unexpected end");
						if (reflectionTypeName[pos] == '[') {
							// it's a generic type
							List<ITypeReference> typeArguments = new List<ITypeReference>();
							pos++;
							typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos));
							if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']')
								pos++;
							else
								throw new ReflectionNameParseException(pos, "Expected end of type argument");
							
							while (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') {
								pos++;
								if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == '[')
									pos++;
								else
									throw new ReflectionNameParseException(pos, "Expected another type argument");
								
								typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos));
								
								if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']')
									pos++;
								else
									throw new ReflectionNameParseException(pos, "Expected end of type argument");
							}
							
							if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') {
								pos++;
								reference = new ParameterizedTypeReference(reference, typeArguments);
							} else {
								throw new ReflectionNameParseException(pos, "Expected end of generic type");
							}
						} else {
							// it's an array
							int dimensions = 1;
							while (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') {
								dimensions++;
								pos++;
							}
							if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') {
								pos++; // end of array
								reference = new ArrayTypeReference(reference, dimensions);
							} else {
								throw new ReflectionNameParseException(pos, "Invalid array modifier");
							}
						}
						break;
					case ',':
						// assembly qualified name, ignore everything up to the end/next ']'
						while (pos < reflectionTypeName.Length && reflectionTypeName[pos] != ']')
							pos++;
						break;
					default:
						pos--; // reset pos to the character we couldn't read
						if (reflectionTypeName[pos] == ']')
							return reference; // return from a nested generic
						else
							throw new ReflectionNameParseException(pos, "Unexpected character: '" + reflectionTypeName[pos] + "'");
				}
			}
			return reference;
		}