mirror of https://github.com/icsharpcode/ILSpy.git
				
				
			
			You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							146 lines
						
					
					
						
							5.5 KiB
						
					
					
				
			
		
		
	
	
							146 lines
						
					
					
						
							5.5 KiB
						
					
					
				// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team | 
						|
//  | 
						|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this | 
						|
// software and associated documentation files (the "Software"), to deal in the Software | 
						|
// without restriction, including without limitation the rights to use, copy, modify, merge, | 
						|
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons | 
						|
// to whom the Software is furnished to do so, subject to the following conditions: | 
						|
//  | 
						|
// The above copyright notice and this permission notice shall be included in all copies or | 
						|
// substantial portions of the Software. | 
						|
//  | 
						|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, | 
						|
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | 
						|
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE | 
						|
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | 
						|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 
						|
// DEALINGS IN THE SOFTWARE. | 
						|
 | 
						|
using System; | 
						|
using System.Diagnostics; | 
						|
using System.IO; | 
						|
using System.Runtime.CompilerServices; | 
						|
 | 
						|
using ICSharpCode.Decompiler.Metadata; | 
						|
 | 
						|
namespace ICSharpCode.Decompiler.Documentation | 
						|
{ | 
						|
	/// <summary> | 
						|
	/// Helps finding and loading .xml documentation. | 
						|
	/// </summary> | 
						|
	public static class XmlDocLoader | 
						|
	{ | 
						|
		static readonly Lazy<XmlDocumentationProvider> mscorlibDocumentation = new Lazy<XmlDocumentationProvider>(LoadMscorlibDocumentation); | 
						|
		static readonly ConditionalWeakTable<PEFile, XmlDocumentationProvider> cache = new ConditionalWeakTable<PEFile, 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(PEFile module) | 
						|
		{ | 
						|
			if (module == null) | 
						|
				throw new ArgumentNullException(nameof(module)); | 
						|
			lock (cache) | 
						|
			{ | 
						|
				if (!cache.TryGetValue(module, out XmlDocumentationProvider xmlDoc)) | 
						|
				{ | 
						|
					string xmlDocFile = LookupLocalizedXmlDoc(module.FileName); | 
						|
					if (xmlDocFile == null) | 
						|
					{ | 
						|
						xmlDocFile = FindXmlDocumentation(Path.GetFileName(module.FileName), module.GetRuntime()); | 
						|
					} | 
						|
					if (xmlDocFile != null) | 
						|
					{ | 
						|
						xmlDoc = new XmlDocumentationProvider(xmlDocFile); | 
						|
						cache.Add(module, xmlDoc); | 
						|
					} | 
						|
					else | 
						|
					{ | 
						|
						cache.Add(module, null); // add missing documentation files as well | 
						|
						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) | 
						|
		{ | 
						|
			if (string.IsNullOrEmpty(fileName)) | 
						|
				return null; | 
						|
 | 
						|
			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; | 
						|
		} | 
						|
	} | 
						|
}
 | 
						|
 |