Browse Source

Introduced DomCache (a kind of code completion database that is generated on-the-fly for each assembly).

Advantages:
- faster than reflection
- referenced libraries do not need to be looked up during code completion (only when generating the cache)
-> fixes SD2-444 ReflectionOnlyAssemblyResolve is not used when an assembly is only needed inside inner classes
--> Code completion for VB's My-namespace works again
- Assemblies do not need to be hold in RAM (they are now loaded in a separate AppDomain)
-> no more locking problems
-> less memory consumption
Disadvantages:
- higher memory-consumption because currently the file is loaded at once (previously the data was lazy-loaded using Reflection)
-> but there are some optimizations possible (reusing string and DefaultParameter instances) and lazy-loading could be reimplemented similar to what Fidalgo does with its CCDB.


git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@524 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 20 years ago
parent
commit
26313ee208
  1. 2
      src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
  2. 3
      src/Main/Base/Project/Src/Dom/IAttribute.cs
  3. 8
      src/Main/Base/Project/Src/Dom/IProperty.cs
  4. 6
      src/Main/Base/Project/Src/Dom/Implementations/ConstructedReturnType.cs
  5. 9
      src/Main/Base/Project/Src/Dom/Implementations/DefaultAttribute.cs
  6. 10
      src/Main/Base/Project/Src/Dom/Implementations/DefaultEvent.cs
  7. 50
      src/Main/Base/Project/Src/Dom/Implementations/DefaultProperty.cs
  8. 667
      src/Main/Base/Project/Src/Dom/ReflectionLayer/DomPersistence.cs
  9. 113
      src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionClass.cs
  10. 12
      src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionEvent.cs
  11. 85
      src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionLoader.cs
  12. 43
      src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionMethod.cs
  13. 21
      src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionProperty.cs
  14. 39
      src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionReturnType.cs
  15. 27
      src/Main/Base/Project/Src/Services/ParserService/ParserService.cs
  16. 194
      src/Main/Base/Project/Src/Services/ParserService/ProjectContentRegistry.cs
  17. 78
      src/Main/Base/Project/Src/Services/ParserService/ReflectionProjectContent.cs

2
src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj

@ -706,6 +706,8 @@ @@ -706,6 +706,8 @@
<Compile Include="Src\Dom\Implementations\AnonymousMethodReturnType.cs" />
<Compile Include="Src\Project\ConfigurationGuiBinding.cs" />
<Compile Include="Src\Project\ChooseStorageLocationButton.cs" />
<Compile Include="Src\Dom\ReflectionLayer\ReflectionLoader.cs" />
<Compile Include="Src\Dom\ReflectionLayer\DomPersistence.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Libraries\DockPanel_Src\WinFormsUI\WinFormsUI.csproj">

3
src/Main/Base/Project/Src/Dom/IAttribute.cs

@ -20,6 +20,8 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -20,6 +20,8 @@ namespace ICSharpCode.SharpDevelop.Dom
get;
}
/*
* These properties are not stored in DomPersistence and cannot not be used!
List<AttributeArgument> PositionalArguments {
get;
}
@ -27,6 +29,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -27,6 +29,7 @@ namespace ICSharpCode.SharpDevelop.Dom
SortedList<string, AttributeArgument> NamedArguments {
get;
}
*/
}
public enum AttributeTarget

8
src/Main/Base/Project/Src/Dom/IProperty.cs

@ -32,13 +32,5 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -32,13 +32,5 @@ namespace ICSharpCode.SharpDevelop.Dom
bool IsIndexer {
get;
}
IMethod GetterMethod {
get;
}
IMethod SetterMethod {
get;
}
}
}

6
src/Main/Base/Project/Src/Dom/Implementations/ConstructedReturnType.cs

@ -24,16 +24,16 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -24,16 +24,16 @@ namespace ICSharpCode.SharpDevelop.Dom
// Return types that should be substituted for the generic types
// If a substitution is unknown (type could not be resolved), the list
// contains a null entry.
List<IReturnType> typeParameters;
IList<IReturnType> typeParameters;
IReturnType baseType;
public List<IReturnType> TypeArguments {
public IList<IReturnType> TypeArguments {
get {
return typeParameters;
}
}
public ConstructedReturnType(IReturnType baseType, List<IReturnType> typeParameters)
public ConstructedReturnType(IReturnType baseType, IList<IReturnType> typeParameters)
{
if (baseType == null)
throw new ArgumentNullException("baseType");

9
src/Main/Base/Project/Src/Dom/Implementations/DefaultAttribute.cs

@ -67,14 +67,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -67,14 +67,7 @@ namespace ICSharpCode.SharpDevelop.Dom
}
public virtual int CompareTo(IAttribute value) {
int cmp;
cmp = Name.CompareTo(value.Name);
if (cmp != 0) {
return cmp;
}
return DiffUtility.Compare(PositionalArguments, value.PositionalArguments);
return Name.CompareTo(value.Name);
}
int IComparable.CompareTo(object value) {

10
src/Main/Base/Project/Src/Dom/Implementations/DefaultEvent.cs

@ -14,7 +14,6 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -14,7 +14,6 @@ namespace ICSharpCode.SharpDevelop.Dom
public class DefaultEvent : AbstractMember, IEvent
{
protected DomRegion bodyRegion;
protected EventAttributes eventAttributes;
protected IMethod addMethod;
protected IMethod removeMethod;
protected IMethod raiseMethod;
@ -31,18 +30,12 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -31,18 +30,12 @@ namespace ICSharpCode.SharpDevelop.Dom
}
}
public virtual EventAttributes EventAttributes {
get {
return eventAttributes;
}
}
public override IMember Clone()
{
return new DefaultEvent(Name, ReturnType, Modifiers, Region, BodyRegion, DeclaringType);
}
protected DefaultEvent(IClass declaringType, string name) : base(declaringType, name)
public DefaultEvent(IClass declaringType, string name) : base(declaringType, name)
{
}
@ -93,6 +86,5 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -93,6 +86,5 @@ namespace ICSharpCode.SharpDevelop.Dom
return raiseMethod;
}
}
}
}

50
src/Main/Base/Project/Src/Dom/Implementations/DefaultProperty.cs

@ -14,23 +14,29 @@ namespace ICSharpCode.SharpDevelop.Dom { @@ -14,23 +14,29 @@ namespace ICSharpCode.SharpDevelop.Dom {
[Serializable]
public class DefaultProperty : AbstractMember, IProperty
{
protected DomRegion bodyRegion = DomRegion.Empty;
DomRegion bodyRegion = DomRegion.Empty;
DomRegion getterRegion = DomRegion.Empty;
DomRegion setterRegion = DomRegion.Empty;
protected IMethod getterMethod;
protected IMethod setterMethod;
List<IParameter> parameters = null;
bool isIndexer;
internal byte accessFlags;
const byte indexerFlag = 1;
const byte getterFlag = 2;
const byte setterFlag = 4;
public bool IsIndexer {
get {
return isIndexer;
get { return (accessFlags & indexerFlag) == indexerFlag; }
set { if (value) accessFlags |= indexerFlag; else accessFlags &= 255-indexerFlag; }
}
set {
isIndexer = value;
public bool CanGet {
get { return (accessFlags & getterFlag) == getterFlag; }
set { if (value) accessFlags |= getterFlag; else accessFlags &= 255-getterFlag; }
}
public bool CanSet {
get { return (accessFlags & setterFlag) == setterFlag; }
set { if (value) accessFlags |= setterFlag; else accessFlags &= 255-setterFlag; }
}
public override string DocumentationTag {
@ -49,7 +55,7 @@ namespace ICSharpCode.SharpDevelop.Dom { @@ -49,7 +55,7 @@ namespace ICSharpCode.SharpDevelop.Dom {
{
DefaultProperty p = new DefaultProperty(Name, ReturnType, Modifiers, Region, BodyRegion, DeclaringType);
p.parameters = DefaultParameter.Clone(this.Parameters);
p.isIndexer = this.isIndexer;
p.accessFlags = this.accessFlags;
return p;
}
@ -83,30 +89,6 @@ namespace ICSharpCode.SharpDevelop.Dom { @@ -83,30 +89,6 @@ namespace ICSharpCode.SharpDevelop.Dom {
}
}
public IMethod GetterMethod {
get {
return getterMethod;
}
}
public IMethod SetterMethod {
get {
return setterMethod;
}
}
public virtual bool CanGet {
get {
return !getterRegion.IsEmpty;
}
}
public virtual bool CanSet {
get {
return !setterRegion.IsEmpty;
}
}
public DefaultProperty(IClass declaringType, string name) : base(declaringType, name)
{
}

667
src/Main/Base/Project/Src/Dom/ReflectionLayer/DomPersistence.cs

@ -0,0 +1,667 @@ @@ -0,0 +1,667 @@
/*
* Created by SharpDevelop.
* User: Daniel Grunwald
* Date: 28.09.2005
* Time: 19:52
*/
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.IO;
using ICSharpCode.Core;
namespace ICSharpCode.SharpDevelop.Dom
{
/// <summary>
/// This class can write Dom entity into a binary file for fast loading.
/// </summary>
public static class DomPersistence
{
public const long FileMagic = 0x11635233ED2F428C;
public const long IndexFileMagic = 0x11635233ED2F427D;
public const short FileVersion = 1;
#region Cache management
#if DEBUG
const string tempPathName = "SharpDevelop/DomCacheDebug";
#else
const string tempPathName = "SharpDevelop/DomCache";
#endif
static string MakeTempPath()
{
string tempPath = Path.Combine(Path.GetTempPath(), tempPathName);
if (!Directory.Exists(tempPath))
Directory.CreateDirectory(tempPath);
return tempPath;
}
public static string SaveProjectContent(ReflectionProjectContent pc)
{
string assemblyFullName = pc.AssemblyFullName;
int pos = assemblyFullName.IndexOf(',');
string fileName = Path.Combine(MakeTempPath(),
assemblyFullName.Substring(0, pos)
+ "." + assemblyFullName.GetHashCode().ToString("x", CultureInfo.InvariantCulture)
+ "." + pc.AssemblyLocation.GetHashCode().ToString("x", CultureInfo.InvariantCulture)
+ ".dat");
AddFileNameToCacheIndex(Path.GetFileName(fileName), pc);
using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write)) {
using (BinaryWriter writer = new BinaryWriter(fs)) {
new ReadWriteHelper(writer).WriteProjectContent(pc);
}
}
return fileName;
}
public static ReflectionProjectContent LoadProjectContentByAssemblyName(string assemblyName)
{
string cacheFileName;
if (CacheIndex.TryGetValue(assemblyName, out cacheFileName)) {
return LoadProjectContent(Path.Combine(MakeTempPath(), cacheFileName));
} else {
return null;
}
}
public static ReflectionProjectContent LoadProjectContent(string cacheFileName)
{
ReflectionProjectContent pc;
using (FileStream fs = new FileStream(cacheFileName, FileMode.Open, FileAccess.Read)) {
using (BinaryReader reader = new BinaryReader(fs)) {
pc = new ReadWriteHelper(reader).ReadProjectContent();
}
}
pc.InitializeSpecialClasses();
return pc;
}
#endregion
#region Cache index
static string GetIndexFileName() { return Path.Combine(MakeTempPath(), "index.dat"); }
static Dictionary<string, string> cacheIndex;
static Dictionary<string, string> CacheIndex {
get {
if (cacheIndex == null) {
cacheIndex = LoadCacheIndex();
}
return cacheIndex;
}
}
static Dictionary<string, string> LoadCacheIndex()
{
string indexFile = GetIndexFileName();
Dictionary<string, string> list = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
if (File.Exists(indexFile)) {
using (FileStream fs = new FileStream(indexFile, FileMode.Open, FileAccess.Read)) {
using (BinaryReader reader = new BinaryReader(fs)) {
if (reader.ReadInt64() != IndexFileMagic) {
LoggingService.Warn("Index cache has wrong file magic");
return list;
}
if (reader.ReadInt16() != FileVersion) {
LoggingService.Warn("Index cache has wrong file version");
return list;
}
int count = reader.ReadInt32();
for (int i = 0; i < count; i++) {
string key = reader.ReadString();
list[key] = reader.ReadString();
}
return list;
}
}
} else {
return list;
}
}
static void SaveCacheIndex(Dictionary<string, string> cacheIndex)
{
string indexFile = GetIndexFileName();
using (FileStream fs = new FileStream(indexFile, FileMode.Create, FileAccess.Write)) {
using (BinaryWriter writer = new BinaryWriter(fs)) {
writer.Write(IndexFileMagic);
writer.Write(FileVersion);
writer.Write(cacheIndex.Count);
foreach (KeyValuePair<string, string> e in cacheIndex) {
writer.Write(e.Key);
writer.Write(e.Value);
}
}
}
}
static void AddFileNameToCacheIndex(string cacheFile, ReflectionProjectContent pc)
{
Dictionary<string, string> l = LoadCacheIndex();
l[pc.AssemblyLocation] = cacheFile;
string txt = pc.AssemblyFullName;
l[txt] = cacheFile;
int pos = txt.LastIndexOf(',');
do {
txt = txt.Substring(0, pos);
if (l.ContainsKey(txt))
break;
l[txt] = cacheFile;
pos = txt.LastIndexOf(',');
} while (pos >= 0);
SaveCacheIndex(l);
cacheIndex = l;
}
#endregion
private sealed class ReadWriteHelper
{
ReflectionProjectContent pc;
readonly BinaryWriter writer;
readonly Dictionary<string, int> classIndices = new Dictionary<string, int>(StringComparer.InvariantCultureIgnoreCase);
readonly BinaryReader reader;
IReturnType[] types;
#region Write/Read ProjectContent
public ReadWriteHelper(BinaryWriter writer)
{
this.writer = writer;
}
public void WriteProjectContent(ReflectionProjectContent pc)
{
this.pc = pc;
writer.Write(FileMagic);
writer.Write(FileVersion);
writer.Write(pc.AssemblyFullName);
writer.Write(pc.AssemblyLocation);
writer.Write(pc.ReferencedAssemblies.Length);
foreach (AssemblyName name in pc.ReferencedAssemblies) {
writer.Write(name.FullName);
}
WriteClasses();
}
public ReadWriteHelper(BinaryReader reader)
{
this.reader = reader;
}
public ReflectionProjectContent ReadProjectContent()
{
if (reader.ReadInt64() != FileMagic) {
LoggingService.Warn("Read dom: wrong magic");
return null;
}
if (reader.ReadInt16() != FileVersion) {
LoggingService.Warn("Read dom: wrong version");
return null;
}
string assemblyName = reader.ReadString();
string assemblyLocation = reader.ReadString();
AssemblyName[] referencedAssemblies = new AssemblyName[reader.ReadInt32()];
for (int i = 0; i < referencedAssemblies.Length; i++) {
referencedAssemblies[i] = new AssemblyName(reader.ReadString());
}
this.pc = new ReflectionProjectContent(assemblyName, assemblyLocation, referencedAssemblies);
ReadClasses();
return pc;
}
void WriteClasses()
{
ICollection<IClass> classes = pc.Classes;
classIndices.Clear();
int i = 0;
foreach (IClass c in classes) {
classIndices[c.FullyQualifiedName] = i;
i += 1;
}
List<string> externalTypes = new List<string>();
CreateExternalTypeList(externalTypes, classes.Count, classes);
writer.Write(classes.Count);
writer.Write(externalTypes.Count);
foreach (IClass c in classes) {
writer.Write(c.FullyQualifiedName);
}
foreach (string type in externalTypes) {
writer.Write(type);
}
foreach (IClass c in classes) {
WriteClass(c);
}
}
void ReadClasses()
{
int classCount = reader.ReadInt32();
int externalTypeCount = reader.ReadInt32();
types = new IReturnType[classCount + externalTypeCount];
DefaultClass[] classes = new DefaultClass[classCount];
for (int i = 0; i < classes.Length; i++) {
DefaultClass c = new DefaultClass(pc.AssemblyCompilationUnit, reader.ReadString());
classes[i] = c;
types[i] = c.DefaultReturnType;
}
for (int i = classCount; i < types.Length; i++) {
types[i] = new GetClassReturnType(pc, reader.ReadString());
}
for (int i = 0; i < classes.Length; i++) {
ReadClass(classes[i]);
pc.AddClassToNamespaceList(classes[i]);
}
}
#endregion
#region Write/Read Class
IClass currentClass;
void WriteClass(IClass c)
{
this.currentClass = c;
WriteTemplates(c.TypeParameters);
writer.Write(c.BaseTypes.Count);
foreach (IReturnType type in c.BaseTypes) {
WriteType(type);
}
writer.Write((int)c.Modifiers);
WriteAttributes(c.Attributes);
writer.Write(c.InnerClasses.Count);
foreach (IClass innerClass in c.InnerClasses) {
WriteString(innerClass.FullyQualifiedName);
WriteClass(innerClass);
}
this.currentClass = c;
writer.Write(c.Methods.Count);
foreach (IMethod method in c.Methods) {
WriteMethod(method);
}
writer.Write(c.Properties.Count);
foreach (IProperty property in c.Properties) {
WriteProperty(property);
}
writer.Write(c.Events.Count);
foreach (IEvent evt in c.Events) {
WriteEvent(evt);
}
writer.Write(c.Fields.Count);
foreach (IField field in c.Fields) {
WriteField(field);
}
this.currentClass = null;
}
void WriteTemplates(List<ITypeParameter> list)
{
// read code exists twice: in ReadClass and ReadMethod
writer.Write((byte)list.Count);
foreach (ITypeParameter typeParameter in list) {
WriteString(typeParameter.Name);
}
foreach (ITypeParameter typeParameter in list) {
writer.Write(typeParameter.Constraints.Count);
foreach (IReturnType type in typeParameter.Constraints) {
WriteType(type);
}
}
}
void ReadClass(DefaultClass c)
{
this.currentClass = c;
int count;
count = reader.ReadByte();
for (int i = 0; i < count; i++) {
c.TypeParameters.Add(new DefaultTypeParameter(c, ReadString(), i));
}
foreach (ITypeParameter typeParameter in c.TypeParameters) {
count = reader.ReadInt32();
for (int i = 0; i < count; i++) {
typeParameter.Constraints.Add(ReadType());
}
}
count = reader.ReadInt32();
for (int i = 0; i < count; i++) {
c.BaseTypes.Add(ReadType());
}
c.Modifiers = (ModifierEnum)reader.ReadInt32();
ReadAttributes(c.Attributes);
count = reader.ReadInt32();
for (int i = 0; i < count; i++) {
DefaultClass innerClass = new DefaultClass(c.CompilationUnit, c);
innerClass.FullyQualifiedName = ReadString();
c.InnerClasses.Add(innerClass);
ReadClass(innerClass);
}
this.currentClass = c;
count = reader.ReadInt32();
for (int i = 0; i < count; i++) {
c.Methods.Add(ReadMethod());
}
count = reader.ReadInt32();
for (int i = 0; i < count; i++) {
c.Properties.Add(ReadProperty());
}
count = reader.ReadInt32();
for (int i = 0; i < count; i++) {
c.Events.Add(ReadEvent());
}
count = reader.ReadInt32();
for (int i = 0; i < count; i++) {
c.Fields.Add(ReadField());
}
this.currentClass = null;
}
#endregion
#region Write/Read return types
/// <summary>
/// Finds all return types used in the class collection and adds the unknown ones
/// to the externalTypeIndices and externalTypes collections.
/// </summary>
void CreateExternalTypeList(List<string> externalTypes,
int classCount, ICollection<IClass> classes)
{
foreach (IClass c in classes) {
CreateExternalTypeList(externalTypes, classCount, c.InnerClasses);
foreach (IReturnType returnType in c.BaseTypes) {
AddExternalType(returnType, externalTypes, classCount);
}
foreach (ITypeParameter tp in c.TypeParameters) {
foreach (IReturnType returnType in tp.Constraints) {
AddExternalType(returnType, externalTypes, classCount);
}
}
foreach (IField f in c.Fields) {
AddExternalType(f.ReturnType, externalTypes, classCount);
}
foreach (IEvent f in c.Events) {
AddExternalType(f.ReturnType, externalTypes, classCount);
}
foreach (IProperty p in c.Properties) {
AddExternalType(p.ReturnType, externalTypes, classCount);
foreach (IParameter parameter in p.Parameters) {
AddExternalType(parameter.ReturnType, externalTypes, classCount);
}
}
foreach (IMethod m in c.Methods) {
AddExternalType(m.ReturnType, externalTypes, classCount);
foreach (IParameter parameter in m.Parameters) {
AddExternalType(parameter.ReturnType, externalTypes, classCount);
}
foreach (ITypeParameter tp in m.TypeParameters) {
foreach (IReturnType returnType in tp.Constraints) {
AddExternalType(returnType, externalTypes, classCount);
}
}
}
}
}
void AddExternalType(IReturnType rt, List<string> externalTypes, int classCount)
{
if (rt.IsDefaultReturnType) {
string name = rt.FullyQualifiedName;
if (!classIndices.ContainsKey(name)) {
classIndices.Add(name, externalTypes.Count + classCount);
externalTypes.Add(name);
}
} else if (rt is ArrayReturnType) {
AddExternalType(((ArrayReturnType)rt).ElementType, externalTypes, classCount);
} else if (rt is ConstructedReturnType) {
ConstructedReturnType crt = (ConstructedReturnType)rt;
AddExternalType(crt.BaseType, externalTypes, classCount);
foreach (IReturnType typeArgument in crt.TypeArguments) {
AddExternalType(typeArgument, externalTypes, classCount);
}
} else if (rt is GenericReturnType) {
// ignore
} else {
LoggingService.Warn("Unknown return type: " + rt.ToString());
}
}
const int ArrayRTCode = -1;
const int ConstructedRTCode = -2;
const int TypeGenericRTCode = -3;
const int MethodGenericRTCode = -4;
const int NullRTReferenceCode = -5;
const int VoidRTCode = -6;
void WriteType(IReturnType rt)
{
if (rt == null) {
writer.Write(NullRTReferenceCode);
return;
}
if (rt.IsDefaultReturnType) {
string name = rt.FullyQualifiedName;
if (name == "System.Void") {
writer.Write(VoidRTCode);
} else {
writer.Write(classIndices[rt.FullyQualifiedName]);
}
} else if (rt is ArrayReturnType) {
ArrayReturnType art = (ArrayReturnType)rt;
writer.Write(ArrayRTCode);
writer.Write(art.ArrayDimensions);
WriteType(art.ElementType);
} else if (rt is ConstructedReturnType) {
ConstructedReturnType crt = (ConstructedReturnType)rt;
writer.Write(ConstructedRTCode);
WriteType(crt.BaseType);
writer.Write((byte)crt.TypeArguments.Count);
foreach (IReturnType typeArgument in crt.TypeArguments) {
WriteType(typeArgument);
}
} else if (rt is GenericReturnType) {
GenericReturnType grt = (GenericReturnType)rt;
if (grt.TypeParameter.Method != null) {
writer.Write(MethodGenericRTCode);
} else {
writer.Write(TypeGenericRTCode);
}
writer.Write(grt.TypeParameter.Index);
} else {
writer.Write(NullRTReferenceCode);
LoggingService.Warn("Unknown return type: " + rt.ToString());
}
}
// outerClass and outerMethod are required for generic return types
IReturnType ReadType()
{
int index = reader.ReadInt32();
switch (index) {
case ArrayRTCode:
int dimensions = reader.ReadInt32();
return new ArrayReturnType(ReadType(), dimensions);
case ConstructedRTCode:
IReturnType baseType = ReadType();
IReturnType[] typeArguments = new IReturnType[reader.ReadByte()];
for (int i = 0; i < typeArguments.Length; i++) {
typeArguments[i] = ReadType();
}
return new ConstructedReturnType(baseType, typeArguments);
case TypeGenericRTCode:
return new GenericReturnType(currentClass.TypeParameters[reader.ReadInt32()]);
case MethodGenericRTCode:
return new GenericReturnType(currentMethod.TypeParameters[reader.ReadInt32()]);
case NullRTReferenceCode:
return null;
case VoidRTCode:
return ReflectionReturnType.Void;
default:
return types[index];
}
}
#endregion
#region Write/Read class member
void WriteString(string text)
{
writer.Write(text ?? string.Empty);
}
string ReadString()
{
return reader.ReadString();
}
void WriteMember(IMember m)
{
WriteString(m.Name);
writer.Write((int)m.Modifiers);
WriteAttributes(m.Attributes);
if (!(m is IMethod)) {
// method must store ReturnType AFTER Template definitions
WriteType(m.ReturnType);
}
}
void ReadMember(IMember m)
{
// name is already read by the method that calls the member constructor
m.Modifiers = (ModifierEnum)reader.ReadInt32();
ReadAttributes(m.Attributes);
if (!(m is IMethod)) {
m.ReturnType = ReadType();
}
}
#endregion
#region Write/Read attributes
void WriteAttributes(IList<IAttribute> attributes)
{
writer.Write((ushort)attributes.Count);
foreach (IAttribute a in attributes) {
WriteString(a.Name);
writer.Write((byte)a.AttributeTarget);
}
}
void ReadAttributes(IList<IAttribute> attributes)
{
int count = reader.ReadUInt16();
for (int i = 0; i < count; i++) {
string name = ReadString();
attributes.Add(new DefaultAttribute(name, (AttributeTarget)reader.ReadByte()));
}
}
#endregion
#region Write/Read parameters
void WriteParameters(IList<IParameter> parameters)
{
writer.Write((ushort)parameters.Count);
foreach (IParameter p in parameters) {
WriteString(p.Name);
WriteType(p.ReturnType);
writer.Write((byte)p.Modifiers);
WriteAttributes(p.Attributes);
}
}
void ReadParameters(IList<IParameter> parameters)
{
int count = reader.ReadUInt16();
for (int i = 0; i < count; i++) {
string name = ReadString();
DefaultParameter p = new DefaultParameter(name, ReadType(), DomRegion.Empty);
p.Modifiers = (ParameterModifiers)reader.ReadByte();
ReadAttributes(p.Attributes);
parameters.Add(p);
}
}
#endregion
#region Write/Read Method
IMethod currentMethod;
void WriteMethod(IMethod m)
{
currentMethod = m;
WriteMember(m);
WriteTemplates(m.TypeParameters);
WriteType(m.ReturnType);
WriteParameters(m.Parameters);
currentMethod = null;
}
IMethod ReadMethod()
{
DefaultMethod m = new DefaultMethod(currentClass, ReadString());
currentMethod = m;
ReadMember(m);
int count = reader.ReadByte();
for (int i = 0; i < count; i++) {
m.TypeParameters.Add(new DefaultTypeParameter(m, ReadString(), i));
}
foreach (ITypeParameter typeParameter in m.TypeParameters) {
count = reader.ReadInt32();
for (int i = 0; i < count; i++) {
typeParameter.Constraints.Add(ReadType());
}
}
m.ReturnType = ReadType();
ReadParameters(m.Parameters);
currentMethod = null;
return m;
}
#endregion
#region Write/Read Property
void WriteProperty(IProperty p)
{
WriteMember(p);
writer.Write(((DefaultProperty)p).accessFlags);
WriteParameters(p.Parameters);
}
IProperty ReadProperty()
{
DefaultProperty p = new DefaultProperty(currentClass, ReadString());
ReadMember(p);
p.accessFlags = reader.ReadByte();
ReadParameters(p.Parameters);
return p;
}
#endregion
#region Write/Read Event
void WriteEvent(IEvent p)
{
WriteMember(p);
}
IEvent ReadEvent()
{
DefaultEvent p = new DefaultEvent(currentClass, ReadString());
ReadMember(p);
return p;
}
#endregion
#region Write/Read Field
void WriteField(IField p)
{
WriteMember(p);
}
IField ReadField()
{
DefaultField p = new DefaultField(currentClass, ReadString());
ReadMember(p);
return p;
}
#endregion
}
}
}

113
src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionClass.cs

@ -16,111 +16,47 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -16,111 +16,47 @@ namespace ICSharpCode.SharpDevelop.Dom
[Serializable]
public class ReflectionClass : DefaultClass
{
Type type;
const BindingFlags flags = BindingFlags.Instance |
BindingFlags.Static |
BindingFlags.NonPublic |
BindingFlags.DeclaredOnly |
BindingFlags.Public;
List<IClass> innerClasses;
public override List<IClass> InnerClasses {
get {
if (innerClasses == null) {
innerClasses = new List<IClass>();
void InitMembers(Type type)
{
foreach (Type nestedType in type.GetNestedTypes(flags)) {
if (!nestedType.IsVisible) continue;
string name = nestedType.FullName.Replace('+', '.');
innerClasses.Add(new ReflectionClass(CompilationUnit, nestedType, name, this));
}
}
return innerClasses;
}
}
static Dictionary<ReflectionClass, List<IField>> fieldCache = new Dictionary<ReflectionClass, List<IField>>();
static Dictionary<ReflectionClass, List<IProperty>> propertyCache = new Dictionary<ReflectionClass, List<IProperty>>();
static Dictionary<ReflectionClass, List<IMethod>> methodCache = new Dictionary<ReflectionClass, List<IMethod>>();
static Dictionary<ReflectionClass, List<IEvent>> eventCache = new Dictionary<ReflectionClass, List<IEvent>>();
public static void ClearMemberCache()
{
fieldCache.Clear();
propertyCache.Clear();
methodCache.Clear();
eventCache.Clear();
InnerClasses.Add(new ReflectionClass(CompilationUnit, nestedType, name, this));
}
public override List<IField> Fields {
get {
List<IField> fields;
if (!fieldCache.TryGetValue(this, out fields)) {
fields = new List<IField>();
foreach (FieldInfo field in type.GetFields(flags)) {
if (!field.IsPublic && !field.IsFamily) continue;
if (!field.IsSpecialName) {
fields.Add(new ReflectionField(field, this));
}
}
fieldCache.Add(this, fields);
}
return fields;
Fields.Add(new ReflectionField(field, this));
}
}
public override List<IProperty> Properties {
get {
List<IProperty> properties;
if (!propertyCache.TryGetValue(this, out properties)) {
properties = new List<IProperty>();
foreach (PropertyInfo propertyInfo in type.GetProperties(flags)) {
ReflectionProperty prop = new ReflectionProperty(propertyInfo, this);
if (prop.IsPublic || prop.IsProtected)
properties.Add(prop);
}
propertyCache.Add(this, properties);
}
return properties;
}
Properties.Add(prop);
}
public override List<IMethod> Methods {
get {
List<IMethod> methods;
if (!methodCache.TryGetValue(this, out methods)) {
methods = new List<IMethod>();
foreach (ConstructorInfo constructorInfo in type.GetConstructors(flags)) {
if (!constructorInfo.IsPublic && !constructorInfo.IsFamily) continue;
IMethod newMethod = new ReflectionMethod(constructorInfo, this);
methods.Add(newMethod);
Methods.Add(new ReflectionMethod(constructorInfo, this));
}
foreach (MethodInfo methodInfo in type.GetMethods(flags)) {
if (!methodInfo.IsPublic && !methodInfo.IsFamily) continue;
if (!methodInfo.IsSpecialName) {
IMethod newMethod = new ReflectionMethod(methodInfo, this);
methods.Add(newMethod);
}
}
methodCache.Add(this, methods);
}
return methods;
Methods.Add(new ReflectionMethod(methodInfo, this));
}
}
public override List<IEvent> Events {
get {
List<IEvent> events;
if (!eventCache.TryGetValue(this, out events)) {
events = new List<IEvent>();
foreach (EventInfo eventInfo in type.GetEvents(flags)) {
events.Add(new ReflectionEvent(eventInfo, this));
}
eventCache.Add(this, events);
}
return events;
Events.Add(new ReflectionEvent(eventInfo, this));
}
}
@ -129,34 +65,6 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -129,34 +65,6 @@ namespace ICSharpCode.SharpDevelop.Dom
return type.IsSubclassOf(typeof(Delegate)) && type != typeof(MulticastDelegate);
}
#region VoidClass / VoidReturnType
public class VoidClass : ReflectionClass
{
public VoidClass(ICompilationUnit compilationUnit) : base(compilationUnit, typeof(void), typeof(void).FullName, null) {}
protected override IReturnType CreateDefaultReturnType() {
return new VoidReturnType(this);
}
}
private class VoidReturnType : DefaultReturnType
{
public VoidReturnType(IClass c) : base(c) {}
public override List<IMethod> GetMethods() {
return new List<IMethod>(1);
}
public override List<IProperty> GetProperties() {
return new List<IProperty>(1);
}
public override List<IField> GetFields() {
return new List<IField>(1);
}
public override List<IEvent> GetEvents() {
return new List<IEvent>(1);
}
}
#endregion
static void AddAttributes(IProjectContent pc, List<IAttribute> list, IList<CustomAttributeData> attributes)
{
foreach (CustomAttributeData att in attributes) {
@ -175,7 +83,6 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -175,7 +83,6 @@ namespace ICSharpCode.SharpDevelop.Dom
public ReflectionClass(ICompilationUnit compilationUnit, Type type, string fullName, IClass declaringType) : base(compilationUnit, declaringType)
{
this.type = type;
if (fullName.Length > 2 && fullName[fullName.Length - 2] == '`') {
FullyQualifiedName = fullName.Substring(0, fullName.Length - 2);
} else {
@ -250,6 +157,8 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -250,6 +157,8 @@ namespace ICSharpCode.SharpDevelop.Dom
foreach (Type iface in type.GetInterfaces()) {
BaseTypes.Add(ReflectionReturnType.Create(compilationUnit.ProjectContent, iface, false));
}
InitMembers(type);
}
}

12
src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionEvent.cs

@ -15,19 +15,9 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -15,19 +15,9 @@ namespace ICSharpCode.SharpDevelop.Dom
[Serializable]
public class ReflectionEvent : DefaultEvent
{
EventInfo eventInfo;
public override IReturnType ReturnType {
get {
return ReflectionReturnType.Create(this, eventInfo.EventHandlerType, false);
}
set {
}
}
public ReflectionEvent(EventInfo eventInfo, IClass declaringType) : base(declaringType, eventInfo.Name)
{
this.eventInfo = eventInfo;
this.ReturnType = ReflectionReturnType.Create(this, eventInfo.EventHandlerType, false);
// get modifiers
MethodInfo methodBase = null;

85
src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionLoader.cs

@ -0,0 +1,85 @@ @@ -0,0 +1,85 @@
/*
* Created by SharpDevelop.
* User: Daniel Grunwald
* Date: 28.09.2005
* Time: 18:48
*/
using System;
using System.IO;
using System.Reflection;
using ICSharpCode.Core;
namespace ICSharpCode.SharpDevelop.Dom
{
public sealed class ReflectionLoader : MarshalByRefObject
{
public override string ToString()
{
return "ReflectionLoader in " + AppDomain.CurrentDomain.FriendlyName;
}
public string LoadAndCreateDatabase(string fileName, string include)
{
try {
ReflectionProjectContent content = LoadProjectContent(fileName, include);
return DomPersistence.SaveProjectContent(content);
} catch (Exception ex) {
LoggingService.Error(ex);
return null;
}
}
ReflectionProjectContent LoadProjectContent(string fileName, string include)
{
fileName = Path.GetFullPath(fileName);
LoggingService.Debug("Trying to load " + fileName);
Assembly assembly;
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += AssemblyResolve;
lookupDirectory = Path.GetDirectoryName(fileName);
try {
if (File.Exists(fileName)) {
assembly = Assembly.ReflectionOnlyLoadFrom(fileName);
return new ReflectionProjectContent(assembly, fileName);
}
assembly = ProjectContentRegistry.LoadGACAssembly(include, true);
return new ReflectionProjectContent(assembly);
} catch (BadImageFormatException) {
LoggingService.Warn("BadImageFormat: " + include);
return null;
} finally {
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve -= AssemblyResolve;
lookupDirectory = null;
}
}
string lookupDirectory;
Assembly AssemblyResolve(object sender, ResolveEventArgs e)
{
AssemblyName name = new AssemblyName(e.Name);
LoggingService.Debug("ProjectContentRegistry.AssemblyResolve " + e.Name);
string path = Path.Combine(lookupDirectory, name.Name);
if (File.Exists(path + ".dll")) {
return Assembly.ReflectionOnlyLoadFrom(path + ".dll");
}
if (File.Exists(path + ".exe")) {
return Assembly.ReflectionOnlyLoadFrom(path + ".exe");
}
if (File.Exists(path)) {
return Assembly.ReflectionOnlyLoadFrom(path);
}
try {
LoggingService.Debug("AssemblyResolve trying ReflectionOnlyLoad");
return Assembly.ReflectionOnlyLoad(e.Name);
} catch (FileNotFoundException) {
LoggingService.Warn("AssemblyResolve: ReflectionOnlyLoad failed for " + e.Name);
// We can't get the assembly we want.
// But propably we can get a similar version of it.
AssemblyName fixedName = ProjectContentRegistry.FindBestMatchingAssemblyName(e.Name);
LoggingService.Info("AssemblyResolve: FixedName: " + fixedName);
return Assembly.ReflectionOnlyLoad(fixedName.FullName);
}
}
}
}

43
src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionMethod.cs

@ -17,50 +17,19 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -17,50 +17,19 @@ namespace ICSharpCode.SharpDevelop.Dom
[Serializable]
public class ReflectionMethod : DefaultMethod
{
MethodBase methodBase;
public override bool IsConstructor {
get {
return methodBase is ConstructorInfo;
}
}
public override IReturnType ReturnType {
get {
public ReflectionMethod(MethodBase methodBase, IClass declaringType)
: base(declaringType, methodBase is ConstructorInfo ? "#ctor" : methodBase.Name)
{
if (methodBase is MethodInfo) {
return ReflectionReturnType.Create(this, ((MethodInfo)methodBase).ReturnType, false);
this.ReturnType = ReflectionReturnType.Create(this, ((MethodInfo)methodBase).ReturnType, false);
} else if (methodBase is ConstructorInfo) {
return DeclaringType.DefaultReturnType;
}
return null;
}
set {
throw new NotSupportedException();
}
this.ReturnType = DeclaringType.DefaultReturnType;
}
List<IParameter> parameters;
public override List<IParameter> Parameters {
get {
if (parameters == null) {
parameters = new List<IParameter>();
foreach (ParameterInfo paramInfo in methodBase.GetParameters()) {
parameters.Add(new ReflectionParameter(paramInfo, this));
}
}
return parameters;
}
set {
throw new NotSupportedException();
}
this.Parameters.Add(new ReflectionParameter(paramInfo, this));
}
public ReflectionMethod(MethodBase methodBase, IClass declaringType)
: base(declaringType, methodBase is ConstructorInfo ? "#ctor" : methodBase.Name)
{
this.methodBase = methodBase;
if (methodBase.IsGenericMethodDefinition) {
foreach (Type g in methodBase.GetGenericArguments()) {
this.TypeParameters.Add(new DefaultTypeParameter(this, g));

21
src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionProperty.cs

@ -15,27 +15,12 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -15,27 +15,12 @@ namespace ICSharpCode.SharpDevelop.Dom
[Serializable]
public class ReflectionProperty : DefaultProperty
{
PropertyInfo propertyInfo;
public override IReturnType ReturnType {
get {
return ReflectionReturnType.Create(this, propertyInfo.PropertyType, false);
}
set {
}
}
public ReflectionProperty(PropertyInfo propertyInfo, IClass declaringType) : base(declaringType, propertyInfo.Name)
{
this.propertyInfo = propertyInfo;
this.ReturnType = ReflectionReturnType.Create(this, propertyInfo.PropertyType, false);
// show the abstract layer that we have getter & setters
if (propertyInfo.CanRead) {
GetterRegion = new DomRegion(0, 0, 0, 0);
}
if (propertyInfo.CanWrite) {
SetterRegion = new DomRegion(0, 0, 0, 0);
}
CanGet = propertyInfo.CanRead;
CanSet = propertyInfo.CanWrite;
ParameterInfo[] parameterInfo = propertyInfo.GetIndexParameters();
if (parameterInfo != null && parameterInfo.Length > 0) {

39
src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionReturnType.cs

@ -61,15 +61,6 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -61,15 +61,6 @@ namespace ICSharpCode.SharpDevelop.Dom
return type;
}
}
/// <summary>Gets a ReturnType describing System.Void.</summary>
public static IReturnType Void {
get {
if (@void == null) {
@void = CreatePrimitive(typeof(void));
}
return @void;
}
}
/// <summary>Gets a ReturnType describing System.Array.</summary>
public static IReturnType Array {
get {
@ -107,6 +98,36 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -107,6 +98,36 @@ namespace ICSharpCode.SharpDevelop.Dom
return @delegate;
}
}
/// <summary>Gets a ReturnType describing System.Void.</summary>
public static IReturnType Void {
get {
if (@void == null) {
@void = new VoidReturnType();
}
return @void;
}
}
private class VoidReturnType : AbstractReturnType
{
public VoidReturnType() {
FullyQualifiedName = typeof(void).FullName;
}
public override IClass GetUnderlyingClass() {
return ProjectContentRegistry.Mscorlib.GetClass(FullyQualifiedName);
}
public override List<IMethod> GetMethods() {
return new List<IMethod>(1);
}
public override List<IProperty> GetProperties() {
return new List<IProperty>(1);
}
public override List<IField> GetFields() {
return new List<IField>(1);
}
public override List<IEvent> GetEvents() {
return new List<IEvent>(1);
}
}
/// <summary>
/// Create a primitive return type.

27
src/Main/Base/Project/Src/Services/ParserService/ParserService.cs

@ -42,7 +42,7 @@ namespace ICSharpCode.Core @@ -42,7 +42,7 @@ namespace ICSharpCode.Core
if (forcedContent != null) return forcedContent;
if (ProjectService.CurrentProject == null || !projectContents.ContainsKey(ProjectService.CurrentProject)) {
return defaultProjectContent;
return DefaultProjectContent;
}
return projectContents[ProjectService.CurrentProject];
}
@ -185,15 +185,9 @@ namespace ICSharpCode.Core @@ -185,15 +185,9 @@ namespace ICSharpCode.Core
LoggingService.Info("ParserUpdateThread started");
// preload mscorlib, we're going to need it anyway
IProjectContent dummyVar = ProjectContentRegistry.Mscorlib;
int counter = 0;
while (!abortParserUpdateThread) {
try {
if (++counter == 10) {
ReflectionClass.ClearMemberCache();
counter = 0;
}
ParserUpdateStep();
} catch (Exception e) {
ICSharpCode.Core.MessageService.ShowError(e);
@ -308,7 +302,22 @@ namespace ICSharpCode.Core @@ -308,7 +302,22 @@ namespace ICSharpCode.Core
return null;
}
static IProjectContent defaultProjectContent = new DefaultProjectContent();
static IProjectContent defaultProjectContent;
public static IProjectContent DefaultProjectContent {
get {
if (defaultProjectContent == null) {
lock (projectContents) {
if (defaultProjectContent == null) {
defaultProjectContent = new DefaultProjectContent();
defaultProjectContent.ReferencedContents.Add(ProjectContentRegistry.Mscorlib);
defaultProjectContent.ReferencedContents.Add(ProjectContentRegistry.WinForms);
}
}
}
return defaultProjectContent;
}
}
public static ParseInformation ParseFile(string fileName, string fileContent, bool updateCommentTags, bool fireUpdate)
{
@ -340,7 +349,7 @@ namespace ICSharpCode.Core @@ -340,7 +349,7 @@ namespace ICSharpCode.Core
// we accept the project content as optional parameter.
fileProjectContent = GetProjectContent(fileName);
if (fileProjectContent == null) {
fileProjectContent = defaultProjectContent;
fileProjectContent = DefaultProjectContent;
}
}

194
src/Main/Base/Project/Src/Services/ParserService/ProjectContentRegistry.cs

@ -26,20 +26,32 @@ namespace ICSharpCode.Core @@ -26,20 +26,32 @@ namespace ICSharpCode.Core
public static class ProjectContentRegistry
{
static Dictionary<string, IProjectContent> contents = new Dictionary<string, IProjectContent>(StringComparer.InvariantCultureIgnoreCase);
static IProjectContent mscorlibContent;
static ReflectionProjectContent mscorlibContent;
public static IProjectContent Mscorlib {
get {
if (mscorlibContent != null) return mscorlibContent;
lock (contents) {
if (contents.ContainsKey("mscorlib")) {
mscorlibContent = contents["mscorlib"];
mscorlibContent = (ReflectionProjectContent)contents["mscorlib"];
return contents["mscorlib"];
}
int time = LoggingService.IsDebugEnabled ? Environment.TickCount : 0;
LoggingService.Debug("Loading PC for mscorlib...");
mscorlibContent = DomPersistence.LoadProjectContentByAssemblyName(typeof(object).Assembly.FullName);
if (mscorlibContent == null) {
mscorlibContent = new ReflectionProjectContent(typeof(object).Assembly);
if (time != 0) {
LoggingService.Debug("Loaded mscorlib with reflection in " + (Environment.TickCount - time) + " ms");
}
DomPersistence.SaveProjectContent(mscorlibContent);
LoggingService.Debug("Saved mscorlib to cache");
} else {
if (time != 0) {
LoggingService.Debug("Loaded mscorlib from cache in " + (Environment.TickCount - time) + " ms");
}
}
contents["mscorlib"] = mscorlibContent;
LoggingService.Debug("Finished loading mscorlib");
return mscorlibContent;
}
}
@ -69,8 +81,6 @@ namespace ICSharpCode.Core @@ -69,8 +81,6 @@ namespace ICSharpCode.Core
}
}
static string lookupDirectory;
public static IProjectContent GetProjectContentForReference(ReferenceProjectItem item)
{
if (item is ProjectReferenceProjectItem) {
@ -101,69 +111,64 @@ namespace ICSharpCode.Core @@ -101,69 +111,64 @@ namespace ICSharpCode.Core
StatusBarService.ProgressMonitor.BeginTask("Loading " + shortName + "...", 100);
#if DEBUG
int time = Environment.TickCount;
string how = "??";
#endif
try {
Assembly assembly = GetDefaultAssembly(shortName);
ReflectionProjectContent pc;
if (assembly != null) {
contents[item.Include] = new ReflectionProjectContent(assembly);
#if DEBUG
how = "typeof";
#endif
return contents[itemInclude];
}
lookupDirectory = Path.GetDirectoryName(itemFileName);
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += AssemblyResolve;
try {
try {
if (File.Exists(itemFileName)) {
assembly = LoadReflectionOnlyAssemblyFrom(itemFileName);
if (assembly != null) {
contents[itemFileName] = new ReflectionProjectContent(assembly, itemFileName);
contents[assembly.FullName] = contents[itemFileName];
#if DEBUG
how = "ReflectionOnly";
#endif
return contents[itemFileName];
pc = DomPersistence.LoadProjectContentByAssemblyName(assembly.FullName);
if (pc == null) {
pc = new ReflectionProjectContent(assembly);
DomPersistence.SaveProjectContent(pc);
}
} else {
pc = LoadProjectContent(itemFileName, itemInclude);
}
} catch (FileNotFoundException) {
// ignore and try loading with LoadGACAssembly
if (pc != null) {
contents[item.Include] = pc;
contents[shortName] = pc;
contents[pc.AssemblyFullName] = pc;
}
try {
assembly = LoadGACAssembly(itemInclude, true);
if (assembly != null) {
contents[itemInclude] = new ReflectionProjectContent(assembly);
contents[assembly.FullName] = contents[itemInclude];
return pc;
} finally {
#if DEBUG
how = "PartialName";
LoggingService.DebugFormatted("Loaded {0} in {1}ms", itemInclude, Environment.TickCount - time);
#endif
return contents[itemInclude];
StatusBarService.ProgressMonitor.Done();
}
} catch (Exception e) {
LoggingService.Warn("Can't load assembly '" + itemInclude + "' : " + e.Message);
}
} catch (BadImageFormatException) {
LoggingService.Warn("BadImageFormat: " + itemInclude);
} finally {
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve -= AssemblyResolve;
lookupDirectory = null;
}
static ReflectionProjectContent LoadProjectContent(string filename, string include)
{
ReflectionProjectContent pc = DomPersistence.LoadProjectContentByAssemblyName(filename);
if (pc != null) {
return pc;
}
pc = DomPersistence.LoadProjectContentByAssemblyName(include);
if (pc != null) {
return pc;
}
AppDomainSetup setup = new AppDomainSetup();
setup.DisallowCodeDownload = true;
setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
AppDomain domain = AppDomain.CreateDomain("AssemblyLoadingDomain", AppDomain.CurrentDomain.Evidence, setup);
string database;
try {
object o = domain.CreateInstanceAndUnwrap(typeof(ReflectionLoader).Assembly.FullName, typeof(ReflectionLoader).FullName);
ReflectionLoader loader = (ReflectionLoader)o;
database = loader.LoadAndCreateDatabase(filename, include);
} finally {
#if DEBUG
LoggingService.DebugFormatted("Loaded {0} with {2} in {1}ms", itemInclude, Environment.TickCount - time, how);
#endif
StatusBarService.ProgressMonitor.Done();
}
return null;
AppDomain.Unload(domain);
}
LoggingService.Debug("AppDomain finished, loading cache...");
return DomPersistence.LoadProjectContent(database);
}
static Assembly GetDefaultAssembly(string shortName)
{
// GAC Assemblies take some time because first the non-GAC try
// has to fail.
// Therefore, assemblies already in use by SharpDevelop are used directly.
// These assemblies are already loaded by SharpDevelop, so we don't need to load
// them in a separate AppDomain.
switch (shortName) {
case "System": // System != mscorlib !!!
return typeof(Uri).Assembly;
@ -191,74 +196,19 @@ namespace ICSharpCode.Core @@ -191,74 +196,19 @@ namespace ICSharpCode.Core
}
}
static Assembly AssemblyResolve(object sender, ResolveEventArgs e)
{
AssemblyName name = new AssemblyName(e.Name);
LoggingService.Debug("ProjectContentRegistry.AssemblyResolve " + e.Name);
string path = Path.Combine(lookupDirectory, name.Name);
if (File.Exists(path + ".dll")) {
return LoadReflectionOnlyAssemblyFrom(path + ".dll");
}
if (File.Exists(path + ".exe")) {
return LoadReflectionOnlyAssemblyFrom(path + ".exe");
}
if (File.Exists(path)) {
return LoadReflectionOnlyAssemblyFrom(path);
}
try {
LoggingService.Debug("AssemblyResolve trying ReflectionOnlyLoad");
return Assembly.ReflectionOnlyLoad(e.Name);
} catch (FileNotFoundException) {
LoggingService.Warn("AssemblyResolve: ReflectionOnlyLoad failed for " + e.Name);
// We can't get the assembly we want.
// But propably we can get a similar version of it.
AssemblyName fixedName = FindBestMatchingAssemblyName(e.Name);
LoggingService.Info("AssemblyResolve: FixedName: " + fixedName);
return Assembly.ReflectionOnlyLoad(fixedName.FullName);
}
}
static Dictionary<string, Assembly> loadFromCache;
static Assembly LoadReflectionOnlyAssemblyFrom(string fileName)
{
fileName = Path.GetFullPath(fileName);
if (loadFromCache == null) {
loadFromCache = new Dictionary<string, Assembly>(StringComparer.InvariantCultureIgnoreCase);
}
if (loadFromCache.ContainsKey(fileName)) {
LoggingService.Debug("Use " + fileName + " from cache.");
return loadFromCache[fileName];
}
LoggingService.Debug("Load " + fileName);
Assembly asm = InternalLoadReflectionOnlyAssemblyFrom(fileName);
if (loadFromCache.ContainsKey(asm.FullName)) {
loadFromCache.Add(fileName, loadFromCache[asm.FullName]);
return loadFromCache[asm.FullName];
}
loadFromCache.Add(fileName, asm);
loadFromCache.Add(asm.FullName, asm);
return asm;
}
static Assembly InternalLoadReflectionOnlyAssemblyFrom(string fileName)
public static Assembly LoadGACAssembly(string partialName, bool reflectionOnly)
{
byte[] data;
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read)) {
if (fs.Length > 10 * 1024 * 1024) {
// more than 10 MB? Do not hold bytes in memory
return Assembly.ReflectionOnlyLoadFrom(fileName);
}
data = new byte[fs.Length];
for (int i = 0; i < data.Length;) {
int c = fs.Read(data, i, data.Length - i);
i += c;
if (c <= 0) {
throw new IOException("Read returned " + c);
}
}
if (reflectionOnly) {
AssemblyName name = FindBestMatchingAssemblyName(partialName);
if (name == null)
return null;
return Assembly.ReflectionOnlyLoad(name.FullName);
} else {
#pragma warning disable 618
return Assembly.LoadWithPartialName(partialName);
#pragma warning restore 618
}
return Assembly.ReflectionOnlyLoad(data);
}
public static AssemblyName FindBestMatchingAssemblyName(string name)
@ -326,19 +276,5 @@ namespace ICSharpCode.Core @@ -326,19 +276,5 @@ namespace ICSharpCode.Core
}
return new AssemblyName(best);
}
public static Assembly LoadGACAssembly(string partialName, bool reflectionOnly)
{
if (reflectionOnly) {
AssemblyName name = FindBestMatchingAssemblyName(partialName);
if (name == null)
return null;
return Assembly.ReflectionOnlyLoad(name.FullName);
} else {
#pragma warning disable 618
return Assembly.LoadWithPartialName(partialName);
#pragma warning restore 618
}
}
}
}

78
src/Main/Base/Project/Src/Services/ParserService/ReflectionProjectContent.cs

@ -14,13 +14,40 @@ using System.Diagnostics; @@ -14,13 +14,40 @@ using System.Diagnostics;
using System.Reflection;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.Core;
namespace ICSharpCode.Core
namespace ICSharpCode.SharpDevelop.Dom
{
public class ReflectionProjectContent : DefaultProjectContent
{
Assembly assembly;
string assemblyFullName;
AssemblyName[] referencedAssemblies;
ICompilationUnit assemblyCompilationUnit;
string assemblyLocation;
public string AssemblyLocation {
get {
return assemblyLocation;
}
}
public string AssemblyFullName {
get {
return assemblyFullName;
}
}
public AssemblyName[] ReferencedAssemblies {
get {
return referencedAssemblies;
}
}
public ICompilationUnit AssemblyCompilationUnit {
get {
return assemblyCompilationUnit;
}
}
public ReflectionProjectContent(Assembly assembly)
: this(assembly, assembly.Location)
@ -28,11 +55,8 @@ namespace ICSharpCode.Core @@ -28,11 +55,8 @@ namespace ICSharpCode.Core
}
public ReflectionProjectContent(Assembly assembly, string assemblyLocation)
: this(assembly.FullName, assemblyLocation, assembly.GetReferencedAssemblies())
{
this.assembly = assembly;
ICompilationUnit assemblyCompilationUnit = new DefaultCompilationUnit(this);
try {
foreach (Type type in assembly.GetExportedTypes()) {
string name = type.FullName;
@ -40,21 +64,24 @@ namespace ICSharpCode.Core @@ -40,21 +64,24 @@ namespace ICSharpCode.Core
AddClassToNamespaceListInternal(new ReflectionClass(assemblyCompilationUnit, type, name, null));
}
}
InitializeSpecialClasses();
} catch (Exception ex) {
MessageService.ShowError(ex);
}
if (assembly == typeof(void).Assembly) {
// Replace void through the special class (ReturnType(void).GetMethods() does not return
// the methods of System.Object and System.ValueType)
AddClassToNamespaceListInternal(new ReflectionClass.VoidClass(assemblyCompilationUnit));
}
public ReflectionProjectContent(string assemblyFullName, string assemblyLocation, AssemblyName[] referencedAssemblies)
{
this.assemblyFullName = assemblyFullName;
this.referencedAssemblies = referencedAssemblies;
this.assemblyLocation = assemblyLocation;
this.assemblyCompilationUnit = new DefaultCompilationUnit(this);
string fileName = LookupLocalizedXmlDoc(assemblyLocation);
// Not found -> look in runtime directory.
if (fileName == null) {
string runtimeDirectory = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory();
fileName = LookupLocalizedXmlDoc(Path.Combine(runtimeDirectory, Path.GetFileName(assembly.Location)));
fileName = LookupLocalizedXmlDoc(Path.Combine(runtimeDirectory, Path.GetFileName(assemblyLocation)));
}
if (fileName != null) {
@ -62,6 +89,24 @@ namespace ICSharpCode.Core @@ -62,6 +89,24 @@ namespace ICSharpCode.Core
}
}
public void InitializeSpecialClasses()
{
if (ClassLists[0].ContainsKey(VoidClass.VoidName)) {
AddClassToNamespaceList(new VoidClass(assemblyCompilationUnit));
}
}
private class VoidClass : ReflectionClass
{
internal static readonly string VoidName = typeof(void).FullName;
public VoidClass(ICompilationUnit compilationUnit) : base(compilationUnit, typeof(void), VoidName, null) {}
protected override IReturnType CreateDefaultReturnType() {
return ReflectionReturnType.Void;
}
}
bool initialized = false;
ArrayList missingNames;
@ -76,13 +121,14 @@ namespace ICSharpCode.Core @@ -76,13 +121,14 @@ namespace ICSharpCode.Core
missingNames.RemoveAt(i--);
}
}
if (missingNames.Count == 0)
if (missingNames.Count == 0) {
missingNames = null;
}
}
return;
}
initialized = true;
foreach (AssemblyName name in assembly.GetReferencedAssemblies()) {
foreach (AssemblyName name in referencedAssemblies) {
IProjectContent content = ProjectContentRegistry.GetExistingProjectContent(name);
if (content != null) {
ReferencedContents.Add(content);
@ -96,7 +142,7 @@ namespace ICSharpCode.Core @@ -96,7 +142,7 @@ namespace ICSharpCode.Core
public override string ToString()
{
return string.Format("[{0}: {1}]", GetType().Name, assembly.FullName);
return string.Format("[{0}: {1}]", GetType().Name, assemblyFullName);
}
}
}

Loading…
Cancel
Save