private void Initialize(string typeName) {
if (typeName == null || typeName.Length == 0) {
typeName = typeof(void).FullName;
this.baseType = typeName;
this.arrayRank = 0;
this.arrayElementType = null;
return;
}
typeName = RipOffAssemblyInformationFromTypeName(typeName);
int end = typeName.Length -1;
int current = end;
needsFixup = true; // default to true, and if we find arity or generic type args, we'll clear the flag.
// Scan the entire string for valid array tails and store ranks for array tails
// we found in a queue.
Queue q = new Queue();
while(current >= 0) {
int rank = 1;
if( typeName[current--] == ']') {
while(current >=0 && typeName[current] == ',') {
rank++;
current--;
}
if( current>=0 && typeName[current] == '[') { // found a valid array tail
q.Enqueue(rank);
current--;
end = current;
continue;
}
}
break;
}
// Try find generic type arguments
current = end;
ArrayList typeArgumentList = new ArrayList();
Stack subTypeNames = new Stack();
if( current > 0 && typeName[current--] == ']') {
needsFixup = false;
int unmatchedRightBrackets = 1;
int subTypeNameEndIndex = end;
// Try find the matching '[', if we can't find it, we will not try to parse the string
while(current >= 0) {
if( typeName[current] == '[' ) {
// break if we found matched brackets
if( --unmatchedRightBrackets == 0) break;
}
else if( typeName[current] == ']' ) {
++unmatchedRightBrackets;
}
else if( typeName[current] == ',' && unmatchedRightBrackets == 1) {
//
if( current + 1 < subTypeNameEndIndex) {
subTypeNames.Push(typeName.Substring(current+1 , subTypeNameEndIndex - current - 1));
}
subTypeNameEndIndex = current;
}
--current;
}
if( current > 0 && (end - current - 1) > 0) {
// push the last generic type argument name if there is any
if( current + 1 < subTypeNameEndIndex) {
subTypeNames.Push(typeName.Substring(current+1 , subTypeNameEndIndex - current - 1));
}
// we found matched brackets and the brackets contains some characters.
while( subTypeNames.Count > 0) {
String name = RipOffAssemblyInformationFromTypeName((string)subTypeNames.Pop());
typeArgumentList.Add(new CodeTypeReference(name));
}
end = current - 1;
}
}
if( end < 0) { // this can happen if we have some string like "[...]"
this.baseType = typeName;
return;
}
if (q.Count > 0 ) {
CodeTypeReference type = new CodeTypeReference(typeName.Substring(0, end + 1));
for(int i = 0; i < typeArgumentList.Count; i++) {
type.TypeArguments.Add((CodeTypeReference)typeArgumentList[i]);
}
while( q.Count > 1) {
type = new CodeTypeReference( type, (int)q.Dequeue());
}
// we don't need to create a new CodeTypeReference for the last one.
Debug.Assert(q.Count == 1 , "We should have one and only one in the rank queue.");
this.baseType = null;
this.arrayRank = (int)q.Dequeue();
this.arrayElementType = type;
}
else if( typeArgumentList.Count > 0 ) {
for( int i = 0; i < typeArgumentList.Count; i++) {
TypeArguments.Add((CodeTypeReference)typeArgumentList[i]);
}
this.baseType = typeName.Substring(0, end + 1);
}
else{
this.baseType = typeName;
}
// Now see if we have some arity. baseType could be null if this is an array type.
if (baseType != null && baseType.IndexOf('`') != -1)
needsFixup = false;
}