diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs index 96a2899ca0..a5869b5a27 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs @@ -51,4 +51,19 @@ namespace ICSharpCode.NRefactory.CSharp.Parser return testCasePC; } } + + [TestFixture] + public class SerializedTypeSystemConvertVisitorTests : TypeSystemTests + { + [TestFixtureSetUp] + public void FixtureSetUp() + { + FastSerializer serializer = new FastSerializer(); + using (MemoryStream ms = new MemoryStream()) { + serializer.Serialize(ms, TypeSystemConvertVisitorTests.ParseTestCase()); + ms.Position = 0; + testCasePC = (IProjectContent)serializer.Deserialize(ms); + } + } + } } diff --git a/ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs b/ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs index b009dde7df..12902b4afa 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs +++ b/ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs @@ -27,6 +27,7 @@ namespace ICSharpCode.NRefactory.CSharp /// /// Represents a file that was parsed and converted for the type system. /// + [Serializable] public sealed class ParsedFile : AbstractFreezable, IParsedFile { readonly string fileName; diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/AliasNamespaceReference.cs b/ICSharpCode.NRefactory/CSharp/Resolver/AliasNamespaceReference.cs index 603e47c9e8..6777d8da34 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/AliasNamespaceReference.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/AliasNamespaceReference.cs @@ -28,6 +28,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// The member lookup performed by the :: operator is handled /// by . /// + [Serializable] public class AliasNamespaceReference : ITypeOrNamespaceReference { readonly UsingScope parentUsingScope; diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/CSharpAttribute.cs b/ICSharpCode.NRefactory/CSharp/Resolver/CSharpAttribute.cs index 143cdd3b5d..c3b47e51fc 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/CSharpAttribute.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/CSharpAttribute.cs @@ -24,6 +24,7 @@ using ICSharpCode.NRefactory.TypeSystem.Implementation; namespace ICSharpCode.NRefactory.CSharp.Resolver { + [Serializable] public sealed class CSharpAttribute : Immutable, IAttribute { ITypeReference attributeType; @@ -128,6 +129,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// Type reference used within an attribute. /// Looks up both 'withoutSuffix' and 'withSuffix' and returns the type that exists. /// + [Serializable] public sealed class AttributeTypeReference : ITypeReference, ISupportsInterning { ITypeReference withoutSuffix, withSuffix; diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs b/ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs index 701384519b..d163e8ad53 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs @@ -29,6 +29,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues // Contains representations for constant C# expressions. // We use these instead of storing the full AST to reduce the memory usage. + [Serializable] public sealed class CSharpConstantValue : Immutable, IConstantValue, ISupportsInterning { ConstantExpression expression; @@ -125,6 +126,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues /// /// Increments an integer by a fixed amount without changing the type. /// + [Serializable] public sealed class IncrementConstantValue : Immutable, IConstantValue, ISupportsInterning { IConstantValue baseValue; @@ -178,6 +180,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public abstract class ConstantExpression { public abstract ResolveResult Resolve(CSharpResolver resolver); @@ -186,6 +189,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues /// /// C#'s equivalent to the SimpleConstantValue. /// + [Serializable] public sealed class PrimitiveConstantExpression : ConstantExpression, ISupportsInterning { ITypeReference type; @@ -233,6 +237,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public sealed class ConstantCast : ConstantExpression, ISupportsInterning { ITypeReference targetType; @@ -274,6 +279,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public sealed class ConstantIdentifierReference : ConstantExpression, ISupportsInterning { string identifier; @@ -327,6 +333,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public sealed class ConstantMemberReference : ConstantExpression, ISupportsInterning { ITypeReference targetType; @@ -398,6 +405,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public sealed class ConstantCheckedExpression : ConstantExpression, ISupportsInterning { bool checkForOverflow; @@ -441,6 +449,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public sealed class ConstantDefaultValue : ConstantExpression, ISupportsInterning { ITypeReference type; @@ -474,6 +483,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public sealed class ConstantUnaryOperator : ConstantExpression, ISupportsInterning { UnaryOperatorType operatorType; @@ -513,6 +523,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public sealed class ConstantBinaryOperator : ConstantExpression, ISupportsInterning { ConstantExpression left; @@ -559,6 +570,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public sealed class ConstantConditionalOperator : ConstantExpression, ISupportsInterning { ConstantExpression condition, trueExpr, falseExpr; @@ -614,6 +626,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues /// /// Represents an array creation (as used within an attribute argument) /// + [Serializable] public sealed class ConstantArrayCreation : ConstantExpression, ISupportsInterning { // type may be null when the element is being inferred diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs b/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs index ac1828efed..5ad2ea39e1 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs @@ -25,6 +25,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// /// Reference to a qualified type or namespace name. /// + [Serializable] public sealed class MemberTypeOrNamespaceReference : ITypeOrNamespaceReference { readonly ITypeOrNamespaceReference target; diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs b/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs index e770931df0..631a1fbd5d 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs @@ -25,6 +25,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// /// Represents a simple C# name. (a single non-qualified identifier with an optional list of type arguments) /// + [Serializable] public sealed class SimpleTypeOrNamespaceReference : ITypeOrNamespaceReference { readonly ITypeDefinition parentTypeDefinition; diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/UsingScope.cs b/ICSharpCode.NRefactory/CSharp/Resolver/UsingScope.cs index fa6212b5e0..7a933459d0 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/UsingScope.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/UsingScope.cs @@ -28,6 +28,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// Represents a scope that contains "using" statements. /// This is either the file itself, or a namespace declaration. /// + [Serializable] public class UsingScope : AbstractFreezable { readonly IProjectContent projectContent; diff --git a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs index 0bdb727d61..bee93e7689 100644 --- a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs +++ b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs @@ -23,6 +23,7 @@ using System.Diagnostics; using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Serialization; using System.Threading; using ICSharpCode.NRefactory.TypeSystem.Implementation; using Mono.Cecil; @@ -234,6 +235,33 @@ namespace ICSharpCode.NRefactory.TypeSystem else return null; } + + IEnumerable IAnnotatable.Annotations { + get { return EmptyList.Instance; } + } + + T IAnnotatable.Annotation() + { + return null; + } + + object IAnnotatable.Annotation(Type type) + { + return null; + } + + void IAnnotatable.AddAnnotation(object annotation) + { + throw new NotSupportedException(); + } + + void IAnnotatable.RemoveAnnotations() + { + } + + void IAnnotatable.RemoveAnnotations(Type type) + { + } } #endregion diff --git a/ICSharpCode.NRefactory/TypeSystem/Error.cs b/ICSharpCode.NRefactory/TypeSystem/Error.cs index 1684e8d81c..7487f12fc5 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Error.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Error.cs @@ -1,4 +1,4 @@ -// +// // Error.cs // // Author: @@ -42,22 +42,27 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Descibes an error during parsing. /// + [Serializable] public class Error { + readonly ErrorType errorType; + readonly string message; + readonly DomRegion region; + /// /// The type of the error. /// - public ErrorType ErrorType { get; private set; } + public ErrorType ErrorType { get { return errorType; } } /// /// The error description. /// - public string Message { get; private set; } + public string Message { get { return message; } } /// /// The region of the error. /// - public DomRegion Region { get; private set; } + public DomRegion Region { get { return region; } } /// /// Initializes a new instance of the class. @@ -73,9 +78,9 @@ namespace ICSharpCode.NRefactory.TypeSystem /// public Error (ErrorType errorType, string message, DomRegion region) { - this.ErrorType = errorType; - this.Message = message; - this.Region = region; + this.errorType = errorType; + this.message = message; + this.region = region; } /// @@ -92,9 +97,9 @@ namespace ICSharpCode.NRefactory.TypeSystem /// public Error (ErrorType errorType, string message, AstLocation location) { - this.ErrorType = errorType; - this.Message = message; - this.Region = new DomRegion (location, location); + this.errorType = errorType; + this.message = message; + this.region = new DomRegion (location, location); } /// @@ -127,9 +132,9 @@ namespace ICSharpCode.NRefactory.TypeSystem /// public Error (ErrorType errorType, string message) { - this.ErrorType = errorType; - this.Message = message; - this.Region = DomRegion.Empty; + this.errorType = errorType; + this.message = message; + this.region = DomRegion.Empty; } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/IAnnotatable.cs b/ICSharpCode.NRefactory/TypeSystem/IAnnotatable.cs index ff30f87443..2021496969 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IAnnotatable.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IAnnotatable.cs @@ -78,7 +78,6 @@ namespace ICSharpCode.NRefactory void RemoveAnnotations(Type type); } - [Serializable] public abstract class AbstractAnnotatable : IAnnotatable { // Annotations: points either null (no annotations), to the single annotation, diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs index 898c98077b..e9612d1f8c 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs @@ -26,7 +26,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// Useful as base class for decorators. /// [Serializable] - public class ProxyTypeResolveContext : AbstractAnnotatable, ITypeResolveContext + public class ProxyTypeResolveContext : ITypeResolveContext { protected readonly ITypeResolveContext target; diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs index e288260245..c00daf635d 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs @@ -20,8 +20,8 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; +using System.Runtime.Serialization; using System.Threading; - using ICSharpCode.NRefactory.Utils; namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -34,12 +34,22 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// Compared with , this class adds support for the IProjectContent interface, /// for partial classes, and for multi-threading. /// - public class SimpleProjectContent : AbstractAnnotatable, IProjectContent + [Serializable] + public class SimpleProjectContent : AbstractAnnotatable, IProjectContent, ISerializable, IDeserializationCallback { readonly TypeStorage types = new TypeStorage(); readonly ReaderWriterLockSlim readerWriterLock = new ReaderWriterLockSlim(); readonly Dictionary fileDict = new Dictionary(Platform.FileNameComparer); + #region Constructor + /// + /// Creates a new SimpleProjectContent instance. + /// + public SimpleProjectContent() + { + } + #endregion + #region AssemblyAttributes readonly List assemblyAttributes = new List(); // mutable assembly attribute storage readonly List moduleAttributes = new List(); @@ -284,5 +294,46 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } #endregion + + #region Serialization + SerializationInfo serializationInfo; + + protected SimpleProjectContent(SerializationInfo info, StreamingContext context) + { + this.serializationInfo = info; + assemblyAttributes.AddRange((IAttribute[])info.GetValue("AssemblyAttributes", typeof(IAttribute[]))); + readOnlyAssemblyAttributes = assemblyAttributes.ToArray(); + moduleAttributes.AddRange((IAttribute[])info.GetValue("ModuleAttributes", typeof(IAttribute[]))); + readOnlyModuleAttributes = moduleAttributes.ToArray(); + } + + public virtual void OnDeserialization(object sender) + { + // We need to do this in OnDeserialization because at the time the deserialization + // constructor runs, type.FullName/file.FileName may not be deserialized yet. + if (serializationInfo != null) { + foreach (var typeDef in (ITypeDefinition[])serializationInfo.GetValue("Types", typeof(ITypeDefinition[]))) { + types.UpdateType(typeDef); + } + foreach (IParsedFile file in (IParsedFile[])serializationInfo.GetValue("Files", typeof(IParsedFile[]))) { + fileDict.Add(file.FileName, file); + } + serializationInfo = null; + } + } + + public virtual void GetObjectData(SerializationInfo info, StreamingContext context) + { + readerWriterLock.EnterReadLock(); + try { + info.AddValue("Types", types.GetTypes().ToArray()); + info.AddValue("AssemblyAttributes", readOnlyAssemblyAttributes); + info.AddValue("ModuleAttributes", readOnlyModuleAttributes); + info.AddValue("Files", fileDict.Values.ToArray()); + } finally { + readerWriterLock.ExitReadLock(); + } + } + #endregion } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs index 53eb718cef..93d8d46dfe 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs @@ -374,7 +374,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation SerializationInfo serializationInfo; - protected TypeStorage(SerializationInfo info, StreamingContext context) + private TypeStorage(SerializationInfo info, StreamingContext context) { this.serializationInfo = info; } @@ -391,6 +391,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation foreach (var typeDef in (ITypeDefinition[])serializationInfo.GetValue("Types", typeof(ITypeDefinition[]))) { UpdateType(typeDef); } + serializationInfo = null; } #endregion }