if (typeName == null)
throw new ArgumentNullException ("typeName");
- TypeSpec res = Parse (typeName, ref pos, false, false);
+ TypeSpec res = Parse (typeName, ref pos, false, true);
if (pos < typeName.Length)
throw new ArgumentException ("Count not parse the whole type name", "typeName");
return res;
{
Assembly asm = null;
if (assemblyResolver == null && typeResolver == null)
- return Type.GetType (name.DisplayName, throwOnError, ignoreCase);
+ return Type.GetType (DisplayFullName, throwOnError, ignoreCase);
if (assembly_name != null) {
if (assemblyResolver != null)
pos = p;
}
+ static void BoundCheck (int idx, string s)
+ {
+ if (idx >= s.Length)
+ throw new ArgumentException ("Invalid generic arguments spec", "typeName");
+ }
+
static TypeIdentifier ParsedTypeIdentifier (string displayName)
{
return TypeIdentifiers.FromDisplay(displayName);
static TypeSpec Parse (string name, ref int p, bool is_recurse, bool allow_aqn)
{
+ // Invariants:
+ // - On exit p, is updated to pos the current unconsumed character.
+ //
+ // - The callee peeks at but does not consume delimiters following
+ // recurisve parse (so for a recursive call like the args of "Foo[P,Q]"
+ // we'll return with p either on ',' or on ']'. If the name was aqn'd
+ // "Foo[[P,assmblystuff],Q]" on return p with be on the ']' just
+ // after the "assmblystuff")
+ //
+ // - If allow_aqn is True, assembly qualification is optional.
+ // If allow_aqn is False, assembly qualification is prohibited.
int pos = p;
int name_start;
bool in_modifiers = false;
data.AddModifier (new PointerSpec(pointer_level));
break;
case ',':
- if (is_recurse) {
+ if (is_recurse && allow_aqn) {
int end = pos;
while (end < name.Length && name [end] != ']')
++end;
if (end >= name.Length)
throw new ArgumentException ("Unmatched ']' while parsing generic argument assembly name");
data.assembly_name = name.Substring (pos + 1, end - pos - 1).Trim ();
- p = end + 1;
+ p = end;
return data;
}
- data.assembly_name = name.Substring (pos + 1).Trim ();
- pos = name.Length;
+ if (is_recurse) {
+ p = pos;
+ return data;
+ }
+ if (allow_aqn) {
+ data.assembly_name = name.Substring (pos + 1).Trim ();
+ pos = name.Length;
+ }
break;
case '[':
if (data.is_byref)
if (aqn)
++pos; //skip '[' to the start of the type
args.Add (Parse (name, ref pos, true, aqn));
- if (pos >= name.Length)
- throw new ArgumentException ("Invalid generic arguments spec", "typeName");
+ BoundCheck (pos, name);
+ if (aqn) {
+ if (name [pos] == ']')
+ ++pos;
+ else
+ throw new ArgumentException ("Unclosed assembly-qualified type name at " + name[pos], "typeName");
+ BoundCheck (pos, name);
+}
if (name [pos] == ']')
- break;
+ break;
if (name [pos] == ',')
++pos; // skip ',' to the start of the next arg
else
break;
case ']':
if (is_recurse) {
- p = pos + 1;
+ p = pos;
return data;
}
throw new ArgumentException ("Unmatched ']'", "typeName");