diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
index 3f2c0f2926..fed8fc3592 100644
--- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
+++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
@@ -706,6 +706,8 @@
+
+
diff --git a/src/Main/Base/Project/Src/Dom/IAttribute.cs b/src/Main/Base/Project/Src/Dom/IAttribute.cs
index 6f106b984a..a639a1ffce 100644
--- a/src/Main/Base/Project/Src/Dom/IAttribute.cs
+++ b/src/Main/Base/Project/Src/Dom/IAttribute.cs
@@ -20,6 +20,8 @@ namespace ICSharpCode.SharpDevelop.Dom
get;
}
+ /*
+ * These properties are not stored in DomPersistence and cannot not be used!
List PositionalArguments {
get;
}
@@ -27,6 +29,7 @@ namespace ICSharpCode.SharpDevelop.Dom
SortedList NamedArguments {
get;
}
+ */
}
public enum AttributeTarget
diff --git a/src/Main/Base/Project/Src/Dom/IProperty.cs b/src/Main/Base/Project/Src/Dom/IProperty.cs
index 031bfcfdc1..ab65599c74 100644
--- a/src/Main/Base/Project/Src/Dom/IProperty.cs
+++ b/src/Main/Base/Project/Src/Dom/IProperty.cs
@@ -32,13 +32,5 @@ namespace ICSharpCode.SharpDevelop.Dom
bool IsIndexer {
get;
}
-
- IMethod GetterMethod {
- get;
- }
-
- IMethod SetterMethod {
- get;
- }
}
}
diff --git a/src/Main/Base/Project/Src/Dom/Implementations/ConstructedReturnType.cs b/src/Main/Base/Project/Src/Dom/Implementations/ConstructedReturnType.cs
index 5a92faf24e..412d8887ea 100644
--- a/src/Main/Base/Project/Src/Dom/Implementations/ConstructedReturnType.cs
+++ b/src/Main/Base/Project/Src/Dom/Implementations/ConstructedReturnType.cs
@@ -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 typeParameters;
+ IList typeParameters;
IReturnType baseType;
- public List TypeArguments {
+ public IList TypeArguments {
get {
return typeParameters;
}
}
- public ConstructedReturnType(IReturnType baseType, List typeParameters)
+ public ConstructedReturnType(IReturnType baseType, IList typeParameters)
{
if (baseType == null)
throw new ArgumentNullException("baseType");
diff --git a/src/Main/Base/Project/Src/Dom/Implementations/DefaultAttribute.cs b/src/Main/Base/Project/Src/Dom/Implementations/DefaultAttribute.cs
index fe5d5424b8..c75555f44b 100644
--- a/src/Main/Base/Project/Src/Dom/Implementations/DefaultAttribute.cs
+++ b/src/Main/Base/Project/Src/Dom/Implementations/DefaultAttribute.cs
@@ -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) {
diff --git a/src/Main/Base/Project/Src/Dom/Implementations/DefaultEvent.cs b/src/Main/Base/Project/Src/Dom/Implementations/DefaultEvent.cs
index f3964911ce..8ee33808d6 100644
--- a/src/Main/Base/Project/Src/Dom/Implementations/DefaultEvent.cs
+++ b/src/Main/Base/Project/Src/Dom/Implementations/DefaultEvent.cs
@@ -13,11 +13,10 @@ namespace ICSharpCode.SharpDevelop.Dom
[Serializable]
public class DefaultEvent : AbstractMember, IEvent
{
- protected DomRegion bodyRegion;
- protected EventAttributes eventAttributes;
- protected IMethod addMethod;
- protected IMethod removeMethod;
- protected IMethod raiseMethod;
+ protected DomRegion bodyRegion;
+ protected IMethod addMethod;
+ protected IMethod removeMethod;
+ protected IMethod raiseMethod;
public override string DocumentationTag {
get {
@@ -30,19 +29,13 @@ namespace ICSharpCode.SharpDevelop.Dom
return bodyRegion;
}
}
-
- 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
return raiseMethod;
}
}
-
}
}
diff --git a/src/Main/Base/Project/Src/Dom/Implementations/DefaultProperty.cs b/src/Main/Base/Project/Src/Dom/Implementations/DefaultProperty.cs
index 55d2612c9e..e1f993b0cc 100644
--- a/src/Main/Base/Project/Src/Dom/Implementations/DefaultProperty.cs
+++ b/src/Main/Base/Project/Src/Dom/Implementations/DefaultProperty.cs
@@ -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 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;
- }
- set {
- isIndexer = value;
- }
+ get { return (accessFlags & indexerFlag) == indexerFlag; }
+ set { if (value) accessFlags |= indexerFlag; else accessFlags &= 255-indexerFlag; }
+ }
+
+ 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 {
{
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;
}
@@ -82,30 +88,6 @@ namespace ICSharpCode.SharpDevelop.Dom {
setterRegion = value;
}
}
-
- 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)
{
diff --git a/src/Main/Base/Project/Src/Dom/ReflectionLayer/DomPersistence.cs b/src/Main/Base/Project/Src/Dom/ReflectionLayer/DomPersistence.cs
new file mode 100644
index 0000000000..1e2971479d
--- /dev/null
+++ b/src/Main/Base/Project/Src/Dom/ReflectionLayer/DomPersistence.cs
@@ -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
+{
+ ///
+ /// This class can write Dom entity into a binary file for fast loading.
+ ///
+ 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 cacheIndex;
+
+ static Dictionary CacheIndex {
+ get {
+ if (cacheIndex == null) {
+ cacheIndex = LoadCacheIndex();
+ }
+ return cacheIndex;
+ }
+ }
+
+ static Dictionary LoadCacheIndex()
+ {
+ string indexFile = GetIndexFileName();
+ Dictionary list = new Dictionary(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 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 e in cacheIndex) {
+ writer.Write(e.Key);
+ writer.Write(e.Value);
+ }
+ }
+ }
+ }
+
+ static void AddFileNameToCacheIndex(string cacheFile, ReflectionProjectContent pc)
+ {
+ Dictionary 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 classIndices = new Dictionary(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 classes = pc.Classes;
+
+ classIndices.Clear();
+ int i = 0;
+ foreach (IClass c in classes) {
+ classIndices[c.FullyQualifiedName] = i;
+ i += 1;
+ }
+
+ List externalTypes = new List();
+ 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 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
+ ///
+ /// Finds all return types used in the class collection and adds the unknown ones
+ /// to the externalTypeIndices and externalTypes collections.
+ ///
+ void CreateExternalTypeList(List externalTypes,
+ int classCount, ICollection 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 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 attributes)
+ {
+ writer.Write((ushort)attributes.Count);
+ foreach (IAttribute a in attributes) {
+ WriteString(a.Name);
+ writer.Write((byte)a.AttributeTarget);
+ }
+ }
+
+ void ReadAttributes(IList 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 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 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
+ }
+ }
+}
diff --git a/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionClass.cs b/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionClass.cs
index cce9d7d76d..7e093a6695 100644
--- a/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionClass.cs
+++ b/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionClass.cs
@@ -16,146 +16,54 @@ 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 innerClasses;
-
- public override List InnerClasses {
- get {
- if (innerClasses == null) {
- innerClasses = new List();
- foreach (Type nestedType in type.GetNestedTypes(flags)) {
- string name = nestedType.FullName.Replace('+', '.');
- innerClasses.Add(new ReflectionClass(CompilationUnit, nestedType, name, this));
- }
- }
- return innerClasses;
- }
- }
-
- static Dictionary> fieldCache = new Dictionary>();
- static Dictionary> propertyCache = new Dictionary>();
- static Dictionary> methodCache = new Dictionary>();
- static Dictionary> eventCache = new Dictionary>();
-
- public static void ClearMemberCache()
+ void InitMembers(Type type)
{
- fieldCache.Clear();
- propertyCache.Clear();
- methodCache.Clear();
- eventCache.Clear();
- }
-
- public override List Fields {
- get {
- List fields;
- if (!fieldCache.TryGetValue(this, out fields)) {
- fields = new List();
- 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;
+ foreach (Type nestedType in type.GetNestedTypes(flags)) {
+ if (!nestedType.IsVisible) continue;
+ string name = nestedType.FullName.Replace('+', '.');
+ InnerClasses.Add(new ReflectionClass(CompilationUnit, nestedType, name, this));
}
- }
-
- public override List Properties {
- get {
- List properties;
- if (!propertyCache.TryGetValue(this, out properties)) {
- properties = new List();
- 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);
+
+ foreach (FieldInfo field in type.GetFields(flags)) {
+ if (!field.IsPublic && !field.IsFamily) continue;
+ if (!field.IsSpecialName) {
+ Fields.Add(new ReflectionField(field, this));
}
- return properties;
}
- }
-
- public override List Methods {
- get {
- List methods;
- if (!methodCache.TryGetValue(this, out methods)) {
- methods = new List();
-
- foreach (ConstructorInfo constructorInfo in type.GetConstructors(flags)) {
- if (!constructorInfo.IsPublic && !constructorInfo.IsFamily) continue;
- IMethod newMethod = new ReflectionMethod(constructorInfo, this);
- methods.Add(newMethod);
- }
-
- 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;
+
+ foreach (PropertyInfo propertyInfo in type.GetProperties(flags)) {
+ ReflectionProperty prop = new ReflectionProperty(propertyInfo, this);
+ if (prop.IsPublic || prop.IsProtected)
+ Properties.Add(prop);
}
- }
-
- public override List Events {
- get {
- List events;
- if (!eventCache.TryGetValue(this, out events)) {
- events = new List();
- foreach (EventInfo eventInfo in type.GetEvents(flags)) {
- events.Add(new ReflectionEvent(eventInfo, this));
- }
- eventCache.Add(this, events);
+
+ foreach (ConstructorInfo constructorInfo in type.GetConstructors(flags)) {
+ if (!constructorInfo.IsPublic && !constructorInfo.IsFamily) continue;
+ Methods.Add(new ReflectionMethod(constructorInfo, this));
+ }
+
+ foreach (MethodInfo methodInfo in type.GetMethods(flags)) {
+ if (!methodInfo.IsPublic && !methodInfo.IsFamily) continue;
+ if (!methodInfo.IsSpecialName) {
+ Methods.Add(new ReflectionMethod(methodInfo, this));
}
- return events;
}
- }
-
- public static bool IsDelegate(Type type)
- {
- 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);
+ foreach (EventInfo eventInfo in type.GetEvents(flags)) {
+ Events.Add(new ReflectionEvent(eventInfo, this));
}
}
- private class VoidReturnType : DefaultReturnType
+ public static bool IsDelegate(Type type)
{
- public VoidReturnType(IClass c) : base(c) {}
- public override List GetMethods() {
- return new List(1);
- }
- public override List GetProperties() {
- return new List(1);
- }
- public override List GetFields() {
- return new List(1);
- }
- public override List GetEvents() {
- return new List(1);
- }
+ return type.IsSubclassOf(typeof(Delegate)) && type != typeof(MulticastDelegate);
}
- #endregion
static void AddAttributes(IProjectContent pc, List list, IList attributes)
{
@@ -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
foreach (Type iface in type.GetInterfaces()) {
BaseTypes.Add(ReflectionReturnType.Create(compilationUnit.ProjectContent, iface, false));
}
+
+ InitMembers(type);
}
}
diff --git a/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionEvent.cs b/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionEvent.cs
index dcdfaf665e..6813621ff8 100644
--- a/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionEvent.cs
+++ b/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionEvent.cs
@@ -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;
diff --git a/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionLoader.cs b/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionLoader.cs
new file mode 100644
index 0000000000..68f8dd0304
--- /dev/null
+++ b/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionLoader.cs
@@ -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);
+ }
+ }
+ }
+}
diff --git a/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionMethod.cs b/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionMethod.cs
index 99a9458002..b20714c49b 100644
--- a/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionMethod.cs
+++ b/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionMethod.cs
@@ -17,49 +17,18 @@ 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 {
- if (methodBase is MethodInfo) {
- return ReflectionReturnType.Create(this, ((MethodInfo)methodBase).ReturnType, false);
- } else if (methodBase is ConstructorInfo) {
- return DeclaringType.DefaultReturnType;
- }
- return null;
- }
- set {
- throw new NotSupportedException();
- }
- }
-
- List parameters;
-
- public override List Parameters {
- get {
- if (parameters == null) {
- parameters = new List();
- foreach (ParameterInfo paramInfo in methodBase.GetParameters()) {
- parameters.Add(new ReflectionParameter(paramInfo, this));
- }
- }
- return parameters;
- }
- set {
- throw new NotSupportedException();
- }
- }
-
public ReflectionMethod(MethodBase methodBase, IClass declaringType)
: base(declaringType, methodBase is ConstructorInfo ? "#ctor" : methodBase.Name)
{
- this.methodBase = methodBase;
+ if (methodBase is MethodInfo) {
+ this.ReturnType = ReflectionReturnType.Create(this, ((MethodInfo)methodBase).ReturnType, false);
+ } else if (methodBase is ConstructorInfo) {
+ this.ReturnType = DeclaringType.DefaultReturnType;
+ }
+
+ foreach (ParameterInfo paramInfo in methodBase.GetParameters()) {
+ this.Parameters.Add(new ReflectionParameter(paramInfo, this));
+ }
if (methodBase.IsGenericMethodDefinition) {
foreach (Type g in methodBase.GetGenericArguments()) {
diff --git a/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionProperty.cs b/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionProperty.cs
index 7738418ac1..57c2560ee6 100644
--- a/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionProperty.cs
+++ b/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionProperty.cs
@@ -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) {
diff --git a/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionReturnType.cs b/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionReturnType.cs
index 3b745cfe18..a74273cd25 100644
--- a/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionReturnType.cs
+++ b/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionReturnType.cs
@@ -61,15 +61,6 @@ namespace ICSharpCode.SharpDevelop.Dom
return type;
}
}
- /// Gets a ReturnType describing System.Void.
- public static IReturnType Void {
- get {
- if (@void == null) {
- @void = CreatePrimitive(typeof(void));
- }
- return @void;
- }
- }
/// Gets a ReturnType describing System.Array.
public static IReturnType Array {
get {
@@ -107,6 +98,36 @@ namespace ICSharpCode.SharpDevelop.Dom
return @delegate;
}
}
+ /// Gets a ReturnType describing System.Void.
+ 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 GetMethods() {
+ return new List(1);
+ }
+ public override List GetProperties() {
+ return new List(1);
+ }
+ public override List GetFields() {
+ return new List(1);
+ }
+ public override List GetEvents() {
+ return new List(1);
+ }
+ }
///
/// Create a primitive return type.
diff --git a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs
index 25828a6b62..51eba87c8d 100644
--- a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs
+++ b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs
@@ -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
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
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
// we accept the project content as optional parameter.
fileProjectContent = GetProjectContent(fileName);
if (fileProjectContent == null) {
- fileProjectContent = defaultProjectContent;
+ fileProjectContent = DefaultProjectContent;
}
}
diff --git a/src/Main/Base/Project/Src/Services/ParserService/ProjectContentRegistry.cs b/src/Main/Base/Project/Src/Services/ParserService/ProjectContentRegistry.cs
index 7d525c86b6..acb73103b4 100644
--- a/src/Main/Base/Project/Src/Services/ParserService/ProjectContentRegistry.cs
+++ b/src/Main/Base/Project/Src/Services/ParserService/ProjectContentRegistry.cs
@@ -26,20 +26,32 @@ namespace ICSharpCode.Core
public static class ProjectContentRegistry
{
static Dictionary contents = new Dictionary(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 = new ReflectionProjectContent(typeof(object).Assembly);
+ 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
}
}
- static string lookupDirectory;
-
public static IProjectContent GetProjectContentForReference(ReferenceProjectItem item)
{
if (item is ProjectReferenceProjectItem) {
@@ -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];
- }
- }
- } catch (FileNotFoundException) {
- // ignore and try loading with LoadGACAssembly
- }
- try {
- assembly = LoadGACAssembly(itemInclude, true);
- if (assembly != null) {
- contents[itemInclude] = new ReflectionProjectContent(assembly);
- contents[assembly.FullName] = contents[itemInclude];
- #if DEBUG
- how = "PartialName";
- #endif
- return contents[itemInclude];
- }
- } catch (Exception e) {
- LoggingService.Warn("Can't load assembly '" + itemInclude + "' : " + e.Message);
+ pc = DomPersistence.LoadProjectContentByAssemblyName(assembly.FullName);
+ if (pc == null) {
+ pc = new ReflectionProjectContent(assembly);
+ DomPersistence.SaveProjectContent(pc);
}
- } catch (BadImageFormatException) {
- LoggingService.Warn("BadImageFormat: " + itemInclude);
- } finally {
- AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve -= AssemblyResolve;
- lookupDirectory = null;
+ } else {
+ pc = LoadProjectContent(itemFileName, itemInclude);
+ }
+ if (pc != null) {
+ contents[item.Include] = pc;
+ contents[shortName] = pc;
+ contents[pc.AssemblyFullName] = pc;
}
+ return pc;
} finally {
#if DEBUG
- LoggingService.DebugFormatted("Loaded {0} with {2} in {1}ms", itemInclude, Environment.TickCount - time, how);
+ LoggingService.DebugFormatted("Loaded {0} in {1}ms", itemInclude, Environment.TickCount - time);
#endif
StatusBarService.ProgressMonitor.Done();
}
- return 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 {
+ 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
}
}
- 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 loadFromCache;
-
- static Assembly LoadReflectionOnlyAssemblyFrom(string fileName)
- {
- fileName = Path.GetFullPath(fileName);
- if (loadFromCache == null) {
- loadFromCache = new Dictionary(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
}
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
- }
- }
}
}
diff --git a/src/Main/Base/Project/Src/Services/ParserService/ReflectionProjectContent.cs b/src/Main/Base/Project/Src/Services/ParserService/ReflectionProjectContent.cs
index cc19c89163..e97a38a508 100644
--- a/src/Main/Base/Project/Src/Services/ParserService/ReflectionProjectContent.cs
+++ b/src/Main/Base/Project/Src/Services/ParserService/ReflectionProjectContent.cs
@@ -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,33 +55,33 @@ 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;
- if (name.IndexOf('+') < 0) { // type.IsNested
+ if (name.IndexOf('+') < 0) { // type.IsNested
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
}
}
+ 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
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
public override string ToString()
{
- return string.Format("[{0}: {1}]", GetType().Name, assembly.FullName);
+ return string.Format("[{0}: {1}]", GetType().Name, assemblyFullName);
}
}
}