Browse Source

change: move "navigateto" key generation to separate CodeElementXmlDocKeyProvider class, in preparation for porting the logic of the existing XmlDocKeyProvider

pull/697/head
yggy 9 years ago
parent
commit
3a75f60915
  1. 147
      ILSpy.AddIn/CodeElementXmlDocKeyProvider.cs
  2. 1
      ILSpy.AddIn/ILSpy.AddIn.csproj
  3. 142
      ILSpy.AddIn/ILSpyAddInPackage.cs

147
ILSpy.AddIn/CodeElementXmlDocKeyProvider.cs

@ -0,0 +1,147 @@ @@ -0,0 +1,147 @@
using System;
namespace ICSharpCode.ILSpy.AddIn
{
public static class CodeElementXmlDocKeyProvider
{
// Get ID string for code element, for /navigateTo command line option.
// See "ID string format" in Appendix A of the C# language specification for details.
// See ICSharpCode.ILSpy.XmlDoc.XmlDocKeyProvider.GetKey for a similar implementation, based on Mono.Cecil.MemberReference.
public static string GetCodeElementIDString(EnvDTE.CodeElement codeElement)
{
switch (codeElement.Kind) {
case EnvDTE.vsCMElement.vsCMElementEvent:
return string.Concat("E:",
GetCodeElementContainerString((EnvDTE.CodeElement)codeElement.Collection.Parent),
".", codeElement.Name);
case EnvDTE.vsCMElement.vsCMElementVariable:
return string.Concat("F:",
GetCodeElementContainerString((EnvDTE.CodeElement)codeElement.Collection.Parent),
".", codeElement.Name);
case EnvDTE.vsCMElement.vsCMElementFunction: {
var codeFunction = (EnvDTE80.CodeFunction2)codeElement;
var idBuilder = new System.Text.StringBuilder();
idBuilder.Append("M:");
// Constructors need to be called "#ctor" for navigation purposes.
string[] genericClassTypeParameters;
string classFullName = GetCodeElementContainerString((EnvDTE.CodeElement)codeFunction.Parent, out genericClassTypeParameters);
string functionName = (codeFunction.FunctionKind == EnvDTE.vsCMFunction.vsCMFunctionConstructor ? "#ctor" : codeFunction.Name);
idBuilder.Append(classFullName);
idBuilder.Append('.');
idBuilder.Append(functionName);
// Get type parameters to generic method, if present.
string[] genericMethodTypeParameters = new string[0];
int iGenericParams = codeFunction.FullName.LastIndexOf('<');
if ((codeFunction.IsGeneric) && (iGenericParams >= 0)) {
genericMethodTypeParameters = codeFunction.FullName.Substring(iGenericParams).Split(new char[] {'<', ',', ' ', '>'}, StringSplitOptions.RemoveEmptyEntries);
idBuilder.Append("``");
idBuilder.Append(genericMethodTypeParameters.Length);
}
// Append parameter types, to disambiguate overloaded methods.
if (codeFunction.Parameters.Count > 0) {
idBuilder.Append("(");
bool first = true;
foreach (EnvDTE.CodeParameter parameter in codeFunction.Parameters) {
if (!first) {
idBuilder.Append(",");
}
first = false;
int genericClassTypeParameterIndex = Array.IndexOf(genericClassTypeParameters, parameter.Type.AsFullName);
if (genericClassTypeParameterIndex >= 0) {
idBuilder.Append('`');
idBuilder.Append(genericClassTypeParameterIndex);
}
else {
int genericMethodTypeParameterIndex = Array.IndexOf(genericMethodTypeParameters, parameter.Type.AsFullName);
if (genericMethodTypeParameterIndex >= 0) {
idBuilder.Append("``");
idBuilder.Append(genericMethodTypeParameterIndex);
}
else {
// Special handling for arrays, because AsFullName for an array is empty.
if (parameter.Type.TypeKind == EnvDTE.vsCMTypeRef.vsCMTypeRefArray) {
idBuilder.Append(parameter.Type.ElementType.AsFullName);
idBuilder.Append("[]");
}
else {
idBuilder.Append(parameter.Type.AsFullName);
}
}
}
}
idBuilder.Append(")");
}
return idBuilder.ToString();
}
case EnvDTE.vsCMElement.vsCMElementNamespace:
return string.Concat("N:",
codeElement.FullName);
case EnvDTE.vsCMElement.vsCMElementProperty:
return string.Concat("P:",
GetCodeElementContainerString((EnvDTE.CodeElement)codeElement.Collection.Parent),
".", codeElement.Name);
case EnvDTE.vsCMElement.vsCMElementDelegate:
case EnvDTE.vsCMElement.vsCMElementEnum:
case EnvDTE.vsCMElement.vsCMElementInterface:
case EnvDTE.vsCMElement.vsCMElementStruct:
case EnvDTE.vsCMElement.vsCMElementClass:
return string.Concat("T:",
GetCodeElementContainerString(codeElement));
default:
return string.Format("!:Code element {0} is of unsupported type {1}", codeElement.FullName, codeElement.Kind.ToString());
}
}
private static string GetCodeElementContainerString(EnvDTE.CodeElement containerElement)
{
string[] genericTypeParametersIgnored;
return GetCodeElementContainerString(containerElement, out genericTypeParametersIgnored);
}
private static string GetCodeElementContainerString(EnvDTE.CodeElement containerElement, out string[] genericTypeParameters)
{
genericTypeParameters = new string[0];
switch (containerElement.Kind) {
case EnvDTE.vsCMElement.vsCMElementNamespace:
return containerElement.FullName;
case EnvDTE.vsCMElement.vsCMElementInterface:
case EnvDTE.vsCMElement.vsCMElementStruct:
case EnvDTE.vsCMElement.vsCMElementClass: {
var idBuilder = new System.Text.StringBuilder();
idBuilder.Append(GetCodeElementContainerString((EnvDTE.CodeElement)containerElement.Collection.Parent));
idBuilder.Append('.');
idBuilder.Append(containerElement.Name);
// For "Generic<T1,T2>" we need "Generic`2".
bool isGeneric =
((containerElement.Kind == EnvDTE.vsCMElement.vsCMElementClass) && ((EnvDTE80.CodeClass2)containerElement).IsGeneric) ||
((containerElement.Kind == EnvDTE.vsCMElement.vsCMElementStruct) && ((EnvDTE80.CodeStruct2)containerElement).IsGeneric) ||
((containerElement.Kind == EnvDTE.vsCMElement.vsCMElementInterface) && ((EnvDTE80.CodeInterface2)containerElement).IsGeneric);
int iGenericParams = containerElement.FullName.LastIndexOf('<');
if (isGeneric && (iGenericParams >= 0)) {
genericTypeParameters = containerElement.FullName.Substring(iGenericParams).Split(new char[] {'<', ',', ' ', '>'}, StringSplitOptions.RemoveEmptyEntries);
idBuilder.Append('`');
idBuilder.Append(genericTypeParameters.Length);
}
return idBuilder.ToString();
}
default:
return string.Format("!:Code element {0} is of unsupported container type {1}", containerElement.FullName, containerElement.Kind.ToString());
}
}
}
}

1
ILSpy.AddIn/ILSpy.AddIn.csproj

@ -138,6 +138,7 @@ @@ -138,6 +138,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Guids.cs" />
<Compile Include="CodeElementXmlDocKeyProvider.cs" />
<Compile Include="Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>

142
ILSpy.AddIn/ILSpyAddInPackage.cs

@ -180,150 +180,10 @@ namespace ICSharpCode.ILSpy.AddIn @@ -180,150 +180,10 @@ namespace ICSharpCode.ILSpy.AddIn
private void OpenCodeItemInILSpy(EnvDTE.CodeElement codeElement)
{
string navigateTo = "/navigateTo:" + GetCodeElementIDString(codeElement);
string navigateTo = "/navigateTo:" + CodeElementXmlDocKeyProvider.GetCodeElementIDString(codeElement);
OpenProjectInILSpy(codeElement.ProjectItem.ContainingProject, navigateTo);
}
// Get ID string for code element, for /navigateTo command line option.
// See "ID string format" in Appendix A of the C# language specification for details.
// See ICSharpCode.ILSpy.XmlDoc.XmlDocKeyProvider.GetKey for a similar implementation, based on Mono.Cecil.MemberReference.
private string GetCodeElementIDString(EnvDTE.CodeElement codeElement)
{
switch (codeElement.Kind) {
case EnvDTE.vsCMElement.vsCMElementEvent:
return string.Concat("E:",
GetCodeElementContainerString((EnvDTE.CodeElement)codeElement.Collection.Parent),
".", codeElement.Name);
case EnvDTE.vsCMElement.vsCMElementVariable:
return string.Concat("F:",
GetCodeElementContainerString((EnvDTE.CodeElement)codeElement.Collection.Parent),
".", codeElement.Name);
case EnvDTE.vsCMElement.vsCMElementFunction: {
var codeFunction = (EnvDTE80.CodeFunction2)codeElement;
var idBuilder = new System.Text.StringBuilder();
idBuilder.Append("M:");
// Constructors need to be called "#ctor" for navigation purposes.
string[] genericClassTypeParameters;
string classFullName = GetCodeElementContainerString((EnvDTE.CodeElement)codeFunction.Parent, out genericClassTypeParameters);
string functionName = (codeFunction.FunctionKind == EnvDTE.vsCMFunction.vsCMFunctionConstructor ? "#ctor" : codeFunction.Name);
idBuilder.Append(classFullName);
idBuilder.Append('.');
idBuilder.Append(functionName);
// Get type parameters to generic method, if present.
string[] genericMethodTypeParameters = new string[0];
int iGenericParams = codeFunction.FullName.LastIndexOf('<');
if ((codeFunction.IsGeneric) && (iGenericParams >= 0)) {
genericMethodTypeParameters = codeFunction.FullName.Substring(iGenericParams).Split(new char[] {'<', ',', ' ', '>'}, StringSplitOptions.RemoveEmptyEntries);
idBuilder.Append("``");
idBuilder.Append(genericMethodTypeParameters.Length);
}
// Append parameter types, to disambiguate overloaded methods.
if (codeFunction.Parameters.Count > 0) {
idBuilder.Append("(");
bool first = true;
foreach (EnvDTE.CodeParameter parameter in codeFunction.Parameters) {
if (!first) {
idBuilder.Append(",");
}
first = false;
int genericClassTypeParameterIndex = Array.IndexOf(genericClassTypeParameters, parameter.Type.AsFullName);
if (genericClassTypeParameterIndex >= 0) {
idBuilder.Append('`');
idBuilder.Append(genericClassTypeParameterIndex);
}
else {
int genericMethodTypeParameterIndex = Array.IndexOf(genericMethodTypeParameters, parameter.Type.AsFullName);
if (genericMethodTypeParameterIndex >= 0) {
idBuilder.Append("``");
idBuilder.Append(genericMethodTypeParameterIndex);
}
else {
// Special handling for arrays, because AsFullName for an array is empty.
if (parameter.Type.TypeKind == EnvDTE.vsCMTypeRef.vsCMTypeRefArray) {
idBuilder.Append(parameter.Type.ElementType.AsFullName);
idBuilder.Append("[]");
}
else {
idBuilder.Append(parameter.Type.AsFullName);
}
}
}
}
idBuilder.Append(")");
}
return idBuilder.ToString();
}
case EnvDTE.vsCMElement.vsCMElementNamespace:
return string.Concat("N:",
codeElement.FullName);
case EnvDTE.vsCMElement.vsCMElementProperty:
return string.Concat("P:",
GetCodeElementContainerString((EnvDTE.CodeElement)codeElement.Collection.Parent),
".", codeElement.Name);
case EnvDTE.vsCMElement.vsCMElementDelegate:
case EnvDTE.vsCMElement.vsCMElementEnum:
case EnvDTE.vsCMElement.vsCMElementInterface:
case EnvDTE.vsCMElement.vsCMElementStruct:
case EnvDTE.vsCMElement.vsCMElementClass:
return string.Concat("T:",
GetCodeElementContainerString(codeElement));
default:
return string.Format("!:Code element {0} is of unsupported type {1}", codeElement.FullName, codeElement.Kind.ToString());
}
}
private string GetCodeElementContainerString(EnvDTE.CodeElement containerElement)
{
string[] genericTypeParametersIgnored;
return GetCodeElementContainerString(containerElement, out genericTypeParametersIgnored);
}
private string GetCodeElementContainerString(EnvDTE.CodeElement containerElement, out string[] genericTypeParameters)
{
genericTypeParameters = new string[0];
switch (containerElement.Kind) {
case EnvDTE.vsCMElement.vsCMElementNamespace:
return containerElement.FullName;
case EnvDTE.vsCMElement.vsCMElementInterface:
case EnvDTE.vsCMElement.vsCMElementStruct:
case EnvDTE.vsCMElement.vsCMElementClass: {
var idBuilder = new System.Text.StringBuilder();
idBuilder.Append(GetCodeElementContainerString((EnvDTE.CodeElement)containerElement.Collection.Parent));
idBuilder.Append('.');
idBuilder.Append(containerElement.Name);
// For "Generic<T1,T2>" we need "Generic`2".
bool isGeneric =
((containerElement.Kind == EnvDTE.vsCMElement.vsCMElementClass) && ((EnvDTE80.CodeClass2)containerElement).IsGeneric) ||
((containerElement.Kind == EnvDTE.vsCMElement.vsCMElementStruct) && ((EnvDTE80.CodeStruct2)containerElement).IsGeneric) ||
((containerElement.Kind == EnvDTE.vsCMElement.vsCMElementInterface) && ((EnvDTE80.CodeInterface2)containerElement).IsGeneric);
int iGenericParams = containerElement.FullName.LastIndexOf('<');
if (isGeneric && (iGenericParams >= 0)) {
genericTypeParameters = containerElement.FullName.Substring(iGenericParams).Split(new char[] {'<', ',', ' ', '>'}, StringSplitOptions.RemoveEmptyEntries);
idBuilder.Append('`');
idBuilder.Append(genericTypeParameters.Length);
}
return idBuilder.ToString();
}
default:
return string.Format("!:Code element {0} is of unsupported container type {1}", containerElement.FullName, containerElement.Kind.ToString());
}
}
private void OpenILSpyCallback(object sender, EventArgs e)
{
Process.Start(GetILSpyPath());

Loading…
Cancel
Save