Browse Source

Add interning support to CecilLoader.

newNRvisualizers
Daniel Grunwald 15 years ago
parent
commit
782887812f
  1. 1
      ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj
  2. 25
      ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs
  3. 122
      ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleInterningProvider.cs

1
ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

@ -221,6 +221,7 @@ @@ -221,6 +221,7 @@
<Compile Include="TypeSystem\Implementation\ProxyTypeResolveContext.cs" />
<Compile Include="TypeSystem\Implementation\DefaultTypeDefinition.cs" />
<Compile Include="TypeSystem\Implementation\SimpleConstantValue.cs" />
<Compile Include="TypeSystem\Implementation\SimpleInterningProvider.cs" />
<Compile Include="TypeSystem\Implementation\SimpleProjectContent.cs" />
<Compile Include="TypeSystem\Implementation\SpecializedEvent.cs" />
<Compile Include="TypeSystem\Implementation\SpecializedField.cs" />

25
ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs

@ -38,6 +38,11 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -38,6 +38,11 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// Gets/Sets the documentation provider that is used to retrive the XML documentation for all members.
/// </summary>
public IDocumentationProvider DocumentationProvider { get; set; }
/// <summary>
/// Gets/Sets the interning provider.
/// </summary>
public IInterningProvider InterningProvider { get; set; }
#endregion
#region Load From AssemblyDefinition
@ -47,12 +52,16 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -47,12 +52,16 @@ namespace ICSharpCode.NRefactory.TypeSystem
throw new ArgumentNullException("assemblyDefinition");
ITypeResolveContext oldEarlyBindContext = this.EarlyBindContext;
try {
List<IAttribute> assemblyAttributes = new List<IAttribute>();
IList<IAttribute> assemblyAttributes = new List<IAttribute>();
foreach (var attr in assemblyDefinition.CustomAttributes) {
assemblyAttributes.Add(ReadAttribute(attr));
}
if (this.InterningProvider != null)
assemblyAttributes = this.InterningProvider.InternList(assemblyAttributes);
else
assemblyAttributes = new ReadOnlyCollection<IAttribute>(assemblyAttributes);
TypeStorage typeStorage = new TypeStorage();
CecilProjectContent pc = new CecilProjectContent(typeStorage, assemblyDefinition.Name.FullName, assemblyAttributes.AsReadOnly(), this.DocumentationProvider);
CecilProjectContent pc = new CecilProjectContent(typeStorage, assemblyDefinition.Name.FullName, assemblyAttributes, this.DocumentationProvider);
this.EarlyBindContext = CompositeTypeResolveContext.Combine(pc, this.EarlyBindContext);
List<CecilTypeDefinition> types = new List<CecilTypeDefinition>();
@ -105,10 +114,10 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -105,10 +114,10 @@ namespace ICSharpCode.NRefactory.TypeSystem
sealed class CecilProjectContent : ProxyTypeResolveContext, IProjectContent, ISynchronizedTypeResolveContext, IDocumentationProvider
{
readonly string assemblyName;
readonly ReadOnlyCollection<IAttribute> assemblyAttributes;
readonly IList<IAttribute> assemblyAttributes;
readonly IDocumentationProvider documentationProvider;
public CecilProjectContent(TypeStorage types, string assemblyName, ReadOnlyCollection<IAttribute> assemblyAttributes, IDocumentationProvider documentationProvider)
public CecilProjectContent(TypeStorage types, string assemblyName, IList<IAttribute> assemblyAttributes, IDocumentationProvider documentationProvider)
: base(types)
{
Debug.Assert(assemblyName != null);
@ -710,6 +719,8 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -710,6 +719,8 @@ namespace ICSharpCode.NRefactory.TypeSystem
}
}
if (this.InterningProvider != null)
m = this.InterningProvider.Intern(m);
return m;
}
@ -830,6 +841,8 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -830,6 +841,8 @@ namespace ICSharpCode.NRefactory.TypeSystem
f.IsVolatile = true;
}
if (this.InterningProvider != null)
f = this.InterningProvider.Intern(f);
return f;
}
@ -897,6 +910,8 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -897,6 +910,8 @@ namespace ICSharpCode.NRefactory.TypeSystem
}
AddAttributes(property, p);
if (this.InterningProvider != null)
p = this.InterningProvider.Intern(p);
return p;
}
@ -936,6 +951,8 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -936,6 +951,8 @@ namespace ICSharpCode.NRefactory.TypeSystem
AddAttributes(ev, e);
if (this.InterningProvider != null)
e = this.InterningProvider.Intern(e);
return e;
}
#endregion

122
ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleInterningProvider.cs

@ -0,0 +1,122 @@ @@ -0,0 +1,122 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.CompilerServices;
using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
/// <summary>
/// Simple interning provider.
/// </summary>
public sealed class SimpleInterningProvider : IInterningProvider
{
sealed class ReferenceComparer : IEqualityComparer<object>
{
public readonly static ReferenceComparer Instance = new ReferenceComparer();
public new bool Equals(object a, object b)
{
return ReferenceEquals(a, b);
}
public int GetHashCode(object obj)
{
return RuntimeHelpers.GetHashCode(obj);
}
}
sealed class InterningComparer : IEqualityComparer<ISupportsInterning>
{
public bool Equals(ISupportsInterning x, ISupportsInterning y)
{
return x.EqualsForInterning(y);
}
public int GetHashCode(ISupportsInterning obj)
{
return obj.GetHashCodeForInterning();
}
}
sealed class ListComparer : IEqualityComparer<IEnumerable<object>>
{
public bool Equals(IEnumerable<object> a, IEnumerable<object> b)
{
if (a.GetType() != b.GetType())
return false;
return Enumerable.SequenceEqual(a, b, ReferenceComparer.Instance);
}
public int GetHashCode(IEnumerable<object> obj)
{
int hashCode = obj.GetType().GetHashCode();
unchecked {
foreach (object o in obj) {
hashCode *= 27;
hashCode += RuntimeHelpers.GetHashCode(o);
}
}
return hashCode;
}
}
Dictionary<object, object> byValueDict = new Dictionary<object, object>();
Dictionary<ISupportsInterning, ISupportsInterning> supportsInternDict = new Dictionary<ISupportsInterning, ISupportsInterning>(new InterningComparer());
Dictionary<IEnumerable<object>, IEnumerable<object>> listDict = new Dictionary<IEnumerable<object>, IEnumerable<object>>(new ListComparer());
public T Intern<T>(T obj) where T : class
{
if (obj == null)
return null;
ISupportsInterning s = obj as ISupportsInterning;
if (s != null) {
ISupportsInterning output;
if (supportsInternDict.TryGetValue(s, out output)) {
obj = (T)output;
} else {
s.PrepareForInterning(this);
if (supportsInternDict.TryGetValue(s, out output))
obj = (T)output;
else
supportsInternDict.Add(s, s);
}
} else if (obj is IType || Type.GetTypeCode(obj.GetType()) >= TypeCode.Boolean) {
object output;
if (byValueDict.TryGetValue(obj, out output))
obj = (T)output;
else
byValueDict.Add(obj, obj);
}
return obj;
}
public IList<T> InternList<T>(IList<T> list) where T : class
{
if (list == null)
return null;
for (int i = 0; i < list.Count; i++) {
T oldItem = list[i];
T newItem = Intern(oldItem);
if (oldItem != newItem) {
if (list.IsReadOnly)
list = new T[list.Count];
list[i] = newItem;
}
}
if (!list.IsReadOnly)
list = new ReadOnlyCollection<T>(list);
IEnumerable<object> output;
if (listDict.TryGetValue(list, out output))
list = (IList<T>)output;
else
listDict.Add(list, list);
return list;
}
}
}
Loading…
Cancel
Save