} // end _TryCrackTemplate() /// <summary> /// Converts a name into either a DbgTemplateLeaf or a DbgTemplate. /// </summary> public static DbgTemplateNode CrackTemplate(string name) { string problem; DbgTemplateNode templatePart; if (!_TryCrackTemplate(name, 0, out templatePart, out problem)) { // TODO: SQM? I think that this can only happen if there are unbalanced brackets. LogManager.Trace("Warning: weird type name: {0}", name); LogManager.Trace("Warning: Problem: {0}", problem); Util.Fail(Util.Sprintf("Weird type name ({0}): {1}", problem, name)); templatePart = new DbgTemplateLeaf(name, false); } return(templatePart); } // end CrackTemplate()
} // end _HasTwoColonsPreceding() private static bool _TryCrackTemplate(string name, int startIdx, out DbgTemplateNode templatePart, out string problem) { templatePart = null; problem = null; name = name.Trim(); bool hasConst = false; if (name.StartsWith("const ", StringComparison.OrdinalIgnoreCase)) { // I haven't actually observed any type names with "const" at the // beginning, but it seems like it could be possible. hasConst = true; name = name.Substring(6).Trim(); } else if (name.EndsWith(" const", StringComparison.OrdinalIgnoreCase)) { hasConst = true; name = name.Substring(0, name.Length - 6).Trim(); } int idx; if (!_LooksLikeATemplateName(name, startIdx, /* angleBracketIdx */ out idx)) { templatePart = new DbgTemplateLeaf(name.Substring(startIdx), hasConst); return(true); } var templateName = name.Substring(startIdx, idx - startIdx); StringBuilder sb = new StringBuilder(); DbgTemplateNode nestedType = null; int depth = 1; var templateParams = new List <DbgTemplateNode>(); for (idx = idx + 1; idx < name.Length; idx++) // start after the first '<' { char c = name[idx]; if ('<' == c) { depth++; } else if ('>' == c) { depth--; if (depth < 0) { problem = Util.Sprintf("Unbalanced closing angle bracket at position {0}.", idx); return(false); } if (0 == depth) { if (sb.Length > 0) { templateParams.Add(CrackTemplate(sb.ToString().Trim())); } if (idx != (name.Length - 1)) { // TODO: '+' for nested types in managed generic types? if ((name.Length < (idx + 4)) || // there has to be at least "::X" (name[idx + 1] != ':') || (name[idx + 2] != ':')) { problem = Util.Sprintf("Unexpected characters at position {0}.", idx); return(false); } idx += 3; // skip the "::" if (!_TryCrackTemplate(name, idx, out nestedType, out problem)) { Util.Assert(!String.IsNullOrEmpty(problem)); return(false); } } break; } } if (depth > 1) { sb.Append(c); } else { Util.Assert(1 == depth); if (',' == c) { // TODO: Hmm... I wonder if it's possible to get a symbol with ",," (which // would lead to an empty part name, which will throw). templateParams.Add(CrackTemplate(sb.ToString().Trim())); sb.Clear(); } else { sb.Append(c); } } } // end for( each character ) templatePart = new DbgTemplate(templateName, templateParams.AsReadOnly(), nestedType, hasConst); return(true); } // end _TryCrackTemplate()