/// <summary> /// Validate that the definition of the class object does not break any rules set by the Smalltalk standard. /// </summary> /// <param name="installer">Context within which the validation is to be performed.</param> /// <returns>Returns true if successful, otherwise false.</returns> protected internal override bool ValidateObject(IDefinitionInstallerContext installer) { if (installer == null) { throw new ArgumentNullException(); } // 1. Get the binding to the global Symbol name = installer.Runtime.GetSymbol(this.Name.Value); ClassBinding binding = installer.GetLocalClassBinding(name); // 2. Check consistency that we didn't mess up in the implementation. if (binding == null) { throw new InvalidOperationException("Should have found a binding, because CreateGlobalBinding() created it!"); } if (binding.Value == null) { throw new InvalidOperationException("Should not be an empty binding, because CreateGlobalObject() just created it!"); } // 3. Get the class object. SmalltalkClass cls = binding.Value; // 4. Validate that superclass is correct List <Symbol> classes = new List <Symbol>(); classes.Add(cls.Name); SmalltalkClass tmp = cls.Superclass; while (tmp != null) { if (classes.IndexOf(tmp.Name) != -1) { return(installer.ReportError(this.SuperclassName, String.Format( InstallerErrors.ClassCircularReference, this.SuperclassName.Value, this.Name.Value))); } classes.Add(tmp.Name); tmp = tmp.Superclass; } if (cls.InstanceState != SmalltalkClass.InstanceStateEnum.ByteIndexable) { tmp = cls; while (tmp != null) { if (tmp.InstanceState == SmalltalkClass.InstanceStateEnum.ByteIndexable) { return(installer.ReportError(this.InstanceState, InstallerErrors.ClassCannotChangeInstanceState)); } tmp = tmp.Superclass; } } foreach (PoolBinding pool in cls.ImportedPoolBindings) { if (pool.Value == null) { SourceReference <string> src = this.ImportedPoolNames.SingleOrDefault(sr => sr.Value == pool.Name.Value); if (src == null) { throw new InvalidOperationException("Should not be null, cause we just added this pool in CreateGlobalObject()."); } return(installer.ReportError(src, InstallerErrors.ClassMissingPoolDefinition)); } } // NB: We must give some source reference, but since we don't have for the whole class, we use the name. installer.RegisterNewClass(cls, this.Name); return(true); // OK }