FixUpCollection.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntityDesign / Design / System / Data / EntityModel / Emitters / FixUpCollection.cs / 1305376 / FixUpCollection.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner       [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

using System; 
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics; 
using System.Data;
using System.Data.EntityModel.SchemaObjectModel; 
using System.Data.Entity.Design; 

namespace System.Data.EntityModel.Emitters 
{
    internal sealed class FixUpCollection : List
    {
        #region Private Types 
        private enum CSDeclType
        { 
            Method, 
            Property,
            Other, 
        }
        public enum VBStatementType
        {
            BeginClass, 
            EndClass,
            BeginProperty, 
            EndProperty, 
            BeginMethod,
            EndMethod, 
            BeginPropertyGetter,
            EndPropertyGetter,
            BeginPropertySetter,
            EndPropertySetter, 
            Other,
        } 
        #endregion 

        #region Instance Fields 
        private Dictionary> _classFixUps = null;
        private LanguageOption _language;
        #endregion
 
        #region Static Fields
        static readonly char[] _CSEndOfClassDelimiters = new char[] { ' ',':' }; 
        const string _CSClassKeyWord = " class "; 
        static readonly char[] _CSFieldMarkers = new char[] { '=',';' };
        static readonly char[] _VBEndOfClassDelimiters = new char[] { ' ', '(' }; 
        static readonly char[] _VBNonDeclMarkers = new char[] { '=', '"', '\'' };
        #endregion

        #region Public Methods 
        /// 
        /// 
        ///  
        public FixUpCollection()
        { 
        }

        public static bool IsLanguageSupported(LanguageOption language)
        { 
            switch ( language )
            { 
                case LanguageOption.GenerateVBCode: 
                case LanguageOption.GenerateCSharpCode:
                    return true; 
            }
            return false;
        }
 
        /// 
        /// 
        ///  
        /// 
        ///  
        /// 
        public void Do(System.IO.TextReader reader, System.IO.TextWriter writer, LanguageOption language, bool hasNamespace)
        {
            Language = language; 

            // set up the fix ups for each class. 
            foreach ( FixUp fixUp in this ) 
            {
                List fixUps = null; 
                if ( ClassFixUps.ContainsKey(fixUp.Class) )
                {
                    fixUps = ClassFixUps[fixUp.Class];
                } 
                else
                { 
                    fixUps = new List(); 
                    ClassFixUps.Add(fixUp.Class,fixUps);
                } 
                fixUps.Add(fixUp);
            }

            switch ( Language ) 
            {
                case LanguageOption.GenerateVBCode: 
                    DoFixUpsForVB(reader, writer); 
                    break;
                case LanguageOption.GenerateCSharpCode: 
                    DoFixUpsForCS(reader, writer, hasNamespace);
                    break;
                default:
                    Debug.Assert(false,"Unexpected language value: "+Language.ToString()); 
                    CopyFile(reader,writer);
                    break; 
            } 
        }
 
        /// 
        ///
        /// 
        ///  
        /// 
        private static void CopyFile(System.IO.TextReader reader, System.IO.TextWriter writer) 
        { 
            string line;
            while ( (line=reader.ReadLine()) != null ) 
                writer.WriteLine(line);
        }

        ///  
        ///
        ///  
        ///  
        /// 
        private void DoFixUpsForCS(System.IO.TextReader reader, System.IO.TextWriter writer, bool hasNamespace) 
        {
            int braceCount = 0;
            string line;
            string trimmedLine; 
            string currentOuterClass = null;
            string className; 
            bool classWanted = false; 
            FixUp getterFixUp = null;
            FixUp setterFixUp = null; 
            int nameSpaceLevel = hasNamespace ? 1 : 0;
            while ( (line=reader.ReadLine()) != null )
            {
                trimmedLine = line.Trim(); 
                if ( trimmedLine == "{" )
                    ++braceCount; 
                else if ( trimmedLine == "}" ) 
                {
                    --braceCount; 
                    if (braceCount < nameSpaceLevel + 2)
                    {
                        setterFixUp = null;
                        if (braceCount < nameSpaceLevel + 1) 
                        {
                            currentOuterClass = null; 
                            classWanted = false; 
                        }
                    } 
                }
                else if ( string.IsNullOrEmpty(trimmedLine) || trimmedLine.StartsWith("//",StringComparison.Ordinal) )
                {
                    // comment, just emit as is.... 
                }
                else if ( IsCSClassDefinition(line,out className) ) 
                { 
                    if (braceCount == nameSpaceLevel)
                    { 
                        currentOuterClass = className;
                        className = null;
                        classWanted = IsClassWanted(currentOuterClass);
                        if ( classWanted ) 
                            line = FixUpClassDecl(currentOuterClass,line);
                    } 
                } 
                else if ( classWanted )
                { 
                    //we only care about methods/properties in top level classes
                    if (braceCount == nameSpaceLevel + 1)
                    {
                        string name; 
                        switch ( GetCSDeclType(trimmedLine,out name) )
                        { 
                            case CSDeclType.Method: 
                                line = FixUpMethodDecl(currentOuterClass,name,line);
                                break; 
                            case CSDeclType.Property:
                                setterFixUp = FixUpSetter(currentOuterClass, name);
                                getterFixUp = FixUpGetter(currentOuterClass, name);
                                break; 
                        }
                    } 
                    else if (braceCount == nameSpaceLevel + 2) 
                    {
                        if (trimmedLine == "set" && setterFixUp != null) 
                        {
                            line = setterFixUp.Fix(LanguageOption.GenerateCSharpCode, line);
                            setterFixUp = null;
                        } 
                        else if (trimmedLine == "get" && getterFixUp != null)
                        { 
                            line = getterFixUp.Fix(LanguageOption.GenerateCSharpCode, line); 
                            getterFixUp = null;
                        } 
                    }
                }
                writer.WriteLine(line);
            } 
        }
 
        ///  
        ///
        ///  
        /// 
        /// 
        public void DoFixUpsForVB(System.IO.TextReader reader, System.IO.TextWriter writer)
        { 
            Language = LanguageOption.GenerateVBCode;
 
            string line; 
            Stack context = new Stack();
            int classDepth = 0; 
            string currentOuterClass = null;
            bool classWanted = false;
            FixUp getterFixUp = null;
            FixUp setterFixUp = null; 
            while ( (line=reader.ReadLine()) != null )
            { 
                if ( line == null || line.Length == 0 || line[0] == '\'' ) 
                {
                    // empty line or comment, ouput as is 
                }
                else
                {
                    string name; 
                    switch ( GetVBStatementType(context, line, out name) )
                    { 
                        case VBStatementType.BeginClass: 
                            ++classDepth;
                            setterFixUp = null; 
                            if ( classDepth == 1 )
                            {
                                currentOuterClass = name;
                                classWanted = IsClassWanted(name); 
                                if ( classWanted )
                                    line = FixUpClassDecl(currentOuterClass, line); 
                            } 
                            break;
 
                        case VBStatementType.EndClass:
                            --classDepth;
                            if (classDepth == 0)
                            { 
                                currentOuterClass = null;
                            } 
                            break; 

                        case VBStatementType.BeginProperty: 
                            if (classWanted)
                            {
                                getterFixUp = FixUpGetter(currentOuterClass, name);
                                setterFixUp = FixUpSetter(currentOuterClass, name); 
                            }
                            else 
                            { 
                                getterFixUp = null;
                                setterFixUp = null; 
                            }
                            break;

                        case VBStatementType.EndProperty: 
                            getterFixUp = null;
                            setterFixUp = null; 
                            break; 

                        case VBStatementType.BeginMethod: 
                            if (classWanted)
                            {
                                line = FixUpMethodDecl(currentOuterClass, name, line);
                            } 
                            break;
 
                        case VBStatementType.BeginPropertySetter: 
                            if (setterFixUp != null)
                            { 
                                line = setterFixUp.Fix(Language, line);
                            }
                            setterFixUp = null;
                            break; 

                        case VBStatementType.BeginPropertyGetter: 
                            if (getterFixUp != null) 
                            {
                                line = getterFixUp.Fix(Language, line); 
                            }
                            getterFixUp = null;
                            break;
                    } 
                }
                writer.WriteLine(line); 
            } 
        }
 
        #endregion

        #region Private Methods
        ///  
        ///
        ///  
        ///  
        /// 
        private bool IsClassWanted(string className) 
        {
            return ClassFixUps.ContainsKey(className);
        }
 
        /// 
        /// 
        ///  
        /// 
        ///  
        /// 
        private static bool IsCSClassDefinition(string line,out string className)
        {
            int index = line.IndexOf(_CSClassKeyWord,StringComparison.Ordinal); 
            if ( index < 0 )
            { 
                className = null; 
                return false;
            } 
            index += _CSClassKeyWord.Length;
            int end = line.IndexOfAny(_CSEndOfClassDelimiters, index);
            if ( end < 0 )
                className = line.Substring(index); 
            else
                className = line.Substring(index,end-index); 
 

            if (className.StartsWith("@", StringComparison.Ordinal)) 
            {
                // remove the escaping mechanisim for C# keywords
                className = className.Substring(1);
            } 

            return true; 
        } 

        ///  
        ///
        /// 
        /// 
        ///  
        /// 
        private string FixUpClassDecl(string className,string line) 
        { 
            IList fixUps = ClassFixUps[className];
            foreach ( FixUp fixUp in fixUps ) 
            {
                if ( fixUp.Type == FixUpType.MarkClassAsStatic )
                {
                    return fixUp.Fix(Language,line); 
                }
            } 
            return line; 
        }
 
        /// 
        ///
        /// 
        ///  
        /// 
        ///  
        private static CSDeclType GetCSDeclType(string line, out string name) 
        {
            // we know we're at the class member level. 
            // things we could encounter are (limited to things we actually emit):
            //    nested classes (already identified)
            //    attributes
            //    fields 
            //    methods
            //    properties 
 
            name = null;
 
            //Attributes
            if (line[0] == '[')
                return CSDeclType.Other;
 
            // Methods have ( and ) without a =
            int parIdx1 = line.IndexOf('('); 
            int parIdx2 = line.IndexOf(')'); 
            int equIdx = line.IndexOf('='); //return -1 for absent equal sign.
 
            if (equIdx == -1 && parIdx1 >= 0 && parIdx2 > parIdx1)
            {
                line = line.Substring(0, parIdx1).TrimEnd(null);
                name = line.Substring(line.LastIndexOf(' ') + 1); 
                return CSDeclType.Method;
            } 
 
            //we assume fields have = or ;
            if (line.IndexOfAny(_CSFieldMarkers, 0) >= 0) 
                return CSDeclType.Other;

            //Properties
            CSDeclType declType = CSDeclType.Property; 
            name = line.Substring(line.LastIndexOf(' ') + 1);
            return declType; 
        } 

        ///  
        ///
        /// 
        /// 
        ///  
        /// 
        ///  
        private string FixUpMethodDecl(string className,string methodName,string line) 
        {
            IList fixUps = ClassFixUps[className]; 
            foreach ( FixUp fixUp in fixUps )
            {
                if ( fixUp.Method == methodName &&
                    (fixUp.Type == FixUpType.MarkOverrideMethodAsSealed || fixUp.Type == FixUpType.MarkAbstractMethodAsPartial) ) 
                {
                    return fixUp.Fix(Language,line); 
                } 
            }
            return line; 
        }

        /// 
        /// 
        /// 
        ///  
        ///  
        /// 
        private FixUp FixUpSetter(string className,string propertyName) 
        {
            IList fixUps = ClassFixUps[className];
            foreach ( FixUp fixUp in fixUps )
            { 
                if (fixUp.Property == propertyName &&
                    (fixUp.Type == FixUpType.MarkPropertySetAsPrivate || 
                     fixUp.Type == FixUpType.MarkPropertySetAsInternal || 
                     fixUp.Type == FixUpType.MarkPropertySetAsPublic ||
                     fixUp.Type == FixUpType.MarkPropertySetAsProtected)) 
                {
                    return fixUp;
                }
            } 
            return null;
        } 
 
        private FixUp FixUpGetter(string className, string propertyName)
        { 
            IList fixUps = ClassFixUps[className];
            foreach (FixUp fixUp in fixUps)
            {
                if (fixUp.Property == propertyName && 
                    (fixUp.Type == FixUpType.MarkPropertyGetAsPrivate ||
                     fixUp.Type == FixUpType.MarkPropertyGetAsInternal || 
                     fixUp.Type == FixUpType.MarkPropertyGetAsPublic || 
                     fixUp.Type == FixUpType.MarkPropertyGetAsProtected))
                { 
                    return fixUp;
                }
            }
            return null; 
        }
        ///  
        /// 
        /// 
        ///  
        /// 
        /// 
        /// 
        private static VBStatementType GetVBStatementType(Stack context, string line, out string name) 
        {
            name = null; 
            VBStatementType current = VBStatementType.Other; 

            // if the statement constains ", =, or... then it's not a statement type we care about 
            if ( line.IndexOfAny(_VBNonDeclMarkers) >= 0 )
                return current;

 
            string normalizedLine = NormalizeForVB(line);
 
            if ( context.Count <= 0 ) 
            {
                // without context we only accept BeginClass 
                if ( LineIsVBBeginClassMethodProperty(normalizedLine, "Class", ref name) )
                {
                    current = VBStatementType.BeginClass;
                    context.Push(current); 
                }
            } 
            else 
            {
                // we only look for things based on context: 
                switch ( context.Peek() )
                {
                    // at BeginClass we only accept
                    //    BeginClass 
                    //    EndClass
                    //    BeginProperty 
                    //    BeginMethod 
                    case VBStatementType.BeginClass:
                        if ( normalizedLine == "End Class" ) 
                        {
                            current = VBStatementType.EndClass;
                            context.Pop();
                        } 
                        else
                        { 
                            if ( LineIsVBBeginClassMethodProperty(normalizedLine, "Class", ref name) ) 
                            {
                                current = VBStatementType.BeginClass; 
                                context.Push(current);
                            }
                            else if ( LineIsVBBeginClassMethodProperty(normalizedLine, "MustOverride Sub", ref name) )
                            { 
                                // Abstract methods do not have an "End Sub", this don't push the context.
                                current = VBStatementType.BeginMethod; 
                            } 
                            else if ( LineIsVBBeginClassMethodProperty(normalizedLine, "Function", ref name)
                                || LineIsVBBeginClassMethodProperty(normalizedLine, "Sub", ref name) ) 
                            {
                                current = VBStatementType.BeginMethod;
                                context.Push(current);
                            } 
                            else if ( LineIsVBBeginClassMethodProperty(normalizedLine, "Property", ref name) )
                            { 
                                current = VBStatementType.BeginProperty; 
                                context.Push(current);
                            } 
                        }
                        break;

                    // at BeginProperty we only accept 
                    //    EndProperty
                    //    BeginPropertyGetter 
                    //    BeginPropertySetter 
                    case VBStatementType.BeginProperty:
                        if ( normalizedLine == "End Property" ) 
                        {
                            current = VBStatementType.EndProperty;
                            context.Pop();
                        } 
                        else
                        { 
                            if ( LineIsVBBeginSetterGetter(normalizedLine, "Get") ) 
                            {
                                current = VBStatementType.BeginPropertyGetter; 
                                context.Push(current);
                            }
                            else if ( LineIsVBBeginSetterGetter(normalizedLine, "Set") )
                            { 
                                current = VBStatementType.BeginPropertySetter;
                                context.Push(current); 
                            } 
                        }
                        break; 

                    // at BeginMethod we only accept
                    //    EndMethod
                    case VBStatementType.BeginMethod: 
                        if ( normalizedLine == "End Sub" || normalizedLine == "End Function" )
                        { 
                            current = VBStatementType.EndMethod; 
                            context.Pop();
                        } 
                        break;

                    // at BeginPropertyGetter we only accept
                    //    EndPropertyGetter 
                    case VBStatementType.BeginPropertyGetter:
                        if ( normalizedLine == "End Get" ) 
                        { 
                            current = VBStatementType.EndPropertyGetter;
                            context.Pop(); 
                        }
                        break;

                    // at BeginPropertySetter we only accept 
                    //    EndPropertySetter
                    case VBStatementType.BeginPropertySetter: 
                        if ( normalizedLine == "End Set" ) 
                        {
                            current = VBStatementType.EndPropertySetter; 
                            context.Pop();
                        }
                        break;
                } 
            }
 
            return current; 
        }
 
        /// 
        ///
        /// 
        ///  
        /// 
        private static string NormalizeForVB(string line) 
        { 
            // no leading or trailing spaces and tabs are replaced with spaces
            line = line.Replace('\t', ' ').Trim(); 

            // consecutuve spaces are replaced with single spaces...
            // (we don't care about hammering strings; we just use the normalized line for statment identification...
            while ( line.IndexOf("  ", 0,StringComparison.Ordinal) >= 0 ) 
                line = line.Replace("  ", " ");
 
            return line; 
        }
 
        /// 
        ///
        /// 
        ///  
        /// 
        ///  
        private static bool LineIsVBBeginSetterGetter(string line, string keyword) 
        {
            return IndexOfKeyword(line, keyword) >= 0; 
        }

        /// 
        /// 
        /// 
        ///  
        ///  
        /// 
        private static int IndexOfKeyword(string line, string keyword) 
        {
            int index = line.IndexOf(keyword,StringComparison.Ordinal);
            if ( index < 0 )
                return index; 

            char ch; 
            int indexAfter = index+keyword.Length; 
            if ( (index == 0 || char.IsWhiteSpace(line, index-1)) && (indexAfter == line.Length || (ch=line[indexAfter]) == '(' || char.IsWhiteSpace(ch)) )
                return index; 

            return -1;
        }
 
        /// 
        /// 
        ///  
        /// 
        ///  
        /// 
        /// 
        private static bool LineIsVBBeginClassMethodProperty(string line, string keyword, ref string name)
        { 
            // line must contain the keyword
            int index = IndexOfKeyword(line, keyword); 
            if ( index < 0 ) 
                return false;
 
            // after the keyword we expact a space and the name
            index += keyword.Length;
            if ( index >= line.Length || !char.IsWhiteSpace(line, index) )
                return false; 
            ++index;
            if ( index >= line.Length ) 
                return false; 

            // after the name we expect a EOL or a delimiter... 
            int end = line.IndexOfAny(_VBEndOfClassDelimiters, index);
            if ( end < 0 )
                end = line.Length;
 
            name = line.Substring(index, end-index).Trim();
 
            if (name.StartsWith("[", StringComparison.Ordinal) && name.EndsWith("]", StringComparison.Ordinal)) 
            {
                // remove the vb keyword escaping mechanisim 
                name = name.Substring(1, name.Length - 2);
            }

            return true; 
        }
        #endregion 
 
        #region Private Properties
        ///  
        ///
        /// 
        private LanguageOption Language
        { 
            get
            { 
                return _language; 
            }
            set 
            {
                _language = value;
            }
        } 

        ///  
        /// 
        /// 
        ///  
        private Dictionary> ClassFixUps
        {
            get
            { 
                if ( _classFixUps == null )
                { 
                    _classFixUps = new Dictionary>(); 
                }
 
                return _classFixUps;
            }
        }
        #endregion 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK