mirror of https://github.com/icsharpcode/ILSpy.git
9 changed files with 344 additions and 85 deletions
@ -0,0 +1,117 @@
@@ -0,0 +1,117 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Diagnostics; |
||||
using System.IO; |
||||
using System.Runtime.CompilerServices; |
||||
using ICSharpCode.NRefactory.Documentation; |
||||
using Mono.Cecil; |
||||
|
||||
namespace ICSharpCode.ILSpy.XmlDoc |
||||
{ |
||||
/// <summary>
|
||||
/// Helps finding and loading .xml documentation.
|
||||
/// </summary>
|
||||
public static class XmlDocLoader |
||||
{ |
||||
static readonly Lazy<XmlDocumentationProvider> mscorlibDocumentation = new Lazy<XmlDocumentationProvider>(LoadMscorlibDocumentation); |
||||
static readonly ConditionalWeakTable<ModuleDefinition, XmlDocumentationProvider> cache = new ConditionalWeakTable<ModuleDefinition, XmlDocumentationProvider>(); |
||||
|
||||
static XmlDocumentationProvider LoadMscorlibDocumentation() |
||||
{ |
||||
string xmlDocFile = FindXmlDocumentation("mscorlib.dll", TargetRuntime.Net_4_0) |
||||
?? FindXmlDocumentation("mscorlib.dll", TargetRuntime.Net_2_0); |
||||
if (xmlDocFile != null) |
||||
return new XmlDocumentationProvider(xmlDocFile); |
||||
else |
||||
return null; |
||||
} |
||||
|
||||
public static XmlDocumentationProvider MscorlibDocumentation { |
||||
get { return mscorlibDocumentation.Value; } |
||||
} |
||||
|
||||
public static XmlDocumentationProvider LoadDocumentation(ModuleDefinition module) |
||||
{ |
||||
if (module == null) |
||||
throw new ArgumentNullException("module"); |
||||
lock (cache) { |
||||
XmlDocumentationProvider xmlDoc; |
||||
if (!cache.TryGetValue(module, out xmlDoc)) { |
||||
string xmlDocFile = LookupLocalizedXmlDoc(module.FullyQualifiedName); |
||||
if (xmlDocFile == null) { |
||||
xmlDocFile = FindXmlDocumentation(Path.GetFileName(module.FullyQualifiedName), module.Runtime); |
||||
} |
||||
if (xmlDocFile != null) { |
||||
xmlDoc = new XmlDocumentationProvider(xmlDocFile); |
||||
cache.Add(module, xmlDoc); |
||||
} else { |
||||
xmlDoc = null; |
||||
} |
||||
} |
||||
return xmlDoc; |
||||
} |
||||
} |
||||
|
||||
static readonly string referenceAssembliesPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), @"Reference Assemblies\Microsoft\\Framework"); |
||||
static readonly string frameworkPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), @"Microsoft.NET\Framework"); |
||||
|
||||
static string FindXmlDocumentation(string assemblyFileName, TargetRuntime runtime) |
||||
{ |
||||
string fileName; |
||||
switch (runtime) { |
||||
case TargetRuntime.Net_1_0: |
||||
fileName = LookupLocalizedXmlDoc(Path.Combine(frameworkPath, "v1.0.3705", assemblyFileName)); |
||||
break; |
||||
case TargetRuntime.Net_1_1: |
||||
fileName = LookupLocalizedXmlDoc(Path.Combine(frameworkPath, "v1.1.4322", assemblyFileName)); |
||||
break; |
||||
case TargetRuntime.Net_2_0: |
||||
fileName = LookupLocalizedXmlDoc(Path.Combine(frameworkPath, "v2.0.50727", assemblyFileName)) |
||||
?? LookupLocalizedXmlDoc(Path.Combine(referenceAssembliesPath, "v3.5")) |
||||
?? LookupLocalizedXmlDoc(Path.Combine(referenceAssembliesPath, "v3.0")) |
||||
?? LookupLocalizedXmlDoc(Path.Combine(referenceAssembliesPath, @".NETFramework\v3.5\Profile\Client")); |
||||
break; |
||||
case TargetRuntime.Net_4_0: |
||||
default: |
||||
fileName = LookupLocalizedXmlDoc(Path.Combine(referenceAssembliesPath, @".NETFramework\v4.0", assemblyFileName)) |
||||
?? LookupLocalizedXmlDoc(Path.Combine(frameworkPath, "v4.0.30319", assemblyFileName)); |
||||
break; |
||||
} |
||||
return fileName; |
||||
} |
||||
|
||||
static string LookupLocalizedXmlDoc(string fileName) |
||||
{ |
||||
string xmlFileName = Path.ChangeExtension(fileName, ".xml"); |
||||
string currentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName; |
||||
string localizedXmlDocFile = GetLocalizedName(xmlFileName, currentCulture); |
||||
|
||||
Debug.WriteLine("Try find XMLDoc @" + localizedXmlDocFile); |
||||
if (File.Exists(localizedXmlDocFile)) { |
||||
return localizedXmlDocFile; |
||||
} |
||||
Debug.WriteLine("Try find XMLDoc @" + xmlFileName); |
||||
if (File.Exists(xmlFileName)) { |
||||
return xmlFileName; |
||||
} |
||||
if (currentCulture != "en") { |
||||
string englishXmlDocFile = GetLocalizedName(xmlFileName, "en"); |
||||
Debug.WriteLine("Try find XMLDoc @" + englishXmlDocFile); |
||||
if (File.Exists(englishXmlDocFile)) { |
||||
return englishXmlDocFile; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
static string GetLocalizedName(string fileName, string language) |
||||
{ |
||||
string localizedXmlDocFile = Path.GetDirectoryName(fileName); |
||||
localizedXmlDocFile = Path.Combine(localizedXmlDocFile, language); |
||||
localizedXmlDocFile = Path.Combine(localizedXmlDocFile, Path.GetFileName(fileName)); |
||||
return localizedXmlDocFile; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,122 @@
@@ -0,0 +1,122 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Diagnostics; |
||||
using System.IO; |
||||
using System.Text; |
||||
using System.Text.RegularExpressions; |
||||
using System.Windows.Controls; |
||||
using System.Xml; |
||||
|
||||
namespace ICSharpCode.ILSpy.XmlDoc |
||||
{ |
||||
/// <summary>
|
||||
/// Renders XML documentation into a WPF <see cref="TextBlock"/>.
|
||||
/// </summary>
|
||||
public class XmlDocRenderer |
||||
{ |
||||
StringBuilder ret = new StringBuilder(); |
||||
|
||||
public void AppendText(string text) |
||||
{ |
||||
ret.Append(text); |
||||
} |
||||
|
||||
public void AddXmlDocumentation(string xmlDocumentation) |
||||
{ |
||||
if (xmlDocumentation == null) |
||||
return; |
||||
Debug.WriteLine(xmlDocumentation); |
||||
try { |
||||
XmlTextReader r = new XmlTextReader(new StringReader("<docroot>" + xmlDocumentation + "</docroot>")); |
||||
r.XmlResolver = null; |
||||
AddXmlDocumentation(r); |
||||
} catch (XmlException) { |
||||
} |
||||
} |
||||
|
||||
static readonly Regex whitespace = new Regex(@"\s+"); |
||||
|
||||
public void AddXmlDocumentation(XmlReader xml) |
||||
{ |
||||
while (xml.Read()) { |
||||
if (xml.NodeType == XmlNodeType.Element) { |
||||
string elname = xml.Name.ToLowerInvariant(); |
||||
switch (elname) { |
||||
case "filterpriority": |
||||
case "remarks": |
||||
xml.Skip(); |
||||
break; |
||||
case "example": |
||||
ret.Append(Environment.NewLine); |
||||
ret.Append("Example:"); |
||||
ret.Append(Environment.NewLine); |
||||
break; |
||||
case "exception": |
||||
ret.Append(Environment.NewLine); |
||||
ret.Append(GetCref(xml["cref"])); |
||||
ret.Append(": "); |
||||
break; |
||||
case "returns": |
||||
ret.Append(Environment.NewLine); |
||||
ret.Append("Returns: "); |
||||
break; |
||||
case "see": |
||||
ret.Append(GetCref(xml["cref"])); |
||||
ret.Append(xml["langword"]); |
||||
break; |
||||
case "seealso": |
||||
ret.Append(Environment.NewLine); |
||||
ret.Append("See also: "); |
||||
ret.Append(GetCref(xml["cref"])); |
||||
break; |
||||
case "paramref": |
||||
ret.Append(xml["name"]); |
||||
break; |
||||
case "param": |
||||
ret.Append(Environment.NewLine); |
||||
ret.Append(whitespace.Replace(xml["name"].Trim()," ")); |
||||
ret.Append(": "); |
||||
break; |
||||
case "typeparam": |
||||
ret.Append(Environment.NewLine); |
||||
ret.Append(whitespace.Replace(xml["name"].Trim()," ")); |
||||
ret.Append(": "); |
||||
break; |
||||
case "value": |
||||
ret.Append(Environment.NewLine); |
||||
ret.Append("Value: "); |
||||
ret.Append(Environment.NewLine); |
||||
break; |
||||
case "br": |
||||
case "para": |
||||
ret.Append(Environment.NewLine); |
||||
break; |
||||
} |
||||
} else if (xml.NodeType == XmlNodeType.Text) { |
||||
ret.Append(whitespace.Replace(xml.Value, " ")); |
||||
} |
||||
} |
||||
} |
||||
|
||||
static string GetCref(string cref) |
||||
{ |
||||
if (cref == null || cref.Trim().Length==0) { |
||||
return ""; |
||||
} |
||||
if (cref.Length < 2) { |
||||
return cref; |
||||
} |
||||
if (cref.Substring(1, 1) == ":") { |
||||
return cref.Substring(2, cref.Length - 2); |
||||
} |
||||
return cref; |
||||
} |
||||
|
||||
public TextBlock CreateTextBlock() |
||||
{ |
||||
return new TextBlock { Text = ret.ToString() }; |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue