Browse Source

More string-based approach. Many things working, but not yet pointers.

pull/697/head
yggy 9 years ago
parent
commit
eee3467492
  1. 225
      ILSpy.AddIn/CodeElementXmlDocKeyProvider.cs

225
ILSpy.AddIn/CodeElementXmlDocKeyProvider.cs

@ -25,7 +25,7 @@ namespace ICSharpCode.ILSpy.AddIn
(member.Kind == EnvDTE.vsCMElement.vsCMElementStruct) || (member.Kind == EnvDTE.vsCMElement.vsCMElementStruct) ||
(member.Kind == EnvDTE.vsCMElement.vsCMElementClass)) { (member.Kind == EnvDTE.vsCMElement.vsCMElementClass)) {
b.Append("T:"); b.Append("T:");
AppendTypeName(b, member); AppendTypeName(b, member.FullName, true, false);
} }
else if (member.Kind == EnvDTE.vsCMElement.vsCMElementNamespace){ else if (member.Kind == EnvDTE.vsCMElement.vsCMElementNamespace){
b.Append("N:"); b.Append("N:");
@ -40,22 +40,28 @@ namespace ICSharpCode.ILSpy.AddIn
b.Append("E:"); b.Append("E:");
else if (member.Kind == EnvDTE.vsCMElement.vsCMElementFunction) else if (member.Kind == EnvDTE.vsCMElement.vsCMElementFunction)
b.Append("M:"); b.Append("M:");
AppendTypeName(b, (EnvDTE.CodeElement)member.Collection.Parent);
int nameIndex = member.FullName.LastIndexOf(member.Name);
string typeName = member.FullName.Substring(0, nameIndex - 1);
string memberName = member.FullName.Substring(nameIndex);
if (member.Kind == EnvDTE.vsCMElement.vsCMElementFunction) {
EnvDTE80.CodeFunction2 mr = (EnvDTE80.CodeFunction2)member;
if (mr.FunctionKind == EnvDTE.vsCMFunction.vsCMFunctionConstructor) {
memberName = memberName.Replace(member.Name, "#ctor");
}
}
string[] genericTypeParameters = AppendTypeName(b, typeName, true, false);
b.Append('.'); b.Append('.');
b.Append(member.Name.Replace('.', '#')); string[] genericMethodParameters = AppendTypeName(b, memberName.Replace('.', '#'), true, true);
EnvDTE.CodeElements parameters; EnvDTE.CodeElements parameters;
string[] genericMethodParameters = cEmptyStringArray;
EnvDTE.CodeTypeRef explicitReturnType = null; EnvDTE.CodeTypeRef explicitReturnType = null;
if (member.Kind == EnvDTE.vsCMElement.vsCMElementProperty) { if (member.Kind == EnvDTE.vsCMElement.vsCMElementProperty) {
parameters = ((EnvDTE.CodeProperty)member).Getter.Parameters; parameters = ((EnvDTE.CodeProperty)member).Getter.Parameters;
} }
else if (member.Kind == EnvDTE.vsCMElement.vsCMElementFunction) { else if (member.Kind == EnvDTE.vsCMElement.vsCMElementFunction) {
EnvDTE80.CodeFunction2 mr = (EnvDTE80.CodeFunction2)member; EnvDTE80.CodeFunction2 mr = (EnvDTE80.CodeFunction2)member;
if (mr.IsGeneric) {
genericMethodParameters = GetGenericParameters(member);
b.Append("``");
b.Append(genericMethodParameters.Length);
}
parameters = mr.Parameters; parameters = mr.Parameters;
if (mr.Name == "op_Implicit" || mr.Name == "op_Explicit") { if (mr.Name == "op_Implicit" || mr.Name == "op_Explicit") {
// TODO: check operator overloads to see if these work // TODO: check operator overloads to see if these work
@ -70,75 +76,97 @@ namespace ICSharpCode.ILSpy.AddIn
int i = 0; int i = 0;
foreach (EnvDTE80.CodeParameter2 parameter in parameters) { foreach (EnvDTE80.CodeParameter2 parameter in parameters) {
if (i > 0) b.Append(','); if (i > 0) b.Append(',');
AppendTypeName(b, parameter, genericMethodParameters); AppendParameterTypeName(b, parameter, genericTypeParameters, genericMethodParameters);
++i; ++i;
} }
b.Append(')'); b.Append(')');
} }
if (explicitReturnType != null) { if (explicitReturnType != null) {
// TODO: test explicit return types
b.Append('~'); b.Append('~');
AppendTypeName(b, (EnvDTE.CodeElement)explicitReturnType); AppendTypeName(b, explicitReturnType.AsFullName, true, false);
} }
} }
return b.ToString(); return b.ToString();
} }
static void AppendTypeName(StringBuilder b, EnvDTE.CodeElement type) static string[] AppendTypeName(StringBuilder b, string typeName, bool appendGenericParameterCount, bool isMethod)
{ {
if (type == null) { List<string> allGenericParameters = new List<string>();
// could happen when a TypeSpecification has no ElementType; e.g. function pointers in C++/CLI assemblies StringBuilder genericParameterName = new StringBuilder();
return;
} bool inGenericParameters = false;
int genericParameterCount = 0;
bool isGeneric = foreach (char ch in typeName) {
((type.Kind == EnvDTE.vsCMElement.vsCMElementClass) && ((EnvDTE80.CodeClass2)type).IsGeneric) || if (inGenericParameters) {
((type.Kind == EnvDTE.vsCMElement.vsCMElementStruct) && ((EnvDTE80.CodeStruct2)type).IsGeneric) || switch (ch) {
((type.Kind == EnvDTE.vsCMElement.vsCMElementInterface) && ((EnvDTE80.CodeInterface2)type).IsGeneric); case ',':
++genericParameterCount;
if (isGeneric) { allGenericParameters.Add(genericParameterName.ToString());
AppendTypeNameWithArguments(b, type, GetGenericParameters(type)); genericParameterName.Clear();
} break;
else { case '>':
// TODO: handle generic parameters, but above? ++genericParameterCount;
//GenericParameter gp = type as GenericParameter; allGenericParameters.Add(genericParameterName.ToString());
//if (gp != null) { genericParameterName.Clear();
// b.Append('`'); if (appendGenericParameterCount) {
// if (gp.Owner.GenericParameterType == GenericParameterType.Method) { b.Append(genericParameterCount);
// b.Append('`'); }
// } inGenericParameters = false;
// b.Append(gp.Position); break;
//} case ' ':
EnvDTE.CodeElement declaringType = GetDeclaringType(type); break;
if (declaringType != null) { default:
AppendTypeName(b, declaringType); genericParameterName.Append(ch);
b.Append('.'); break;
b.Append(type.Name); }
} }
else { else {
b.Append(type.FullName); switch (ch) {
case '<':
if (appendGenericParameterCount) {
b.Append('`');
if (isMethod) {
b.Append('`');
}
}
inGenericParameters = true;
genericParameterCount = 0;
break;
case '[':
case ']':
break;
default:
b.Append(ch);
break;
}
} }
} }
return allGenericParameters.ToArray();
} }
static void AppendTypeName(StringBuilder b, EnvDTE80.CodeParameter2 parameter, string[] genericMethodParameters) static void AppendParameterTypeName(StringBuilder b, EnvDTE80.CodeParameter2 parameter, string[] genericTypeParameters, string[] genericMethodParameters)
{ {
EnvDTE80.CodeTypeRef2 typeRef = (EnvDTE80.CodeTypeRef2)parameter.Type; EnvDTE80.CodeTypeRef2 typeRef = (EnvDTE80.CodeTypeRef2)parameter.Type;
// Parameters of generic types from generic method are indicated as ``1, ``2, etc. int indexOfGenericTypeParameter = Array.IndexOf(genericTypeParameters, typeRef.AsFullName);
// TODO: parameters of generic types from enclosing class (and nested classes??) int indexOfGenericMethodParameter = Array.IndexOf(genericMethodParameters, typeRef.AsFullName);
int indexOfGenericParameter = Array.IndexOf(genericMethodParameters, typeRef.AsFullName); if (indexOfGenericTypeParameter >= 0) {
if (indexOfGenericParameter >= 0) { b.Append("`");
b.Append(indexOfGenericTypeParameter);
}
else if (indexOfGenericMethodParameter >= 0) {
b.Append("``"); b.Append("``");
b.Append(indexOfGenericParameter); b.Append(indexOfGenericMethodParameter);
} }
else if (typeRef.TypeKind == EnvDTE.vsCMTypeRef.vsCMTypeRefArray) { else if (typeRef.TypeKind == EnvDTE.vsCMTypeRef.vsCMTypeRefPointer) {
AppendTypeNameWithArguments(b, (EnvDTE.CodeElement)typeRef.ElementType, genericMethodParameters); AppendTypeNameWithArguments(b, (EnvDTE.CodeElement)typeRef.ElementType, genericTypeParameters, genericMethodParameters);
} }
else { else {
AppendTypeNameWithArguments(b, (EnvDTE.CodeElement)typeRef.CodeType, genericMethodParameters); AppendTypeNameWithArguments(b, (EnvDTE.CodeElement)typeRef.CodeType, genericTypeParameters, genericMethodParameters);
} }
// TODO: think we need to handle generic arguments here (from enclosing type or method, but how?)
if (typeRef.TypeKind == EnvDTE.vsCMTypeRef.vsCMTypeRefArray) { if (typeRef.TypeKind == EnvDTE.vsCMTypeRef.vsCMTypeRefArray) {
b.Append('['); b.Append('[');
for (int i = 0; i < typeRef.Rank; i++) { for (int i = 0; i < typeRef.Rank; i++) {
@ -155,46 +183,62 @@ namespace ICSharpCode.ILSpy.AddIn
b.Append(']'); b.Append(']');
} }
// TODO: test out and ref parameters
if ((parameter.ParameterKind == EnvDTE80.vsCMParameterKind.vsCMParameterKindRef) || if ((parameter.ParameterKind == EnvDTE80.vsCMParameterKind.vsCMParameterKindRef) ||
(parameter.ParameterKind == EnvDTE80.vsCMParameterKind.vsCMParameterKindOut)) { (parameter.ParameterKind == EnvDTE80.vsCMParameterKind.vsCMParameterKindOut)) {
b.Append('@'); b.Append('@');
} }
// TODO: test pointer parameters
if (typeRef.TypeKind == EnvDTE.vsCMTypeRef.vsCMTypeRefPointer) { if (typeRef.TypeKind == EnvDTE.vsCMTypeRef.vsCMTypeRefPointer) {
b.Append('*'); b.Append('*');
} }
} }
static int AppendTypeNameWithArguments(StringBuilder b, EnvDTE.CodeElement type, string[] genericArguments) private static void AppendTypeNameWithArguments(StringBuilder b, EnvDTE.CodeElement type, string[] genericTypeParameters, string[] genericMethodParameters)
{ {
int outerTypeParameterCount = 0; int nameIndex = type.FullName.LastIndexOf(type.Name);
EnvDTE.CodeElement declaringType = GetDeclaringType(type); string containerName = type.FullName.Substring(0, nameIndex - 1);
if (declaringType != null) { string typeName = type.FullName.Substring(nameIndex);
outerTypeParameterCount = AppendTypeNameWithArguments(b, declaringType, genericArguments);
b.Append('.'); EnvDTE.CodeElement declaringElement = null;
try {
declaringElement = (EnvDTE.CodeElement)type.Collection.Parent;
} }
else { catch (Exception) {
string typeNamespace = GetNamespace(type); }
if (!string.IsNullOrEmpty(typeNamespace)) {
b.Append(typeNamespace); if (declaringElement == null) {
if (!string.IsNullOrEmpty(containerName)) {
b.Append(containerName);
b.Append('.'); b.Append('.');
} }
} }
else if (declaringElement.Kind == EnvDTE.vsCMElement.vsCMElementNamespace) {
b.Append(declaringElement.FullName);
b.Append('.');
}
else {
AppendTypeNameWithArguments(b, declaringElement, genericTypeParameters, genericMethodParameters);
b.Append('.');
}
string[] localTypeParameters = GetGenericParameters(type); string[] localTypeParameters = AppendTypeName(b, typeName, false, false);
int localTypeParameterCount = localTypeParameters.Length;
b.Append(type.Name);
if (localTypeParameterCount > 0) { if (localTypeParameters.Length > 0) {
int totalTypeParameterCount = outerTypeParameterCount + localTypeParameterCount;
b.Append('{'); b.Append('{');
for (int i = 0; i < localTypeParameterCount; i++) { for (int i = 0; i < localTypeParameters.Length; i++) {
if (i > 0) b.Append(','); if (i > 0) b.Append(',');
string localTypeParameter = localTypeParameters[i]; string localTypeParameter = localTypeParameters[i];
int genericIndex = Array.IndexOf(genericArguments, localTypeParameter); int indexOfGenericTypeParameter = Array.IndexOf(genericTypeParameters, localTypeParameter);
if (genericIndex >= 0) { int indexOfGenericMethodParameter = Array.IndexOf(genericMethodParameters, localTypeParameter);
if (indexOfGenericTypeParameter >= 0) {
b.Append("`");
b.Append(indexOfGenericTypeParameter);
}
else if (indexOfGenericMethodParameter >= 0) {
b.Append("``"); b.Append("``");
b.Append(genericIndex); b.Append(indexOfGenericMethodParameter);
} }
else { else {
b.Append(localTypeParameter); b.Append(localTypeParameter);
@ -202,47 +246,6 @@ namespace ICSharpCode.ILSpy.AddIn
} }
b.Append('}'); b.Append('}');
} }
return outerTypeParameterCount + localTypeParameterCount;
}
private static string[] GetGenericParameters(EnvDTE.CodeElement codeElement)
{
int iGenericParameters = codeElement.FullName.LastIndexOf('<');
if (iGenericParameters >= 0) {
return codeElement.FullName.Substring(iGenericParameters).Split(cGenericParameterSeparators, StringSplitOptions.RemoveEmptyEntries);
}
else {
return cEmptyStringArray;
}
}
private static readonly char[] cGenericParameterSeparators = new char[] { '<', ',', ' ', '>' };
private static readonly string[] cEmptyStringArray = new string[0];
private static EnvDTE.CodeElement GetDeclaringType(EnvDTE.CodeElement codeElement)
{
EnvDTE.CodeElement declaringElement = null;
if (codeElement != null) {
declaringElement = (EnvDTE.CodeElement)codeElement.Collection.Parent;
bool hasDeclaringType =
(declaringElement.Kind == EnvDTE.vsCMElement.vsCMElementClass) ||
(declaringElement.Kind == EnvDTE.vsCMElement.vsCMElementStruct) ||
(declaringElement.Kind == EnvDTE.vsCMElement.vsCMElementInterface);
if (!hasDeclaringType) {
declaringElement = null;
}
}
return declaringElement;
}
private static string GetNamespace(EnvDTE.CodeElement codeElement)
{
if (codeElement != null) {
EnvDTE.CodeElement parent = (EnvDTE.CodeElement)codeElement.Collection.Parent;
if (parent.Kind == EnvDTE.vsCMElement.vsCMElementNamespace) {
return parent.FullName;
}
}
return null;
} }
#endregion #endregion

Loading…
Cancel
Save