1
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
2
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
5
using System.Collections.Generic;
6
using System.Collections.ObjectModel;
8
using System.Diagnostics;
10
namespace ICSharpCode.SharpDevelop.Dom
13
/// A class made up of multiple partial classes.
15
/// CompoundClass is immutable, it freezes the underlying DefaultClass in the constructor.
16
/// The constructor also freezes all parts to ensure that the methods/properties/fields/events of a
17
/// CompoundClass never change.
18
/// When you want to build add or remove parts from a CompoundClass, you need to create a new
19
/// CompoundClass instance with the new parts.
21
public sealed class CompoundClass : DefaultClass
24
/// The parts this class is based on.
26
readonly ReadOnlyCollection<IClass> parts;
29
/// Gets the parts this class is based on.
31
public ReadOnlyCollection<IClass> Parts {
38
/// Creates a new CompoundClass with the specified parts.
40
public static CompoundClass Create(IEnumerable<IClass> parts)
42
// Ensure that the list of parts does not change.
43
var p = parts.ToList();
44
foreach (IClass c in p) {
47
return new CompoundClass(p);
50
private CompoundClass(List<IClass> parts) : base(new DefaultCompilationUnit(parts[0].ProjectContent), parts[0].FullyQualifiedName)
52
this.CompilationUnit.Classes.Add(this);
54
this.parts = parts.AsReadOnly();
56
UpdateInformationFromParts();
57
this.CompilationUnit.Freeze();
58
Debug.Assert(this.IsFrozen);
62
/// Calculate information from class parts (Modifier, Base classes, Type parameters etc.)
64
void UpdateInformationFromParts()
66
// Common for all parts:
67
this.ClassType = parts[0].ClassType;
69
ModifierEnum modifier = ModifierEnum.None;
70
const ModifierEnum defaultClassVisibility = ModifierEnum.Internal;
72
this.BaseTypes.Clear();
73
this.InnerClasses.Clear();
74
this.Attributes.Clear();
76
this.Properties.Clear();
80
string shortestFileName = null;
82
foreach (IClass part in parts) {
83
if (!string.IsNullOrEmpty(part.CompilationUnit.FileName)) {
84
if (shortestFileName == null || part.CompilationUnit.FileName.Length < shortestFileName.Length) {
85
shortestFileName = part.CompilationUnit.FileName;
86
this.Region = part.Region;
90
if ((part.Modifiers & ModifierEnum.VisibilityMask) != defaultClassVisibility) {
91
modifier |= part.Modifiers;
93
modifier |= part.Modifiers &~ ModifierEnum.VisibilityMask;
95
foreach (IReturnType rt in part.BaseTypes) {
96
if (!rt.IsDefaultReturnType || rt.FullyQualifiedName != "System.Object") {
97
this.BaseTypes.Add(rt);
100
this.InnerClasses.AddRange(part.InnerClasses);
101
this.Attributes.AddRange(part.Attributes);
102
this.Methods.AddRange(part.Methods);
103
this.Properties.AddRange(part.Properties);
104
this.Events.AddRange(part.Events);
105
this.Fields.AddRange(part.Fields);
107
this.AddDefaultConstructorIfRequired |= part.AddDefaultConstructorIfRequired;
109
this.CompilationUnit.FileName = shortestFileName;
110
if ((modifier & ModifierEnum.VisibilityMask) == ModifierEnum.None) {
111
modifier |= defaultClassVisibility;
113
this.Modifiers = modifier;
117
/// Type parameters are the same on all parts.
119
public override IList<ITypeParameter> TypeParameters {
121
// Locking for the time of getting the reference to the sub-list is sufficient:
122
// Classes used for parts never change, instead the whole part is replaced with
123
// a new IClass instance.
124
return parts[0].TypeParameters;
127
throw new NotSupportedException();