Пример #1
0
        /// <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
        }