Browse Source

Fixed SD2-1510: Too slow startup when DesignerViewContent.cs was open

(different solution to the problem, the previous commit introduced errors)

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3769 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 17 years ago
parent
commit
aef5688593
  1. 51
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultClass.cs
  2. 21
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/SearchClassReturnType.cs
  3. 20
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryASTConvertVisitor.cs
  4. 41
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/TypeVisitor.cs
  5. 35
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/IProjectContent.cs

51
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultClass.cs

@ -374,13 +374,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -374,13 +374,7 @@ namespace ICSharpCode.SharpDevelop.Dom
return CompareTo((IClass)o);
}
sealed class InheritanceTreeCache
{
internal IClass[] inheritanceTree;
internal bool isCreating;
}
volatile InheritanceTreeCache inheritanceTreeCache;
volatile IClass[] inheritanceTreeCache;
public IEnumerable<IClass> ClassInheritanceTree {
get {
@ -392,47 +386,24 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -392,47 +386,24 @@ namespace ICSharpCode.SharpDevelop.Dom
// Especially the recursive calls are tricky, this has caused incorrect behavior (SD2-1474)
// or performance problems (SD2-1510) in the past.
// get the inheritanceTreeCache, creating it if required
// (on demand-creation saves memory - lots of classes never need a ClassInheritanceTree)
InheritanceTreeCache inheritanceTreeCache = this.inheritanceTreeCache;
if (inheritanceTreeCache == null) {
// but ensure only one is created, even when ClassInheritanceTree is called by multiple threads
InheritanceTreeCache newCache = new InheritanceTreeCache();
#pragma warning disable 420
// Warning CS0420: 'ICSharpCode.SharpDevelop.Dom.DefaultClass.inheritanceTreeCache': a reference to a volatile field will not be treated as volatile
// We disable this warning because Interlocked.* treats the location as volatile, even though
// normally ref-parameters in C# lose the volatile modifier.
inheritanceTreeCache = Interlocked.CompareExchange(ref this.inheritanceTreeCache, newCache, null) ?? newCache;
#pragma warning restore 420
}
// now we have the inheritanceTreeCache -> lock on it
lock (inheritanceTreeCache) {
if (inheritanceTreeCache.inheritanceTree == null) {
// inheritance tree does not exist yet
if (inheritanceTreeCache.isCreating) {
// this is a recursive call -> don't produce inheritance tree
return EmptyList<IClass>.Instance;
} else {
// now produce the actual inheritance tree
inheritanceTreeCache.isCreating = true;
inheritanceTreeCache.inheritanceTree = CalculateClassInheritanceTree();
inheritanceTreeCache.isCreating = false;
IClass[] inheritanceTree = this.inheritanceTreeCache;
if (inheritanceTree != null) {
return inheritanceTree;
}
inheritanceTree = CalculateClassInheritanceTree();
this.inheritanceTreeCache = inheritanceTree;
if (!KeepInheritanceTree)
DomCache.RegisterForClear(ClearCachedInheritanceTree);
}
}
return inheritanceTreeCache.inheritanceTree;
}
return inheritanceTree;
}
}
void ClearCachedInheritanceTree()
{
lock (inheritanceTreeCache) {
inheritanceTreeCache.inheritanceTree = null;
}
inheritanceTreeCache = null;
}
IClass[] CalculateClassInheritanceTree()

21
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/SearchClassReturnType.cs

@ -24,6 +24,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -24,6 +24,7 @@ namespace ICSharpCode.SharpDevelop.Dom
string name;
string shortName;
int typeParameterCount;
bool lookForInnerClassesInDeclaringClass = true;
public SearchClassReturnType(IProjectContent projectContent, IClass declaringClass, int caretLine, int caretColumn, string name, int typeParameterCount)
{
@ -42,6 +43,19 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -42,6 +43,19 @@ namespace ICSharpCode.SharpDevelop.Dom
shortName = name.Substring(pos + 1);
}
/// <summary>
/// Gets/Sets whether to look for inner classes in the declaring class.
/// The default is true.
/// Set this property to false for return types that are used as base type references.
/// </summary>
public bool LookForInnerClassesInDeclaringClass {
get { return lookForInnerClassesInDeclaringClass; }
set {
lookForInnerClassesInDeclaringClass = value;
ClearCachedBaseType();
}
}
volatile IReturnType cachedBaseType;
int isSearching; // 0=false, 1=true
@ -58,7 +72,12 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -58,7 +72,12 @@ namespace ICSharpCode.SharpDevelop.Dom
if (Interlocked.CompareExchange(ref isSearching, 1, 0) != 0)
return null;
try {
type = pc.SearchType(new SearchTypeRequest(name, typeParameterCount, declaringClass, caretLine, caretColumn)).Result;
SearchTypeRequest request = new SearchTypeRequest(name, typeParameterCount, declaringClass, caretLine, caretColumn);
if (!lookForInnerClassesInDeclaringClass) {
// skip looking for inner classes by adjusting the CurrentType for the lookup
request.CurrentType = declaringClass.DeclaringType;
}
type = pc.SearchType(request).Result;
cachedBaseType = type;
if (type != null)
DomCache.RegisterForClear(ClearCachedBaseType);

20
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryASTConvertVisitor.cs

@ -388,7 +388,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -388,7 +388,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
if (c.ClassType != ClassType.Enum && typeDeclaration.BaseTypes != null) {
foreach (AST.TypeReference type in typeDeclaration.BaseTypes) {
IReturnType rt = CreateReturnType(type);
IReturnType rt = CreateReturnType(type, null, TypeVisitor.ReturnTypeOptions.BaseTypeReference);
if (rt != null) {
c.BaseTypes.Add(rt);
}
@ -508,7 +508,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -508,7 +508,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
internal static IParameter CreateParameter(AST.ParameterDeclarationExpression par, IMethod method, IClass currentClass, ICompilationUnit cu)
{
IReturnType parType = CreateReturnType(par.TypeReference, method, currentClass, cu);
IReturnType parType = CreateReturnType(par.TypeReference, method, currentClass, cu, TypeVisitor.ReturnTypeOptions.None);
DefaultParameter p = new DefaultParameter(par.ParameterName, parType, GetRegion(par.StartLocation, par.EndLocation));
p.Modifiers = (ParameterModifiers)par.ParamModifier;
return p;
@ -524,7 +524,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -524,7 +524,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
method.IsExtensionMethod = methodDeclaration.IsExtensionMethod;
method.Documentation = GetDocumentation(region.BeginLine, methodDeclaration.Attributes);
ConvertTemplates(methodDeclaration.Templates, method);
method.ReturnType = CreateReturnType(methodDeclaration.TypeReference, method);
method.ReturnType = CreateReturnType(methodDeclaration.TypeReference, method, TypeVisitor.ReturnTypeOptions.None);
ConvertAttributes(methodDeclaration, method);
if (methodDeclaration.Parameters.Count > 0) {
foreach (AST.ParameterDeclarationExpression par in methodDeclaration.Parameters) {
@ -559,7 +559,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -559,7 +559,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
method.Documentation = GetDocumentation(region.BeginLine, declareDeclaration.Attributes);
method.Modifiers |= ModifierEnum.Extern | ModifierEnum.Static;
method.ReturnType = CreateReturnType(declareDeclaration.TypeReference, method);
method.ReturnType = CreateReturnType(declareDeclaration.TypeReference, method, TypeVisitor.ReturnTypeOptions.None);
ConvertAttributes(declareDeclaration, method);
foreach (AST.ParameterDeclarationExpression par in declareDeclaration.Parameters) {
@ -753,23 +753,23 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -753,23 +753,23 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
return null;
}
IReturnType CreateReturnType(AST.TypeReference reference, IMethod method)
IReturnType CreateReturnType(AST.TypeReference reference, IMethod method, TypeVisitor.ReturnTypeOptions options)
{
return CreateReturnType(reference, method, GetCurrentClass(), cu);
return CreateReturnType(reference, method, GetCurrentClass(), cu, options);
}
static IReturnType CreateReturnType(AST.TypeReference reference, IMethod method, IClass currentClass, ICompilationUnit cu)
static IReturnType CreateReturnType(AST.TypeReference reference, IMethod method, IClass currentClass, ICompilationUnit cu, TypeVisitor.ReturnTypeOptions options)
{
if (currentClass == null) {
return TypeVisitor.CreateReturnType(reference, new DefaultClass(cu, "___DummyClass"), method, 1, 1, cu.ProjectContent, true);
return TypeVisitor.CreateReturnType(reference, new DefaultClass(cu, "___DummyClass"), method, 1, 1, cu.ProjectContent, options | TypeVisitor.ReturnTypeOptions.Lazy);
} else {
return TypeVisitor.CreateReturnType(reference, currentClass, method, currentClass.Region.BeginLine + 1, 1, cu.ProjectContent, true);
return TypeVisitor.CreateReturnType(reference, currentClass, method, currentClass.Region.BeginLine + 1, 1, cu.ProjectContent, options | TypeVisitor.ReturnTypeOptions.Lazy);
}
}
IReturnType CreateReturnType(AST.TypeReference reference)
{
return CreateReturnType(reference, null);
return CreateReturnType(reference, null, TypeVisitor.ReturnTypeOptions.None);
}
}
}

41
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/TypeVisitor.cs

@ -20,24 +20,47 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -20,24 +20,47 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
// TODO: Rename this class, the visitor functionality was moved to ResolveVisitor
public static class TypeVisitor
{
[Flags]
public enum ReturnTypeOptions
{
None = 0,
Lazy = 1,
BaseTypeReference = 2
}
public static IReturnType CreateReturnType(TypeReference reference, NRefactoryResolver resolver)
{
return CreateReturnType(reference,
resolver.CallingClass, resolver.CallingMember,
resolver.CaretLine, resolver.CaretColumn,
resolver.ProjectContent, false);
resolver.ProjectContent, ReturnTypeOptions.None);
}
[Obsolete("Use the overload with ReturnTypeOptions instead")]
public static IReturnType CreateReturnType(TypeReference reference, IClass callingClass,
IMember callingMember, int caretLine, int caretColumn,
IProjectContent projectContent,
bool useLazyReturnType)
{
return CreateReturnType(reference, callingClass, callingMember, caretLine, caretColumn,
projectContent,
useLazyReturnType ? ReturnTypeOptions.Lazy : ReturnTypeOptions.None);
}
public static IReturnType CreateReturnType(TypeReference reference, IClass callingClass,
IMember callingMember, int caretLine, int caretColumn,
IProjectContent projectContent,
ReturnTypeOptions options)
{
if (reference == null) return null;
if (reference.IsNull) return null;
if (reference is InnerClassTypeReference) {
reference = ((InnerClassTypeReference)reference).CombineToNormalTypeReference();
}
bool useLazyReturnType = (options & ReturnTypeOptions.Lazy) == ReturnTypeOptions.Lazy;
bool isBaseTypeReference = (options & ReturnTypeOptions.BaseTypeReference) == ReturnTypeOptions.BaseTypeReference;
LanguageProperties languageProperties = projectContent.Language;
IReturnType t = null;
if (callingClass != null && !reference.IsGlobal) {
@ -57,7 +80,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -57,7 +80,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
}
}
if (t == null) {
if (reference.Type != reference.Type) {
if (reference.IsKeyword) {
// keyword-type like void, int, string etc.
IClass c = projectContent.GetClass(reference.Type, 0);
if (c != null)
@ -66,11 +89,15 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -66,11 +89,15 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
t = new GetClassReturnType(projectContent, reference.Type, 0);
} else {
int typeParameterCount = reference.GenericTypes.Count;
if (useLazyReturnType) {
if (reference.IsGlobal || reference.IsKeyword)
if (useLazyReturnType || isBaseTypeReference) {
if (reference.IsGlobal) {
t = new GetClassReturnType(projectContent, reference.Type, typeParameterCount);
else if (callingClass != null)
t = new SearchClassReturnType(projectContent, callingClass, caretLine, caretColumn, reference.Type, typeParameterCount);
} else if (callingClass != null) {
SearchClassReturnType scrt = new SearchClassReturnType(projectContent, callingClass, caretLine, caretColumn, reference.Type, typeParameterCount);
if (isBaseTypeReference)
scrt.LookForInnerClassesInDeclaringClass = false;
t = scrt;
}
} else {
IClass c;
if (reference.IsGlobal || reference.IsKeyword) {
@ -88,7 +115,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -88,7 +115,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
if (reference.GenericTypes.Count > 0) {
List<IReturnType> para = new List<IReturnType>(reference.GenericTypes.Count);
for (int i = 0; i < reference.GenericTypes.Count; ++i) {
para.Add(CreateReturnType(reference.GenericTypes[i], callingClass, callingMember, caretLine, caretColumn, projectContent, useLazyReturnType));
para.Add(CreateReturnType(reference.GenericTypes[i], callingClass, callingMember, caretLine, caretColumn, projectContent, options));
}
t = new ConstructedReturnType(t, para);
}

35
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/IProjectContent.cs

@ -138,15 +138,34 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -138,15 +138,34 @@ namespace ICSharpCode.SharpDevelop.Dom
Default = LookInReferences | LookForInnerClass
}
public struct SearchTypeRequest
public sealed class SearchTypeRequest
{
public readonly string Name;
public readonly int TypeParameterCount;
public readonly ICompilationUnit CurrentCompilationUnit;
public readonly IClass CurrentType;
public readonly int CaretLine;
public readonly int CaretColumn;
public readonly IUsingScope CurrentUsingScope;
IUsingScope currentUsingScope;
ICompilationUnit currentCompilationUnit;
public string Name { get; set; }
public int TypeParameterCount { get; set; }
public IClass CurrentType { get; set; }
public int CaretLine { get; set; }
public int CaretColumn { get; set; }
public ICompilationUnit CurrentCompilationUnit {
get { return currentCompilationUnit; }
set {
if (value == null)
throw new ArgumentNullException("CurrentCompilationUnit");
currentCompilationUnit = value;
}
}
public IUsingScope CurrentUsingScope {
get { return currentUsingScope; }
set {
if (value == null)
throw new ArgumentNullException("CurrentUsingScope");
currentUsingScope = value;
}
}
public SearchTypeRequest(string name, int typeParameterCount, IClass currentType, int caretLine, int caretColumn)
{

Loading…
Cancel
Save