File: Microsoft.Tools.Common\Microsoft\Activities\Presentation\Xaml\WorkflowDesignerXamlHelper.cs
Project: ndp\cdf\src\NetFx40\Tools\System.Activities.Presentation.csproj (System.Activities.Presentation)
// <copyright>
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
 
namespace Microsoft.Activities.Presentation.Xaml
{
    using System;
    using System.Activities;
    using System.Activities.Debugger;
    using System.Activities.Debugger.Symbol;
    using System.Activities.Presentation;
    using System.Activities.Presentation.ViewState;
    using System.Activities.Presentation.Xaml;
    using System.Activities.XamlIntegration;
    using System.Collections;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Globalization;
    using System.IO;
    using System.Runtime.Versioning;
    using System.Xaml;
 
    internal class WorkflowDesignerXamlHelper
    {
        private IWorkflowDesignerXamlHelperExecutionContext executionContext;
 
        private XamlMember dynamicActivityPropertyNameMember;
 
        private XamlMember dynamicActivityPropertyValueMember;
 
        internal WorkflowDesignerXamlHelper(IWorkflowDesignerXamlHelperExecutionContext executionContext)
        {
            this.executionContext = executionContext;
            SharedFx.Assert(this.executionContext != null, "this.executionContext != null");
            SharedFx.Assert(this.executionContext.XamlSchemaContext != null, "this.executionContext.XamlSchemaContext != null");
 
            this.dynamicActivityPropertyNameMember = new XamlMember(typeof(DynamicActivityProperty).GetProperty("Name"), this.XamlSchemaContext);
            this.dynamicActivityPropertyValueMember = new XamlMember(typeof(DynamicActivityProperty).GetProperty("Value"), this.XamlSchemaContext);
        }
 
        private delegate void SourceLocationFoundCallback(object obj, SourceLocation sourceLocation);
 
        internal enum DeserializationMode
        {
            Default,
            ErrorTolerant,
        }
 
        public FrameworkName FrameworkName
        {
            get { return this.executionContext.FrameworkName; }
        }
 
        public WorkflowDesignerXamlSchemaContext XamlSchemaContext
        {
            get { return this.executionContext.XamlSchemaContext; }
        }
 
        public ViewStateIdManager IdManager
        {
            get { return this.executionContext.IdManager; }
        }
 
        public WorkflowSymbol LastWorkflowSymbol
        {
            get
            {
                return this.executionContext.LastWorkflowSymbol;
            }
 
            set
            {
                this.executionContext.LastWorkflowSymbol = value;
            }
        }
 
        public string LocalAssemblyName
        {
            get { return this.executionContext.LocalAssemblyName; }
        }
 
        public void OnSerializationCompleted(Dictionary<object, object> sourceLocationObjectToModelItemObjectMapping)
        {
            this.executionContext.OnSerializationCompleted(sourceLocationObjectToModelItemObjectMapping);
        }
 
        public void OnBeforeDeserialize()
        {
            this.executionContext.OnBeforeDeserialize();
        }
 
        public void OnSourceLocationFound(object target, SourceLocation sourceLocation)
        {
            this.executionContext.OnSourceLocationFound(target, sourceLocation);
        }
 
        public void OnAfterDeserialize(Dictionary<string, SourceLocation> viewStateDataSourceLocationMapping)
        {
            this.executionContext.OnAfterDeserialize(viewStateDataSourceLocationMapping);
        }
 
        // Get root Activity. Currently only handle when the object is ActivityBuilder or Activity.
        // May return null if it does not know how to get the root activity.
        internal static Activity GetRootWorkflowElement(object rootModelObject)
        {
            SharedFx.Assert(rootModelObject != null, "Cannot pass null as rootModelObject");
            Activity rootWorkflowElement;
            IDebuggableWorkflowTree debuggableWorkflowTree = rootModelObject as IDebuggableWorkflowTree;
            if (debuggableWorkflowTree != null)
            {
                rootWorkflowElement = debuggableWorkflowTree.GetWorkflowRoot();
            }
            else
            {
                // Loose xaml case.
                rootWorkflowElement = rootModelObject as Activity;
            }
 
            return rootWorkflowElement;
        }
 
        internal static Activity GetRootElementForSymbol(object rootInstance, Activity documentRootElement)
        {
            ActivityBuilder activityBuilder = rootInstance as ActivityBuilder;
            if (activityBuilder != null)
            {
                documentRootElement = activityBuilder.ConvertToDynamicActivity();
            }
 
            return documentRootElement;
        }
 
        // Copy the root namespaces from a reader to a writer.
        // DesignTimeXamlWriter follows proper XAML convention by omitting the assembly name from
        // clr-namespaces in the local assembly. However, VB Expressions aren't local-assembly-aware,
        // and require an assembly name. So for every clr-namespace with no assembly name, we add an
        // additional namespace record with an assembly name, to support VB.
        // We only do this at the root level, since the designer only writes out namespaces at the root level.
        internal void CopyNamespacesAndAddLocalAssembly(System.Xaml.XamlReader activityBuilderReader, System.Xaml.XamlWriter objectWriter)
        {
            // Designer loads alwas provide line info
            IXamlLineInfo lineInfo = (IXamlLineInfo)activityBuilderReader;
            IXamlLineInfoConsumer lineInfoConsumer = (IXamlLineInfoConsumer)objectWriter;
            HashSet<string> definedPrefixes = new HashSet<string>();
            List<NamespaceDeclaration> localAsmNamespaces = null;
 
            while (activityBuilderReader.Read())
            {
                lineInfoConsumer.SetLineInfo(lineInfo.LineNumber, lineInfo.LinePosition);
 
                if (activityBuilderReader.NodeType == XamlNodeType.NamespaceDeclaration)
                {
                    definedPrefixes.Add(activityBuilderReader.Namespace.Prefix);
                    if (this.XamlSchemaContext.IsClrNamespaceWithNoAssembly(activityBuilderReader.Namespace.Namespace))
                    {
                        if (localAsmNamespaces == null)
                        {
                            localAsmNamespaces = new List<NamespaceDeclaration>();
                        }
 
                        localAsmNamespaces.Add(activityBuilderReader.Namespace);
                    }
 
                    objectWriter.WriteNode(activityBuilderReader);
                }
                else
                {
                    if (localAsmNamespaces != null)
                    {
                        foreach (NamespaceDeclaration ns in localAsmNamespaces)
                        {
                            string prefix = null;
                            int i = 0;
                            do
                            {
                                i++;
                                prefix = ns.Prefix + i.ToString(CultureInfo.InvariantCulture);
                            }
                            while (definedPrefixes.Contains(prefix));
                            string fullNs = this.XamlSchemaContext.AddLocalAssembly(ns.Namespace);
                            objectWriter.WriteNamespace(new NamespaceDeclaration(fullNs, prefix));
                            definedPrefixes.Add(prefix);
                        }
                    }
 
                    objectWriter.WriteNode(activityBuilderReader);
                    return;
                }
            }
        }
 
        internal string SerializeToString(object obj, string fileName)
        {
            FrameworkName targetFramework = this.FrameworkName;
 
            string sourceFile = null;
            Activity rootWorkflowElement = GetRootWorkflowElement(obj);
            Dictionary<int, object> modelItemObjectSequence = null;
 
            // If the current target is 4.5 or Higher, let us not write the filename attribute as DebugSymbol eliminates the need for it.
            // We will serialize without the Filename by removing it from the element and adding it back after serialization
            if (targetFramework.Is45OrHigher())
            {
                if (AttachablePropertyServices.TryGetProperty<string>(rootWorkflowElement, XamlDebuggerXmlReader.FileNameName, out sourceFile))
                {
                    AttachablePropertyServices.RemoveProperty(rootWorkflowElement, XamlDebuggerXmlReader.FileNameName);
                }
            }
 
            TextWriter textWriter = new StringWriter(CultureInfo.InvariantCulture);
 
            WorkflowDesignerXamlSchemaContext schemaContext = obj is ActivityBuilder ? this.XamlSchemaContext : new WorkflowDesignerXamlSchemaContext(null);
 
            bool shouldWriteDebugSymbol = true;
            if (targetFramework.IsLessThan45())
            {
                shouldWriteDebugSymbol = false;
            }
 
            System.Xaml.XamlReader outerReader;
            XamlObjectReaderWithSequence innerReader;
 
            using (textWriter)
            {
                UsingXamlWriter(
                    new DesignTimeXamlWriter(textWriter, schemaContext, shouldWriteDebugSymbol),
                    delegate(DesignTimeXamlWriter designTimeXamlWriter)
                    {
                        UsingXamlWriter(
                            ActivityXamlServices.CreateBuilderWriter(designTimeXamlWriter),
                            delegate(System.Xaml.XamlWriter activityBuilderWriter)
                            {
                                UsingXamlWriter(
                                    new ActivityTemplateFactoryBuilderWriter(activityBuilderWriter, schemaContext),
                                    delegate(System.Xaml.XamlWriter writer)
                                    {
                                        // If ViewStateManager property is attached, remove it. It needs to be regenerated if we target 4.5. 
                                        // It should be removed if we're targeting 4.0.
                                        AttachablePropertyServices.RemoveProperty(obj, WorkflowViewState.ViewStateManagerProperty);
 
                                        this.CreateXamlObjectReaders(obj, schemaContext, out outerReader, out innerReader);
 
                                        using (innerReader)
                                        {
                                            using (outerReader)
                                            {
#if ERROR_TOLERANT_SUPPORT
                                                if (ErrorActivity.GetHasErrorActivities(obj))
                                                {
                                                    ErrorTolerantObjectWriter.TransformAndStripErrors(outerReader, writer);
                                                }
                                                else
                                                {
#endif
                                                    XamlServices.Transform(outerReader, writer);
#if ERROR_TOLERANT_SUPPORT
                                                }
#endif
                                            }
                                        }
 
                                        modelItemObjectSequence = innerReader.SequenceNumberToObjectMap;
                                    });
                            });
                    });
            }
 
            string retVal = textWriter.ToString();
 
            if (targetFramework.IsLessThan45())
            {
                if (sourceFile != null)
                {
                    XamlDebuggerXmlReader.SetFileName(rootWorkflowElement, sourceFile);
                }
            }
 
            IList<XamlLoadErrorInfo> loadErrors;
            Dictionary<object, SourceLocation> sourceLocations;
            object deserializedObject = this.DeserializeString(retVal, out loadErrors, out sourceLocations);
 
            if (!string.IsNullOrEmpty(fileName) && targetFramework.Is45OrHigher())
            {
                this.LastWorkflowSymbol = this.GetWorkflowSymbol(fileName, deserializedObject, sourceLocations);
                if (this.LastWorkflowSymbol != null)
                {
                    retVal = retVal.Replace(DesignTimeXamlWriter.EmptyWorkflowSymbol, this.LastWorkflowSymbol.Encode());
                }
            }
 
            // The symbol is actually removed in GetAttachedWorkflowSymbol() after deserialization completes.
            System.Xaml.AttachablePropertyServices.RemoveProperty(GetRootWorkflowElement(deserializedObject), DebugSymbol.SymbolName);
            this.CreateXamlObjectReaders(deserializedObject, schemaContext, out outerReader, out innerReader);
            Dictionary<object, object> sourceLocationObjectToModelItemObjectMapping = new Dictionary<object, object>(ObjectReferenceEqualityComparer<object>.Default);
            using (innerReader)
            {
                using (outerReader)
                {
                    while (outerReader.Read())
                    {
                    }
 
                    Dictionary<int, object> sourceLocationObjectSequence = innerReader.SequenceNumberToObjectMap;
                    foreach (KeyValuePair<int, object> sourceLocationObjectEntry in sourceLocationObjectSequence)
                    {
                        int key = sourceLocationObjectEntry.Key;
                        object sourceLocationObject = sourceLocationObjectEntry.Value;
                        object modelItemObject;
 
                        if (modelItemObjectSequence.TryGetValue(key, out modelItemObject))
                        {
                            sourceLocationObjectToModelItemObjectMapping.Add(sourceLocationObject, modelItemObject);
                        }
                    }
                }
            }
 
            this.OnSerializationCompleted(sourceLocationObjectToModelItemObjectMapping);
            return retVal;
        }
 
        internal void CreateXamlObjectReaders(object deserializedObject, XamlSchemaContext schemaContext, out XamlReader newWorkflowReader, out XamlObjectReaderWithSequence deserializedObjectSequenceBuilder)
        {
            deserializedObjectSequenceBuilder = new XamlObjectReaderWithSequence(deserializedObject, schemaContext);
            if (this.FrameworkName.Is45OrHigher())
            {
                newWorkflowReader = ViewStateXamlHelper.ConvertAttachedPropertiesToViewState(deserializedObjectSequenceBuilder, this.IdManager);
            }
            else
            {
                newWorkflowReader = ViewStateXamlHelper.RemoveIdRefs(deserializedObjectSequenceBuilder);
            }
        }
 
        internal object DeserializeString(string text)
        {
            IList<XamlLoadErrorInfo> loadErrors;
            Dictionary<object, SourceLocation> sourceLocations;
            return this.DeserializeString(text, out loadErrors, out sourceLocations);
        }
 
        internal object DeserializeString(string text, out IList<XamlLoadErrorInfo> loadErrors, out Dictionary<object, SourceLocation> sourceLocations)
        {
            try
            {
                return this.DeserializeString(text, DeserializationMode.Default, out loadErrors, out sourceLocations);
            }
            catch (XamlObjectWriterException)
            {
                // Fall back to error-tolerant path. We don't do this by default for perf reasons.
                return this.DeserializeString(text, DeserializationMode.ErrorTolerant, out loadErrors, out sourceLocations);
            }
        }
 
        //// XAML writer may throw exception during dispose, therefore the following code will cause exception masking
        ////
        //// using (XamlWriter xamlWriter)
        //// {
        ////      ...
        //// }
        ////
        //// If there are any exception A thrown within the block, and if xamlWriter.Dispose() throws an exception B
        //// The exception B will mask exception A and the exception is the ErrorTolerant scenario will be broken.
        ////
        //// The fix to this problem is to ---- any XamlException thrown during Dispose(), we are in general not
        //// interested in those exceptions.
        private static void UsingXamlWriter<T>(T xamlWriter, Action<T> work) where T : XamlWriter
        {
            if (xamlWriter != null)
            {
                try
                {
                    work(xamlWriter);
                }
                finally
                {
                    try
                    {
                        xamlWriter.Close();
                    }
                    catch (XamlException e)
                    {
                        // ignore any XAML exception during closing a XamlWriter
                        Trace.WriteLine(e.Message);
                    }
                }
            }
        }
 
        // there are two kind of attribute:
        // 1) in lined : argument="some value"
        // 2) <argument>
        //       <Expression ....../>
        //    </argument>
        // here, for (1) return the source location of "some value".
        // for (2) return null
        private static SourceLocation GetInlineAttributeValueLocation(LineColumnPair startPoint, SourceTextScanner sourceTextScanner)
        {
            const char SingleQuote = '\'';
            const char DoubleQuote = '"';
            const char StartAngleBracket = '<';
            Tuple<LineColumnPair, char> start = sourceTextScanner.SearchCharAfter(startPoint, SingleQuote, DoubleQuote, StartAngleBracket);
            if (start == null)
            {
                return null;
            }
 
            if (start.Item2 == StartAngleBracket)
            {
                return null;
            }
 
            Tuple<LineColumnPair, char> end = sourceTextScanner.SearchCharAfter(start.Item1, start.Item2);
            if (end == null)
            {
                SharedFx.Assert("end of SourceLocation is not found");
                return null;
            }
 
            return new SourceLocation(null, start.Item1.LineNumber, start.Item1.ColumnNumber, end.Item1.LineNumber, end.Item1.ColumnNumber);
        }
 
        private WorkflowSymbol GetWorkflowSymbol(string fileName, object deserializedObject, Dictionary<object, SourceLocation> sourceLocations)
        {
            if (deserializedObject != null)
            {
                Activity deserializedRootElement = GetRootWorkflowElement(deserializedObject);
                if (deserializedRootElement != null)
                {
                    try
                    {
                        deserializedRootElement = GetRootElementForSymbol(deserializedObject, deserializedRootElement);
                        return new WorkflowSymbol
                        {
                            FileName = fileName,
                            Symbols = SourceLocationProvider.GetSymbols(deserializedRootElement, sourceLocations)
                        };
                    }
                    catch (Exception ex)
                    {
                        if (SharedFx.IsFatal(ex))
                        {
                            throw;
                        }
 
                        // This happens when the workflow is invalid so GetSymbols fails.
                        // ---- exception here.
                    }
                }
            }
 
            return null;
        }
 
        private object DeserializeString(string text, DeserializationMode mode, out IList<XamlLoadErrorInfo> loadErrors, out Dictionary<object, SourceLocation> sourceLocations)
        {
            object result = null;
            loadErrors = null;
            Dictionary<object, SourceLocation> collectingSourceLocations = new Dictionary<object, SourceLocation>(ObjectReferenceEqualityComparer<object>.Default);
            SourceLocationFoundCallback sourceLocationFoundCallback = new SourceLocationFoundCallback((obj, sourceLocation) =>
            {
                // If an object appear more than once in the XAML stream (e.g. System.Type, which is cached by reflection)
                // we count the first occurrence.
                if (!collectingSourceLocations.ContainsKey(obj))
                {
                    collectingSourceLocations.Add(obj, sourceLocation);
                }
 
                this.OnSourceLocationFound(obj, sourceLocation);
            });
 
            this.XamlSchemaContext.ContainsConversionRequiredType = false;
            Dictionary<string, SourceLocation> viewStateDataSourceLocationMapping = null;
            using (XamlDebuggerXmlReader debuggerReader = new XamlDebuggerXmlReader(new StringReader(text), this.XamlSchemaContext))
            {
                using (System.Xaml.XamlReader activityBuilderReader = ActivityXamlServices.CreateBuilderReader(debuggerReader))
                {
                    using (System.Xaml.XamlReader activityTemplateFactoryBuilderReader = new ActivityTemplateFactoryBuilderReader(activityBuilderReader, this.XamlSchemaContext))
                    {
                        debuggerReader.SourceLocationFound += delegate(object sender, SourceLocationFoundEventArgs args)
                        {
                            sourceLocationFoundCallback(args.Target, args.SourceLocation);
                        };
 
                        this.OnBeforeDeserialize();
                        debuggerReader.CollectNonActivitySourceLocation = this.FrameworkName.Is45OrHigher();
 
                        using (System.Xaml.XamlReader reader = ViewStateXamlHelper.ConvertViewStateToAttachedProperties(activityTemplateFactoryBuilderReader, this.IdManager, out viewStateDataSourceLocationMapping))
                        {
                            switch (mode)
                            {
#if ERROR_TOLERANT_SUPPORT
                                case DeserializationMode.ErrorTolerant:
                                    {
                                        ErrorTolerantObjectWriter tolerantWriter = new ErrorTolerantObjectWriter(reader.SchemaContext);
                                        tolerantWriter.LocalAssemblyName = this.LocalAssemblyName;
                                        XamlServices.Transform(reader, tolerantWriter);
                                        loadErrors = this.CheckFileFormatError(tolerantWriter.LoadErrors);
                                        result = tolerantWriter.Result;
                                        ErrorActivity.SetHasErrorActivities(result, true);
                                    }
 
                                    break;
#endif
                                case DeserializationMode.Default:
                                    {
                                        result = this.TransformAndGetPropertySourceLocation(reader, new SourceTextScanner(text), sourceLocationFoundCallback);
 
                                        loadErrors = this.CheckFileFormatError(loadErrors);
                                    }
 
                                    break;
                            }
                        }
                    }
                }
            }
 
            sourceLocations = collectingSourceLocations;
            this.OnAfterDeserialize(viewStateDataSourceLocationMapping);
            return result;
        }
 
        // For dynamic activity property, we needs to collect the source location of 
        // its default value when the value is inlined.
        private KeyValuePair<string, SourceLocation> TransformDynamicActivityProperty(
            XamlReader reader,
            XamlObjectWriter objectWriter,
            SourceTextScanner sourceTextScanner)
        {
            // (Number of SM -Number of EM) since SM DAP.Name is read.
            // SO DAP                   ---nameReadingLevel=0
            //   SM NAME                ---nameReadingLevel=1
            //     SO String            ---nameReadingLevel=1
            //       SM Initialize      ---nameReadingLevel=2
            //         VA StringValue   ---nameReadingLevel=2
            //       EM                 ---nameReadingLevel=1
            //     SO                   ---nameReadingLevel=1
            //   EM                     ---nameReadingLevel=0
            // EO                       ---nameReadingLevel=0
            int nameReadingLevel = 0;
 
            IXamlLineInfo lineInfo = (IXamlLineInfo)reader;
            SourceLocation defaultValueLocation = null;
            string propertyName = null;
 
            while (reader.Read())
            {
                switch (reader.NodeType)
                {
                    case XamlNodeType.StartMember:
                        if (nameReadingLevel > 0
                            || reader.Member == this.dynamicActivityPropertyNameMember)
                        {
                            ++nameReadingLevel;
                        }
                        else if (reader.Member == this.dynamicActivityPropertyValueMember)
                        {
                            LineColumnPair startPoint = new LineColumnPair(lineInfo.LineNumber, lineInfo.LinePosition);
                            defaultValueLocation = GetInlineAttributeValueLocation(startPoint, sourceTextScanner);
                        }
 
                        break;
 
                    case XamlNodeType.EndMember:
                        if (nameReadingLevel > 0)
                        {
                            --nameReadingLevel;
                        }
 
                        break;
 
                    case XamlNodeType.Value:
                        if (nameReadingLevel > 0)
                        {
                            propertyName = reader.Value as string;
                        }
 
                        break;
                }
 
                objectWriter.WriteNode(reader);
            }
 
            if (propertyName != null && defaultValueLocation != null)
            {
                return new KeyValuePair<string, SourceLocation>(propertyName, defaultValueLocation);
            }
 
            return new KeyValuePair<string, SourceLocation>();
        }
 
        private object TransformAndGetPropertySourceLocation(XamlReader reader, SourceTextScanner sourceTextScanner, SourceLocationFoundCallback sourceLocationFoundCallback)
        {
            // <property name, value's start location>
            Dictionary<string, SourceLocation> propertyValueLocationMapping = new Dictionary<string, SourceLocation>();
 
            object deserializedObject = null;
            object earlyResult = null;
 
            UsingXamlWriter(
                new XamlObjectWriter(reader.SchemaContext),
                delegate(XamlObjectWriter objectWriter)
                {
                    if (this.XamlSchemaContext.HasLocalAssembly)
                    {
                        this.CopyNamespacesAndAddLocalAssembly(reader, objectWriter);
                    }
 
                    if (!(reader is IXamlLineInfo))
                    {
                        XamlServices.Transform(reader, objectWriter);
                        earlyResult = objectWriter.Result;
                        return;
                    }
 
                    XamlType dynamicActivityPropertyType = this.XamlSchemaContext.GetXamlType(typeof(DynamicActivityProperty));
                    while (reader.Read())
                    {
                        // read SubTree will moves the reader pointed to
                        // element after its EO. So, we need to use a while
                        while (!reader.IsEof && reader.NodeType == XamlNodeType.StartObject
                            && dynamicActivityPropertyType == reader.Type)
                        {
                            KeyValuePair<string, SourceLocation> nameSourceLocation = this.TransformDynamicActivityProperty(reader.ReadSubtree(), objectWriter, sourceTextScanner);
                            if (nameSourceLocation.Key != null && nameSourceLocation.Value != null && !propertyValueLocationMapping.ContainsKey(nameSourceLocation.Key))
                            {
                                propertyValueLocationMapping.Add(nameSourceLocation.Key, nameSourceLocation.Value);
                            }
                        }
 
                        if (!reader.IsEof)
                        {
                            objectWriter.WriteNode(reader);
                        }
                    }
 
                    deserializedObject = objectWriter.Result;
                });
 
            if (earlyResult != null)
            {
                return earlyResult;
            }
 
            ActivityBuilder activityBuilder = deserializedObject as ActivityBuilder;
            if (activityBuilder == null)
            {
                return deserializedObject;
            }
 
            foreach (KeyValuePair<string, SourceLocation> propertyValueLocation in propertyValueLocationMapping)
            {
                string propertyName = propertyValueLocation.Key;
                SourceLocation propertyLocation = propertyValueLocation.Value;
                if (!activityBuilder.Properties.Contains(propertyName))
                {
                    SharedFx.Assert(string.Format(CultureInfo.CurrentCulture, "no such property:{0}", propertyName));
                    continue;
                }
 
                DynamicActivityProperty property = activityBuilder.Properties[propertyName];
 
                if (property == null || property.Value == null)
                {
                    SharedFx.Assert(string.Format(CultureInfo.CurrentCulture, "no such property value:{0}", propertyName));
                    continue;
                }
 
                object expression = (property.Value is Argument) ? ((Argument)property.Value).Expression : null;
                if (expression != null)
                {
                    sourceLocationFoundCallback(expression, propertyLocation);
                }
                else
                {
                    sourceLocationFoundCallback(property.Value, propertyLocation);
                }
            }
 
            return deserializedObject;
        }
 
        private IList<XamlLoadErrorInfo> CheckFileFormatError(IList<XamlLoadErrorInfo> loadErrors)
        {
            IList<XamlLoadErrorInfo> result = loadErrors;
 
            if (this.XamlSchemaContext.ContainsConversionRequiredType)
            {
                if (result == null)
                {
                    result = new List<XamlLoadErrorInfo>();
                }
 
                result.Add(new XamlLoadErrorInfo(SharedSR.FileFormatError, 0, 0));
            }
 
            return result;
        }
    }
}