File: FrameworkFork\Microsoft.CodeDom\Compiler\CodeValidator.cs
Web Access
Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
namespace Microsoft.CodeDom.Compiler
{
    using System;
    using Microsoft.CodeDom;
    using System.Collections;
    using System.Globalization;
    using System.IO;
 
    // This is an internal helper class which walks the tree for the ValidateIdentifiers API in the CodeGenerator. For the most part the generator code has been copied and
    // turned into validation code. This code will only validate identifiers and types to check that they are ok in a language
    // independent manner. By default, this will not be turned on. This gives clients of codedom a mechanism to 
    // protect themselves against certain types of code injection attacks (using identifier and type names). 
    // You can pass in any node in the tree that is a subclass of CodeObject.
    internal class CodeValidator
    {
        private static readonly char[] s_newLineChars = new char[] { '\r', '\n', '\u2028', '\u2029', '\u0085' };
 
        internal void ValidateIdentifiers(CodeObject e)
        {
            if (e is CodeCompileUnit)
            {
                ValidateCodeCompileUnit((CodeCompileUnit)e);
            }
            else if (e is CodeComment)
            {
                ValidateComment((CodeComment)e);
            }
            else if (e is CodeExpression)
            {
                ValidateExpression((CodeExpression)e);
            }
            else if (e is CodeNamespace)
            {
                ValidateNamespace((CodeNamespace)e);
            }
            else if (e is CodeNamespaceImport)
            {
                ValidateNamespaceImport((CodeNamespaceImport)e);
            }
            else if (e is CodeStatement)
            {
                ValidateStatement((CodeStatement)e);
            }
            else if (e is CodeTypeMember)
            {
                ValidateTypeMember((CodeTypeMember)e);
            }
            else if (e is CodeTypeReference)
            {
                ValidateTypeReference((CodeTypeReference)e);
            }
            else if (e is CodeDirective)
            {
                ValidateCodeDirective((CodeDirective)e);
            }
            else
            {
                throw new ArgumentException(string.Format(SRCodeDom.InvalidElementType, e.GetType().FullName), "e");
            }
        }
 
        private void ValidateTypeMember(CodeTypeMember e)
        {
            ValidateCommentStatements(e.Comments);
            ValidateCodeDirectives(e.StartDirectives);
            ValidateCodeDirectives(e.EndDirectives);
            if (e.LinePragma != null) ValidateLinePragmaStart(e.LinePragma);
 
            if (e is CodeMemberEvent)
            {
                ValidateEvent((CodeMemberEvent)e);
            }
            else if (e is CodeMemberField)
            {
                ValidateField((CodeMemberField)e);
            }
            else if (e is CodeMemberMethod)
            {
                ValidateMemberMethod((CodeMemberMethod)e);
            }
            else if (e is CodeMemberProperty)
            {
                ValidateProperty((CodeMemberProperty)e);
            }
            else if (e is CodeSnippetTypeMember)
            {
                ValidateSnippetMember((CodeSnippetTypeMember)e);
            }
            else if (e is CodeTypeDeclaration)
            {
                ValidateTypeDeclaration((CodeTypeDeclaration)e);
            }
            else
            {
                throw new ArgumentException(string.Format(SRCodeDom.InvalidElementType, e.GetType().FullName), "e");
            }
        }
 
        private void ValidateCodeCompileUnit(CodeCompileUnit e)
        {
            ValidateCodeDirectives(e.StartDirectives);
            ValidateCodeDirectives(e.EndDirectives);
            if (e is CodeSnippetCompileUnit)
            {
                ValidateSnippetCompileUnit((CodeSnippetCompileUnit)e);
            }
            else
            {
                ValidateCompileUnitStart(e);
                ValidateNamespaces(e);
                ValidateCompileUnitEnd(e);
            }
        }
 
        private void ValidateSnippetCompileUnit(CodeSnippetCompileUnit e)
        {
            if (e.LinePragma != null) ValidateLinePragmaStart(e.LinePragma);
        }
 
        private void ValidateCompileUnitStart(CodeCompileUnit e)
        {
            if (e.AssemblyCustomAttributes.Count > 0)
            {
                ValidateAttributes(e.AssemblyCustomAttributes);
            }
        }
 
        private void ValidateCompileUnitEnd(CodeCompileUnit e)
        {
        }
 
        private void ValidateNamespaces(CodeCompileUnit e)
        {
            foreach (CodeNamespace n in e.Namespaces)
            {
                ValidateNamespace(n);
            }
        }
 
        private void ValidateNamespace(CodeNamespace e)
        {
            ValidateCommentStatements(e.Comments);
            ValidateNamespaceStart(e);
            ValidateNamespaceImports(e);
            ValidateTypes(e);
        }
 
 
        private static void ValidateNamespaceStart(CodeNamespace e)
        {
            if (e.Name != null && e.Name.Length > 0)
            {
                ValidateTypeName(e, "Name", e.Name);
            }
        }
 
        private void ValidateNamespaceImports(CodeNamespace e)
        {
            IEnumerator en = e.Imports.GetEnumerator();
            while (en.MoveNext())
            {
                CodeNamespaceImport imp = (CodeNamespaceImport)en.Current;
                if (imp.LinePragma != null) ValidateLinePragmaStart(imp.LinePragma);
                ValidateNamespaceImport(imp);
            }
        }
 
        private static void ValidateNamespaceImport(CodeNamespaceImport e)
        {
            ValidateTypeName(e, "Namespace", e.Namespace);
        }
 
        private void ValidateAttributes(CodeAttributeDeclarationCollection attributes)
        {
            if (attributes.Count == 0) return;
            IEnumerator en = attributes.GetEnumerator();
            while (en.MoveNext())
            {
                CodeAttributeDeclaration current = (CodeAttributeDeclaration)en.Current;
                ValidateTypeName(current, "Name", current.Name);
                ValidateTypeReference(current.AttributeType);
 
                foreach (CodeAttributeArgument arg in current.Arguments)
                {
                    ValidateAttributeArgument(arg);
                }
            }
        }
 
        private void ValidateAttributeArgument(CodeAttributeArgument arg)
        {
            if (arg.Name != null && arg.Name.Length > 0)
            {
                ValidateIdentifier(arg, "Name", arg.Name);
            }
            ValidateExpression(arg.Value);
        }
 
        private void ValidateTypes(CodeNamespace e)
        {
            foreach (CodeTypeDeclaration type in e.Types)
            {
                ValidateTypeDeclaration(type);
            }
        }
 
        private void ValidateTypeDeclaration(CodeTypeDeclaration e)
        {
            // This function can be called recursively and will modify the global variable currentClass
            // We will save currentClass to a local, modify it to do whatever we want and restore it back when we exit so that it is re-entrant.
            CodeTypeDeclaration savedClass = _currentClass;
            _currentClass = e;
 
            ValidateTypeStart(e);
            ValidateTypeParameters(e.TypeParameters);
            ValidateTypeMembers(e); // Recursive call can come from here.
            ValidateTypeReferences(e.BaseTypes);
 
            _currentClass = savedClass;
        }
 
        private void ValidateTypeMembers(CodeTypeDeclaration e)
        {
            foreach (CodeTypeMember currentMember in e.Members)
            {
                ValidateTypeMember(currentMember);
            }
        }
 
        private void ValidateTypeParameters(CodeTypeParameterCollection parameters)
        {
            for (int i = 0; i < parameters.Count; i++)
            {
                ValidateTypeParameter(parameters[i]);
            }
        }
 
        private void ValidateTypeParameter(CodeTypeParameter e)
        {
            ValidateIdentifier(e, "Name", e.Name);
            ValidateTypeReferences(e.Constraints);
            ValidateAttributes(e.CustomAttributes);
        }
 
        private void ValidateField(CodeMemberField e)
        {
            if (e.CustomAttributes.Count > 0)
            {
                ValidateAttributes(e.CustomAttributes);
            }
 
            ValidateIdentifier(e, "Name", e.Name);
            if (!IsCurrentEnum)
            {
                ValidateTypeReference(e.Type);
            }
 
            if (e.InitExpression != null)
            {
                ValidateExpression(e.InitExpression);
            }
        }
 
        private void ValidateConstructor(CodeConstructor e)
        {
            if (e.CustomAttributes.Count > 0)
            {
                ValidateAttributes(e.CustomAttributes);
            }
 
            ValidateParameters(e.Parameters);
 
            CodeExpressionCollection baseArgs = e.BaseConstructorArgs;
            CodeExpressionCollection thisArgs = e.ChainedConstructorArgs;
 
            if (baseArgs.Count > 0)
            {
                ValidateExpressionList(baseArgs);
            }
 
            if (thisArgs.Count > 0)
            {
                ValidateExpressionList(thisArgs);
            }
 
            ValidateStatements(e.Statements);
        }
 
        private void ValidateProperty(CodeMemberProperty e)
        {
            if (e.CustomAttributes.Count > 0)
            {
                ValidateAttributes(e.CustomAttributes);
            }
 
            ValidateTypeReference(e.Type);
            ValidateTypeReferences(e.ImplementationTypes);
 
            if (e.PrivateImplementationType != null && !IsCurrentInterface)
            {
                ValidateTypeReference(e.PrivateImplementationType);
            }
 
            if (e.Parameters.Count > 0 && String.Compare(e.Name, "Item", StringComparison.OrdinalIgnoreCase) == 0)
            {
                ValidateParameters(e.Parameters);
            }
            else
            {
                ValidateIdentifier(e, "Name", e.Name);
            }
 
            if (e.HasGet)
            {
                if (!(IsCurrentInterface || (e.Attributes & MemberAttributes.ScopeMask) == MemberAttributes.Abstract))
                {
                    ValidateStatements(e.GetStatements);
                }
            }
 
            if (e.HasSet)
            {
                if (!(IsCurrentInterface || (e.Attributes & MemberAttributes.ScopeMask) == MemberAttributes.Abstract))
                {
                    ValidateStatements(e.SetStatements);
                }
            }
        }
 
        private void ValidateMemberMethod(CodeMemberMethod e)
        {
            ValidateCommentStatements(e.Comments);
            if (e.LinePragma != null) ValidateLinePragmaStart(e.LinePragma);
 
            ValidateTypeParameters(e.TypeParameters);
            ValidateTypeReferences(e.ImplementationTypes);
 
            if (e is CodeEntryPointMethod)
            {
                ValidateStatements(((CodeEntryPointMethod)e).Statements);
            }
            else if (e is CodeConstructor)
            {
                ValidateConstructor((CodeConstructor)e);
            }
            else if (e is CodeTypeConstructor)
            {
                ValidateTypeConstructor((CodeTypeConstructor)e);
            }
            else
            {
                ValidateMethod(e);
            }
        }
 
        private void ValidateTypeConstructor(CodeTypeConstructor e)
        {
            ValidateStatements(e.Statements);
        }
 
        private void ValidateMethod(CodeMemberMethod e)
        {
            if (e.CustomAttributes.Count > 0)
            {
                ValidateAttributes(e.CustomAttributes);
            }
            if (e.ReturnTypeCustomAttributes.Count > 0)
            {
                ValidateAttributes(e.ReturnTypeCustomAttributes);
            }
 
            ValidateTypeReference(e.ReturnType);
            if (e.PrivateImplementationType != null)
            {
                ValidateTypeReference(e.PrivateImplementationType);
            }
 
            ValidateIdentifier(e, "Name", e.Name);
            ValidateParameters(e.Parameters);
 
            if (!IsCurrentInterface
                && (e.Attributes & MemberAttributes.ScopeMask) != MemberAttributes.Abstract)
            {
                ValidateStatements(e.Statements);
            }
        }
 
        private void ValidateSnippetMember(CodeSnippetTypeMember e)
        {
        }
 
        private void ValidateTypeStart(CodeTypeDeclaration e)
        {
            ValidateCommentStatements(e.Comments);
            if (e.CustomAttributes.Count > 0)
            {
                ValidateAttributes(e.CustomAttributes);
            }
 
            ValidateIdentifier(e, "Name", e.Name);
            if (IsCurrentDelegate)
            {
                CodeTypeDelegate del = (CodeTypeDelegate)e;
                ValidateTypeReference(del.ReturnType);
                ValidateParameters(del.Parameters);
            }
            else
            {
                foreach (CodeTypeReference typeRef in e.BaseTypes)
                {
                    ValidateTypeReference(typeRef);
                }
            }
        }
 
        private void ValidateCommentStatements(CodeCommentStatementCollection e)
        {
            foreach (CodeCommentStatement comment in e)
            {
                ValidateCommentStatement(comment);
            }
        }
 
        private void ValidateCommentStatement(CodeCommentStatement e)
        {
            ValidateComment(e.Comment);
        }
 
        private void ValidateComment(CodeComment e)
        {
        }
 
        private void ValidateStatement(CodeStatement e)
        {
            ValidateCodeDirectives(e.StartDirectives);
            ValidateCodeDirectives(e.EndDirectives);
 
            if (e is CodeCommentStatement)
            {
                ValidateCommentStatement((CodeCommentStatement)e);
            }
            else if (e is CodeMethodReturnStatement)
            {
                ValidateMethodReturnStatement((CodeMethodReturnStatement)e);
            }
            else if (e is CodeConditionStatement)
            {
                ValidateConditionStatement((CodeConditionStatement)e);
            }
            else if (e is CodeTryCatchFinallyStatement)
            {
                ValidateTryCatchFinallyStatement((CodeTryCatchFinallyStatement)e);
            }
            else if (e is CodeAssignStatement)
            {
                ValidateAssignStatement((CodeAssignStatement)e);
            }
            else if (e is CodeExpressionStatement)
            {
                ValidateExpressionStatement((CodeExpressionStatement)e);
            }
            else if (e is CodeIterationStatement)
            {
                ValidateIterationStatement((CodeIterationStatement)e);
            }
            else if (e is CodeThrowExceptionStatement)
            {
                ValidateThrowExceptionStatement((CodeThrowExceptionStatement)e);
            }
            else if (e is CodeSnippetStatement)
            {
                ValidateSnippetStatement((CodeSnippetStatement)e);
            }
            else if (e is CodeVariableDeclarationStatement)
            {
                ValidateVariableDeclarationStatement((CodeVariableDeclarationStatement)e);
            }
            else if (e is CodeAttachEventStatement)
            {
                ValidateAttachEventStatement((CodeAttachEventStatement)e);
            }
            else if (e is CodeRemoveEventStatement)
            {
                ValidateRemoveEventStatement((CodeRemoveEventStatement)e);
            }
            else if (e is CodeGotoStatement)
            {
                ValidateGotoStatement((CodeGotoStatement)e);
            }
            else if (e is CodeLabeledStatement)
            {
                ValidateLabeledStatement((CodeLabeledStatement)e);
            }
            else
            {
                throw new ArgumentException(string.Format(SRCodeDom.InvalidElementType, e.GetType().FullName), "e");
            }
        }
 
        private void ValidateStatements(CodeStatementCollection stms)
        {
            IEnumerator en = stms.GetEnumerator();
            while (en.MoveNext())
            {
                ValidateStatement((CodeStatement)en.Current);
            }
        }
 
        private void ValidateExpressionStatement(CodeExpressionStatement e)
        {
            ValidateExpression(e.Expression);
        }
 
        private void ValidateIterationStatement(CodeIterationStatement e)
        {
            ValidateStatement(e.InitStatement);
            ValidateExpression(e.TestExpression);
            ValidateStatement(e.IncrementStatement);
            ValidateStatements(e.Statements);
        }
 
        private void ValidateThrowExceptionStatement(CodeThrowExceptionStatement e)
        {
            if (e.ToThrow != null)
            {
                ValidateExpression(e.ToThrow);
            }
        }
 
        private void ValidateMethodReturnStatement(CodeMethodReturnStatement e)
        {
            if (e.Expression != null)
            {
                ValidateExpression(e.Expression);
            }
        }
 
        private void ValidateConditionStatement(CodeConditionStatement e)
        {
            ValidateExpression(e.Condition);
            ValidateStatements(e.TrueStatements);
 
            CodeStatementCollection falseStatemetns = e.FalseStatements;
            if (falseStatemetns.Count > 0)
            {
                ValidateStatements(e.FalseStatements);
            }
        }
 
        private void ValidateTryCatchFinallyStatement(CodeTryCatchFinallyStatement e)
        {
            ValidateStatements(e.TryStatements);
            CodeCatchClauseCollection catches = e.CatchClauses;
            if (catches.Count > 0)
            {
                IEnumerator en = catches.GetEnumerator();
                while (en.MoveNext())
                {
                    CodeCatchClause current = (CodeCatchClause)en.Current;
                    ValidateTypeReference(current.CatchExceptionType);
                    ValidateIdentifier(current, "LocalName", current.LocalName);
                    ValidateStatements(current.Statements);
                }
            }
 
            CodeStatementCollection finallyStatements = e.FinallyStatements;
            if (finallyStatements.Count > 0)
            {
                ValidateStatements(finallyStatements);
            }
        }
 
        private void ValidateAssignStatement(CodeAssignStatement e)
        {
            ValidateExpression(e.Left);
            ValidateExpression(e.Right);
        }
 
        private void ValidateAttachEventStatement(CodeAttachEventStatement e)
        {
            ValidateEventReferenceExpression(e.Event);
            ValidateExpression(e.Listener);
        }
 
        private void ValidateRemoveEventStatement(CodeRemoveEventStatement e)
        {
            ValidateEventReferenceExpression(e.Event);
            ValidateExpression(e.Listener);
        }
 
        private static void ValidateGotoStatement(CodeGotoStatement e)
        {
            ValidateIdentifier(e, "Label", e.Label);
        }
 
        private void ValidateLabeledStatement(CodeLabeledStatement e)
        {
            ValidateIdentifier(e, "Label", e.Label);
            if (e.Statement != null)
            {
                ValidateStatement(e.Statement);
            }
        }
 
        private void ValidateVariableDeclarationStatement(CodeVariableDeclarationStatement e)
        {
            ValidateTypeReference(e.Type);
            ValidateIdentifier(e, "Name", e.Name);
            if (e.InitExpression != null)
            {
                ValidateExpression(e.InitExpression);
            }
        }
 
        private void ValidateLinePragmaStart(CodeLinePragma e)
        {
        }
 
        private void ValidateEvent(CodeMemberEvent e)
        {
            if (e.CustomAttributes.Count > 0)
            {
                ValidateAttributes(e.CustomAttributes);
            }
            if (e.PrivateImplementationType != null)
            {
                ValidateTypeReference(e.Type);
                ValidateIdentifier(e, "Name", e.Name);
            }
 
            ValidateTypeReferences(e.ImplementationTypes);
        }
 
        private void ValidateParameters(CodeParameterDeclarationExpressionCollection parameters)
        {
            IEnumerator en = parameters.GetEnumerator();
            while (en.MoveNext())
            {
                CodeParameterDeclarationExpression current = (CodeParameterDeclarationExpression)en.Current;
                ValidateParameterDeclarationExpression(current);
            }
        }
 
        private void ValidateSnippetStatement(CodeSnippetStatement e)
        {
        }
 
        private void ValidateExpressionList(CodeExpressionCollection expressions)
        {
            IEnumerator en = expressions.GetEnumerator();
            while (en.MoveNext())
            {
                ValidateExpression((CodeExpression)en.Current);
            }
        }
 
        private static void ValidateTypeReference(CodeTypeReference e)
        {
            String baseType = e.BaseType;
            ValidateTypeName(e, "BaseType", baseType);
            ValidateArity(e);
            ValidateTypeReferences(e.TypeArguments);
        }
 
        private static void ValidateTypeReferences(CodeTypeReferenceCollection refs)
        {
            for (int i = 0; i < refs.Count; i++)
            {
                ValidateTypeReference(refs[i]);
            }
        }
 
        private static void ValidateArity(CodeTypeReference e)
        {
            // Verify that the number of TypeArguments agrees with the arity on the type.  
            string baseType = e.BaseType;
            int totalTypeArgs = 0;
            for (int i = 0; i < baseType.Length; i++)
            {
                if (baseType[i] == '`')
                {
                    i++;    // skip the '
                    int numTypeArgs = 0;
                    while (i < baseType.Length && baseType[i] >= '0' && baseType[i] <= '9')
                    {
                        numTypeArgs = numTypeArgs * 10 + (baseType[i] - '0');
                        i++;
                    }
 
                    totalTypeArgs += numTypeArgs;
                }
            }
 
            // Check if we have zero type args for open types.
            if ((totalTypeArgs != e.TypeArguments.Count) && (e.TypeArguments.Count != 0))
            {
                throw new ArgumentException(string.Format(SRCodeDom.ArityDoesntMatch, baseType, e.TypeArguments.Count));
            }
        }
 
        private static void ValidateTypeName(Object e, String propertyName, String typeName)
        {
            if (!CodeGenerator.IsValidLanguageIndependentTypeName(typeName))
            {
                String message = string.Format(SRCodeDom.InvalidTypeName, typeName, propertyName, e.GetType().FullName);
                throw new ArgumentException(message, "typeName");
            }
        }
 
        private static void ValidateIdentifier(Object e, String propertyName, String identifier)
        {
            if (!CodeGenerator.IsValidLanguageIndependentIdentifier(identifier))
            {
                String message = string.Format(SRCodeDom.InvalidLanguageIdentifier, identifier, propertyName, e.GetType().FullName);
                throw new ArgumentException(message, "identifier");
            }
        }
 
        private void ValidateExpression(CodeExpression e)
        {
            if (e is CodeArrayCreateExpression)
            {
                ValidateArrayCreateExpression((CodeArrayCreateExpression)e);
            }
            else if (e is CodeBaseReferenceExpression)
            {
                ValidateBaseReferenceExpression((CodeBaseReferenceExpression)e);
            }
            else if (e is CodeBinaryOperatorExpression)
            {
                ValidateBinaryOperatorExpression((CodeBinaryOperatorExpression)e);
            }
            else if (e is CodeCastExpression)
            {
                ValidateCastExpression((CodeCastExpression)e);
            }
            else if (e is CodeDefaultValueExpression)
            {
                ValidateDefaultValueExpression((CodeDefaultValueExpression)e);
            }
            else if (e is CodeDelegateCreateExpression)
            {
                ValidateDelegateCreateExpression((CodeDelegateCreateExpression)e);
            }
            else if (e is CodeFieldReferenceExpression)
            {
                ValidateFieldReferenceExpression((CodeFieldReferenceExpression)e);
            }
            else if (e is CodeArgumentReferenceExpression)
            {
                ValidateArgumentReferenceExpression((CodeArgumentReferenceExpression)e);
            }
            else if (e is CodeVariableReferenceExpression)
            {
                ValidateVariableReferenceExpression((CodeVariableReferenceExpression)e);
            }
            else if (e is CodeIndexerExpression)
            {
                ValidateIndexerExpression((CodeIndexerExpression)e);
            }
            else if (e is CodeArrayIndexerExpression)
            {
                ValidateArrayIndexerExpression((CodeArrayIndexerExpression)e);
            }
            else if (e is CodeSnippetExpression)
            {
                ValidateSnippetExpression((CodeSnippetExpression)e);
            }
            else if (e is CodeMethodInvokeExpression)
            {
                ValidateMethodInvokeExpression((CodeMethodInvokeExpression)e);
            }
            else if (e is CodeMethodReferenceExpression)
            {
                ValidateMethodReferenceExpression((CodeMethodReferenceExpression)e);
            }
            else if (e is CodeEventReferenceExpression)
            {
                ValidateEventReferenceExpression((CodeEventReferenceExpression)e);
            }
            else if (e is CodeDelegateInvokeExpression)
            {
                ValidateDelegateInvokeExpression((CodeDelegateInvokeExpression)e);
            }
            else if (e is CodeObjectCreateExpression)
            {
                ValidateObjectCreateExpression((CodeObjectCreateExpression)e);
            }
            else if (e is CodeParameterDeclarationExpression)
            {
                ValidateParameterDeclarationExpression((CodeParameterDeclarationExpression)e);
            }
            else if (e is CodeDirectionExpression)
            {
                ValidateDirectionExpression((CodeDirectionExpression)e);
            }
            else if (e is CodePrimitiveExpression)
            {
                ValidatePrimitiveExpression((CodePrimitiveExpression)e);
            }
            else if (e is CodePropertyReferenceExpression)
            {
                ValidatePropertyReferenceExpression((CodePropertyReferenceExpression)e);
            }
            else if (e is CodePropertySetValueReferenceExpression)
            {
                ValidatePropertySetValueReferenceExpression((CodePropertySetValueReferenceExpression)e);
            }
            else if (e is CodeThisReferenceExpression)
            {
                ValidateThisReferenceExpression((CodeThisReferenceExpression)e);
            }
            else if (e is CodeTypeReferenceExpression)
            {
                ValidateTypeReference(((CodeTypeReferenceExpression)e).Type);
            }
            else if (e is CodeTypeOfExpression)
            {
                ValidateTypeOfExpression((CodeTypeOfExpression)e);
            }
            else
            {
                if (e == null)
                {
                    throw new ArgumentNullException("e");
                }
                else
                {
                    throw new ArgumentException(string.Format(SRCodeDom.InvalidElementType, e.GetType().FullName), "e");
                }
            }
        }
 
        private void ValidateArrayCreateExpression(CodeArrayCreateExpression e)
        {
            ValidateTypeReference(e.CreateType);
            CodeExpressionCollection init = e.Initializers;
            if (init.Count > 0)
            {
                ValidateExpressionList(init);
            }
            else
            {
                if (e.SizeExpression != null)
                {
                    ValidateExpression(e.SizeExpression);
                }
            }
        }
 
        private void ValidateBaseReferenceExpression(CodeBaseReferenceExpression e)
        { // Nothing to validate
        }
 
        private void ValidateBinaryOperatorExpression(CodeBinaryOperatorExpression e)
        {
            ValidateExpression(e.Left);
            ValidateExpression(e.Right);
        }
 
        private void ValidateCastExpression(CodeCastExpression e)
        {
            ValidateTypeReference(e.TargetType);
            ValidateExpression(e.Expression);
        }
 
        private static void ValidateDefaultValueExpression(CodeDefaultValueExpression e)
        {
            ValidateTypeReference(e.Type);
        }
 
        private void ValidateDelegateCreateExpression(CodeDelegateCreateExpression e)
        {
            ValidateTypeReference(e.DelegateType);
            ValidateExpression(e.TargetObject);
            ValidateIdentifier(e, "MethodName", e.MethodName);
        }
 
        private void ValidateFieldReferenceExpression(CodeFieldReferenceExpression e)
        {
            if (e.TargetObject != null)
            {
                ValidateExpression(e.TargetObject);
            }
            ValidateIdentifier(e, "FieldName", e.FieldName);
        }
 
        private static void ValidateArgumentReferenceExpression(CodeArgumentReferenceExpression e)
        {
            ValidateIdentifier(e, "ParameterName", e.ParameterName);
        }
 
        private static void ValidateVariableReferenceExpression(CodeVariableReferenceExpression e)
        {
            ValidateIdentifier(e, "VariableName", e.VariableName);
        }
 
        private void ValidateIndexerExpression(CodeIndexerExpression e)
        {
            ValidateExpression(e.TargetObject);
            foreach (CodeExpression exp in e.Indices)
            {
                ValidateExpression(exp);
            }
        }
 
        private void ValidateArrayIndexerExpression(CodeArrayIndexerExpression e)
        {
            ValidateExpression(e.TargetObject);
            foreach (CodeExpression exp in e.Indices)
            {
                ValidateExpression(exp);
            }
        }
 
        private void ValidateSnippetExpression(CodeSnippetExpression e)
        {
        }
 
        private void ValidateMethodInvokeExpression(CodeMethodInvokeExpression e)
        {
            ValidateMethodReferenceExpression(e.Method);
            ValidateExpressionList(e.Parameters);
        }
 
        private void ValidateMethodReferenceExpression(CodeMethodReferenceExpression e)
        {
            if (e.TargetObject != null)
            {
                ValidateExpression(e.TargetObject);
            }
            ValidateIdentifier(e, "MethodName", e.MethodName);
            ValidateTypeReferences(e.TypeArguments);
        }
 
        private void ValidateEventReferenceExpression(CodeEventReferenceExpression e)
        {
            if (e.TargetObject != null)
            {
                ValidateExpression(e.TargetObject);
            }
            ValidateIdentifier(e, "EventName", e.EventName);
        }
 
        private void ValidateDelegateInvokeExpression(CodeDelegateInvokeExpression e)
        {
            if (e.TargetObject != null)
            {
                ValidateExpression(e.TargetObject);
            }
            ValidateExpressionList(e.Parameters);
        }
 
        private void ValidateObjectCreateExpression(CodeObjectCreateExpression e)
        {
            ValidateTypeReference(e.CreateType);
            ValidateExpressionList(e.Parameters);
        }
 
        private void ValidateParameterDeclarationExpression(CodeParameterDeclarationExpression e)
        {
            if (e.CustomAttributes.Count > 0)
            {
                ValidateAttributes(e.CustomAttributes);
            }
 
            ValidateTypeReference(e.Type);
            ValidateIdentifier(e, "Name", e.Name);
        }
 
        private void ValidateDirectionExpression(CodeDirectionExpression e)
        {
            ValidateExpression(e.Expression);
        }
 
        private void ValidatePrimitiveExpression(CodePrimitiveExpression e)
        {
        }
 
        private void ValidatePropertyReferenceExpression(CodePropertyReferenceExpression e)
        {
            if (e.TargetObject != null)
            {
                ValidateExpression(e.TargetObject);
            }
            ValidateIdentifier(e, "PropertyName", e.PropertyName);
        }
 
        private void ValidatePropertySetValueReferenceExpression(CodePropertySetValueReferenceExpression e)
        { // Do nothing
        }
 
        private void ValidateThisReferenceExpression(CodeThisReferenceExpression e)
        {  // Do nothing
        }
 
        private static void ValidateTypeOfExpression(CodeTypeOfExpression e)
        {
            ValidateTypeReference(e.Type);
        }
 
        private static void ValidateCodeDirectives(CodeDirectiveCollection e)
        {
            for (int i = 0; i < e.Count; i++)
                ValidateCodeDirective(e[i]);
        }
 
        private static void ValidateCodeDirective(CodeDirective e)
        {
            if (e is CodeChecksumPragma)
                ValidateChecksumPragma((CodeChecksumPragma)e);
            else if (e is CodeRegionDirective)
                ValidateRegionDirective((CodeRegionDirective)e);
            else
                throw new ArgumentException(string.Format(SRCodeDom.InvalidElementType, e.GetType().FullName), "e");
        }
 
        private static void ValidateChecksumPragma(CodeChecksumPragma e)
        {
            if (e.FileName.IndexOfAny(Path.GetInvalidPathChars()) != -1)
                throw new ArgumentException(string.Format(SRCodeDom.InvalidPathCharsInChecksum, e.FileName));
        }
 
        private static void ValidateRegionDirective(CodeRegionDirective e)
        {
            if (e.RegionText.IndexOfAny(s_newLineChars) != -1)
                throw new ArgumentException(string.Format(SRCodeDom.InvalidRegion, e.RegionText));
        }
 
        private bool IsCurrentInterface
        {
            get
            {
                if (_currentClass != null && !(_currentClass is CodeTypeDelegate))
                {
                    return _currentClass.IsInterface;
                }
                return false;
            }
        }
 
        private bool IsCurrentEnum
        {
            get
            {
                if (_currentClass != null && !(_currentClass is CodeTypeDelegate))
                {
                    return _currentClass.IsEnum;
                }
                return false;
            }
        }
 
        private bool IsCurrentDelegate
        {
            get
            {
                if (_currentClass != null && _currentClass is CodeTypeDelegate)
                {
                    return true;
                }
                return false;
            }
        }
 
        private CodeTypeDeclaration _currentClass;
    }
}