From 925837dee860effdef9b466f7c3f5ddf37fef98c Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Tue, 18 Sep 2012 00:31:58 +0200 Subject: [PATCH] Implemented TopLevelTypeDefinitionModelCollection. --- .../Base/Project/Dom/ConcatModelCollection.cs | 11 --- src/Main/Base/Project/Dom/IModelCollection.cs | 2 +- src/Main/Base/Project/Dom/IModelFactory.cs | 2 +- .../Base/Project/Dom/ITypeDefinitionModel.cs | 5 + .../Dom/ITypeDefinitionModelCollection.cs | 16 ++- .../Base/Project/Dom/KeyedModelCollection.cs | 3 + .../Project/Src/Project/CompilableProject.cs | 2 +- src/Main/Base/Test/Dom/CSharpModelTests.cs | 8 ++ src/Main/SharpDevelop/Dom/ModelFactory.cs | 2 +- .../TopLevelTypeDefinitionModelCollection.cs | 99 +++++++++++++++++-- .../SharpDevelop/Dom/TypeDefinitionModel.cs | 44 +++------ 11 files changed, 133 insertions(+), 61 deletions(-) diff --git a/src/Main/Base/Project/Dom/ConcatModelCollection.cs b/src/Main/Base/Project/Dom/ConcatModelCollection.cs index eeb5b7d013..3158a9845b 100644 --- a/src/Main/Base/Project/Dom/ConcatModelCollection.cs +++ b/src/Main/Base/Project/Dom/ConcatModelCollection.cs @@ -152,16 +152,5 @@ namespace ICSharpCode.SharpDevelop.Dom { return GetEnumerator(); } - - public T this[int index] { - get { - int inputIndex = 0; - while (index >= inputs[inputIndex].Count) { - index -= inputs[inputIndex].Count; - inputIndex++; - } - return inputs[inputIndex][index]; - } - } } } diff --git a/src/Main/Base/Project/Dom/IModelCollection.cs b/src/Main/Base/Project/Dom/IModelCollection.cs index b5ce0e7f66..3f251e7bab 100644 --- a/src/Main/Base/Project/Dom/IModelCollection.cs +++ b/src/Main/Base/Project/Dom/IModelCollection.cs @@ -10,7 +10,7 @@ namespace ICSharpCode.SharpDevelop.Dom /// /// A read-only collection that provides change notifications. /// - public interface IModelCollection : IReadOnlyList, INotifyCollectionChanged + public interface IModelCollection : IReadOnlyCollection, INotifyCollectionChanged { } } diff --git a/src/Main/Base/Project/Dom/IModelFactory.cs b/src/Main/Base/Project/Dom/IModelFactory.cs index 357cb18906..27822fbdc2 100644 --- a/src/Main/Base/Project/Dom/IModelFactory.cs +++ b/src/Main/Base/Project/Dom/IModelFactory.cs @@ -16,7 +16,7 @@ namespace ICSharpCode.SharpDevelop.Dom /// /// Creates an empty type definition collection that holds the top-level types for a project. /// - IMutableTypeDefinitionModelCollection CreateTopLevelTypeDefinitionCollection(IEntityModelContext context); + ITypeDefinitionModelCollection CreateTopLevelTypeDefinitionCollection(IEntityModelContext context); ITypeDefinitionModel CreateTypeDefinitionModel(IEntityModelContext context, params IUnresolvedTypeDefinition[] parts); IMemberModel CreateMemberModel(IEntityModelContext context, IUnresolvedMember member); diff --git a/src/Main/Base/Project/Dom/ITypeDefinitionModel.cs b/src/Main/Base/Project/Dom/ITypeDefinitionModel.cs index c0e10383ba..704254611d 100644 --- a/src/Main/Base/Project/Dom/ITypeDefinitionModel.cs +++ b/src/Main/Base/Project/Dom/ITypeDefinitionModel.cs @@ -27,5 +27,10 @@ namespace ICSharpCode.SharpDevelop.Dom /// Returns null if the type definition could not be resolved. /// new ITypeDefinition Resolve(ISolutionSnapshotWithProjectMapping solutionSnapshot); + + /// + /// Retrieves + /// + ITypeDefinitionModel GetNestedType(string name, int atpc); } } diff --git a/src/Main/Base/Project/Dom/ITypeDefinitionModelCollection.cs b/src/Main/Base/Project/Dom/ITypeDefinitionModelCollection.cs index 94e9ee0c84..ddffe89e64 100644 --- a/src/Main/Base/Project/Dom/ITypeDefinitionModelCollection.cs +++ b/src/Main/Base/Project/Dom/ITypeDefinitionModelCollection.cs @@ -27,10 +27,7 @@ namespace ICSharpCode.SharpDevelop.Dom /// Returns null if no such model object exists. /// ITypeDefinitionModel this[TopLevelTypeName topLevelTypeName] { get; } - } - - public interface IMutableTypeDefinitionModelCollection : ITypeDefinitionModelCollection, IList - { + /// /// Updates the collection when the parse information has changed. /// @@ -54,12 +51,6 @@ namespace ICSharpCode.SharpDevelop.Dom get { return null; } } - ITypeDefinitionModel IReadOnlyList.this[int index] { - get { - throw new ArgumentOutOfRangeException(); - } - } - int IReadOnlyCollection.Count { get { return 0; } } @@ -73,5 +64,10 @@ namespace ICSharpCode.SharpDevelop.Dom { return Enumerable.Empty().GetEnumerator(); } + + void ITypeDefinitionModelCollection.Update(IUnresolvedFile oldFile, IUnresolvedFile newFile) + { + throw new NotSupportedException(); + } } } diff --git a/src/Main/Base/Project/Dom/KeyedModelCollection.cs b/src/Main/Base/Project/Dom/KeyedModelCollection.cs index 6aa1a0e42c..f53bcd52b7 100644 --- a/src/Main/Base/Project/Dom/KeyedModelCollection.cs +++ b/src/Main/Base/Project/Dom/KeyedModelCollection.cs @@ -12,6 +12,9 @@ namespace ICSharpCode.SharpDevelop.Dom /// public abstract class KeyedModelCollection : KeyedCollection, IModelCollection { + // TODO: do we still need this class? maybe we should remove it? + // It's less useful than I initially thought because the indexer throws exceptions and there's no TryGetValue + protected override void ClearItems() { base.ClearItems(); diff --git a/src/Main/Base/Project/Src/Project/CompilableProject.cs b/src/Main/Base/Project/Src/Project/CompilableProject.cs index 679f032473..4dd2ddcdb5 100644 --- a/src/Main/Base/Project/Src/Project/CompilableProject.cs +++ b/src/Main/Base/Project/Src/Project/CompilableProject.cs @@ -346,7 +346,7 @@ namespace ICSharpCode.SharpDevelop.Project #region Type System volatile ProjectContentContainer projectContentContainer; - IMutableTypeDefinitionModelCollection typeDefinitionModels; + ITypeDefinitionModelCollection typeDefinitionModels; protected void InitializeProjectContent(IProjectContent initialProjectContent) { diff --git a/src/Main/Base/Test/Dom/CSharpModelTests.cs b/src/Main/Base/Test/Dom/CSharpModelTests.cs index 9b6d5bc071..2a90a6d211 100644 --- a/src/Main/Base/Test/Dom/CSharpModelTests.cs +++ b/src/Main/Base/Test/Dom/CSharpModelTests.cs @@ -77,6 +77,14 @@ namespace ICSharpCode.SharpDevelop.Dom public void EmptyProject() { Assert.AreEqual(0, topLevelTypeModels.Count); + Assert.IsNull(topLevelTypeModels[new TopLevelTypeName("A")]); + } + + [Test] + public void AddSimpleClass() + { + AddCodeFile("test.cs", @"class SimpleClass {}"); + Assert.AreEqual(1, topLevelTypeModels.Count); } } } diff --git a/src/Main/SharpDevelop/Dom/ModelFactory.cs b/src/Main/SharpDevelop/Dom/ModelFactory.cs index 1a9d892f14..b0e31de25f 100644 --- a/src/Main/SharpDevelop/Dom/ModelFactory.cs +++ b/src/Main/SharpDevelop/Dom/ModelFactory.cs @@ -8,7 +8,7 @@ namespace ICSharpCode.SharpDevelop.Dom { sealed class ModelFactory : IModelFactory { - public IMutableTypeDefinitionModelCollection CreateTopLevelTypeDefinitionCollection(IEntityModelContext context) + public ITypeDefinitionModelCollection CreateTopLevelTypeDefinitionCollection(IEntityModelContext context) { return new TopLevelTypeDefinitionModelCollection(context); } diff --git a/src/Main/SharpDevelop/Dom/TopLevelTypeDefinitionModelCollection.cs b/src/Main/SharpDevelop/Dom/TopLevelTypeDefinitionModelCollection.cs index d6ab8ed6f0..5f6cea2cdd 100644 --- a/src/Main/SharpDevelop/Dom/TopLevelTypeDefinitionModelCollection.cs +++ b/src/Main/SharpDevelop/Dom/TopLevelTypeDefinitionModelCollection.cs @@ -13,9 +13,11 @@ namespace ICSharpCode.SharpDevelop.Dom /// /// A TypeDefinitionModel-collection that holds models for all top-level types in a project content. /// - sealed class TopLevelTypeDefinitionModelCollection : KeyedModelCollection, IMutableTypeDefinitionModelCollection + sealed class TopLevelTypeDefinitionModelCollection : ITypeDefinitionModelCollection { readonly IEntityModelContext context; + Dictionary dict = new Dictionary(); + public event NotifyCollectionChangedEventHandler CollectionChanged; public TopLevelTypeDefinitionModelCollection(IEntityModelContext context) { @@ -24,11 +26,27 @@ namespace ICSharpCode.SharpDevelop.Dom this.context = context; } + public int Count { + get { return dict.Count; } + } + + public ITypeDefinitionModel this[TopLevelTypeName topLevelName] { + get { + TypeDefinitionModel model; + if (dict.TryGetValue(topLevelName, out model)) + return model; + else + return null; + } + } + public ITypeDefinitionModel this[FullTypeName fullTypeName] { get { - ITypeDefinitionModel model = base[fullTypeName.TopLevelTypeName]; + ITypeDefinitionModel model = this[fullTypeName.TopLevelTypeName]; for (int i = 0; i < fullTypeName.NestingLevel; i++) { - throw new NotImplementedException(); + string name = fullTypeName.GetNestedTypeName(i); + int atpc = fullTypeName.GetNestedTypeAdditionalTypeParameterCount(i); + model = model.GetNestedType(name, atpc); } return model; } @@ -39,15 +57,82 @@ namespace ICSharpCode.SharpDevelop.Dom /// public void Update(IUnresolvedFile oldFile, IUnresolvedFile newFile) { + List oldModels = null; + List newModels = null; + bool[] oldTypeDefHandled = null; if (oldFile != null) { - + oldTypeDefHandled = new bool[oldFile.TopLevelTypeDefinitions.Count]; + } + if (newFile != null) { + foreach (var newPart in newFile.TopLevelTypeDefinitions) { + FullTypeName newFullTypeName = newPart.FullTypeName; + TypeDefinitionModel model; + if (dict.TryGetValue(newFullTypeName.TopLevelTypeName, out model)) { + // Existing type changed + // Find a matching old part: + IUnresolvedTypeDefinition oldPart = null; + if (oldFile != null) { + for (int i = 0; i < oldTypeDefHandled.Length; i++) { + if (oldTypeDefHandled[i]) + continue; + if (oldFile.TopLevelTypeDefinitions[i].FullTypeName == newFullTypeName) { + oldTypeDefHandled[i] = true; + oldPart = oldFile.TopLevelTypeDefinitions[i]; + break; + } + } + } + model.Update(oldPart, newPart); + } else { + // New type added + model = new TypeDefinitionModel(context, newPart); + dict.Add(newFullTypeName.TopLevelTypeName, model); + if (newModels == null) + newModels = new List(); + newModels.Add(model); + } + } } - throw new NotImplementedException(); + // Remove all old parts that weren't updated: + if (oldFile != null) { + for (int i = 0; i < oldTypeDefHandled.Length; i++) { + if (!oldTypeDefHandled[i]) { + IUnresolvedTypeDefinition oldPart = oldFile.TopLevelTypeDefinitions[i]; + TopLevelTypeName topLevelTypeName = oldPart.FullTypeName.TopLevelTypeName; + TypeDefinitionModel model; + if (dict.TryGetValue(topLevelTypeName, out model)) { + // Remove the part from the model + if (model.Parts.Count > 1) { + model.Update(oldPart, null); + } else { + dict.Remove(topLevelTypeName); + if (oldModels == null) + oldModels = new List(); + oldModels.Add(model); + } + } + } + } + } + // Raise the event if necessary: + if (CollectionChanged != null) { + if (oldModels != null && newModels != null) + CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, newModels, oldModels)); + else if (oldModels != null) + CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, oldModels)); + else if (newModels != null) + CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, newModels)); + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + return dict.Values.GetEnumerator(); } - protected override TopLevelTypeName GetKeyForItem(ITypeDefinitionModel item) + IEnumerator IEnumerable.GetEnumerator() { - return item.FullTypeName.TopLevelTypeName; + return dict.Values.GetEnumerator(); } } } diff --git a/src/Main/SharpDevelop/Dom/TypeDefinitionModel.cs b/src/Main/SharpDevelop/Dom/TypeDefinitionModel.cs index b4ac2e66a5..4df6dd49c5 100644 --- a/src/Main/SharpDevelop/Dom/TypeDefinitionModel.cs +++ b/src/Main/SharpDevelop/Dom/TypeDefinitionModel.cs @@ -49,24 +49,9 @@ namespace ICSharpCode.SharpDevelop.Dom parts[0] = primaryPart; } - /* - /// - /// Updates the type definition model by removing the old parts and adding the new ones. - /// - public void Update(IReadOnlyList removedParts, IReadOnlyList newParts) - { - SD.MainThread.VerifyAccess(); - if (removedParts != null) - foreach (var p in removedParts) - parts.Remove(p); - if (newParts != null) - parts.AddRange(newParts); - - MemberModelCollection members; - if (membersWeakReference.TryGetTarget(out members)) { - members.Update(parts); - } - }*/ + public IReadOnlyList Parts { + get { return parts; } + } public IProject ParentProject { get { return context.Project; } @@ -221,17 +206,6 @@ namespace ICSharpCode.SharpDevelop.Dom { return GetEnumerator(); } - - public MemberModel this[int index] { - get { - int inputIndex = 0; - while (index >= lists[inputIndex].Count) { - index -= lists[inputIndex].Count; - inputIndex++; - } - return lists[inputIndex][index]; - } - } } WeakReference membersWeakReference = new WeakReference(null); @@ -255,10 +229,22 @@ namespace ICSharpCode.SharpDevelop.Dom } #endregion + #region Nested Types collection public IModelCollection NestedTypes { get { throw new NotImplementedException(); } } + + public ITypeDefinitionModel GetNestedType(string name, int atpc) + { + throw new NotImplementedException(); + } + #endregion + + public void Update(IUnresolvedTypeDefinition oldPart, IUnresolvedTypeDefinition newPart) + { + throw new NotImplementedException(); + } } }