From 59c9e99921133a3321ac487b4d60e33b0844fc06 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Thu, 23 Feb 2012 17:11:44 +0100 Subject: [PATCH] DefaultResolvedTypeDefinition: lazily initialize the list of members. This makes creating a DefaultResolvedTypeDefinition much cheaper, so we no longer need to use Lazy in CSharpAssembly. --- .../TypeSystem/CSharpAssembly.cs | 30 +- .../DefaultResolvedTypeDefinition.cs | 277 +++++++++++++----- ICSharpCode.NRefactory/Utils/ProjectedList.cs | 114 ------- 3 files changed, 221 insertions(+), 200 deletions(-) diff --git a/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAssembly.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAssembly.cs index 2f78951b4e..7b0d37bd13 100644 --- a/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAssembly.cs +++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAssembly.cs @@ -179,9 +179,9 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem return fullAssemblyName.Substring(0, pos); } - Dictionary> typeDict; + Dictionary typeDict; - Dictionary> GetTypes() + Dictionary GetTypes() { var dict = this.typeDict; if (dict != null) { @@ -199,26 +199,24 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem } } - Lazy CreateResolvedTypeDefinition(IUnresolvedTypeDefinition[] parts) + ITypeDefinition CreateResolvedTypeDefinition(IUnresolvedTypeDefinition[] parts) { - return new Lazy( - () => new DefaultResolvedTypeDefinition(context, parts), - LazyThreadSafetyMode.PublicationOnly); + return new DefaultResolvedTypeDefinition(context, parts); } public ITypeDefinition GetTypeDefinition(string ns, string name, int typeParameterCount) { var key = new FullNameAndTypeParameterCount(ns ?? string.Empty, name, typeParameterCount); - Lazy def; + ITypeDefinition def; if (GetTypes().TryGetValue(key, out def)) - return def.Value; + return def; else return null; } public IEnumerable TopLevelTypeDefinitions { get { - return GetTypes().Values.Select(t => t.Value); + return GetTypes().Values; } } @@ -234,7 +232,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem readonly string fullName; readonly string name; internal readonly List childNamespaces = new List(); - internal readonly Dictionary> types; + internal readonly Dictionary types; public NS(CSharpAssembly assembly) { @@ -244,7 +242,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem // Our main dictionary for the CSharpAssembly is using an ordinal comparer. // If the compilation's comparer isn't ordinal, we need to create a new dictionary with the compilation's comparer. if (assembly.compilation.NameComparer != StringComparer.Ordinal) { - this.types = new Dictionary>(new FullNameAndTypeParameterCountComparer(assembly.compilation.NameComparer)); + this.types = new Dictionary(new FullNameAndTypeParameterCountComparer(assembly.compilation.NameComparer)); } } @@ -255,7 +253,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem this.fullName = fullName; this.name = name; if (parentNamespace.types != null) - this.types = new Dictionary>(parentNamespace.types.Comparer); + this.types = new Dictionary(parentNamespace.types.Comparer); } string INamespace.ExternAlias { @@ -281,12 +279,12 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem IEnumerable INamespace.Types { get { if (types != null) - return types.Values.Select(t => t.Value); + return types.Values; else return ( from t in assembly.GetTypes() where t.Key.Namespace == fullName - select t.Value.Value + select t.Value ); } } @@ -309,9 +307,9 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem { if (types != null) { var key = new FullNameAndTypeParameterCount(fullName, name, typeParameterCount); - Lazy typeDef; + ITypeDefinition typeDef; if (types.TryGetValue(key, out typeDef)) - return typeDef.Value; + return typeDef; else return null; } else { diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs index 930e8c0730..b99ea8ac9a 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs @@ -33,8 +33,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation readonly ITypeResolveContext parentContext; readonly IUnresolvedTypeDefinition[] parts; Accessibility accessibility = Accessibility.Internal; - List unresolvedMembers = new List(); - ProjectedListWithContextPerElement resolvedMembers; bool isAbstract, isSealed, isShadowing; bool isSynthetic = true; // true if all parts are synthetic @@ -46,68 +44,70 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation throw new ArgumentException("No parts were specified", "parts"); this.parentContext = parentContext; this.parts = parts; - ITypeResolveContext contextForTypeParameters = parts[0].CreateResolveContext(parentContext); - contextForTypeParameters = contextForTypeParameters.WithCurrentTypeDefinition(this); - if (parentContext.CurrentTypeDefinition == null || parentContext.CurrentTypeDefinition.TypeParameterCount == 0) { - this.TypeParameters = parts[0].TypeParameters.CreateResolvedTypeParameters(contextForTypeParameters); - } else { - // This is a nested class inside a generic class; copy type parameters from outer class if we can: - var outerClass = parentContext.CurrentTypeDefinition; - ITypeParameter[] typeParameters = new ITypeParameter[parts[0].TypeParameters.Count]; - for (int i = 0; i < typeParameters.Length; i++) { - var unresolvedTP = parts[0].TypeParameters[i]; - if (i < outerClass.TypeParameterCount && outerClass.TypeParameters[i].Name == unresolvedTP.Name) - typeParameters[i] = outerClass.TypeParameters[i]; - else - typeParameters[i] = unresolvedTP.CreateResolvedTypeParameter(contextForTypeParameters); - } - this.TypeParameters = Array.AsReadOnly(typeParameters); - } - List unresolvedAttributes = new List(); - List contextPerAttribute = new List(); - List contextPerMember = new List(); - bool addDefaultConstructorIfRequired = false; + foreach (IUnresolvedTypeDefinition part in parts) { - ITypeResolveContext parentContextForPart = part.CreateResolveContext(parentContext); - ITypeResolveContext contextForPart = parentContextForPart.WithCurrentTypeDefinition(this); - foreach (var attr in part.Attributes) { - unresolvedAttributes.Add(attr); - contextPerAttribute.Add(parentContextForPart); - } - foreach (var member in part.Members) { - unresolvedMembers.Add(member); - contextPerMember.Add(contextForPart); - } - isAbstract |= part.IsAbstract; isSealed |= part.IsSealed; isShadowing |= part.IsShadowing; isSynthetic &= part.IsSynthetic; // true if all parts are synthetic - DefaultUnresolvedTypeDefinition dutd = part as DefaultUnresolvedTypeDefinition; - if (dutd != null) { - addDefaultConstructorIfRequired |= dutd.AddDefaultConstructorIfRequired; - } - // internal is the default, so use another part's accessibility until we find a non-internal accessibility if (accessibility == Accessibility.Internal) accessibility = part.Accessibility; } - if (addDefaultConstructorIfRequired) { - TypeKind kind = this.Kind; - if (kind == TypeKind.Class && !this.IsStatic && !unresolvedMembers.Any(m => m.EntityType == EntityType.Constructor && !m.IsStatic) - || kind == TypeKind.Enum || kind == TypeKind.Struct) - { - contextPerMember.Add(parts[0].CreateResolveContext(parentContext).WithCurrentTypeDefinition(this)); - unresolvedMembers.Add(DefaultUnresolvedMethod.CreateDefaultConstructor(parts[0])); + } + + IList typeParameters; + + public IList TypeParameters { + get { + var result = this.typeParameters; + if (result != null) { + LazyInit.ReadBarrier(); + return result; + } + ITypeResolveContext contextForTypeParameters = parts[0].CreateResolveContext(parentContext); + contextForTypeParameters = contextForTypeParameters.WithCurrentTypeDefinition(this); + if (parentContext.CurrentTypeDefinition == null || parentContext.CurrentTypeDefinition.TypeParameterCount == 0) { + result = parts[0].TypeParameters.CreateResolvedTypeParameters(contextForTypeParameters); + } else { + // This is a nested class inside a generic class; copy type parameters from outer class if we can: + var outerClass = parentContext.CurrentTypeDefinition; + ITypeParameter[] typeParameters = new ITypeParameter[parts[0].TypeParameters.Count]; + for (int i = 0; i < typeParameters.Length; i++) { + var unresolvedTP = parts[0].TypeParameters[i]; + if (i < outerClass.TypeParameterCount && outerClass.TypeParameters[i].Name == unresolvedTP.Name) + typeParameters[i] = outerClass.TypeParameters[i]; + else + typeParameters[i] = unresolvedTP.CreateResolvedTypeParameter(contextForTypeParameters); + } + result = Array.AsReadOnly(typeParameters); } + return LazyInit.GetOrSet(ref this.typeParameters, result); } - this.Attributes = new ProjectedListWithContextPerElement(contextPerAttribute, unresolvedAttributes, (c, a) => a.CreateResolvedAttribute(c)); - this.resolvedMembers = new ProjectedListWithContextPerElement(contextPerMember, unresolvedMembers, (c, m) => m.CreateResolved(c)); } - public IList TypeParameters { get; private set; } - public IList Attributes { get; private set; } + IList attributes; + + public IList Attributes { + get { + var result = this.attributes; + if (result != null) { + LazyInit.ReadBarrier(); + return result; + } + result = new List(); + foreach (IUnresolvedTypeDefinition part in parts) { + ITypeResolveContext parentContextForPart = part.CreateResolveContext(parentContext); + foreach (var attr in part.Attributes) { + result.Add(attr.CreateResolvedAttribute(parentContextForPart)); + } + } + if (result.Count == 0) + result = EmptyList.Instance; + return LazyInit.GetOrSet(ref this.attributes, result); + } + } public IList Parts { get { return parts; } @@ -121,6 +121,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation get { return parts[0].Kind; } } + #region NestedTypes IList nestedTypes; public IList NestedTypes { @@ -140,37 +141,170 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } } + #endregion #region Members + sealed class MemberList : IList + { + internal readonly ITypeResolveContext[] contextPerMember; + internal readonly IUnresolvedMember[] unresolvedMembers; + internal readonly IMember[] resolvedMembers; + + public MemberList(ITypeResolveContext[] contextPerMember, IUnresolvedMember[] unresolvedMembers) + { + this.contextPerMember = contextPerMember; + this.unresolvedMembers = unresolvedMembers; + this.resolvedMembers = new IMember[unresolvedMembers.Length]; + } + + public IMember this[int index] { + get { + IMember output = resolvedMembers[index]; + if (output != null) { + LazyInit.ReadBarrier(); + return output; + } + return LazyInit.GetOrSet(ref resolvedMembers[index], unresolvedMembers[index].CreateResolved(contextPerMember[index])); + } + set { throw new NotSupportedException(); } + } + + public int Count { + get { return unresolvedMembers.Length; } + } + + bool ICollection.IsReadOnly { + get { return true; } + } + + public int IndexOf(IMember item) + { + for (int i = 0; i < this.Count; i++) { + if (this[i].Equals(item)) + return i; + } + return -1; + } + + void IList.Insert(int index, IMember item) + { + throw new NotSupportedException(); + } + + void IList.RemoveAt(int index) + { + throw new NotSupportedException(); + } + + void ICollection.Add(IMember item) + { + throw new NotSupportedException(); + } + + void ICollection.Clear() + { + throw new NotSupportedException(); + } + + bool ICollection.Contains(IMember item) + { + return IndexOf(item) >= 0; + } + + void ICollection.CopyTo(IMember[] array, int arrayIndex) + { + for (int i = 0; i < this.Count; i++) { + array[arrayIndex + i] = this[i]; + } + } + + bool ICollection.Remove(IMember item) + { + throw new NotSupportedException(); + } + + public IEnumerator GetEnumerator() + { + for (int i = 0; i < this.Count; i++) { + yield return this[i]; + } + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } + + MemberList memberList; + + MemberList GetMemberList() + { + var result = this.memberList; + if (result != null) { + LazyInit.ReadBarrier(); + return result; + } + List unresolvedMembers = new List(); + List contextPerMember = new List(); + bool addDefaultConstructorIfRequired = false; + foreach (IUnresolvedTypeDefinition part in parts) { + ITypeResolveContext parentContextForPart = part.CreateResolveContext(parentContext); + ITypeResolveContext contextForPart = parentContextForPart.WithCurrentTypeDefinition(this); + foreach (var member in part.Members) { + unresolvedMembers.Add(member); + contextPerMember.Add(contextForPart); + } + + DefaultUnresolvedTypeDefinition dutd = part as DefaultUnresolvedTypeDefinition; + if (dutd != null) { + addDefaultConstructorIfRequired |= dutd.AddDefaultConstructorIfRequired; + } + } + if (addDefaultConstructorIfRequired) { + TypeKind kind = this.Kind; + if (kind == TypeKind.Class && !this.IsStatic && !unresolvedMembers.Any(m => m.EntityType == EntityType.Constructor && !m.IsStatic) + || kind == TypeKind.Enum || kind == TypeKind.Struct) + { + contextPerMember.Add(parts[0].CreateResolveContext(parentContext).WithCurrentTypeDefinition(this)); + unresolvedMembers.Add(DefaultUnresolvedMethod.CreateDefaultConstructor(parts[0])); + } + } + return LazyInit.GetOrSet(ref this.memberList, new MemberList(contextPerMember.ToArray(), unresolvedMembers.ToArray())); + } + public IList Members { - get { return resolvedMembers; } + get { return GetMemberList(); } } public IEnumerable Fields { get { - for (int i = 0; i < unresolvedMembers.Count; i++) { - if (unresolvedMembers[i].EntityType == EntityType.Field) - yield return (IField)resolvedMembers[i]; + var members = GetMemberList(); + for (int i = 0; i < members.Count; i++) { + if (members.unresolvedMembers[i].EntityType == EntityType.Field) + yield return (IField)members[i]; } } } public IEnumerable Methods { get { - for (int i = 0; i < unresolvedMembers.Count; i++) { - if (unresolvedMembers[i] is IUnresolvedMethod) - yield return (IMethod)resolvedMembers[i]; + var members = GetMemberList(); + for (int i = 0; i < members.Count; i++) { + if (members.unresolvedMembers[i] is IUnresolvedMethod) + yield return (IMethod)members[i]; } } } public IEnumerable Properties { get { - for (int i = 0; i < unresolvedMembers.Count; i++) { - switch (unresolvedMembers[i].EntityType) { + var members = GetMemberList(); + for (int i = 0; i < members.Count; i++) { + switch (members.unresolvedMembers[i].EntityType) { case EntityType.Property: case EntityType.Indexer: - yield return (IProperty)resolvedMembers[i]; + yield return (IProperty)members[i]; break; } } @@ -179,9 +313,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public IEnumerable Events { get { - for (int i = 0; i < unresolvedMembers.Count; i++) { - if (unresolvedMembers[i].EntityType == EntityType.Event) - yield return (IEvent)resolvedMembers[i]; + var members = GetMemberList(); + for (int i = 0; i < members.Count; i++) { + if (members.unresolvedMembers[i].EntityType == EntityType.Event) + yield return (IEvent)members[i]; } } } @@ -289,7 +424,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } public int TypeParameterCount { - get { return this.TypeParameters.Count; } + get { return parts[0].TypeParameters.Count; } } #region DirectBaseTypes @@ -504,19 +639,21 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation #region GetMembers() IEnumerable GetFilteredMembers(Predicate filter) { - for (int i = 0; i < unresolvedMembers.Count; i++) { - if (filter == null || filter(unresolvedMembers[i])) { - yield return resolvedMembers[i]; + var members = GetMemberList(); + for (int i = 0; i < members.Count; i++) { + if (filter == null || filter(members.unresolvedMembers[i])) { + yield return members[i]; } } } IEnumerable GetFilteredMembers(Predicate filter) where TUnresolved : class, IUnresolvedMember where TResolved : class, IMember { - for (int i = 0; i < unresolvedMembers.Count; i++) { - TUnresolved unresolved = unresolvedMembers[i] as TUnresolved; + var members = GetMemberList(); + for (int i = 0; i < members.Count; i++) { + TUnresolved unresolved = members.unresolvedMembers[i] as TUnresolved; if (unresolved != null && (filter == null || filter(unresolved))) { - yield return (TResolved)resolvedMembers[i]; + yield return (TResolved)members[i]; } } } diff --git a/ICSharpCode.NRefactory/Utils/ProjectedList.cs b/ICSharpCode.NRefactory/Utils/ProjectedList.cs index beacd3d155..7b907217b1 100644 --- a/ICSharpCode.NRefactory/Utils/ProjectedList.cs +++ b/ICSharpCode.NRefactory/Utils/ProjectedList.cs @@ -238,118 +238,4 @@ namespace ICSharpCode.NRefactory.Utils return GetEnumerator(); } } - - public sealed class ProjectedListWithContextPerElement : IList where TOutput : class - { - readonly IList input; - readonly IList context; - readonly Func projection; - readonly TOutput[] items; - - public ProjectedListWithContextPerElement(IList context, IList input, Func projection) - { - if (context == null) - throw new ArgumentNullException("context"); - if (input == null) - throw new ArgumentNullException("input"); - if (projection == null) - throw new ArgumentNullException("projection"); - if (context.Count != input.Count) - throw new ArgumentException("context list must have same length as input list"); - this.input = input; - this.context = context; - this.projection = projection; - this.items = new TOutput[input.Count]; - } - - public TOutput this[int index] { - get { - TOutput output = items[index]; - if (output != null) { - LazyInit.ReadBarrier(); - return output; - } - return LazyInit.GetOrSet(ref items[index], projection(context[index], input[index])); - } - } - - TOutput IList.this[int index] { - get { return this[index]; } - set { - throw new NotSupportedException(); - } - } - - public int Count { - get { return items.Length; } - } - - bool ICollection.IsReadOnly { - get { return true; } - } - - int IList.IndexOf(TOutput item) - { - var comparer = EqualityComparer.Default; - for (int i = 0; i < this.Count; i++) { - if (comparer.Equals(this[i], item)) - return i; - } - return -1; - } - - void IList.Insert(int index, TOutput item) - { - throw new NotSupportedException(); - } - - void IList.RemoveAt(int index) - { - throw new NotSupportedException(); - } - - void ICollection.Add(TOutput item) - { - throw new NotSupportedException(); - } - - void ICollection.Clear() - { - throw new NotSupportedException(); - } - - bool ICollection.Contains(TOutput item) - { - var comparer = EqualityComparer.Default; - for (int i = 0; i < this.Count; i++) { - if (comparer.Equals(this[i], item)) - return true; - } - return false; - } - - void ICollection.CopyTo(TOutput[] array, int arrayIndex) - { - for (int i = 0; i < items.Length; i++) { - array[arrayIndex + i] = this[i]; - } - } - - bool ICollection.Remove(TOutput item) - { - throw new NotSupportedException(); - } - - public IEnumerator GetEnumerator() - { - for (int i = 0; i < this.Count; i++) { - yield return this[i]; - } - } - - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - } }