Browse Source

Use 'UsingScopeCache' instance for caching the extension methods.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
82fad4ef64
  1. 4
      ICSharpCode.NRefactory/CSharp/Refactoring/TypeSystemAstBuilder.cs
  2. 2
      ICSharpCode.NRefactory/CSharp/Resolver/AliasNamespaceReference.cs
  3. 97
      ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs
  4. 2
      ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs
  5. 2
      ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs
  6. 6
      ICSharpCode.NRefactory/CSharp/Resolver/MethodGroupResolveResult.cs
  7. 26
      ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs
  8. 2
      ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs

4
ICSharpCode.NRefactory/CSharp/Refactoring/TypeSystemAstBuilder.cs

@ -115,7 +115,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -115,7 +115,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (resolver != null) {
// Look if there's an alias to the target type
for (UsingScope usingScope = resolver.UsingScope; usingScope != null; usingScope = usingScope.Parent) {
for (UsingScope usingScope = resolver.CurrentUsingScope; usingScope != null; usingScope = usingScope.Parent) {
foreach (var pair in usingScope.UsingAliases) {
IType type = pair.Value.Resolve(resolver.Context);
if (TypeMatches(type, typeDef, typeArguments))
@ -200,7 +200,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -200,7 +200,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
if (resolver != null) {
// Look if there's an alias to the target namespace
for (UsingScope usingScope = resolver.UsingScope; usingScope != null; usingScope = usingScope.Parent) {
for (UsingScope usingScope = resolver.CurrentUsingScope; usingScope != null; usingScope = usingScope.Parent) {
foreach (var pair in usingScope.UsingAliases) {
// maybe add some caching? we're resolving all aliases N times when converting a namespace name with N parts
NamespaceResolveResult nrr = pair.Value.ResolveNamespace(resolver.Context);

2
ICSharpCode.NRefactory/CSharp/Resolver/AliasNamespaceReference.cs

@ -45,7 +45,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -45,7 +45,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public ResolveResult DoResolve(ITypeResolveContext context)
{
CSharpResolver r = new CSharpResolver(context);
r.UsingScope = parentUsingScope;
r.CurrentUsingScope = parentUsingScope;
return r.ResolveAlias(identifier);
}

97
ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
@ -25,6 +26,7 @@ using System.Text; @@ -25,6 +26,7 @@ using System.Text;
using System.Threading;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.CSharp.Resolver
{
@ -82,10 +84,67 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -82,10 +84,67 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary>
public ITypeDefinition CurrentTypeDefinition { get; set; }
UsingScopeCache currentUsingScope;
/// <summary>
/// Gets/Sets the current using scope that is used to look up identifiers as class names.
/// </summary>
public UsingScope UsingScope { get; set; }
public UsingScope CurrentUsingScope {
get { return currentUsingScope != null ? currentUsingScope.UsingScope : null; }
set {
if (value == null) {
currentUsingScope = null;
} else {
if (currentUsingScope != null && currentUsingScope.UsingScope == value)
return;
CacheManager cache = context.CacheManager;
if (cache != null) {
object obj;
if (cache.Dictionary.TryGetValue(value, out obj)) {
currentUsingScope = (UsingScopeCache)obj;
} else {
currentUsingScope = new UsingScopeCache(value);
cache.Dictionary.TryAdd(value, currentUsingScope);
}
} else {
currentUsingScope = new UsingScopeCache(value);
}
}
}
}
/// <summary>
/// Gets the current project content.
/// Returns <c>CurrentUsingScope.ProjectContent</c>.
/// </summary>
public IProjectContent ProjectContent {
get {
if (currentUsingScope != null)
return currentUsingScope.UsingScope.ProjectContent;
else
return null;
}
}
#endregion
#region Per-UsingScope Cache
/// <summary>
/// There is one cache instance per using scope; and it might be shared between multiple resolvers
/// that are on different threads, so it must be thread-safe.
/// </summary>
sealed class UsingScopeCache
{
public readonly UsingScope UsingScope;
public volatile List<List<IMethod>> AllExtensionMethods;
public UsingScopeCache(UsingScope usingScope)
{
this.UsingScope = usingScope;
}
}
#endregion
#region Local Variable Management
@ -1910,6 +1969,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1910,6 +1969,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (parameterizeResultType && typeArguments.All(t => t.Kind == TypeKind.UnboundTypeArgument))
parameterizeResultType = false;
ResolveResult r;
// look in current type definitions
for (ITypeDefinition t = this.CurrentTypeDefinition; t != null; t = t.DeclaringTypeDefinition) {
if (k == 0) {
@ -1928,7 +1988,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1928,7 +1988,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
MemberLookup lookup = new MemberLookup(context, t, t.ProjectContent);
ResolveResult r;
if (lookupMode == SimpleNameLookupMode.Expression || lookupMode == SimpleNameLookupMode.InvocationTarget) {
r = lookup.Lookup(new TypeResolveResult(t), identifier, typeArguments, lookupMode == SimpleNameLookupMode.InvocationTarget);
} else {
@ -1939,7 +1998,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1939,7 +1998,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
// look in current namespace definitions
for (UsingScope n = this.UsingScope; n != null; n = n.Parent) {
for (UsingScope n = this.CurrentUsingScope; n != null; n = n.Parent) {
// first look for a namespace
if (k == 0) {
string fullName = NamespaceDeclaration.BuildQualifiedName(n.NamespaceName, identifier);
@ -1966,7 +2025,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1966,7 +2025,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (n.ExternAliases.Contains(identifier)) {
return ResolveExternAlias(identifier);
}
if (lookupMode != SimpleNameLookupMode.TypeInUsingDeclaration || n != this.UsingScope) {
if (lookupMode != SimpleNameLookupMode.TypeInUsingDeclaration || n != this.CurrentUsingScope) {
foreach (var pair in n.UsingAliases) {
if (pair.Key == identifier) {
NamespaceResolveResult ns = pair.Value.ResolveNamespace(context);
@ -1979,7 +2038,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1979,7 +2038,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
// finally, look in the imported namespaces:
if (lookupMode != SimpleNameLookupMode.TypeInUsingDeclaration || n != this.UsingScope) {
if (lookupMode != SimpleNameLookupMode.TypeInUsingDeclaration || n != this.CurrentUsingScope) {
IType firstResult = null;
foreach (var u in n.Usings) {
NamespaceResolveResult ns = u.ResolveNamespace(context);
@ -2020,7 +2079,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2020,7 +2079,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (identifier == "global")
return new NamespaceResolveResult(string.Empty);
for (UsingScope n = this.UsingScope; n != null; n = n.Parent) {
for (UsingScope n = this.CurrentUsingScope; n != null; n = n.Parent) {
if (n.ExternAliases.Contains(identifier)) {
return ResolveExternAlias(identifier);
}
@ -2033,7 +2092,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2033,7 +2092,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return ErrorResult;
}
ResolveResult ResolveExternAlias(string alias)
static ResolveResult ResolveExternAlias(string alias)
{
// TODO: implement extern alias support
return new NamespaceResolveResult(string.Empty);
@ -2069,7 +2128,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2069,7 +2128,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (mgrr != null) {
Debug.Assert(mgrr.extensionMethods == null);
// set the values that are necessary to make MethodGroupResolveResult.GetExtensionMethods() work
mgrr.usingScope = this.UsingScope;
mgrr.usingScope = this.CurrentUsingScope;
mgrr.resolver = this;
}
}
@ -2115,7 +2174,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2115,7 +2174,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary>
public MemberLookup CreateMemberLookup()
{
return new MemberLookup(context, this.CurrentTypeDefinition, this.UsingScope != null ? this.UsingScope.ProjectContent : null);
return new MemberLookup(context, this.CurrentTypeDefinition, this.ProjectContent);
}
#endregion
@ -2178,17 +2237,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2178,17 +2237,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// Gets all extension methods available in the current using scope.
/// This list includes unaccessible
/// </summary>
List<List<IMethod>> GetAllExtensionMethods()
{
// TODO: maybe cache the result?
// Idea: class ExtensionMethodGroupCache : List<List<IMethod>>
// a new ExtensionMethodGroupCache instance would be created whenever the UsingScope is changed
// The list contents would be initialized on-demand.
// Because cloning the resolver would re-use the cache, it must be thread-safe.
// The cache could be passed to the MethodGroupResolveResult instead of passing the resolver.
List<List<IMethod>> extensionMethodGroups = new List<List<IMethod>>();
IList<List<IMethod>> GetAllExtensionMethods()
{
if (currentUsingScope == null)
return EmptyList<List<IMethod>>.Instance;
List<List<IMethod>> extensionMethodGroups = currentUsingScope.AllExtensionMethods;
if (extensionMethodGroups != null)
return extensionMethodGroups;
extensionMethodGroups = new List<List<IMethod>>();
List<IMethod> m;
for (UsingScope scope = this.UsingScope; scope != null; scope = scope.Parent) {
for (UsingScope scope = currentUsingScope.UsingScope; scope != null; scope = scope.Parent) {
m = GetExtensionMethods(scope.NamespaceName).ToList();
if (m.Count > 0)
extensionMethodGroups.Add(m);
@ -2202,6 +2260,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2202,6 +2260,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (m.Count > 0)
extensionMethodGroups.Add(m);
}
currentUsingScope.AllExtensionMethods = extensionMethodGroups;
return extensionMethodGroups;
}

2
ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs

@ -53,7 +53,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues @@ -53,7 +53,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues
return new CSharpResolver(context) {
CheckForOverflow = false, // TODO: get project-wide overflow setting
CurrentTypeDefinition = parentTypeDefinition,
UsingScope = parentUsingScope
CurrentUsingScope = parentUsingScope
};
}

2
ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs

@ -71,7 +71,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -71,7 +71,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return targetRR;
CSharpResolver r = new CSharpResolver(context);
r.CurrentTypeDefinition = parentTypeDefinition;
r.UsingScope = parentUsingScope;
r.CurrentUsingScope = parentUsingScope;
IType[] typeArgs = new IType[typeArguments.Count];
for (int i = 0; i < typeArgs.Length; i++) {
typeArgs[i] = typeArguments[i].Resolve(context);

6
ICSharpCode.NRefactory/CSharp/Resolver/MethodGroupResolveResult.cs

@ -138,12 +138,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -138,12 +138,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
if (resolver != null) {
Debug.Assert(extensionMethods == null);
UsingScope oldUsingScope = resolver.UsingScope;
UsingScope oldUsingScope = resolver.CurrentUsingScope;
try {
resolver.UsingScope = usingScope;
resolver.CurrentUsingScope = usingScope;
extensionMethods = resolver.GetExtensionMethods(this.TargetType, methodName, typeArguments);
} finally {
resolver.UsingScope = oldUsingScope;
resolver.CurrentUsingScope = oldUsingScope;
resolver = null;
usingScope = null;
}

26
ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs

@ -357,31 +357,31 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -357,31 +357,31 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#region Track UsingScope
public override ResolveResult VisitCompilationUnit(CompilationUnit unit, object data)
{
UsingScope previousUsingScope = resolver.UsingScope;
UsingScope previousUsingScope = resolver.CurrentUsingScope;
try {
if (parsedFile != null)
resolver.UsingScope = parsedFile.RootUsingScope;
resolver.CurrentUsingScope = parsedFile.RootUsingScope;
ScanChildren(unit);
return voidResult;
} finally {
resolver.UsingScope = previousUsingScope;
resolver.CurrentUsingScope = previousUsingScope;
}
}
public override ResolveResult VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data)
{
UsingScope previousUsingScope = resolver.UsingScope;
UsingScope previousUsingScope = resolver.CurrentUsingScope;
try {
if (parsedFile != null) {
resolver.UsingScope = parsedFile.GetUsingScope(namespaceDeclaration.StartLocation);
resolver.CurrentUsingScope = parsedFile.GetUsingScope(namespaceDeclaration.StartLocation);
}
ScanChildren(namespaceDeclaration);
if (resolver.UsingScope != null)
return new NamespaceResolveResult(resolver.UsingScope.NamespaceName);
if (resolver.CurrentUsingScope != null)
return new NamespaceResolveResult(resolver.CurrentUsingScope.NamespaceName);
else
return null;
} finally {
resolver.UsingScope = previousUsingScope;
resolver.CurrentUsingScope = previousUsingScope;
}
}
#endregion
@ -782,11 +782,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -782,11 +782,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public override ResolveResult VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression, object data)
{
// 7.6.10.6 Anonymous object creation expressions
if (resolver.UsingScope == null) {
if (resolver.ProjectContent == null) {
ScanChildren(anonymousTypeCreateExpression);
return errorResult;
}
var anonymousType = new DefaultTypeDefinition(resolver.UsingScope.ProjectContent, string.Empty, "$Anonymous$");
var anonymousType = new DefaultTypeDefinition(resolver.ProjectContent, string.Empty, "$Anonymous$");
anonymousType.IsSynthetic = true;
resolver.PushInitializerType(anonymousType);
foreach (var expr in anonymousTypeCreateExpression.Initializers) {
@ -2100,7 +2100,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2100,7 +2100,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
IConstantValue cv = null;
if (isConst) {
cv = TypeSystemConvertVisitor.ConvertConstantValue(type, vi.Initializer, resolver.CurrentTypeDefinition, resolver.CurrentMember as IMethod, resolver.UsingScope);
cv = TypeSystemConvertVisitor.ConvertConstantValue(type, vi.Initializer, resolver.CurrentTypeDefinition, resolver.CurrentMember as IMethod, resolver.CurrentUsingScope);
}
resolver.AddVariable(type, MakeRegion(vi), vi.Name, cv);
@ -2299,7 +2299,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2299,7 +2299,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ITypeReference MakeTypeReference(AstType type)
{
return TypeSystemConvertVisitor.ConvertType(type, resolver.CurrentTypeDefinition, resolver.CurrentMember as IMethod, resolver.UsingScope, currentTypeLookupMode);
return TypeSystemConvertVisitor.ConvertType(type, resolver.CurrentTypeDefinition, resolver.CurrentMember as IMethod, resolver.CurrentUsingScope, currentTypeLookupMode);
}
sealed class VarTypeReference : ITypeReference
@ -2440,7 +2440,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2440,7 +2440,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ResolveResult HandleAttributeType(AstType astType)
{
ScanChildren(astType);
IType type = TypeSystemConvertVisitor.ConvertAttributeType(astType, resolver.CurrentTypeDefinition, resolver.CurrentMember as IMethod, resolver.UsingScope).Resolve(resolver.Context);
IType type = TypeSystemConvertVisitor.ConvertAttributeType(astType, resolver.CurrentTypeDefinition, resolver.CurrentMember as IMethod, resolver.CurrentUsingScope).Resolve(resolver.Context);
if (type.Kind != TypeKind.Unknown)
return new TypeResolveResult(type);
else

2
ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs

@ -66,7 +66,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -66,7 +66,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
CSharpResolver r = new CSharpResolver(context);
r.CurrentTypeDefinition = parentTypeDefinition;
r.UsingScope = parentUsingScope;
r.CurrentUsingScope = parentUsingScope;
IType[] typeArgs = new IType[typeArguments.Count];
for (int i = 0; i < typeArgs.Length; i++) {
typeArgs[i] = typeArguments[i].Resolve(context);

Loading…
Cancel
Save