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.
201 lines
6.1 KiB
201 lines
6.1 KiB
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) |
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) |
|
|
|
using System; |
|
using System.Collections.Generic; |
|
using System.IO; |
|
using System.Reflection; |
|
|
|
using ICSharpCode.SharpDevelop.Dom.ReflectionLayer; |
|
|
|
namespace ICSharpCode.SharpDevelop.Dom |
|
{ |
|
public class ReflectionProjectContent : DefaultProjectContent |
|
{ |
|
string assemblyFullName; |
|
string assemblyName; |
|
DomAssemblyName[] referencedAssemblyNames; |
|
ICompilationUnit assemblyCompilationUnit; |
|
string assemblyLocation; |
|
ProjectContentRegistry registry; |
|
|
|
public string AssemblyLocation { |
|
get { |
|
return assemblyLocation; |
|
} |
|
} |
|
|
|
public string AssemblyFullName { |
|
get { |
|
return assemblyFullName; |
|
} |
|
} |
|
|
|
public override string AssemblyName { |
|
get { return assemblyName; } |
|
} |
|
|
|
/// <summary> |
|
/// Gets the list of assembly names referenced by this project content. |
|
/// </summary> |
|
public IList<DomAssemblyName> ReferencedAssemblyNames { |
|
get { return Array.AsReadOnly(referencedAssemblyNames); } |
|
} |
|
|
|
public ICompilationUnit AssemblyCompilationUnit { |
|
get { return assemblyCompilationUnit; } |
|
} |
|
|
|
public override IList<IAttribute> GetAssemblyAttributes() |
|
{ |
|
return assemblyCompilationUnit.Attributes; |
|
} |
|
|
|
DateTime assemblyFileLastWriteTime; |
|
|
|
/// <summary> |
|
/// Gets if the project content is representing the current version of the assembly. |
|
/// This property always returns true for ParseProjectContents but might return false |
|
/// for ReflectionProjectContent/CecilProjectContent if the file was changed. |
|
/// </summary> |
|
public override bool IsUpToDate { |
|
get { |
|
DateTime newWriteTime; |
|
try { |
|
newWriteTime = File.GetLastWriteTimeUtc(assemblyLocation); |
|
} catch (Exception ex) { |
|
LoggingService.Warn(ex); |
|
return true; |
|
} |
|
return assemblyFileLastWriteTime == newWriteTime; |
|
} |
|
} |
|
|
|
public ReflectionProjectContent(Assembly assembly, ProjectContentRegistry registry) |
|
: this(assembly, assembly.Location, registry) |
|
{ |
|
} |
|
|
|
public ReflectionProjectContent(Assembly assembly, string assemblyLocation, ProjectContentRegistry registry) |
|
: this(assembly.FullName, assemblyLocation, DomAssemblyName.Convert(assembly.GetReferencedAssemblies()), registry) |
|
{ |
|
foreach (Type type in assembly.GetExportedTypes()) { |
|
string name = type.FullName; |
|
if (name.IndexOf('+') < 0) { // type.IsNested |
|
AddClassToNamespaceListInternal(new ReflectionClass(assemblyCompilationUnit, type, name, null)); |
|
} |
|
} |
|
InitializeSpecialClasses(); |
|
AddAssemblyAttributes(assembly); |
|
assemblyCompilationUnit.Freeze(); |
|
} |
|
|
|
/// <summary> |
|
/// Adds assembly attributes from the specified assembly. |
|
/// |
|
/// The constructor already does this, this method is meant for unit tests only! |
|
/// </summary> |
|
public void AddAssemblyAttributes(Assembly assembly) |
|
{ |
|
ReflectionClass.AddAttributes(this, assemblyCompilationUnit.Attributes, CustomAttributeData.GetCustomAttributes(assembly)); |
|
} |
|
|
|
public ReflectionProjectContent(string assemblyFullName, string assemblyLocation, DomAssemblyName[] referencedAssemblies, ProjectContentRegistry registry) |
|
{ |
|
if (assemblyFullName == null) |
|
throw new ArgumentNullException("assemblyFullName"); |
|
if (assemblyLocation == null) |
|
throw new ArgumentNullException("assemblyLocation"); |
|
if (registry == null) |
|
throw new ArgumentNullException("registry"); |
|
|
|
this.registry = registry; |
|
this.assemblyFullName = assemblyFullName; |
|
this.assemblyName = (assemblyFullName.IndexOf(',') > -1) ? assemblyFullName.Substring(0, assemblyFullName.IndexOf(',')) : assemblyFullName; |
|
this.referencedAssemblyNames = referencedAssemblies; |
|
this.assemblyLocation = assemblyLocation; |
|
this.assemblyCompilationUnit = new DefaultCompilationUnit(this); |
|
|
|
try { |
|
assemblyFileLastWriteTime = File.GetLastWriteTimeUtc(assemblyLocation); |
|
} catch (Exception ex) { |
|
LoggingService.Warn(ex); |
|
} |
|
|
|
string fileName = XmlDoc.LookupLocalizedXmlDoc(assemblyLocation); |
|
if (fileName == null) { |
|
// Not found -> look in other directories: |
|
foreach (string testDirectory in XmlDoc.XmlDocLookupDirectories) { |
|
fileName = XmlDoc.LookupLocalizedXmlDoc(Path.Combine(testDirectory, Path.GetFileName(assemblyLocation))); |
|
if (fileName != null) |
|
break; |
|
} |
|
} |
|
|
|
if (fileName != null) { |
|
if (registry.persistence != null) { |
|
this.XmlDoc = XmlDoc.Load(fileName, Path.Combine(registry.persistence.CacheDirectory, "XmlDoc")); |
|
} else { |
|
this.XmlDoc = XmlDoc.Load(fileName, null); |
|
} |
|
} |
|
} |
|
|
|
public void InitializeSpecialClasses() |
|
{ |
|
// Replace the class representing System.Void with VoidClass.Instance |
|
IClass voidClass = GetClassInternal(VoidClass.VoidName, 0, Language); |
|
if (voidClass != null) { |
|
RemoveClass(voidClass); |
|
AddClassToNamespaceList(new VoidClass(this)); |
|
} |
|
} |
|
|
|
bool initialized = false; |
|
List<DomAssemblyName> missingNames; |
|
|
|
public void InitializeReferences() |
|
{ |
|
bool changed = false; |
|
if (initialized) { |
|
if (missingNames != null) { |
|
for (int i = 0; i < missingNames.Count; i++) { |
|
IProjectContent content = registry.GetExistingProjectContent(missingNames[i]); |
|
if (content != null) { |
|
changed = true; |
|
lock (ReferencedContents) { |
|
ReferencedContents.Add(content); |
|
} |
|
missingNames.RemoveAt(i--); |
|
} |
|
} |
|
if (missingNames.Count == 0) { |
|
missingNames = null; |
|
} |
|
} |
|
} else { |
|
initialized = true; |
|
foreach (DomAssemblyName name in referencedAssemblyNames) { |
|
IProjectContent content = registry.GetExistingProjectContent(name); |
|
if (content != null) { |
|
changed = true; |
|
lock (ReferencedContents) { |
|
ReferencedContents.Add(content); |
|
} |
|
} else { |
|
if (missingNames == null) |
|
missingNames = new List<DomAssemblyName>(); |
|
missingNames.Add(name); |
|
} |
|
} |
|
} |
|
if (changed) |
|
OnReferencedContentsChanged(EventArgs.Empty); |
|
} |
|
|
|
public override string ToString() |
|
{ |
|
return string.Format("[{0}: {1}]", GetType().Name, assemblyFullName); |
|
} |
|
} |
|
}
|
|
|