protected void AddClassToNamespaceListInternal(IClass addClass) { // Freeze the class when adding it to the project content addClass.Freeze(); Debug.Assert(!(addClass is CompoundClass)); Debug.Assert(!addClass.HasCompoundClass); string fullyQualifiedName = addClass.FullyQualifiedName; IClass existingClass = GetClassInternal(fullyQualifiedName, addClass.TypeParameters.Count, language); if (existingClass != null && existingClass.TypeParameters.Count == addClass.TypeParameters.Count) { LoggingService.Debug("Adding existing class " + addClass.Name + " from " + Path.GetFileName(addClass.CompilationUnit.FileName)); CompoundClass compound = existingClass as CompoundClass; if (compound != null) { // mark the class as partial // (VB allows specifying the 'partial' modifier only on one part) addClass.HasCompoundClass = true; // add the new class to the compound class List <IClass> newParts = new List <IClass>(compound.Parts); newParts.Add(addClass); // construct a replacement CompoundClass with the new part list addClass = CompoundClass.Create(newParts); LoggingService.Debug("Added new part (old part count=" + compound.Parts.Count + ", new part count=" + newParts.Count + ")"); } else { // Instead of overwriting a class with another, treat both parts as partial. // This fixes SD2-1217. if (!(addClass.IsPartial || language.ImplicitPartialClasses)) { LoggingService.Info("Duplicate class " + fullyQualifiedName + ", creating compound"); } else { LoggingService.Debug("Creating compound for " + fullyQualifiedName); } // Merge existing non-partial class with addClass addClass.HasCompoundClass = true; existingClass.HasCompoundClass = true; addClass = CompoundClass.Create(new[] { addClass, existingClass }); } } AddClassToNamespaceListInternal2(addClass); }
protected void RemoveClass(IClass @class) { string fullyQualifiedName = @class.FullyQualifiedName; int typeParameterCount = @class.TypeParameters.Count; if (@class.HasCompoundClass) { LoggingService.Debug("Removing part " + @class.CompilationUnit.FileName + " from compound class " + @class.FullyQualifiedName); // remove a part of a partial class // Use "as" cast to fix SD2-680: the stored class might be a part not marked as partial CompoundClass compound = GetClassInternal(fullyQualifiedName, typeParameterCount, language) as CompoundClass; if (compound == null) { LoggingService.Warn("compound class not found"); return; } typeParameterCount = compound.TypeParameters.Count; List <IClass> newParts = new List <IClass>(compound.Parts); newParts.Remove(@class); if (newParts.Count > 1) { LoggingService.Debug("Part removed, old part count = " + compound.Parts.Count + ", new part count=" + newParts.Count); AddClassToNamespaceListInternal2(CompoundClass.Create(newParts)); return; } else if (newParts.Count == 1) { LoggingService.Debug("Second-to-last part removed (old part count = " + compound.Parts.Count + "), overwriting compound with last part"); newParts[0].HasCompoundClass = false; AddClassToNamespaceListInternal2(newParts[0]); return; } else // newParts.Count == 0 // this should not be possible, the compound should have been destroyed when there was only 1 part left { LoggingService.Warn("All parts removed, remove compound"); @class = compound; // all parts removed, remove compound class } } IClass classInDictionary; if (!GetClasses(language).TryGetValue(fullyQualifiedName, out classInDictionary)) { return; } GenericClassContainer gcc = classInDictionary as GenericClassContainer; if (gcc != null) { gcc.Remove(typeParameterCount); if (gcc.RealClassCount > 0) { return; } } foreach (Dictionary <string, IClass> classes in ClassLists) { classes.Remove(fullyQualifiedName); } string nSpace = @class.Namespace; if (nSpace == null) { nSpace = String.Empty; } // Remove class from namespace lists List <IClass> classList = GetNamespaces(this.language)[nSpace].Classes; for (int i = 0; i < classList.Count; i++) { if (language.NameComparer.Equals(classList[i].FullyQualifiedName, fullyQualifiedName)) { classList.RemoveAt(i); break; } } if (classList.Count == 0) { RemoveEmptyNamespace(nSpace); } }