diff --git a/ICSharpCode.NRefactory.CSharp/Ast/AstType.cs b/ICSharpCode.NRefactory.CSharp/Ast/AstType.cs index 022f3cc072..cf58d1cd3f 100644 --- a/ICSharpCode.NRefactory.CSharp/Ast/AstType.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/AstType.cs @@ -58,7 +58,7 @@ namespace ICSharpCode.NRefactory.CSharp return other == null || other.IsNull; } - public override ITypeReference ToTypeReference(NameLookupMode lookupMode) + public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider) { return SpecialType.UnknownType; } @@ -99,7 +99,7 @@ namespace ICSharpCode.NRefactory.CSharp return visitor.VisitPatternPlaceholder (this, child, data); } - public override ITypeReference ToTypeReference(NameLookupMode lookupMode) + public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider) { throw new NotSupportedException(); } @@ -135,7 +135,7 @@ namespace ICSharpCode.NRefactory.CSharp /// For resolving simple names, the current namespace and usings from the CurrentUsingScope /// (on CSharpTypeResolveContext only) is used. /// - public abstract ITypeReference ToTypeReference(NameLookupMode lookupMode = NameLookupMode.Type); + public abstract ITypeReference ToTypeReference(NameLookupMode lookupMode = NameLookupMode.Type, InterningProvider interningProvider = null); /// /// Creates a pointer type from this type by nesting it in a . diff --git a/ICSharpCode.NRefactory.CSharp/Ast/ComposedType.cs b/ICSharpCode.NRefactory.CSharp/Ast/ComposedType.cs index 0103937a69..ebbd64951d 100644 --- a/ICSharpCode.NRefactory.CSharp/Ast/ComposedType.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/ComposedType.cs @@ -78,7 +78,7 @@ namespace ICSharpCode.NRefactory.CSharp { visitor.VisitComposedType (this); } - + public override T AcceptVisitor (IAstVisitor visitor) { return visitor.VisitComposedType (this); @@ -126,18 +126,20 @@ namespace ICSharpCode.NRefactory.CSharp return this; } - public override ITypeReference ToTypeReference(NameLookupMode lookupMode = NameLookupMode.Type) + public override ITypeReference ToTypeReference(NameLookupMode lookupMode = NameLookupMode.Type, InterningProvider interningProvider = null) { - ITypeReference t = this.BaseType.ToTypeReference(lookupMode); + if (interningProvider == null) + interningProvider = InterningProvider.Dummy; + ITypeReference t = this.BaseType.ToTypeReference(lookupMode, interningProvider); if (this.HasNullableSpecifier) { - t = NullableType.Create(t); + t = interningProvider.Intern(NullableType.Create(t)); } int pointerRank = this.PointerRank; for (int i = 0; i < pointerRank; i++) { - t = new PointerTypeReference(t); + t = interningProvider.Intern(new PointerTypeReference(t)); } foreach (var a in this.ArraySpecifiers.Reverse()) { - t = new ArrayTypeReference(t, a.Dimensions); + t = interningProvider.Intern(new ArrayTypeReference(t, a.Dimensions)); } return t; } @@ -190,7 +192,7 @@ namespace ICSharpCode.NRefactory.CSharp { visitor.VisitArraySpecifier (this); } - + public override T AcceptVisitor (IAstVisitor visitor) { return visitor.VisitArraySpecifier (this); diff --git a/ICSharpCode.NRefactory.CSharp/Ast/MemberType.cs b/ICSharpCode.NRefactory.CSharp/Ast/MemberType.cs index 76efbc7a81..a3ff86af1b 100644 --- a/ICSharpCode.NRefactory.CSharp/Ast/MemberType.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/MemberType.cs @@ -135,26 +135,30 @@ namespace ICSharpCode.NRefactory.CSharp return b.ToString(); } - public override ITypeReference ToTypeReference(NameLookupMode lookupMode = NameLookupMode.Type) + public override ITypeReference ToTypeReference(NameLookupMode lookupMode = NameLookupMode.Type, InterningProvider interningProvider = null) { + if (interningProvider == null) + interningProvider = InterningProvider.Dummy; + TypeOrNamespaceReference t; if (this.IsDoubleColon) { SimpleType st = this.Target as SimpleType; if (st != null) { - t = new AliasNamespaceReference(st.Identifier); + t = interningProvider.Intern(new AliasNamespaceReference(interningProvider.Intern(st.Identifier))); } else { t = null; } } else { - t = this.Target.ToTypeReference(lookupMode) as TypeOrNamespaceReference; + t = this.Target.ToTypeReference(lookupMode, interningProvider) as TypeOrNamespaceReference; } if (t == null) return SpecialType.UnknownType; var typeArguments = new List(); foreach (var ta in this.TypeArguments) { - typeArguments.Add(ta.ToTypeReference(lookupMode)); + typeArguments.Add(ta.ToTypeReference(lookupMode, interningProvider)); } - return new MemberTypeOrNamespaceReference(t, this.MemberName, typeArguments, lookupMode); + string memberName = interningProvider.Intern(this.MemberName); + return interningProvider.Intern(new MemberTypeOrNamespaceReference(t, memberName, interningProvider.InternList(typeArguments), lookupMode)); } } } diff --git a/ICSharpCode.NRefactory.CSharp/Ast/PrimitiveType.cs b/ICSharpCode.NRefactory.CSharp/Ast/PrimitiveType.cs index 9d8a575be8..87df2983f8 100644 --- a/ICSharpCode.NRefactory.CSharp/Ast/PrimitiveType.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/PrimitiveType.cs @@ -103,7 +103,7 @@ namespace ICSharpCode.NRefactory.CSharp return Keyword; } - public override ITypeReference ToTypeReference(NameLookupMode lookupMode = NameLookupMode.Type) + public override ITypeReference ToTypeReference(NameLookupMode lookupMode = NameLookupMode.Type, InterningProvider interningProvider = null) { KnownTypeCode typeCode = GetTypeCodeForPrimitiveType(this.Keyword); if (typeCode == KnownTypeCode.None) diff --git a/ICSharpCode.NRefactory.CSharp/Ast/SimpleType.cs b/ICSharpCode.NRefactory.CSharp/Ast/SimpleType.cs index 79b4e0f9c0..e34437b74f 100644 --- a/ICSharpCode.NRefactory.CSharp/Ast/SimpleType.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/SimpleType.cs @@ -50,7 +50,7 @@ namespace ICSharpCode.NRefactory.CSharp public override void AcceptVisitor (IAstVisitor visitor) { } - + public override T AcceptVisitor (IAstVisitor visitor) { return default (T); @@ -66,7 +66,7 @@ namespace ICSharpCode.NRefactory.CSharp return other == null || other.IsNull; } - public override ITypeReference ToTypeReference(NameLookupMode lookupMode) + public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider) { return SpecialType.UnknownType; } @@ -130,7 +130,7 @@ namespace ICSharpCode.NRefactory.CSharp { visitor.VisitSimpleType (this); } - + public override T AcceptVisitor (IAstVisitor visitor) { return visitor.VisitSimpleType (this); @@ -158,17 +158,21 @@ namespace ICSharpCode.NRefactory.CSharp return b.ToString(); } - public override ITypeReference ToTypeReference(NameLookupMode lookupMode = NameLookupMode.Type) + public override ITypeReference ToTypeReference(NameLookupMode lookupMode = NameLookupMode.Type, InterningProvider interningProvider = null) { + if (interningProvider == null) + interningProvider = InterningProvider.Dummy; var typeArguments = new List(); foreach (var ta in this.TypeArguments) { - typeArguments.Add(ta.ToTypeReference(lookupMode)); + typeArguments.Add(ta.ToTypeReference(lookupMode, interningProvider)); } - if (typeArguments.Count == 0 && string.IsNullOrEmpty(this.Identifier)) { + string identifier = interningProvider.Intern(this.Identifier); + if (typeArguments.Count == 0 && string.IsNullOrEmpty(identifier)) { // empty SimpleType is used for typeof(List<>). return SpecialType.UnboundTypeArgument; } - return new SimpleTypeOrNamespaceReference(this.Identifier, typeArguments, lookupMode); + var t = new SimpleTypeOrNamespaceReference(identifier, interningProvider.InternList(typeArguments), lookupMode); + return interningProvider.Intern(t); } } } diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs index 428a17eb83..78bca9521e 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs @@ -285,16 +285,18 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring /// Adds type arguments to the result type. /// /// The result AST node (a SimpleType or MemberType) + /// The type definition that owns the type parameters /// The list of type arguments /// Index of first type argument to add /// Index after last type argument to add void AddTypeArguments(AstType result, ITypeDefinition typeDef, IList typeArguments, int startIndex, int endIndex) { + Debug.Assert(endIndex <= typeDef.TypeParameterCount); for (int i = startIndex; i < endIndex; i++) { if (ConvertUnboundTypeArguments && typeArguments[i].Kind == TypeKind.UnboundTypeArgument) { - result.AddChild(new SimpleType(typeDef.TypeParameters [i].Name), Roles.TypeArgument); + result.AddChild(new SimpleType(typeDef.TypeParameters[i].Name), Roles.TypeArgument); } else { - result.AddChild(ConvertType(typeArguments [i]), Roles.TypeArgument); + result.AddChild(ConvertType(typeArguments[i]), Roles.TypeArgument); } } } diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs index d88109fa21..890eb07bbc 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs @@ -797,7 +797,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } else { // Re-discover the method: EntityType entityType = memberDeclaration.EntityType; - var parameterTypes = TypeSystemConvertVisitor.GetParameterTypes(memberDeclaration.GetChildrenByRole(Roles.Parameter)); + var parameterTypes = TypeSystemConvertVisitor.GetParameterTypes(memberDeclaration.GetChildrenByRole(Roles.Parameter), InterningProvider.Dummy); if (entityType == EntityType.Constructor) { string name = memberDeclaration.HasModifier(Modifiers.Static) ? ".cctor" : ".ctor"; member = AbstractUnresolvedMember.Resolve( @@ -860,7 +860,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } else { // Re-discover the property: string name = propertyOrIndexerDeclaration.Name; - var parameterTypeReferences = TypeSystemConvertVisitor.GetParameterTypes(propertyOrIndexerDeclaration.GetChildrenByRole(Roles.Parameter)); + var parameterTypeReferences = TypeSystemConvertVisitor.GetParameterTypes(propertyOrIndexerDeclaration.GetChildrenByRole(Roles.Parameter), InterningProvider.Dummy); AstType explicitInterfaceAstType = propertyOrIndexerDeclaration.GetChildByRole(EntityDeclaration.PrivateImplementationTypeRole); ITypeReference explicitInterfaceType = null; if (!explicitInterfaceAstType.IsNull) { diff --git a/ICSharpCode.NRefactory.CSharp/TypeSystem/AliasNamespaceReference.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/AliasNamespaceReference.cs index a6baf0189d..d214103436 100644 --- a/ICSharpCode.NRefactory.CSharp/TypeSystem/AliasNamespaceReference.cs +++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/AliasNamespaceReference.cs @@ -31,7 +31,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem /// by . /// [Serializable] - public class AliasNamespaceReference : TypeOrNamespaceReference + public sealed class AliasNamespaceReference : TypeOrNamespaceReference, ISupportsInterning { readonly string identifier; @@ -55,5 +55,16 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem { return identifier + "::"; } + + int ISupportsInterning.GetHashCodeForInterning() + { + return identifier.GetHashCode(); + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + AliasNamespaceReference anr = other as AliasNamespaceReference; + return anr != null && this.identifier == anr.identifier; + } } } diff --git a/ICSharpCode.NRefactory.CSharp/TypeSystem/AttributeTypeReference.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/AttributeTypeReference.cs index 854a9c979e..62b3f4626d 100644 --- a/ICSharpCode.NRefactory.CSharp/TypeSystem/AttributeTypeReference.cs +++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/AttributeTypeReference.cs @@ -35,7 +35,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem [Serializable] public sealed class AttributeTypeReference : ITypeReference, ISupportsInterning { - ITypeReference withoutSuffix, withSuffix; + readonly ITypeReference withoutSuffix, withSuffix; public AttributeTypeReference(ITypeReference withoutSuffix, ITypeReference withSuffix) { @@ -75,12 +75,6 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem return withoutSuffix.ToString() + "[Attribute]"; } - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - withoutSuffix = provider.Intern(withoutSuffix); - withSuffix = provider.Intern(withSuffix); - } - int ISupportsInterning.GetHashCodeForInterning() { unchecked { diff --git a/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAttribute.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAttribute.cs index 0b2960e4fb..2d5c5119e0 100644 --- a/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAttribute.cs +++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAttribute.cs @@ -51,7 +51,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem this.namedCtorArguments = namedCtorArguments ?? EmptyList>.Instance; this.namedArguments = namedArguments ?? EmptyList>.Instance; } - public DomRegion Region { + + public DomRegion Region { get { return region; } } @@ -165,93 +166,4 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem } } } - - /* - public IMethod ResolveConstructor(ITypeResolveContext context) - { - CSharpResolver r = new CSharpResolver(context); - IType type = attributeType.Resolve(context); - int totalArgumentCount = 0; - if (positionalArguments != null) - totalArgumentCount += positionalArguments.Count; - if (namedCtorArguments != null) - totalArgumentCount += namedCtorArguments.Count; - ResolveResult[] arguments = new ResolveResult[totalArgumentCount]; - string[] argumentNames = new string[totalArgumentCount]; - int i = 0; - if (positionalArguments != null) { - while (i < positionalArguments.Count) { - IConstantValue cv = positionalArguments[i]; - arguments[i] = cv.Resolve(context); - i++; - } - } - if (namedCtorArguments != null) { - foreach (var pair in namedCtorArguments) { - argumentNames[i] = pair.Key; - arguments[i] = pair.Value.Resolve(context); - i++; - } - } - MemberResolveResult mrr = r.ResolveObjectCreation(type, arguments, argumentNames) as MemberResolveResult; - return mrr != null ? mrr.Member as IMethod : null; - } - - public IList GetPositionalArguments(ITypeResolveContext context) - { - List result = new List(); - if (positionalArguments != null) { - foreach (var arg in positionalArguments) { - result.Add(Resolve(arg, context)); - } - } - if (namedCtorArguments == null || namedCtorArguments.Count == 0) { - // no namedCtorArguments: just return the positionalArguments - return result.AsReadOnly(); - } - // we do have namedCtorArguments, which need to be re-ordered and appended to the positional arguments - IMethod method = ResolveConstructor(context); - if (method != null) { - for (int i = result.Count; i < method.Parameters.Count; i++) { - IParameter p = method.Parameters[i]; - bool found = false; - foreach (var pair in namedCtorArguments) { - if (pair.Key == p.Name) { - result.Add(Resolve(pair.Value, context)); - found = true; - } - } - if (!found) { - // add the parameter's default value: - if (p.DefaultValue != null) { - result.Add(Resolve(p.DefaultValue, context)); - } else { - IType type = p.Type.Resolve(context); - result.Add(new ConstantResolveResult(type, CSharpResolver.GetDefaultValue(type))); - } - } - } - } - return result.AsReadOnly(); - } - - ResolveResult Resolve(IConstantValue constantValue, ITypeResolveContext context) - { - if (constantValue != null) - return constantValue.Resolve(context); - else - return new ErrorResolveResult(SpecialType.UnknownType); - } - - public IList> GetNamedArguments(ITypeResolveContext context) - { - if (namedArguments != null) { - return namedArguments.Select(p => new KeyValuePair(p.Key, p.Value.Resolve(context))) - .ToList().AsReadOnly(); - } else { - return EmptyList>.Instance; - } - } - } - */ } \ No newline at end of file diff --git a/ICSharpCode.NRefactory.CSharp/TypeSystem/ConstantValues.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/ConstantValues.cs index 66cff254ab..56333627ee 100644 --- a/ICSharpCode.NRefactory.CSharp/TypeSystem/ConstantValues.cs +++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/ConstantValues.cs @@ -128,8 +128,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues [Serializable] public sealed class IncrementConstantValue : IConstantValue, ISupportsInterning { - IConstantValue baseValue; - int incrementAmount; + readonly IConstantValue baseValue; + readonly int incrementAmount; public IncrementConstantValue(IConstantValue baseValue, int incrementAmount = 1) { @@ -160,11 +160,6 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues return new ErrorResolveResult(rr.Type); } - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - baseValue = provider.Intern(baseValue); - } - int ISupportsInterning.GetHashCodeForInterning() { unchecked { @@ -185,8 +180,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues [Serializable] public sealed class PrimitiveConstantExpression : ConstantExpression, ISupportsInterning { - ITypeReference type; - object value; + readonly ITypeReference type; + readonly object value; public ITypeReference Type { get { return type; } @@ -209,12 +204,6 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues return new ConstantResolveResult(type.Resolve(resolver.CurrentTypeResolveContext), value); } - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - type = provider.Intern(type); - value = provider.Intern(value); - } - int ISupportsInterning.GetHashCodeForInterning() { return type.GetHashCode() ^ (value != null ? value.GetHashCode() : 0); @@ -228,9 +217,9 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues } [Serializable] - public sealed class TypeOfConstantExpression : ConstantExpression, ISupportsInterning + public sealed class TypeOfConstantExpression : ConstantExpression { - ITypeReference type; + readonly ITypeReference type; public ITypeReference Type { get { return type; } @@ -245,29 +234,13 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues { return resolver.ResolveTypeOf(type.Resolve(resolver.CurrentTypeResolveContext)); } - - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - type = provider.Intern(type); - } - - int ISupportsInterning.GetHashCodeForInterning() - { - return type.GetHashCode(); - } - - bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) - { - TypeOfConstantExpression o = other as TypeOfConstantExpression; - return o != null && type == o.type; - } } [Serializable] public sealed class ConstantCast : ConstantExpression, ISupportsInterning { - ITypeReference targetType; - ConstantExpression expression; + readonly ITypeReference targetType; + readonly ConstantExpression expression; public ConstantCast(ITypeReference targetType, ConstantExpression expression) { @@ -284,12 +257,6 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues return resolver.ResolveCast(targetType.Resolve(resolver.CurrentTypeResolveContext), expression.Resolve(resolver)); } - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - targetType = provider.Intern(targetType); - expression = provider.Intern(expression); - } - int ISupportsInterning.GetHashCodeForInterning() { unchecked { @@ -306,10 +273,10 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues } [Serializable] - public sealed class ConstantIdentifierReference : ConstantExpression, ISupportsInterning + public sealed class ConstantIdentifierReference : ConstantExpression { - string identifier; - IList typeArguments; + readonly string identifier; + readonly IList typeArguments; public ConstantIdentifierReference(string identifier, IList typeArguments = null) { @@ -323,35 +290,15 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues { return resolver.ResolveSimpleName(identifier, typeArguments.Resolve(resolver.CurrentTypeResolveContext)); } - - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - identifier = provider.Intern(identifier); - typeArguments = provider.InternList(typeArguments); - } - - int ISupportsInterning.GetHashCodeForInterning() - { - unchecked { - return identifier.GetHashCode() ^ typeArguments.GetHashCode(); - } - } - - bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) - { - ConstantIdentifierReference cir = other as ConstantIdentifierReference; - return cir != null && - this.identifier == cir.identifier && this.typeArguments == cir.typeArguments; - } } [Serializable] - public sealed class ConstantMemberReference : ConstantExpression, ISupportsInterning + public sealed class ConstantMemberReference : ConstantExpression { - ITypeReference targetType; - ConstantExpression targetExpression; - string memberName; - IList typeArguments; + readonly ITypeReference targetType; + readonly ConstantExpression targetExpression; + readonly string memberName; + readonly IList typeArguments; public ConstantMemberReference(ITypeReference targetType, string memberName, IList typeArguments = null) { @@ -384,43 +331,13 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues rr = targetExpression.Resolve(resolver); return resolver.ResolveMemberAccess(rr, memberName, typeArguments.Resolve(resolver.CurrentTypeResolveContext)); } - - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - targetType = provider.Intern(targetType); - targetExpression = provider.Intern(targetExpression); - memberName = provider.Intern(memberName); - typeArguments = provider.InternList(typeArguments); - } - - int ISupportsInterning.GetHashCodeForInterning() - { - unchecked { - int hashCode; - if (targetType != null) - hashCode = targetType.GetHashCode(); - else - hashCode = targetExpression.GetHashCode(); - hashCode ^= memberName.GetHashCode(); - hashCode ^= typeArguments.GetHashCode(); - return hashCode; - } - } - - bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) - { - ConstantMemberReference cmr = other as ConstantMemberReference; - return cmr != null - && this.targetType == cmr.targetType && this.targetExpression == cmr.targetExpression - && this.memberName == cmr.memberName && this.typeArguments == cmr.typeArguments; - } } [Serializable] - public sealed class ConstantCheckedExpression : ConstantExpression, ISupportsInterning + public sealed class ConstantCheckedExpression : ConstantExpression { - bool checkForOverflow; - ConstantExpression expression; + readonly bool checkForOverflow; + readonly ConstantExpression expression; public ConstantCheckedExpression(bool checkForOverflow, ConstantExpression expression) { @@ -434,30 +351,12 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues { return expression.Resolve(resolver.WithCheckForOverflow(checkForOverflow)); } - - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - expression = provider.Intern(expression); - } - - int ISupportsInterning.GetHashCodeForInterning() - { - return expression.GetHashCode() ^ (checkForOverflow ? 161851612 : 75163517); - } - - bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) - { - ConstantCheckedExpression cce = other as ConstantCheckedExpression; - return cce != null - && this.expression == cce.expression - && this.checkForOverflow == cce.checkForOverflow; - } } [Serializable] public sealed class ConstantDefaultValue : ConstantExpression, ISupportsInterning { - ITypeReference type; + readonly ITypeReference type; public ConstantDefaultValue(ITypeReference type) { @@ -471,11 +370,6 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues return resolver.ResolveDefaultValue(type.Resolve(resolver.CurrentTypeResolveContext)); } - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - type = provider.Intern(type); - } - int ISupportsInterning.GetHashCodeForInterning() { return type.GetHashCode(); @@ -489,10 +383,10 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues } [Serializable] - public sealed class ConstantUnaryOperator : ConstantExpression, ISupportsInterning + public sealed class ConstantUnaryOperator : ConstantExpression { - UnaryOperatorType operatorType; - ConstantExpression expression; + readonly UnaryOperatorType operatorType; + readonly ConstantExpression expression; public ConstantUnaryOperator(UnaryOperatorType operatorType, ConstantExpression expression) { @@ -506,34 +400,14 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues { return resolver.ResolveUnaryOperator(operatorType, expression.Resolve(resolver)); } - - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - expression = provider.Intern(expression); - } - - int ISupportsInterning.GetHashCodeForInterning() - { - unchecked { - return expression.GetHashCode() * 811 + operatorType.GetHashCode(); - } - } - - bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) - { - ConstantUnaryOperator uop = other as ConstantUnaryOperator; - return uop != null - && this.operatorType == uop.operatorType - && this.expression == uop.expression; - } } [Serializable] - public sealed class ConstantBinaryOperator : ConstantExpression, ISupportsInterning + public sealed class ConstantBinaryOperator : ConstantExpression { - ConstantExpression left; - BinaryOperatorType operatorType; - ConstantExpression right; + readonly ConstantExpression left; + readonly BinaryOperatorType operatorType; + readonly ConstantExpression right; public ConstantBinaryOperator(ConstantExpression left, BinaryOperatorType operatorType, ConstantExpression right) { @@ -552,33 +426,12 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues ResolveResult rhs = right.Resolve(resolver); return resolver.ResolveBinaryOperator(operatorType, lhs, rhs); } - - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - left = provider.Intern(left); - right = provider.Intern(right); - } - - int ISupportsInterning.GetHashCodeForInterning() - { - unchecked { - return left.GetHashCode() * 811 + operatorType.GetHashCode() + right.GetHashCode() * 91781; - } - } - - bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) - { - ConstantBinaryOperator bop = other as ConstantBinaryOperator; - return bop != null - && this.operatorType == bop.operatorType - && this.left == bop.left && this.right == bop.right; - } } [Serializable] - public sealed class ConstantConditionalOperator : ConstantExpression, ISupportsInterning + public sealed class ConstantConditionalOperator : ConstantExpression { - ConstantExpression condition, trueExpr, falseExpr; + readonly ConstantExpression condition, trueExpr, falseExpr; public ConstantConditionalOperator(ConstantExpression condition, ConstantExpression trueExpr, ConstantExpression falseExpr) { @@ -601,42 +454,17 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues falseExpr.Resolve(resolver) ); } - - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - condition = provider.Intern(condition); - trueExpr = provider.Intern(trueExpr); - falseExpr = provider.Intern(falseExpr); - } - - int ISupportsInterning.GetHashCodeForInterning() - { - unchecked { - return condition.GetHashCode() * 182981713 - + trueExpr.GetHashCode() * 917517169 - + falseExpr.GetHashCode() * 611651; - } - } - - bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) - { - ConstantConditionalOperator coo = other as ConstantConditionalOperator; - return coo != null - && this.condition == coo.condition - && this.trueExpr == coo.trueExpr - && this.falseExpr == coo.falseExpr; - } } /// /// Represents an array creation (as used within an attribute argument) /// [Serializable] - public sealed class ConstantArrayCreation : ConstantExpression, ISupportsInterning + public sealed class ConstantArrayCreation : ConstantExpression { // type may be null when the element is being inferred - ITypeReference elementType; - IList arrayElements; + readonly ITypeReference elementType; + readonly IList arrayElements; public ConstantArrayCreation(ITypeReference type, IList arrayElements) { @@ -658,22 +486,5 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues return resolver.ResolveArrayCreation(null, 1, null, elements); } } - - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - elementType = provider.Intern(elementType); - arrayElements = provider.InternList(arrayElements); - } - - int ISupportsInterning.GetHashCodeForInterning() - { - return (elementType != null ? elementType.GetHashCode() : 0) ^ arrayElements.GetHashCode(); - } - - bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) - { - ConstantArrayCreation cac = other as ConstantArrayCreation; - return cac != null && this.elementType == cac.elementType && this.arrayElements == cac.arrayElements; - } } } diff --git a/ICSharpCode.NRefactory.CSharp/TypeSystem/MemberTypeOrNamespaceReference.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/MemberTypeOrNamespaceReference.cs index 19ecf27ff8..6956472c59 100644 --- a/ICSharpCode.NRefactory.CSharp/TypeSystem/MemberTypeOrNamespaceReference.cs +++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/MemberTypeOrNamespaceReference.cs @@ -32,9 +32,9 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem [Serializable] public sealed class MemberTypeOrNamespaceReference : TypeOrNamespaceReference, ISupportsInterning { - TypeOrNamespaceReference target; - string identifier; - IList typeArguments; + readonly TypeOrNamespaceReference target; + readonly string identifier; + readonly IList typeArguments; readonly NameLookupMode lookupMode; public MemberTypeOrNamespaceReference(TypeOrNamespaceReference target, string identifier, IList typeArguments, NameLookupMode lookupMode = NameLookupMode.Type) @@ -94,13 +94,6 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem return target.ToString() + "." + identifier + "<" + string.Join(",", typeArguments) + ">"; } - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - target = provider.Intern(target); - identifier = provider.Intern(identifier); - typeArguments = provider.InternList(typeArguments); - } - int ISupportsInterning.GetHashCodeForInterning() { int hashCode = 0; diff --git a/ICSharpCode.NRefactory.CSharp/TypeSystem/SimpleTypeOrNamespaceReference.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/SimpleTypeOrNamespaceReference.cs index ed049a7ef9..d0047ef6e3 100644 --- a/ICSharpCode.NRefactory.CSharp/TypeSystem/SimpleTypeOrNamespaceReference.cs +++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/SimpleTypeOrNamespaceReference.cs @@ -33,8 +33,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem [Serializable] public sealed class SimpleTypeOrNamespaceReference : TypeOrNamespaceReference, ISupportsInterning { - string identifier; - IList typeArguments; + readonly string identifier; + readonly IList typeArguments; readonly NameLookupMode lookupMode; public SimpleTypeOrNamespaceReference(string identifier, IList typeArguments, NameLookupMode lookupMode = NameLookupMode.Type) @@ -77,12 +77,6 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem return identifier + "<" + string.Join(",", typeArguments) + ">"; } - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - identifier = provider.Intern(identifier); - typeArguments = provider.InternList(typeArguments); - } - int ISupportsInterning.GetHashCodeForInterning() { int hashCode = 0; diff --git a/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs index 288209a837..cfc9e421f3 100644 --- a/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs @@ -46,15 +46,19 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem CSharpUnresolvedTypeDefinition currentTypeDefinition; DefaultUnresolvedMethod currentMethod; - IInterningProvider interningProvider = new SimpleInterningProvider(); + InterningProvider interningProvider = new SimpleInterningProvider(); /// /// Gets/Sets the interning provider to use. /// The default value is a new instance. /// - public IInterningProvider InterningProvider { + public InterningProvider InterningProvider { get { return interningProvider; } - set { interningProvider = value; } + set { + if (interningProvider == null) + throw new ArgumentNullException(); + interningProvider = value; + } } /// @@ -143,10 +147,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem public override IUnresolvedEntity VisitUsingDeclaration(UsingDeclaration usingDeclaration) { - TypeOrNamespaceReference u = usingDeclaration.Import.ToTypeReference(NameLookupMode.TypeInUsingDeclaration) as TypeOrNamespaceReference; + var u = ConvertTypeReference(usingDeclaration.Import, NameLookupMode.TypeInUsingDeclaration) as TypeOrNamespaceReference; if (u != null) { - if (interningProvider != null) - u = interningProvider.Intern(u); usingScope.Usings.Add(u); } return null; @@ -154,10 +156,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem public override IUnresolvedEntity VisitUsingAliasDeclaration(UsingAliasDeclaration usingDeclaration) { - TypeOrNamespaceReference u = usingDeclaration.Import.ToTypeReference(NameLookupMode.TypeInUsingDeclaration) as TypeOrNamespaceReference; + TypeOrNamespaceReference u = ConvertTypeReference(usingDeclaration.Import, NameLookupMode.TypeInUsingDeclaration) as TypeOrNamespaceReference; if (u != null) { - if (interningProvider != null) - u = interningProvider.Intern(u); usingScope.UsingAliases.Add(new KeyValuePair(usingDeclaration.Alias, u)); } return null; @@ -225,7 +225,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem ConvertTypeParameters(td.TypeParameters, typeDeclaration.TypeParameters, typeDeclaration.Constraints, EntityType.TypeDefinition); foreach (AstType baseType in typeDeclaration.BaseTypes) { - td.BaseTypes.Add(baseType.ToTypeReference(NameLookupMode.BaseTypeReference)); + td.BaseTypes.Add(ConvertTypeReference(baseType, NameLookupMode.BaseTypeReference)); } foreach (EntityDeclaration member in typeDeclaration.Members) { @@ -233,9 +233,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem } currentTypeDefinition = (CSharpUnresolvedTypeDefinition)currentTypeDefinition.DeclaringTypeDefinition; - if (interningProvider != null) { - td.ApplyInterningProvider(interningProvider); - } + td.ApplyInterningProvider(interningProvider); return td; } @@ -252,7 +250,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem ConvertTypeParameters(td.TypeParameters, delegateDeclaration.TypeParameters, delegateDeclaration.Constraints, EntityType.TypeDefinition); - ITypeReference returnType = delegateDeclaration.ReturnType.ToTypeReference(); + ITypeReference returnType = ConvertTypeReference(delegateDeclaration.ReturnType); List parameters = new List(); ConvertParameters(parameters, delegateDeclaration.Parameters); AddDefaultMethodsToDelegate(td, returnType, parameters); @@ -273,9 +271,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem } currentTypeDefinition = (CSharpUnresolvedTypeDefinition)currentTypeDefinition.DeclaringTypeDefinition; - if (interningProvider != null) { - td.ApplyInterningProvider(interningProvider); - } + td.ApplyInterningProvider(interningProvider); return td; } @@ -364,7 +360,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem field.IsVolatile = (modifiers & Modifiers.Volatile) != 0; field.IsReadOnly = (modifiers & Modifiers.Readonly) != 0; - field.ReturnType = fieldDeclaration.ReturnType.ToTypeReference(); + field.ReturnType = ConvertTypeReference(fieldDeclaration.ReturnType); if ((modifiers & Modifiers.Const) != 0) { field.ConstantValue = ConvertConstantValue(field.ReturnType, vi.Initializer); @@ -372,9 +368,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem } currentTypeDefinition.Members.Add(field); - if (interningProvider != null) { - field.ApplyInterningProvider(interningProvider); - } + field.ApplyInterningProvider(interningProvider); } return isSingleField ? field : null; } @@ -397,9 +391,9 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem } else { ITypeReference[] typeArgs = new ITypeReference[currentTypeDefinition.TypeParameters.Count]; for (int i = 0; i < typeArgs.Length; i++) { - typeArgs[i] = new TypeParameterReference(EntityType.TypeDefinition, i); + typeArgs[i] = TypeParameterReference.Create(EntityType.TypeDefinition, i); } - field.ReturnType = new ParameterizedTypeReference(currentTypeDefinition, typeArgs); + field.ReturnType = interningProvider.Intern(new ParameterizedTypeReference(currentTypeDefinition, typeArgs)); } field.Accessibility = Accessibility.Public; field.IsStatic = true; @@ -410,14 +404,12 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem if (prevField == null || prevField.ConstantValue == null) { field.ConstantValue = ConvertConstantValue(field.ReturnType, new PrimitiveExpression(0)); } else { - field.ConstantValue = new IncrementConstantValue(prevField.ConstantValue); + field.ConstantValue = interningProvider.Intern(new IncrementConstantValue(prevField.ConstantValue)); } } currentTypeDefinition.Members.Add(field); - if (interningProvider != null) { - field.ApplyInterningProvider(interningProvider); - } + field.ApplyInterningProvider(interningProvider); return field; } #endregion @@ -438,12 +430,13 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem tp.Region = MakeRegion(tpDecl); ConvertAttributes(tp.Attributes, tpDecl.Attributes); tp.Variance = tpDecl.Variance; + tp.ApplyInterningProvider(interningProvider); m.TypeParameters.Add(tp); } } else { ConvertTypeParameters(m.TypeParameters, methodDeclaration.TypeParameters, methodDeclaration.Constraints, EntityType.Method); } - m.ReturnType = methodDeclaration.ReturnType.ToTypeReference(); + m.ReturnType = ConvertTypeReference(methodDeclaration.ReturnType); ConvertAttributes(m.Attributes, methodDeclaration.Attributes.Where(s => s.AttributeTarget != "return")); ConvertAttributes(m.ReturnTypeAttributes, methodDeclaration.Attributes.Where(s => s.AttributeTarget == "return")); @@ -459,16 +452,16 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem if (!methodDeclaration.PrivateImplementationType.IsNull) { m.Accessibility = Accessibility.None; m.IsExplicitInterfaceImplementation = true; - m.ExplicitInterfaceImplementations.Add(new DefaultMemberReference( - m.EntityType, methodDeclaration.PrivateImplementationType.ToTypeReference(), m.Name, - m.TypeParameters.Count, GetParameterTypes(m.Parameters))); + m.ExplicitInterfaceImplementations.Add( + interningProvider.Intern(new DefaultMemberReference( + m.EntityType, + ConvertTypeReference(methodDeclaration.PrivateImplementationType), + m.Name, m.TypeParameters.Count, GetParameterTypes(m.Parameters)))); } currentTypeDefinition.Members.Add(m); currentMethod = null; - if (interningProvider != null) { - m.ApplyInterningProvider(interningProvider); - } + m.ApplyInterningProvider(interningProvider); return m; } @@ -480,7 +473,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem for (int i = 0; i < types.Length; i++) { types[i] = parameters[i].Type; } - return types; + return interningProvider.InternList(types); } bool InheritsConstraints(MethodDeclaration methodDeclaration) @@ -523,30 +516,15 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem } } var lookupMode = (ownerType == EntityType.TypeDefinition) ? NameLookupMode.BaseTypeReference : NameLookupMode.Type; - tp.Constraints.Add(type.ToTypeReference(lookupMode)); + tp.Constraints.Add(ConvertTypeReference(type, lookupMode)); } break; } } } - } - - IMemberReference ConvertInterfaceImplementation(AstType interfaceType, AbstractUnresolvedMember unresolvedMember) - { - ITypeReference interfaceTypeReference = interfaceType.ToTypeReference(); - int typeParameterCount = 0; - IList parameterTypes = null; - if (unresolvedMember.EntityType == EntityType.Method) { - typeParameterCount = ((IUnresolvedMethod)unresolvedMember).TypeParameters.Count; + foreach (DefaultUnresolvedTypeParameter tp in list) { + tp.ApplyInterningProvider(interningProvider); } - IUnresolvedParameterizedMember parameterizedMember = unresolvedMember as IUnresolvedParameterizedMember; - if (parameterizedMember != null) { - parameterTypes = new ITypeReference[parameterizedMember.Parameters.Count]; - for (int i = 0; i < parameterTypes.Count; i++) { - parameterTypes[i] = parameterizedMember.Parameters[i].Type; - } - } - return new DefaultMemberReference(unresolvedMember.EntityType, interfaceTypeReference, unresolvedMember.Name, typeParameterCount, parameterTypes); } #endregion @@ -559,7 +537,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem m.BodyRegion = MakeRegion(operatorDeclaration.Body); AddXmlDocumentation(m, operatorDeclaration); - m.ReturnType = operatorDeclaration.ReturnType.ToTypeReference(); + m.ReturnType = ConvertTypeReference(operatorDeclaration.ReturnType); ConvertAttributes(m.Attributes, operatorDeclaration.Attributes.Where(s => s.AttributeTarget != "return")); ConvertAttributes(m.ReturnTypeAttributes, operatorDeclaration.Attributes.Where(s => s.AttributeTarget == "return")); @@ -569,9 +547,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem ConvertParameters(m.Parameters, operatorDeclaration.Parameters); currentTypeDefinition.Members.Add(m); - if (interningProvider != null) { - m.ApplyInterningProvider(interningProvider); - } + m.ApplyInterningProvider(interningProvider); return m; } #endregion @@ -602,9 +578,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem ApplyModifiers(ctor, modifiers); currentTypeDefinition.Members.Add(ctor); - if (interningProvider != null) { - ctor.ApplyInterningProvider(interningProvider); - } + ctor.ApplyInterningProvider(interningProvider); return ctor; } #endregion @@ -625,9 +599,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem AddXmlDocumentation(dtor, destructorDeclaration); currentTypeDefinition.Members.Add(dtor); - if (interningProvider != null) { - dtor.ApplyInterningProvider(interningProvider); - } + dtor.ApplyInterningProvider(interningProvider); return dtor; } #endregion @@ -639,22 +611,20 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem p.Region = MakeRegion(propertyDeclaration); p.BodyRegion = MakeBraceRegion(propertyDeclaration); ApplyModifiers(p, propertyDeclaration.Modifiers); - p.ReturnType = propertyDeclaration.ReturnType.ToTypeReference(); + p.ReturnType = ConvertTypeReference(propertyDeclaration.ReturnType); ConvertAttributes(p.Attributes, propertyDeclaration.Attributes); AddXmlDocumentation(p, propertyDeclaration); if (!propertyDeclaration.PrivateImplementationType.IsNull) { p.Accessibility = Accessibility.None; p.IsExplicitInterfaceImplementation = true; - p.ExplicitInterfaceImplementations.Add(new DefaultMemberReference( - p.EntityType, propertyDeclaration.PrivateImplementationType.ToTypeReference(), p.Name)); + p.ExplicitInterfaceImplementations.Add(interningProvider.Intern(new DefaultMemberReference( + p.EntityType, ConvertTypeReference(propertyDeclaration.PrivateImplementationType), p.Name))); } bool isExtern = propertyDeclaration.HasModifier(Modifiers.Extern); p.Getter = ConvertAccessor(propertyDeclaration.Getter, p, "get_", isExtern); p.Setter = ConvertAccessor(propertyDeclaration.Setter, p, "set_", isExtern); currentTypeDefinition.Members.Add(p); - if (interningProvider != null) { - p.ApplyInterningProvider(interningProvider); - } + p.ApplyInterningProvider(interningProvider); return p; } @@ -665,7 +635,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem p.Region = MakeRegion(indexerDeclaration); p.BodyRegion = MakeBraceRegion(indexerDeclaration); ApplyModifiers(p, indexerDeclaration.Modifiers); - p.ReturnType = indexerDeclaration.ReturnType.ToTypeReference(); + p.ReturnType = ConvertTypeReference(indexerDeclaration.ReturnType); ConvertAttributes(p.Attributes, indexerDeclaration.Attributes); AddXmlDocumentation(p, indexerDeclaration); @@ -674,17 +644,15 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem if (!indexerDeclaration.PrivateImplementationType.IsNull) { p.Accessibility = Accessibility.None; p.IsExplicitInterfaceImplementation = true; - p.ExplicitInterfaceImplementations.Add(new DefaultMemberReference( - p.EntityType, indexerDeclaration.PrivateImplementationType.ToTypeReference(), p.Name, 0, GetParameterTypes(p.Parameters))); + p.ExplicitInterfaceImplementations.Add(interningProvider.Intern(new DefaultMemberReference( + p.EntityType, indexerDeclaration.PrivateImplementationType.ToTypeReference(), p.Name, 0, GetParameterTypes(p.Parameters)))); } bool isExtern = indexerDeclaration.HasModifier(Modifiers.Extern); p.Getter = ConvertAccessor(indexerDeclaration.Getter, p, "get_", isExtern); p.Setter = ConvertAccessor(indexerDeclaration.Setter, p, "set_", isExtern); currentTypeDefinition.Members.Add(p); - if (interningProvider != null) { - p.ApplyInterningProvider(interningProvider); - } + p.ApplyInterningProvider(interningProvider); return p; } @@ -705,7 +673,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem a.Region = MakeRegion(accessor); a.BodyRegion = MakeRegion(accessor.Body); - // An accessor has no body if all both are true: + // An accessor has no body if both are true: // a) there's no body in the code // b) the member is either abstract or extern a.HasBody = !(accessor.Body.IsNull && (p.IsAbstract || memberIsExtern)); @@ -733,12 +701,13 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem if (p.IsExplicitInterfaceImplementation) { a.IsExplicitInterfaceImplementation = true; Debug.Assert(p.ExplicitInterfaceImplementations.Count == 1); - a.ExplicitInterfaceImplementations.Add(new DefaultMemberReference( + a.ExplicitInterfaceImplementations.Add(interningProvider.Intern(new DefaultMemberReference( EntityType.Accessor, p.ExplicitInterfaceImplementations[0].DeclaringTypeReference, a.Name, 0, GetParameterTypes(a.Parameters) - )); + ))); } + a.ApplyInterningProvider(interningProvider); return a; } #endregion @@ -758,7 +727,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem ApplyModifiers(ev, modifiers); AddXmlDocumentation(ev, eventDeclaration); - ev.ReturnType = eventDeclaration.ReturnType.ToTypeReference(); + ev.ReturnType = ConvertTypeReference(eventDeclaration.ReturnType); var valueParameter = new DefaultUnresolvedParameter(ev.ReturnType, "value"); ev.AddAccessor = CreateDefaultEventAccessor(ev, "add_" + ev.Name, valueParameter); @@ -777,9 +746,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem } currentTypeDefinition.Members.Add(ev); - if (interningProvider != null) { - ev.ApplyInterningProvider(interningProvider); - } + ev.ApplyInterningProvider(interningProvider); } return isSingleEvent ? ev : null; } @@ -810,15 +777,15 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem e.Region = MakeRegion(eventDeclaration); e.BodyRegion = MakeBraceRegion(eventDeclaration); ApplyModifiers(e, eventDeclaration.Modifiers); - e.ReturnType = eventDeclaration.ReturnType.ToTypeReference(); + e.ReturnType = ConvertTypeReference(eventDeclaration.ReturnType); ConvertAttributes(e.Attributes, eventDeclaration.Attributes); AddXmlDocumentation(e, eventDeclaration); if (!eventDeclaration.PrivateImplementationType.IsNull) { e.Accessibility = Accessibility.None; e.IsExplicitInterfaceImplementation = true; - e.ExplicitInterfaceImplementations.Add(new DefaultMemberReference( - e.EntityType, eventDeclaration.PrivateImplementationType.ToTypeReference(), e.Name)); + e.ExplicitInterfaceImplementations.Add(interningProvider.Intern(new DefaultMemberReference( + e.EntityType, eventDeclaration.PrivateImplementationType.ToTypeReference(), e.Name))); } // custom events can't be extern; the non-custom event syntax must be used for extern events @@ -826,9 +793,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem e.RemoveAccessor = ConvertAccessor(eventDeclaration.RemoveAccessor, e, "remove_", false); currentTypeDefinition.Members.Add(e); - if (interningProvider != null) { - e.ApplyInterningProvider(interningProvider); - } + e.ApplyInterningProvider(interningProvider); return e; } #endregion @@ -904,18 +869,18 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem } } - internal static ITypeReference ConvertAttributeType(AstType type) + internal static ITypeReference ConvertAttributeType(AstType type, InterningProvider interningProvider) { - ITypeReference tr = type.ToTypeReference(); + ITypeReference tr = type.ToTypeReference(NameLookupMode.Type, interningProvider); if (!type.GetChildByRole(Roles.Identifier).IsVerbatim) { // Try to add "Attribute" suffix, but only if the identifier // (=last identifier in fully qualified name) isn't a verbatim identifier. SimpleTypeOrNamespaceReference st = tr as SimpleTypeOrNamespaceReference; MemberTypeOrNamespaceReference mt = tr as MemberTypeOrNamespaceReference; if (st != null) - return new AttributeTypeReference(st, st.AddSuffix("Attribute")); + return interningProvider.Intern(new AttributeTypeReference(st, interningProvider.Intern(st.AddSuffix("Attribute")))); else if (mt != null) - return new AttributeTypeReference(mt, mt.AddSuffix("Attribute")); + return interningProvider.Intern(new AttributeTypeReference(mt, interningProvider.Intern(mt.AddSuffix("Attribute")))); } return tr; } @@ -923,20 +888,21 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem CSharpAttribute ConvertAttribute(CSharp.Attribute attr) { DomRegion region = MakeRegion(attr); - ITypeReference type = ConvertAttributeType(attr.Type); + ITypeReference type = ConvertAttributeType(attr.Type, interningProvider); List positionalArguments = null; List> namedCtorArguments = null; List> namedArguments = null; foreach (Expression expr in attr.Arguments) { NamedArgumentExpression nae = expr as NamedArgumentExpression; if (nae != null) { + string name = interningProvider.Intern(nae.Name); if (namedCtorArguments == null) namedCtorArguments = new List>(); - namedCtorArguments.Add(new KeyValuePair(nae.Name, ConvertAttributeArgument(nae.Expression))); + namedCtorArguments.Add(new KeyValuePair(name, ConvertAttributeArgument(nae.Expression))); } else { NamedExpression namedExpression = expr as NamedExpression; if (namedExpression != null) { - string name = namedExpression.Name; + string name = interningProvider.Intern(namedExpression.Name); if (namedArguments == null) namedArguments = new List>(); namedArguments.Add(new KeyValuePair(name, ConvertAttributeArgument(namedExpression.Expression))); @@ -947,53 +913,55 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem } } } - return new CSharpAttribute(type, region, positionalArguments, namedCtorArguments, namedArguments); + return new CSharpAttribute(type, region, interningProvider.InternList(positionalArguments), namedCtorArguments, namedArguments); } #endregion #region Types - [Obsolete("Use AstType.ToTypeReference() instead.")] - public static ITypeReference ConvertType(AstType type, NameLookupMode lookupMode = NameLookupMode.Type) + ITypeReference ConvertTypeReference(AstType type, NameLookupMode lookupMode = NameLookupMode.Type) { - return type.ToTypeReference(lookupMode); + return type.ToTypeReference(lookupMode, interningProvider); } #endregion #region Constant Values IConstantValue ConvertConstantValue(ITypeReference targetType, AstNode expression) { - return ConvertConstantValue(targetType, expression, currentTypeDefinition, currentMethod, usingScope); + return ConvertConstantValue(targetType, expression, currentTypeDefinition, currentMethod, usingScope, interningProvider); } internal static IConstantValue ConvertConstantValue( ITypeReference targetType, AstNode expression, - IUnresolvedTypeDefinition parentTypeDefinition, IUnresolvedMethod parentMethodDefinition, UsingScope parentUsingScope) + IUnresolvedTypeDefinition parentTypeDefinition, IUnresolvedMethod parentMethodDefinition, UsingScope parentUsingScope, + InterningProvider interningProvider) { - ConstantValueBuilder b = new ConstantValueBuilder(false); + ConstantValueBuilder b = new ConstantValueBuilder(false, interningProvider); ConstantExpression c = expression.AcceptVisitor(b); if (c == null) return new ErrorConstantValue(targetType); PrimitiveConstantExpression pc = c as PrimitiveConstantExpression; if (pc != null && pc.Type == targetType) { // Save memory by directly using a SimpleConstantValue. - return new SimpleConstantValue(targetType, pc.Value); + return interningProvider.Intern(new SimpleConstantValue(targetType, pc.Value)); } // cast to the desired type - return new ConstantCast(targetType, c); + return interningProvider.Intern(new ConstantCast(targetType, c)); } IConstantValue ConvertAttributeArgument(Expression expression) { - ConstantValueBuilder b = new ConstantValueBuilder(true); + ConstantValueBuilder b = new ConstantValueBuilder(true, interningProvider); return expression.AcceptVisitor(b); } sealed class ConstantValueBuilder : DepthFirstAstVisitor { + readonly InterningProvider interningProvider; readonly bool isAttributeArgument; - public ConstantValueBuilder(bool isAttributeArgument) + public ConstantValueBuilder(bool isAttributeArgument, InterningProvider interningProvider) { + this.interningProvider = interningProvider; this.isAttributeArgument = isAttributeArgument; } @@ -1004,13 +972,21 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem public override ConstantExpression VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression) { - return new PrimitiveConstantExpression(KnownTypeReference.Object, null); + return interningProvider.Intern( + new PrimitiveConstantExpression(KnownTypeReference.Object, null)); } public override ConstantExpression VisitPrimitiveExpression(PrimitiveExpression primitiveExpression) { - TypeCode typeCode = Type.GetTypeCode(primitiveExpression.Value.GetType()); - return new PrimitiveConstantExpression(typeCode.ToTypeReference(), primitiveExpression.Value); + object val = interningProvider.InternValue(primitiveExpression.Value); + TypeCode typeCode = Type.GetTypeCode(val.GetType()); + return interningProvider.Intern( + new PrimitiveConstantExpression(typeCode.ToTypeReference(), val)); + } + + ITypeReference ConvertTypeReference(AstType type) + { + return type.ToTypeReference(NameLookupMode.Type, interningProvider); } IList ConvertTypeArguments(AstNodeCollection types) @@ -1021,31 +997,33 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem ITypeReference[] result = new ITypeReference[count]; int pos = 0; foreach (AstType type in types) { - result[pos++] = type.ToTypeReference(); + result[pos++] = ConvertTypeReference(type); } - return result; + return interningProvider.InternList(result); } public override ConstantExpression VisitIdentifierExpression(IdentifierExpression identifierExpression) { - return new ConstantIdentifierReference(identifierExpression.Identifier, ConvertTypeArguments(identifierExpression.TypeArguments)); + string identifier = interningProvider.Intern(identifierExpression.Identifier); + return new ConstantIdentifierReference(identifier, ConvertTypeArguments(identifierExpression.TypeArguments)); } public override ConstantExpression VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression) { + string memberName = interningProvider.Intern(memberReferenceExpression.MemberName); TypeReferenceExpression tre = memberReferenceExpression.Target as TypeReferenceExpression; if (tre != null) { // handle "int.MaxValue" return new ConstantMemberReference( - tre.Type.ToTypeReference(), - memberReferenceExpression.MemberName, + ConvertTypeReference(tre.Type), + memberName, ConvertTypeArguments(memberReferenceExpression.TypeArguments)); } ConstantExpression v = memberReferenceExpression.Target.AcceptVisitor(this); if (v == null) return null; return new ConstantMemberReference( - v, memberReferenceExpression.MemberName, + v, memberName, ConvertTypeArguments(memberReferenceExpression.TypeArguments)); } @@ -1059,7 +1037,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem ConstantExpression v = castExpression.Expression.AcceptVisitor(this); if (v == null) return null; - return new ConstantCast(castExpression.Type.ToTypeReference(), v); + return interningProvider.Intern(new ConstantCast(ConvertTypeReference(castExpression.Type), v)); } public override ConstantExpression VisitCheckedExpression(CheckedExpression checkedExpression) @@ -1082,7 +1060,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem public override ConstantExpression VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression) { - return new ConstantDefaultValue(defaultValueExpression.Type.ToTypeReference()); + return interningProvider.Intern( + new ConstantDefaultValue(ConvertTypeReference(defaultValueExpression.Type))); } public override ConstantExpression VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression) @@ -1113,7 +1092,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem public override ConstantExpression VisitTypeOfExpression(TypeOfExpression typeOfExpression) { if (isAttributeArgument) { - return new TypeOfConstantExpression(typeOfExpression.Type.ToTypeReference()); + return new TypeOfConstantExpression(ConvertTypeReference(typeOfExpression.Type)); } else { return null; } @@ -1128,9 +1107,9 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem if (arrayCreateExpression.Type.IsNull) { type = null; } else { - type = arrayCreateExpression.Type.ToTypeReference(); + type = ConvertTypeReference(arrayCreateExpression.Type); foreach (var spec in arrayCreateExpression.AdditionalArraySpecifiers.Reverse()) { - type = new ArrayTypeReference(type, spec.Dimensions); + type = interningProvider.Intern(new ArrayTypeReference(type, spec.Dimensions)); } } ConstantExpression[] elements = new ConstantExpression[initializer.Elements.Count]; @@ -1153,17 +1132,17 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem void ConvertParameters(IList outputList, IEnumerable parameters) { foreach (ParameterDeclaration pd in parameters) { - DefaultUnresolvedParameter p = new DefaultUnresolvedParameter(pd.Type.ToTypeReference(), pd.Name); + DefaultUnresolvedParameter p = new DefaultUnresolvedParameter(ConvertTypeReference(pd.Type), interningProvider.Intern(pd.Name)); p.Region = MakeRegion(pd); ConvertAttributes(p.Attributes, pd.Attributes); switch (pd.ParameterModifier) { case ParameterModifier.Ref: p.IsRef = true; - p.Type = new ByReferenceTypeReference(p.Type); + p.Type = interningProvider.Intern(new ByReferenceTypeReference(p.Type)); break; case ParameterModifier.Out: p.IsOut = true; - p.Type = new ByReferenceTypeReference(p.Type); + p.Type = interningProvider.Intern(new ByReferenceTypeReference(p.Type)); break; case ParameterModifier.Params: p.IsParams = true; @@ -1171,17 +1150,17 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem } if (!pd.DefaultExpression.IsNull) p.DefaultValue = ConvertConstantValue(p.Type, pd.DefaultExpression); - outputList.Add(p); + outputList.Add(interningProvider.Intern(p)); } } - internal static IList GetParameterTypes(IEnumerable parameters) + internal static IList GetParameterTypes(IEnumerable parameters, InterningProvider interningProvider) { List result = new List(); foreach (ParameterDeclaration pd in parameters) { - ITypeReference type = pd.Type.ToTypeReference(); + ITypeReference type = pd.Type.ToTypeReference(NameLookupMode.Type, interningProvider); if (pd.ParameterModifier == ParameterModifier.Ref || pd.ParameterModifier == ParameterModifier.Out) - type = new ByReferenceTypeReference(type); + type = interningProvider.Intern(new ByReferenceTypeReference(type)); result.Add(type); } return result; diff --git a/ICSharpCode.NRefactory/Documentation/IdStringProvider.cs b/ICSharpCode.NRefactory/Documentation/IdStringProvider.cs index c8d5c76742..460ba9b682 100644 --- a/ICSharpCode.NRefactory/Documentation/IdStringProvider.cs +++ b/ICSharpCode.NRefactory/Documentation/IdStringProvider.cs @@ -285,11 +285,11 @@ namespace ICSharpCode.NRefactory.Documentation // method type parameter reference pos++; int index = ReflectionHelper.ReadTypeParameterCount(reflectionTypeName, ref pos); - result = new TypeParameterReference(EntityType.Method, index); + result = TypeParameterReference.Create(EntityType.Method, index); } else { // class type parameter reference int index = ReflectionHelper.ReadTypeParameterCount(reflectionTypeName, ref pos); - result = new TypeParameterReference(EntityType.TypeDefinition, index); + result = TypeParameterReference.Create(EntityType.TypeDefinition, index); } } else { // not a type parameter reference: read the actual type name diff --git a/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs b/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs index 18ade936cf..373ebaf666 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs @@ -147,8 +147,8 @@ namespace ICSharpCode.NRefactory.TypeSystem [Serializable] public sealed class ArrayTypeReference : ITypeReference, ISupportsInterning { - ITypeReference elementType; - int dimensions; + readonly ITypeReference elementType; + readonly int dimensions; public ArrayTypeReference(ITypeReference elementType, int dimensions = 1) { @@ -178,11 +178,6 @@ namespace ICSharpCode.NRefactory.TypeSystem return elementType.ToString() + "[" + new string(',', dimensions - 1) + "]"; } - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - elementType = provider.Intern(elementType); - } - int ISupportsInterning.GetHashCodeForInterning() { return elementType.GetHashCode() ^ dimensions; diff --git a/ICSharpCode.NRefactory/TypeSystem/ByReferenceType.cs b/ICSharpCode.NRefactory/TypeSystem/ByReferenceType.cs index 21661c7246..5039eff67d 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ByReferenceType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ByReferenceType.cs @@ -75,7 +75,7 @@ namespace ICSharpCode.NRefactory.TypeSystem [Serializable] public sealed class ByReferenceTypeReference : ITypeReference, ISupportsInterning { - ITypeReference elementType; + readonly ITypeReference elementType; public ByReferenceTypeReference(ITypeReference elementType) { @@ -98,11 +98,6 @@ namespace ICSharpCode.NRefactory.TypeSystem return elementType.ToString() + "&"; } - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - elementType = provider.Intern(elementType); - } - int ISupportsInterning.GetHashCodeForInterning() { return elementType.GetHashCode() ^ 91725814; diff --git a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs index fa23cbb4d4..82ad487cea 100644 --- a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs +++ b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs @@ -72,10 +72,19 @@ namespace ICSharpCode.NRefactory.TypeSystem /// public IDocumentationProvider DocumentationProvider { get; set; } + InterningProvider interningProvider; + /// /// Gets/Sets the interning provider. /// - public IInterningProvider InterningProvider { get; set; } + public InterningProvider InterningProvider { + get { return interningProvider; } + set { + if (value == null) + throw new ArgumentNullException(); + interningProvider = value; + } + } /// /// Gets/Sets the cancellation token used by the cecil loader. @@ -140,6 +149,7 @@ namespace ICSharpCode.NRefactory.TypeSystem this.currentModule = loader.currentModule; this.currentAssembly = loader.currentAssembly; // don't use interning - the interning provider is most likely not thread-safe + this.interningProvider = InterningProvider.Dummy; // don't use cancellation for delay-loaded members } @@ -162,10 +172,8 @@ namespace ICSharpCode.NRefactory.TypeSystem AddAttributes(assemblyDefinition, assemblyAttributes); AddAttributes(assemblyDefinition.MainModule, moduleAttributes); - if (this.InterningProvider != null) { - assemblyAttributes = this.InterningProvider.InternList(assemblyAttributes); - moduleAttributes = this.InterningProvider.InternList(moduleAttributes); - } + assemblyAttributes = interningProvider.InternList(assemblyAttributes); + moduleAttributes = interningProvider.InternList(moduleAttributes); this.currentAssembly = new CecilUnresolvedAssembly(assemblyDefinition.Name.Name, this.DocumentationProvider); currentAssembly.Location = assemblyDefinition.MainModule.FullyQualifiedName; @@ -176,11 +184,13 @@ namespace ICSharpCode.NRefactory.TypeSystem foreach (ExportedType type in assemblyDefinition.MainModule.ExportedTypes) { if (type.IsForwarder) { int typeParameterCount; + string ns = type.Namespace; string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount); - var typeRef = new GetClassTypeReference(GetAssemblyReference(type.Scope), type.Namespace, name, typeParameterCount); - if (this.InterningProvider != null) - typeRef = this.InterningProvider.Intern(typeRef); - var key = new FullNameAndTypeParameterCount(type.Namespace, name, typeParameterCount); + ns = interningProvider.Intern(ns); + name = interningProvider.Intern(name); + var typeRef = new GetClassTypeReference(GetAssemblyReference(type.Scope), ns, name, typeParameterCount); + typeRef = interningProvider.Intern(typeRef); + var key = new FullNameAndTypeParameterCount(ns, name, typeParameterCount); currentAssembly.AddTypeForwarder(key, typeRef); } } @@ -335,23 +345,26 @@ namespace ICSharpCode.NRefactory.TypeSystem if (type is Mono.Cecil.ByReferenceType) { typeIndex++; - return new ByReferenceTypeReference( - CreateType( - (type as Mono.Cecil.ByReferenceType).ElementType, - typeAttributes, ref typeIndex)); + return interningProvider.Intern( + new ByReferenceTypeReference( + CreateType( + (type as Mono.Cecil.ByReferenceType).ElementType, + typeAttributes, ref typeIndex))); } else if (type is Mono.Cecil.PointerType) { typeIndex++; - return new PointerTypeReference( - CreateType( - (type as Mono.Cecil.PointerType).ElementType, - typeAttributes, ref typeIndex)); + return interningProvider.Intern( + new PointerTypeReference( + CreateType( + (type as Mono.Cecil.PointerType).ElementType, + typeAttributes, ref typeIndex))); } else if (type is Mono.Cecil.ArrayType) { typeIndex++; - return new ArrayTypeReference( - CreateType( - (type as Mono.Cecil.ArrayType).ElementType, - typeAttributes, ref typeIndex), - (type as Mono.Cecil.ArrayType).Rank); + return interningProvider.Intern( + new ArrayTypeReference( + CreateType( + (type as Mono.Cecil.ArrayType).ElementType, + typeAttributes, ref typeIndex), + (type as Mono.Cecil.ArrayType).Rank)); } else if (type is GenericInstanceType) { GenericInstanceType gType = (GenericInstanceType)type; ITypeReference baseType = CreateType(gType.ElementType, typeAttributes, ref typeIndex); @@ -360,17 +373,18 @@ namespace ICSharpCode.NRefactory.TypeSystem typeIndex++; para[i] = CreateType(gType.GenericArguments[i], typeAttributes, ref typeIndex); } - return new ParameterizedTypeReference(baseType, para); + return interningProvider.Intern(new ParameterizedTypeReference(baseType, para)); } else if (type is GenericParameter) { GenericParameter typeGP = (GenericParameter)type; - return new TypeParameterReference(typeGP.Owner is MethodDefinition ? EntityType.Method : EntityType.TypeDefinition, typeGP.Position); + return TypeParameterReference.Create(typeGP.Owner is MethodDefinition ? EntityType.Method : EntityType.TypeDefinition, typeGP.Position); } else if (type.IsNested) { ITypeReference typeRef = CreateType(type.DeclaringType, typeAttributes, ref typeIndex); int partTypeParameterCount; string namepart = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out partTypeParameterCount); - return new NestedTypeReference(typeRef, namepart, partTypeParameterCount); + namepart = interningProvider.Intern(namepart); + return interningProvider.Intern(new NestedTypeReference(typeRef, namepart, partTypeParameterCount)); } else { - string ns = type.Namespace ?? string.Empty; + string ns = interningProvider.Intern(type.Namespace ?? string.Empty); string name = type.Name; if (name == null) throw new InvalidOperationException("type.Name returned null. Type: " + type.ToString()); @@ -380,12 +394,13 @@ namespace ICSharpCode.NRefactory.TypeSystem } else { int typeParameterCount; name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(name, out typeParameterCount); + name = interningProvider.Intern(name); if (currentAssembly != null) { IUnresolvedTypeDefinition c = currentAssembly.GetTypeDefinition(ns, name, typeParameterCount); if (c != null) return c; } - return new GetClassTypeReference(GetAssemblyReference(type.Scope), ns, name, typeParameterCount); + return interningProvider.Intern(new GetClassTypeReference(GetAssemblyReference(type.Scope), ns, name, typeParameterCount)); } } } @@ -395,7 +410,7 @@ namespace ICSharpCode.NRefactory.TypeSystem if (scope == null || scope == currentModule) return DefaultAssemblyReference.CurrentAssembly; else - return new DefaultAssemblyReference(scope.Name); + return interningProvider.Intern(new DefaultAssemblyReference(scope.Name)); } static bool HasDynamicAttribute(ICustomAttributeProvider attributeProvider, int typeIndex) @@ -433,10 +448,15 @@ namespace ICSharpCode.NRefactory.TypeSystem // AssemblyVersionAttribute if (assembly.Name.Version != null) { var assemblyVersion = new DefaultUnresolvedAttribute(assemblyVersionAttributeTypeRef, new[] { KnownTypeReference.String }); - assemblyVersion.PositionalArguments.Add(new SimpleConstantValue(KnownTypeReference.String, assembly.Name.Version.ToString())); - outputList.Add(assemblyVersion); + assemblyVersion.PositionalArguments.Add(CreateSimpleConstantValue(KnownTypeReference.String, assembly.Name.Version.ToString())); + outputList.Add(interningProvider.Intern(assemblyVersion)); } } + + IConstantValue CreateSimpleConstantValue(ITypeReference type, object value) + { + return interningProvider.Intern(new SimpleConstantValue(type, interningProvider.InternValue(value))); + } #endregion #region Module Attributes @@ -497,7 +517,7 @@ namespace ICSharpCode.NRefactory.TypeSystem if (methodDefinition.HasPInvokeInfo) { PInvokeInfo info = methodDefinition.PInvokeInfo; var dllImport = new DefaultUnresolvedAttribute(dllImportAttributeTypeRef, new[] { KnownTypeReference.String }); - dllImport.PositionalArguments.Add(new SimpleConstantValue(KnownTypeReference.String, info.Module.Name)); + dllImport.PositionalArguments.Add(CreateSimpleConstantValue(KnownTypeReference.String, info.Module.Name)); if (info.IsBestFitDisabled) dllImport.AddNamedFieldArgument("BestFitMapping", falseValue); @@ -529,7 +549,7 @@ namespace ICSharpCode.NRefactory.TypeSystem throw new NotSupportedException("unknown calling convention"); } if (callingConvention != CallingConvention.Winapi) - dllImport.AddNamedFieldArgument("CallingConvention", callingConventionTypeRef, (int)callingConvention); + dllImport.AddNamedFieldArgument("CallingConvention", CreateSimpleConstantValue(callingConventionTypeRef, (int)callingConvention)); CharSet charSet = CharSet.None; switch (info.Attributes & PInvokeAttributes.CharSetMask) { @@ -544,10 +564,10 @@ namespace ICSharpCode.NRefactory.TypeSystem break; } if (charSet != CharSet.None) - dllImport.AddNamedFieldArgument("CharSet", charSetTypeRef, (int)charSet); + dllImport.AddNamedFieldArgument("CharSet", CreateSimpleConstantValue(charSetTypeRef, (int)charSet)); if (!string.IsNullOrEmpty(info.EntryPoint) && info.EntryPoint != methodDefinition.Name) - dllImport.AddNamedFieldArgument("EntryPoint", KnownTypeReference.String, info.EntryPoint); + dllImport.AddNamedFieldArgument("EntryPoint", CreateSimpleConstantValue(KnownTypeReference.String, info.EntryPoint)); if (info.IsNoMangle) dllImport.AddNamedFieldArgument("ExactSpelling", trueValue); @@ -565,7 +585,7 @@ namespace ICSharpCode.NRefactory.TypeSystem if (info.IsThrowOnUnmappableCharEnabled) dllImport.AddNamedFieldArgument("ThrowOnUnmappableChar", trueValue); - attributes.Add(dllImport); + attributes.Add(interningProvider.Intern(dllImport)); } #endregion @@ -579,8 +599,8 @@ namespace ICSharpCode.NRefactory.TypeSystem #region MethodImplAttribute if (implAttributes != 0) { var methodImpl = new DefaultUnresolvedAttribute(methodImplAttributeTypeRef, new[] { methodImplOptionsTypeRef }); - methodImpl.PositionalArguments.Add(new SimpleConstantValue(methodImplOptionsTypeRef, (int)implAttributes)); - attributes.Add(methodImpl); + methodImpl.PositionalArguments.Add(CreateSimpleConstantValue(methodImplOptionsTypeRef, (int)implAttributes)); + attributes.Add(interningProvider.Intern(methodImpl)); } #endregion @@ -641,17 +661,17 @@ namespace ICSharpCode.NRefactory.TypeSystem LayoutKind defaultLayoutKind = (typeDefinition.IsValueType && !typeDefinition.IsEnum) ? LayoutKind.Sequential: LayoutKind.Auto; if (layoutKind != defaultLayoutKind || charSet != CharSet.Ansi || typeDefinition.PackingSize > 0 || typeDefinition.ClassSize > 0) { DefaultUnresolvedAttribute structLayout = new DefaultUnresolvedAttribute(structLayoutAttributeTypeRef, new[] { layoutKindTypeRef }); - structLayout.PositionalArguments.Add(new SimpleConstantValue(layoutKindTypeRef, (int)layoutKind)); + structLayout.PositionalArguments.Add(CreateSimpleConstantValue(layoutKindTypeRef, (int)layoutKind)); if (charSet != CharSet.Ansi) { - structLayout.AddNamedFieldArgument("CharSet", charSetTypeRef, (int)charSet); + structLayout.AddNamedFieldArgument("CharSet", CreateSimpleConstantValue(charSetTypeRef, (int)charSet)); } if (typeDefinition.PackingSize > 0) { - structLayout.AddNamedFieldArgument("Pack", KnownTypeReference.Int32, (int)typeDefinition.PackingSize); + structLayout.AddNamedFieldArgument("Pack", CreateSimpleConstantValue(KnownTypeReference.Int32, (int)typeDefinition.PackingSize)); } if (typeDefinition.ClassSize > 0) { - structLayout.AddNamedFieldArgument("Size", KnownTypeReference.Int32, (int)typeDefinition.ClassSize); + structLayout.AddNamedFieldArgument("Size", CreateSimpleConstantValue(KnownTypeReference.Int32, (int)typeDefinition.ClassSize)); } - targetEntity.Attributes.Add(structLayout); + targetEntity.Attributes.Add(interningProvider.Intern(structLayout)); } #endregion @@ -673,8 +693,8 @@ namespace ICSharpCode.NRefactory.TypeSystem // FieldOffsetAttribute if (fieldDefinition.HasLayoutInfo) { DefaultUnresolvedAttribute fieldOffset = new DefaultUnresolvedAttribute(fieldOffsetAttributeTypeRef, new[] { KnownTypeReference.Int32 }); - fieldOffset.PositionalArguments.Add(new SimpleConstantValue(KnownTypeReference.Int32, fieldDefinition.Offset)); - targetEntity.Attributes.Add(fieldOffset); + fieldOffset.PositionalArguments.Add(CreateSimpleConstantValue(KnownTypeReference.Int32, fieldDefinition.Offset)); + targetEntity.Attributes.Add(interningProvider.Intern(fieldOffset)); } // NonSerializedAttribute @@ -714,42 +734,42 @@ namespace ICSharpCode.NRefactory.TypeSystem static readonly ITypeReference marshalAsAttributeTypeRef = typeof(MarshalAsAttribute).ToTypeReference(); static readonly ITypeReference unmanagedTypeTypeRef = typeof(UnmanagedType).ToTypeReference(); - static IUnresolvedAttribute ConvertMarshalInfo(MarshalInfo marshalInfo) + IUnresolvedAttribute ConvertMarshalInfo(MarshalInfo marshalInfo) { DefaultUnresolvedAttribute attr = new DefaultUnresolvedAttribute(marshalAsAttributeTypeRef, new[] { unmanagedTypeTypeRef }); - attr.PositionalArguments.Add(new SimpleConstantValue(unmanagedTypeTypeRef, (int)marshalInfo.NativeType)); + attr.PositionalArguments.Add(CreateSimpleConstantValue(unmanagedTypeTypeRef, (int)marshalInfo.NativeType)); FixedArrayMarshalInfo fami = marshalInfo as FixedArrayMarshalInfo; if (fami != null) { - attr.AddNamedFieldArgument("SizeConst", KnownTypeReference.Int32, (int)fami.Size); + attr.AddNamedFieldArgument("SizeConst", CreateSimpleConstantValue(KnownTypeReference.Int32, (int)fami.Size)); if (fami.ElementType != NativeType.None) - attr.AddNamedFieldArgument("ArraySubType", unmanagedTypeTypeRef, (int)fami.ElementType); + attr.AddNamedFieldArgument("ArraySubType", CreateSimpleConstantValue(unmanagedTypeTypeRef, (int)fami.ElementType)); } SafeArrayMarshalInfo sami = marshalInfo as SafeArrayMarshalInfo; if (sami != null && sami.ElementType != VariantType.None) { - attr.AddNamedFieldArgument("SafeArraySubType", typeof(VarEnum).ToTypeReference(), (int)sami.ElementType); + attr.AddNamedFieldArgument("SafeArraySubType", CreateSimpleConstantValue(typeof(VarEnum).ToTypeReference(), (int)sami.ElementType)); } ArrayMarshalInfo ami = marshalInfo as ArrayMarshalInfo; if (ami != null) { if (ami.ElementType != NativeType.Max) - attr.AddNamedFieldArgument("ArraySubType", unmanagedTypeTypeRef, (int)ami.ElementType); + attr.AddNamedFieldArgument("ArraySubType", CreateSimpleConstantValue(unmanagedTypeTypeRef, (int)ami.ElementType)); if (ami.Size >= 0) - attr.AddNamedFieldArgument("SizeConst", KnownTypeReference.Int32, (int)ami.Size); + attr.AddNamedFieldArgument("SizeConst", CreateSimpleConstantValue(KnownTypeReference.Int32, (int)ami.Size)); if (ami.SizeParameterMultiplier != 0 && ami.SizeParameterIndex >= 0) - attr.AddNamedFieldArgument("SizeParamIndex", KnownTypeReference.Int16, (short)ami.SizeParameterIndex); + attr.AddNamedFieldArgument("SizeParamIndex", CreateSimpleConstantValue(KnownTypeReference.Int16, (short)ami.SizeParameterIndex)); } CustomMarshalInfo cmi = marshalInfo as CustomMarshalInfo; if (cmi != null) { - attr.AddNamedFieldArgument("MarshalType", KnownTypeReference.String, cmi.ManagedType.FullName); + attr.AddNamedFieldArgument("MarshalType", CreateSimpleConstantValue(KnownTypeReference.String, cmi.ManagedType.FullName)); if (!string.IsNullOrEmpty(cmi.Cookie)) - attr.AddNamedFieldArgument("MarshalCookie", KnownTypeReference.String, cmi.Cookie); + attr.AddNamedFieldArgument("MarshalCookie", CreateSimpleConstantValue(KnownTypeReference.String, cmi.Cookie)); } FixedSysStringMarshalInfo fssmi = marshalInfo as FixedSysStringMarshalInfo; if (fssmi != null) { - attr.AddNamedFieldArgument("SizeConst", KnownTypeReference.Int32, (int)fssmi.Size); + attr.AddNamedFieldArgument("SizeConst", CreateSimpleConstantValue(KnownTypeReference.Int32, (int)fssmi.Size)); } - return attr; + return InterningProvider.Intern(attr); } #endregion @@ -775,18 +795,15 @@ namespace ICSharpCode.NRefactory.TypeSystem throw new ArgumentNullException("attribute"); MethodReference ctor = attribute.Constructor; ITypeReference attributeType = ReadTypeReference(attribute.AttributeType); - IList ctorParameterTypes = null; + IList ctorParameterTypes = EmptyList.Instance; if (ctor.HasParameters) { ctorParameterTypes = new ITypeReference[ctor.Parameters.Count]; for (int i = 0; i < ctorParameterTypes.Count; i++) { ctorParameterTypes[i] = ReadTypeReference(ctor.Parameters[i].ParameterType); } + ctorParameterTypes = interningProvider.InternList(ctorParameterTypes); } - if (this.InterningProvider != null) { - attributeType = this.InterningProvider.Intern(attributeType); - ctorParameterTypes = this.InterningProvider.InternList(ctorParameterTypes); - } - return new CecilUnresolvedAttribute(attributeType, ctorParameterTypes ?? EmptyList.Instance, attribute.GetBlob()); + return interningProvider.Intern(new CecilUnresolvedAttribute(attributeType, ctorParameterTypes, attribute.GetBlob())); } #endregion @@ -842,11 +859,6 @@ namespace ICSharpCode.NRefactory.TypeSystem return new CecilResolvedAttribute(context, this); } - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - // We already interned our child elements in ReadAttribute(). - } - int ISupportsInterning.GetHashCodeForInterning() { return attributeType.GetHashCode() ^ ctorParameterTypes.GetHashCode() ^ GetBlobHashCode(blob); @@ -1357,11 +1369,9 @@ namespace ICSharpCode.NRefactory.TypeSystem // binary attribute uint attributeCount = reader.ReadCompressedUInt32(); UnresolvedSecurityDeclaration unresolvedSecDecl = new UnresolvedSecurityDeclaration(securityAction, blob); - if (this.InterningProvider != null) { - unresolvedSecDecl = this.InterningProvider.Intern(unresolvedSecDecl); - } + unresolvedSecDecl = interningProvider.Intern(unresolvedSecDecl); for (uint i = 0; i < attributeCount; i++) { - targetCollection.Add(new UnresolvedSecurityAttribute(unresolvedSecDecl, (int)i)); + targetCollection.Add(interningProvider.Intern(new UnresolvedSecurityAttribute(unresolvedSecDecl, (int)i))); } } else { // for backward compatibility with .NET 1.0: XML-encoded attribute @@ -1369,16 +1379,16 @@ namespace ICSharpCode.NRefactory.TypeSystem attr.ConstructorParameterTypes.Add(securityActionTypeReference); attr.PositionalArguments.Add(securityAction); string xml = System.Text.Encoding.Unicode.GetString(blob); - attr.AddNamedPropertyArgument("XML", KnownTypeReference.String, xml); - targetCollection.Add(attr); + attr.AddNamedPropertyArgument("XML", CreateSimpleConstantValue(KnownTypeReference.String, xml)); + targetCollection.Add(interningProvider.Intern(attr)); } } [Serializable, FastSerializerVersion(cecilLoaderVersion)] sealed class UnresolvedSecurityDeclaration : ISupportsInterning { - IConstantValue securityAction; - byte[] blob; + readonly IConstantValue securityAction; + readonly byte[] blob; public UnresolvedSecurityDeclaration(IConstantValue securityAction, byte[] blob) { @@ -1444,11 +1454,6 @@ namespace ICSharpCode.NRefactory.TypeSystem } } - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - securityAction = provider.Intern(securityAction); - } - int ISupportsInterning.GetHashCodeForInterning() { return securityAction.GetHashCode() ^ GetBlobHashCode(blob); @@ -1462,7 +1467,7 @@ namespace ICSharpCode.NRefactory.TypeSystem } [Serializable, FastSerializerVersion(cecilLoaderVersion)] - sealed class UnresolvedSecurityAttribute : IUnresolvedAttribute + sealed class UnresolvedSecurityAttribute : IUnresolvedAttribute, ISupportsInterning { readonly UnresolvedSecurityDeclaration secDecl; readonly int index; @@ -1482,6 +1487,17 @@ namespace ICSharpCode.NRefactory.TypeSystem { return secDecl.Resolve(context.CurrentAssembly)[index]; } + + int ISupportsInterning.GetHashCodeForInterning() + { + return index ^ secDecl.GetHashCode(); + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + UnresolvedSecurityAttribute attr = other as UnresolvedSecurityAttribute; + return attr != null && index == attr.index && secDecl == attr.secDecl; + } } #endregion #endregion @@ -1511,7 +1527,9 @@ namespace ICSharpCode.NRefactory.TypeSystem void InitTypeParameterConstraints(TypeDefinition typeDefinition, IList typeParameters) { for (int i = 0; i < typeParameters.Count; i++) { - AddConstraints((DefaultUnresolvedTypeParameter)typeParameters[i], typeDefinition.GenericParameters[i]); + var tp = (DefaultUnresolvedTypeParameter)typeParameters[i]; + AddConstraints(tp, typeDefinition.GenericParameters[i]); + tp.ApplyInterningProvider(interningProvider); } } @@ -1530,9 +1548,7 @@ namespace ICSharpCode.NRefactory.TypeSystem td.AddDefaultConstructorIfRequired = (td.Kind == TypeKind.Struct || td.Kind == TypeKind.Enum); InitMembers(typeDefinition, td, td.Members); - if (this.InterningProvider != null) { - td.ApplyInterningProvider(this.InterningProvider); - } + td.ApplyInterningProvider(interningProvider); td.Freeze(); RegisterCecilObject(td, typeDefinition); } @@ -1750,9 +1766,7 @@ namespace ICSharpCode.NRefactory.TypeSystem loader.AddAttributes(typeDefinition, this); flags[FlagHasExtensionMethods] = HasExtensionAttribute(typeDefinition); - if (loader.InterningProvider != null) { - this.ApplyInterningProvider(loader.InterningProvider); - } + this.ApplyInterningProvider(loader.interningProvider); this.Freeze(); } @@ -1895,7 +1909,9 @@ namespace ICSharpCode.NRefactory.TypeSystem EntityType.Method, i, method.GenericParameters[i].Name)); } for (int i = 0; i < method.GenericParameters.Count; i++) { - AddConstraints((DefaultUnresolvedTypeParameter)m.TypeParameters[i], method.GenericParameters[i]); + var tp = (DefaultUnresolvedTypeParameter)m.TypeParameters[i]; + AddConstraints(tp, method.GenericParameters[i]); + tp.ApplyInterningProvider(interningProvider); } } @@ -2005,7 +2021,7 @@ namespace ICSharpCode.NRefactory.TypeSystem if (parameter == null) throw new ArgumentNullException("parameter"); var type = ReadTypeReference(parameter.ParameterType, typeAttributes: parameter); - var p = new DefaultUnresolvedParameter(type, parameter.Name); + var p = new DefaultUnresolvedParameter(type, interningProvider.Intern(parameter.Name)); if (parameter.ParameterType is Mono.Cecil.ByReferenceType) { if (!parameter.IsIn && parameter.IsOut) @@ -2016,7 +2032,7 @@ namespace ICSharpCode.NRefactory.TypeSystem AddAttributes(parameter, p); if (parameter.IsOptional) { - p.DefaultValue = new SimpleConstantValue(type, parameter.Constant); + p.DefaultValue = CreateSimpleConstantValue(type, parameter.Constant); } if (parameter.ParameterType is Mono.Cecil.ArrayType) { @@ -2028,7 +2044,7 @@ namespace ICSharpCode.NRefactory.TypeSystem } } - return p; + return interningProvider.Intern(p); } #endregion @@ -2056,7 +2072,7 @@ namespace ICSharpCode.NRefactory.TypeSystem f.IsStatic = field.IsStatic; f.ReturnType = ReadTypeReference(field.FieldType, typeAttributes: field); if (field.HasConstant) { - f.ConstantValue = new SimpleConstantValue(f.ReturnType, field.Constant); + f.ConstantValue = CreateSimpleConstantValue(f.ReturnType, field.Constant); } AddAttributes(field, f); @@ -2184,13 +2200,14 @@ namespace ICSharpCode.NRefactory.TypeSystem } #endregion + #region FinishReadMember / Interning void FinishReadMember(AbstractUnresolvedMember member, MemberReference cecilDefinition) { - if (this.InterningProvider != null) - member.ApplyInterningProvider(this.InterningProvider); + member.ApplyInterningProvider(interningProvider); member.Freeze(); RegisterCecilObject(member, cecilDefinition); } + #endregion #region Type system translation table readonly Dictionary typeSystemTranslationTable; diff --git a/ICSharpCode.NRefactory/TypeSystem/IInterningProvider.cs b/ICSharpCode.NRefactory/TypeSystem/IInterningProvider.cs index 89edd7f9f4..fc97fef765 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IInterningProvider.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IInterningProvider.cs @@ -39,16 +39,64 @@ namespace ICSharpCode.NRefactory.TypeSystem /// and which are used only within a single type definition. Then a persistent file format could be organized so /// that shared objects are loaded only once, yet non-shared objects get loaded lazily together with the class. /// - public interface IInterningProvider + public abstract class InterningProvider { + public static readonly InterningProvider Dummy = new DummyInterningProvider(); + /// /// Interns the specified object. - /// The object must implement , or must be of one of the types - /// known to the interning provider to use value equality, - /// otherwise it will be returned without being interned. + /// + /// If the object is freezable, it will be frozen. + /// + public abstract ISupportsInterning Intern(ISupportsInterning obj); + + /// + /// Interns the specified object. + /// + /// If the object is freezable, it will be frozen. + /// + public T Intern(T obj) where T : class, ISupportsInterning + { + ISupportsInterning input = obj; + return (T)Intern(input); + } + + /// + /// Interns the specified string. + /// + public abstract string Intern(string text); + + /// + /// Inters a boxed value type. + /// + public abstract object InternValue(object obj); + + /// + /// Interns the given list. Uses reference equality to compare the list elements. /// - T Intern(T obj) where T : class; + public abstract IList InternList(IList list) where T : class; - IList InternList(IList list) where T : class; + sealed class DummyInterningProvider : InterningProvider + { + public override ISupportsInterning Intern(ISupportsInterning obj) + { + return obj; + } + + public override string Intern(string text) + { + return text; + } + + public override object InternValue(object obj) + { + return obj; + } + + public override IList InternList(IList list) + { + return list; + } + } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/ISupportsInterning.cs b/ICSharpCode.NRefactory/TypeSystem/ISupportsInterning.cs index 0832e33e90..21c2e1b36c 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ISupportsInterning.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ISupportsInterning.cs @@ -26,11 +26,6 @@ namespace ICSharpCode.NRefactory.TypeSystem /// public interface ISupportsInterning { - /// - /// Interns child objects and strings. - /// - void PrepareForInterning(IInterningProvider provider); - /// /// Gets a hash code for interning. /// diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs index 448a0bfd85..d9dd27c16d 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs @@ -219,7 +219,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public ITypeReference ToTypeReference() { - return new TypeParameterReference(this.OwnerType, this.Index); + return TypeParameterReference.Create(this.OwnerType, this.Index); } IEnumerable IType.GetNestedTypes(Predicate filter, GetMemberOptions options) diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractUnresolvedEntity.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractUnresolvedEntity.cs index 86a2f9a15f..d85f350bc7 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractUnresolvedEntity.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractUnresolvedEntity.cs @@ -85,7 +85,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation rareFields.FreezeInternal(); } - public virtual void ApplyInterningProvider(IInterningProvider provider) + /// + /// Uses the specified interning provider to intern + /// strings and lists in this entity. + /// This method does not test arbitrary objects to see if they implement ISupportsInterning; + /// instead we assume that those are interned immediately when they are created (before they are added to this entity). + /// + public virtual void ApplyInterningProvider(InterningProvider provider) { if (provider == null) throw new ArgumentNullException("provider"); @@ -124,7 +130,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation { } - public virtual void ApplyInterningProvider(IInterningProvider provider) + public virtual void ApplyInterningProvider(InterningProvider provider) { } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractUnresolvedMember.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractUnresolvedMember.cs index dd85fb9dc8..4baaea7386 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractUnresolvedMember.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractUnresolvedMember.cs @@ -32,10 +32,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation ITypeReference returnType = SpecialType.UnknownType; IList interfaceImplementations; - public override void ApplyInterningProvider(IInterningProvider provider) + public override void ApplyInterningProvider(InterningProvider provider) { base.ApplyInterningProvider(provider); - returnType = provider.Intern(returnType); interfaceImplementations = provider.InternList(interfaceImplementations); } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAssemblyReference.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAssemblyReference.cs index eb4795cac5..daa668a31b 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAssemblyReference.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAssemblyReference.cs @@ -29,7 +29,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public static readonly IAssemblyReference CurrentAssembly = new CurrentAssemblyReference(); public static readonly IAssemblyReference Corlib = new DefaultAssemblyReference("mscorlib"); - string shortName; + readonly string shortName; public DefaultAssemblyReference(string assemblyName) { @@ -57,11 +57,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return shortName; } - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - shortName = provider.Intern(shortName); - } - int ISupportsInterning.GetHashCodeForInterning() { unchecked { diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMemberReference.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMemberReference.cs index c82a3a3017..5a1de9bb22 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMemberReference.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMemberReference.cs @@ -33,11 +33,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation [Serializable] public sealed class DefaultMemberReference : IMemberReference, ISupportsInterning { - EntityType entityType; - ITypeReference typeReference; - string name; - int typeParameterCount; - IList parameterTypes; + readonly EntityType entityType; + readonly ITypeReference typeReference; + readonly string name; + readonly int typeParameterCount; + readonly IList parameterTypes; public DefaultMemberReference(EntityType entityType, ITypeReference typeReference, string name, int typeParameterCount = 0, IList parameterTypes = null) { @@ -99,13 +99,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return null; } - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - typeReference = provider.Intern(typeReference); - name = provider.Intern(name); - parameterTypes = provider.InternList(parameterTypes); - } - int ISupportsInterning.GetHashCodeForInterning() { return (int)entityType ^ typeReference.GetHashCode() ^ name.GetHashCode() ^ parameterTypes.GetHashCode(); diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAttribute.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAttribute.cs index 09a8b577fb..c18321b59e 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAttribute.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAttribute.cs @@ -106,11 +106,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation )); } - public void AddNamedFieldArgument(string fieldName, ITypeReference valueType, object value) - { - AddNamedFieldArgument(fieldName, new SimpleConstantValue(valueType, value)); - } - public void AddNamedPropertyArgument(string propertyName, IConstantValue value) { this.NamedArguments.Add(new KeyValuePair( @@ -119,40 +114,29 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation )); } - public void AddNamedPropertyArgument(string propertyName, ITypeReference valueType, object value) - { - AddNamedPropertyArgument(propertyName, new SimpleConstantValue(valueType, value)); - } - public IAttribute CreateResolvedAttribute(ITypeResolveContext context) { return new DefaultResolvedAttribute(this, context); } - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + int ISupportsInterning.GetHashCodeForInterning() { - if (!this.IsFrozen) { - attributeType = provider.Intern(attributeType); - constructorParameterTypes = provider.InternList(constructorParameterTypes); - positionalArguments = provider.InternList(positionalArguments); - if (namedArguments != null) { - for (int i = 0; i < namedArguments.Count; i++) { - namedArguments[i] = new KeyValuePair( - provider.Intern(namedArguments[i].Key), - provider.Intern(namedArguments[i].Value) - ); + int hash = attributeType.GetHashCode() ^ constructorParameterTypes.GetHashCode(); + unchecked { + if (constructorParameterTypes != null) { + foreach (var type in constructorParameterTypes) { + hash *= 27; + hash += type.GetHashCode(); } } - Freeze(); - } - } - - int ISupportsInterning.GetHashCodeForInterning() - { - int hash = attributeType.GetHashCode() ^ constructorParameterTypes.GetHashCode() ^ positionalArguments.GetHashCode(); - if (namedArguments != null) { - foreach (var pair in namedArguments) { - unchecked { + if (positionalArguments != null) { + foreach (var arg in positionalArguments) { + hash *= 31; + hash += arg.GetHashCode(); + } + } + if (namedArguments != null) { + foreach (var pair in namedArguments) { hash *= 71; hash += pair.Key.GetHashCode() + pair.Value.GetHashCode() * 73; } @@ -165,13 +149,33 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation { DefaultUnresolvedAttribute o = other as DefaultUnresolvedAttribute; return o != null && attributeType == o.attributeType - && constructorParameterTypes == o.constructorParameterTypes && positionalArguments == o.positionalArguments + && ListEquals(constructorParameterTypes, o.constructorParameterTypes) + && ListEquals(positionalArguments, o.positionalArguments) && ListEquals(namedArguments ?? EmptyList>.Instance, o.namedArguments ?? EmptyList>.Instance); } + static bool ListEquals(IList list1, IList list2) where T : class + { + if (list1 == null) + list1 = EmptyList.Instance; + if (list2 == null) + list2 = EmptyList.Instance; + if (list1 == list2) + return true; + if (list1.Count != list2.Count) + return false; + for (int i = 0; i < list1.Count; i++) { + if (list1[i] != list2[i]) + return false; + } + return true; + } + static bool ListEquals(IList> list1, IList> list2) { + if (list1 == list2) + return true; if (list1.Count != list2.Count) return false; for (int i = 0; i < list1.Count; i++) { diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedEvent.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedEvent.cs index 6ffc9d7635..c04a2e8b34 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedEvent.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedEvent.cs @@ -36,14 +36,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation FreezableHelper.Freeze(invokeAccessor); } - public override void ApplyInterningProvider(IInterningProvider provider) - { - base.ApplyInterningProvider(provider); - addAccessor = provider.Intern(addAccessor); - removeAccessor = provider.Intern(removeAccessor); - invokeAccessor = provider.Intern(invokeAccessor); - } - public DefaultUnresolvedEvent() { this.EntityType = EntityType.Event; diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedField.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedField.cs index 3e6406e27d..3559c8d29f 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedField.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedField.cs @@ -34,12 +34,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation base.FreezeInternal(); } - public override void ApplyInterningProvider(IInterningProvider provider) - { - base.ApplyInterningProvider(provider); - constantValue = provider.Intern(constantValue); - } - public DefaultUnresolvedField() { this.EntityType = EntityType.Field; diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedMethod.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedMethod.cs index a8afe7421e..a77317cf39 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedMethod.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedMethod.cs @@ -54,7 +54,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return copy; } - public override void ApplyInterningProvider(IInterningProvider provider) + public override void ApplyInterningProvider(InterningProvider provider) { base.ApplyInterningProvider(provider); if (provider != null) { diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedParameter.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedParameter.cs index 3a0a197de9..1ca05856ac 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedParameter.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedParameter.cs @@ -18,8 +18,8 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text; - using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.Utils; @@ -146,29 +146,30 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation get { return this.DefaultValue != null; } } - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + int ISupportsInterning.GetHashCodeForInterning() { - if (!IsFrozen) { - name = provider.Intern(name); - type = provider.Intern(type); - attributes = provider.InternList(attributes); - defaultValue = provider.Intern(defaultValue); + unchecked { + int hashCode = 1919191 ^ (flags & ~1); + hashCode *= 31; + hashCode += type.GetHashCode(); + hashCode *= 31; + hashCode += name.GetHashCode(); + hashCode += attributes != null ? attributes.Count : 0; + return hashCode; } } - int ISupportsInterning.GetHashCodeForInterning() + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) { - return type.GetHashCode() ^ name.GetHashCode() - ^ (attributes != null ? attributes.GetHashCode() : 0) - ^ (defaultValue != null ? defaultValue.GetHashCode() : 0) - ^ region.GetHashCode() ^ flags; + // compare everything except for the IsFrozen flag + DefaultUnresolvedParameter p = other as DefaultUnresolvedParameter; + return p != null && type == p.type && name == p.name && ListEquals(attributes, p.attributes) + && defaultValue == p.defaultValue && region == p.region && (flags & ~1) == (p.flags & ~1); } - bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + static bool ListEquals(IList list1, IList list2) { - DefaultUnresolvedParameter p = other as DefaultUnresolvedParameter; - return p != null && type == p.type && attributes == p.attributes && name == p.name - && defaultValue == p.defaultValue && region == p.region && flags == p.flags; + return (list1 ?? EmptyList.Instance).SequenceEqual(list2 ?? EmptyList.Instance); } public override string ToString() diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedProperty.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedProperty.cs index bdbea8897b..a133c1c6d6 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedProperty.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedProperty.cs @@ -47,11 +47,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return copy; } - public override void ApplyInterningProvider(IInterningProvider provider) + public override void ApplyInterningProvider(InterningProvider provider) { base.ApplyInterningProvider(provider); - getter = provider.Intern(getter); - setter = provider.Intern(setter); parameters = provider.InternList(parameters); } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedTypeParameter.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedTypeParameter.cs index ecc830e22c..8e8d305fe9 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedTypeParameter.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedTypeParameter.cs @@ -157,6 +157,22 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } + /// + /// Uses the specified interning provider to intern + /// strings and lists in this entity. + /// This method does not test arbitrary objects to see if they implement ISupportsInterning; + /// instead we assume that those are interned immediately when they are created (before they are added to this entity). + /// + public virtual void ApplyInterningProvider(InterningProvider provider) + { + if (provider == null) + throw new ArgumentNullException("provider"); + FreezableHelper.ThrowIfFrozen(this); + name = provider.Intern(name); + attributes = provider.InternList(attributes); + constraints = provider.InternList(constraints); + } + public virtual ITypeParameter CreateResolvedTypeParameter(ITypeResolveContext context) { IEntity owner = null; diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DummyTypeParameter.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DummyTypeParameter.cs index b95b9d66b6..22e7fc4fc8 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DummyTypeParameter.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DummyTypeParameter.cs @@ -153,7 +153,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public override ITypeReference ToTypeReference() { - return new TypeParameterReference(ownerType, index); + return TypeParameterReference.Create(ownerType, index); } public override IType AcceptVisitor(TypeVisitor visitor) diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs index e9ac4f08f0..e561b71acf 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs @@ -27,9 +27,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation [Serializable] public sealed class GetClassTypeReference : ITypeReference, ISupportsInterning { - IAssemblyReference assembly; - string nameSpace, name; - int typeParameterCount; + readonly IAssemblyReference assembly; + readonly string nameSpace, name; + readonly int typeParameterCount; /// /// Creates a new GetClassTypeReference that searches a top-level type. @@ -115,13 +115,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return name1 + "." + name2; } - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - assembly = provider.Intern(assembly); - nameSpace = provider.Intern(nameSpace); - name = provider.Intern(name); - } - int ISupportsInterning.GetHashCodeForInterning() { unchecked { diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/NestedTypeReference.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/NestedTypeReference.cs index 224f0b8194..78e0e312f6 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/NestedTypeReference.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/NestedTypeReference.cs @@ -26,9 +26,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation [Serializable] public sealed class NestedTypeReference : ITypeReference, ISupportsInterning { - ITypeReference declaringTypeRef; - string name; - int additionalTypeParameterCount; + readonly ITypeReference declaringTypeRef; + readonly string name; + readonly int additionalTypeParameterCount; /// /// Creates a new NestedTypeReference. @@ -84,12 +84,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return declaringTypeRef + "+" + name + "`" + additionalTypeParameterCount; } - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - declaringTypeRef = provider.Intern(declaringTypeRef); - name = provider.Intern(name); - } - int ISupportsInterning.GetHashCodeForInterning() { return declaringTypeRef.GetHashCode() ^ name.GetHashCode() ^ additionalTypeParameterCount; diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleConstantValue.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleConstantValue.cs index 928624c0de..43ca5662a1 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleConstantValue.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleConstantValue.cs @@ -27,8 +27,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation [Serializable] public sealed class SimpleConstantValue : IConstantValue, ISupportsInterning { - ITypeReference type; - object value; + readonly ITypeReference type; + readonly object value; public SimpleConstantValue(ITypeReference type, object value) { @@ -55,12 +55,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return value.ToString(); } - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - type = provider.Intern(type); - value = provider.Intern(value); - } - int ISupportsInterning.GetHashCodeForInterning() { return type.GetHashCode() ^ (value != null ? value.GetHashCode() : 0); diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleInterningProvider.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleInterningProvider.cs index a1bf22c37f..b6af392a9b 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleInterningProvider.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleInterningProvider.cs @@ -30,7 +30,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Simple interning provider. /// - public sealed class SimpleInterningProvider : IInterningProvider + public sealed class SimpleInterningProvider : InterningProvider { sealed class InterningComparer : IEqualityComparer { @@ -82,52 +82,52 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation Dictionary supportsInternDict = new Dictionary(new InterningComparer()); Dictionary listDict = new Dictionary(new ListComparer()); - int stackDepth = 0; - - public T Intern(T obj) where T : class + public override ISupportsInterning Intern(ISupportsInterning obj) { 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 (Type.GetTypeCode(obj.GetType()) >= TypeCode.Boolean) { - // Intern primitive types (and strings) by value - object output; - if (byValueDict.TryGetValue(obj, out output)) - obj = (T)output; - else - byValueDict.Add(obj, obj); + + ISupportsInterning output; + if (supportsInternDict.TryGetValue(obj, out output)) { + return output; + } else { + // ensure objects are frozen when we put them into the dictionary + FreezableHelper.Freeze(obj); + supportsInternDict.Add(obj, obj); + return obj; } - stackDepth--; - return obj; } - public IList InternList(IList list) where T : class + public override string Intern(string text) + { + if (text == null) + return null; + + object output; + if (byValueDict.TryGetValue(text, out output)) + return (string)output; + else + return text; + } + + public override object InternValue(object obj) + { + if (obj == null) + return null; + + object output; + if (byValueDict.TryGetValue(obj, out output)) + return output; + else + return obj; + } + + public override IList InternList(IList list) { 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) { - T[] array = new T[list.Count]; - list.CopyTo(array, 0); - list = array; - } - list[i] = newItem; - } - } + if (list.Count == 0) + return EmptyList.Instance; if (!list.IsReadOnly) list = new ReadOnlyCollection(list); IEnumerable output; diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeParameterReference.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeParameterReference.cs index 595fe2e90b..d3f39b76e9 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeParameterReference.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeParameterReference.cs @@ -18,12 +18,34 @@ using System; using System.Globalization; +using ICSharpCode.NRefactory.Utils; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { [Serializable] - public sealed class TypeParameterReference : ITypeReference, ISupportsInterning + public sealed class TypeParameterReference : ITypeReference { + static readonly TypeParameterReference[] classTypeParameterReferences = new TypeParameterReference[8]; + static readonly TypeParameterReference[] methodTypeParameterReferences = new TypeParameterReference[8]; + + /// + /// Creates a type parameter reference. + /// For common type parameter references, this method may return a shared instance. + /// + public static TypeParameterReference Create(EntityType ownerType, int index) + { + if (index >= 0 && index < 8 && (ownerType == EntityType.TypeDefinition || ownerType == EntityType.Method)) { + TypeParameterReference[] arr = (ownerType == EntityType.TypeDefinition) ? classTypeParameterReferences : methodTypeParameterReferences; + TypeParameterReference result = LazyInit.VolatileRead(ref arr[index]); + if (result == null) { + result = LazyInit.GetOrSet(ref arr[index], new TypeParameterReference(ownerType, index)); + } + return result; + } else { + return new TypeParameterReference(ownerType, index); + } + } + readonly EntityType ownerType; readonly int index; @@ -52,21 +74,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - } - - int ISupportsInterning.GetHashCodeForInterning() - { - return index * 33 + (int)ownerType; - } - - bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) - { - TypeParameterReference r = other as TypeParameterReference; - return r != null && index == r.index && ownerType == r.ownerType; - } - public override string ToString() { if (ownerType == EntityType.Method) diff --git a/ICSharpCode.NRefactory/TypeSystem/NullableType.cs b/ICSharpCode.NRefactory/TypeSystem/NullableType.cs index 204559f0e3..618962f84b 100644 --- a/ICSharpCode.NRefactory/TypeSystem/NullableType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/NullableType.cs @@ -78,7 +78,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Creates a nullable type reference. /// - public static ITypeReference Create(ITypeReference elementType) + public static ParameterizedTypeReference Create(ITypeReference elementType) { if (elementType == null) throw new ArgumentNullException("elementType"); diff --git a/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs b/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs index e42af1af1f..f62e27769c 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs @@ -341,8 +341,8 @@ namespace ICSharpCode.NRefactory.TypeSystem [Serializable] public sealed class ParameterizedTypeReference : ITypeReference, ISupportsInterning { - ITypeReference genericType; - ITypeReference[] typeArguments; + readonly ITypeReference genericType; + readonly ITypeReference[] typeArguments; public ParameterizedTypeReference(ITypeReference genericType, IEnumerable typeArguments) { @@ -402,14 +402,6 @@ namespace ICSharpCode.NRefactory.TypeSystem return b.ToString(); } - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - genericType = provider.Intern(genericType); - for (int i = 0; i < typeArguments.Length; i++) { - typeArguments[i] = provider.Intern(typeArguments[i]); - } - } - int ISupportsInterning.GetHashCodeForInterning() { int hashCode = genericType.GetHashCode(); diff --git a/ICSharpCode.NRefactory/TypeSystem/PointerType.cs b/ICSharpCode.NRefactory/TypeSystem/PointerType.cs index 37335731ff..9096a4f032 100644 --- a/ICSharpCode.NRefactory/TypeSystem/PointerType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/PointerType.cs @@ -76,7 +76,7 @@ namespace ICSharpCode.NRefactory.TypeSystem [Serializable] public sealed class PointerTypeReference : ITypeReference, ISupportsInterning { - ITypeReference elementType; + readonly ITypeReference elementType; public PointerTypeReference(ITypeReference elementType) { @@ -99,11 +99,6 @@ namespace ICSharpCode.NRefactory.TypeSystem return elementType.ToString() + "*"; } - void ISupportsInterning.PrepareForInterning(IInterningProvider provider) - { - elementType = provider.Intern(elementType); - } - int ISupportsInterning.GetHashCodeForInterning() { return elementType.GetHashCode() ^ 91725812; diff --git a/ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs b/ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs index e95c622e89..142b715990 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs @@ -106,9 +106,9 @@ namespace ICSharpCode.NRefactory.TypeSystem return new ByReferenceTypeReference(ToTypeReference(type.GetElementType())); } else if (type.IsGenericParameter) { if (type.DeclaringMethod != null) { - return new TypeParameterReference(EntityType.Method, type.GenericParameterPosition); + return TypeParameterReference.Create(EntityType.Method, type.GenericParameterPosition); } else { - return new TypeParameterReference(EntityType.TypeDefinition, type.GenericParameterPosition); + return TypeParameterReference.Create(EntityType.TypeDefinition, type.GenericParameterPosition); } } else if (type.DeclaringType != null) { if (type == typeof(Dynamic)) @@ -259,11 +259,11 @@ namespace ICSharpCode.NRefactory.TypeSystem // method type parameter reference pos++; int index = ReadTypeParameterCount(reflectionTypeName, ref pos); - reference = new TypeParameterReference(EntityType.Method, index); + reference = TypeParameterReference.Create(EntityType.Method, index); } else { // class type parameter reference int index = ReadTypeParameterCount(reflectionTypeName, ref pos); - reference = new TypeParameterReference(EntityType.TypeDefinition, index); + reference = TypeParameterReference.Create(EntityType.TypeDefinition, index); } } else { // not a type parameter reference: read the actual type name